foresthouse 1.0.0-dev.2 → 1.0.0-dev.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/cli.mjs +11 -3
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +9 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{tree-Cp8CNmeY.mjs → tree-B5Q_Mgkq.mjs} +167 -45
- package/dist/tree-B5Q_Mgkq.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/tree-Cp8CNmeY.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
- Resolves local imports, re-exports, `require()`, and string-literal dynamic `import()`
|
|
20
20
|
- Honors the nearest `tsconfig.json` or `jsconfig.json`, including `baseUrl` and `paths`
|
|
21
21
|
- Prints a tree by default, or JSON with `--json`
|
|
22
|
+
- Colorizes ASCII output automatically when the terminal supports ANSI colors
|
|
22
23
|
|
|
23
24
|
## Usage
|
|
24
25
|
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as graphToSerializableReactTree, n as printReactUsageTree, o as analyzeDependencies, r as analyzeReactUsage, s as graphToSerializableTree, t as printDependencyTree } from "./tree-
|
|
2
|
+
import { a as graphToSerializableReactTree, n as printReactUsageTree, o as analyzeDependencies, r as analyzeReactUsage, s as graphToSerializableTree, t as printDependencyTree } from "./tree-B5Q_Mgkq.mjs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
//#region src/cli.ts
|
|
@@ -27,12 +27,13 @@ function main() {
|
|
|
27
27
|
...options.configPath === void 0 ? {} : { configPath: options.configPath }
|
|
28
28
|
});
|
|
29
29
|
if (options.json) {
|
|
30
|
-
process.stdout.write(`${JSON.stringify(graphToSerializableTree(graph), null, 2)}\n`);
|
|
30
|
+
process.stdout.write(`${JSON.stringify(graphToSerializableTree(graph, { omitUnused: options.omitUnused }), null, 2)}\n`);
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
process.stdout.write(`${printDependencyTree(graph, {
|
|
34
34
|
cwd: options.cwd ?? graph.cwd,
|
|
35
|
-
includeExternals: options.includeExternals
|
|
35
|
+
includeExternals: options.includeExternals,
|
|
36
|
+
omitUnused: options.omitUnused
|
|
36
37
|
})}\n`);
|
|
37
38
|
} catch (error) {
|
|
38
39
|
const message = error instanceof Error ? error.message : "Unknown error occurred.";
|
|
@@ -53,6 +54,7 @@ function parseArgs(argv) {
|
|
|
53
54
|
let cwd;
|
|
54
55
|
let configPath;
|
|
55
56
|
let includeExternals = false;
|
|
57
|
+
let omitUnused = false;
|
|
56
58
|
let json = false;
|
|
57
59
|
let react;
|
|
58
60
|
for (let index = 0; index < argv.length; index += 1) {
|
|
@@ -72,6 +74,10 @@ function parseArgs(argv) {
|
|
|
72
74
|
includeExternals = true;
|
|
73
75
|
continue;
|
|
74
76
|
}
|
|
77
|
+
if (argument === "--no-unused") {
|
|
78
|
+
omitUnused = true;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
75
81
|
if (argument === "--json") {
|
|
76
82
|
json = true;
|
|
77
83
|
continue;
|
|
@@ -98,6 +104,7 @@ function parseArgs(argv) {
|
|
|
98
104
|
cwd,
|
|
99
105
|
configPath,
|
|
100
106
|
includeExternals,
|
|
107
|
+
omitUnused,
|
|
101
108
|
json,
|
|
102
109
|
react
|
|
103
110
|
};
|
|
@@ -117,6 +124,7 @@ Options:
|
|
|
117
124
|
--cwd <path> Working directory used for relative paths.
|
|
118
125
|
--config <path> Explicit tsconfig.json or jsconfig.json path.
|
|
119
126
|
--include-externals Include packages and Node built-ins in the tree.
|
|
127
|
+
--no-unused Omit imports that are never referenced.
|
|
120
128
|
--react[=component|hook] Print a React usage tree instead of the import tree.
|
|
121
129
|
--json Print the dependency tree as JSON.
|
|
122
130
|
-v, --version Show the current version.
|
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { createRequire } from 'node:module'\nimport process from 'node:process'\n\nimport { analyzeDependencies, graphToSerializableTree } from './analyzer.js'\nimport {\n analyzeReactUsage,\n graphToSerializableReactTree,\n} from './react-analyzer.js'\nimport { printReactUsageTree } from './react-tree.js'\nimport { printDependencyTree } from './tree.js'\nimport type { ReactUsageFilter } from './types.js'\n\nconst require = createRequire(import.meta.url)\nconst { version } = require('../package.json') as { version: string }\n\ninterface CliOptions {\n readonly entryFile: string\n readonly cwd: string | undefined\n readonly configPath: string | undefined\n readonly includeExternals: boolean\n readonly json: boolean\n readonly react: ReactUsageFilter | undefined\n}\n\nfunction main(): void {\n try {\n const options = parseArgs(process.argv.slice(2))\n\n if (options.react !== undefined) {\n const graph = analyzeReactUsage(options.entryFile, {\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n ...(options.configPath === undefined\n ? {}\n : { configPath: options.configPath }),\n })\n\n if (options.json) {\n process.stdout.write(\n `${JSON.stringify(\n graphToSerializableReactTree(graph, {\n filter: options.react,\n }),\n null,\n 2,\n )}\\n`,\n )\n return\n }\n\n process.stdout.write(\n `${printReactUsageTree(graph, {\n cwd: options.cwd ?? graph.cwd,\n filter: options.react,\n })}\\n`,\n )\n return\n }\n\n const graph = analyzeDependencies(options.entryFile, {\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n ...(options.configPath === undefined\n ? {}\n : { configPath: options.configPath }),\n })\n\n if (options.json) {\n process.stdout.write(\n `${JSON.stringify(graphToSerializableTree(graph
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { createRequire } from 'node:module'\nimport process from 'node:process'\n\nimport { analyzeDependencies, graphToSerializableTree } from './analyzer.js'\nimport {\n analyzeReactUsage,\n graphToSerializableReactTree,\n} from './react-analyzer.js'\nimport { printReactUsageTree } from './react-tree.js'\nimport { printDependencyTree } from './tree.js'\nimport type { ReactUsageFilter } from './types.js'\n\nconst require = createRequire(import.meta.url)\nconst { version } = require('../package.json') as { version: string }\n\ninterface CliOptions {\n readonly entryFile: string\n readonly cwd: string | undefined\n readonly configPath: string | undefined\n readonly includeExternals: boolean\n readonly omitUnused: boolean\n readonly json: boolean\n readonly react: ReactUsageFilter | undefined\n}\n\nfunction main(): void {\n try {\n const options = parseArgs(process.argv.slice(2))\n\n if (options.react !== undefined) {\n const graph = analyzeReactUsage(options.entryFile, {\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n ...(options.configPath === undefined\n ? {}\n : { configPath: options.configPath }),\n })\n\n if (options.json) {\n process.stdout.write(\n `${JSON.stringify(\n graphToSerializableReactTree(graph, {\n filter: options.react,\n }),\n null,\n 2,\n )}\\n`,\n )\n return\n }\n\n process.stdout.write(\n `${printReactUsageTree(graph, {\n cwd: options.cwd ?? graph.cwd,\n filter: options.react,\n })}\\n`,\n )\n return\n }\n\n const graph = analyzeDependencies(options.entryFile, {\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n ...(options.configPath === undefined\n ? {}\n : { configPath: options.configPath }),\n })\n\n if (options.json) {\n process.stdout.write(\n `${JSON.stringify(\n graphToSerializableTree(graph, {\n omitUnused: options.omitUnused,\n }),\n null,\n 2,\n )}\\n`,\n )\n return\n }\n\n process.stdout.write(\n `${printDependencyTree(graph, {\n cwd: options.cwd ?? graph.cwd,\n includeExternals: options.includeExternals,\n omitUnused: options.omitUnused,\n })}\\n`,\n )\n } catch (error) {\n const message =\n error instanceof Error ? error.message : 'Unknown error occurred.'\n process.stderr.write(`foresthouse: ${message}\\n`)\n process.exitCode = 1\n }\n}\n\nfunction parseArgs(argv: string[]): CliOptions {\n if (argv.includes('--version') || argv.includes('-v')) {\n process.stdout.write(`${version}\\n`)\n process.exit(0)\n }\n\n if (argv.length === 0 || argv.includes('--help') || argv.includes('-h')) {\n printHelp()\n process.exit(0)\n }\n\n let entryFile: string | undefined\n let cwd: string | undefined\n let configPath: string | undefined\n let includeExternals = false\n let omitUnused = false\n let json = false\n let react: ReactUsageFilter | undefined\n\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index]\n if (argument === undefined) {\n continue\n }\n\n if (argument === '--cwd') {\n cwd = readOptionValue(argv, index, '--cwd')\n index += 1\n continue\n }\n\n if (argument === '--config') {\n configPath = readOptionValue(argv, index, '--config')\n index += 1\n continue\n }\n\n if (argument === '--include-externals') {\n includeExternals = true\n continue\n }\n\n if (argument === '--no-unused') {\n omitUnused = true\n continue\n }\n\n if (argument === '--json') {\n json = true\n continue\n }\n\n if (argument === '--react') {\n react = 'all'\n continue\n }\n\n if (argument.startsWith('--react=')) {\n const value = argument.slice('--react='.length)\n if (value === 'component' || value === 'hook') {\n react = value\n continue\n }\n\n throw new Error(`Unknown React mode: ${value}`)\n }\n\n if (argument.startsWith('-')) {\n throw new Error(`Unknown option: ${argument}`)\n }\n\n if (entryFile !== undefined) {\n throw new Error('Only one entry file can be provided.')\n }\n\n entryFile = argument\n }\n\n if (entryFile === undefined) {\n throw new Error('An entry file is required.')\n }\n\n return {\n entryFile,\n cwd,\n configPath,\n includeExternals,\n omitUnused,\n json,\n react,\n }\n}\n\nfunction readOptionValue(\n argv: string[],\n index: number,\n optionName: string,\n): string {\n const value = argv[index + 1]\n if (value === undefined || value.startsWith('-')) {\n throw new Error(`Missing value for ${optionName}`)\n }\n\n return value\n}\n\nfunction printHelp(): void {\n process.stdout.write(`foresthouse v${version}\n\nUsage:\n foresthouse <entry-file> [options]\n\nOptions:\n --cwd <path> Working directory used for relative paths.\n --config <path> Explicit tsconfig.json or jsconfig.json path.\n --include-externals Include packages and Node built-ins in the tree.\n --no-unused Omit imports that are never referenced.\n --react[=component|hook] Print a React usage tree instead of the import tree.\n --json Print the dependency tree as JSON.\n -v, --version Show the current version.\n -h, --help Show this help message.\n`)\n}\n\nmain()\n"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -5,6 +5,7 @@ interface DependencyEdge {
|
|
|
5
5
|
readonly specifier: string;
|
|
6
6
|
readonly referenceKind: ReferenceKind;
|
|
7
7
|
readonly isTypeOnly: boolean;
|
|
8
|
+
readonly unused: boolean;
|
|
8
9
|
readonly kind: DependencyKind;
|
|
9
10
|
readonly target: string;
|
|
10
11
|
}
|
|
@@ -25,8 +26,11 @@ interface AnalyzeOptions {
|
|
|
25
26
|
interface PrintTreeOptions {
|
|
26
27
|
readonly cwd?: string;
|
|
27
28
|
readonly includeExternals?: boolean;
|
|
29
|
+
readonly omitUnused?: boolean;
|
|
30
|
+
readonly color?: ColorMode;
|
|
28
31
|
}
|
|
29
32
|
type ReactSymbolKind = 'component' | 'hook';
|
|
33
|
+
type ColorMode = boolean | 'auto';
|
|
30
34
|
type ReactUsageFilter = 'all' | ReactSymbolKind;
|
|
31
35
|
type ReactUsageEdgeKind = 'render' | 'hook-call';
|
|
32
36
|
interface ReactUsageEdge {
|
|
@@ -49,11 +53,14 @@ interface ReactUsageGraph {
|
|
|
49
53
|
interface PrintReactTreeOptions {
|
|
50
54
|
readonly cwd?: string;
|
|
51
55
|
readonly filter?: ReactUsageFilter;
|
|
56
|
+
readonly color?: ColorMode;
|
|
52
57
|
}
|
|
53
58
|
//#endregion
|
|
54
59
|
//#region src/analyzer.d.ts
|
|
55
60
|
declare function analyzeDependencies(entryFile: string, options?: AnalyzeOptions): DependencyGraph;
|
|
56
|
-
declare function graphToSerializableTree(graph: DependencyGraph
|
|
61
|
+
declare function graphToSerializableTree(graph: DependencyGraph, options?: {
|
|
62
|
+
readonly omitUnused?: boolean;
|
|
63
|
+
}): object;
|
|
57
64
|
//#endregion
|
|
58
65
|
//#region src/react-analyzer.d.ts
|
|
59
66
|
declare function analyzeReactUsage(entryFile: string, options?: AnalyzeOptions): ReactUsageGraph;
|
|
@@ -68,5 +75,5 @@ declare function printReactUsageTree(graph: ReactUsageGraph, options?: PrintReac
|
|
|
68
75
|
//#region src/tree.d.ts
|
|
69
76
|
declare function printDependencyTree(graph: DependencyGraph, options?: PrintTreeOptions): string;
|
|
70
77
|
//#endregion
|
|
71
|
-
export { type AnalyzeOptions, type DependencyEdge, type DependencyGraph, type DependencyKind, type PrintReactTreeOptions, type PrintTreeOptions, type ReactSymbolKind, type ReactUsageEdge, type ReactUsageEdgeKind, type ReactUsageFilter, type ReactUsageGraph, type ReactUsageNode, type ReferenceKind, type SourceModuleNode, analyzeDependencies, analyzeReactUsage, getReactUsageRoots, graphToSerializableReactTree, graphToSerializableTree, printDependencyTree, printReactUsageTree };
|
|
78
|
+
export { type AnalyzeOptions, type ColorMode, type DependencyEdge, type DependencyGraph, type DependencyKind, type PrintReactTreeOptions, type PrintTreeOptions, type ReactSymbolKind, type ReactUsageEdge, type ReactUsageEdgeKind, type ReactUsageFilter, type ReactUsageGraph, type ReactUsageNode, type ReferenceKind, type SourceModuleNode, analyzeDependencies, analyzeReactUsage, getReactUsageRoots, graphToSerializableReactTree, graphToSerializableTree, printDependencyTree, printReactUsageTree };
|
|
72
79
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/analyzer.ts","../src/react-analyzer.ts","../src/react-tree.ts","../src/tree.ts"],"mappings":";KAAY,cAAA;AAAA,KAEA,aAAA;AAAA,UAOK,cAAA;EAAA,SACN,SAAA;EAAA,SACA,aAAA,EAAe,aAAA;EAAA,SACf,UAAA;EAAA,SACA,IAAA,EAAM,cAAA;EAAA,SACN,MAAA;AAAA;AAAA,UAGM,gBAAA;EAAA,SACN,EAAA;EAAA,SACA,YAAA,WAAuB,cAAA;AAAA;AAAA,UAGjB,eAAA;EAAA,SACN,GAAA;EAAA,SACA,OAAA;EAAA,SACA,KAAA,EAAO,WAAA,SAAoB,gBAAA;EAAA,SAC3B,UAAA;AAAA;AAAA,UAGM,cAAA;EAAA,SACN,GAAA;EAAA,SACA,UAAA;AAAA;AAAA,UAGM,gBAAA;EAAA,SACN,GAAA;EAAA,SACA,gBAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/analyzer.ts","../src/react-analyzer.ts","../src/react-tree.ts","../src/tree.ts"],"mappings":";KAAY,cAAA;AAAA,KAEA,aAAA;AAAA,UAOK,cAAA;EAAA,SACN,SAAA;EAAA,SACA,aAAA,EAAe,aAAA;EAAA,SACf,UAAA;EAAA,SACA,MAAA;EAAA,SACA,IAAA,EAAM,cAAA;EAAA,SACN,MAAA;AAAA;AAAA,UAGM,gBAAA;EAAA,SACN,EAAA;EAAA,SACA,YAAA,WAAuB,cAAA;AAAA;AAAA,UAGjB,eAAA;EAAA,SACN,GAAA;EAAA,SACA,OAAA;EAAA,SACA,KAAA,EAAO,WAAA,SAAoB,gBAAA;EAAA,SAC3B,UAAA;AAAA;AAAA,UAGM,cAAA;EAAA,SACN,GAAA;EAAA,SACA,UAAA;AAAA;AAAA,UAGM,gBAAA;EAAA,SACN,GAAA;EAAA,SACA,gBAAA;EAAA,SACA,UAAA;EAAA,SACA,KAAA,GAAQ,SAAA;AAAA;AAAA,KAGP,eAAA;AAAA,KAEA,SAAA;AAAA,KAEA,gBAAA,WAA2B,eAAA;AAAA,KAE3B,kBAAA;AAAA,UAEK,cAAA;EAAA,SACN,IAAA,EAAM,kBAAA;EAAA,SACN,MAAA;AAAA;AAAA,UAGM,cAAA;EAAA,SACN,EAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA,EAAM,eAAA;EAAA,SACN,QAAA;EAAA,SACA,WAAA;EAAA,SACA,MAAA,WAAiB,cAAA;AAAA;AAAA,UAGX,eAAA;EAAA,SACN,GAAA;EAAA,SACA,OAAA;EAAA,SACA,KAAA,EAAO,WAAA,SAAoB,cAAA;AAAA;AAAA,UAGrB,qBAAA;EAAA,SACN,GAAA;EAAA,SACA,MAAA,GAAS,gBAAA;EAAA,SACT,KAAA,GAAQ,SAAA;AAAA;;;iBC1CH,mBAAA,CACd,SAAA,UACA,OAAA,GAAS,cAAA,GACR,eAAA;AAAA,iBA8Ba,uBAAA,CACd,KAAA,EAAO,eAAA,EACP,OAAA;EAAA,SACW,UAAA;AAAA;;;iBCcG,iBAAA,CACd,SAAA,UACA,OAAA,GAAS,cAAA,GACR,eAAA;AAAA,iBAyHa,4BAAA,CACd,KAAA,EAAO,eAAA,EACP,OAAA;EAAA,SACW,MAAA,GAAS,gBAAA;AAAA;AAAA,iBAkBN,kBAAA,CACd,KAAA,EAAO,eAAA,EACP,MAAA,GAAQ,gBAAA;;;iBC1NM,mBAAA,CACd,KAAA,EAAO,eAAA,EACP,OAAA,GAAS,qBAAA;;;iBCJK,mBAAA,CACd,KAAA,EAAO,eAAA,EACP,OAAA,GAAS,gBAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as graphToSerializableReactTree, i as getReactUsageRoots, n as printReactUsageTree, o as analyzeDependencies, r as analyzeReactUsage, s as graphToSerializableTree, t as printDependencyTree } from "./tree-
|
|
1
|
+
import { a as graphToSerializableReactTree, i as getReactUsageRoots, n as printReactUsageTree, o as analyzeDependencies, r as analyzeReactUsage, s as graphToSerializableTree, t as printDependencyTree } from "./tree-B5Q_Mgkq.mjs";
|
|
2
2
|
export { analyzeDependencies, analyzeReactUsage, getReactUsageRoots, graphToSerializableReactTree, graphToSerializableTree, printDependencyTree, printReactUsageTree };
|
|
@@ -3,6 +3,7 @@ import fs from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import ts from "typescript";
|
|
5
5
|
import { parseSync, visitorKeys } from "oxc-parser";
|
|
6
|
+
import process$1 from "node:process";
|
|
6
7
|
//#region src/config.ts
|
|
7
8
|
function loadCompilerOptions(searchFrom, explicitConfigPath) {
|
|
8
9
|
const configPath = explicitConfigPath === void 0 ? findNearestConfig(searchFrom) : path.resolve(searchFrom, explicitConfigPath);
|
|
@@ -86,7 +87,8 @@ function analyzeDependencies(entryFile, options = {}) {
|
|
|
86
87
|
...ts.sys.realpath === void 0 ? {} : { realpath: ts.sys.realpath }
|
|
87
88
|
};
|
|
88
89
|
const nodes = /* @__PURE__ */ new Map();
|
|
89
|
-
|
|
90
|
+
const program = createProgram(resolvedEntryPath, compilerOptions, cwd);
|
|
91
|
+
visitFile(resolvedEntryPath, compilerOptions, host, program.getTypeChecker(), program, nodes);
|
|
90
92
|
return {
|
|
91
93
|
cwd,
|
|
92
94
|
entryId: resolvedEntryPath,
|
|
@@ -94,11 +96,11 @@ function analyzeDependencies(entryFile, options = {}) {
|
|
|
94
96
|
...configPath === void 0 ? {} : { configPath }
|
|
95
97
|
};
|
|
96
98
|
}
|
|
97
|
-
function graphToSerializableTree(graph) {
|
|
99
|
+
function graphToSerializableTree(graph, options = {}) {
|
|
98
100
|
const visited = /* @__PURE__ */ new Set();
|
|
99
|
-
return serializeNode(graph.entryId, graph, visited);
|
|
101
|
+
return serializeNode(graph.entryId, graph, visited, options.omitUnused ?? false);
|
|
100
102
|
}
|
|
101
|
-
function serializeNode(filePath, graph, visited) {
|
|
103
|
+
function serializeNode(filePath, graph, visited, omitUnused) {
|
|
102
104
|
const node = graph.nodes.get(filePath);
|
|
103
105
|
const displayPath = toDisplayPath(filePath, graph.cwd);
|
|
104
106
|
if (node === void 0) return {
|
|
@@ -112,11 +114,12 @@ function serializeNode(filePath, graph, visited) {
|
|
|
112
114
|
dependencies: []
|
|
113
115
|
};
|
|
114
116
|
visited.add(filePath);
|
|
115
|
-
const dependencies = node.dependencies.map((dependency) => {
|
|
117
|
+
const dependencies = node.dependencies.filter((dependency) => !omitUnused || !dependency.unused).map((dependency) => {
|
|
116
118
|
if (dependency.kind !== "source") return {
|
|
117
119
|
specifier: dependency.specifier,
|
|
118
120
|
referenceKind: dependency.referenceKind,
|
|
119
121
|
isTypeOnly: dependency.isTypeOnly,
|
|
122
|
+
unused: dependency.unused,
|
|
120
123
|
kind: dependency.kind,
|
|
121
124
|
target: dependency.kind === "missing" ? dependency.target : toDisplayPath(dependency.target, graph.cwd)
|
|
122
125
|
};
|
|
@@ -124,9 +127,10 @@ function serializeNode(filePath, graph, visited) {
|
|
|
124
127
|
specifier: dependency.specifier,
|
|
125
128
|
referenceKind: dependency.referenceKind,
|
|
126
129
|
isTypeOnly: dependency.isTypeOnly,
|
|
130
|
+
unused: dependency.unused,
|
|
127
131
|
kind: dependency.kind,
|
|
128
132
|
target: toDisplayPath(dependency.target, graph.cwd),
|
|
129
|
-
node: serializeNode(dependency.target, graph, new Set(visited))
|
|
133
|
+
node: serializeNode(dependency.target, graph, new Set(visited), omitUnused)
|
|
130
134
|
};
|
|
131
135
|
});
|
|
132
136
|
return {
|
|
@@ -135,50 +139,56 @@ function serializeNode(filePath, graph, visited) {
|
|
|
135
139
|
dependencies
|
|
136
140
|
};
|
|
137
141
|
}
|
|
138
|
-
function visitFile(filePath, compilerOptions, host, nodes) {
|
|
142
|
+
function visitFile(filePath, compilerOptions, host, checker, program, nodes) {
|
|
139
143
|
const normalizedPath = normalizeFilePath(filePath);
|
|
140
144
|
if (nodes.has(normalizedPath)) return;
|
|
141
|
-
const
|
|
142
|
-
const dependencies = collectModuleReferences(ts.createSourceFile(normalizedPath, sourceText, ts.ScriptTarget.Latest, true, getScriptKind(normalizedPath))).map((reference) => resolveDependency(reference, normalizedPath, compilerOptions, host));
|
|
145
|
+
const dependencies = collectModuleReferences(program.getSourceFile(normalizedPath) ?? createSourceFile(normalizedPath), checker).map((reference) => resolveDependency(reference, normalizedPath, compilerOptions, host));
|
|
143
146
|
nodes.set(normalizedPath, {
|
|
144
147
|
id: normalizedPath,
|
|
145
148
|
dependencies
|
|
146
149
|
});
|
|
147
|
-
for (const dependency of dependencies) if (dependency.kind === "source") visitFile(dependency.target, compilerOptions, host, nodes);
|
|
150
|
+
for (const dependency of dependencies) if (dependency.kind === "source") visitFile(dependency.target, compilerOptions, host, checker, program, nodes);
|
|
148
151
|
}
|
|
149
|
-
function collectModuleReferences(sourceFile) {
|
|
150
|
-
const references =
|
|
151
|
-
const
|
|
152
|
-
function addReference(specifier, referenceKind, isTypeOnly) {
|
|
152
|
+
function collectModuleReferences(sourceFile, checker) {
|
|
153
|
+
const references = /* @__PURE__ */ new Map();
|
|
154
|
+
const unusedImports = collectUnusedImports(sourceFile, checker);
|
|
155
|
+
function addReference(specifier, referenceKind, isTypeOnly, unused) {
|
|
153
156
|
const key = `${referenceKind}:${isTypeOnly ? "type" : "value"}:${specifier}`;
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
+
const existing = references.get(key);
|
|
158
|
+
if (existing !== void 0) {
|
|
159
|
+
if (existing.unused && !unused) references.set(key, {
|
|
160
|
+
...existing,
|
|
161
|
+
unused: false
|
|
162
|
+
});
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
references.set(key, {
|
|
157
166
|
specifier,
|
|
158
167
|
referenceKind,
|
|
159
|
-
isTypeOnly
|
|
168
|
+
isTypeOnly,
|
|
169
|
+
unused
|
|
160
170
|
});
|
|
161
171
|
}
|
|
162
172
|
function visit(node) {
|
|
163
|
-
if (ts.isImportDeclaration(node) && ts.isStringLiteralLike(node.moduleSpecifier)) addReference(node.moduleSpecifier.text, "import", node.importClause?.isTypeOnly ?? false);
|
|
164
|
-
else if (ts.isExportDeclaration(node) && node.moduleSpecifier !== void 0 && ts.isStringLiteralLike(node.moduleSpecifier)) addReference(node.moduleSpecifier.text, "export", node.isTypeOnly ?? false);
|
|
173
|
+
if (ts.isImportDeclaration(node) && ts.isStringLiteralLike(node.moduleSpecifier)) addReference(node.moduleSpecifier.text, "import", node.importClause?.isTypeOnly ?? false, unusedImports.get(node) ?? false);
|
|
174
|
+
else if (ts.isExportDeclaration(node) && node.moduleSpecifier !== void 0 && ts.isStringLiteralLike(node.moduleSpecifier)) addReference(node.moduleSpecifier.text, "export", node.isTypeOnly ?? false, false);
|
|
165
175
|
else if (ts.isImportEqualsDeclaration(node)) {
|
|
166
176
|
const moduleReference = node.moduleReference;
|
|
167
|
-
if (ts.isExternalModuleReference(moduleReference) && moduleReference.expression !== void 0 && ts.isStringLiteralLike(moduleReference.expression)) addReference(moduleReference.expression.text, "import-equals", false);
|
|
177
|
+
if (ts.isExternalModuleReference(moduleReference) && moduleReference.expression !== void 0 && ts.isStringLiteralLike(moduleReference.expression)) addReference(moduleReference.expression.text, "import-equals", false, false);
|
|
168
178
|
} else if (ts.isCallExpression(node)) {
|
|
169
179
|
if (node.expression.kind === ts.SyntaxKind.ImportKeyword && node.arguments.length === 1) {
|
|
170
180
|
const [argument] = node.arguments;
|
|
171
|
-
if (argument !== void 0 && ts.isStringLiteralLike(argument)) addReference(argument.text, "dynamic-import", false);
|
|
181
|
+
if (argument !== void 0 && ts.isStringLiteralLike(argument)) addReference(argument.text, "dynamic-import", false, false);
|
|
172
182
|
}
|
|
173
183
|
if (ts.isIdentifier(node.expression) && node.expression.text === "require" && node.arguments.length === 1) {
|
|
174
184
|
const [argument] = node.arguments;
|
|
175
|
-
if (argument !== void 0 && ts.isStringLiteralLike(argument)) addReference(argument.text, "require", false);
|
|
185
|
+
if (argument !== void 0 && ts.isStringLiteralLike(argument)) addReference(argument.text, "require", false, false);
|
|
176
186
|
}
|
|
177
187
|
}
|
|
178
188
|
ts.forEachChild(node, visit);
|
|
179
189
|
}
|
|
180
190
|
visit(sourceFile);
|
|
181
|
-
return references;
|
|
191
|
+
return [...references.values()];
|
|
182
192
|
}
|
|
183
193
|
function resolveDependency(reference, containingFile, compilerOptions, host) {
|
|
184
194
|
const specifier = reference.specifier;
|
|
@@ -197,10 +207,92 @@ function createEdge(reference, kind, target) {
|
|
|
197
207
|
specifier: reference.specifier,
|
|
198
208
|
referenceKind: reference.referenceKind,
|
|
199
209
|
isTypeOnly: reference.isTypeOnly,
|
|
210
|
+
unused: reference.unused,
|
|
200
211
|
kind,
|
|
201
212
|
target
|
|
202
213
|
};
|
|
203
214
|
}
|
|
215
|
+
function createProgram(entryFile, compilerOptions, cwd) {
|
|
216
|
+
const host = ts.createCompilerHost(compilerOptions, true);
|
|
217
|
+
host.getCurrentDirectory = () => cwd;
|
|
218
|
+
if (ts.sys.realpath !== void 0) host.realpath = ts.sys.realpath;
|
|
219
|
+
return ts.createProgram({
|
|
220
|
+
rootNames: [entryFile],
|
|
221
|
+
options: compilerOptions,
|
|
222
|
+
host
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
function createSourceFile(filePath) {
|
|
226
|
+
const sourceText = fs.readFileSync(filePath, "utf8");
|
|
227
|
+
return ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true, getScriptKind(filePath));
|
|
228
|
+
}
|
|
229
|
+
function collectUnusedImports(sourceFile, checker) {
|
|
230
|
+
const importUsage = /* @__PURE__ */ new Map();
|
|
231
|
+
const symbolToImportDeclaration = /* @__PURE__ */ new Map();
|
|
232
|
+
const importedLocalNames = /* @__PURE__ */ new Set();
|
|
233
|
+
sourceFile.statements.forEach((statement) => {
|
|
234
|
+
if (!ts.isImportDeclaration(statement) || statement.importClause === void 0) return;
|
|
235
|
+
const identifiers = getImportBindingIdentifiers(statement.importClause);
|
|
236
|
+
if (identifiers.length === 0) return;
|
|
237
|
+
importUsage.set(statement, {
|
|
238
|
+
canTrack: false,
|
|
239
|
+
used: false
|
|
240
|
+
});
|
|
241
|
+
identifiers.forEach((identifier) => {
|
|
242
|
+
importedLocalNames.add(identifier.text);
|
|
243
|
+
const symbol = tryGetSymbolAtLocation(checker, identifier);
|
|
244
|
+
if (symbol === void 0) return;
|
|
245
|
+
symbolToImportDeclaration.set(symbol, statement);
|
|
246
|
+
const state = importUsage.get(statement);
|
|
247
|
+
if (state !== void 0) state.canTrack = true;
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
function visit(node) {
|
|
251
|
+
if (ts.isImportDeclaration(node)) return;
|
|
252
|
+
if (ts.isIdentifier(node) && importedLocalNames.has(node.text) && isReferenceIdentifier(node)) {
|
|
253
|
+
const symbol = tryGetSymbolAtLocation(checker, node);
|
|
254
|
+
const declaration = symbol === void 0 ? void 0 : symbolToImportDeclaration.get(symbol);
|
|
255
|
+
if (declaration !== void 0) {
|
|
256
|
+
const state = importUsage.get(declaration);
|
|
257
|
+
if (state !== void 0) state.used = true;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
ts.forEachChild(node, visit);
|
|
261
|
+
}
|
|
262
|
+
visit(sourceFile);
|
|
263
|
+
return new Map([...importUsage.entries()].map(([declaration, state]) => [declaration, state.canTrack && !state.used]));
|
|
264
|
+
}
|
|
265
|
+
function getImportBindingIdentifiers(importClause) {
|
|
266
|
+
const identifiers = [];
|
|
267
|
+
if (importClause.name !== void 0) identifiers.push(importClause.name);
|
|
268
|
+
const namedBindings = importClause.namedBindings;
|
|
269
|
+
if (namedBindings === void 0) return identifiers;
|
|
270
|
+
if (ts.isNamespaceImport(namedBindings)) {
|
|
271
|
+
identifiers.push(namedBindings.name);
|
|
272
|
+
return identifiers;
|
|
273
|
+
}
|
|
274
|
+
namedBindings.elements.forEach((element) => {
|
|
275
|
+
identifiers.push(element.name);
|
|
276
|
+
});
|
|
277
|
+
return identifiers;
|
|
278
|
+
}
|
|
279
|
+
function isReferenceIdentifier(node) {
|
|
280
|
+
const parent = node.parent;
|
|
281
|
+
if (ts.isPropertyAccessExpression(parent) && parent.name === node) return false;
|
|
282
|
+
if (ts.isQualifiedName(parent) && parent.right === node) return false;
|
|
283
|
+
if (ts.isPropertyAssignment(parent) && parent.name === node) return false;
|
|
284
|
+
if (ts.isBindingElement(parent) && parent.propertyName === node) return false;
|
|
285
|
+
if (ts.isJsxAttribute(parent) && parent.name === node) return false;
|
|
286
|
+
if (ts.isExportSpecifier(parent)) return parent.propertyName === node || parent.propertyName === void 0;
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
function tryGetSymbolAtLocation(checker, node) {
|
|
290
|
+
try {
|
|
291
|
+
return checker.getSymbolAtLocation(node);
|
|
292
|
+
} catch {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
204
296
|
function getScriptKind(filePath) {
|
|
205
297
|
switch (path.extname(filePath).toLowerCase()) {
|
|
206
298
|
case ".js":
|
|
@@ -659,9 +751,33 @@ function isComponentName(name) {
|
|
|
659
751
|
return /^[A-Z]/.test(name);
|
|
660
752
|
}
|
|
661
753
|
//#endregion
|
|
754
|
+
//#region src/color.ts
|
|
755
|
+
const ANSI_RESET = "\x1B[0m";
|
|
756
|
+
const ANSI_COMPONENT = "\x1B[36m";
|
|
757
|
+
const ANSI_HOOK = "\x1B[35m";
|
|
758
|
+
const ANSI_UNUSED = "\x1B[38;5;214m";
|
|
759
|
+
function resolveColorSupport(mode = "auto", options = {}) {
|
|
760
|
+
if (mode === true) return true;
|
|
761
|
+
if (mode === false) return false;
|
|
762
|
+
const forceColor = "forceColor" in options ? options.forceColor : process$1.env.FORCE_COLOR;
|
|
763
|
+
if (forceColor !== void 0) return forceColor !== "0";
|
|
764
|
+
if (("noColor" in options ? options.noColor : process$1.env.NO_COLOR) !== void 0) return false;
|
|
765
|
+
return ("isTTY" in options ? options.isTTY : process$1.stdout.isTTY) === true;
|
|
766
|
+
}
|
|
767
|
+
function colorizeUnusedMarker(text, enabled) {
|
|
768
|
+
if (!enabled) return text;
|
|
769
|
+
return text.replaceAll("(unused)", `${ANSI_UNUSED}(unused)${ANSI_RESET}`);
|
|
770
|
+
}
|
|
771
|
+
function formatReactSymbolLabel(name, kind, enabled) {
|
|
772
|
+
const label = `${name} [${kind}]`;
|
|
773
|
+
if (!enabled) return label;
|
|
774
|
+
return `${kind === "component" ? ANSI_COMPONENT : ANSI_HOOK}${label}${ANSI_RESET}`;
|
|
775
|
+
}
|
|
776
|
+
//#endregion
|
|
662
777
|
//#region src/react-tree.ts
|
|
663
778
|
function printReactUsageTree(graph, options = {}) {
|
|
664
779
|
const cwd = options.cwd ?? graph.cwd;
|
|
780
|
+
const color = resolveColorSupport(options.color);
|
|
665
781
|
const filter = options.filter ?? "all";
|
|
666
782
|
const roots = getReactUsageRoots(graph, filter);
|
|
667
783
|
if (roots.length === 0) return "No React symbols found.";
|
|
@@ -669,52 +785,54 @@ function printReactUsageTree(graph, options = {}) {
|
|
|
669
785
|
roots.forEach((rootId, index) => {
|
|
670
786
|
const root = graph.nodes.get(rootId);
|
|
671
787
|
if (root === void 0) return;
|
|
672
|
-
lines.push(formatReactNodeLabel(root, cwd));
|
|
788
|
+
lines.push(formatReactNodeLabel(root, cwd, color));
|
|
673
789
|
const usages = getFilteredUsages(root, graph, filter);
|
|
674
790
|
usages.forEach((usage, usageIndex) => {
|
|
675
|
-
lines.push(...renderUsage(usage, graph, cwd, filter, new Set([root.id]), "", usageIndex === usages.length - 1));
|
|
791
|
+
lines.push(...renderUsage(usage, graph, cwd, filter, color, new Set([root.id]), "", usageIndex === usages.length - 1));
|
|
676
792
|
});
|
|
677
793
|
if (index < roots.length - 1) lines.push("");
|
|
678
794
|
});
|
|
679
795
|
return lines.join("\n");
|
|
680
796
|
}
|
|
681
|
-
function renderUsage(usage, graph, cwd, filter, visited, prefix, isLast) {
|
|
797
|
+
function renderUsage(usage, graph, cwd, filter, color, visited, prefix, isLast) {
|
|
682
798
|
const branch = `${prefix}${isLast ? "└─ " : "├─ "}`;
|
|
683
799
|
const target = graph.nodes.get(usage.target);
|
|
684
800
|
if (target === void 0) return [`${branch}${usage.target}`];
|
|
685
|
-
if (visited.has(target.id)) return [`${branch}${formatReactNodeLabel(target, cwd)} (circular)`];
|
|
686
|
-
const childLines = [`${branch}${formatReactNodeLabel(target, cwd)}`];
|
|
801
|
+
if (visited.has(target.id)) return [`${branch}${formatReactNodeLabel(target, cwd, color)} (circular)`];
|
|
802
|
+
const childLines = [`${branch}${formatReactNodeLabel(target, cwd, color)}`];
|
|
687
803
|
const nextVisited = new Set(visited);
|
|
688
804
|
nextVisited.add(target.id);
|
|
689
805
|
const nextPrefix = `${prefix}${isLast ? " " : "│ "}`;
|
|
690
806
|
const childUsages = getFilteredUsages(target, graph, filter);
|
|
691
807
|
childUsages.forEach((childUsage, index) => {
|
|
692
|
-
childLines.push(...renderUsage(childUsage, graph, cwd, filter, nextVisited, nextPrefix, index === childUsages.length - 1));
|
|
808
|
+
childLines.push(...renderUsage(childUsage, graph, cwd, filter, color, nextVisited, nextPrefix, index === childUsages.length - 1));
|
|
693
809
|
});
|
|
694
810
|
return childLines;
|
|
695
811
|
}
|
|
696
|
-
function formatReactNodeLabel(node, cwd) {
|
|
697
|
-
return `${node.name
|
|
812
|
+
function formatReactNodeLabel(node, cwd, color) {
|
|
813
|
+
return `${formatReactSymbolLabel(node.name, node.kind, color)} (${toDisplayPath(node.filePath, cwd)})`;
|
|
698
814
|
}
|
|
699
815
|
//#endregion
|
|
700
816
|
//#region src/tree.ts
|
|
701
817
|
function printDependencyTree(graph, options = {}) {
|
|
702
818
|
const cwd = options.cwd ?? graph.cwd;
|
|
819
|
+
const color = resolveColorSupport(options.color);
|
|
703
820
|
const includeExternals = options.includeExternals ?? false;
|
|
821
|
+
const omitUnused = options.omitUnused ?? false;
|
|
704
822
|
const rootLines = [toDisplayPath(graph.entryId, cwd)];
|
|
705
823
|
const visited = new Set([graph.entryId]);
|
|
706
824
|
const entryNode = graph.nodes.get(graph.entryId);
|
|
707
825
|
if (entryNode === void 0) return rootLines.join("\n");
|
|
708
|
-
const rootDependencies = filterDependencies(entryNode.dependencies, includeExternals);
|
|
826
|
+
const rootDependencies = filterDependencies(entryNode.dependencies, includeExternals, omitUnused);
|
|
709
827
|
rootDependencies.forEach((dependency, index) => {
|
|
710
|
-
const lines = renderDependency(dependency, graph, visited, "", index === rootDependencies.length - 1, includeExternals, cwd);
|
|
828
|
+
const lines = renderDependency(dependency, graph, visited, "", index === rootDependencies.length - 1, includeExternals, omitUnused, color, cwd);
|
|
711
829
|
rootLines.push(...lines);
|
|
712
830
|
});
|
|
713
831
|
return rootLines.join("\n");
|
|
714
832
|
}
|
|
715
|
-
function renderDependency(dependency, graph, visited, prefix, isLast, includeExternals, cwd) {
|
|
833
|
+
function renderDependency(dependency, graph, visited, prefix, isLast, includeExternals, omitUnused, color, cwd) {
|
|
716
834
|
const branch = `${prefix}${isLast ? "└─ " : "├─ "}`;
|
|
717
|
-
const label = formatDependencyLabel(dependency,
|
|
835
|
+
const label = formatDependencyLabel(dependency, cwd, color);
|
|
718
836
|
if (dependency.kind !== "source") return [`${branch}${label}`];
|
|
719
837
|
if (visited.has(dependency.target)) return [`${branch}${label} (circular)`];
|
|
720
838
|
const childNode = graph.nodes.get(dependency.target);
|
|
@@ -723,20 +841,21 @@ function renderDependency(dependency, graph, visited, prefix, isLast, includeExt
|
|
|
723
841
|
const nextVisited = new Set(visited);
|
|
724
842
|
nextVisited.add(dependency.target);
|
|
725
843
|
const childLines = [`${branch}${label}`];
|
|
726
|
-
const childDependencies = filterDependencies(childNode.dependencies, includeExternals);
|
|
844
|
+
const childDependencies = filterDependencies(childNode.dependencies, includeExternals, omitUnused);
|
|
727
845
|
childDependencies.forEach((childDependency, index) => {
|
|
728
846
|
const isChildLast = index === childDependencies.length - 1;
|
|
729
|
-
childLines.push(...renderDependency(childDependency, graph, nextVisited, nextPrefix, isChildLast, includeExternals, cwd));
|
|
847
|
+
childLines.push(...renderDependency(childDependency, graph, nextVisited, nextPrefix, isChildLast, includeExternals, omitUnused, color, cwd));
|
|
730
848
|
});
|
|
731
849
|
return childLines;
|
|
732
850
|
}
|
|
733
|
-
function filterDependencies(dependencies, includeExternals) {
|
|
851
|
+
function filterDependencies(dependencies, includeExternals, omitUnused) {
|
|
734
852
|
return dependencies.filter((dependency) => {
|
|
853
|
+
if (omitUnused && dependency.unused) return false;
|
|
735
854
|
if (dependency.kind === "source" || dependency.kind === "missing") return true;
|
|
736
855
|
return includeExternals;
|
|
737
856
|
});
|
|
738
857
|
}
|
|
739
|
-
function formatDependencyLabel(dependency,
|
|
858
|
+
function formatDependencyLabel(dependency, cwd, color) {
|
|
740
859
|
const prefixes = [];
|
|
741
860
|
if (dependency.isTypeOnly) prefixes.push("type");
|
|
742
861
|
if (dependency.referenceKind === "require") prefixes.push("require");
|
|
@@ -744,12 +863,15 @@ function formatDependencyLabel(dependency, _graph, cwd) {
|
|
|
744
863
|
else if (dependency.referenceKind === "export") prefixes.push("re-export");
|
|
745
864
|
else if (dependency.referenceKind === "import-equals") prefixes.push("import=");
|
|
746
865
|
const annotation = prefixes.length > 0 ? `[${prefixes.join(", ")}] ` : "";
|
|
747
|
-
if (dependency.kind === "source") return `${annotation}${toDisplayPath(dependency.target, cwd)}
|
|
748
|
-
if (dependency.kind === "missing") return `${annotation}${dependency.specifier} [missing]
|
|
749
|
-
if (dependency.kind === "builtin") return `${annotation}${dependency.target} [builtin]
|
|
750
|
-
return `${annotation}${dependency.target} [external]
|
|
866
|
+
if (dependency.kind === "source") return colorizeUnusedMarker(withUnusedSuffix(`${annotation}${toDisplayPath(dependency.target, cwd)}`, dependency.unused), color);
|
|
867
|
+
if (dependency.kind === "missing") return colorizeUnusedMarker(withUnusedSuffix(`${annotation}${dependency.specifier} [missing]`, dependency.unused), color);
|
|
868
|
+
if (dependency.kind === "builtin") return colorizeUnusedMarker(withUnusedSuffix(`${annotation}${dependency.target} [builtin]`, dependency.unused), color);
|
|
869
|
+
return colorizeUnusedMarker(withUnusedSuffix(`${annotation}${dependency.target} [external]`, dependency.unused), color);
|
|
870
|
+
}
|
|
871
|
+
function withUnusedSuffix(label, unused) {
|
|
872
|
+
return unused ? `${label} (unused)` : label;
|
|
751
873
|
}
|
|
752
874
|
//#endregion
|
|
753
875
|
export { graphToSerializableReactTree as a, getReactUsageRoots as i, printReactUsageTree as n, analyzeDependencies as o, analyzeReactUsage as r, graphToSerializableTree as s, printDependencyTree as t };
|
|
754
876
|
|
|
755
|
-
//# sourceMappingURL=tree-
|
|
877
|
+
//# sourceMappingURL=tree-B5Q_Mgkq.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree-B5Q_Mgkq.mjs","names":["process"],"sources":["../src/config.ts","../src/path-utils.ts","../src/analyzer.ts","../src/react-analyzer.ts","../src/color.ts","../src/react-tree.ts","../src/tree.ts"],"sourcesContent":["import path from 'node:path'\nimport ts from 'typescript'\n\nexport interface LoadedConfig {\n readonly path?: string\n readonly compilerOptions: ts.CompilerOptions\n}\n\nexport function loadCompilerOptions(\n searchFrom: string,\n explicitConfigPath?: string,\n): LoadedConfig {\n const configPath =\n explicitConfigPath === undefined\n ? findNearestConfig(searchFrom)\n : path.resolve(searchFrom, explicitConfigPath)\n\n if (configPath === undefined) {\n return {\n compilerOptions: defaultCompilerOptions(),\n }\n }\n\n const readResult = ts.readConfigFile(configPath, ts.sys.readFile)\n if (readResult.error !== undefined) {\n throw new Error(\n `Failed to read TypeScript config at ${configPath}: ${formatDiagnostic(\n readResult.error,\n )}`,\n )\n }\n\n const parsed = ts.parseJsonConfigFileContent(\n readResult.config,\n ts.sys,\n path.dirname(configPath),\n defaultCompilerOptions(),\n configPath,\n )\n\n if (parsed.errors.length > 0) {\n const [firstError] = parsed.errors\n if (firstError === undefined) {\n throw new Error(`Failed to parse TypeScript config at ${configPath}.`)\n }\n\n throw new Error(\n `Failed to parse TypeScript config at ${configPath}: ${formatDiagnostic(\n firstError,\n )}`,\n )\n }\n\n return {\n path: configPath,\n compilerOptions: parsed.options,\n }\n}\n\nfunction findNearestConfig(searchFrom: string): string | undefined {\n let currentDirectory = path.resolve(searchFrom)\n\n while (true) {\n const tsconfigPath = path.join(currentDirectory, 'tsconfig.json')\n if (ts.sys.fileExists(tsconfigPath)) {\n return tsconfigPath\n }\n\n const jsconfigPath = path.join(currentDirectory, 'jsconfig.json')\n if (ts.sys.fileExists(jsconfigPath)) {\n return jsconfigPath\n }\n\n const parentDirectory = path.dirname(currentDirectory)\n if (parentDirectory === currentDirectory) {\n return undefined\n }\n\n currentDirectory = parentDirectory\n }\n}\n\nfunction defaultCompilerOptions(): ts.CompilerOptions {\n return {\n allowJs: true,\n jsx: ts.JsxEmit.ReactJSX,\n module: ts.ModuleKind.NodeNext,\n moduleResolution: ts.ModuleResolutionKind.NodeNext,\n target: ts.ScriptTarget.ESNext,\n resolveJsonModule: true,\n esModuleInterop: true,\n }\n}\n\nfunction formatDiagnostic(diagnostic: ts.Diagnostic): string {\n return ts.flattenDiagnosticMessageText(diagnostic.messageText, '\\n')\n}\n","import path from 'node:path'\n\nexport const SOURCE_EXTENSIONS = new Set([\n '.js',\n '.jsx',\n '.ts',\n '.tsx',\n '.mjs',\n '.cjs',\n '.mts',\n '.cts',\n])\n\nexport function normalizeFilePath(filePath: string): string {\n return path.normalize(filePath)\n}\n\nexport function toDisplayPath(filePath: string, cwd: string): string {\n const relativePath = path.relative(cwd, filePath)\n if (relativePath === '') {\n return '.'\n }\n\n const normalizedPath = relativePath.split(path.sep).join('/')\n return normalizedPath.startsWith('..') ? filePath : normalizedPath\n}\n\nexport function isSourceCodeFile(filePath: string): boolean {\n return SOURCE_EXTENSIONS.has(path.extname(filePath).toLowerCase())\n}\n","import fs from 'node:fs'\nimport { builtinModules } from 'node:module'\nimport path from 'node:path'\nimport ts from 'typescript'\n\nimport { loadCompilerOptions } from './config.js'\nimport {\n isSourceCodeFile,\n normalizeFilePath,\n toDisplayPath,\n} from './path-utils.js'\nimport type {\n AnalyzeOptions,\n DependencyEdge,\n DependencyGraph,\n DependencyKind,\n ReferenceKind,\n SourceModuleNode,\n} from './types.js'\n\ninterface ModuleReference {\n readonly specifier: string\n readonly referenceKind: ReferenceKind\n readonly isTypeOnly: boolean\n readonly unused: boolean\n}\n\nconst BUILTIN_MODULES = new Set(\n builtinModules.flatMap((name) => [name, `node:${name}`]),\n)\n\nexport function analyzeDependencies(\n entryFile: string,\n options: AnalyzeOptions = {},\n): DependencyGraph {\n const cwd = path.resolve(options.cwd ?? process.cwd())\n const resolvedEntryPath = resolveExistingPath(cwd, entryFile)\n const { compilerOptions, path: configPath } = loadCompilerOptions(\n path.dirname(resolvedEntryPath),\n options.configPath,\n )\n\n const host: ts.ModuleResolutionHost = {\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n directoryExists: ts.sys.directoryExists,\n getCurrentDirectory: () => cwd,\n getDirectories: ts.sys.getDirectories,\n ...(ts.sys.realpath === undefined ? {} : { realpath: ts.sys.realpath }),\n }\n\n const nodes = new Map<string, SourceModuleNode>()\n const program = createProgram(resolvedEntryPath, compilerOptions, cwd)\n const checker = program.getTypeChecker()\n visitFile(resolvedEntryPath, compilerOptions, host, checker, program, nodes)\n\n return {\n cwd,\n entryId: resolvedEntryPath,\n nodes,\n ...(configPath === undefined ? {} : { configPath }),\n }\n}\n\nexport function graphToSerializableTree(\n graph: DependencyGraph,\n options: {\n readonly omitUnused?: boolean\n } = {},\n): object {\n const visited = new Set<string>()\n return serializeNode(\n graph.entryId,\n graph,\n visited,\n options.omitUnused ?? false,\n )\n}\n\nfunction serializeNode(\n filePath: string,\n graph: DependencyGraph,\n visited: Set<string>,\n omitUnused: boolean,\n): object {\n const node = graph.nodes.get(filePath)\n const displayPath = toDisplayPath(filePath, graph.cwd)\n\n if (node === undefined) {\n return {\n path: displayPath,\n kind: 'missing',\n dependencies: [],\n }\n }\n\n if (visited.has(filePath)) {\n return {\n path: displayPath,\n kind: 'circular',\n dependencies: [],\n }\n }\n\n visited.add(filePath)\n\n const dependencies = node.dependencies\n .filter((dependency) => !omitUnused || !dependency.unused)\n .map((dependency) => {\n if (dependency.kind !== 'source') {\n return {\n specifier: dependency.specifier,\n referenceKind: dependency.referenceKind,\n isTypeOnly: dependency.isTypeOnly,\n unused: dependency.unused,\n kind: dependency.kind,\n target:\n dependency.kind === 'missing'\n ? dependency.target\n : toDisplayPath(dependency.target, graph.cwd),\n }\n }\n\n return {\n specifier: dependency.specifier,\n referenceKind: dependency.referenceKind,\n isTypeOnly: dependency.isTypeOnly,\n unused: dependency.unused,\n kind: dependency.kind,\n target: toDisplayPath(dependency.target, graph.cwd),\n node: serializeNode(\n dependency.target,\n graph,\n new Set(visited),\n omitUnused,\n ),\n }\n })\n\n return {\n path: displayPath,\n kind: filePath === graph.entryId ? 'entry' : 'source',\n dependencies,\n }\n}\n\nfunction visitFile(\n filePath: string,\n compilerOptions: ts.CompilerOptions,\n host: ts.ModuleResolutionHost,\n checker: ts.TypeChecker,\n program: ts.Program,\n nodes: Map<string, SourceModuleNode>,\n): void {\n const normalizedPath = normalizeFilePath(filePath)\n if (nodes.has(normalizedPath)) {\n return\n }\n\n const sourceFile =\n program.getSourceFile(normalizedPath) ?? createSourceFile(normalizedPath)\n\n const references = collectModuleReferences(sourceFile, checker)\n const dependencies = references.map((reference) =>\n resolveDependency(reference, normalizedPath, compilerOptions, host),\n )\n\n nodes.set(normalizedPath, {\n id: normalizedPath,\n dependencies,\n })\n\n for (const dependency of dependencies) {\n if (dependency.kind === 'source') {\n visitFile(\n dependency.target,\n compilerOptions,\n host,\n checker,\n program,\n nodes,\n )\n }\n }\n}\n\nfunction collectModuleReferences(\n sourceFile: ts.SourceFile,\n checker: ts.TypeChecker,\n): ModuleReference[] {\n const references = new Map<string, ModuleReference>()\n const unusedImports = collectUnusedImports(sourceFile, checker)\n\n function addReference(\n specifier: string,\n referenceKind: ReferenceKind,\n isTypeOnly: boolean,\n unused: boolean,\n ): void {\n const key = `${referenceKind}:${isTypeOnly ? 'type' : 'value'}:${specifier}`\n const existing = references.get(key)\n if (existing !== undefined) {\n if (existing.unused && !unused) {\n references.set(key, {\n ...existing,\n unused: false,\n })\n }\n return\n }\n\n references.set(key, {\n specifier,\n referenceKind,\n isTypeOnly,\n unused,\n })\n }\n\n function visit(node: ts.Node): void {\n if (\n ts.isImportDeclaration(node) &&\n ts.isStringLiteralLike(node.moduleSpecifier)\n ) {\n addReference(\n node.moduleSpecifier.text,\n 'import',\n node.importClause?.isTypeOnly ?? false,\n unusedImports.get(node) ?? false,\n )\n } else if (\n ts.isExportDeclaration(node) &&\n node.moduleSpecifier !== undefined &&\n ts.isStringLiteralLike(node.moduleSpecifier)\n ) {\n addReference(\n node.moduleSpecifier.text,\n 'export',\n node.isTypeOnly ?? false,\n false,\n )\n } else if (ts.isImportEqualsDeclaration(node)) {\n const moduleReference = node.moduleReference\n if (\n ts.isExternalModuleReference(moduleReference) &&\n moduleReference.expression !== undefined &&\n ts.isStringLiteralLike(moduleReference.expression)\n ) {\n addReference(\n moduleReference.expression.text,\n 'import-equals',\n false,\n false,\n )\n }\n } else if (ts.isCallExpression(node)) {\n if (\n node.expression.kind === ts.SyntaxKind.ImportKeyword &&\n node.arguments.length === 1\n ) {\n const [argument] = node.arguments\n if (argument !== undefined && ts.isStringLiteralLike(argument)) {\n addReference(argument.text, 'dynamic-import', false, false)\n }\n }\n\n if (\n ts.isIdentifier(node.expression) &&\n node.expression.text === 'require' &&\n node.arguments.length === 1\n ) {\n const [argument] = node.arguments\n if (argument !== undefined && ts.isStringLiteralLike(argument)) {\n addReference(argument.text, 'require', false, false)\n }\n }\n }\n\n ts.forEachChild(node, visit)\n }\n\n visit(sourceFile)\n return [...references.values()]\n}\n\nfunction resolveDependency(\n reference: ModuleReference,\n containingFile: string,\n compilerOptions: ts.CompilerOptions,\n host: ts.ModuleResolutionHost,\n): DependencyEdge {\n const specifier = reference.specifier\n if (BUILTIN_MODULES.has(specifier)) {\n return createEdge(reference, 'builtin', specifier)\n }\n\n const resolution = ts.resolveModuleName(\n specifier,\n containingFile,\n compilerOptions,\n host,\n ).resolvedModule\n\n if (resolution !== undefined) {\n const resolvedPath = normalizeFilePath(resolution.resolvedFileName)\n if (\n resolution.isExternalLibraryImport ||\n resolvedPath.includes(`${path.sep}node_modules${path.sep}`)\n ) {\n return createEdge(reference, 'external', specifier)\n }\n\n if (isSourceCodeFile(resolvedPath) && !resolvedPath.endsWith('.d.ts')) {\n return createEdge(reference, 'source', resolvedPath)\n }\n }\n\n if (!specifier.startsWith('.') && !path.isAbsolute(specifier)) {\n return createEdge(reference, 'external', specifier)\n }\n\n return createEdge(reference, 'missing', specifier)\n}\n\nfunction createEdge(\n reference: ModuleReference,\n kind: DependencyKind,\n target: string,\n): DependencyEdge {\n return {\n specifier: reference.specifier,\n referenceKind: reference.referenceKind,\n isTypeOnly: reference.isTypeOnly,\n unused: reference.unused,\n kind,\n target,\n }\n}\n\nfunction createProgram(\n entryFile: string,\n compilerOptions: ts.CompilerOptions,\n cwd: string,\n): ts.Program {\n const host = ts.createCompilerHost(compilerOptions, true)\n host.getCurrentDirectory = () => cwd\n\n if (ts.sys.realpath !== undefined) {\n host.realpath = ts.sys.realpath\n }\n\n return ts.createProgram({\n rootNames: [entryFile],\n options: compilerOptions,\n host,\n })\n}\n\nfunction createSourceFile(filePath: string): ts.SourceFile {\n const sourceText = fs.readFileSync(filePath, 'utf8')\n return ts.createSourceFile(\n filePath,\n sourceText,\n ts.ScriptTarget.Latest,\n true,\n getScriptKind(filePath),\n )\n}\n\nfunction collectUnusedImports(\n sourceFile: ts.SourceFile,\n checker: ts.TypeChecker,\n): ReadonlyMap<ts.ImportDeclaration, boolean> {\n const importUsage = new Map<\n ts.ImportDeclaration,\n {\n canTrack: boolean\n used: boolean\n }\n >()\n const symbolToImportDeclaration = new Map<ts.Symbol, ts.ImportDeclaration>()\n const importedLocalNames = new Set<string>()\n\n sourceFile.statements.forEach((statement) => {\n if (\n !ts.isImportDeclaration(statement) ||\n statement.importClause === undefined\n ) {\n return\n }\n\n const identifiers = getImportBindingIdentifiers(statement.importClause)\n if (identifiers.length === 0) {\n return\n }\n\n importUsage.set(statement, {\n canTrack: false,\n used: false,\n })\n\n identifiers.forEach((identifier) => {\n importedLocalNames.add(identifier.text)\n\n const symbol = tryGetSymbolAtLocation(checker, identifier)\n if (symbol === undefined) {\n return\n }\n\n symbolToImportDeclaration.set(symbol, statement)\n const state = importUsage.get(statement)\n if (state !== undefined) {\n state.canTrack = true\n }\n })\n })\n\n function visit(node: ts.Node): void {\n if (ts.isImportDeclaration(node)) {\n return\n }\n\n if (\n ts.isIdentifier(node) &&\n importedLocalNames.has(node.text) &&\n isReferenceIdentifier(node)\n ) {\n const symbol = tryGetSymbolAtLocation(checker, node)\n const declaration =\n symbol === undefined ? undefined : symbolToImportDeclaration.get(symbol)\n if (declaration !== undefined) {\n const state = importUsage.get(declaration)\n if (state !== undefined) {\n state.used = true\n }\n }\n }\n\n ts.forEachChild(node, visit)\n }\n\n visit(sourceFile)\n\n return new Map(\n [...importUsage.entries()].map(([declaration, state]) => [\n declaration,\n state.canTrack && !state.used,\n ]),\n )\n}\n\nfunction getImportBindingIdentifiers(\n importClause: ts.ImportClause,\n): ts.Identifier[] {\n const identifiers: ts.Identifier[] = []\n\n if (importClause.name !== undefined) {\n identifiers.push(importClause.name)\n }\n\n const namedBindings = importClause.namedBindings\n if (namedBindings === undefined) {\n return identifiers\n }\n\n if (ts.isNamespaceImport(namedBindings)) {\n identifiers.push(namedBindings.name)\n return identifiers\n }\n\n namedBindings.elements.forEach((element) => {\n identifiers.push(element.name)\n })\n\n return identifiers\n}\n\nfunction isReferenceIdentifier(node: ts.Identifier): boolean {\n const parent = node.parent\n\n if (ts.isPropertyAccessExpression(parent) && parent.name === node) {\n return false\n }\n\n if (ts.isQualifiedName(parent) && parent.right === node) {\n return false\n }\n\n if (ts.isPropertyAssignment(parent) && parent.name === node) {\n return false\n }\n\n if (ts.isBindingElement(parent) && parent.propertyName === node) {\n return false\n }\n\n if (ts.isJsxAttribute(parent) && parent.name === node) {\n return false\n }\n\n if (ts.isExportSpecifier(parent)) {\n return parent.propertyName === node || parent.propertyName === undefined\n }\n\n return true\n}\n\nfunction tryGetSymbolAtLocation(\n checker: ts.TypeChecker,\n node: ts.Node,\n): ts.Symbol | undefined {\n try {\n return checker.getSymbolAtLocation(node)\n } catch {\n return undefined\n }\n}\n\nfunction getScriptKind(filePath: string): ts.ScriptKind {\n switch (path.extname(filePath).toLowerCase()) {\n case '.js':\n case '.mjs':\n case '.cjs':\n return ts.ScriptKind.JS\n case '.jsx':\n return ts.ScriptKind.JSX\n case '.tsx':\n return ts.ScriptKind.TSX\n case '.json':\n return ts.ScriptKind.JSON\n default:\n return ts.ScriptKind.TS\n }\n}\n\nfunction resolveExistingPath(cwd: string, entryFile: string): string {\n const absolutePath = path.resolve(cwd, entryFile)\n const normalizedPath = normalizeFilePath(absolutePath)\n\n if (!fs.existsSync(normalizedPath)) {\n throw new Error(`Entry file not found: ${entryFile}`)\n }\n\n if (!isSourceCodeFile(normalizedPath)) {\n throw new Error(`Entry file must be a JS/TS source file: ${entryFile}`)\n }\n\n return normalizedPath\n}\n","import fs from 'node:fs'\nimport type {\n ArrowFunctionExpression,\n CallExpression,\n ExportDefaultDeclaration,\n ExportNamedDeclaration,\n Expression,\n FunctionBody,\n ImportDeclaration,\n ImportDeclarationSpecifier,\n JSXElement,\n JSXElementName,\n JSXFragment,\n ModuleExportName,\n Node,\n Function as OxcFunction,\n Program,\n Statement,\n VariableDeclarator,\n} from 'oxc-parser'\nimport { parseSync, visitorKeys } from 'oxc-parser'\n\nimport { analyzeDependencies } from './analyzer.js'\nimport { isSourceCodeFile, toDisplayPath } from './path-utils.js'\nimport type {\n AnalyzeOptions,\n ReactSymbolKind,\n ReactUsageEdge,\n ReactUsageFilter,\n ReactUsageGraph,\n ReactUsageNode,\n} from './types.js'\n\ninterface PendingReactUsageNode {\n readonly id: string\n readonly name: string\n readonly kind: ReactSymbolKind\n readonly filePath: string\n readonly declaration: OxcFunction | ArrowFunctionExpression\n readonly exportNames: Set<string>\n readonly componentReferences: Set<string>\n readonly hookReferences: Set<string>\n}\n\ninterface ImportBinding {\n readonly importedName: string\n readonly sourceSpecifier: string\n readonly sourcePath?: string\n}\n\ninterface FileAnalysis {\n readonly filePath: string\n readonly importsByLocalName: Map<string, ImportBinding>\n readonly exportsByName: Map<string, string>\n readonly symbolsById: Map<string, PendingReactUsageNode>\n readonly symbolsByName: Map<string, PendingReactUsageNode>\n}\n\ninterface SerializedReactUsageNode {\n readonly id: string\n readonly name: string\n readonly symbolKind: ReactSymbolKind | 'circular'\n readonly filePath: string\n readonly exportNames: readonly string[]\n readonly usages: readonly SerializedReactUsageEdge[]\n}\n\ninterface SerializedReactUsageEdge {\n readonly kind: ReactUsageEdge['kind']\n readonly targetId: string\n readonly node: SerializedReactUsageNode\n}\n\nconst FUNCTION_NODE_TYPES = new Set([\n 'FunctionDeclaration',\n 'FunctionExpression',\n 'ArrowFunctionExpression',\n 'TSDeclareFunction',\n 'TSEmptyBodyFunctionExpression',\n])\n\nexport function analyzeReactUsage(\n entryFile: string,\n options: AnalyzeOptions = {},\n): ReactUsageGraph {\n const dependencyGraph = analyzeDependencies(entryFile, options)\n const reachableFiles = new Set<string>([\n dependencyGraph.entryId,\n ...dependencyGraph.nodes.keys(),\n ])\n const fileAnalyses = new Map<string, FileAnalysis>()\n\n for (const filePath of [...reachableFiles].sort()) {\n if (!isSourceCodeFile(filePath) || filePath.endsWith('.d.ts')) {\n continue\n }\n\n const sourceText = fs.readFileSync(filePath, 'utf8')\n const parseResult = parseSync(filePath, sourceText, {\n astType: 'ts',\n sourceType: 'unambiguous',\n })\n\n const dependencyNode = dependencyGraph.nodes.get(filePath)\n const sourceDependencies = new Map<string, string>()\n dependencyNode?.dependencies.forEach((dependency) => {\n if (dependency.kind === 'source') {\n sourceDependencies.set(dependency.specifier, dependency.target)\n }\n })\n\n fileAnalyses.set(\n filePath,\n analyzeReactFile(parseResult.program, filePath, sourceDependencies),\n )\n }\n\n const nodes = new Map<string, ReactUsageNode>()\n for (const fileAnalysis of fileAnalyses.values()) {\n for (const symbol of fileAnalysis.symbolsById.values()) {\n nodes.set(symbol.id, {\n id: symbol.id,\n name: symbol.name,\n kind: symbol.kind,\n filePath: symbol.filePath,\n exportNames: [...symbol.exportNames].sort(),\n usages: [],\n })\n }\n }\n\n for (const fileAnalysis of fileAnalyses.values()) {\n fileAnalysis.importsByLocalName.forEach((binding, localName) => {\n if (binding.sourcePath !== undefined) {\n return\n }\n\n if (!isHookName(localName) && !isHookName(binding.importedName)) {\n return\n }\n\n const externalNode = createExternalHookNode(binding, localName)\n if (!nodes.has(externalNode.id)) {\n nodes.set(externalNode.id, externalNode)\n }\n })\n }\n\n for (const fileAnalysis of fileAnalyses.values()) {\n for (const symbol of fileAnalysis.symbolsById.values()) {\n const usages = new Map<string, ReactUsageEdge>()\n\n symbol.componentReferences.forEach((referenceName) => {\n const targetId = resolveReactReference(\n fileAnalysis,\n fileAnalyses,\n referenceName,\n 'component',\n )\n if (targetId !== undefined && targetId !== symbol.id) {\n usages.set(`render:${targetId}`, {\n kind: 'render',\n target: targetId,\n })\n }\n })\n\n symbol.hookReferences.forEach((referenceName) => {\n const targetId = resolveReactReference(\n fileAnalysis,\n fileAnalyses,\n referenceName,\n 'hook',\n )\n if (targetId !== undefined && targetId !== symbol.id) {\n usages.set(`hook:${targetId}`, {\n kind: 'hook-call',\n target: targetId,\n })\n }\n })\n\n const node = nodes.get(symbol.id)\n if (node === undefined) {\n continue\n }\n\n const sortedUsages = [...usages.values()].sort((left, right) =>\n compareReactNodeIds(left.target, right.target, nodes),\n )\n\n nodes.set(symbol.id, {\n ...node,\n usages: sortedUsages,\n })\n }\n }\n\n return {\n cwd: dependencyGraph.cwd,\n entryId: dependencyGraph.entryId,\n nodes,\n }\n}\n\nexport function graphToSerializableReactTree(\n graph: ReactUsageGraph,\n options: {\n readonly filter?: ReactUsageFilter\n } = {},\n): object {\n const roots = getReactUsageRoots(graph, options.filter)\n\n return {\n kind: 'react-usage',\n roots: roots.map((rootId) =>\n serializeReactUsageNode(\n rootId,\n graph,\n options.filter ?? 'all',\n new Set(),\n ),\n ),\n }\n}\n\nexport function getReactUsageRoots(\n graph: ReactUsageGraph,\n filter: ReactUsageFilter = 'all',\n): string[] {\n const filteredNodes = getFilteredReactUsageNodes(graph, filter)\n const inboundCounts = new Map<string, number>()\n\n filteredNodes.forEach((node) => {\n inboundCounts.set(node.id, 0)\n })\n\n filteredNodes.forEach((node) => {\n getFilteredUsages(node, graph, filter).forEach((usage) => {\n inboundCounts.set(\n usage.target,\n (inboundCounts.get(usage.target) ?? 0) + 1,\n )\n })\n })\n\n const roots = filteredNodes\n .filter((node) => (inboundCounts.get(node.id) ?? 0) === 0)\n .map((node) => node.id)\n\n if (roots.length > 0) {\n return roots.sort((left, right) =>\n compareReactNodeIds(left, right, graph.nodes),\n )\n }\n\n return filteredNodes\n .map((node) => node.id)\n .sort((left, right) => compareReactNodeIds(left, right, graph.nodes))\n}\n\nexport function getFilteredUsages(\n node: ReactUsageNode,\n graph: ReactUsageGraph,\n filter: ReactUsageFilter = 'all',\n): ReactUsageEdge[] {\n return node.usages.filter((usage) => {\n const targetNode = graph.nodes.get(usage.target)\n return targetNode !== undefined && matchesReactFilter(targetNode, filter)\n })\n}\n\nfunction analyzeReactFile(\n program: Program,\n filePath: string,\n sourceDependencies: ReadonlyMap<string, string>,\n): FileAnalysis {\n const symbolsByName = new Map<string, PendingReactUsageNode>()\n\n program.body.forEach((statement) => {\n collectTopLevelReactSymbols(statement, filePath, symbolsByName)\n })\n\n const importsByLocalName = new Map<string, ImportBinding>()\n const exportsByName = new Map<string, string>()\n\n program.body.forEach((statement) => {\n collectImportsAndExports(\n statement,\n sourceDependencies,\n symbolsByName,\n importsByLocalName,\n exportsByName,\n )\n })\n\n symbolsByName.forEach((symbol) => {\n analyzeSymbolUsages(symbol)\n })\n\n return {\n filePath,\n importsByLocalName,\n exportsByName,\n symbolsById: new Map(\n [...symbolsByName.values()].map((symbol) => [symbol.id, symbol]),\n ),\n symbolsByName,\n }\n}\n\nfunction collectTopLevelReactSymbols(\n statement: Statement,\n filePath: string,\n symbolsByName: Map<string, PendingReactUsageNode>,\n): void {\n switch (statement.type) {\n case 'FunctionDeclaration':\n addFunctionSymbol(statement, filePath, symbolsByName)\n return\n case 'VariableDeclaration':\n statement.declarations.forEach((declarator) => {\n addVariableSymbol(declarator, filePath, symbolsByName)\n })\n return\n case 'ExportNamedDeclaration':\n if (statement.declaration !== null) {\n collectTopLevelReactSymbols(\n statement.declaration,\n filePath,\n symbolsByName,\n )\n }\n return\n case 'ExportDefaultDeclaration':\n addDefaultExportSymbol(statement, filePath, symbolsByName)\n return\n default:\n return\n }\n}\n\nfunction addFunctionSymbol(\n declaration: OxcFunction,\n filePath: string,\n symbolsByName: Map<string, PendingReactUsageNode>,\n): void {\n const name = declaration.id?.name\n if (name === undefined) {\n return\n }\n\n const kind = classifyReactSymbol(name, declaration)\n if (kind === undefined) {\n return\n }\n\n symbolsByName.set(\n name,\n createPendingSymbol(filePath, name, kind, declaration),\n )\n}\n\nfunction addVariableSymbol(\n declarator: VariableDeclarator,\n filePath: string,\n symbolsByName: Map<string, PendingReactUsageNode>,\n): void {\n if (declarator.id.type !== 'Identifier' || declarator.init === null) {\n return\n }\n\n if (\n declarator.init.type !== 'ArrowFunctionExpression' &&\n declarator.init.type !== 'FunctionExpression'\n ) {\n return\n }\n\n const name = declarator.id.name\n const kind = classifyReactSymbol(name, declarator.init)\n if (kind === undefined) {\n return\n }\n\n symbolsByName.set(\n name,\n createPendingSymbol(filePath, name, kind, declarator.init),\n )\n}\n\nfunction addDefaultExportSymbol(\n declaration: ExportDefaultDeclaration,\n filePath: string,\n symbolsByName: Map<string, PendingReactUsageNode>,\n): void {\n if (\n declaration.declaration.type === 'FunctionDeclaration' ||\n declaration.declaration.type === 'FunctionExpression'\n ) {\n addFunctionSymbol(declaration.declaration, filePath, symbolsByName)\n } else if (declaration.declaration.type === 'ArrowFunctionExpression') {\n const name = 'default'\n const kind = declaration.declaration.body\n ? classifyReactSymbol(name, declaration.declaration)\n : undefined\n if (kind !== undefined) {\n symbolsByName.set(\n name,\n createPendingSymbol(filePath, name, kind, declaration.declaration),\n )\n }\n }\n}\n\nfunction createPendingSymbol(\n filePath: string,\n name: string,\n kind: ReactSymbolKind,\n declaration: OxcFunction | ArrowFunctionExpression,\n): PendingReactUsageNode {\n return {\n id: `${filePath}#${kind}:${name}`,\n name,\n kind,\n filePath,\n declaration,\n exportNames: new Set<string>(),\n componentReferences: new Set<string>(),\n hookReferences: new Set<string>(),\n }\n}\n\nfunction collectImportsAndExports(\n statement: Statement,\n sourceDependencies: ReadonlyMap<string, string>,\n symbolsByName: ReadonlyMap<string, PendingReactUsageNode>,\n importsByLocalName: Map<string, ImportBinding>,\n exportsByName: Map<string, string>,\n): void {\n switch (statement.type) {\n case 'ImportDeclaration':\n collectImportBindings(statement, sourceDependencies, importsByLocalName)\n return\n case 'ExportNamedDeclaration':\n collectNamedExports(statement, symbolsByName, exportsByName)\n return\n case 'ExportDefaultDeclaration':\n collectDefaultExport(statement, symbolsByName, exportsByName)\n return\n default:\n return\n }\n}\n\nfunction collectImportBindings(\n declaration: ImportDeclaration,\n sourceDependencies: ReadonlyMap<string, string>,\n importsByLocalName: Map<string, ImportBinding>,\n): void {\n if (declaration.importKind === 'type') {\n return\n }\n\n const sourceSpecifier = declaration.source.value\n const sourcePath = sourceDependencies.get(declaration.source.value)\n\n declaration.specifiers.forEach((specifier) => {\n const binding = getImportBinding(specifier, sourceSpecifier, sourcePath)\n if (binding === undefined) {\n return\n }\n\n importsByLocalName.set(binding.localName, {\n importedName: binding.importedName,\n sourceSpecifier: binding.sourceSpecifier,\n ...(binding.sourcePath === undefined\n ? {}\n : { sourcePath: binding.sourcePath }),\n })\n })\n}\n\nfunction getImportBinding(\n specifier: ImportDeclarationSpecifier,\n sourceSpecifier: string,\n sourcePath: string | undefined,\n):\n | {\n readonly localName: string\n readonly importedName: string\n readonly sourceSpecifier: string\n readonly sourcePath?: string\n }\n | undefined {\n if (specifier.type === 'ImportSpecifier') {\n if (specifier.importKind === 'type') {\n return undefined\n }\n\n return {\n localName: specifier.local.name,\n importedName: toModuleExportName(specifier.imported),\n sourceSpecifier,\n ...(sourcePath === undefined ? {} : { sourcePath }),\n }\n }\n\n if (specifier.type === 'ImportDefaultSpecifier') {\n return {\n localName: specifier.local.name,\n importedName: 'default',\n sourceSpecifier,\n ...(sourcePath === undefined ? {} : { sourcePath }),\n }\n }\n\n return undefined\n}\n\nfunction collectNamedExports(\n declaration: ExportNamedDeclaration,\n symbolsByName: ReadonlyMap<string, PendingReactUsageNode>,\n exportsByName: Map<string, string>,\n): void {\n if (declaration.exportKind === 'type') {\n return\n }\n\n if (declaration.declaration !== null) {\n if (declaration.declaration.type === 'FunctionDeclaration') {\n const name = declaration.declaration.id?.name\n if (name !== undefined) {\n addExportBinding(name, name, symbolsByName, exportsByName)\n }\n } else if (declaration.declaration.type === 'VariableDeclaration') {\n declaration.declaration.declarations.forEach((declarator) => {\n if (declarator.id.type === 'Identifier') {\n addExportBinding(\n declarator.id.name,\n declarator.id.name,\n symbolsByName,\n exportsByName,\n )\n }\n })\n }\n\n return\n }\n\n if (declaration.source !== null) {\n return\n }\n\n declaration.specifiers.forEach((specifier) => {\n if (specifier.exportKind === 'type') {\n return\n }\n\n const localName = toModuleExportName(specifier.local)\n const exportedName = toModuleExportName(specifier.exported)\n addExportBinding(localName, exportedName, symbolsByName, exportsByName)\n })\n}\n\nfunction collectDefaultExport(\n declaration: ExportDefaultDeclaration,\n symbolsByName: ReadonlyMap<string, PendingReactUsageNode>,\n exportsByName: Map<string, string>,\n): void {\n if (\n declaration.declaration.type === 'FunctionDeclaration' ||\n declaration.declaration.type === 'FunctionExpression'\n ) {\n const localName = declaration.declaration.id?.name\n if (localName !== undefined) {\n addExportBinding(localName, 'default', symbolsByName, exportsByName)\n }\n return\n }\n\n if (declaration.declaration.type === 'Identifier') {\n addExportBinding(\n declaration.declaration.name,\n 'default',\n symbolsByName,\n exportsByName,\n )\n return\n }\n\n if (declaration.declaration.type === 'ArrowFunctionExpression') {\n addExportBinding('default', 'default', symbolsByName, exportsByName)\n }\n}\n\nfunction addExportBinding(\n localName: string,\n exportedName: string,\n symbolsByName: ReadonlyMap<string, PendingReactUsageNode>,\n exportsByName: Map<string, string>,\n): void {\n const symbol = symbolsByName.get(localName)\n if (symbol === undefined) {\n return\n }\n\n symbol.exportNames.add(exportedName)\n exportsByName.set(exportedName, symbol.id)\n}\n\nfunction analyzeSymbolUsages(symbol: PendingReactUsageNode): void {\n const root =\n symbol.declaration.type === 'ArrowFunctionExpression'\n ? symbol.declaration.body\n : symbol.declaration.body\n\n if (root === null) {\n return\n }\n\n walkReactUsageTree(root, (node) => {\n if (node.type === 'JSXElement') {\n const name = getComponentReferenceName(node)\n if (name !== undefined) {\n symbol.componentReferences.add(name)\n }\n return\n }\n\n if (node.type === 'CallExpression') {\n const hookReference = getHookReferenceName(node)\n if (hookReference !== undefined) {\n symbol.hookReferences.add(hookReference)\n }\n\n const componentReference = getCreateElementComponentReferenceName(node)\n if (componentReference !== undefined) {\n symbol.componentReferences.add(componentReference)\n }\n }\n })\n}\n\nfunction classifyReactSymbol(\n name: string,\n declaration: OxcFunction | ArrowFunctionExpression,\n): ReactSymbolKind | undefined {\n if (isHookName(name)) {\n return 'hook'\n }\n\n if (isComponentName(name) && returnsReactElement(declaration)) {\n return 'component'\n }\n\n return undefined\n}\n\nfunction returnsReactElement(\n declaration: OxcFunction | ArrowFunctionExpression,\n): boolean {\n if (\n declaration.type === 'ArrowFunctionExpression' &&\n declaration.expression\n ) {\n return containsReactElementLikeExpression(declaration.body as Expression)\n }\n\n const body = declaration.body\n if (body === null) {\n return false\n }\n\n let found = false\n walkReactUsageTree(body, (node) => {\n if (node.type !== 'ReturnStatement' || node.argument === null) {\n return\n }\n\n if (containsReactElementLikeExpression(node.argument)) {\n found = true\n }\n })\n\n return found\n}\n\nfunction containsReactElementLikeExpression(expression: Expression): boolean {\n let found = false\n\n walkNode(expression, (node) => {\n if (\n node.type === 'JSXElement' ||\n node.type === 'JSXFragment' ||\n (node.type === 'CallExpression' && isReactCreateElementCall(node))\n ) {\n found = true\n }\n })\n\n return found\n}\n\nfunction getComponentReferenceName(node: JSXElement): string | undefined {\n const name = getJsxName(node.openingElement.name)\n return name !== undefined && isComponentName(name) ? name : undefined\n}\n\nfunction getHookReferenceName(node: CallExpression): string | undefined {\n const calleeName = getIdentifierName(node.callee)\n return calleeName !== undefined && isHookName(calleeName)\n ? calleeName\n : undefined\n}\n\nfunction getCreateElementComponentReferenceName(\n node: CallExpression,\n): string | undefined {\n if (!isReactCreateElementCall(node)) {\n return undefined\n }\n\n const [firstArgument] = node.arguments\n if (firstArgument === undefined || firstArgument.type !== 'Identifier') {\n return undefined\n }\n\n return isComponentName(firstArgument.name) ? firstArgument.name : undefined\n}\n\nfunction isReactCreateElementCall(node: CallExpression): boolean {\n const callee = unwrapExpression(node.callee)\n if (callee.type !== 'MemberExpression' || callee.computed) {\n return false\n }\n\n return (\n callee.object.type === 'Identifier' &&\n callee.object.name === 'React' &&\n callee.property.name === 'createElement'\n )\n}\n\nfunction getJsxName(name: JSXElementName): string | undefined {\n if (name.type === 'JSXIdentifier') {\n return name.name\n }\n\n return undefined\n}\n\nfunction getIdentifierName(expression: Expression): string | undefined {\n const unwrapped = unwrapExpression(expression)\n return unwrapped.type === 'Identifier' ? unwrapped.name : undefined\n}\n\nfunction unwrapExpression(expression: Expression): Expression {\n let current = expression\n\n while (true) {\n if (\n current.type === 'ParenthesizedExpression' ||\n current.type === 'TSAsExpression' ||\n current.type === 'TSSatisfiesExpression' ||\n current.type === 'TSTypeAssertion' ||\n current.type === 'TSNonNullExpression'\n ) {\n current = current.expression\n continue\n }\n\n return current\n }\n}\n\nfunction walkReactUsageTree(\n root: FunctionBody | Expression | JSXFragment | JSXElement,\n visit: (node: Node) => void,\n): void {\n walkNode(root, visit, true)\n}\n\nfunction walkNode(\n node: Node,\n visit: (node: Node) => void,\n allowNestedFunctions = false,\n): void {\n visit(node)\n\n const keys = visitorKeys[node.type]\n if (keys === undefined) {\n return\n }\n\n keys.forEach((key) => {\n const value = (node as unknown as Record<string, unknown>)[key]\n walkChild(value, visit, allowNestedFunctions)\n })\n}\n\nfunction walkChild(\n value: unknown,\n visit: (node: Node) => void,\n allowNestedFunctions: boolean,\n): void {\n if (Array.isArray(value)) {\n value.forEach((entry) => {\n walkChild(entry, visit, allowNestedFunctions)\n })\n return\n }\n\n if (!isNode(value)) {\n return\n }\n\n if (!allowNestedFunctions && FUNCTION_NODE_TYPES.has(value.type)) {\n return\n }\n\n walkNode(value, visit, false)\n}\n\nfunction isNode(value: unknown): value is Node {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n typeof (value as { type: unknown }).type === 'string'\n )\n}\n\nfunction resolveReactReference(\n fileAnalysis: FileAnalysis,\n fileAnalyses: ReadonlyMap<string, FileAnalysis>,\n name: string,\n kind: ReactSymbolKind,\n): string | undefined {\n const localSymbol = fileAnalysis.symbolsByName.get(name)\n if (localSymbol !== undefined && localSymbol.kind === kind) {\n return localSymbol.id\n }\n\n const importBinding = fileAnalysis.importsByLocalName.get(name)\n if (importBinding === undefined) {\n return undefined\n }\n\n if (importBinding.sourcePath === undefined) {\n return kind === 'hook'\n ? getExternalHookNodeId(importBinding, name)\n : undefined\n }\n\n const sourceFileAnalysis = fileAnalyses.get(importBinding.sourcePath)\n if (sourceFileAnalysis === undefined) {\n return undefined\n }\n\n const targetId = sourceFileAnalysis.exportsByName.get(\n importBinding.importedName,\n )\n if (targetId === undefined) {\n return undefined\n }\n\n const targetSymbol = sourceFileAnalysis.symbolsById.get(targetId)\n return targetSymbol?.kind === kind ? targetId : undefined\n}\n\nfunction createExternalHookNode(\n binding: ImportBinding,\n localName: string,\n): ReactUsageNode {\n const name = getExternalHookName(binding, localName)\n\n return {\n id: getExternalHookNodeId(binding, localName),\n name,\n kind: 'hook',\n filePath: binding.sourceSpecifier,\n exportNames: [binding.importedName],\n usages: [],\n }\n}\n\nfunction getExternalHookNodeId(\n binding: ImportBinding,\n localName: string,\n): string {\n return `external:${binding.sourceSpecifier}#hook:${getExternalHookName(binding, localName)}`\n}\n\nfunction getExternalHookName(\n binding: ImportBinding,\n localName: string,\n): string {\n return binding.importedName === 'default' ? localName : binding.importedName\n}\n\nfunction getFilteredReactUsageNodes(\n graph: ReactUsageGraph,\n filter: ReactUsageFilter,\n): ReactUsageNode[] {\n return [...graph.nodes.values()]\n .filter((node) => matchesReactFilter(node, filter))\n .sort((left, right) => compareReactNodes(left, right))\n}\n\nfunction matchesReactFilter(\n node: ReactUsageNode,\n filter: ReactUsageFilter,\n): boolean {\n return filter === 'all' || node.kind === filter\n}\n\nfunction serializeReactUsageNode(\n nodeId: string,\n graph: ReactUsageGraph,\n filter: ReactUsageFilter,\n visited: Set<string>,\n): SerializedReactUsageNode {\n const node = graph.nodes.get(nodeId)\n if (node === undefined) {\n return {\n id: nodeId,\n name: nodeId,\n symbolKind: 'circular',\n filePath: '',\n exportNames: [],\n usages: [],\n }\n }\n\n if (visited.has(nodeId)) {\n return {\n id: node.id,\n name: node.name,\n symbolKind: 'circular',\n filePath: toDisplayPath(node.filePath, graph.cwd),\n exportNames: node.exportNames,\n usages: [],\n }\n }\n\n const nextVisited = new Set(visited)\n nextVisited.add(nodeId)\n\n return {\n id: node.id,\n name: node.name,\n symbolKind: node.kind,\n filePath: toDisplayPath(node.filePath, graph.cwd),\n exportNames: node.exportNames,\n usages: getFilteredUsages(node, graph, filter).map((usage) => ({\n kind: usage.kind,\n targetId: usage.target,\n node: serializeReactUsageNode(usage.target, graph, filter, nextVisited),\n })),\n }\n}\n\nfunction compareReactNodeIds(\n leftId: string,\n rightId: string,\n nodes: ReadonlyMap<string, ReactUsageNode>,\n): number {\n const left = nodes.get(leftId)\n const right = nodes.get(rightId)\n\n if (left === undefined || right === undefined) {\n return leftId.localeCompare(rightId)\n }\n\n return compareReactNodes(left, right)\n}\n\nfunction compareReactNodes(\n left: ReactUsageNode,\n right: ReactUsageNode,\n): number {\n return (\n left.filePath.localeCompare(right.filePath) ||\n left.name.localeCompare(right.name) ||\n left.kind.localeCompare(right.kind)\n )\n}\n\nfunction toModuleExportName(name: ModuleExportName): string {\n return name.type === 'Literal' ? name.value : name.name\n}\n\nfunction isHookName(name: string): boolean {\n return /^use[A-Z0-9]/.test(name)\n}\n\nfunction isComponentName(name: string): boolean {\n return /^[A-Z]/.test(name)\n}\n","import process from 'node:process'\n\nimport type { ColorMode, ReactSymbolKind } from './types.js'\n\nconst ANSI_RESET = '\\u001B[0m'\nconst ANSI_COMPONENT = '\\u001B[36m'\nconst ANSI_HOOK = '\\u001B[35m'\nconst ANSI_UNUSED = '\\u001B[38;5;214m'\n\ninterface ResolveColorSupportOptions {\n readonly forceColor?: string | undefined\n readonly isTTY?: boolean | undefined\n readonly noColor?: string | undefined\n}\n\nexport function resolveColorSupport(\n mode: ColorMode = 'auto',\n options: ResolveColorSupportOptions = {},\n): boolean {\n if (mode === true) {\n return true\n }\n\n if (mode === false) {\n return false\n }\n\n const forceColor =\n 'forceColor' in options ? options.forceColor : process.env.FORCE_COLOR\n if (forceColor !== undefined) {\n return forceColor !== '0'\n }\n\n const noColor = 'noColor' in options ? options.noColor : process.env.NO_COLOR\n if (noColor !== undefined) {\n return false\n }\n\n const isTTY = 'isTTY' in options ? options.isTTY : process.stdout.isTTY\n return isTTY === true\n}\n\nexport function colorizeUnusedMarker(text: string, enabled: boolean): string {\n if (!enabled) {\n return text\n }\n\n return text.replaceAll('(unused)', `${ANSI_UNUSED}(unused)${ANSI_RESET}`)\n}\n\nexport function formatReactSymbolLabel(\n name: string,\n kind: ReactSymbolKind,\n enabled: boolean,\n): string {\n const label = `${name} [${kind}]`\n if (!enabled) {\n return label\n }\n\n const color = kind === 'component' ? ANSI_COMPONENT : ANSI_HOOK\n return `${color}${label}${ANSI_RESET}`\n}\n","import { formatReactSymbolLabel, resolveColorSupport } from './color.js'\nimport { toDisplayPath } from './path-utils.js'\nimport { getFilteredUsages, getReactUsageRoots } from './react-analyzer.js'\nimport type {\n PrintReactTreeOptions,\n ReactUsageEdge,\n ReactUsageGraph,\n ReactUsageNode,\n} from './types.js'\n\nexport function printReactUsageTree(\n graph: ReactUsageGraph,\n options: PrintReactTreeOptions = {},\n): string {\n const cwd = options.cwd ?? graph.cwd\n const color = resolveColorSupport(options.color)\n const filter = options.filter ?? 'all'\n const roots = getReactUsageRoots(graph, filter)\n\n if (roots.length === 0) {\n return 'No React symbols found.'\n }\n\n const lines: string[] = []\n roots.forEach((rootId, index) => {\n const root = graph.nodes.get(rootId)\n if (root === undefined) {\n return\n }\n\n lines.push(formatReactNodeLabel(root, cwd, color))\n const usages = getFilteredUsages(root, graph, filter)\n usages.forEach((usage, usageIndex) => {\n lines.push(\n ...renderUsage(\n usage,\n graph,\n cwd,\n filter,\n color,\n new Set([root.id]),\n '',\n usageIndex === usages.length - 1,\n ),\n )\n })\n\n if (index < roots.length - 1) {\n lines.push('')\n }\n })\n\n return lines.join('\\n')\n}\n\nfunction renderUsage(\n usage: ReactUsageEdge,\n graph: ReactUsageGraph,\n cwd: string,\n filter: NonNullable<PrintReactTreeOptions['filter']>,\n color: boolean,\n visited: ReadonlySet<string>,\n prefix: string,\n isLast: boolean,\n): string[] {\n const branch = `${prefix}${isLast ? '└─ ' : '├─ '}`\n const target = graph.nodes.get(usage.target)\n\n if (target === undefined) {\n return [`${branch}${usage.target}`]\n }\n\n if (visited.has(target.id)) {\n return [`${branch}${formatReactNodeLabel(target, cwd, color)} (circular)`]\n }\n\n const childLines = [`${branch}${formatReactNodeLabel(target, cwd, color)}`]\n const nextVisited = new Set(visited)\n nextVisited.add(target.id)\n const nextPrefix = `${prefix}${isLast ? ' ' : '│ '}`\n const childUsages = getFilteredUsages(target, graph, filter)\n\n childUsages.forEach((childUsage, index) => {\n childLines.push(\n ...renderUsage(\n childUsage,\n graph,\n cwd,\n filter,\n color,\n nextVisited,\n nextPrefix,\n index === childUsages.length - 1,\n ),\n )\n })\n\n return childLines\n}\n\nfunction formatReactNodeLabel(\n node: ReactUsageNode,\n cwd: string,\n color: boolean,\n): string {\n return `${formatReactSymbolLabel(node.name, node.kind, color)} (${toDisplayPath(node.filePath, cwd)})`\n}\n","import { colorizeUnusedMarker, resolveColorSupport } from './color.js'\nimport { toDisplayPath } from './path-utils.js'\nimport type {\n DependencyEdge,\n DependencyGraph,\n PrintTreeOptions,\n} from './types.js'\n\nexport function printDependencyTree(\n graph: DependencyGraph,\n options: PrintTreeOptions = {},\n): string {\n const cwd = options.cwd ?? graph.cwd\n const color = resolveColorSupport(options.color)\n const includeExternals = options.includeExternals ?? false\n const omitUnused = options.omitUnused ?? false\n const rootLines = [toDisplayPath(graph.entryId, cwd)]\n const visited = new Set<string>([graph.entryId])\n const entryNode = graph.nodes.get(graph.entryId)\n\n if (entryNode === undefined) {\n return rootLines.join('\\n')\n }\n\n const rootDependencies = filterDependencies(\n entryNode.dependencies,\n includeExternals,\n omitUnused,\n )\n\n rootDependencies.forEach((dependency, index) => {\n const isLast = index === rootDependencies.length - 1\n const lines = renderDependency(\n dependency,\n graph,\n visited,\n '',\n isLast,\n includeExternals,\n omitUnused,\n color,\n cwd,\n )\n rootLines.push(...lines)\n })\n\n return rootLines.join('\\n')\n}\n\nfunction renderDependency(\n dependency: DependencyEdge,\n graph: DependencyGraph,\n visited: ReadonlySet<string>,\n prefix: string,\n isLast: boolean,\n includeExternals: boolean,\n omitUnused: boolean,\n color: boolean,\n cwd: string,\n): string[] {\n const branch = `${prefix}${isLast ? '└─ ' : '├─ '}`\n const label = formatDependencyLabel(dependency, cwd, color)\n\n if (dependency.kind !== 'source') {\n return [`${branch}${label}`]\n }\n\n if (visited.has(dependency.target)) {\n return [`${branch}${label} (circular)`]\n }\n\n const childNode = graph.nodes.get(dependency.target)\n if (childNode === undefined) {\n return [`${branch}${label}`]\n }\n\n const nextPrefix = `${prefix}${isLast ? ' ' : '│ '}`\n const nextVisited = new Set(visited)\n nextVisited.add(dependency.target)\n\n const childLines = [`${branch}${label}`]\n const childDependencies = filterDependencies(\n childNode.dependencies,\n includeExternals,\n omitUnused,\n )\n\n childDependencies.forEach((childDependency, index) => {\n const isChildLast = index === childDependencies.length - 1\n childLines.push(\n ...renderDependency(\n childDependency,\n graph,\n nextVisited,\n nextPrefix,\n isChildLast,\n includeExternals,\n omitUnused,\n color,\n cwd,\n ),\n )\n })\n\n return childLines\n}\n\nfunction filterDependencies(\n dependencies: readonly DependencyEdge[],\n includeExternals: boolean,\n omitUnused: boolean,\n): DependencyEdge[] {\n return dependencies.filter((dependency) => {\n if (omitUnused && dependency.unused) {\n return false\n }\n\n if (dependency.kind === 'source' || dependency.kind === 'missing') {\n return true\n }\n\n return includeExternals\n })\n}\n\nfunction formatDependencyLabel(\n dependency: DependencyEdge,\n cwd: string,\n color: boolean,\n): string {\n const prefixes: string[] = []\n if (dependency.isTypeOnly) {\n prefixes.push('type')\n }\n\n if (dependency.referenceKind === 'require') {\n prefixes.push('require')\n } else if (dependency.referenceKind === 'dynamic-import') {\n prefixes.push('dynamic')\n } else if (dependency.referenceKind === 'export') {\n prefixes.push('re-export')\n } else if (dependency.referenceKind === 'import-equals') {\n prefixes.push('import=')\n }\n\n const annotation = prefixes.length > 0 ? `[${prefixes.join(', ')}] ` : ''\n\n if (dependency.kind === 'source') {\n return colorizeUnusedMarker(\n withUnusedSuffix(\n `${annotation}${toDisplayPath(dependency.target, cwd)}`,\n dependency.unused,\n ),\n color,\n )\n }\n\n if (dependency.kind === 'missing') {\n return colorizeUnusedMarker(\n withUnusedSuffix(\n `${annotation}${dependency.specifier} [missing]`,\n dependency.unused,\n ),\n color,\n )\n }\n\n if (dependency.kind === 'builtin') {\n return colorizeUnusedMarker(\n withUnusedSuffix(\n `${annotation}${dependency.target} [builtin]`,\n dependency.unused,\n ),\n color,\n )\n }\n\n return colorizeUnusedMarker(\n withUnusedSuffix(\n `${annotation}${dependency.target} [external]`,\n dependency.unused,\n ),\n color,\n )\n}\n\nfunction withUnusedSuffix(label: string, unused: boolean): string {\n return unused ? `${label} (unused)` : label\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tree-Cp8CNmeY.mjs","names":[],"sources":["../src/config.ts","../src/path-utils.ts","../src/analyzer.ts","../src/react-analyzer.ts","../src/react-tree.ts","../src/tree.ts"],"sourcesContent":["import path from 'node:path'\nimport ts from 'typescript'\n\nexport interface LoadedConfig {\n readonly path?: string\n readonly compilerOptions: ts.CompilerOptions\n}\n\nexport function loadCompilerOptions(\n searchFrom: string,\n explicitConfigPath?: string,\n): LoadedConfig {\n const configPath =\n explicitConfigPath === undefined\n ? findNearestConfig(searchFrom)\n : path.resolve(searchFrom, explicitConfigPath)\n\n if (configPath === undefined) {\n return {\n compilerOptions: defaultCompilerOptions(),\n }\n }\n\n const readResult = ts.readConfigFile(configPath, ts.sys.readFile)\n if (readResult.error !== undefined) {\n throw new Error(\n `Failed to read TypeScript config at ${configPath}: ${formatDiagnostic(\n readResult.error,\n )}`,\n )\n }\n\n const parsed = ts.parseJsonConfigFileContent(\n readResult.config,\n ts.sys,\n path.dirname(configPath),\n defaultCompilerOptions(),\n configPath,\n )\n\n if (parsed.errors.length > 0) {\n const [firstError] = parsed.errors\n if (firstError === undefined) {\n throw new Error(`Failed to parse TypeScript config at ${configPath}.`)\n }\n\n throw new Error(\n `Failed to parse TypeScript config at ${configPath}: ${formatDiagnostic(\n firstError,\n )}`,\n )\n }\n\n return {\n path: configPath,\n compilerOptions: parsed.options,\n }\n}\n\nfunction findNearestConfig(searchFrom: string): string | undefined {\n let currentDirectory = path.resolve(searchFrom)\n\n while (true) {\n const tsconfigPath = path.join(currentDirectory, 'tsconfig.json')\n if (ts.sys.fileExists(tsconfigPath)) {\n return tsconfigPath\n }\n\n const jsconfigPath = path.join(currentDirectory, 'jsconfig.json')\n if (ts.sys.fileExists(jsconfigPath)) {\n return jsconfigPath\n }\n\n const parentDirectory = path.dirname(currentDirectory)\n if (parentDirectory === currentDirectory) {\n return undefined\n }\n\n currentDirectory = parentDirectory\n }\n}\n\nfunction defaultCompilerOptions(): ts.CompilerOptions {\n return {\n allowJs: true,\n jsx: ts.JsxEmit.ReactJSX,\n module: ts.ModuleKind.NodeNext,\n moduleResolution: ts.ModuleResolutionKind.NodeNext,\n target: ts.ScriptTarget.ESNext,\n resolveJsonModule: true,\n esModuleInterop: true,\n }\n}\n\nfunction formatDiagnostic(diagnostic: ts.Diagnostic): string {\n return ts.flattenDiagnosticMessageText(diagnostic.messageText, '\\n')\n}\n","import path from 'node:path'\n\nexport const SOURCE_EXTENSIONS = new Set([\n '.js',\n '.jsx',\n '.ts',\n '.tsx',\n '.mjs',\n '.cjs',\n '.mts',\n '.cts',\n])\n\nexport function normalizeFilePath(filePath: string): string {\n return path.normalize(filePath)\n}\n\nexport function toDisplayPath(filePath: string, cwd: string): string {\n const relativePath = path.relative(cwd, filePath)\n if (relativePath === '') {\n return '.'\n }\n\n const normalizedPath = relativePath.split(path.sep).join('/')\n return normalizedPath.startsWith('..') ? filePath : normalizedPath\n}\n\nexport function isSourceCodeFile(filePath: string): boolean {\n return SOURCE_EXTENSIONS.has(path.extname(filePath).toLowerCase())\n}\n","import fs from 'node:fs'\nimport { builtinModules } from 'node:module'\nimport path from 'node:path'\nimport ts from 'typescript'\n\nimport { loadCompilerOptions } from './config.js'\nimport {\n isSourceCodeFile,\n normalizeFilePath,\n toDisplayPath,\n} from './path-utils.js'\nimport type {\n AnalyzeOptions,\n DependencyEdge,\n DependencyGraph,\n DependencyKind,\n ReferenceKind,\n SourceModuleNode,\n} from './types.js'\n\ninterface ModuleReference {\n readonly specifier: string\n readonly referenceKind: ReferenceKind\n readonly isTypeOnly: boolean\n}\n\nconst BUILTIN_MODULES = new Set(\n builtinModules.flatMap((name) => [name, `node:${name}`]),\n)\n\nexport function analyzeDependencies(\n entryFile: string,\n options: AnalyzeOptions = {},\n): DependencyGraph {\n const cwd = path.resolve(options.cwd ?? process.cwd())\n const resolvedEntryPath = resolveExistingPath(cwd, entryFile)\n const { compilerOptions, path: configPath } = loadCompilerOptions(\n path.dirname(resolvedEntryPath),\n options.configPath,\n )\n\n const host: ts.ModuleResolutionHost = {\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n directoryExists: ts.sys.directoryExists,\n getCurrentDirectory: () => cwd,\n getDirectories: ts.sys.getDirectories,\n ...(ts.sys.realpath === undefined ? {} : { realpath: ts.sys.realpath }),\n }\n\n const nodes = new Map<string, SourceModuleNode>()\n visitFile(resolvedEntryPath, compilerOptions, host, nodes)\n\n return {\n cwd,\n entryId: resolvedEntryPath,\n nodes,\n ...(configPath === undefined ? {} : { configPath }),\n }\n}\n\nexport function graphToSerializableTree(graph: DependencyGraph): object {\n const visited = new Set<string>()\n return serializeNode(graph.entryId, graph, visited)\n}\n\nfunction serializeNode(\n filePath: string,\n graph: DependencyGraph,\n visited: Set<string>,\n): object {\n const node = graph.nodes.get(filePath)\n const displayPath = toDisplayPath(filePath, graph.cwd)\n\n if (node === undefined) {\n return {\n path: displayPath,\n kind: 'missing',\n dependencies: [],\n }\n }\n\n if (visited.has(filePath)) {\n return {\n path: displayPath,\n kind: 'circular',\n dependencies: [],\n }\n }\n\n visited.add(filePath)\n\n const dependencies = node.dependencies.map((dependency) => {\n if (dependency.kind !== 'source') {\n return {\n specifier: dependency.specifier,\n referenceKind: dependency.referenceKind,\n isTypeOnly: dependency.isTypeOnly,\n kind: dependency.kind,\n target:\n dependency.kind === 'missing'\n ? dependency.target\n : toDisplayPath(dependency.target, graph.cwd),\n }\n }\n\n return {\n specifier: dependency.specifier,\n referenceKind: dependency.referenceKind,\n isTypeOnly: dependency.isTypeOnly,\n kind: dependency.kind,\n target: toDisplayPath(dependency.target, graph.cwd),\n node: serializeNode(dependency.target, graph, new Set(visited)),\n }\n })\n\n return {\n path: displayPath,\n kind: filePath === graph.entryId ? 'entry' : 'source',\n dependencies,\n }\n}\n\nfunction visitFile(\n filePath: string,\n compilerOptions: ts.CompilerOptions,\n host: ts.ModuleResolutionHost,\n nodes: Map<string, SourceModuleNode>,\n): void {\n const normalizedPath = normalizeFilePath(filePath)\n if (nodes.has(normalizedPath)) {\n return\n }\n\n const sourceText = fs.readFileSync(normalizedPath, 'utf8')\n const sourceFile = ts.createSourceFile(\n normalizedPath,\n sourceText,\n ts.ScriptTarget.Latest,\n true,\n getScriptKind(normalizedPath),\n )\n\n const references = collectModuleReferences(sourceFile)\n const dependencies = references.map((reference) =>\n resolveDependency(reference, normalizedPath, compilerOptions, host),\n )\n\n nodes.set(normalizedPath, {\n id: normalizedPath,\n dependencies,\n })\n\n for (const dependency of dependencies) {\n if (dependency.kind === 'source') {\n visitFile(dependency.target, compilerOptions, host, nodes)\n }\n }\n}\n\nfunction collectModuleReferences(sourceFile: ts.SourceFile): ModuleReference[] {\n const references: ModuleReference[] = []\n const seen = new Set<string>()\n\n function addReference(\n specifier: string,\n referenceKind: ReferenceKind,\n isTypeOnly: boolean,\n ): void {\n const key = `${referenceKind}:${isTypeOnly ? 'type' : 'value'}:${specifier}`\n if (seen.has(key)) {\n return\n }\n\n seen.add(key)\n references.push({\n specifier,\n referenceKind,\n isTypeOnly,\n })\n }\n\n function visit(node: ts.Node): void {\n if (\n ts.isImportDeclaration(node) &&\n ts.isStringLiteralLike(node.moduleSpecifier)\n ) {\n addReference(\n node.moduleSpecifier.text,\n 'import',\n node.importClause?.isTypeOnly ?? false,\n )\n } else if (\n ts.isExportDeclaration(node) &&\n node.moduleSpecifier !== undefined &&\n ts.isStringLiteralLike(node.moduleSpecifier)\n ) {\n addReference(\n node.moduleSpecifier.text,\n 'export',\n node.isTypeOnly ?? false,\n )\n } else if (ts.isImportEqualsDeclaration(node)) {\n const moduleReference = node.moduleReference\n if (\n ts.isExternalModuleReference(moduleReference) &&\n moduleReference.expression !== undefined &&\n ts.isStringLiteralLike(moduleReference.expression)\n ) {\n addReference(moduleReference.expression.text, 'import-equals', false)\n }\n } else if (ts.isCallExpression(node)) {\n if (\n node.expression.kind === ts.SyntaxKind.ImportKeyword &&\n node.arguments.length === 1\n ) {\n const [argument] = node.arguments\n if (argument !== undefined && ts.isStringLiteralLike(argument)) {\n addReference(argument.text, 'dynamic-import', false)\n }\n }\n\n if (\n ts.isIdentifier(node.expression) &&\n node.expression.text === 'require' &&\n node.arguments.length === 1\n ) {\n const [argument] = node.arguments\n if (argument !== undefined && ts.isStringLiteralLike(argument)) {\n addReference(argument.text, 'require', false)\n }\n }\n }\n\n ts.forEachChild(node, visit)\n }\n\n visit(sourceFile)\n return references\n}\n\nfunction resolveDependency(\n reference: ModuleReference,\n containingFile: string,\n compilerOptions: ts.CompilerOptions,\n host: ts.ModuleResolutionHost,\n): DependencyEdge {\n const specifier = reference.specifier\n if (BUILTIN_MODULES.has(specifier)) {\n return createEdge(reference, 'builtin', specifier)\n }\n\n const resolution = ts.resolveModuleName(\n specifier,\n containingFile,\n compilerOptions,\n host,\n ).resolvedModule\n\n if (resolution !== undefined) {\n const resolvedPath = normalizeFilePath(resolution.resolvedFileName)\n if (\n resolution.isExternalLibraryImport ||\n resolvedPath.includes(`${path.sep}node_modules${path.sep}`)\n ) {\n return createEdge(reference, 'external', specifier)\n }\n\n if (isSourceCodeFile(resolvedPath) && !resolvedPath.endsWith('.d.ts')) {\n return createEdge(reference, 'source', resolvedPath)\n }\n }\n\n if (!specifier.startsWith('.') && !path.isAbsolute(specifier)) {\n return createEdge(reference, 'external', specifier)\n }\n\n return createEdge(reference, 'missing', specifier)\n}\n\nfunction createEdge(\n reference: ModuleReference,\n kind: DependencyKind,\n target: string,\n): DependencyEdge {\n return {\n specifier: reference.specifier,\n referenceKind: reference.referenceKind,\n isTypeOnly: reference.isTypeOnly,\n kind,\n target,\n }\n}\n\nfunction getScriptKind(filePath: string): ts.ScriptKind {\n switch (path.extname(filePath).toLowerCase()) {\n case '.js':\n case '.mjs':\n case '.cjs':\n return ts.ScriptKind.JS\n case '.jsx':\n return ts.ScriptKind.JSX\n case '.tsx':\n return ts.ScriptKind.TSX\n case '.json':\n return ts.ScriptKind.JSON\n default:\n return ts.ScriptKind.TS\n }\n}\n\nfunction resolveExistingPath(cwd: string, entryFile: string): string {\n const absolutePath = path.resolve(cwd, entryFile)\n const normalizedPath = normalizeFilePath(absolutePath)\n\n if (!fs.existsSync(normalizedPath)) {\n throw new Error(`Entry file not found: ${entryFile}`)\n }\n\n if (!isSourceCodeFile(normalizedPath)) {\n throw new Error(`Entry file must be a JS/TS source file: ${entryFile}`)\n }\n\n return normalizedPath\n}\n","import fs from 'node:fs'\nimport type {\n ArrowFunctionExpression,\n CallExpression,\n ExportDefaultDeclaration,\n ExportNamedDeclaration,\n Expression,\n FunctionBody,\n ImportDeclaration,\n ImportDeclarationSpecifier,\n JSXElement,\n JSXElementName,\n JSXFragment,\n ModuleExportName,\n Node,\n Function as OxcFunction,\n Program,\n Statement,\n VariableDeclarator,\n} from 'oxc-parser'\nimport { parseSync, visitorKeys } from 'oxc-parser'\n\nimport { analyzeDependencies } from './analyzer.js'\nimport { isSourceCodeFile, toDisplayPath } from './path-utils.js'\nimport type {\n AnalyzeOptions,\n ReactSymbolKind,\n ReactUsageEdge,\n ReactUsageFilter,\n ReactUsageGraph,\n ReactUsageNode,\n} from './types.js'\n\ninterface PendingReactUsageNode {\n readonly id: string\n readonly name: string\n readonly kind: ReactSymbolKind\n readonly filePath: string\n readonly declaration: OxcFunction | ArrowFunctionExpression\n readonly exportNames: Set<string>\n readonly componentReferences: Set<string>\n readonly hookReferences: Set<string>\n}\n\ninterface ImportBinding {\n readonly importedName: string\n readonly sourceSpecifier: string\n readonly sourcePath?: string\n}\n\ninterface FileAnalysis {\n readonly filePath: string\n readonly importsByLocalName: Map<string, ImportBinding>\n readonly exportsByName: Map<string, string>\n readonly symbolsById: Map<string, PendingReactUsageNode>\n readonly symbolsByName: Map<string, PendingReactUsageNode>\n}\n\ninterface SerializedReactUsageNode {\n readonly id: string\n readonly name: string\n readonly symbolKind: ReactSymbolKind | 'circular'\n readonly filePath: string\n readonly exportNames: readonly string[]\n readonly usages: readonly SerializedReactUsageEdge[]\n}\n\ninterface SerializedReactUsageEdge {\n readonly kind: ReactUsageEdge['kind']\n readonly targetId: string\n readonly node: SerializedReactUsageNode\n}\n\nconst FUNCTION_NODE_TYPES = new Set([\n 'FunctionDeclaration',\n 'FunctionExpression',\n 'ArrowFunctionExpression',\n 'TSDeclareFunction',\n 'TSEmptyBodyFunctionExpression',\n])\n\nexport function analyzeReactUsage(\n entryFile: string,\n options: AnalyzeOptions = {},\n): ReactUsageGraph {\n const dependencyGraph = analyzeDependencies(entryFile, options)\n const reachableFiles = new Set<string>([\n dependencyGraph.entryId,\n ...dependencyGraph.nodes.keys(),\n ])\n const fileAnalyses = new Map<string, FileAnalysis>()\n\n for (const filePath of [...reachableFiles].sort()) {\n if (!isSourceCodeFile(filePath) || filePath.endsWith('.d.ts')) {\n continue\n }\n\n const sourceText = fs.readFileSync(filePath, 'utf8')\n const parseResult = parseSync(filePath, sourceText, {\n astType: 'ts',\n sourceType: 'unambiguous',\n })\n\n const dependencyNode = dependencyGraph.nodes.get(filePath)\n const sourceDependencies = new Map<string, string>()\n dependencyNode?.dependencies.forEach((dependency) => {\n if (dependency.kind === 'source') {\n sourceDependencies.set(dependency.specifier, dependency.target)\n }\n })\n\n fileAnalyses.set(\n filePath,\n analyzeReactFile(parseResult.program, filePath, sourceDependencies),\n )\n }\n\n const nodes = new Map<string, ReactUsageNode>()\n for (const fileAnalysis of fileAnalyses.values()) {\n for (const symbol of fileAnalysis.symbolsById.values()) {\n nodes.set(symbol.id, {\n id: symbol.id,\n name: symbol.name,\n kind: symbol.kind,\n filePath: symbol.filePath,\n exportNames: [...symbol.exportNames].sort(),\n usages: [],\n })\n }\n }\n\n for (const fileAnalysis of fileAnalyses.values()) {\n fileAnalysis.importsByLocalName.forEach((binding, localName) => {\n if (binding.sourcePath !== undefined) {\n return\n }\n\n if (!isHookName(localName) && !isHookName(binding.importedName)) {\n return\n }\n\n const externalNode = createExternalHookNode(binding, localName)\n if (!nodes.has(externalNode.id)) {\n nodes.set(externalNode.id, externalNode)\n }\n })\n }\n\n for (const fileAnalysis of fileAnalyses.values()) {\n for (const symbol of fileAnalysis.symbolsById.values()) {\n const usages = new Map<string, ReactUsageEdge>()\n\n symbol.componentReferences.forEach((referenceName) => {\n const targetId = resolveReactReference(\n fileAnalysis,\n fileAnalyses,\n referenceName,\n 'component',\n )\n if (targetId !== undefined && targetId !== symbol.id) {\n usages.set(`render:${targetId}`, {\n kind: 'render',\n target: targetId,\n })\n }\n })\n\n symbol.hookReferences.forEach((referenceName) => {\n const targetId = resolveReactReference(\n fileAnalysis,\n fileAnalyses,\n referenceName,\n 'hook',\n )\n if (targetId !== undefined && targetId !== symbol.id) {\n usages.set(`hook:${targetId}`, {\n kind: 'hook-call',\n target: targetId,\n })\n }\n })\n\n const node = nodes.get(symbol.id)\n if (node === undefined) {\n continue\n }\n\n const sortedUsages = [...usages.values()].sort((left, right) =>\n compareReactNodeIds(left.target, right.target, nodes),\n )\n\n nodes.set(symbol.id, {\n ...node,\n usages: sortedUsages,\n })\n }\n }\n\n return {\n cwd: dependencyGraph.cwd,\n entryId: dependencyGraph.entryId,\n nodes,\n }\n}\n\nexport function graphToSerializableReactTree(\n graph: ReactUsageGraph,\n options: {\n readonly filter?: ReactUsageFilter\n } = {},\n): object {\n const roots = getReactUsageRoots(graph, options.filter)\n\n return {\n kind: 'react-usage',\n roots: roots.map((rootId) =>\n serializeReactUsageNode(\n rootId,\n graph,\n options.filter ?? 'all',\n new Set(),\n ),\n ),\n }\n}\n\nexport function getReactUsageRoots(\n graph: ReactUsageGraph,\n filter: ReactUsageFilter = 'all',\n): string[] {\n const filteredNodes = getFilteredReactUsageNodes(graph, filter)\n const inboundCounts = new Map<string, number>()\n\n filteredNodes.forEach((node) => {\n inboundCounts.set(node.id, 0)\n })\n\n filteredNodes.forEach((node) => {\n getFilteredUsages(node, graph, filter).forEach((usage) => {\n inboundCounts.set(\n usage.target,\n (inboundCounts.get(usage.target) ?? 0) + 1,\n )\n })\n })\n\n const roots = filteredNodes\n .filter((node) => (inboundCounts.get(node.id) ?? 0) === 0)\n .map((node) => node.id)\n\n if (roots.length > 0) {\n return roots.sort((left, right) =>\n compareReactNodeIds(left, right, graph.nodes),\n )\n }\n\n return filteredNodes\n .map((node) => node.id)\n .sort((left, right) => compareReactNodeIds(left, right, graph.nodes))\n}\n\nexport function getFilteredUsages(\n node: ReactUsageNode,\n graph: ReactUsageGraph,\n filter: ReactUsageFilter = 'all',\n): ReactUsageEdge[] {\n return node.usages.filter((usage) => {\n const targetNode = graph.nodes.get(usage.target)\n return targetNode !== undefined && matchesReactFilter(targetNode, filter)\n })\n}\n\nfunction analyzeReactFile(\n program: Program,\n filePath: string,\n sourceDependencies: ReadonlyMap<string, string>,\n): FileAnalysis {\n const symbolsByName = new Map<string, PendingReactUsageNode>()\n\n program.body.forEach((statement) => {\n collectTopLevelReactSymbols(statement, filePath, symbolsByName)\n })\n\n const importsByLocalName = new Map<string, ImportBinding>()\n const exportsByName = new Map<string, string>()\n\n program.body.forEach((statement) => {\n collectImportsAndExports(\n statement,\n sourceDependencies,\n symbolsByName,\n importsByLocalName,\n exportsByName,\n )\n })\n\n symbolsByName.forEach((symbol) => {\n analyzeSymbolUsages(symbol)\n })\n\n return {\n filePath,\n importsByLocalName,\n exportsByName,\n symbolsById: new Map(\n [...symbolsByName.values()].map((symbol) => [symbol.id, symbol]),\n ),\n symbolsByName,\n }\n}\n\nfunction collectTopLevelReactSymbols(\n statement: Statement,\n filePath: string,\n symbolsByName: Map<string, PendingReactUsageNode>,\n): void {\n switch (statement.type) {\n case 'FunctionDeclaration':\n addFunctionSymbol(statement, filePath, symbolsByName)\n return\n case 'VariableDeclaration':\n statement.declarations.forEach((declarator) => {\n addVariableSymbol(declarator, filePath, symbolsByName)\n })\n return\n case 'ExportNamedDeclaration':\n if (statement.declaration !== null) {\n collectTopLevelReactSymbols(\n statement.declaration,\n filePath,\n symbolsByName,\n )\n }\n return\n case 'ExportDefaultDeclaration':\n addDefaultExportSymbol(statement, filePath, symbolsByName)\n return\n default:\n return\n }\n}\n\nfunction addFunctionSymbol(\n declaration: OxcFunction,\n filePath: string,\n symbolsByName: Map<string, PendingReactUsageNode>,\n): void {\n const name = declaration.id?.name\n if (name === undefined) {\n return\n }\n\n const kind = classifyReactSymbol(name, declaration)\n if (kind === undefined) {\n return\n }\n\n symbolsByName.set(\n name,\n createPendingSymbol(filePath, name, kind, declaration),\n )\n}\n\nfunction addVariableSymbol(\n declarator: VariableDeclarator,\n filePath: string,\n symbolsByName: Map<string, PendingReactUsageNode>,\n): void {\n if (declarator.id.type !== 'Identifier' || declarator.init === null) {\n return\n }\n\n if (\n declarator.init.type !== 'ArrowFunctionExpression' &&\n declarator.init.type !== 'FunctionExpression'\n ) {\n return\n }\n\n const name = declarator.id.name\n const kind = classifyReactSymbol(name, declarator.init)\n if (kind === undefined) {\n return\n }\n\n symbolsByName.set(\n name,\n createPendingSymbol(filePath, name, kind, declarator.init),\n )\n}\n\nfunction addDefaultExportSymbol(\n declaration: ExportDefaultDeclaration,\n filePath: string,\n symbolsByName: Map<string, PendingReactUsageNode>,\n): void {\n if (\n declaration.declaration.type === 'FunctionDeclaration' ||\n declaration.declaration.type === 'FunctionExpression'\n ) {\n addFunctionSymbol(declaration.declaration, filePath, symbolsByName)\n } else if (declaration.declaration.type === 'ArrowFunctionExpression') {\n const name = 'default'\n const kind = declaration.declaration.body\n ? classifyReactSymbol(name, declaration.declaration)\n : undefined\n if (kind !== undefined) {\n symbolsByName.set(\n name,\n createPendingSymbol(filePath, name, kind, declaration.declaration),\n )\n }\n }\n}\n\nfunction createPendingSymbol(\n filePath: string,\n name: string,\n kind: ReactSymbolKind,\n declaration: OxcFunction | ArrowFunctionExpression,\n): PendingReactUsageNode {\n return {\n id: `${filePath}#${kind}:${name}`,\n name,\n kind,\n filePath,\n declaration,\n exportNames: new Set<string>(),\n componentReferences: new Set<string>(),\n hookReferences: new Set<string>(),\n }\n}\n\nfunction collectImportsAndExports(\n statement: Statement,\n sourceDependencies: ReadonlyMap<string, string>,\n symbolsByName: ReadonlyMap<string, PendingReactUsageNode>,\n importsByLocalName: Map<string, ImportBinding>,\n exportsByName: Map<string, string>,\n): void {\n switch (statement.type) {\n case 'ImportDeclaration':\n collectImportBindings(statement, sourceDependencies, importsByLocalName)\n return\n case 'ExportNamedDeclaration':\n collectNamedExports(statement, symbolsByName, exportsByName)\n return\n case 'ExportDefaultDeclaration':\n collectDefaultExport(statement, symbolsByName, exportsByName)\n return\n default:\n return\n }\n}\n\nfunction collectImportBindings(\n declaration: ImportDeclaration,\n sourceDependencies: ReadonlyMap<string, string>,\n importsByLocalName: Map<string, ImportBinding>,\n): void {\n if (declaration.importKind === 'type') {\n return\n }\n\n const sourceSpecifier = declaration.source.value\n const sourcePath = sourceDependencies.get(declaration.source.value)\n\n declaration.specifiers.forEach((specifier) => {\n const binding = getImportBinding(specifier, sourceSpecifier, sourcePath)\n if (binding === undefined) {\n return\n }\n\n importsByLocalName.set(binding.localName, {\n importedName: binding.importedName,\n sourceSpecifier: binding.sourceSpecifier,\n ...(binding.sourcePath === undefined\n ? {}\n : { sourcePath: binding.sourcePath }),\n })\n })\n}\n\nfunction getImportBinding(\n specifier: ImportDeclarationSpecifier,\n sourceSpecifier: string,\n sourcePath: string | undefined,\n):\n | {\n readonly localName: string\n readonly importedName: string\n readonly sourceSpecifier: string\n readonly sourcePath?: string\n }\n | undefined {\n if (specifier.type === 'ImportSpecifier') {\n if (specifier.importKind === 'type') {\n return undefined\n }\n\n return {\n localName: specifier.local.name,\n importedName: toModuleExportName(specifier.imported),\n sourceSpecifier,\n ...(sourcePath === undefined ? {} : { sourcePath }),\n }\n }\n\n if (specifier.type === 'ImportDefaultSpecifier') {\n return {\n localName: specifier.local.name,\n importedName: 'default',\n sourceSpecifier,\n ...(sourcePath === undefined ? {} : { sourcePath }),\n }\n }\n\n return undefined\n}\n\nfunction collectNamedExports(\n declaration: ExportNamedDeclaration,\n symbolsByName: ReadonlyMap<string, PendingReactUsageNode>,\n exportsByName: Map<string, string>,\n): void {\n if (declaration.exportKind === 'type') {\n return\n }\n\n if (declaration.declaration !== null) {\n if (declaration.declaration.type === 'FunctionDeclaration') {\n const name = declaration.declaration.id?.name\n if (name !== undefined) {\n addExportBinding(name, name, symbolsByName, exportsByName)\n }\n } else if (declaration.declaration.type === 'VariableDeclaration') {\n declaration.declaration.declarations.forEach((declarator) => {\n if (declarator.id.type === 'Identifier') {\n addExportBinding(\n declarator.id.name,\n declarator.id.name,\n symbolsByName,\n exportsByName,\n )\n }\n })\n }\n\n return\n }\n\n if (declaration.source !== null) {\n return\n }\n\n declaration.specifiers.forEach((specifier) => {\n if (specifier.exportKind === 'type') {\n return\n }\n\n const localName = toModuleExportName(specifier.local)\n const exportedName = toModuleExportName(specifier.exported)\n addExportBinding(localName, exportedName, symbolsByName, exportsByName)\n })\n}\n\nfunction collectDefaultExport(\n declaration: ExportDefaultDeclaration,\n symbolsByName: ReadonlyMap<string, PendingReactUsageNode>,\n exportsByName: Map<string, string>,\n): void {\n if (\n declaration.declaration.type === 'FunctionDeclaration' ||\n declaration.declaration.type === 'FunctionExpression'\n ) {\n const localName = declaration.declaration.id?.name\n if (localName !== undefined) {\n addExportBinding(localName, 'default', symbolsByName, exportsByName)\n }\n return\n }\n\n if (declaration.declaration.type === 'Identifier') {\n addExportBinding(\n declaration.declaration.name,\n 'default',\n symbolsByName,\n exportsByName,\n )\n return\n }\n\n if (declaration.declaration.type === 'ArrowFunctionExpression') {\n addExportBinding('default', 'default', symbolsByName, exportsByName)\n }\n}\n\nfunction addExportBinding(\n localName: string,\n exportedName: string,\n symbolsByName: ReadonlyMap<string, PendingReactUsageNode>,\n exportsByName: Map<string, string>,\n): void {\n const symbol = symbolsByName.get(localName)\n if (symbol === undefined) {\n return\n }\n\n symbol.exportNames.add(exportedName)\n exportsByName.set(exportedName, symbol.id)\n}\n\nfunction analyzeSymbolUsages(symbol: PendingReactUsageNode): void {\n const root =\n symbol.declaration.type === 'ArrowFunctionExpression'\n ? symbol.declaration.body\n : symbol.declaration.body\n\n if (root === null) {\n return\n }\n\n walkReactUsageTree(root, (node) => {\n if (node.type === 'JSXElement') {\n const name = getComponentReferenceName(node)\n if (name !== undefined) {\n symbol.componentReferences.add(name)\n }\n return\n }\n\n if (node.type === 'CallExpression') {\n const hookReference = getHookReferenceName(node)\n if (hookReference !== undefined) {\n symbol.hookReferences.add(hookReference)\n }\n\n const componentReference = getCreateElementComponentReferenceName(node)\n if (componentReference !== undefined) {\n symbol.componentReferences.add(componentReference)\n }\n }\n })\n}\n\nfunction classifyReactSymbol(\n name: string,\n declaration: OxcFunction | ArrowFunctionExpression,\n): ReactSymbolKind | undefined {\n if (isHookName(name)) {\n return 'hook'\n }\n\n if (isComponentName(name) && returnsReactElement(declaration)) {\n return 'component'\n }\n\n return undefined\n}\n\nfunction returnsReactElement(\n declaration: OxcFunction | ArrowFunctionExpression,\n): boolean {\n if (\n declaration.type === 'ArrowFunctionExpression' &&\n declaration.expression\n ) {\n return containsReactElementLikeExpression(declaration.body as Expression)\n }\n\n const body = declaration.body\n if (body === null) {\n return false\n }\n\n let found = false\n walkReactUsageTree(body, (node) => {\n if (node.type !== 'ReturnStatement' || node.argument === null) {\n return\n }\n\n if (containsReactElementLikeExpression(node.argument)) {\n found = true\n }\n })\n\n return found\n}\n\nfunction containsReactElementLikeExpression(expression: Expression): boolean {\n let found = false\n\n walkNode(expression, (node) => {\n if (\n node.type === 'JSXElement' ||\n node.type === 'JSXFragment' ||\n (node.type === 'CallExpression' && isReactCreateElementCall(node))\n ) {\n found = true\n }\n })\n\n return found\n}\n\nfunction getComponentReferenceName(node: JSXElement): string | undefined {\n const name = getJsxName(node.openingElement.name)\n return name !== undefined && isComponentName(name) ? name : undefined\n}\n\nfunction getHookReferenceName(node: CallExpression): string | undefined {\n const calleeName = getIdentifierName(node.callee)\n return calleeName !== undefined && isHookName(calleeName)\n ? calleeName\n : undefined\n}\n\nfunction getCreateElementComponentReferenceName(\n node: CallExpression,\n): string | undefined {\n if (!isReactCreateElementCall(node)) {\n return undefined\n }\n\n const [firstArgument] = node.arguments\n if (firstArgument === undefined || firstArgument.type !== 'Identifier') {\n return undefined\n }\n\n return isComponentName(firstArgument.name) ? firstArgument.name : undefined\n}\n\nfunction isReactCreateElementCall(node: CallExpression): boolean {\n const callee = unwrapExpression(node.callee)\n if (callee.type !== 'MemberExpression' || callee.computed) {\n return false\n }\n\n return (\n callee.object.type === 'Identifier' &&\n callee.object.name === 'React' &&\n callee.property.name === 'createElement'\n )\n}\n\nfunction getJsxName(name: JSXElementName): string | undefined {\n if (name.type === 'JSXIdentifier') {\n return name.name\n }\n\n return undefined\n}\n\nfunction getIdentifierName(expression: Expression): string | undefined {\n const unwrapped = unwrapExpression(expression)\n return unwrapped.type === 'Identifier' ? unwrapped.name : undefined\n}\n\nfunction unwrapExpression(expression: Expression): Expression {\n let current = expression\n\n while (true) {\n if (\n current.type === 'ParenthesizedExpression' ||\n current.type === 'TSAsExpression' ||\n current.type === 'TSSatisfiesExpression' ||\n current.type === 'TSTypeAssertion' ||\n current.type === 'TSNonNullExpression'\n ) {\n current = current.expression\n continue\n }\n\n return current\n }\n}\n\nfunction walkReactUsageTree(\n root: FunctionBody | Expression | JSXFragment | JSXElement,\n visit: (node: Node) => void,\n): void {\n walkNode(root, visit, true)\n}\n\nfunction walkNode(\n node: Node,\n visit: (node: Node) => void,\n allowNestedFunctions = false,\n): void {\n visit(node)\n\n const keys = visitorKeys[node.type]\n if (keys === undefined) {\n return\n }\n\n keys.forEach((key) => {\n const value = (node as unknown as Record<string, unknown>)[key]\n walkChild(value, visit, allowNestedFunctions)\n })\n}\n\nfunction walkChild(\n value: unknown,\n visit: (node: Node) => void,\n allowNestedFunctions: boolean,\n): void {\n if (Array.isArray(value)) {\n value.forEach((entry) => {\n walkChild(entry, visit, allowNestedFunctions)\n })\n return\n }\n\n if (!isNode(value)) {\n return\n }\n\n if (!allowNestedFunctions && FUNCTION_NODE_TYPES.has(value.type)) {\n return\n }\n\n walkNode(value, visit, false)\n}\n\nfunction isNode(value: unknown): value is Node {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'type' in value &&\n typeof (value as { type: unknown }).type === 'string'\n )\n}\n\nfunction resolveReactReference(\n fileAnalysis: FileAnalysis,\n fileAnalyses: ReadonlyMap<string, FileAnalysis>,\n name: string,\n kind: ReactSymbolKind,\n): string | undefined {\n const localSymbol = fileAnalysis.symbolsByName.get(name)\n if (localSymbol !== undefined && localSymbol.kind === kind) {\n return localSymbol.id\n }\n\n const importBinding = fileAnalysis.importsByLocalName.get(name)\n if (importBinding === undefined) {\n return undefined\n }\n\n if (importBinding.sourcePath === undefined) {\n return kind === 'hook'\n ? getExternalHookNodeId(importBinding, name)\n : undefined\n }\n\n const sourceFileAnalysis = fileAnalyses.get(importBinding.sourcePath)\n if (sourceFileAnalysis === undefined) {\n return undefined\n }\n\n const targetId = sourceFileAnalysis.exportsByName.get(\n importBinding.importedName,\n )\n if (targetId === undefined) {\n return undefined\n }\n\n const targetSymbol = sourceFileAnalysis.symbolsById.get(targetId)\n return targetSymbol?.kind === kind ? targetId : undefined\n}\n\nfunction createExternalHookNode(\n binding: ImportBinding,\n localName: string,\n): ReactUsageNode {\n const name = getExternalHookName(binding, localName)\n\n return {\n id: getExternalHookNodeId(binding, localName),\n name,\n kind: 'hook',\n filePath: binding.sourceSpecifier,\n exportNames: [binding.importedName],\n usages: [],\n }\n}\n\nfunction getExternalHookNodeId(\n binding: ImportBinding,\n localName: string,\n): string {\n return `external:${binding.sourceSpecifier}#hook:${getExternalHookName(binding, localName)}`\n}\n\nfunction getExternalHookName(\n binding: ImportBinding,\n localName: string,\n): string {\n return binding.importedName === 'default' ? localName : binding.importedName\n}\n\nfunction getFilteredReactUsageNodes(\n graph: ReactUsageGraph,\n filter: ReactUsageFilter,\n): ReactUsageNode[] {\n return [...graph.nodes.values()]\n .filter((node) => matchesReactFilter(node, filter))\n .sort((left, right) => compareReactNodes(left, right))\n}\n\nfunction matchesReactFilter(\n node: ReactUsageNode,\n filter: ReactUsageFilter,\n): boolean {\n return filter === 'all' || node.kind === filter\n}\n\nfunction serializeReactUsageNode(\n nodeId: string,\n graph: ReactUsageGraph,\n filter: ReactUsageFilter,\n visited: Set<string>,\n): SerializedReactUsageNode {\n const node = graph.nodes.get(nodeId)\n if (node === undefined) {\n return {\n id: nodeId,\n name: nodeId,\n symbolKind: 'circular',\n filePath: '',\n exportNames: [],\n usages: [],\n }\n }\n\n if (visited.has(nodeId)) {\n return {\n id: node.id,\n name: node.name,\n symbolKind: 'circular',\n filePath: toDisplayPath(node.filePath, graph.cwd),\n exportNames: node.exportNames,\n usages: [],\n }\n }\n\n const nextVisited = new Set(visited)\n nextVisited.add(nodeId)\n\n return {\n id: node.id,\n name: node.name,\n symbolKind: node.kind,\n filePath: toDisplayPath(node.filePath, graph.cwd),\n exportNames: node.exportNames,\n usages: getFilteredUsages(node, graph, filter).map((usage) => ({\n kind: usage.kind,\n targetId: usage.target,\n node: serializeReactUsageNode(usage.target, graph, filter, nextVisited),\n })),\n }\n}\n\nfunction compareReactNodeIds(\n leftId: string,\n rightId: string,\n nodes: ReadonlyMap<string, ReactUsageNode>,\n): number {\n const left = nodes.get(leftId)\n const right = nodes.get(rightId)\n\n if (left === undefined || right === undefined) {\n return leftId.localeCompare(rightId)\n }\n\n return compareReactNodes(left, right)\n}\n\nfunction compareReactNodes(\n left: ReactUsageNode,\n right: ReactUsageNode,\n): number {\n return (\n left.filePath.localeCompare(right.filePath) ||\n left.name.localeCompare(right.name) ||\n left.kind.localeCompare(right.kind)\n )\n}\n\nfunction toModuleExportName(name: ModuleExportName): string {\n return name.type === 'Literal' ? name.value : name.name\n}\n\nfunction isHookName(name: string): boolean {\n return /^use[A-Z0-9]/.test(name)\n}\n\nfunction isComponentName(name: string): boolean {\n return /^[A-Z]/.test(name)\n}\n","import { toDisplayPath } from './path-utils.js'\nimport { getFilteredUsages, getReactUsageRoots } from './react-analyzer.js'\nimport type {\n PrintReactTreeOptions,\n ReactUsageEdge,\n ReactUsageGraph,\n ReactUsageNode,\n} from './types.js'\n\nexport function printReactUsageTree(\n graph: ReactUsageGraph,\n options: PrintReactTreeOptions = {},\n): string {\n const cwd = options.cwd ?? graph.cwd\n const filter = options.filter ?? 'all'\n const roots = getReactUsageRoots(graph, filter)\n\n if (roots.length === 0) {\n return 'No React symbols found.'\n }\n\n const lines: string[] = []\n roots.forEach((rootId, index) => {\n const root = graph.nodes.get(rootId)\n if (root === undefined) {\n return\n }\n\n lines.push(formatReactNodeLabel(root, cwd))\n const usages = getFilteredUsages(root, graph, filter)\n usages.forEach((usage, usageIndex) => {\n lines.push(\n ...renderUsage(\n usage,\n graph,\n cwd,\n filter,\n new Set([root.id]),\n '',\n usageIndex === usages.length - 1,\n ),\n )\n })\n\n if (index < roots.length - 1) {\n lines.push('')\n }\n })\n\n return lines.join('\\n')\n}\n\nfunction renderUsage(\n usage: ReactUsageEdge,\n graph: ReactUsageGraph,\n cwd: string,\n filter: NonNullable<PrintReactTreeOptions['filter']>,\n visited: ReadonlySet<string>,\n prefix: string,\n isLast: boolean,\n): string[] {\n const branch = `${prefix}${isLast ? '└─ ' : '├─ '}`\n const target = graph.nodes.get(usage.target)\n\n if (target === undefined) {\n return [`${branch}${usage.target}`]\n }\n\n if (visited.has(target.id)) {\n return [`${branch}${formatReactNodeLabel(target, cwd)} (circular)`]\n }\n\n const childLines = [`${branch}${formatReactNodeLabel(target, cwd)}`]\n const nextVisited = new Set(visited)\n nextVisited.add(target.id)\n const nextPrefix = `${prefix}${isLast ? ' ' : '│ '}`\n const childUsages = getFilteredUsages(target, graph, filter)\n\n childUsages.forEach((childUsage, index) => {\n childLines.push(\n ...renderUsage(\n childUsage,\n graph,\n cwd,\n filter,\n nextVisited,\n nextPrefix,\n index === childUsages.length - 1,\n ),\n )\n })\n\n return childLines\n}\n\nfunction formatReactNodeLabel(node: ReactUsageNode, cwd: string): string {\n return `${node.name} [${node.kind}] (${toDisplayPath(node.filePath, cwd)})`\n}\n","import { toDisplayPath } from './path-utils.js'\nimport type {\n DependencyEdge,\n DependencyGraph,\n PrintTreeOptions,\n} from './types.js'\n\nexport function printDependencyTree(\n graph: DependencyGraph,\n options: PrintTreeOptions = {},\n): string {\n const cwd = options.cwd ?? graph.cwd\n const includeExternals = options.includeExternals ?? false\n const rootLines = [toDisplayPath(graph.entryId, cwd)]\n const visited = new Set<string>([graph.entryId])\n const entryNode = graph.nodes.get(graph.entryId)\n\n if (entryNode === undefined) {\n return rootLines.join('\\n')\n }\n\n const rootDependencies = filterDependencies(\n entryNode.dependencies,\n includeExternals,\n )\n\n rootDependencies.forEach((dependency, index) => {\n const isLast = index === rootDependencies.length - 1\n const lines = renderDependency(\n dependency,\n graph,\n visited,\n '',\n isLast,\n includeExternals,\n cwd,\n )\n rootLines.push(...lines)\n })\n\n return rootLines.join('\\n')\n}\n\nfunction renderDependency(\n dependency: DependencyEdge,\n graph: DependencyGraph,\n visited: ReadonlySet<string>,\n prefix: string,\n isLast: boolean,\n includeExternals: boolean,\n cwd: string,\n): string[] {\n const branch = `${prefix}${isLast ? '└─ ' : '├─ '}`\n const label = formatDependencyLabel(dependency, graph, cwd)\n\n if (dependency.kind !== 'source') {\n return [`${branch}${label}`]\n }\n\n if (visited.has(dependency.target)) {\n return [`${branch}${label} (circular)`]\n }\n\n const childNode = graph.nodes.get(dependency.target)\n if (childNode === undefined) {\n return [`${branch}${label}`]\n }\n\n const nextPrefix = `${prefix}${isLast ? ' ' : '│ '}`\n const nextVisited = new Set(visited)\n nextVisited.add(dependency.target)\n\n const childLines = [`${branch}${label}`]\n const childDependencies = filterDependencies(\n childNode.dependencies,\n includeExternals,\n )\n\n childDependencies.forEach((childDependency, index) => {\n const isChildLast = index === childDependencies.length - 1\n childLines.push(\n ...renderDependency(\n childDependency,\n graph,\n nextVisited,\n nextPrefix,\n isChildLast,\n includeExternals,\n cwd,\n ),\n )\n })\n\n return childLines\n}\n\nfunction filterDependencies(\n dependencies: readonly DependencyEdge[],\n includeExternals: boolean,\n): DependencyEdge[] {\n return dependencies.filter((dependency) => {\n if (dependency.kind === 'source' || dependency.kind === 'missing') {\n return true\n }\n\n return includeExternals\n })\n}\n\nfunction formatDependencyLabel(\n dependency: DependencyEdge,\n _graph: DependencyGraph,\n cwd: string,\n): string {\n const prefixes: string[] = []\n if (dependency.isTypeOnly) {\n prefixes.push('type')\n }\n\n if (dependency.referenceKind === 'require') {\n prefixes.push('require')\n } else if (dependency.referenceKind === 'dynamic-import') {\n prefixes.push('dynamic')\n } else if (dependency.referenceKind === 'export') {\n prefixes.push('re-export')\n } else if (dependency.referenceKind === 'import-equals') {\n prefixes.push('import=')\n }\n\n const annotation = prefixes.length > 0 ? `[${prefixes.join(', ')}] ` : ''\n\n if (dependency.kind === 'source') {\n return `${annotation}${toDisplayPath(dependency.target, cwd)}`\n }\n\n if (dependency.kind === 'missing') {\n return `${annotation}${dependency.specifier} [missing]`\n }\n\n if (dependency.kind === 'builtin') {\n return `${annotation}${dependency.target} [builtin]`\n }\n\n return `${annotation}${dependency.target} [external]`\n}\n"],"mappings":"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"}
|