@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.
Files changed (269) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +141 -0
  3. package/dist/adapters/llm.d.ts +68 -0
  4. package/dist/adapters/llm.d.ts.map +1 -0
  5. package/dist/adapters/llm.js +189 -0
  6. package/dist/adapters/llm.js.map +1 -0
  7. package/dist/config.d.ts +37 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +81 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/detector-registry.d.ts +32 -0
  12. package/dist/detector-registry.d.ts.map +1 -0
  13. package/dist/detector-registry.js +74 -0
  14. package/dist/detector-registry.js.map +1 -0
  15. package/dist/detectors/api-race.d.ts +6 -0
  16. package/dist/detectors/api-race.d.ts.map +1 -0
  17. package/dist/detectors/api-race.js +222 -0
  18. package/dist/detectors/api-race.js.map +1 -0
  19. package/dist/detectors/bad-config.d.ts +6 -0
  20. package/dist/detectors/bad-config.d.ts.map +1 -0
  21. package/dist/detectors/bad-config.js +529 -0
  22. package/dist/detectors/bad-config.js.map +1 -0
  23. package/dist/detectors/console-log-prod.d.ts +6 -0
  24. package/dist/detectors/console-log-prod.d.ts.map +1 -0
  25. package/dist/detectors/console-log-prod.js +72 -0
  26. package/dist/detectors/console-log-prod.js.map +1 -0
  27. package/dist/detectors/dead-api.d.ts +10 -0
  28. package/dist/detectors/dead-api.d.ts.map +1 -0
  29. package/dist/detectors/dead-api.js +115 -0
  30. package/dist/detectors/dead-api.js.map +1 -0
  31. package/dist/detectors/dead-export.d.ts +12 -0
  32. package/dist/detectors/dead-export.d.ts.map +1 -0
  33. package/dist/detectors/dead-export.js +140 -0
  34. package/dist/detectors/dead-export.js.map +1 -0
  35. package/dist/detectors/dead-handler.d.ts +12 -0
  36. package/dist/detectors/dead-handler.d.ts.map +1 -0
  37. package/dist/detectors/dead-handler.js +40 -0
  38. package/dist/detectors/dead-handler.js.map +1 -0
  39. package/dist/detectors/dead-module.d.ts +14 -0
  40. package/dist/detectors/dead-module.d.ts.map +1 -0
  41. package/dist/detectors/dead-module.js +50 -0
  42. package/dist/detectors/dead-module.js.map +1 -0
  43. package/dist/detectors/deep-nesting.d.ts +12 -0
  44. package/dist/detectors/deep-nesting.d.ts.map +1 -0
  45. package/dist/detectors/deep-nesting.js +133 -0
  46. package/dist/detectors/deep-nesting.js.map +1 -0
  47. package/dist/detectors/duplicate-function.d.ts +9 -0
  48. package/dist/detectors/duplicate-function.d.ts.map +1 -0
  49. package/dist/detectors/duplicate-function.js +199 -0
  50. package/dist/detectors/duplicate-function.js.map +1 -0
  51. package/dist/detectors/duplicate-type.d.ts +9 -0
  52. package/dist/detectors/duplicate-type.d.ts.map +1 -0
  53. package/dist/detectors/duplicate-type.js +166 -0
  54. package/dist/detectors/duplicate-type.js.map +1 -0
  55. package/dist/detectors/hot-hub-file.d.ts +11 -0
  56. package/dist/detectors/hot-hub-file.d.ts.map +1 -0
  57. package/dist/detectors/hot-hub-file.js +42 -0
  58. package/dist/detectors/hot-hub-file.js.map +1 -0
  59. package/dist/detectors/long-file.d.ts +12 -0
  60. package/dist/detectors/long-file.d.ts.map +1 -0
  61. package/dist/detectors/long-file.js +82 -0
  62. package/dist/detectors/long-file.js.map +1 -0
  63. package/dist/detectors/long-function.d.ts +12 -0
  64. package/dist/detectors/long-function.d.ts.map +1 -0
  65. package/dist/detectors/long-function.js +45 -0
  66. package/dist/detectors/long-function.js.map +1 -0
  67. package/dist/detectors/magic-numbers.d.ts +10 -0
  68. package/dist/detectors/magic-numbers.d.ts.map +1 -0
  69. package/dist/detectors/magic-numbers.js +332 -0
  70. package/dist/detectors/magic-numbers.js.map +1 -0
  71. package/dist/detectors/mutable-globals.d.ts +6 -0
  72. package/dist/detectors/mutable-globals.d.ts.map +1 -0
  73. package/dist/detectors/mutable-globals.js +95 -0
  74. package/dist/detectors/mutable-globals.js.map +1 -0
  75. package/dist/detectors/mutation.d.ts +11 -0
  76. package/dist/detectors/mutation.d.ts.map +1 -0
  77. package/dist/detectors/mutation.js +397 -0
  78. package/dist/detectors/mutation.js.map +1 -0
  79. package/dist/detectors/public-any.d.ts +6 -0
  80. package/dist/detectors/public-any.d.ts.map +1 -0
  81. package/dist/detectors/public-any.js +52 -0
  82. package/dist/detectors/public-any.js.map +1 -0
  83. package/dist/detectors/race-condition.d.ts +6 -0
  84. package/dist/detectors/race-condition.d.ts.map +1 -0
  85. package/dist/detectors/race-condition.js +608 -0
  86. package/dist/detectors/race-condition.js.map +1 -0
  87. package/dist/detectors/shared-db-write.d.ts +6 -0
  88. package/dist/detectors/shared-db-write.d.ts.map +1 -0
  89. package/dist/detectors/shared-db-write.js +656 -0
  90. package/dist/detectors/shared-db-write.js.map +1 -0
  91. package/dist/detectors/silent-catch.d.ts +6 -0
  92. package/dist/detectors/silent-catch.d.ts.map +1 -0
  93. package/dist/detectors/silent-catch.js +167 -0
  94. package/dist/detectors/silent-catch.js.map +1 -0
  95. package/dist/detectors/similar-functions.d.ts +15 -0
  96. package/dist/detectors/similar-functions.d.ts.map +1 -0
  97. package/dist/detectors/similar-functions.js +334 -0
  98. package/dist/detectors/similar-functions.js.map +1 -0
  99. package/dist/detectors/skip-tests.d.ts +6 -0
  100. package/dist/detectors/skip-tests.d.ts.map +1 -0
  101. package/dist/detectors/skip-tests.js +69 -0
  102. package/dist/detectors/skip-tests.js.map +1 -0
  103. package/dist/detectors/todo-comments.d.ts +29 -0
  104. package/dist/detectors/todo-comments.d.ts.map +1 -0
  105. package/dist/detectors/todo-comments.js +154 -0
  106. package/dist/detectors/todo-comments.js.map +1 -0
  107. package/dist/detectors/unused-deps.d.ts +8 -0
  108. package/dist/detectors/unused-deps.d.ts.map +1 -0
  109. package/dist/detectors/unused-deps.js +115 -0
  110. package/dist/detectors/unused-deps.js.map +1 -0
  111. package/dist/extraction/api-race-confirmer.d.ts +31 -0
  112. package/dist/extraction/api-race-confirmer.d.ts.map +1 -0
  113. package/dist/extraction/api-race-confirmer.js +110 -0
  114. package/dist/extraction/api-race-confirmer.js.map +1 -0
  115. package/dist/extraction/llm-confirmer.d.ts +25 -0
  116. package/dist/extraction/llm-confirmer.d.ts.map +1 -0
  117. package/dist/extraction/llm-confirmer.js +118 -0
  118. package/dist/extraction/llm-confirmer.js.map +1 -0
  119. package/dist/extraction/mutation-confirmer.d.ts +30 -0
  120. package/dist/extraction/mutation-confirmer.d.ts.map +1 -0
  121. package/dist/extraction/mutation-confirmer.js +73 -0
  122. package/dist/extraction/mutation-confirmer.js.map +1 -0
  123. package/dist/extraction/prompt-chunking.d.ts +37 -0
  124. package/dist/extraction/prompt-chunking.d.ts.map +1 -0
  125. package/dist/extraction/prompt-chunking.js +61 -0
  126. package/dist/extraction/prompt-chunking.js.map +1 -0
  127. package/dist/extraction/race-confirmer.d.ts +28 -0
  128. package/dist/extraction/race-confirmer.d.ts.map +1 -0
  129. package/dist/extraction/race-confirmer.js +68 -0
  130. package/dist/extraction/race-confirmer.js.map +1 -0
  131. package/dist/extraction/shared-db-write-confirmer.d.ts +31 -0
  132. package/dist/extraction/shared-db-write-confirmer.d.ts.map +1 -0
  133. package/dist/extraction/shared-db-write-confirmer.js +141 -0
  134. package/dist/extraction/shared-db-write-confirmer.js.map +1 -0
  135. package/dist/extraction/triage-confirmer.d.ts +59 -0
  136. package/dist/extraction/triage-confirmer.d.ts.map +1 -0
  137. package/dist/extraction/triage-confirmer.js +104 -0
  138. package/dist/extraction/triage-confirmer.js.map +1 -0
  139. package/dist/graph/cfg.d.ts +45 -0
  140. package/dist/graph/cfg.d.ts.map +1 -0
  141. package/dist/graph/cfg.js +198 -0
  142. package/dist/graph/cfg.js.map +1 -0
  143. package/dist/graph/decorator-entries.d.ts +2 -0
  144. package/dist/graph/decorator-entries.d.ts.map +1 -0
  145. package/dist/graph/decorator-entries.js +89 -0
  146. package/dist/graph/decorator-entries.js.map +1 -0
  147. package/dist/graph/entry-points.d.ts +12 -0
  148. package/dist/graph/entry-points.d.ts.map +1 -0
  149. package/dist/graph/entry-points.js +282 -0
  150. package/dist/graph/entry-points.js.map +1 -0
  151. package/dist/graph/handler-conventions.d.ts +2 -0
  152. package/dist/graph/handler-conventions.d.ts.map +1 -0
  153. package/dist/graph/handler-conventions.js +26 -0
  154. package/dist/graph/handler-conventions.js.map +1 -0
  155. package/dist/graph/iac-entries.d.ts +2 -0
  156. package/dist/graph/iac-entries.d.ts.map +1 -0
  157. package/dist/graph/iac-entries.js +123 -0
  158. package/dist/graph/iac-entries.js.map +1 -0
  159. package/dist/graph/import-graph.d.ts +48 -0
  160. package/dist/graph/import-graph.d.ts.map +1 -0
  161. package/dist/graph/import-graph.js +86 -0
  162. package/dist/graph/import-graph.js.map +1 -0
  163. package/dist/graph/monorepo-detect.d.ts +3 -0
  164. package/dist/graph/monorepo-detect.d.ts.map +1 -0
  165. package/dist/graph/monorepo-detect.js +166 -0
  166. package/dist/graph/monorepo-detect.js.map +1 -0
  167. package/dist/graph/tsconfig-paths.d.ts +23 -0
  168. package/dist/graph/tsconfig-paths.d.ts.map +1 -0
  169. package/dist/graph/tsconfig-paths.js +217 -0
  170. package/dist/graph/tsconfig-paths.js.map +1 -0
  171. package/dist/multi-workspace-scanner.d.ts +13 -0
  172. package/dist/multi-workspace-scanner.d.ts.map +1 -0
  173. package/dist/multi-workspace-scanner.js +130 -0
  174. package/dist/multi-workspace-scanner.js.map +1 -0
  175. package/dist/normalizers/type-normalizer.d.ts +16 -0
  176. package/dist/normalizers/type-normalizer.d.ts.map +1 -0
  177. package/dist/normalizers/type-normalizer.js +189 -0
  178. package/dist/normalizers/type-normalizer.js.map +1 -0
  179. package/dist/parsers/typescript-parser.d.ts +57 -0
  180. package/dist/parsers/typescript-parser.d.ts.map +1 -0
  181. package/dist/parsers/typescript-parser.js +502 -0
  182. package/dist/parsers/typescript-parser.js.map +1 -0
  183. package/dist/reporter/json-reporter.d.ts +12 -0
  184. package/dist/reporter/json-reporter.d.ts.map +1 -0
  185. package/dist/reporter/json-reporter.js +28 -0
  186. package/dist/reporter/json-reporter.js.map +1 -0
  187. package/dist/reporter/markdown-reporter.d.ts +11 -0
  188. package/dist/reporter/markdown-reporter.d.ts.map +1 -0
  189. package/dist/reporter/markdown-reporter.js +77 -0
  190. package/dist/reporter/markdown-reporter.js.map +1 -0
  191. package/dist/rothunter.d.ts +125 -0
  192. package/dist/rothunter.d.ts.map +1 -0
  193. package/dist/rothunter.js +1038 -0
  194. package/dist/rothunter.js.map +1 -0
  195. package/dist/server/false-positives.d.ts +34 -0
  196. package/dist/server/false-positives.d.ts.map +1 -0
  197. package/dist/server/false-positives.js +85 -0
  198. package/dist/server/false-positives.js.map +1 -0
  199. package/dist/server/index.d.ts +2 -0
  200. package/dist/server/index.d.ts.map +1 -0
  201. package/dist/server/index.js +1529 -0
  202. package/dist/server/index.js.map +1 -0
  203. package/dist/server/marked-to-fix.d.ts +16 -0
  204. package/dist/server/marked-to-fix.d.ts.map +1 -0
  205. package/dist/server/marked-to-fix.js +36 -0
  206. package/dist/server/marked-to-fix.js.map +1 -0
  207. package/dist/server/scan-store.d.ts +147 -0
  208. package/dist/server/scan-store.d.ts.map +1 -0
  209. package/dist/server/scan-store.js +291 -0
  210. package/dist/server/scan-store.js.map +1 -0
  211. package/dist/server/settings-store.d.ts +28 -0
  212. package/dist/server/settings-store.d.ts.map +1 -0
  213. package/dist/server/settings-store.js +46 -0
  214. package/dist/server/settings-store.js.map +1 -0
  215. package/dist/server/workspace-store.d.ts +39 -0
  216. package/dist/server/workspace-store.d.ts.map +1 -0
  217. package/dist/server/workspace-store.js +108 -0
  218. package/dist/server/workspace-store.js.map +1 -0
  219. package/dist/types/detector-input.d.ts +37 -0
  220. package/dist/types/detector-input.d.ts.map +1 -0
  221. package/dist/types/detector-input.js +2 -0
  222. package/dist/types/detector-input.js.map +1 -0
  223. package/dist/types.d.ts +110 -0
  224. package/dist/types.d.ts.map +1 -0
  225. package/dist/types.js +2 -0
  226. package/dist/types.js.map +1 -0
  227. package/dist/utils/clustering.d.ts +14 -0
  228. package/dist/utils/clustering.d.ts.map +1 -0
  229. package/dist/utils/clustering.js +56 -0
  230. package/dist/utils/clustering.js.map +1 -0
  231. package/dist/utils/gitignore.d.ts +32 -0
  232. package/dist/utils/gitignore.d.ts.map +1 -0
  233. package/dist/utils/gitignore.js +122 -0
  234. package/dist/utils/gitignore.js.map +1 -0
  235. package/dist/utils/hash.d.ts +11 -0
  236. package/dist/utils/hash.d.ts.map +1 -0
  237. package/dist/utils/hash.js +14 -0
  238. package/dist/utils/hash.js.map +1 -0
  239. package/dist/utils/ignore-annotation.d.ts +28 -0
  240. package/dist/utils/ignore-annotation.d.ts.map +1 -0
  241. package/dist/utils/ignore-annotation.js +46 -0
  242. package/dist/utils/ignore-annotation.js.map +1 -0
  243. package/dist/utils/llm-json.d.ts +2 -0
  244. package/dist/utils/llm-json.d.ts.map +1 -0
  245. package/dist/utils/llm-json.js +53 -0
  246. package/dist/utils/llm-json.js.map +1 -0
  247. package/dist/utils/logger.d.ts +3 -0
  248. package/dist/utils/logger.d.ts.map +1 -0
  249. package/dist/utils/logger.js +4 -0
  250. package/dist/utils/logger.js.map +1 -0
  251. package/dist/utils/project-conventions.d.ts +2 -0
  252. package/dist/utils/project-conventions.d.ts.map +1 -0
  253. package/dist/utils/project-conventions.js +108 -0
  254. package/dist/utils/project-conventions.js.map +1 -0
  255. package/dist/utils/regex.d.ts +9 -0
  256. package/dist/utils/regex.d.ts.map +1 -0
  257. package/dist/utils/regex.js +11 -0
  258. package/dist/utils/regex.js.map +1 -0
  259. package/dist/utils/snippet.d.ts +20 -0
  260. package/dist/utils/snippet.d.ts.map +1 -0
  261. package/dist/utils/snippet.js +28 -0
  262. package/dist/utils/snippet.js.map +1 -0
  263. package/dist/utils/source-reader.d.ts +19 -0
  264. package/dist/utils/source-reader.d.ts.map +1 -0
  265. package/dist/utils/source-reader.js +32 -0
  266. package/dist/utils/source-reader.js.map +1 -0
  267. package/logo.png +0 -0
  268. package/package.json +92 -0
  269. 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,2 @@
1
+ export declare function isHandlerConventionFile(file: string): boolean;
2
+ //# sourceMappingURL=handler-conventions.d.ts.map
@@ -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,2 @@
1
+ export declare function resolveIacEntryFiles(workspaceRoot: string, files: ReadonlyArray<string>): Set<string>;
2
+ //# sourceMappingURL=iac-entries.d.ts.map
@@ -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,3 @@
1
+ import type { WorkspaceConfig } from '../config.js';
2
+ export declare function discoverMonorepoWorkspaces(repoRoot: string): WorkspaceConfig[] | null;
3
+ //# sourceMappingURL=monorepo-detect.d.ts.map
@@ -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"}