@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,166 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
// Auto-detect monorepo layout from package.json#workspaces (npm/yarn/bun/
|
|
4
|
+
// turbo/lerna), pnpm-workspace.yaml, nx.json#workspaceLayout. Simple globs
|
|
5
|
+
// (dir/*) only — complex patterns require explicit rothunter.config.json.
|
|
6
|
+
export function discoverMonorepoWorkspaces(repoRoot) {
|
|
7
|
+
const dirs = new Set();
|
|
8
|
+
// ---- package.json `workspaces` -------------------------------------------
|
|
9
|
+
const rootPkgPath = path.join(repoRoot, 'package.json');
|
|
10
|
+
if (fs.existsSync(rootPkgPath)) {
|
|
11
|
+
try {
|
|
12
|
+
const pkg = JSON.parse(fs.readFileSync(rootPkgPath, 'utf-8'));
|
|
13
|
+
const list = Array.isArray(pkg.workspaces)
|
|
14
|
+
? pkg.workspaces
|
|
15
|
+
: Array.isArray(pkg.workspaces?.packages)
|
|
16
|
+
? pkg.workspaces.packages
|
|
17
|
+
: [];
|
|
18
|
+
for (const pattern of list) {
|
|
19
|
+
for (const d of expandWorkspacePattern(repoRoot, pattern))
|
|
20
|
+
dirs.add(d);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// unreadable package.json — fall through
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// ---- pnpm-workspace.yaml -------------------------------------------------
|
|
28
|
+
const pnpmPath = path.join(repoRoot, 'pnpm-workspace.yaml');
|
|
29
|
+
if (fs.existsSync(pnpmPath)) {
|
|
30
|
+
try {
|
|
31
|
+
const yaml = fs.readFileSync(pnpmPath, 'utf-8');
|
|
32
|
+
for (const pattern of parsePnpmWorkspacePackages(yaml)) {
|
|
33
|
+
for (const d of expandWorkspacePattern(repoRoot, pattern))
|
|
34
|
+
dirs.add(d);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// ignore
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// ---- nx.json `workspaceLayout` -------------------------------------------
|
|
42
|
+
const nxPath = path.join(repoRoot, 'nx.json');
|
|
43
|
+
if (fs.existsSync(nxPath)) {
|
|
44
|
+
try {
|
|
45
|
+
const nx = JSON.parse(fs.readFileSync(nxPath, 'utf-8'));
|
|
46
|
+
const roots = [nx.workspaceLayout?.libsDir, nx.workspaceLayout?.appsDir].filter((s) => typeof s === 'string');
|
|
47
|
+
for (const r of roots) {
|
|
48
|
+
for (const d of expandWorkspacePattern(repoRoot, `${r}/*`))
|
|
49
|
+
dirs.add(d);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// ignore
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Filter to directories that have their own package.json (the canonical
|
|
57
|
+
// "this is a workspace" signal). Skip the repo root itself.
|
|
58
|
+
const workspaces = [];
|
|
59
|
+
for (const dir of dirs) {
|
|
60
|
+
if (path.resolve(dir) === path.resolve(repoRoot))
|
|
61
|
+
continue;
|
|
62
|
+
const dirPkg = path.join(dir, 'package.json');
|
|
63
|
+
if (!fs.existsSync(dirPkg))
|
|
64
|
+
continue;
|
|
65
|
+
let name;
|
|
66
|
+
let packageName;
|
|
67
|
+
try {
|
|
68
|
+
const parsed = JSON.parse(fs.readFileSync(dirPkg, 'utf-8'));
|
|
69
|
+
packageName = typeof parsed.name === 'string' ? parsed.name : undefined;
|
|
70
|
+
name = packageName?.replace(/^@[^/]+\//, '') || path.basename(dir);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
name = path.basename(dir);
|
|
74
|
+
}
|
|
75
|
+
if (!name)
|
|
76
|
+
continue;
|
|
77
|
+
workspaces.push({
|
|
78
|
+
rootAbs: path.resolve(dir),
|
|
79
|
+
name,
|
|
80
|
+
packageName,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (workspaces.length === 0)
|
|
84
|
+
return null;
|
|
85
|
+
// Deduplicate by `name` (could collide if two siblings produce the same
|
|
86
|
+
// basename after the npm-scope strip); the second one wins via Map.
|
|
87
|
+
const byName = new Map();
|
|
88
|
+
for (const w of workspaces)
|
|
89
|
+
byName.set(w.name, w);
|
|
90
|
+
return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Expand a workspace pattern relative to repoRoot.
|
|
94
|
+
*
|
|
95
|
+
* Supports two shapes:
|
|
96
|
+
* - `packages/foo` — concrete directory; included if it exists
|
|
97
|
+
* - `packages/*` — every direct subdirectory of `packages/`
|
|
98
|
+
*
|
|
99
|
+
* `**` and other complex globs are deliberately rejected; users with that
|
|
100
|
+
* level of branching should provide an explicit rothunter.config.json.
|
|
101
|
+
*/
|
|
102
|
+
function expandWorkspacePattern(repoRoot, pattern) {
|
|
103
|
+
const trimmed = pattern.trim();
|
|
104
|
+
if (!trimmed)
|
|
105
|
+
return [];
|
|
106
|
+
// Concrete path (no glob).
|
|
107
|
+
if (!trimmed.includes('*')) {
|
|
108
|
+
const abs = path.resolve(repoRoot, trimmed);
|
|
109
|
+
return fs.existsSync(abs) && fs.statSync(abs).isDirectory() ? [abs] : [];
|
|
110
|
+
}
|
|
111
|
+
// Single trailing `/*` shape.
|
|
112
|
+
if (trimmed.endsWith('/*') && !trimmed.includes('**')) {
|
|
113
|
+
const baseDir = path.resolve(repoRoot, trimmed.slice(0, -2));
|
|
114
|
+
if (!fs.existsSync(baseDir) || !fs.statSync(baseDir).isDirectory())
|
|
115
|
+
return [];
|
|
116
|
+
return fs
|
|
117
|
+
.readdirSync(baseDir, { withFileTypes: true })
|
|
118
|
+
.filter((d) => d.isDirectory())
|
|
119
|
+
.map((d) => path.join(baseDir, d.name));
|
|
120
|
+
}
|
|
121
|
+
// Anything else: skip with a noisy console warning (debugging help) but
|
|
122
|
+
// don't crash the scan.
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Minimal pnpm-workspace.yaml parser — pulls strings under a `packages:`
|
|
127
|
+
* list. We don't bring in a full YAML parser; the pnpm-workspace shape is
|
|
128
|
+
* narrow enough to handle directly.
|
|
129
|
+
*
|
|
130
|
+
* packages:
|
|
131
|
+
* - "apps/*"
|
|
132
|
+
* - "packages/*"
|
|
133
|
+
* - "!packages/legacy" <-- excludes; we ignore the `!` prefix entries.
|
|
134
|
+
*/
|
|
135
|
+
function parsePnpmWorkspacePackages(yaml) {
|
|
136
|
+
const out = [];
|
|
137
|
+
const lines = yaml.split(/\r?\n/);
|
|
138
|
+
let inPackages = false;
|
|
139
|
+
for (const raw of lines) {
|
|
140
|
+
const line = raw.replace(/#.*$/, '').replace(/\r$/, '');
|
|
141
|
+
if (/^\s*packages\s*:\s*$/.test(line)) {
|
|
142
|
+
inPackages = true;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (inPackages) {
|
|
146
|
+
const trim = line.trim();
|
|
147
|
+
// End of packages list when we hit another top-level key.
|
|
148
|
+
if (line.length > 0 && !line.startsWith(' ') && !line.startsWith('\t')) {
|
|
149
|
+
inPackages = false;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (!trim.startsWith('-'))
|
|
153
|
+
continue;
|
|
154
|
+
let value = trim.slice(1).trim();
|
|
155
|
+
// Strip surrounding quotes if present.
|
|
156
|
+
value = value.replace(/^["']|["']$/g, '');
|
|
157
|
+
if (!value)
|
|
158
|
+
continue;
|
|
159
|
+
if (value.startsWith('!'))
|
|
160
|
+
continue; // exclusion patterns
|
|
161
|
+
out.push(value);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return out;
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=monorepo-detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monorepo-detect.js","sourceRoot":"","sources":["../../src/graph/monorepo-detect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface TsconfigPaths {
|
|
2
|
+
/** Absolute base directory derived from baseUrl, or workspaceRoot. */
|
|
3
|
+
baseDir: string;
|
|
4
|
+
/** Compiled mapping: alias prefix → resolved target paths (absolute). */
|
|
5
|
+
mappings: Array<{
|
|
6
|
+
/** Either the literal alias or the prefix up to (and not including) `*`. */
|
|
7
|
+
aliasPrefix: string;
|
|
8
|
+
/** Whether the alias originally contained `*`. */
|
|
9
|
+
isWildcard: boolean;
|
|
10
|
+
/** Possible target paths to try, in priority order, absolute. */
|
|
11
|
+
targets: string[];
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export declare function loadTsconfigPaths(workspaceRoot: string): TsconfigPaths | null;
|
|
15
|
+
/**
|
|
16
|
+
* Resolve an alias specifier to an existing file on disk. Returns the
|
|
17
|
+
* absolute path or null if no mapping matched / no target existed.
|
|
18
|
+
*
|
|
19
|
+
* The `extensions` parameter mirrors the standard TS resolution candidate
|
|
20
|
+
* list (`.ts`, `.tsx`, `/index.ts`, etc).
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveTsconfigAlias(cfg: TsconfigPaths, specifier: string, extensions?: string[]): string | null;
|
|
23
|
+
//# sourceMappingURL=tsconfig-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tsconfig-paths.d.ts","sourceRoot":"","sources":["../../src/graph/tsconfig-paths.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,QAAQ,EAAE,KAAK,CAAC;QACd,4EAA4E;QAC5E,WAAW,EAAE,MAAM,CAAC;QACpB,kDAAkD;QAClD,UAAU,EAAE,OAAO,CAAC;QACpB,iEAAiE;QACjE,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC,CAAC;CACJ;AAID,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAS7E;AAoKD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,EACjB,UAAU,GAAE,MAAM,EAA2E,GAC5F,MAAM,GAAG,IAAI,CAqBf"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
const CONFIG_CANDIDATES = ['tsconfig.json', 'jsconfig.json'];
|
|
4
|
+
export function loadTsconfigPaths(workspaceRoot) {
|
|
5
|
+
for (const candidate of CONFIG_CANDIDATES) {
|
|
6
|
+
const abs = path.join(workspaceRoot, candidate);
|
|
7
|
+
if (!fs.existsSync(abs))
|
|
8
|
+
continue;
|
|
9
|
+
const merged = readMergedConfig(abs, new Set());
|
|
10
|
+
if (!merged)
|
|
11
|
+
continue;
|
|
12
|
+
return compileMappings(abs, merged, workspaceRoot);
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const MAX_EXTENDS_DEPTH = 8;
|
|
17
|
+
function readMergedConfig(configPath, visited) {
|
|
18
|
+
// Cycle guard: `visited` tracks the realpath of every config seen on the
|
|
19
|
+
// extends chain. A self-extending or A→B→A loop returns null instead of
|
|
20
|
+
// recursing forever. Depth cap is a belt-and-braces for pathological
|
|
21
|
+
// chains the cycle guard didn't catch (e.g. each step is a distinct
|
|
22
|
+
// file but the chain length is still adversarial).
|
|
23
|
+
const realPath = (() => {
|
|
24
|
+
try {
|
|
25
|
+
return fs.realpathSync(configPath);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return configPath;
|
|
29
|
+
}
|
|
30
|
+
})();
|
|
31
|
+
if (visited.has(realPath))
|
|
32
|
+
return null;
|
|
33
|
+
if (visited.size >= MAX_EXTENDS_DEPTH)
|
|
34
|
+
return null;
|
|
35
|
+
visited.add(realPath);
|
|
36
|
+
const raw = readJsonWithComments(configPath);
|
|
37
|
+
if (!raw)
|
|
38
|
+
return null;
|
|
39
|
+
if (typeof raw.extends === 'string') {
|
|
40
|
+
const parentPath = resolveExtends(configPath, raw.extends);
|
|
41
|
+
if (parentPath && fs.existsSync(parentPath)) {
|
|
42
|
+
const parent = readMergedConfig(parentPath, visited);
|
|
43
|
+
if (parent) {
|
|
44
|
+
return {
|
|
45
|
+
extends: raw.extends,
|
|
46
|
+
compilerOptions: {
|
|
47
|
+
baseUrl: raw.compilerOptions?.baseUrl ?? parent.compilerOptions?.baseUrl,
|
|
48
|
+
paths: {
|
|
49
|
+
...(parent.compilerOptions?.paths ?? {}),
|
|
50
|
+
...(raw.compilerOptions?.paths ?? {}),
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return raw;
|
|
58
|
+
}
|
|
59
|
+
function resolveExtends(configPath, extendsValue) {
|
|
60
|
+
const dir = path.dirname(configPath);
|
|
61
|
+
// Relative path
|
|
62
|
+
if (extendsValue.startsWith('.') || extendsValue.startsWith('/')) {
|
|
63
|
+
const direct = path.resolve(dir, extendsValue);
|
|
64
|
+
if (fs.existsSync(direct))
|
|
65
|
+
return direct;
|
|
66
|
+
if (fs.existsSync(`${direct}.json`))
|
|
67
|
+
return `${direct}.json`;
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
// Bare specifier — `@org/tsconfig-base` etc. Try node_modules lookup walking up.
|
|
71
|
+
let cur = dir;
|
|
72
|
+
while (cur !== path.dirname(cur)) {
|
|
73
|
+
const candidate = path.join(cur, 'node_modules', extendsValue);
|
|
74
|
+
if (fs.existsSync(candidate))
|
|
75
|
+
return candidate;
|
|
76
|
+
if (fs.existsSync(`${candidate}.json`))
|
|
77
|
+
return `${candidate}.json`;
|
|
78
|
+
cur = path.dirname(cur);
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
function readJsonWithComments(configPath) {
|
|
83
|
+
let text;
|
|
84
|
+
try {
|
|
85
|
+
text = fs.readFileSync(configPath, 'utf-8');
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
// String-aware comment + trailing-comma stripper. The naive regex
|
|
91
|
+
// `/\*[\s\S]*?\*\//` corrupts tsconfig path values like `"@/*": ["src/*"]`
|
|
92
|
+
// because `@/*` opens what the regex thinks is a comment, and `src/*"`
|
|
93
|
+
// closes it. Walk the source as a tiny state machine instead.
|
|
94
|
+
const repaired = stripJsoncTrivia(text);
|
|
95
|
+
try {
|
|
96
|
+
return JSON.parse(repaired);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function stripJsoncTrivia(text) {
|
|
103
|
+
let out = '';
|
|
104
|
+
let i = 0;
|
|
105
|
+
const n = text.length;
|
|
106
|
+
while (i < n) {
|
|
107
|
+
const ch = text[i];
|
|
108
|
+
const next = i + 1 < n ? text[i + 1] : '';
|
|
109
|
+
if (ch === '"') {
|
|
110
|
+
// Copy the entire string literal verbatim, respecting `\` escapes.
|
|
111
|
+
let j = i + 1;
|
|
112
|
+
out += '"';
|
|
113
|
+
while (j < n) {
|
|
114
|
+
const c = text[j];
|
|
115
|
+
out += c;
|
|
116
|
+
if (c === '\\' && j + 1 < n) {
|
|
117
|
+
out += text[j + 1];
|
|
118
|
+
j += 2;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (c === '"') {
|
|
122
|
+
j += 1;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
j += 1;
|
|
126
|
+
}
|
|
127
|
+
i = j;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (ch === '/' && next === '/') {
|
|
131
|
+
// Line comment — skip to end of line.
|
|
132
|
+
while (i < n && text[i] !== '\n')
|
|
133
|
+
i++;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (ch === '/' && next === '*') {
|
|
137
|
+
// Block comment — skip until `*/`.
|
|
138
|
+
i += 2;
|
|
139
|
+
while (i < n && !(text[i] === '*' && text[i + 1] === '/'))
|
|
140
|
+
i++;
|
|
141
|
+
i += 2;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (ch === ',') {
|
|
145
|
+
// Tolerate trailing commas: look ahead for the next non-whitespace.
|
|
146
|
+
let k = i + 1;
|
|
147
|
+
while (k < n && /\s/.test(text[k]))
|
|
148
|
+
k++;
|
|
149
|
+
if (k < n && (text[k] === '}' || text[k] === ']')) {
|
|
150
|
+
i = k; // drop the comma; emit the closing brace next iteration
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
out += ch;
|
|
155
|
+
i += 1;
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
function compileMappings(configPath, raw, workspaceRoot) {
|
|
160
|
+
const configDir = path.dirname(configPath);
|
|
161
|
+
const baseUrl = raw.compilerOptions?.baseUrl;
|
|
162
|
+
const baseDir = baseUrl ? path.resolve(configDir, baseUrl) : workspaceRoot;
|
|
163
|
+
const paths = raw.compilerOptions?.paths ?? {};
|
|
164
|
+
const mappings = [];
|
|
165
|
+
for (const [alias, targets] of Object.entries(paths)) {
|
|
166
|
+
const isWildcard = alias.endsWith('*');
|
|
167
|
+
const aliasPrefix = isWildcard ? alias.slice(0, -1) : alias;
|
|
168
|
+
const absTargets = targets.map((t) => path.resolve(baseDir, t));
|
|
169
|
+
mappings.push({ aliasPrefix, isWildcard, targets: absTargets });
|
|
170
|
+
}
|
|
171
|
+
// Longest-prefix-first: ensures `@/foo` doesn't accidentally win over `@/foo/bar`.
|
|
172
|
+
mappings.sort((a, b) => b.aliasPrefix.length - a.aliasPrefix.length);
|
|
173
|
+
return { baseDir, mappings };
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Resolve an alias specifier to an existing file on disk. Returns the
|
|
177
|
+
* absolute path or null if no mapping matched / no target existed.
|
|
178
|
+
*
|
|
179
|
+
* The `extensions` parameter mirrors the standard TS resolution candidate
|
|
180
|
+
* list (`.ts`, `.tsx`, `/index.ts`, etc).
|
|
181
|
+
*/
|
|
182
|
+
export function resolveTsconfigAlias(cfg, specifier, extensions = ['', '.ts', '.tsx', '/index.ts', '/index.tsx', '.d.ts', '/index.d.ts']) {
|
|
183
|
+
for (const m of cfg.mappings) {
|
|
184
|
+
if (m.isWildcard) {
|
|
185
|
+
if (!specifier.startsWith(m.aliasPrefix))
|
|
186
|
+
continue;
|
|
187
|
+
const tail = specifier.slice(m.aliasPrefix.length);
|
|
188
|
+
for (const t of m.targets) {
|
|
189
|
+
const candidate = t.endsWith('*') ? t.slice(0, -1) + tail : path.join(t, tail);
|
|
190
|
+
const hit = tryExtensions(candidate, extensions);
|
|
191
|
+
if (hit)
|
|
192
|
+
return hit;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
if (specifier !== m.aliasPrefix)
|
|
197
|
+
continue;
|
|
198
|
+
for (const t of m.targets) {
|
|
199
|
+
const hit = tryExtensions(t, extensions);
|
|
200
|
+
if (hit)
|
|
201
|
+
return hit;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// baseUrl fallback — try resolving the specifier under baseDir.
|
|
206
|
+
const baseCandidate = path.join(cfg.baseDir, specifier);
|
|
207
|
+
return tryExtensions(baseCandidate, extensions);
|
|
208
|
+
}
|
|
209
|
+
function tryExtensions(base, extensions) {
|
|
210
|
+
for (const ext of extensions) {
|
|
211
|
+
const abs = `${base}${ext}`;
|
|
212
|
+
if (fs.existsSync(abs) && fs.statSync(abs).isFile())
|
|
213
|
+
return abs;
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=tsconfig-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tsconfig-paths.js","sourceRoot":"","sources":["../../src/graph/tsconfig-paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RotHunterConfig, WorkspaceConfig } from './config.js';
|
|
2
|
+
import type { SymbolRecord } from './types.js';
|
|
3
|
+
import type { ImportRecord } from './graph/import-graph.js';
|
|
4
|
+
export interface MultiWorkspaceParseResult {
|
|
5
|
+
symbols: SymbolRecord[];
|
|
6
|
+
imports: ImportRecord[];
|
|
7
|
+
/** All workspace-relative file paths, prefixed by their workspace name (e.g. `backend/src/index.ts`). */
|
|
8
|
+
files: string[];
|
|
9
|
+
/** Workspace configs in the order they were scanned. */
|
|
10
|
+
workspaces: WorkspaceConfig[];
|
|
11
|
+
}
|
|
12
|
+
export declare function scanWorkspaces(config: RotHunterConfig): Promise<MultiWorkspaceParseResult>;
|
|
13
|
+
//# sourceMappingURL=multi-workspace-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-workspace-scanner.d.ts","sourceRoot":"","sources":["../src/multi-workspace-scanner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,yGAAyG;IACzG,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,wDAAwD;IACxD,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAKD,wBAAsB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,yBAAyB,CAAC,CA6EhG"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import * as crypto from 'node:crypto';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { TypeScriptParser } from './parsers/typescript-parser.js';
|
|
5
|
+
import { resolveImport } from './graph/import-graph.js';
|
|
6
|
+
// Parse every linked workspace; stitch cross-workspace imports by resolving
|
|
7
|
+
// bare specifiers against sibling `package` names. File paths get a
|
|
8
|
+
// workspace-name prefix for global uniqueness.
|
|
9
|
+
export async function scanWorkspaces(config) {
|
|
10
|
+
const parser = new TypeScriptParser();
|
|
11
|
+
// Pass 1 — parse each workspace independently. Keep raw results keyed by name.
|
|
12
|
+
const parsed = new Map();
|
|
13
|
+
for (const ws of config.workspaces) {
|
|
14
|
+
const r = await parser.parseWorkspaceFull({ workspaceRoot: ws.rootAbs });
|
|
15
|
+
parsed.set(ws.name, r);
|
|
16
|
+
}
|
|
17
|
+
// Build a lookup from packageName → workspace name, for cross-workspace
|
|
18
|
+
// resolution. Also auto-derive from each workspace's package.json `name`
|
|
19
|
+
// field when no explicit `package` was set in the config.
|
|
20
|
+
const pkgToWorkspace = new Map();
|
|
21
|
+
for (const ws of config.workspaces) {
|
|
22
|
+
const declared = ws.packageName ?? readPackageName(ws.rootAbs);
|
|
23
|
+
if (declared)
|
|
24
|
+
pkgToWorkspace.set(declared, ws.name);
|
|
25
|
+
}
|
|
26
|
+
const symbols = [];
|
|
27
|
+
const imports = [];
|
|
28
|
+
const files = [];
|
|
29
|
+
for (const ws of config.workspaces) {
|
|
30
|
+
const r = parsed.get(ws.name);
|
|
31
|
+
if (!r)
|
|
32
|
+
continue;
|
|
33
|
+
// Prefix every file with the workspace name so downstream code can treat
|
|
34
|
+
// paths as globally unique without losing the within-workspace structure.
|
|
35
|
+
// Re-mint the symbol id with the workspace name folded in — without
|
|
36
|
+
// this, two workspaces with the same relative file path (e.g. both
|
|
37
|
+
// export `interface User` from `src/types.ts`) produce symbols that
|
|
38
|
+
// share the parser's content-derived id and collapse into a single
|
|
39
|
+
// entry in every downstream Map<id, …>. The duplicate-type detector
|
|
40
|
+
// never sees the cross-workspace pair as a result.
|
|
41
|
+
for (const sym of r.symbols) {
|
|
42
|
+
symbols.push({
|
|
43
|
+
...sym,
|
|
44
|
+
id: namespaceId(ws.name, sym.id),
|
|
45
|
+
workspace: ws.name,
|
|
46
|
+
file: prefix(ws.name, sym.file),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
for (const f of r.files)
|
|
50
|
+
files.push(prefix(ws.name, f));
|
|
51
|
+
for (const imp of r.imports) {
|
|
52
|
+
// Default: stays within source workspace.
|
|
53
|
+
let target = imp.target ? prefix(ws.name, imp.target) : null;
|
|
54
|
+
let targetWorkspace;
|
|
55
|
+
// Cross-workspace resolution. Two cases:
|
|
56
|
+
// (a) a bare-specifier that exactly matches a sibling's package name
|
|
57
|
+
// (b) `<pkg>/sub/path` — resolve sub/path inside the sibling workspace
|
|
58
|
+
if (!target) {
|
|
59
|
+
const crossWs = matchPackageSpecifier(imp.specifier, pkgToWorkspace);
|
|
60
|
+
if (crossWs) {
|
|
61
|
+
const subPath = imp.specifier.slice(crossWs.packageName.length);
|
|
62
|
+
const sibling = config.workspaces.find((w) => w.name === crossWs.workspaceName);
|
|
63
|
+
if (sibling) {
|
|
64
|
+
const resolved = resolveSubPath(sibling.rootAbs, subPath);
|
|
65
|
+
if (resolved) {
|
|
66
|
+
target = prefix(sibling.name, resolved);
|
|
67
|
+
targetWorkspace = sibling.name;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
imports.push({
|
|
73
|
+
...imp,
|
|
74
|
+
source: prefix(ws.name, imp.source),
|
|
75
|
+
sourceWorkspace: ws.name,
|
|
76
|
+
target,
|
|
77
|
+
targetWorkspace,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { symbols, imports, files, workspaces: config.workspaces };
|
|
82
|
+
}
|
|
83
|
+
function prefix(workspaceName, file) {
|
|
84
|
+
// Use POSIX separator so paths are stable across platforms.
|
|
85
|
+
return `${workspaceName}/${file.split(path.sep).join('/')}`;
|
|
86
|
+
}
|
|
87
|
+
function namespaceId(workspaceName, id) {
|
|
88
|
+
return crypto.createHash('sha256').update(`${workspaceName}::${id}`).digest('hex').slice(0, 16);
|
|
89
|
+
}
|
|
90
|
+
function readPackageName(rootAbs) {
|
|
91
|
+
const pkgPath = path.join(rootAbs, 'package.json');
|
|
92
|
+
if (!fs.existsSync(pkgPath))
|
|
93
|
+
return undefined;
|
|
94
|
+
try {
|
|
95
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
96
|
+
return typeof pkg.name === 'string' ? pkg.name : undefined;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function matchPackageSpecifier(specifier, pkgToWorkspace) {
|
|
103
|
+
for (const [pkg, ws] of pkgToWorkspace) {
|
|
104
|
+
if (specifier === pkg || specifier.startsWith(`${pkg}/`)) {
|
|
105
|
+
return { packageName: pkg, workspaceName: ws };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
function resolveSubPath(workspaceRoot, subPath) {
|
|
111
|
+
// `subPath` is like "" (just the package name), "/src/foo", or "/dist/foo".
|
|
112
|
+
// We try the most common shapes: empty → src/index, /x → src/x.ts, /x → x.ts.
|
|
113
|
+
const candidates = [];
|
|
114
|
+
if (subPath === '' || subPath === '/') {
|
|
115
|
+
candidates.push(path.join(workspaceRoot, 'src/index.ts'), path.join(workspaceRoot, 'index.ts'), path.join(workspaceRoot, 'src/index.tsx'));
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const rel = subPath.startsWith('/') ? subPath.slice(1) : subPath;
|
|
119
|
+
candidates.push(path.join(workspaceRoot, 'src', `${rel}.ts`), path.join(workspaceRoot, 'src', rel, 'index.ts'), path.join(workspaceRoot, `${rel}.ts`), path.join(workspaceRoot, rel, 'index.ts'));
|
|
120
|
+
}
|
|
121
|
+
for (const c of candidates) {
|
|
122
|
+
if (fs.existsSync(c) && fs.statSync(c).isFile()) {
|
|
123
|
+
return path.relative(workspaceRoot, c);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Last resort: piggy-back on the standard resolver pretending we're already
|
|
127
|
+
// inside the workspace root.
|
|
128
|
+
return resolveImport(workspaceRoot, 'fake.ts', `./${subPath.replace(/^\//, '')}`);
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=multi-workspace-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-workspace-scanner.js","sourceRoot":"","sources":["../src/multi-workspace-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SymbolRecord } from '../types.js';
|
|
2
|
+
export declare class TypeNormalizer {
|
|
3
|
+
normalize(record: SymbolRecord): SymbolRecord;
|
|
4
|
+
normalizeAll(records: SymbolRecord[]): SymbolRecord[];
|
|
5
|
+
/**
|
|
6
|
+
* Compute three function hashes:
|
|
7
|
+
* strict : `(param:type, ...) => returnType { body-normalized }`
|
|
8
|
+
* structural : same, but param names dropped and body identifiers stripped
|
|
9
|
+
* of token-identity (keep only structural tokens — kw, punct, types)
|
|
10
|
+
* normalized-names: param names mapped through the synonym table, body unchanged
|
|
11
|
+
*
|
|
12
|
+
* `bodyNormalized` was already whitespace-collapsed by the parser.
|
|
13
|
+
*/
|
|
14
|
+
private normalizeFunction;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=type-normalizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-normalizer.d.ts","sourceRoot":"","sources":["../../src/normalizers/type-normalizer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAqC,YAAY,EAAE,MAAM,aAAa,CAAC;AAkBnF,qBAAa,cAAc;IACzB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY;IA8C7C,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE;IAIrD;;;;;;;;OAQG;IACH,OAAO,CAAC,iBAAiB;CAmB1B"}
|