AUXteam's picture
Upload folder using huggingface_hub
d530f14 verified
import { NextResponse } from 'next/server';
import { parseJavaScriptFile, buildComponentTree } from '@/lib/file-parser';
import { FileManifest, FileInfo, RouteInfo } from '@/types/file-manifest';
// SandboxState type used implicitly through global.activeSandbox
declare global {
var activeSandbox: any;
}
export async function GET() {
try {
if (!global.activeSandbox) {
return NextResponse.json({
success: false,
error: 'No active sandbox'
}, { status: 404 });
}
console.log('[get-sandbox-files] Fetching and analyzing file structure...');
// Get list of all relevant files
const findResult = await global.activeSandbox.runCommand({
cmd: 'find',
args: [
'.',
'-name', 'node_modules', '-prune', '-o',
'-name', '.git', '-prune', '-o',
'-name', 'dist', '-prune', '-o',
'-name', 'build', '-prune', '-o',
'-type', 'f',
'(',
'-name', '*.jsx',
'-o', '-name', '*.js',
'-o', '-name', '*.tsx',
'-o', '-name', '*.ts',
'-o', '-name', '*.css',
'-o', '-name', '*.json',
')',
'-print'
]
});
if (findResult.exitCode !== 0) {
throw new Error('Failed to list files');
}
const fileList = (await findResult.stdout()).split('\n').filter((f: string) => f.trim());
console.log('[get-sandbox-files] Found', fileList.length, 'files');
// Read content of each file (limit to reasonable sizes)
const filesContent: Record<string, string> = {};
for (const filePath of fileList) {
try {
// Check file size first
const statResult = await global.activeSandbox.runCommand({
cmd: 'stat',
args: ['-f', '%z', filePath]
});
if (statResult.exitCode === 0) {
const fileSize = parseInt(await statResult.stdout());
// Only read files smaller than 10KB
if (fileSize < 10000) {
const catResult = await global.activeSandbox.runCommand({
cmd: 'cat',
args: [filePath]
});
if (catResult.exitCode === 0) {
const content = await catResult.stdout();
// Remove leading './' from path
const relativePath = filePath.replace(/^\.\//, '');
filesContent[relativePath] = content;
}
}
}
} catch (parseError) {
console.debug('Error parsing component info:', parseError);
// Skip files that can't be read
continue;
}
}
// Get directory structure
const treeResult = await global.activeSandbox.runCommand({
cmd: 'find',
args: ['.', '-type', 'd', '-not', '-path', '*/node_modules*', '-not', '-path', '*/.git*']
});
let structure = '';
if (treeResult.exitCode === 0) {
const dirs = (await treeResult.stdout()).split('\n').filter((d: string) => d.trim());
structure = dirs.slice(0, 50).join('\n'); // Limit to 50 lines
}
// Build enhanced file manifest
const fileManifest: FileManifest = {
files: {},
routes: [],
componentTree: {},
entryPoint: '',
styleFiles: [],
timestamp: Date.now(),
};
// Process each file
for (const [relativePath, content] of Object.entries(filesContent)) {
const fullPath = `/${relativePath}`;
// Create base file info
const fileInfo: FileInfo = {
content: content,
type: 'utility',
path: fullPath,
relativePath,
lastModified: Date.now(),
};
// Parse JavaScript/JSX files
if (relativePath.match(/\.(jsx?|tsx?)$/)) {
const parseResult = parseJavaScriptFile(content, fullPath);
Object.assign(fileInfo, parseResult);
// Identify entry point
if (relativePath === 'src/main.jsx' || relativePath === 'src/index.jsx') {
fileManifest.entryPoint = fullPath;
}
// Identify App.jsx
if (relativePath === 'src/App.jsx' || relativePath === 'App.jsx') {
fileManifest.entryPoint = fileManifest.entryPoint || fullPath;
}
}
// Track style files
if (relativePath.endsWith('.css')) {
fileManifest.styleFiles.push(fullPath);
fileInfo.type = 'style';
}
fileManifest.files[fullPath] = fileInfo;
}
// Build component tree
fileManifest.componentTree = buildComponentTree(fileManifest.files);
// Extract routes (simplified - looks for Route components or page pattern)
fileManifest.routes = extractRoutes(fileManifest.files);
// Update global file cache with manifest
if (global.sandboxState?.fileCache) {
global.sandboxState.fileCache.manifest = fileManifest;
}
return NextResponse.json({
success: true,
files: filesContent,
structure,
fileCount: Object.keys(filesContent).length,
manifest: fileManifest,
});
} catch (error) {
console.error('[get-sandbox-files] Error:', error);
return NextResponse.json({
success: false,
error: (error as Error).message
}, { status: 500 });
}
}
function extractRoutes(files: Record<string, FileInfo>): RouteInfo[] {
const routes: RouteInfo[] = [];
// Look for React Router usage
for (const [path, fileInfo] of Object.entries(files)) {
if (fileInfo.content.includes('<Route') || fileInfo.content.includes('createBrowserRouter')) {
// Extract route definitions (simplified)
const routeMatches = fileInfo.content.matchAll(/path=["']([^"']+)["'].*(?:element|component)={([^}]+)}/g);
for (const match of routeMatches) {
const [, routePath] = match;
// componentRef available in match but not used currently
routes.push({
path: routePath,
component: path,
});
}
}
// Check for Next.js style pages
if (fileInfo.relativePath.startsWith('pages/') || fileInfo.relativePath.startsWith('src/pages/')) {
const routePath = '/' + fileInfo.relativePath
.replace(/^(src\/)?pages\//, '')
.replace(/\.(jsx?|tsx?)$/, '')
.replace(/index$/, '');
routes.push({
path: routePath,
component: path,
});
}
}
return routes;
}