/ find-missing-imports.mjs
find-missing-imports.mjs
 1  // Finds all relative imports in dist/ that point to non-existent files
 2  import { readFileSync, existsSync, readdirSync } from 'fs';
 3  import { join, dirname, resolve, relative } from 'path';
 4  import { fileURLToPath } from 'url';
 5  
 6  const __dirname = dirname(fileURLToPath(import.meta.url));
 7  const DIST_SRC = join(__dirname, 'dist', 'src');
 8  
 9  function walkDir(dir) {
10    const results = [];
11    for (const entry of readdirSync(dir, { withFileTypes: true })) {
12      const full = join(dir, entry.name);
13      if (entry.isDirectory()) walkDir(full).forEach(f => results.push(f));
14      else if (entry.name.endsWith('.js')) results.push(full);
15    }
16    return results;
17  }
18  
19  const missing = new Set();
20  for (const f of walkDir(DIST_SRC)) {
21    const code = readFileSync(f, 'utf-8');
22    // Match: from "./foo.js"  or  from '../bar.js'
23    const re = /from\s+["'](\.[^"']+)["']/g;
24    let m;
25    while ((m = re.exec(code)) !== null) {
26      const resolved = resolve(dirname(f), m[1]);
27      if (!existsSync(resolved) && !existsSync(resolved + '.js') && !existsSync(resolved + '/index.js')) {
28        missing.add(resolved);
29      }
30    }
31  }
32  
33  const sorted = [...missing].sort();
34  console.log(`Missing files: ${sorted.length}`);
35  sorted.forEach(f => console.log(relative(join(__dirname, 'dist'), f)));