Initial Commit
This commit is contained in:
133
scripts/lint/fix-deep-imports.ts
Normal file
133
scripts/lint/fix-deep-imports.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env bun
|
||||
/**
|
||||
* Fixes `../<X>.js` imports that now point to folders instead of files
|
||||
* (since migrate-feature-layout moved X.ts → X/X.ts). Rewrites to the
|
||||
* appropriate file path.
|
||||
*/
|
||||
|
||||
import {
|
||||
existsSync,
|
||||
readdirSync,
|
||||
readFileSync,
|
||||
statSync,
|
||||
writeFileSync,
|
||||
} from "node:fs";
|
||||
import { dirname, join, relative } from "node:path";
|
||||
|
||||
const PACKAGES_DIR = "packages";
|
||||
|
||||
function walkTs(dir: string): string[] {
|
||||
const out: string[] = [];
|
||||
for (const name of readdirSync(dir)) {
|
||||
const full = join(dir, name);
|
||||
const s = statSync(full);
|
||||
if (s.isDirectory()) out.push(...walkTs(full));
|
||||
else if (
|
||||
(name.endsWith(".ts") || name.endsWith(".tsx")) &&
|
||||
!name.endsWith(".d.ts")
|
||||
) {
|
||||
out.push(full);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function listPackages(): string[] {
|
||||
const out: string[] = [];
|
||||
for (const cat of readdirSync(PACKAGES_DIR)) {
|
||||
const catDir = join(PACKAGES_DIR, cat);
|
||||
if (!statSync(catDir).isDirectory()) continue;
|
||||
for (const plugin of readdirSync(catDir)) {
|
||||
const pluginDir = join(catDir, plugin);
|
||||
if (!statSync(pluginDir).isDirectory()) continue;
|
||||
for (const pkg of readdirSync(pluginDir)) {
|
||||
const pkgDir = join(pluginDir, pkg);
|
||||
if (!statSync(pkgDir).isDirectory()) continue;
|
||||
if (existsSync(join(pkgDir, "src"))) out.push(pkgDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function fileExists(p: string): boolean {
|
||||
try {
|
||||
statSync(p);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isDirectory(p: string): boolean {
|
||||
try {
|
||||
return statSync(p).isDirectory();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function fixFile(file: string, srcDir: string): number {
|
||||
const src = readFileSync(file, "utf8");
|
||||
let updated = src;
|
||||
let fixes = 0;
|
||||
|
||||
const re = /"((?:\.\.?\/)+[^"]+\.js)"/g;
|
||||
const seen = new Set<string>();
|
||||
for (const m of src.matchAll(re)) seen.add(m[1] as string);
|
||||
|
||||
for (const importPath of seen) {
|
||||
const fileDir = dirname(file);
|
||||
const stripped = importPath.replace(/\.js$/, "");
|
||||
const resolved = join(fileDir, stripped);
|
||||
|
||||
// Skip if outside src/
|
||||
const relFromSrc = relative(srcDir, resolved);
|
||||
if (relFromSrc.startsWith("..")) continue;
|
||||
|
||||
// If the .ts file exists at this exact path, resolution is fine.
|
||||
if (fileExists(`${resolved}.ts`) || fileExists(`${resolved}.tsx`))
|
||||
continue;
|
||||
// If a directory exists at this path, the import is broken — must rewrite.
|
||||
if (!isDirectory(resolved)) continue;
|
||||
|
||||
const baseName = relative(srcDir, resolved).split("/").pop() as string;
|
||||
const innerImpl = join(resolved, `${baseName}.ts`);
|
||||
const innerIndex = join(resolved, "index.ts");
|
||||
|
||||
// Prefer the impl file (matches migrate-feature-layout's sibling pattern).
|
||||
let newImportPath: string | null = null;
|
||||
if (fileExists(innerImpl)) {
|
||||
newImportPath = importPath.replace(/\.js$/, `/${baseName}.js`);
|
||||
} else if (fileExists(innerIndex)) {
|
||||
newImportPath = importPath.replace(/\.js$/, "/index.js");
|
||||
}
|
||||
if (newImportPath === null) continue;
|
||||
|
||||
updated = updated.split(`"${importPath}"`).join(`"${newImportPath}"`);
|
||||
fixes++;
|
||||
}
|
||||
|
||||
if (updated !== src) writeFileSync(file, updated);
|
||||
return fixes;
|
||||
}
|
||||
|
||||
function main(): void {
|
||||
let totalFiles = 0;
|
||||
let totalFixes = 0;
|
||||
for (const pkg of listPackages()) {
|
||||
const srcDir = join(pkg, "src");
|
||||
const files = walkTs(srcDir);
|
||||
for (const f of files) {
|
||||
const fixes = fixFile(f, srcDir);
|
||||
if (fixes > 0) {
|
||||
totalFiles++;
|
||||
totalFixes += fixes;
|
||||
console.log(`FIX ${f} (${fixes})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(`\nFixed ${totalFixes} imports across ${totalFiles} files.`);
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user