Skip to content

Commit f95cbaa

Browse files
committed
impr: enhance import tree script with folder leaf detection and error handling
!nuf
1 parent e89ec7c commit f95cbaa

1 file changed

Lines changed: 44 additions & 7 deletions

File tree

frontend/scripts/import-tree.ts

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@ function collectTsFiles(dir: string): string[] {
3535
return results;
3636
}
3737

38+
const isDir = fs.statSync(resolved).isDirectory();
39+
const boundary = isDir ? resolved : null;
40+
3841
let entryPoints: string[];
39-
if (fs.statSync(resolved).isDirectory()) {
42+
if (isDir) {
4043
entryPoints = collectTsFiles(resolved);
4144
} else {
4245
entryPoints = [resolved];
@@ -63,10 +66,17 @@ const JS_IMPORT_RE =
6366

6467
function extractImports(filePath: string): string[] {
6568
const content = fs.readFileSync(filePath, "utf-8");
66-
const { outputText } = ts.transpileModule(content, {
67-
compilerOptions: tsConfig,
68-
fileName: filePath,
69-
});
69+
let outputText: string;
70+
try {
71+
({ outputText } = ts.transpileModule(content, {
72+
compilerOptions: tsConfig,
73+
fileName: filePath,
74+
}));
75+
} catch {
76+
// Some files (e.g. declaration files) can't be transpiled — fall back to
77+
// regex on the original source, which still strips type-only imports.
78+
outputText = content;
79+
}
7080
const specifiers: string[] = [];
7181
for (const match of outputText.matchAll(JS_IMPORT_RE)) {
7282
const spec = match[1];
@@ -204,6 +214,12 @@ function depthColor(depth: number): string {
204214

205215
// --- Display ---
206216

217+
function leavesFolder(filePath: string): boolean {
218+
if (boundary === null) return false;
219+
if (filePath.startsWith("@monkeytype/")) return true;
220+
return !filePath.startsWith(boundary + "/");
221+
}
222+
207223
function displayPath(filePath: string): string {
208224
if (filePath.startsWith(ROOT + "/")) {
209225
return path.relative(ROOT, filePath);
@@ -224,9 +240,12 @@ function printTree(
224240
const connector = isRoot ? "" : isLast ? "└── " : "├── ";
225241
const dc = depthColor(depth);
226242

243+
const leaves = !isRoot && leavesFolder(filePath);
244+
const leavesTag = leaves ? ` ${c.red}[↑]${c.reset}` : "";
245+
227246
if (!info) {
228247
// leaf node (e.g. @monkeytype package)
229-
console.log(`${c.dim}${prefix}${connector}${dp}${c.reset}`);
248+
console.log(`${c.dim}${prefix}${connector}${dp}${c.reset}${leavesTag}`);
230249
return;
231250
}
232251

@@ -239,7 +258,7 @@ function printTree(
239258
const seen = !isRoot && printed.has(filePath);
240259
const seenTag = seen ? ` ${c.dim}[seen above]${c.reset}` : "";
241260
console.log(
242-
`${c.dim}${prefix}${connector}${c.reset}${nameStyle}${dp}${c.reset}${stats}${seenTag}`,
261+
`${c.dim}${prefix}${connector}${c.reset}${nameStyle}${dp}${c.reset}${stats}${leavesTag}${seenTag}`,
243262
);
244263

245264
if (seen || depth >= maxDepthLimit) return;
@@ -350,3 +369,21 @@ console.log(
350369
console.log(
351370
`Max depth: ${c.bold}${maxDepthSeen}${c.reset} ${c.dim}(${displayPath(maxDepthFile)})${c.reset}`,
352371
);
372+
373+
if (boundary !== null) {
374+
const externalDirect = new Set<string>();
375+
const externalTransitive = new Set<string>();
376+
for (const entry of entryPoints) {
377+
const info = cache.get(entry);
378+
if (!info) continue;
379+
for (const dep of info.directImports) {
380+
if (leavesFolder(dep)) externalDirect.add(dep);
381+
}
382+
for (const dep of getAllReachable(entry, new Set())) {
383+
if (leavesFolder(dep)) externalTransitive.add(dep);
384+
}
385+
}
386+
console.log(
387+
`Leaves folder ${c.red}[↑]${c.reset}: ${c.bold}${externalDirect.size}${c.reset} direct, ${c.bold}${externalTransitive.size}${c.reset} transitive`,
388+
);
389+
}

0 commit comments

Comments
 (0)