mirror of
https://git.coastit.co.za/caitlin/CRM_ENVR.git
synced 2026-07-10 03:05:43 +02:00
92 lines
3.2 KiB
TypeScript
92 lines
3.2 KiB
TypeScript
// ── 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<string>();
|
|
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<string, MissingModule[]> {
|
|
const groups = new Map<string, MissingModule[]>();
|
|
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;
|
|
} |