projscan 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -19
- package/dist/analyzers/unusedDependencyCheck.js +69 -17
- package/dist/analyzers/unusedDependencyCheck.js.map +1 -1
- package/dist/cli/_shared.d.ts +16 -0
- package/dist/cli/_shared.js +210 -0
- package/dist/cli/_shared.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +1 -0
- package/dist/cli/commands/analyze.js +87 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/audit.d.ts +1 -0
- package/dist/cli/commands/audit.js +47 -0
- package/dist/cli/commands/audit.js.map +1 -0
- package/dist/cli/commands/badge.d.ts +1 -0
- package/dist/cli/commands/badge.js +45 -0
- package/dist/cli/commands/badge.js.map +1 -0
- package/dist/cli/commands/ci.d.ts +1 -0
- package/dist/cli/commands/ci.js +57 -0
- package/dist/cli/commands/ci.js.map +1 -0
- package/dist/cli/commands/coupling.d.ts +1 -0
- package/dist/cli/commands/coupling.js +83 -0
- package/dist/cli/commands/coupling.js.map +1 -0
- package/dist/cli/commands/coverage.d.ts +1 -0
- package/dist/cli/commands/coverage.js +63 -0
- package/dist/cli/commands/coverage.js.map +1 -0
- package/dist/cli/commands/dependencies.d.ts +1 -0
- package/dist/cli/commands/dependencies.js +45 -0
- package/dist/cli/commands/dependencies.js.map +1 -0
- package/dist/cli/commands/diagram.d.ts +1 -0
- package/dist/cli/commands/diagram.js +45 -0
- package/dist/cli/commands/diagram.js.map +1 -0
- package/dist/cli/commands/diff.d.ts +1 -0
- package/dist/cli/commands/diff.js +70 -0
- package/dist/cli/commands/diff.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +1 -0
- package/dist/cli/commands/doctor.js +62 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/explain.d.ts +1 -0
- package/dist/cli/commands/explain.js +42 -0
- package/dist/cli/commands/explain.js.map +1 -0
- package/dist/cli/commands/file.d.ts +1 -0
- package/dist/cli/commands/file.js +45 -0
- package/dist/cli/commands/file.js.map +1 -0
- package/dist/cli/commands/fix.d.ts +1 -0
- package/dist/cli/commands/fix.js +70 -0
- package/dist/cli/commands/fix.js.map +1 -0
- package/dist/cli/commands/help.d.ts +1 -0
- package/dist/cli/commands/help.js +11 -0
- package/dist/cli/commands/help.js.map +1 -0
- package/dist/cli/commands/hotspots.d.ts +1 -0
- package/dist/cli/commands/hotspots.js +74 -0
- package/dist/cli/commands/hotspots.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +1 -0
- package/dist/cli/commands/mcp.js +21 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/outdated.d.ts +1 -0
- package/dist/cli/commands/outdated.js +51 -0
- package/dist/cli/commands/outdated.js.map +1 -0
- package/dist/cli/commands/prDiff.d.ts +1 -0
- package/dist/cli/commands/prDiff.js +59 -0
- package/dist/cli/commands/prDiff.js.map +1 -0
- package/dist/cli/commands/search.d.ts +1 -0
- package/dist/cli/commands/search.js +233 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/commands/structure.d.ts +1 -0
- package/dist/cli/commands/structure.js +58 -0
- package/dist/cli/commands/structure.js.map +1 -0
- package/dist/cli/commands/upgrade.d.ts +1 -0
- package/dist/cli/commands/upgrade.js +44 -0
- package/dist/cli/commands/upgrade.js.map +1 -0
- package/dist/cli/commands/workspaces.d.ts +1 -0
- package/dist/cli/commands/workspaces.js +35 -0
- package/dist/cli/commands/workspaces.js.map +1 -0
- package/dist/cli/index.js +45 -1132
- package/dist/cli/index.js.map +1 -1
- package/dist/core/ast.d.ts +2 -0
- package/dist/core/ast.js +35 -2
- package/dist/core/ast.js.map +1 -1
- package/dist/core/codeGraph.d.ts +2 -0
- package/dist/core/codeGraph.js +2 -0
- package/dist/core/codeGraph.js.map +1 -1
- package/dist/core/couplingAnalyzer.d.ts +18 -0
- package/dist/core/couplingAnalyzer.js +174 -0
- package/dist/core/couplingAnalyzer.js.map +1 -0
- package/dist/core/fileInspector.d.ts +1 -1
- package/dist/core/fileInspector.js +31 -1
- package/dist/core/fileInspector.js.map +1 -1
- package/dist/core/hotspotAnalyzer.d.ts +13 -0
- package/dist/core/hotspotAnalyzer.js +29 -6
- package/dist/core/hotspotAnalyzer.js.map +1 -1
- package/dist/core/indexCache.js +6 -3
- package/dist/core/indexCache.js.map +1 -1
- package/dist/core/languages/LanguageAdapter.d.ts +1 -1
- package/dist/core/languages/goAdapter.d.ts +2 -0
- package/dist/core/languages/goAdapter.js +138 -0
- package/dist/core/languages/goAdapter.js.map +1 -0
- package/dist/core/languages/goCallSites.d.ts +20 -0
- package/dist/core/languages/goCallSites.js +42 -0
- package/dist/core/languages/goCallSites.js.map +1 -0
- package/dist/core/languages/goCyclomatic.d.ts +21 -0
- package/dist/core/languages/goCyclomatic.js +55 -0
- package/dist/core/languages/goCyclomatic.js.map +1 -0
- package/dist/core/languages/goExports.d.ts +26 -0
- package/dist/core/languages/goExports.js +89 -0
- package/dist/core/languages/goExports.js.map +1 -0
- package/dist/core/languages/goImports.d.ts +26 -0
- package/dist/core/languages/goImports.js +64 -0
- package/dist/core/languages/goImports.js.map +1 -0
- package/dist/core/languages/goManifests.d.ts +19 -0
- package/dist/core/languages/goManifests.js +56 -0
- package/dist/core/languages/goManifests.js.map +1 -0
- package/dist/core/languages/javaAdapter.d.ts +2 -0
- package/dist/core/languages/javaAdapter.js +148 -0
- package/dist/core/languages/javaAdapter.js.map +1 -0
- package/dist/core/languages/javaCallSites.d.ts +16 -0
- package/dist/core/languages/javaCallSites.js +45 -0
- package/dist/core/languages/javaCallSites.js.map +1 -0
- package/dist/core/languages/javaCyclomatic.d.ts +21 -0
- package/dist/core/languages/javaCyclomatic.js +49 -0
- package/dist/core/languages/javaCyclomatic.js.map +1 -0
- package/dist/core/languages/javaExports.d.ts +25 -0
- package/dist/core/languages/javaExports.js +80 -0
- package/dist/core/languages/javaExports.js.map +1 -0
- package/dist/core/languages/javaImports.d.ts +25 -0
- package/dist/core/languages/javaImports.js +49 -0
- package/dist/core/languages/javaImports.js.map +1 -0
- package/dist/core/languages/javaManifests.d.ts +25 -0
- package/dist/core/languages/javaManifests.js +86 -0
- package/dist/core/languages/javaManifests.js.map +1 -0
- package/dist/core/languages/pythonAdapter.js +8 -1
- package/dist/core/languages/pythonAdapter.js.map +1 -1
- package/dist/core/languages/pythonCallSites.d.ts +19 -0
- package/dist/core/languages/pythonCallSites.js +40 -0
- package/dist/core/languages/pythonCallSites.js.map +1 -0
- package/dist/core/languages/pythonCyclomatic.d.ts +18 -0
- package/dist/core/languages/pythonCyclomatic.js +45 -0
- package/dist/core/languages/pythonCyclomatic.js.map +1 -0
- package/dist/core/languages/registry.js +4 -1
- package/dist/core/languages/registry.js.map +1 -1
- package/dist/core/languages/rubyAdapter.d.ts +2 -0
- package/dist/core/languages/rubyAdapter.js +131 -0
- package/dist/core/languages/rubyAdapter.js.map +1 -0
- package/dist/core/languages/rubyCallSites.d.ts +16 -0
- package/dist/core/languages/rubyCallSites.js +34 -0
- package/dist/core/languages/rubyCallSites.js.map +1 -0
- package/dist/core/languages/rubyCyclomatic.d.ts +19 -0
- package/dist/core/languages/rubyCyclomatic.js +47 -0
- package/dist/core/languages/rubyCyclomatic.js.map +1 -0
- package/dist/core/languages/rubyExports.d.ts +24 -0
- package/dist/core/languages/rubyExports.js +53 -0
- package/dist/core/languages/rubyExports.js.map +1 -0
- package/dist/core/languages/rubyImports.d.ts +12 -0
- package/dist/core/languages/rubyImports.js +75 -0
- package/dist/core/languages/rubyImports.js.map +1 -0
- package/dist/core/languages/rubyManifests.d.ts +20 -0
- package/dist/core/languages/rubyManifests.js +55 -0
- package/dist/core/languages/rubyManifests.js.map +1 -0
- package/dist/core/languages/treeSitterLoader.js +4 -1
- package/dist/core/languages/treeSitterLoader.js.map +1 -1
- package/dist/core/monorepo.d.ts +20 -0
- package/dist/core/monorepo.js +270 -0
- package/dist/core/monorepo.js.map +1 -0
- package/dist/core/outdatedDetector.d.ts +13 -2
- package/dist/core/outdatedDetector.js +86 -16
- package/dist/core/outdatedDetector.js.map +1 -1
- package/dist/core/prDiff.d.ts +43 -0
- package/dist/core/prDiff.js +298 -0
- package/dist/core/prDiff.js.map +1 -0
- package/dist/core/telemetry.d.ts +90 -0
- package/dist/core/telemetry.js +199 -0
- package/dist/core/telemetry.js.map +1 -0
- package/dist/grammars/tree-sitter-go.wasm +0 -0
- package/dist/grammars/tree-sitter-java.wasm +0 -0
- package/dist/grammars/tree-sitter-ruby.wasm +0 -0
- package/dist/mcp/tools/_shared.d.ts +24 -0
- package/dist/mcp/tools/_shared.js +82 -0
- package/dist/mcp/tools/_shared.js.map +1 -0
- package/dist/mcp/tools/analyze.d.ts +2 -0
- package/dist/mcp/tools/analyze.js +55 -0
- package/dist/mcp/tools/analyze.js.map +1 -0
- package/dist/mcp/tools/audit.d.ts +2 -0
- package/dist/mcp/tools/audit.js +32 -0
- package/dist/mcp/tools/audit.js.map +1 -0
- package/dist/mcp/tools/coupling.d.ts +2 -0
- package/dist/mcp/tools/coupling.js +67 -0
- package/dist/mcp/tools/coupling.js.map +1 -0
- package/dist/mcp/tools/coverage.d.ts +2 -0
- package/dist/mcp/tools/coverage.js +53 -0
- package/dist/mcp/tools/coverage.js.map +1 -0
- package/dist/mcp/tools/dependencies.d.ts +2 -0
- package/dist/mcp/tools/dependencies.js +16 -0
- package/dist/mcp/tools/dependencies.js.map +1 -0
- package/dist/mcp/tools/doctor.d.ts +2 -0
- package/dist/mcp/tools/doctor.js +30 -0
- package/dist/mcp/tools/doctor.js.map +1 -0
- package/dist/mcp/tools/explain.d.ts +2 -0
- package/dist/mcp/tools/explain.js +30 -0
- package/dist/mcp/tools/explain.js.map +1 -0
- package/dist/mcp/tools/file.d.ts +2 -0
- package/dist/mcp/tools/file.js +22 -0
- package/dist/mcp/tools/file.js.map +1 -0
- package/dist/mcp/tools/graph.d.ts +2 -0
- package/dist/mcp/tools/graph.js +69 -0
- package/dist/mcp/tools/graph.js.map +1 -0
- package/dist/mcp/tools/hotspots.d.ts +2 -0
- package/dist/mcp/tools/hotspots.js +64 -0
- package/dist/mcp/tools/hotspots.js.map +1 -0
- package/dist/mcp/tools/outdated.d.ts +2 -0
- package/dist/mcp/tools/outdated.js +36 -0
- package/dist/mcp/tools/outdated.js.map +1 -0
- package/dist/mcp/tools/prDiff.d.ts +2 -0
- package/dist/mcp/tools/prDiff.js +38 -0
- package/dist/mcp/tools/prDiff.js.map +1 -0
- package/dist/mcp/tools/search.d.ts +2 -0
- package/dist/mcp/tools/search.js +167 -0
- package/dist/mcp/tools/search.js.map +1 -0
- package/dist/mcp/tools/structure.d.ts +2 -0
- package/dist/mcp/tools/structure.js +34 -0
- package/dist/mcp/tools/structure.js.map +1 -0
- package/dist/mcp/tools/upgrade.d.ts +2 -0
- package/dist/mcp/tools/upgrade.js +38 -0
- package/dist/mcp/tools/upgrade.js.map +1 -0
- package/dist/mcp/tools/workspaces.d.ts +2 -0
- package/dist/mcp/tools/workspaces.js +13 -0
- package/dist/mcp/tools/workspaces.js.map +1 -0
- package/dist/mcp/tools.d.ts +12 -6
- package/dist/mcp/tools.js +40 -605
- package/dist/mcp/tools.js.map +1 -1
- package/dist/reporters/consoleReporter.d.ts +4 -1
- package/dist/reporters/consoleReporter.js +113 -0
- package/dist/reporters/consoleReporter.js.map +1 -1
- package/dist/reporters/jsonReporter.d.ts +4 -1
- package/dist/reporters/jsonReporter.js +9 -0
- package/dist/reporters/jsonReporter.js.map +1 -1
- package/dist/reporters/markdownReporter.d.ts +4 -1
- package/dist/reporters/markdownReporter.js +103 -3
- package/dist/reporters/markdownReporter.js.map +1 -1
- package/dist/tool-manifest.json +358 -0
- package/dist/types.d.ts +115 -0
- package/dist/utils/cache.d.ts +3 -0
- package/dist/utils/cache.js +51 -0
- package/dist/utils/cache.js.map +1 -0
- package/package.json +7 -3
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fg from 'fast-glob';
|
|
4
|
+
/**
|
|
5
|
+
* Detect monorepo workspaces. Covers the three setups that account for the
|
|
6
|
+
* vast majority of JS/TS monorepos: npm/yarn workspaces (package.json
|
|
7
|
+
* `workspaces`), pnpm (pnpm-workspace.yaml), and the Nx/Turbo/Lerna fallback
|
|
8
|
+
* (their files exist but they typically piggy-back on package.json
|
|
9
|
+
* workspaces or rely on a `packages/` convention).
|
|
10
|
+
*
|
|
11
|
+
* Returns kind 'none' for non-monorepos. Always includes the workspace root
|
|
12
|
+
* package itself if it has its own package.json with a name.
|
|
13
|
+
*/
|
|
14
|
+
export async function detectWorkspaces(rootPath) {
|
|
15
|
+
// Read root package.json (may not exist for Python-only repos).
|
|
16
|
+
const rootPkg = await readPackageJson(path.join(rootPath, 'package.json'));
|
|
17
|
+
// 1) pnpm has its own manifest. Prefer it when present.
|
|
18
|
+
const pnpmManifest = path.join(rootPath, 'pnpm-workspace.yaml');
|
|
19
|
+
if (await fileExists(pnpmManifest)) {
|
|
20
|
+
const patterns = await readPnpmPackages(pnpmManifest);
|
|
21
|
+
const packages = await collectPackages(rootPath, patterns, rootPkg);
|
|
22
|
+
return { kind: 'pnpm', packages, source: 'pnpm-workspace.yaml' };
|
|
23
|
+
}
|
|
24
|
+
// 2) npm / yarn workspaces in package.json.
|
|
25
|
+
if (rootPkg) {
|
|
26
|
+
const patterns = readNpmYarnPatterns(rootPkg);
|
|
27
|
+
if (patterns && patterns.length > 0) {
|
|
28
|
+
const packages = await collectPackages(rootPath, patterns, rootPkg);
|
|
29
|
+
// Distinguish yarn from npm if a yarn.lock is present - affects nothing
|
|
30
|
+
// about discovery, just labelling.
|
|
31
|
+
const kind = (await fileExists(path.join(rootPath, 'yarn.lock')))
|
|
32
|
+
? 'yarn'
|
|
33
|
+
: 'npm';
|
|
34
|
+
return { kind, packages, source: 'package.json#workspaces' };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// 3) Lerna - its config has an explicit `packages` field with globs.
|
|
38
|
+
const lernaPath = path.join(rootPath, 'lerna.json');
|
|
39
|
+
if (await fileExists(lernaPath)) {
|
|
40
|
+
const patterns = (await readJsonField(lernaPath, 'packages')) ?? ['packages/*'];
|
|
41
|
+
const packages = await collectPackages(rootPath, patterns, rootPkg);
|
|
42
|
+
if (packages.length > 0) {
|
|
43
|
+
return { kind: 'lerna', packages, source: 'lerna.json#packages' };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// 4) Nx - workspaceLayout supplies appsDir/libsDir; project.json files
|
|
47
|
+
// anywhere identify packages. Older Nx variants used workspace.json (a
|
|
48
|
+
// single file enumerating projects); we read its `projects` map too.
|
|
49
|
+
const nxJsonPath = path.join(rootPath, 'nx.json');
|
|
50
|
+
if (await fileExists(nxJsonPath)) {
|
|
51
|
+
const nxPackages = await collectNxPackages(rootPath, nxJsonPath);
|
|
52
|
+
if (nxPackages.length > 0 || rootPkg) {
|
|
53
|
+
const merged = rootPkg ? [rootPackageOnly(rootPkg), ...nxPackages] : nxPackages;
|
|
54
|
+
merged.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
55
|
+
return { kind: 'nx', packages: merged, source: 'nx.json + project.json scan' };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// 5) Turbo - turbo.json defines task pipelines, NOT workspace layout.
|
|
59
|
+
// Turbo always rides on top of npm/yarn/pnpm workspaces (handled above).
|
|
60
|
+
// If we get here with a turbo.json but no workspace declaration, treat it
|
|
61
|
+
// as a marker and fall back to the packages/* convention so we still
|
|
62
|
+
// surface something useful.
|
|
63
|
+
if (await fileExists(path.join(rootPath, 'turbo.json'))) {
|
|
64
|
+
const packages = await collectPackages(rootPath, ['packages/*', 'apps/*'], rootPkg);
|
|
65
|
+
if (packages.length > 0) {
|
|
66
|
+
return { kind: 'turbo', packages, source: 'turbo.json (fallback glob)' };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Single-package repo (or non-JS).
|
|
70
|
+
return { kind: 'none', packages: rootPkg ? [rootPackageOnly(rootPkg)] : [] };
|
|
71
|
+
}
|
|
72
|
+
async function readPackageJson(absPath) {
|
|
73
|
+
try {
|
|
74
|
+
const raw = await fs.readFile(absPath, 'utf-8');
|
|
75
|
+
return JSON.parse(raw);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function readNpmYarnPatterns(pkg) {
|
|
82
|
+
if (!pkg.workspaces)
|
|
83
|
+
return null;
|
|
84
|
+
if (Array.isArray(pkg.workspaces))
|
|
85
|
+
return pkg.workspaces;
|
|
86
|
+
if (Array.isArray(pkg.workspaces.packages))
|
|
87
|
+
return pkg.workspaces.packages;
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
async function readPnpmPackages(manifestPath) {
|
|
91
|
+
// Tiny YAML subset reader: pnpm-workspace.yaml is just `packages:` followed
|
|
92
|
+
// by a YAML list. Avoiding a full YAML dep keeps the install size small.
|
|
93
|
+
let content;
|
|
94
|
+
try {
|
|
95
|
+
content = await fs.readFile(manifestPath, 'utf-8');
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
const patterns = [];
|
|
101
|
+
const lines = content.split('\n');
|
|
102
|
+
let inPackages = false;
|
|
103
|
+
for (const raw of lines) {
|
|
104
|
+
const line = raw.trimEnd();
|
|
105
|
+
if (line.startsWith('packages:')) {
|
|
106
|
+
inPackages = true;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (inPackages) {
|
|
110
|
+
// List item: ` - 'pattern'` or ` - "pattern"` or ` - pattern`.
|
|
111
|
+
const m = /^\s*-\s*['"]?([^'"\n]+?)['"]?\s*$/.exec(line);
|
|
112
|
+
if (m) {
|
|
113
|
+
patterns.push(m[1]);
|
|
114
|
+
}
|
|
115
|
+
else if (line.length > 0 && !line.startsWith(' ') && !line.startsWith('\t')) {
|
|
116
|
+
// New top-level key - packages section ended.
|
|
117
|
+
inPackages = false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return patterns;
|
|
122
|
+
}
|
|
123
|
+
async function collectPackages(rootPath, patterns, rootPkg) {
|
|
124
|
+
// Each pattern is typically `packages/*`. Resolve to package.json files.
|
|
125
|
+
const pkgManifests = patterns.map((p) => `${trimTrailingSlash(p)}/package.json`);
|
|
126
|
+
const matches = await fg(pkgManifests, {
|
|
127
|
+
cwd: rootPath,
|
|
128
|
+
onlyFiles: true,
|
|
129
|
+
ignore: ['**/node_modules/**'],
|
|
130
|
+
});
|
|
131
|
+
const packages = [];
|
|
132
|
+
for (const rel of matches) {
|
|
133
|
+
const abs = path.join(rootPath, rel);
|
|
134
|
+
const pkg = await readPackageJson(abs);
|
|
135
|
+
if (!pkg)
|
|
136
|
+
continue;
|
|
137
|
+
const dir = path.posix.dirname(rel.split(path.sep).join('/'));
|
|
138
|
+
packages.push({
|
|
139
|
+
name: pkg.name ?? path.posix.basename(dir),
|
|
140
|
+
relativePath: dir,
|
|
141
|
+
version: pkg.version,
|
|
142
|
+
isRoot: false,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
if (rootPkg && rootPkg.name) {
|
|
146
|
+
packages.unshift(rootPackageOnly(rootPkg));
|
|
147
|
+
}
|
|
148
|
+
packages.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
149
|
+
return packages;
|
|
150
|
+
}
|
|
151
|
+
function rootPackageOnly(rootPkg) {
|
|
152
|
+
return {
|
|
153
|
+
name: rootPkg.name ?? '<root>',
|
|
154
|
+
relativePath: '',
|
|
155
|
+
version: rootPkg.version,
|
|
156
|
+
isRoot: true,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function trimTrailingSlash(p) {
|
|
160
|
+
return p.endsWith('/') ? p.slice(0, -1) : p;
|
|
161
|
+
}
|
|
162
|
+
async function fileExists(absPath) {
|
|
163
|
+
try {
|
|
164
|
+
await fs.access(absPath);
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/** Read a JSON file and return one named field (or undefined). Best-effort. */
|
|
172
|
+
async function readJsonField(absPath, field) {
|
|
173
|
+
try {
|
|
174
|
+
const raw = await fs.readFile(absPath, 'utf-8');
|
|
175
|
+
const parsed = JSON.parse(raw);
|
|
176
|
+
const v = parsed[field];
|
|
177
|
+
return v;
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Discover Nx workspace packages.
|
|
185
|
+
*
|
|
186
|
+
* Modern Nx (16+) puts a `project.json` next to every project. Older Nx
|
|
187
|
+
* (<= 15) maintains a single `workspace.json` listing them. We try both:
|
|
188
|
+
* scan for project.json files first (covers anything modern), then read
|
|
189
|
+
* workspace.json's `projects` map and treat its directories as packages.
|
|
190
|
+
*
|
|
191
|
+
* `nx.json#workspaceLayout` provides default `appsDir` / `libsDir` hints
|
|
192
|
+
* that we use to scope the project.json scan. When unspecified Nx defaults
|
|
193
|
+
* to "apps" and "libs"; we honor that.
|
|
194
|
+
*/
|
|
195
|
+
async function collectNxPackages(rootPath, nxJsonPath) {
|
|
196
|
+
const layout = (await readJsonField(nxJsonPath, 'workspaceLayout')) ?? {};
|
|
197
|
+
const appsDir = (layout.appsDir ?? 'apps').replace(/\/+$/, '');
|
|
198
|
+
const libsDir = (layout.libsDir ?? 'libs').replace(/\/+$/, '');
|
|
199
|
+
const found = new Map();
|
|
200
|
+
// 1) Scan for project.json files. Look in the layout dirs first, then in
|
|
201
|
+
// a wider `**/project.json` search bounded by reasonable globs.
|
|
202
|
+
const patterns = Array.from(new Set([
|
|
203
|
+
`${appsDir}/**/project.json`,
|
|
204
|
+
`${libsDir}/**/project.json`,
|
|
205
|
+
'packages/**/project.json',
|
|
206
|
+
]));
|
|
207
|
+
const matches = await fg(patterns, {
|
|
208
|
+
cwd: rootPath,
|
|
209
|
+
onlyFiles: true,
|
|
210
|
+
ignore: ['**/node_modules/**'],
|
|
211
|
+
deep: 4,
|
|
212
|
+
});
|
|
213
|
+
for (const rel of matches) {
|
|
214
|
+
const projectJsonPath = path.join(rootPath, rel);
|
|
215
|
+
const name = (await readJsonField(projectJsonPath, 'name')) ?? path.posix.basename(path.posix.dirname(rel.split(path.sep).join('/')));
|
|
216
|
+
const dir = path.posix.dirname(rel.split(path.sep).join('/'));
|
|
217
|
+
if (!found.has(dir)) {
|
|
218
|
+
found.set(dir, { name, relativePath: dir, isRoot: false });
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// 2) Older Nx: read workspace.json projects map.
|
|
222
|
+
const workspaceJsonPath = path.join(rootPath, 'workspace.json');
|
|
223
|
+
if (await fileExists(workspaceJsonPath)) {
|
|
224
|
+
const projects = (await readJsonField(workspaceJsonPath, 'projects')) ?? {};
|
|
225
|
+
for (const [name, val] of Object.entries(projects)) {
|
|
226
|
+
const root = typeof val === 'string' ? val : val.root;
|
|
227
|
+
if (!root)
|
|
228
|
+
continue;
|
|
229
|
+
const dir = root.replace(/\/+$/, '');
|
|
230
|
+
if (!found.has(dir)) {
|
|
231
|
+
found.set(dir, { name, relativePath: dir, isRoot: false });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return [...found.values()];
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Given a file's project-relative path, return the workspace package whose
|
|
239
|
+
* `relativePath` is its longest matching prefix. Used to filter hotspots /
|
|
240
|
+
* coupling rows by --package.
|
|
241
|
+
*/
|
|
242
|
+
export function findPackageForFile(workspaces, filePath) {
|
|
243
|
+
let best = null;
|
|
244
|
+
for (const pkg of workspaces.packages) {
|
|
245
|
+
if (pkg.isRoot)
|
|
246
|
+
continue;
|
|
247
|
+
const prefix = pkg.relativePath ? pkg.relativePath + '/' : '';
|
|
248
|
+
if (filePath === pkg.relativePath || filePath.startsWith(prefix)) {
|
|
249
|
+
if (!best || pkg.relativePath.length > best.relativePath.length)
|
|
250
|
+
best = pkg;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Fall back to root package if nothing more specific matched.
|
|
254
|
+
if (!best) {
|
|
255
|
+
const root = workspaces.packages.find((p) => p.isRoot);
|
|
256
|
+
return root ?? null;
|
|
257
|
+
}
|
|
258
|
+
return best;
|
|
259
|
+
}
|
|
260
|
+
/** Filter helper for callers passing --package <name>. */
|
|
261
|
+
export function filterFilesByPackage(workspaces, packageName, files) {
|
|
262
|
+
const pkg = workspaces.packages.find((p) => p.name === packageName);
|
|
263
|
+
if (!pkg)
|
|
264
|
+
return [];
|
|
265
|
+
if (pkg.isRoot)
|
|
266
|
+
return files;
|
|
267
|
+
const prefix = pkg.relativePath + '/';
|
|
268
|
+
return files.filter((f) => f === pkg.relativePath || f.startsWith(prefix));
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=monorepo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monorepo.js","sourceRoot":"","sources":["../../src/core/monorepo.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
import type { OutdatedReport } from '../types.js';
|
|
1
|
+
import type { OutdatedReport, WorkspaceInfo } from '../types.js';
|
|
2
|
+
export interface OutdatedOptions {
|
|
3
|
+
/** When provided, scan each workspace package's package.json individually. */
|
|
4
|
+
workspaces?: WorkspaceInfo;
|
|
5
|
+
/** When provided alongside workspaces, restrict to a single package by name. */
|
|
6
|
+
workspaceFilter?: string;
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
9
|
* Offline outdated check - compares the version declared in package.json
|
|
4
10
|
* to the version installed under node_modules/<pkg>/package.json.
|
|
5
11
|
*
|
|
12
|
+
* In a monorepo (caller supplies workspaces), each package's package.json is
|
|
13
|
+
* scanned. Each result entry carries the workspace it came from. Installed
|
|
14
|
+
* versions still resolve through the root node_modules (npm/yarn/pnpm hoisting
|
|
15
|
+
* makes that the right place to look in 95% of installs).
|
|
16
|
+
*
|
|
6
17
|
* Does not hit the npm registry. `latest` is filled in only when a node_modules
|
|
7
18
|
* install exists; the drift calculation uses installed vs declared.
|
|
8
19
|
*/
|
|
9
|
-
export declare function detectOutdated(rootPath: string): Promise<OutdatedReport>;
|
|
20
|
+
export declare function detectOutdated(rootPath: string, options?: OutdatedOptions): Promise<OutdatedReport>;
|
|
@@ -5,10 +5,58 @@ import { drift as semverDrift } from '../utils/semver.js';
|
|
|
5
5
|
* Offline outdated check - compares the version declared in package.json
|
|
6
6
|
* to the version installed under node_modules/<pkg>/package.json.
|
|
7
7
|
*
|
|
8
|
+
* In a monorepo (caller supplies workspaces), each package's package.json is
|
|
9
|
+
* scanned. Each result entry carries the workspace it came from. Installed
|
|
10
|
+
* versions still resolve through the root node_modules (npm/yarn/pnpm hoisting
|
|
11
|
+
* makes that the right place to look in 95% of installs).
|
|
12
|
+
*
|
|
8
13
|
* Does not hit the npm registry. `latest` is filled in only when a node_modules
|
|
9
14
|
* install exists; the drift calculation uses installed vs declared.
|
|
10
15
|
*/
|
|
11
|
-
export async function detectOutdated(rootPath) {
|
|
16
|
+
export async function detectOutdated(rootPath, options = {}) {
|
|
17
|
+
const ws = options.workspaces;
|
|
18
|
+
const isMonorepo = ws !== undefined && ws.kind !== 'none' && ws.packages.length > 1;
|
|
19
|
+
if (!isMonorepo) {
|
|
20
|
+
// Single-package path: read root package.json only.
|
|
21
|
+
return await scanSinglePackage(rootPath, undefined);
|
|
22
|
+
}
|
|
23
|
+
// Monorepo path: scan each package's manifest, attribute results.
|
|
24
|
+
const nodeModules = path.join(rootPath, 'node_modules');
|
|
25
|
+
const nodeModulesExists = await pathExists(nodeModules);
|
|
26
|
+
const allPackages = [];
|
|
27
|
+
const byWorkspace = [];
|
|
28
|
+
for (const wp of ws.packages) {
|
|
29
|
+
if (options.workspaceFilter && wp.name !== options.workspaceFilter)
|
|
30
|
+
continue;
|
|
31
|
+
const pkgDir = wp.relativePath ? path.join(rootPath, wp.relativePath) : rootPath;
|
|
32
|
+
const pkgManifest = path.join(pkgDir, 'package.json');
|
|
33
|
+
const pkgEntries = await readManifestEntries(pkgManifest);
|
|
34
|
+
const pkgResults = [];
|
|
35
|
+
for (const [name, declared, scope] of pkgEntries) {
|
|
36
|
+
let installed = null;
|
|
37
|
+
if (nodeModulesExists)
|
|
38
|
+
installed = await readInstalledVersion(nodeModules, name);
|
|
39
|
+
pkgResults.push({
|
|
40
|
+
name,
|
|
41
|
+
declared,
|
|
42
|
+
installed,
|
|
43
|
+
latest: installed,
|
|
44
|
+
drift: semverDrift(declared, installed),
|
|
45
|
+
scope,
|
|
46
|
+
workspace: wp.name,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
allPackages.push(...pkgResults);
|
|
50
|
+
byWorkspace.push({ workspace: wp.name, relativePath: wp.relativePath, total: pkgResults.length });
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
available: true,
|
|
54
|
+
totalPackages: allPackages.length,
|
|
55
|
+
packages: allPackages,
|
|
56
|
+
byWorkspace,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
async function scanSinglePackage(rootPath, workspaceName) {
|
|
12
60
|
const pkgPath = path.join(rootPath, 'package.json');
|
|
13
61
|
let raw;
|
|
14
62
|
try {
|
|
@@ -22,9 +70,9 @@ export async function detectOutdated(rootPath) {
|
|
|
22
70
|
packages: [],
|
|
23
71
|
};
|
|
24
72
|
}
|
|
25
|
-
let
|
|
73
|
+
let pkgJson;
|
|
26
74
|
try {
|
|
27
|
-
|
|
75
|
+
pkgJson = JSON.parse(raw);
|
|
28
76
|
}
|
|
29
77
|
catch {
|
|
30
78
|
return {
|
|
@@ -34,29 +82,25 @@ export async function detectOutdated(rootPath) {
|
|
|
34
82
|
packages: [],
|
|
35
83
|
};
|
|
36
84
|
}
|
|
37
|
-
const
|
|
38
|
-
const devDependencies = (pkg.devDependencies ?? {});
|
|
39
|
-
const entries = [
|
|
40
|
-
...Object.entries(dependencies).map(([n, v]) => [n, v, 'dependency']),
|
|
41
|
-
...Object.entries(devDependencies).map(([n, v]) => [n, v, 'devDependency']),
|
|
42
|
-
];
|
|
85
|
+
const entries = manifestEntriesFromParsed(pkgJson);
|
|
43
86
|
const nodeModules = path.join(rootPath, 'node_modules');
|
|
44
87
|
const nodeModulesExists = await pathExists(nodeModules);
|
|
45
88
|
const packages = [];
|
|
46
89
|
for (const [name, declared, scope] of entries) {
|
|
47
90
|
let installed = null;
|
|
48
|
-
if (nodeModulesExists)
|
|
91
|
+
if (nodeModulesExists)
|
|
49
92
|
installed = await readInstalledVersion(nodeModules, name);
|
|
50
|
-
|
|
51
|
-
const drift = semverDrift(declared, installed);
|
|
52
|
-
packages.push({
|
|
93
|
+
const entry = {
|
|
53
94
|
name,
|
|
54
95
|
declared,
|
|
55
96
|
installed,
|
|
56
|
-
latest: installed,
|
|
57
|
-
drift,
|
|
97
|
+
latest: installed,
|
|
98
|
+
drift: semverDrift(declared, installed),
|
|
58
99
|
scope,
|
|
59
|
-
}
|
|
100
|
+
};
|
|
101
|
+
if (workspaceName)
|
|
102
|
+
entry.workspace = workspaceName;
|
|
103
|
+
packages.push(entry);
|
|
60
104
|
}
|
|
61
105
|
return {
|
|
62
106
|
available: true,
|
|
@@ -64,6 +108,32 @@ export async function detectOutdated(rootPath) {
|
|
|
64
108
|
packages,
|
|
65
109
|
};
|
|
66
110
|
}
|
|
111
|
+
function manifestEntriesFromParsed(pkg) {
|
|
112
|
+
const dependencies = (pkg.dependencies ?? {});
|
|
113
|
+
const devDependencies = (pkg.devDependencies ?? {});
|
|
114
|
+
return [
|
|
115
|
+
...Object.entries(dependencies).map(([n, v]) => [n, v, 'dependency']),
|
|
116
|
+
...Object.entries(devDependencies).map(([n, v]) => [n, v, 'devDependency']),
|
|
117
|
+
];
|
|
118
|
+
}
|
|
119
|
+
/** Read deps/devDeps from a package.json. Returns [] if file unreadable/invalid (used in monorepo iteration where one bad workspace shouldn't fail the whole scan). */
|
|
120
|
+
async function readManifestEntries(pkgPath) {
|
|
121
|
+
let raw;
|
|
122
|
+
try {
|
|
123
|
+
raw = await fs.readFile(pkgPath, 'utf-8');
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
let pkg;
|
|
129
|
+
try {
|
|
130
|
+
pkg = JSON.parse(raw);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
return manifestEntriesFromParsed(pkg);
|
|
136
|
+
}
|
|
67
137
|
async function pathExists(p) {
|
|
68
138
|
try {
|
|
69
139
|
await fs.access(p);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outdatedDetector.js","sourceRoot":"","sources":["../../src/core/outdatedDetector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"outdatedDetector.js","sourceRoot":"","sources":["../../src/core/outdatedDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type CodeGraph } from './codeGraph.js';
|
|
2
|
+
import type { PrDiffReport } from '../types.js';
|
|
3
|
+
export interface PrDiffOptions {
|
|
4
|
+
/** Base ref (branch, tag, sha). Default: origin/main, falling back to main. */
|
|
5
|
+
base?: string;
|
|
6
|
+
/** Head ref. Default: HEAD. */
|
|
7
|
+
head?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Compute a structural diff between two refs by building a CodeGraph for each
|
|
11
|
+
* side and comparing exports / imports / call sites / cyclomatic complexity /
|
|
12
|
+
* fan-in.
|
|
13
|
+
*
|
|
14
|
+
* Strategy: stand up a throwaway git worktree at the base ref, scan it like
|
|
15
|
+
* any other project, build its graph, then diff against the head graph
|
|
16
|
+
* (caller passes head graph in or the function builds one from `rootPath`).
|
|
17
|
+
*
|
|
18
|
+
* This is "structural diff", not text diff: agents reviewing PRs care about
|
|
19
|
+
* "what's the new export surface" and "which call sites disappeared", not
|
|
20
|
+
* "what whitespace changed on line 42."
|
|
21
|
+
*/
|
|
22
|
+
export declare function computePrDiff(rootPath: string, options?: PrDiffOptions): Promise<PrDiffReport>;
|
|
23
|
+
/** Pure function - exported for unit testing without a real git repo. */
|
|
24
|
+
export declare function diffGraphs(baseRef: string, baseSha: string | null, headRef: string, headSha: string | null, baseGraph: CodeGraph, headGraph: CodeGraph): PrDiffReport;
|
|
25
|
+
/**
|
|
26
|
+
* Pair removed/added export names that look like renames. A pair counts as a
|
|
27
|
+
* rename when it's the best-scoring match on both sides AND the similarity
|
|
28
|
+
* exceeds a threshold. Each name participates in at most one pair (greedy by
|
|
29
|
+
* descending score). Whatever isn't paired stays in the +/- lists.
|
|
30
|
+
*
|
|
31
|
+
* Similarity blends two signals (each in [0,1]): normalized Levenshtein
|
|
32
|
+
* distance and longest-common-affix fraction. Threshold of 0.6 chosen to
|
|
33
|
+
* pair "fooBar" → "fooBaz" and "Widget" → "WidgetThing" without pairing
|
|
34
|
+
* unrelated names like "save" → "load".
|
|
35
|
+
*/
|
|
36
|
+
import type { ExportRename } from '../types.js';
|
|
37
|
+
interface RenameSplit {
|
|
38
|
+
renames: ExportRename[];
|
|
39
|
+
removedAfter: string[];
|
|
40
|
+
addedAfter: string[];
|
|
41
|
+
}
|
|
42
|
+
export declare function detectRenames(removed: string[], added: string[]): RenameSplit;
|
|
43
|
+
export {};
|