// ── TypeScript Error Parser ────────────────────────────────────────── // Parses `tsc --noEmit` or `npm run build` output to extract // "Module not found: Can't resolve '@/path/to/module'" errors. // Returns actionable missing module info for the generator. export interface MissingModule { /** The import path that failed, e.g. "@/data/stickers" */ importPath: string; /** The file that contains the failing import */ importerFile: string; /** Line number in importer file */ line: number; /** Column number */ column: number; /** Full error message for context */ message: string; /** Whether this is an internal (@/...) module we can generate */ isInternal: boolean; /** The normalized internal path, e.g. "data/stickers" */ internalPath?: string; } /** Parse TypeScript compiler output for missing module errors */ export function parseMissingModules(tscOutput: string): MissingModule[] { const results: MissingModule[] = []; // Pattern: error TS2307: Cannot find module '@/data/stickers' or its corresponding type declarations. // File: src/components/chats/media-picker.tsx:10:1 const errorRegex = /error\s+TS\d+:\s+Cannot find module\s+'([^']+)'\s+or its corresponding type declarations\.\s*(?:\n\s*(.*?):(\d+):(\d+))?/g; let match; while ((match = errorRegex.exec(tscOutput)) !== null) { const importPath = match[1]; const importerFile = match[2] || ""; const line = parseInt(match[3] || "0", 10); const column = parseInt(match[4] || "0", 10); // Also handle: Module not found: Error: Can't resolve '@/data/stickers' in 'C:\...\src\components\chats' const altRegex = /Module not found: Error: Can't resolve\s+'([^']+)'\s+in\s+'([^']+)'/g; let altMatch; let altImporter = importerFile; while ((altMatch = altRegex.exec(tscOutput)) !== null) { if (altMatch[1] === importPath) { altImporter = altMatch[2]; break; } } const isInternal = importPath.startsWith("@/") || importPath.startsWith("~/"); let internalPath: string | undefined; if (isInternal) { internalPath = importPath.replace(/^[@~]\//, ""); } results.push({ importPath, importerFile: altImporter, line, column, message: `Cannot find module '${importPath}'`, isInternal, internalPath, }); } // Deduplicate by importPath + importerFile const seen = new Set(); return results.filter((m) => { const key = `${m.importPath}|${m.importerFile}`; if (seen.has(key)) return false; seen.add(key); return true; }); } /** Filter to only internal (@/...) modules we can auto-generate */ export function filterGeneratable(modules: MissingModule[]): MissingModule[] { return modules.filter((m) => m.isInternal && m.internalPath); } /** Group missing modules by internal path */ export function groupByInternalPath(modules: MissingModule[]): Map { const groups = new Map(); for (const m of modules) { if (!m.internalPath) continue; const existing = groups.get(m.internalPath) || []; existing.push(m); groups.set(m.internalPath, existing); } return groups; }