import ignore from 'ignore'; // Common patterns to ignore, similar to .gitignore export const IGNORE_PATTERNS = [ 'node_modules/**', '.git/**', 'dist/**', 'build/**', '.next/**', 'coverage/**', '.cache/**', '.vscode/**', '.idea/**', '**/*.log', '**/.DS_Store', '**/npm-debug.log*', '**/yarn-debug.log*', '**/yarn-error.log*', ]; export const MAX_FILES = 1000; export const ig = ignore().add(IGNORE_PATTERNS); export const generateId = () => Math.random().toString(36).substring(2, 15); export const isBinaryFile = async (file: File): Promise => { const chunkSize = 1024; const buffer = new Uint8Array(await file.slice(0, chunkSize).arrayBuffer()); for (let i = 0; i < buffer.length; i++) { const byte = buffer[i]; if (byte === 0 || (byte < 32 && byte !== 9 && byte !== 10 && byte !== 13)) { return true; } } return false; }; export const shouldIncludeFile = (path: string): boolean => { return !ig.ignores(path); }; const readPackageJson = async (files: File[]): Promise<{ scripts?: Record } | null> => { const packageJsonFile = files.find((f) => f.webkitRelativePath.endsWith('package.json')); if (!packageJsonFile) { return null; } try { const content = await new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result as string); reader.onerror = reject; reader.readAsText(packageJsonFile); }); return JSON.parse(content); } catch (error) { console.error('Error reading package.json:', error); return null; } }; export const detectProjectType = async ( files: File[], ): Promise<{ type: string; setupCommand: string; followupMessage: string }> => { const hasFile = (name: string) => files.some((f) => f.webkitRelativePath.endsWith(name)); if (hasFile('package.json')) { const packageJson = await readPackageJson(files); const scripts = packageJson?.scripts || {}; // Check for preferred commands in priority order const preferredCommands = ['dev', 'start', 'preview']; const availableCommand = preferredCommands.find((cmd) => scripts[cmd]); if (availableCommand) { return { type: 'Node.js', setupCommand: `npm install && npm run ${availableCommand}`, followupMessage: `Found "${availableCommand}" script in package.json. Running "npm run ${availableCommand}" after installation.`, }; } return { type: 'Node.js', setupCommand: 'npm install', followupMessage: 'Would you like me to inspect package.json to determine the available scripts for running this project?', }; } if (hasFile('index.html')) { return { type: 'Static', setupCommand: 'npx --yes serve', followupMessage: '', }; } return { type: '', setupCommand: '', followupMessage: '' }; };