@lbroth/rothunter 1.0.0-rc.1
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/LICENSE +21 -0
- package/README.md +141 -0
- package/dist/adapters/llm.d.ts +68 -0
- package/dist/adapters/llm.d.ts.map +1 -0
- package/dist/adapters/llm.js +189 -0
- package/dist/adapters/llm.js.map +1 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +81 -0
- package/dist/config.js.map +1 -0
- package/dist/detector-registry.d.ts +32 -0
- package/dist/detector-registry.d.ts.map +1 -0
- package/dist/detector-registry.js +74 -0
- package/dist/detector-registry.js.map +1 -0
- package/dist/detectors/api-race.d.ts +6 -0
- package/dist/detectors/api-race.d.ts.map +1 -0
- package/dist/detectors/api-race.js +222 -0
- package/dist/detectors/api-race.js.map +1 -0
- package/dist/detectors/bad-config.d.ts +6 -0
- package/dist/detectors/bad-config.d.ts.map +1 -0
- package/dist/detectors/bad-config.js +529 -0
- package/dist/detectors/bad-config.js.map +1 -0
- package/dist/detectors/console-log-prod.d.ts +6 -0
- package/dist/detectors/console-log-prod.d.ts.map +1 -0
- package/dist/detectors/console-log-prod.js +72 -0
- package/dist/detectors/console-log-prod.js.map +1 -0
- package/dist/detectors/dead-api.d.ts +10 -0
- package/dist/detectors/dead-api.d.ts.map +1 -0
- package/dist/detectors/dead-api.js +115 -0
- package/dist/detectors/dead-api.js.map +1 -0
- package/dist/detectors/dead-export.d.ts +12 -0
- package/dist/detectors/dead-export.d.ts.map +1 -0
- package/dist/detectors/dead-export.js +140 -0
- package/dist/detectors/dead-export.js.map +1 -0
- package/dist/detectors/dead-handler.d.ts +12 -0
- package/dist/detectors/dead-handler.d.ts.map +1 -0
- package/dist/detectors/dead-handler.js +40 -0
- package/dist/detectors/dead-handler.js.map +1 -0
- package/dist/detectors/dead-module.d.ts +14 -0
- package/dist/detectors/dead-module.d.ts.map +1 -0
- package/dist/detectors/dead-module.js +50 -0
- package/dist/detectors/dead-module.js.map +1 -0
- package/dist/detectors/deep-nesting.d.ts +12 -0
- package/dist/detectors/deep-nesting.d.ts.map +1 -0
- package/dist/detectors/deep-nesting.js +133 -0
- package/dist/detectors/deep-nesting.js.map +1 -0
- package/dist/detectors/duplicate-function.d.ts +9 -0
- package/dist/detectors/duplicate-function.d.ts.map +1 -0
- package/dist/detectors/duplicate-function.js +199 -0
- package/dist/detectors/duplicate-function.js.map +1 -0
- package/dist/detectors/duplicate-type.d.ts +9 -0
- package/dist/detectors/duplicate-type.d.ts.map +1 -0
- package/dist/detectors/duplicate-type.js +166 -0
- package/dist/detectors/duplicate-type.js.map +1 -0
- package/dist/detectors/hot-hub-file.d.ts +11 -0
- package/dist/detectors/hot-hub-file.d.ts.map +1 -0
- package/dist/detectors/hot-hub-file.js +42 -0
- package/dist/detectors/hot-hub-file.js.map +1 -0
- package/dist/detectors/long-file.d.ts +12 -0
- package/dist/detectors/long-file.d.ts.map +1 -0
- package/dist/detectors/long-file.js +82 -0
- package/dist/detectors/long-file.js.map +1 -0
- package/dist/detectors/long-function.d.ts +12 -0
- package/dist/detectors/long-function.d.ts.map +1 -0
- package/dist/detectors/long-function.js +45 -0
- package/dist/detectors/long-function.js.map +1 -0
- package/dist/detectors/magic-numbers.d.ts +10 -0
- package/dist/detectors/magic-numbers.d.ts.map +1 -0
- package/dist/detectors/magic-numbers.js +332 -0
- package/dist/detectors/magic-numbers.js.map +1 -0
- package/dist/detectors/mutable-globals.d.ts +6 -0
- package/dist/detectors/mutable-globals.d.ts.map +1 -0
- package/dist/detectors/mutable-globals.js +95 -0
- package/dist/detectors/mutable-globals.js.map +1 -0
- package/dist/detectors/mutation.d.ts +11 -0
- package/dist/detectors/mutation.d.ts.map +1 -0
- package/dist/detectors/mutation.js +397 -0
- package/dist/detectors/mutation.js.map +1 -0
- package/dist/detectors/public-any.d.ts +6 -0
- package/dist/detectors/public-any.d.ts.map +1 -0
- package/dist/detectors/public-any.js +52 -0
- package/dist/detectors/public-any.js.map +1 -0
- package/dist/detectors/race-condition.d.ts +6 -0
- package/dist/detectors/race-condition.d.ts.map +1 -0
- package/dist/detectors/race-condition.js +608 -0
- package/dist/detectors/race-condition.js.map +1 -0
- package/dist/detectors/shared-db-write.d.ts +6 -0
- package/dist/detectors/shared-db-write.d.ts.map +1 -0
- package/dist/detectors/shared-db-write.js +656 -0
- package/dist/detectors/shared-db-write.js.map +1 -0
- package/dist/detectors/silent-catch.d.ts +6 -0
- package/dist/detectors/silent-catch.d.ts.map +1 -0
- package/dist/detectors/silent-catch.js +167 -0
- package/dist/detectors/silent-catch.js.map +1 -0
- package/dist/detectors/similar-functions.d.ts +15 -0
- package/dist/detectors/similar-functions.d.ts.map +1 -0
- package/dist/detectors/similar-functions.js +334 -0
- package/dist/detectors/similar-functions.js.map +1 -0
- package/dist/detectors/skip-tests.d.ts +6 -0
- package/dist/detectors/skip-tests.d.ts.map +1 -0
- package/dist/detectors/skip-tests.js +69 -0
- package/dist/detectors/skip-tests.js.map +1 -0
- package/dist/detectors/todo-comments.d.ts +29 -0
- package/dist/detectors/todo-comments.d.ts.map +1 -0
- package/dist/detectors/todo-comments.js +154 -0
- package/dist/detectors/todo-comments.js.map +1 -0
- package/dist/detectors/unused-deps.d.ts +8 -0
- package/dist/detectors/unused-deps.d.ts.map +1 -0
- package/dist/detectors/unused-deps.js +115 -0
- package/dist/detectors/unused-deps.js.map +1 -0
- package/dist/extraction/api-race-confirmer.d.ts +31 -0
- package/dist/extraction/api-race-confirmer.d.ts.map +1 -0
- package/dist/extraction/api-race-confirmer.js +110 -0
- package/dist/extraction/api-race-confirmer.js.map +1 -0
- package/dist/extraction/llm-confirmer.d.ts +25 -0
- package/dist/extraction/llm-confirmer.d.ts.map +1 -0
- package/dist/extraction/llm-confirmer.js +118 -0
- package/dist/extraction/llm-confirmer.js.map +1 -0
- package/dist/extraction/mutation-confirmer.d.ts +30 -0
- package/dist/extraction/mutation-confirmer.d.ts.map +1 -0
- package/dist/extraction/mutation-confirmer.js +73 -0
- package/dist/extraction/mutation-confirmer.js.map +1 -0
- package/dist/extraction/prompt-chunking.d.ts +37 -0
- package/dist/extraction/prompt-chunking.d.ts.map +1 -0
- package/dist/extraction/prompt-chunking.js +61 -0
- package/dist/extraction/prompt-chunking.js.map +1 -0
- package/dist/extraction/race-confirmer.d.ts +28 -0
- package/dist/extraction/race-confirmer.d.ts.map +1 -0
- package/dist/extraction/race-confirmer.js +68 -0
- package/dist/extraction/race-confirmer.js.map +1 -0
- package/dist/extraction/shared-db-write-confirmer.d.ts +31 -0
- package/dist/extraction/shared-db-write-confirmer.d.ts.map +1 -0
- package/dist/extraction/shared-db-write-confirmer.js +141 -0
- package/dist/extraction/shared-db-write-confirmer.js.map +1 -0
- package/dist/extraction/triage-confirmer.d.ts +59 -0
- package/dist/extraction/triage-confirmer.d.ts.map +1 -0
- package/dist/extraction/triage-confirmer.js +104 -0
- package/dist/extraction/triage-confirmer.js.map +1 -0
- package/dist/graph/cfg.d.ts +45 -0
- package/dist/graph/cfg.d.ts.map +1 -0
- package/dist/graph/cfg.js +198 -0
- package/dist/graph/cfg.js.map +1 -0
- package/dist/graph/decorator-entries.d.ts +2 -0
- package/dist/graph/decorator-entries.d.ts.map +1 -0
- package/dist/graph/decorator-entries.js +89 -0
- package/dist/graph/decorator-entries.js.map +1 -0
- package/dist/graph/entry-points.d.ts +12 -0
- package/dist/graph/entry-points.d.ts.map +1 -0
- package/dist/graph/entry-points.js +282 -0
- package/dist/graph/entry-points.js.map +1 -0
- package/dist/graph/handler-conventions.d.ts +2 -0
- package/dist/graph/handler-conventions.d.ts.map +1 -0
- package/dist/graph/handler-conventions.js +26 -0
- package/dist/graph/handler-conventions.js.map +1 -0
- package/dist/graph/iac-entries.d.ts +2 -0
- package/dist/graph/iac-entries.d.ts.map +1 -0
- package/dist/graph/iac-entries.js +123 -0
- package/dist/graph/iac-entries.js.map +1 -0
- package/dist/graph/import-graph.d.ts +48 -0
- package/dist/graph/import-graph.d.ts.map +1 -0
- package/dist/graph/import-graph.js +86 -0
- package/dist/graph/import-graph.js.map +1 -0
- package/dist/graph/monorepo-detect.d.ts +3 -0
- package/dist/graph/monorepo-detect.d.ts.map +1 -0
- package/dist/graph/monorepo-detect.js +166 -0
- package/dist/graph/monorepo-detect.js.map +1 -0
- package/dist/graph/tsconfig-paths.d.ts +23 -0
- package/dist/graph/tsconfig-paths.d.ts.map +1 -0
- package/dist/graph/tsconfig-paths.js +217 -0
- package/dist/graph/tsconfig-paths.js.map +1 -0
- package/dist/multi-workspace-scanner.d.ts +13 -0
- package/dist/multi-workspace-scanner.d.ts.map +1 -0
- package/dist/multi-workspace-scanner.js +130 -0
- package/dist/multi-workspace-scanner.js.map +1 -0
- package/dist/normalizers/type-normalizer.d.ts +16 -0
- package/dist/normalizers/type-normalizer.d.ts.map +1 -0
- package/dist/normalizers/type-normalizer.js +189 -0
- package/dist/normalizers/type-normalizer.js.map +1 -0
- package/dist/parsers/typescript-parser.d.ts +57 -0
- package/dist/parsers/typescript-parser.d.ts.map +1 -0
- package/dist/parsers/typescript-parser.js +502 -0
- package/dist/parsers/typescript-parser.js.map +1 -0
- package/dist/reporter/json-reporter.d.ts +12 -0
- package/dist/reporter/json-reporter.d.ts.map +1 -0
- package/dist/reporter/json-reporter.js +28 -0
- package/dist/reporter/json-reporter.js.map +1 -0
- package/dist/reporter/markdown-reporter.d.ts +11 -0
- package/dist/reporter/markdown-reporter.d.ts.map +1 -0
- package/dist/reporter/markdown-reporter.js +77 -0
- package/dist/reporter/markdown-reporter.js.map +1 -0
- package/dist/rothunter.d.ts +125 -0
- package/dist/rothunter.d.ts.map +1 -0
- package/dist/rothunter.js +1038 -0
- package/dist/rothunter.js.map +1 -0
- package/dist/server/false-positives.d.ts +34 -0
- package/dist/server/false-positives.d.ts.map +1 -0
- package/dist/server/false-positives.js +85 -0
- package/dist/server/false-positives.js.map +1 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +1529 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/marked-to-fix.d.ts +16 -0
- package/dist/server/marked-to-fix.d.ts.map +1 -0
- package/dist/server/marked-to-fix.js +36 -0
- package/dist/server/marked-to-fix.js.map +1 -0
- package/dist/server/scan-store.d.ts +147 -0
- package/dist/server/scan-store.d.ts.map +1 -0
- package/dist/server/scan-store.js +291 -0
- package/dist/server/scan-store.js.map +1 -0
- package/dist/server/settings-store.d.ts +28 -0
- package/dist/server/settings-store.d.ts.map +1 -0
- package/dist/server/settings-store.js +46 -0
- package/dist/server/settings-store.js.map +1 -0
- package/dist/server/workspace-store.d.ts +39 -0
- package/dist/server/workspace-store.d.ts.map +1 -0
- package/dist/server/workspace-store.js +108 -0
- package/dist/server/workspace-store.js.map +1 -0
- package/dist/types/detector-input.d.ts +37 -0
- package/dist/types/detector-input.d.ts.map +1 -0
- package/dist/types/detector-input.js +2 -0
- package/dist/types/detector-input.js.map +1 -0
- package/dist/types.d.ts +110 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/clustering.d.ts +14 -0
- package/dist/utils/clustering.d.ts.map +1 -0
- package/dist/utils/clustering.js +56 -0
- package/dist/utils/clustering.js.map +1 -0
- package/dist/utils/gitignore.d.ts +32 -0
- package/dist/utils/gitignore.d.ts.map +1 -0
- package/dist/utils/gitignore.js +122 -0
- package/dist/utils/gitignore.js.map +1 -0
- package/dist/utils/hash.d.ts +11 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +14 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/ignore-annotation.d.ts +28 -0
- package/dist/utils/ignore-annotation.d.ts.map +1 -0
- package/dist/utils/ignore-annotation.js +46 -0
- package/dist/utils/ignore-annotation.js.map +1 -0
- package/dist/utils/llm-json.d.ts +2 -0
- package/dist/utils/llm-json.d.ts.map +1 -0
- package/dist/utils/llm-json.js +53 -0
- package/dist/utils/llm-json.js.map +1 -0
- package/dist/utils/logger.d.ts +3 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +4 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/project-conventions.d.ts +2 -0
- package/dist/utils/project-conventions.d.ts.map +1 -0
- package/dist/utils/project-conventions.js +108 -0
- package/dist/utils/project-conventions.js.map +1 -0
- package/dist/utils/regex.d.ts +9 -0
- package/dist/utils/regex.d.ts.map +1 -0
- package/dist/utils/regex.js +11 -0
- package/dist/utils/regex.js.map +1 -0
- package/dist/utils/snippet.d.ts +20 -0
- package/dist/utils/snippet.d.ts.map +1 -0
- package/dist/utils/snippet.js +28 -0
- package/dist/utils/snippet.js.map +1 -0
- package/dist/utils/source-reader.d.ts +19 -0
- package/dist/utils/source-reader.d.ts.map +1 -0
- package/dist/utils/source-reader.js +32 -0
- package/dist/utils/source-reader.js.map +1 -0
- package/logo.png +0 -0
- package/package.json +92 -0
- package/scripts/start-llm.mjs +161 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
// Entry-point heuristics: package.json main/module/bin/exports, conventional
|
|
4
|
+
// filenames (index/main/cli, scripts/, bin/), tests, framework routes (Next,
|
|
5
|
+
// SvelteKit, Astro). Workspace-relative POSIX paths.
|
|
6
|
+
/**
|
|
7
|
+
* Decide whether the workspace at `root` describes a published npm
|
|
8
|
+
* library. Heuristic: top-level `package.json` has a name + version,
|
|
9
|
+
* is NOT marked private, AND declares one of the standard package
|
|
10
|
+
* entry fields (main / module / exports / bin). When this is true,
|
|
11
|
+
* downstream consumers can import individual files and dead-export
|
|
12
|
+
* verdicts need to lean toward FALSE-POSITIVE for any symbol that
|
|
13
|
+
* looks like a utility / config / type-surface helper.
|
|
14
|
+
*/
|
|
15
|
+
export function isPublishedLibrary(root) {
|
|
16
|
+
try {
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf-8'));
|
|
18
|
+
if (typeof pkg.name !== 'string' || pkg.name.length === 0)
|
|
19
|
+
return false;
|
|
20
|
+
if (typeof pkg.version !== 'string' || pkg.version.length === 0)
|
|
21
|
+
return false;
|
|
22
|
+
if (pkg.private === true)
|
|
23
|
+
return false;
|
|
24
|
+
return (typeof pkg.main === 'string' ||
|
|
25
|
+
typeof pkg.module === 'string' ||
|
|
26
|
+
pkg.exports != null ||
|
|
27
|
+
pkg.bin != null);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function discoverEntryPoints(workspaceRoot, knownFiles) {
|
|
34
|
+
const entries = new Set();
|
|
35
|
+
addPackageJsonEntries(workspaceRoot, entries);
|
|
36
|
+
// Walk nested package.json files (monorepo workspaces — `packages/foo/
|
|
37
|
+
// package.json`, `apps/bar/package.json`, etc.). Each one's scripts /
|
|
38
|
+
// main / bin / exports field names entry points in its own subtree.
|
|
39
|
+
// Walked via direct fs scan rather than `knownFiles` because package.json
|
|
40
|
+
// is not parsed by the TS parser and never appears in the file set.
|
|
41
|
+
for (const pkgDir of findNestedPackageDirs(workspaceRoot)) {
|
|
42
|
+
addPackageJsonEntries(pkgDir, entries, workspaceRoot);
|
|
43
|
+
}
|
|
44
|
+
for (const file of knownFiles) {
|
|
45
|
+
if (matchesConvention(file))
|
|
46
|
+
entries.add(file);
|
|
47
|
+
}
|
|
48
|
+
return entries;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Filesystem walk for every directory containing a `package.json`
|
|
52
|
+
* below `root`. Skips `node_modules`, dot-directories, and common
|
|
53
|
+
* build / cache outputs to keep the walk bounded. Returns absolute
|
|
54
|
+
* paths (consumed by `addPackageJsonEntries`).
|
|
55
|
+
*/
|
|
56
|
+
function findNestedPackageDirs(root) {
|
|
57
|
+
const out = [];
|
|
58
|
+
const SKIP_DIRS = new Set([
|
|
59
|
+
'node_modules', 'dist', 'build', 'out', 'coverage', '.git',
|
|
60
|
+
'.next', '.nuxt', '.svelte-kit', '.turbo', '.cache', '.parcel-cache',
|
|
61
|
+
'.vite', 'tmp', 'temp',
|
|
62
|
+
]);
|
|
63
|
+
const stack = [root];
|
|
64
|
+
while (stack.length > 0) {
|
|
65
|
+
const dir = stack.pop();
|
|
66
|
+
let dirents;
|
|
67
|
+
try {
|
|
68
|
+
dirents = fs.readdirSync(dir, { withFileTypes: true });
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
for (const e of dirents) {
|
|
74
|
+
if (e.isDirectory()) {
|
|
75
|
+
if (e.name.startsWith('.') && e.name !== '.')
|
|
76
|
+
continue;
|
|
77
|
+
if (SKIP_DIRS.has(e.name))
|
|
78
|
+
continue;
|
|
79
|
+
stack.push(path.join(dir, e.name));
|
|
80
|
+
}
|
|
81
|
+
else if (e.isFile() && e.name === 'package.json' && dir !== root) {
|
|
82
|
+
out.push(dir);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
88
|
+
const ENTRY_FILENAMES = new Set([
|
|
89
|
+
'index.ts',
|
|
90
|
+
'index.tsx',
|
|
91
|
+
'main.ts',
|
|
92
|
+
'main.tsx',
|
|
93
|
+
'cli.ts',
|
|
94
|
+
'mcp-server.ts',
|
|
95
|
+
'server.ts',
|
|
96
|
+
]);
|
|
97
|
+
/** Patterns that indicate a file is conventionally an entry point or a test harness. */
|
|
98
|
+
function matchesConvention(file) {
|
|
99
|
+
const posix = file.split(path.sep).join('/');
|
|
100
|
+
const basename = path.basename(posix);
|
|
101
|
+
if (ENTRY_FILENAMES.has(basename))
|
|
102
|
+
return true;
|
|
103
|
+
if (/^scripts\//.test(posix))
|
|
104
|
+
return true;
|
|
105
|
+
if (/^bin\//.test(posix))
|
|
106
|
+
return true;
|
|
107
|
+
if (/(^|\/)__tests__\//.test(posix))
|
|
108
|
+
return true;
|
|
109
|
+
if (/(^|\/)__fixtures__\//.test(posix))
|
|
110
|
+
return true;
|
|
111
|
+
if (/(^|\/)__mocks__\//.test(posix))
|
|
112
|
+
return true;
|
|
113
|
+
if (/(^|\/)tests\//.test(posix))
|
|
114
|
+
return true;
|
|
115
|
+
if (/(^|\/)test\//.test(posix))
|
|
116
|
+
return true;
|
|
117
|
+
if (/(^|\/)e2e\//.test(posix))
|
|
118
|
+
return true;
|
|
119
|
+
// Standalone demos / runnable examples — never imported, but invoked
|
|
120
|
+
// directly via `tsx examples/foo.ts`. Real-world FP on nullpii's
|
|
121
|
+
// examples/01-basic.ts etc.
|
|
122
|
+
if (/(^|\/)examples\//.test(posix))
|
|
123
|
+
return true;
|
|
124
|
+
if (/(^|\/)demo\//.test(posix))
|
|
125
|
+
return true;
|
|
126
|
+
if (/(^|\/)benchmarks?\//.test(posix))
|
|
127
|
+
return true;
|
|
128
|
+
// Workspace-level config files at the root — `vitest.config.ts`,
|
|
129
|
+
// `jest.config.ts`, `vite.config.ts`, `playwright.config.ts`, etc.
|
|
130
|
+
if (/^[^/]*\.config\.(ts|tsx|mts|cts)$/.test(posix))
|
|
131
|
+
return true;
|
|
132
|
+
if (/\.(test|spec)\.(ts|tsx)$/.test(posix))
|
|
133
|
+
return true;
|
|
134
|
+
// ---- Next.js (pages-router + app-router) --------------------------------
|
|
135
|
+
if (/(^|\/)pages\//.test(posix))
|
|
136
|
+
return true;
|
|
137
|
+
// app/ files: match both the un-nested case (`app/layout.tsx`, `app/page.tsx`)
|
|
138
|
+
// AND nested route segments (`app/users/[id]/page.tsx`).
|
|
139
|
+
if (/(^|\/)(src\/)?app\/(.*\/)?(page|route|layout|loading|error|template|not-found|head|default|global-error)\.(ts|tsx)$/.test(posix))
|
|
140
|
+
return true;
|
|
141
|
+
if (basename === 'middleware.ts' || basename === 'middleware.tsx')
|
|
142
|
+
return true;
|
|
143
|
+
if (basename === 'instrumentation.ts' || basename === 'instrumentation-client.ts')
|
|
144
|
+
return true;
|
|
145
|
+
// ---- SvelteKit / Remix / Astro -------------------------------------------
|
|
146
|
+
if (/(^|\/)routes\//.test(posix))
|
|
147
|
+
return true;
|
|
148
|
+
if (/(^|\/)src\/pages\//.test(posix))
|
|
149
|
+
return true;
|
|
150
|
+
if (/(^|\/)app\/routes\//.test(posix))
|
|
151
|
+
return true;
|
|
152
|
+
// ---- Serverless handlers ------------------------------------------------
|
|
153
|
+
// Vercel /api, Netlify functions, AWS SAM/CDK Lambda layouts, OpenNext.
|
|
154
|
+
if (/(^|\/)api\//.test(posix) && /\.(ts|tsx)$/.test(posix))
|
|
155
|
+
return true;
|
|
156
|
+
if (/(^|\/)netlify\/(functions|edge-functions)\//.test(posix))
|
|
157
|
+
return true;
|
|
158
|
+
if (/(^|\/)functions\//.test(posix))
|
|
159
|
+
return true;
|
|
160
|
+
if (/(^|\/)src\/functions\//.test(posix))
|
|
161
|
+
return true;
|
|
162
|
+
if (/(^|\/)handlers\//.test(posix))
|
|
163
|
+
return true;
|
|
164
|
+
if (/(^|\/)src\/handlers\//.test(posix))
|
|
165
|
+
return true;
|
|
166
|
+
if (/(^|\/)src\/lambdas?\//.test(posix))
|
|
167
|
+
return true;
|
|
168
|
+
if (/(^|\/)lambdas?\//.test(posix))
|
|
169
|
+
return true;
|
|
170
|
+
// Cloudflare Workers, Deno, Bun single-file conventions.
|
|
171
|
+
if (basename === 'mod.ts')
|
|
172
|
+
return true;
|
|
173
|
+
if (basename === 'worker.ts' || basename === 'worker.tsx')
|
|
174
|
+
return true;
|
|
175
|
+
// ---- AWS CDK / IaC entrypoints ------------------------------------------
|
|
176
|
+
if (/(^|\/)(bin|infra|cdk)\//.test(posix) && /\.(ts|tsx)$/.test(posix))
|
|
177
|
+
return true;
|
|
178
|
+
if (/\.stack\.(ts|tsx)$/.test(posix))
|
|
179
|
+
return true;
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
function addPackageJsonEntries(pkgRoot, entries,
|
|
183
|
+
/**
|
|
184
|
+
* Workspace root for emitting workspace-relative paths. Defaults to
|
|
185
|
+
* `pkgRoot` for the top-level case; nested package.json files pass
|
|
186
|
+
* the original workspace root so resolved files stay relative to it.
|
|
187
|
+
*/
|
|
188
|
+
workspaceRoot = pkgRoot) {
|
|
189
|
+
const pkgPath = path.join(pkgRoot, 'package.json');
|
|
190
|
+
if (!fs.existsSync(pkgPath))
|
|
191
|
+
return;
|
|
192
|
+
let pkg;
|
|
193
|
+
try {
|
|
194
|
+
pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
pushIfFile(pkgRoot, pkg.main, entries, workspaceRoot);
|
|
200
|
+
pushIfFile(pkgRoot, pkg.module, entries, workspaceRoot);
|
|
201
|
+
pushIfFile(pkgRoot, pkg.types, entries, workspaceRoot);
|
|
202
|
+
const bin = pkg.bin;
|
|
203
|
+
if (typeof bin === 'string')
|
|
204
|
+
pushIfFile(pkgRoot, bin, entries, workspaceRoot);
|
|
205
|
+
else if (bin && typeof bin === 'object') {
|
|
206
|
+
for (const v of Object.values(bin))
|
|
207
|
+
pushIfFile(pkgRoot, v, entries, workspaceRoot);
|
|
208
|
+
}
|
|
209
|
+
const exportsField = pkg.exports;
|
|
210
|
+
if (exportsField && typeof exportsField === 'object') {
|
|
211
|
+
walkExports(pkgRoot, exportsField, entries, workspaceRoot);
|
|
212
|
+
}
|
|
213
|
+
// `scripts` field: dev runners (`tsx watch src/dev.ts`), one-off
|
|
214
|
+
// scripts (`node scripts/seed.ts`), build steps that compile a file
|
|
215
|
+
// directly — each names a real file in the workspace that should
|
|
216
|
+
// count as an entry point. Without this, every server `dev.ts` /
|
|
217
|
+
// worker / migration script reads as dead-module.
|
|
218
|
+
const scripts = pkg.scripts;
|
|
219
|
+
if (scripts && typeof scripts === 'object') {
|
|
220
|
+
for (const v of Object.values(scripts)) {
|
|
221
|
+
if (typeof v === 'string')
|
|
222
|
+
extractScriptFileRefs(pkgRoot, v, entries, workspaceRoot);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Walk a package.json script command and extract every workspace-
|
|
228
|
+
* relative file path that looks like a source-file argument. Matches
|
|
229
|
+
* tokens ending in `.ts` / `.tsx` / `.mts` / `.cts` / `.js` / `.mjs` /
|
|
230
|
+
* `.cjs` and runs them through the same `pushIfFile` resolver as
|
|
231
|
+
* `main` / `bin` / `exports` so `dist/foo.js` → `src/foo.ts` swapping
|
|
232
|
+
* still works.
|
|
233
|
+
*
|
|
234
|
+
* Heuristic: extract via word boundary on whitespace, `&&`, `||`, `;`,
|
|
235
|
+
* `|`. Skip flag-shaped tokens (`--config=foo.ts`) — they're tooling
|
|
236
|
+
* config, not entry points the tool walks.
|
|
237
|
+
*/
|
|
238
|
+
function extractScriptFileRefs(pkgRoot, cmd, out, workspaceRoot) {
|
|
239
|
+
const tokens = cmd.split(/[\s&|;]+/).filter(Boolean);
|
|
240
|
+
for (const tok of tokens) {
|
|
241
|
+
if (tok.startsWith('-'))
|
|
242
|
+
continue;
|
|
243
|
+
if (tok.startsWith('"') || tok.startsWith("'"))
|
|
244
|
+
continue;
|
|
245
|
+
// Strip leading `./` / `node:` / shell expansion artifacts.
|
|
246
|
+
const cleaned = tok.replace(/^\.\/+/, '').replace(/[)"';]+$/, '');
|
|
247
|
+
if (!/\.(?:ts|tsx|mts|cts|js|mjs|cjs)$/i.test(cleaned))
|
|
248
|
+
continue;
|
|
249
|
+
pushIfFile(pkgRoot, cleaned, out, workspaceRoot);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function walkExports(pkgRoot, node, out, workspaceRoot) {
|
|
253
|
+
if (typeof node === 'string') {
|
|
254
|
+
pushIfFile(pkgRoot, node, out, workspaceRoot);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
for (const v of Object.values(node)) {
|
|
258
|
+
if (typeof v === 'string')
|
|
259
|
+
pushIfFile(pkgRoot, v, out, workspaceRoot);
|
|
260
|
+
else if (v && typeof v === 'object')
|
|
261
|
+
walkExports(pkgRoot, v, out, workspaceRoot);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function pushIfFile(pkgRoot, value, out, workspaceRoot) {
|
|
265
|
+
if (typeof value !== 'string')
|
|
266
|
+
return;
|
|
267
|
+
// Resolve package.json paths (often `dist/index.js`) back to the source by
|
|
268
|
+
// swapping `dist/` → `src/` and `.js` → `.ts` — a common build convention.
|
|
269
|
+
const candidates = [
|
|
270
|
+
value,
|
|
271
|
+
value.replace(/^\.?\/?dist\//, 'src/').replace(/\.js$/, '.ts'),
|
|
272
|
+
value.replace(/\.js$/, '.ts'),
|
|
273
|
+
];
|
|
274
|
+
for (const c of candidates) {
|
|
275
|
+
const abs = path.resolve(pkgRoot, c);
|
|
276
|
+
if (fs.existsSync(abs) && fs.statSync(abs).isFile()) {
|
|
277
|
+
out.add(path.relative(workspaceRoot, abs));
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=entry-points.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry-points.js","sourceRoot":"","sources":["../../src/graph/entry-points.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-conventions.d.ts","sourceRoot":"","sources":["../../src/graph/handler-conventions.ts"],"names":[],"mappings":"AAiBA,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAO7D"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
// Files in dirs where runtimes load handlers via explicit config (CDK/SAM/SST,
|
|
3
|
+
// netlify.toml, serverless): src/handlers, src/lambdas, src/functions, netlify/
|
|
4
|
+
// functions, etc. Auto-routed paths (pages/api, app/api/.../route) excluded —
|
|
5
|
+
// those are wired by filesystem convention, handled by entry-points.ts.
|
|
6
|
+
const HANDLER_DIR_PATTERNS = [
|
|
7
|
+
/(^|\/)src\/handlers\//,
|
|
8
|
+
/(^|\/)src\/lambdas?\//,
|
|
9
|
+
/(^|\/)src\/functions\//,
|
|
10
|
+
/(^|\/)handlers\//,
|
|
11
|
+
/(^|\/)lambdas?\//,
|
|
12
|
+
/(^|\/)functions\//,
|
|
13
|
+
/(^|\/)netlify\/(functions|edge-functions)\//,
|
|
14
|
+
];
|
|
15
|
+
export function isHandlerConventionFile(file) {
|
|
16
|
+
const posix = file.split(path.sep).join('/');
|
|
17
|
+
// Skip ambient declarations / story files — never handlers.
|
|
18
|
+
if (/\.d\.ts$/.test(posix))
|
|
19
|
+
return false;
|
|
20
|
+
if (/\.(test|spec)\.(ts|tsx)$/.test(posix))
|
|
21
|
+
return false;
|
|
22
|
+
if (!/\.(ts|tsx)$/.test(posix))
|
|
23
|
+
return false;
|
|
24
|
+
return HANDLER_DIR_PATTERNS.some((re) => re.test(posix));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=handler-conventions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-conventions.js","sourceRoot":"","sources":["../../src/graph/handler-conventions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,wEAAwE;AAExE,MAAM,oBAAoB,GAAa;IACrC,uBAAuB;IACvB,uBAAuB;IACvB,wBAAwB;IACxB,kBAAkB;IAClB,kBAAkB;IAClB,mBAAmB;IACnB,6CAA6C;CAC9C,CAAC;AAEF,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7C,4DAA4D;IAC5D,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACzD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iac-entries.d.ts","sourceRoot":"","sources":["../../src/graph/iac-entries.ts"],"names":[],"mappings":"AAOA,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,GAC3B,GAAG,CAAC,MAAM,CAAC,CAcb"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { Project, SyntaxKind } from 'ts-morph';
|
|
4
|
+
// IaC entry-point walker. Picks up CDK / SST / serverless constructs:
|
|
5
|
+
// NodejsFunction, lambda.Function, sst.Function, sst.Api routes, bundle({...}).
|
|
6
|
+
// Reads `entry` / `handler` / `code` strings → workspace-relative paths.
|
|
7
|
+
export function resolveIacEntryFiles(workspaceRoot, files) {
|
|
8
|
+
const project = new Project({
|
|
9
|
+
skipAddingFilesFromTsConfig: true,
|
|
10
|
+
skipFileDependencyResolution: true,
|
|
11
|
+
});
|
|
12
|
+
for (const rel of files) {
|
|
13
|
+
project.addSourceFileAtPathIfExists(path.join(workspaceRoot, rel));
|
|
14
|
+
}
|
|
15
|
+
const out = new Set();
|
|
16
|
+
for (const sf of project.getSourceFiles()) {
|
|
17
|
+
walkFile(workspaceRoot, sf, out);
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
const ENTRY_PROPERTY_NAMES = new Set(['entry', 'handler', 'code', 'entrypoint']);
|
|
22
|
+
/**
|
|
23
|
+
* Scan a single TypeScript source file for IaC construct entry strings.
|
|
24
|
+
* Emits each resolved workspace-relative target into `accumulator`.
|
|
25
|
+
*/
|
|
26
|
+
function walkFile(workspaceRoot, sourceFile, accumulator) {
|
|
27
|
+
const sourceFileDir = path.dirname(sourceFile.getFilePath());
|
|
28
|
+
// Walk every object-literal expression and inspect properties whose name is
|
|
29
|
+
// a known IaC entry property. We don't try to scope this to NewExpression
|
|
30
|
+
// ancestry — that adds complexity for little gain. False positives here
|
|
31
|
+
// simply mean "this string was treated as an entry point" which is the safe
|
|
32
|
+
// direction (entry points get *protected* by the dead-module detector).
|
|
33
|
+
for (const obj of sourceFile.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression)) {
|
|
34
|
+
for (const prop of obj.getProperties()) {
|
|
35
|
+
if (prop.getKind() !== SyntaxKind.PropertyAssignment)
|
|
36
|
+
continue;
|
|
37
|
+
// PropertyAssignment has .getName() and .getInitializer() on ts-morph wrapper.
|
|
38
|
+
const pa = prop;
|
|
39
|
+
const name = pa.getName();
|
|
40
|
+
if (!ENTRY_PROPERTY_NAMES.has(name))
|
|
41
|
+
continue;
|
|
42
|
+
const init = pa.getInitializer();
|
|
43
|
+
if (!init)
|
|
44
|
+
continue;
|
|
45
|
+
// Accept plain string literals and template literals with no interpolation.
|
|
46
|
+
const k = init.getKind();
|
|
47
|
+
if (k !== SyntaxKind.StringLiteral && k !== SyntaxKind.NoSubstitutionTemplateLiteral)
|
|
48
|
+
continue;
|
|
49
|
+
const raw = init.getLiteralText();
|
|
50
|
+
// `handler: 'src/handlers/foo.handler'` — strip the trailing export name.
|
|
51
|
+
// For AWS Lambda the convention is `<file>.<exportedFn>`; we want the
|
|
52
|
+
// file, not the export.
|
|
53
|
+
const filePart = raw.replace(/\.[A-Za-z_$][\w$]*$/, '');
|
|
54
|
+
const resolved = resolveEntryString(workspaceRoot, sourceFileDir, filePart);
|
|
55
|
+
if (resolved)
|
|
56
|
+
accumulator.add(resolved);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// SST / Serverless `routes: { 'GET /foo': 'src/routes/foo.handler' }` — pick
|
|
60
|
+
// string values whose lexical position is a value in a routes-shaped object.
|
|
61
|
+
for (const obj of sourceFile.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression)) {
|
|
62
|
+
const parent = obj.getParent();
|
|
63
|
+
const parentName = inferPropertyOwnerName(parent);
|
|
64
|
+
if (parentName !== 'routes')
|
|
65
|
+
continue;
|
|
66
|
+
for (const prop of obj.getProperties()) {
|
|
67
|
+
if (prop.getKind() !== SyntaxKind.PropertyAssignment)
|
|
68
|
+
continue;
|
|
69
|
+
const pa = prop;
|
|
70
|
+
const init = pa.getInitializer();
|
|
71
|
+
if (!init)
|
|
72
|
+
continue;
|
|
73
|
+
const k = init.getKind();
|
|
74
|
+
if (k !== SyntaxKind.StringLiteral && k !== SyntaxKind.NoSubstitutionTemplateLiteral)
|
|
75
|
+
continue;
|
|
76
|
+
const raw = init.getLiteralText();
|
|
77
|
+
const filePart = raw.replace(/\.[A-Za-z_$][\w$]*$/, '');
|
|
78
|
+
const resolved = resolveEntryString(workspaceRoot, sourceFileDir, filePart);
|
|
79
|
+
if (resolved)
|
|
80
|
+
accumulator.add(resolved);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** Walk up the parent chain looking for the PropertyAssignment that holds this object literal. */
|
|
85
|
+
function inferPropertyOwnerName(node) {
|
|
86
|
+
let cur = node;
|
|
87
|
+
for (let i = 0; cur && i < 4; i++) {
|
|
88
|
+
if (cur.getKind && cur.getKind() === SyntaxKind.PropertyAssignment && cur.getName) {
|
|
89
|
+
return cur.getName();
|
|
90
|
+
}
|
|
91
|
+
cur = cur.getParent ? cur.getParent() : undefined;
|
|
92
|
+
}
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Resolve a CDK/SST entry string to a workspace-relative file path. The
|
|
97
|
+
* string is typically project-relative (`src/handlers/foo.ts`) but may be
|
|
98
|
+
* relative to the file declaring the construct (`./foo.ts`).
|
|
99
|
+
*/
|
|
100
|
+
function resolveEntryString(workspaceRoot, sourceFileDir, raw) {
|
|
101
|
+
const trimmed = raw.trim();
|
|
102
|
+
if (!trimmed)
|
|
103
|
+
return null;
|
|
104
|
+
const candidates = [];
|
|
105
|
+
const isRelative = trimmed.startsWith('.') || trimmed.startsWith('/');
|
|
106
|
+
if (isRelative) {
|
|
107
|
+
candidates.push(path.resolve(sourceFileDir, trimmed));
|
|
108
|
+
}
|
|
109
|
+
// Project-relative form is by far the most common in CDK projects.
|
|
110
|
+
candidates.push(path.resolve(workspaceRoot, trimmed));
|
|
111
|
+
candidates.push(path.resolve(workspaceRoot, 'src', trimmed));
|
|
112
|
+
const extensions = ['', '.ts', '.tsx', '/index.ts', '/index.tsx'];
|
|
113
|
+
for (const base of candidates) {
|
|
114
|
+
for (const ext of extensions) {
|
|
115
|
+
const abs = `${base}${ext}`;
|
|
116
|
+
if (fs.existsSync(abs) && fs.statSync(abs).isFile()) {
|
|
117
|
+
return path.relative(workspaceRoot, abs);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=iac-entries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iac-entries.js","sourceRoot":"","sources":["../../src/graph/iac-entries.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type TsconfigPaths } from './tsconfig-paths.js';
|
|
2
|
+
/**
|
|
3
|
+
* File-level import graph.
|
|
4
|
+
*
|
|
5
|
+
* A directed edge `a → b` means "file a imports something from file b". The
|
|
6
|
+
* graph is used by the dead-module detector to find files unreachable from
|
|
7
|
+
* any entry point.
|
|
8
|
+
*
|
|
9
|
+
* Edges and node identities are workspace-relative POSIX paths so the graph
|
|
10
|
+
* is stable across machines and easy to serialise.
|
|
11
|
+
*/
|
|
12
|
+
export interface ImportGraph {
|
|
13
|
+
/** All workspace files known to the graph. */
|
|
14
|
+
nodes: Set<string>;
|
|
15
|
+
/** Outgoing edges keyed by source file. */
|
|
16
|
+
outgoing: Map<string, Set<string>>;
|
|
17
|
+
/** Incoming edges keyed by target file. */
|
|
18
|
+
incoming: Map<string, Set<string>>;
|
|
19
|
+
}
|
|
20
|
+
export interface ImportRecord {
|
|
21
|
+
/** Source file (workspace-relative). */
|
|
22
|
+
source: string;
|
|
23
|
+
/** Logical workspace name of the source file in multi-workspace mode. */
|
|
24
|
+
sourceWorkspace?: string;
|
|
25
|
+
/** Resolved target file (workspace-relative) if the specifier resolved to a workspace path, else null. */
|
|
26
|
+
target: string | null;
|
|
27
|
+
/** Workspace name of the resolved target when the import crossed a workspace boundary. */
|
|
28
|
+
targetWorkspace?: string;
|
|
29
|
+
/** Raw specifier as written in the import (e.g. `'./utils'`, `'fs'`, `'@org/pkg'`). */
|
|
30
|
+
specifier: string;
|
|
31
|
+
/** Named imports (`import { a, b as c }` → ['a', 'c']). Aliases recorded as the local name. */
|
|
32
|
+
namedImports: string[];
|
|
33
|
+
/** Default import local name (`import Foo from ...`). */
|
|
34
|
+
defaultImport?: string;
|
|
35
|
+
/** Namespace alias (`import * as ns from ...`). When set, every export of the target is consumed. */
|
|
36
|
+
namespaceAlias?: string;
|
|
37
|
+
/** True when this record came from `export ... from '...'` (re-export). */
|
|
38
|
+
isReExport: boolean;
|
|
39
|
+
/** True for `export * from '...'` — every export of the target propagates. */
|
|
40
|
+
isStarReExport: boolean;
|
|
41
|
+
/** Original exported names mentioned in the re-export (`export { a as b } from` → ['a']). */
|
|
42
|
+
reExportNames?: string[];
|
|
43
|
+
}
|
|
44
|
+
export declare function buildImportGraph(records: ImportRecord[]): ImportGraph;
|
|
45
|
+
export declare function resolveImport(workspaceRoot: string, sourceFile: string, specifier: string, tsconfigPaths?: TsconfigPaths | null): string | null;
|
|
46
|
+
/** BFS reachability from a set of entry-point files. Returns the reachable set. */
|
|
47
|
+
export declare function reachableFrom(graph: ImportGraph, entryPoints: Iterable<string>): Set<string>;
|
|
48
|
+
//# sourceMappingURL=import-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-graph.d.ts","sourceRoot":"","sources":["../../src/graph/import-graph.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE/E;;;;;;;;;GASG;AACH,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,2CAA2C;IAC3C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACnC,2CAA2C;IAC3C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0GAA0G;IAC1G,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,0FAA0F;IAC1F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uFAAuF;IACvF,SAAS,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qGAAqG;IACrG,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,UAAU,EAAE,OAAO,CAAC;IACpB,8EAA8E;IAC9E,cAAc,EAAE,OAAO,CAAC;IACxB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,WAAW,CAarE;AAUD,wBAAgB,aAAa,CAC3B,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,GACnC,MAAM,GAAG,IAAI,CAuCf;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAoB5F"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { resolveTsconfigAlias } from './tsconfig-paths.js';
|
|
4
|
+
export function buildImportGraph(records) {
|
|
5
|
+
const nodes = new Set();
|
|
6
|
+
const outgoing = new Map();
|
|
7
|
+
const incoming = new Map();
|
|
8
|
+
for (const r of records) {
|
|
9
|
+
nodes.add(r.source);
|
|
10
|
+
if (!r.target)
|
|
11
|
+
continue;
|
|
12
|
+
nodes.add(r.target);
|
|
13
|
+
addEdge(outgoing, r.source, r.target);
|
|
14
|
+
addEdge(incoming, r.target, r.source);
|
|
15
|
+
}
|
|
16
|
+
return { nodes, outgoing, incoming };
|
|
17
|
+
}
|
|
18
|
+
function addEdge(map, from, to) {
|
|
19
|
+
const s = map.get(from) ?? new Set();
|
|
20
|
+
s.add(to);
|
|
21
|
+
map.set(from, s);
|
|
22
|
+
}
|
|
23
|
+
// Resolve TS import specifier → workspace-relative path, or null for
|
|
24
|
+
// node_modules / virtual. Tries relative, absolute, then tsconfig paths aliases.
|
|
25
|
+
export function resolveImport(workspaceRoot, sourceFile, specifier, tsconfigPaths) {
|
|
26
|
+
const sourceAbs = path.isAbsolute(sourceFile)
|
|
27
|
+
? sourceFile
|
|
28
|
+
: path.join(workspaceRoot, sourceFile);
|
|
29
|
+
// Relative + absolute path resolution path.
|
|
30
|
+
if (specifier.startsWith('.') || specifier.startsWith('/')) {
|
|
31
|
+
const baseDir = path.dirname(sourceAbs);
|
|
32
|
+
const target = specifier.startsWith('/')
|
|
33
|
+
? specifier
|
|
34
|
+
: path.resolve(baseDir, specifier);
|
|
35
|
+
const candidates = [
|
|
36
|
+
target,
|
|
37
|
+
`${target}.ts`,
|
|
38
|
+
`${target}.tsx`,
|
|
39
|
+
path.join(target, 'index.ts'),
|
|
40
|
+
path.join(target, 'index.tsx'),
|
|
41
|
+
`${target}.d.ts`,
|
|
42
|
+
path.join(target, 'index.d.ts'),
|
|
43
|
+
];
|
|
44
|
+
if (target.endsWith('.js')) {
|
|
45
|
+
candidates.push(target.slice(0, -3) + '.ts', target.slice(0, -3) + '.tsx');
|
|
46
|
+
}
|
|
47
|
+
for (const c of candidates) {
|
|
48
|
+
if (fs.existsSync(c) && fs.statSync(c).isFile()) {
|
|
49
|
+
return path.relative(workspaceRoot, c);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
// Bare specifier: try tsconfig path aliases (`@/foo`, `~/bar`, `@app/lib`).
|
|
55
|
+
if (tsconfigPaths) {
|
|
56
|
+
const hit = resolveTsconfigAlias(tsconfigPaths, specifier);
|
|
57
|
+
if (hit)
|
|
58
|
+
return path.relative(workspaceRoot, hit);
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
/** BFS reachability from a set of entry-point files. Returns the reachable set. */
|
|
63
|
+
export function reachableFrom(graph, entryPoints) {
|
|
64
|
+
const reachable = new Set();
|
|
65
|
+
const queue = [];
|
|
66
|
+
for (const e of entryPoints) {
|
|
67
|
+
if (graph.nodes.has(e) && !reachable.has(e)) {
|
|
68
|
+
reachable.add(e);
|
|
69
|
+
queue.push(e);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
while (queue.length > 0) {
|
|
73
|
+
const cur = queue.shift();
|
|
74
|
+
const out = graph.outgoing.get(cur);
|
|
75
|
+
if (!out)
|
|
76
|
+
continue;
|
|
77
|
+
for (const next of out) {
|
|
78
|
+
if (reachable.has(next))
|
|
79
|
+
continue;
|
|
80
|
+
reachable.add(next);
|
|
81
|
+
queue.push(next);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return reachable;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=import-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-graph.js","sourceRoot":"","sources":["../../src/graph/import-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monorepo-detect.d.ts","sourceRoot":"","sources":["../../src/graph/monorepo-detect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAKpD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,GAAG,IAAI,CAoFrF"}
|