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.
Files changed (242) hide show
  1. package/README.md +56 -19
  2. package/dist/analyzers/unusedDependencyCheck.js +69 -17
  3. package/dist/analyzers/unusedDependencyCheck.js.map +1 -1
  4. package/dist/cli/_shared.d.ts +16 -0
  5. package/dist/cli/_shared.js +210 -0
  6. package/dist/cli/_shared.js.map +1 -0
  7. package/dist/cli/commands/analyze.d.ts +1 -0
  8. package/dist/cli/commands/analyze.js +87 -0
  9. package/dist/cli/commands/analyze.js.map +1 -0
  10. package/dist/cli/commands/audit.d.ts +1 -0
  11. package/dist/cli/commands/audit.js +47 -0
  12. package/dist/cli/commands/audit.js.map +1 -0
  13. package/dist/cli/commands/badge.d.ts +1 -0
  14. package/dist/cli/commands/badge.js +45 -0
  15. package/dist/cli/commands/badge.js.map +1 -0
  16. package/dist/cli/commands/ci.d.ts +1 -0
  17. package/dist/cli/commands/ci.js +57 -0
  18. package/dist/cli/commands/ci.js.map +1 -0
  19. package/dist/cli/commands/coupling.d.ts +1 -0
  20. package/dist/cli/commands/coupling.js +83 -0
  21. package/dist/cli/commands/coupling.js.map +1 -0
  22. package/dist/cli/commands/coverage.d.ts +1 -0
  23. package/dist/cli/commands/coverage.js +63 -0
  24. package/dist/cli/commands/coverage.js.map +1 -0
  25. package/dist/cli/commands/dependencies.d.ts +1 -0
  26. package/dist/cli/commands/dependencies.js +45 -0
  27. package/dist/cli/commands/dependencies.js.map +1 -0
  28. package/dist/cli/commands/diagram.d.ts +1 -0
  29. package/dist/cli/commands/diagram.js +45 -0
  30. package/dist/cli/commands/diagram.js.map +1 -0
  31. package/dist/cli/commands/diff.d.ts +1 -0
  32. package/dist/cli/commands/diff.js +70 -0
  33. package/dist/cli/commands/diff.js.map +1 -0
  34. package/dist/cli/commands/doctor.d.ts +1 -0
  35. package/dist/cli/commands/doctor.js +62 -0
  36. package/dist/cli/commands/doctor.js.map +1 -0
  37. package/dist/cli/commands/explain.d.ts +1 -0
  38. package/dist/cli/commands/explain.js +42 -0
  39. package/dist/cli/commands/explain.js.map +1 -0
  40. package/dist/cli/commands/file.d.ts +1 -0
  41. package/dist/cli/commands/file.js +45 -0
  42. package/dist/cli/commands/file.js.map +1 -0
  43. package/dist/cli/commands/fix.d.ts +1 -0
  44. package/dist/cli/commands/fix.js +70 -0
  45. package/dist/cli/commands/fix.js.map +1 -0
  46. package/dist/cli/commands/help.d.ts +1 -0
  47. package/dist/cli/commands/help.js +11 -0
  48. package/dist/cli/commands/help.js.map +1 -0
  49. package/dist/cli/commands/hotspots.d.ts +1 -0
  50. package/dist/cli/commands/hotspots.js +74 -0
  51. package/dist/cli/commands/hotspots.js.map +1 -0
  52. package/dist/cli/commands/mcp.d.ts +1 -0
  53. package/dist/cli/commands/mcp.js +21 -0
  54. package/dist/cli/commands/mcp.js.map +1 -0
  55. package/dist/cli/commands/outdated.d.ts +1 -0
  56. package/dist/cli/commands/outdated.js +51 -0
  57. package/dist/cli/commands/outdated.js.map +1 -0
  58. package/dist/cli/commands/prDiff.d.ts +1 -0
  59. package/dist/cli/commands/prDiff.js +59 -0
  60. package/dist/cli/commands/prDiff.js.map +1 -0
  61. package/dist/cli/commands/search.d.ts +1 -0
  62. package/dist/cli/commands/search.js +233 -0
  63. package/dist/cli/commands/search.js.map +1 -0
  64. package/dist/cli/commands/structure.d.ts +1 -0
  65. package/dist/cli/commands/structure.js +58 -0
  66. package/dist/cli/commands/structure.js.map +1 -0
  67. package/dist/cli/commands/upgrade.d.ts +1 -0
  68. package/dist/cli/commands/upgrade.js +44 -0
  69. package/dist/cli/commands/upgrade.js.map +1 -0
  70. package/dist/cli/commands/workspaces.d.ts +1 -0
  71. package/dist/cli/commands/workspaces.js +35 -0
  72. package/dist/cli/commands/workspaces.js.map +1 -0
  73. package/dist/cli/index.js +45 -1132
  74. package/dist/cli/index.js.map +1 -1
  75. package/dist/core/ast.d.ts +2 -0
  76. package/dist/core/ast.js +35 -2
  77. package/dist/core/ast.js.map +1 -1
  78. package/dist/core/codeGraph.d.ts +2 -0
  79. package/dist/core/codeGraph.js +2 -0
  80. package/dist/core/codeGraph.js.map +1 -1
  81. package/dist/core/couplingAnalyzer.d.ts +18 -0
  82. package/dist/core/couplingAnalyzer.js +174 -0
  83. package/dist/core/couplingAnalyzer.js.map +1 -0
  84. package/dist/core/fileInspector.d.ts +1 -1
  85. package/dist/core/fileInspector.js +31 -1
  86. package/dist/core/fileInspector.js.map +1 -1
  87. package/dist/core/hotspotAnalyzer.d.ts +13 -0
  88. package/dist/core/hotspotAnalyzer.js +29 -6
  89. package/dist/core/hotspotAnalyzer.js.map +1 -1
  90. package/dist/core/indexCache.js +6 -3
  91. package/dist/core/indexCache.js.map +1 -1
  92. package/dist/core/languages/LanguageAdapter.d.ts +1 -1
  93. package/dist/core/languages/goAdapter.d.ts +2 -0
  94. package/dist/core/languages/goAdapter.js +138 -0
  95. package/dist/core/languages/goAdapter.js.map +1 -0
  96. package/dist/core/languages/goCallSites.d.ts +20 -0
  97. package/dist/core/languages/goCallSites.js +42 -0
  98. package/dist/core/languages/goCallSites.js.map +1 -0
  99. package/dist/core/languages/goCyclomatic.d.ts +21 -0
  100. package/dist/core/languages/goCyclomatic.js +55 -0
  101. package/dist/core/languages/goCyclomatic.js.map +1 -0
  102. package/dist/core/languages/goExports.d.ts +26 -0
  103. package/dist/core/languages/goExports.js +89 -0
  104. package/dist/core/languages/goExports.js.map +1 -0
  105. package/dist/core/languages/goImports.d.ts +26 -0
  106. package/dist/core/languages/goImports.js +64 -0
  107. package/dist/core/languages/goImports.js.map +1 -0
  108. package/dist/core/languages/goManifests.d.ts +19 -0
  109. package/dist/core/languages/goManifests.js +56 -0
  110. package/dist/core/languages/goManifests.js.map +1 -0
  111. package/dist/core/languages/javaAdapter.d.ts +2 -0
  112. package/dist/core/languages/javaAdapter.js +148 -0
  113. package/dist/core/languages/javaAdapter.js.map +1 -0
  114. package/dist/core/languages/javaCallSites.d.ts +16 -0
  115. package/dist/core/languages/javaCallSites.js +45 -0
  116. package/dist/core/languages/javaCallSites.js.map +1 -0
  117. package/dist/core/languages/javaCyclomatic.d.ts +21 -0
  118. package/dist/core/languages/javaCyclomatic.js +49 -0
  119. package/dist/core/languages/javaCyclomatic.js.map +1 -0
  120. package/dist/core/languages/javaExports.d.ts +25 -0
  121. package/dist/core/languages/javaExports.js +80 -0
  122. package/dist/core/languages/javaExports.js.map +1 -0
  123. package/dist/core/languages/javaImports.d.ts +25 -0
  124. package/dist/core/languages/javaImports.js +49 -0
  125. package/dist/core/languages/javaImports.js.map +1 -0
  126. package/dist/core/languages/javaManifests.d.ts +25 -0
  127. package/dist/core/languages/javaManifests.js +86 -0
  128. package/dist/core/languages/javaManifests.js.map +1 -0
  129. package/dist/core/languages/pythonAdapter.js +8 -1
  130. package/dist/core/languages/pythonAdapter.js.map +1 -1
  131. package/dist/core/languages/pythonCallSites.d.ts +19 -0
  132. package/dist/core/languages/pythonCallSites.js +40 -0
  133. package/dist/core/languages/pythonCallSites.js.map +1 -0
  134. package/dist/core/languages/pythonCyclomatic.d.ts +18 -0
  135. package/dist/core/languages/pythonCyclomatic.js +45 -0
  136. package/dist/core/languages/pythonCyclomatic.js.map +1 -0
  137. package/dist/core/languages/registry.js +4 -1
  138. package/dist/core/languages/registry.js.map +1 -1
  139. package/dist/core/languages/rubyAdapter.d.ts +2 -0
  140. package/dist/core/languages/rubyAdapter.js +131 -0
  141. package/dist/core/languages/rubyAdapter.js.map +1 -0
  142. package/dist/core/languages/rubyCallSites.d.ts +16 -0
  143. package/dist/core/languages/rubyCallSites.js +34 -0
  144. package/dist/core/languages/rubyCallSites.js.map +1 -0
  145. package/dist/core/languages/rubyCyclomatic.d.ts +19 -0
  146. package/dist/core/languages/rubyCyclomatic.js +47 -0
  147. package/dist/core/languages/rubyCyclomatic.js.map +1 -0
  148. package/dist/core/languages/rubyExports.d.ts +24 -0
  149. package/dist/core/languages/rubyExports.js +53 -0
  150. package/dist/core/languages/rubyExports.js.map +1 -0
  151. package/dist/core/languages/rubyImports.d.ts +12 -0
  152. package/dist/core/languages/rubyImports.js +75 -0
  153. package/dist/core/languages/rubyImports.js.map +1 -0
  154. package/dist/core/languages/rubyManifests.d.ts +20 -0
  155. package/dist/core/languages/rubyManifests.js +55 -0
  156. package/dist/core/languages/rubyManifests.js.map +1 -0
  157. package/dist/core/languages/treeSitterLoader.js +4 -1
  158. package/dist/core/languages/treeSitterLoader.js.map +1 -1
  159. package/dist/core/monorepo.d.ts +20 -0
  160. package/dist/core/monorepo.js +270 -0
  161. package/dist/core/monorepo.js.map +1 -0
  162. package/dist/core/outdatedDetector.d.ts +13 -2
  163. package/dist/core/outdatedDetector.js +86 -16
  164. package/dist/core/outdatedDetector.js.map +1 -1
  165. package/dist/core/prDiff.d.ts +43 -0
  166. package/dist/core/prDiff.js +298 -0
  167. package/dist/core/prDiff.js.map +1 -0
  168. package/dist/core/telemetry.d.ts +90 -0
  169. package/dist/core/telemetry.js +199 -0
  170. package/dist/core/telemetry.js.map +1 -0
  171. package/dist/grammars/tree-sitter-go.wasm +0 -0
  172. package/dist/grammars/tree-sitter-java.wasm +0 -0
  173. package/dist/grammars/tree-sitter-ruby.wasm +0 -0
  174. package/dist/mcp/tools/_shared.d.ts +24 -0
  175. package/dist/mcp/tools/_shared.js +82 -0
  176. package/dist/mcp/tools/_shared.js.map +1 -0
  177. package/dist/mcp/tools/analyze.d.ts +2 -0
  178. package/dist/mcp/tools/analyze.js +55 -0
  179. package/dist/mcp/tools/analyze.js.map +1 -0
  180. package/dist/mcp/tools/audit.d.ts +2 -0
  181. package/dist/mcp/tools/audit.js +32 -0
  182. package/dist/mcp/tools/audit.js.map +1 -0
  183. package/dist/mcp/tools/coupling.d.ts +2 -0
  184. package/dist/mcp/tools/coupling.js +67 -0
  185. package/dist/mcp/tools/coupling.js.map +1 -0
  186. package/dist/mcp/tools/coverage.d.ts +2 -0
  187. package/dist/mcp/tools/coverage.js +53 -0
  188. package/dist/mcp/tools/coverage.js.map +1 -0
  189. package/dist/mcp/tools/dependencies.d.ts +2 -0
  190. package/dist/mcp/tools/dependencies.js +16 -0
  191. package/dist/mcp/tools/dependencies.js.map +1 -0
  192. package/dist/mcp/tools/doctor.d.ts +2 -0
  193. package/dist/mcp/tools/doctor.js +30 -0
  194. package/dist/mcp/tools/doctor.js.map +1 -0
  195. package/dist/mcp/tools/explain.d.ts +2 -0
  196. package/dist/mcp/tools/explain.js +30 -0
  197. package/dist/mcp/tools/explain.js.map +1 -0
  198. package/dist/mcp/tools/file.d.ts +2 -0
  199. package/dist/mcp/tools/file.js +22 -0
  200. package/dist/mcp/tools/file.js.map +1 -0
  201. package/dist/mcp/tools/graph.d.ts +2 -0
  202. package/dist/mcp/tools/graph.js +69 -0
  203. package/dist/mcp/tools/graph.js.map +1 -0
  204. package/dist/mcp/tools/hotspots.d.ts +2 -0
  205. package/dist/mcp/tools/hotspots.js +64 -0
  206. package/dist/mcp/tools/hotspots.js.map +1 -0
  207. package/dist/mcp/tools/outdated.d.ts +2 -0
  208. package/dist/mcp/tools/outdated.js +36 -0
  209. package/dist/mcp/tools/outdated.js.map +1 -0
  210. package/dist/mcp/tools/prDiff.d.ts +2 -0
  211. package/dist/mcp/tools/prDiff.js +38 -0
  212. package/dist/mcp/tools/prDiff.js.map +1 -0
  213. package/dist/mcp/tools/search.d.ts +2 -0
  214. package/dist/mcp/tools/search.js +167 -0
  215. package/dist/mcp/tools/search.js.map +1 -0
  216. package/dist/mcp/tools/structure.d.ts +2 -0
  217. package/dist/mcp/tools/structure.js +34 -0
  218. package/dist/mcp/tools/structure.js.map +1 -0
  219. package/dist/mcp/tools/upgrade.d.ts +2 -0
  220. package/dist/mcp/tools/upgrade.js +38 -0
  221. package/dist/mcp/tools/upgrade.js.map +1 -0
  222. package/dist/mcp/tools/workspaces.d.ts +2 -0
  223. package/dist/mcp/tools/workspaces.js +13 -0
  224. package/dist/mcp/tools/workspaces.js.map +1 -0
  225. package/dist/mcp/tools.d.ts +12 -6
  226. package/dist/mcp/tools.js +40 -605
  227. package/dist/mcp/tools.js.map +1 -1
  228. package/dist/reporters/consoleReporter.d.ts +4 -1
  229. package/dist/reporters/consoleReporter.js +113 -0
  230. package/dist/reporters/consoleReporter.js.map +1 -1
  231. package/dist/reporters/jsonReporter.d.ts +4 -1
  232. package/dist/reporters/jsonReporter.js +9 -0
  233. package/dist/reporters/jsonReporter.js.map +1 -1
  234. package/dist/reporters/markdownReporter.d.ts +4 -1
  235. package/dist/reporters/markdownReporter.js +103 -3
  236. package/dist/reporters/markdownReporter.js.map +1 -1
  237. package/dist/tool-manifest.json +358 -0
  238. package/dist/types.d.ts +115 -0
  239. package/dist/utils/cache.d.ts +3 -0
  240. package/dist/utils/cache.js +51 -0
  241. package/dist/utils/cache.js.map +1 -0
  242. 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 pkg;
73
+ let pkgJson;
26
74
  try {
27
- pkg = JSON.parse(raw);
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 dependencies = (pkg.dependencies ?? {});
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, // without registry lookup, installed is the best we know
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":"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"}
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 {};