scan_project
Scans directories to identify files containing legacy HeroUI/NextUI components for migration to HeroUI v3 beta.
Instructions
Recursively scans a directory for files using legacy HeroUI/NextUI components.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| directory | Yes |
Implementation Reference
- src/core/migration.ts:155-222 (handler)The `scanProject` function implements the logic to scan a project directory for legacy components (based on `KNOWN_V2_IMPORTS`), calculate a priority level for each file, and maintain a scan cache.
export async function scanProject(directory: string, options: { force?: boolean } = {}) { const { force = false } = options; const patterns = ["**/*.{ts,tsx,js,jsx}"]; const files = await fg(patterns, { cwd: directory, absolute: true, onlyFiles: true, ignore: ["**/node_modules/**", "**/dist/**", "**/.next/**"] }); const report: { file: string, components: string[]; priority?: string }[] = []; const v2Keys = Object.keys(KNOWN_V2_IMPORTS); const joint = v2Keys.map(k => k.replace(/[.*+?^${}()|[\\]\\]/g, '\\$&')).join("|"); const quick = new RegExp(joint); // simple cache stored at repo root const cacheFile = path.join(process.cwd(), '.scan-cache.json'); let cache: Record<string, { mtime: number; components: string[] }> = {}; if (!force) { try { cache = JSON.parse(await fs.readFile(cacheFile, 'utf8')); } catch { }; } for (const file of files) { const rel = path.relative(directory, file); const stat = await fs.stat(file); const m = stat.mtimeMs; if (!force && cache[rel] && cache[rel].mtime === m) { if (cache[rel].components.length) { report.push({ file: rel, components: cache[rel].components }); } continue; } const content = await fs.readFile(file, "utf8"); if (!quick.test(content)) { cache[rel] = { mtime: m, components: [] }; continue; } const found: string[] = []; for (const key of v2Keys) { if (content.includes(key)) { found.push(key); } } if (found.length > 0) { // assign priority: P0 if any component is structural or manual-only const pri = found.some(key => { const cat = getTransformationCategory(key); if (cat !== 'safe_rename') return true; const suggestion = KNOWN_V2_IMPORTS[key] || ''; if (suggestion.includes('legacy') || suggestion.startsWith('NOT IN')) return true; return false; }) ? 'P0' : 'P1'; report.push({ file: rel, components: found, priority: pri }); } cache[rel] = { mtime: m, components: found }; } try { await fs.writeFile(cacheFile, JSON.stringify(cache, null, 2)); } catch { /* ignore */ } return { content: [], structuredContent: { report, totalFiles: files.length, affectedFiles: report.length } }; }