@openrewrite/rewrite 8.72.2 → 8.72.3

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 (197) hide show
  1. package/dist/execution.js +3 -16
  2. package/dist/execution.js.map +1 -1
  3. package/dist/index.js +34 -49
  4. package/dist/index.js.map +1 -1
  5. package/dist/java/markers.js +12 -29
  6. package/dist/java/markers.js.map +1 -1
  7. package/dist/java/print.js +2 -13
  8. package/dist/java/print.js.map +1 -1
  9. package/dist/java/rpc.js +1344 -1725
  10. package/dist/java/rpc.js.map +1 -1
  11. package/dist/java/type-visitor.js +143 -184
  12. package/dist/java/type-visitor.js.map +1 -1
  13. package/dist/java/visitor.js +1072 -1249
  14. package/dist/java/visitor.js.map +1 -1
  15. package/dist/javascript/add-import.js +495 -534
  16. package/dist/javascript/add-import.js.map +1 -1
  17. package/dist/javascript/autodetect.js +116 -159
  18. package/dist/javascript/autodetect.js.map +1 -1
  19. package/dist/javascript/cleanup/add-parse-int-radix.js +41 -57
  20. package/dist/javascript/cleanup/add-parse-int-radix.js.map +1 -1
  21. package/dist/javascript/cleanup/prefer-optional-chain.js +89 -105
  22. package/dist/javascript/cleanup/prefer-optional-chain.js.map +1 -1
  23. package/dist/javascript/cleanup/use-object-property-shorthand.js +74 -95
  24. package/dist/javascript/cleanup/use-object-property-shorthand.js.map +1 -1
  25. package/dist/javascript/comparator.js +815 -1167
  26. package/dist/javascript/comparator.js.map +1 -1
  27. package/dist/javascript/dependency-workspace.js +206 -219
  28. package/dist/javascript/dependency-workspace.js.map +1 -1
  29. package/dist/javascript/format/format.js +682 -908
  30. package/dist/javascript/format/format.js.map +1 -1
  31. package/dist/javascript/format/minimum-viable-spacing-visitor.js +152 -231
  32. package/dist/javascript/format/minimum-viable-spacing-visitor.js.map +1 -1
  33. package/dist/javascript/format/normalize-whitespace-visitor.js +12 -31
  34. package/dist/javascript/format/normalize-whitespace-visitor.js.map +1 -1
  35. package/dist/javascript/format/prettier-config-loader.js +134 -153
  36. package/dist/javascript/format/prettier-config-loader.js.map +1 -1
  37. package/dist/javascript/format/prettier-format.js +112 -129
  38. package/dist/javascript/format/prettier-format.js.map +1 -1
  39. package/dist/javascript/format/tabs-and-indents-visitor.js +112 -136
  40. package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
  41. package/dist/javascript/markers.js +59 -92
  42. package/dist/javascript/markers.js.map +1 -1
  43. package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.js +39 -52
  44. package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.js.map +1 -1
  45. package/dist/javascript/migrate/es6/modernize-octal-literals.js +25 -38
  46. package/dist/javascript/migrate/es6/modernize-octal-literals.js.map +1 -1
  47. package/dist/javascript/migrate/es6/remove-duplicate-object-keys.js +66 -82
  48. package/dist/javascript/migrate/es6/remove-duplicate-object-keys.js.map +1 -1
  49. package/dist/javascript/migrate/typescript/export-assignment-to-export-default.js +10 -23
  50. package/dist/javascript/migrate/typescript/export-assignment-to-export-default.js.map +1 -1
  51. package/dist/javascript/node-resolution-result.js +137 -166
  52. package/dist/javascript/node-resolution-result.js.map +1 -1
  53. package/dist/javascript/package-json-parser.js +312 -343
  54. package/dist/javascript/package-json-parser.js.map +1 -1
  55. package/dist/javascript/package-manager.js +145 -170
  56. package/dist/javascript/package-manager.js.map +1 -1
  57. package/dist/javascript/parser.d.ts.map +1 -1
  58. package/dist/javascript/parser.js +94 -68
  59. package/dist/javascript/parser.js.map +1 -1
  60. package/dist/javascript/print.js +1572 -1835
  61. package/dist/javascript/print.js.map +1 -1
  62. package/dist/javascript/project-parser.js +151 -172
  63. package/dist/javascript/project-parser.js.map +1 -1
  64. package/dist/javascript/recipes/add-dependency.js +140 -175
  65. package/dist/javascript/recipes/add-dependency.js.map +1 -1
  66. package/dist/javascript/recipes/async-callback-in-sync-array-method.js +20 -36
  67. package/dist/javascript/recipes/async-callback-in-sync-array-method.js.map +1 -1
  68. package/dist/javascript/recipes/auto-format.js +3 -14
  69. package/dist/javascript/recipes/auto-format.js.map +1 -1
  70. package/dist/javascript/recipes/change-import.js +447 -495
  71. package/dist/javascript/recipes/change-import.js.map +1 -1
  72. package/dist/javascript/recipes/order-imports.js +162 -175
  73. package/dist/javascript/recipes/order-imports.js.map +1 -1
  74. package/dist/javascript/recipes/upgrade-dependency-version.js +167 -197
  75. package/dist/javascript/recipes/upgrade-dependency-version.js.map +1 -1
  76. package/dist/javascript/recipes/upgrade-transitive-dependency-version.js +166 -193
  77. package/dist/javascript/recipes/upgrade-transitive-dependency-version.js.map +1 -1
  78. package/dist/javascript/remove-import.js +689 -724
  79. package/dist/javascript/remove-import.js.map +1 -1
  80. package/dist/javascript/rpc.js +1007 -1332
  81. package/dist/javascript/rpc.js.map +1 -1
  82. package/dist/javascript/search/find-dependency.js +84 -110
  83. package/dist/javascript/search/find-dependency.js.map +1 -1
  84. package/dist/javascript/search/uses-method.js +5 -19
  85. package/dist/javascript/search/uses-method.js.map +1 -1
  86. package/dist/javascript/search/uses-type.js +9 -20
  87. package/dist/javascript/search/uses-type.js.map +1 -1
  88. package/dist/javascript/templating/comparator.js +737 -822
  89. package/dist/javascript/templating/comparator.js.map +1 -1
  90. package/dist/javascript/templating/engine.js +211 -245
  91. package/dist/javascript/templating/engine.js.map +1 -1
  92. package/dist/javascript/templating/pattern.js +169 -190
  93. package/dist/javascript/templating/pattern.js.map +1 -1
  94. package/dist/javascript/templating/placeholder-replacement.js +172 -210
  95. package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
  96. package/dist/javascript/templating/rewrite.js +75 -97
  97. package/dist/javascript/templating/rewrite.js.map +1 -1
  98. package/dist/javascript/templating/template.js +69 -82
  99. package/dist/javascript/templating/template.js.map +1 -1
  100. package/dist/javascript/tree-debug.js +109 -137
  101. package/dist/javascript/tree-debug.js.map +1 -1
  102. package/dist/javascript/visitor.js +1090 -1254
  103. package/dist/javascript/visitor.js.map +1 -1
  104. package/dist/json/print.js +72 -103
  105. package/dist/json/print.js.map +1 -1
  106. package/dist/json/rpc.js +120 -181
  107. package/dist/json/rpc.js.map +1 -1
  108. package/dist/json/visitor.js +69 -100
  109. package/dist/json/visitor.js.map +1 -1
  110. package/dist/marketplace.js +20 -33
  111. package/dist/marketplace.js.map +1 -1
  112. package/dist/parse-error.js +41 -62
  113. package/dist/parse-error.js.map +1 -1
  114. package/dist/parser.js +7 -18
  115. package/dist/parser.js.map +1 -1
  116. package/dist/path-utils.js +46 -59
  117. package/dist/path-utils.js.map +1 -1
  118. package/dist/preconditions.js +30 -47
  119. package/dist/preconditions.js.map +1 -1
  120. package/dist/print.js +6 -19
  121. package/dist/print.js.map +1 -1
  122. package/dist/recipe.js +42 -73
  123. package/dist/recipe.js.map +1 -1
  124. package/dist/rpc/index.js +74 -115
  125. package/dist/rpc/index.js.map +1 -1
  126. package/dist/rpc/queue.js +71 -90
  127. package/dist/rpc/queue.js.map +1 -1
  128. package/dist/rpc/recipe.js +32 -57
  129. package/dist/rpc/recipe.js.map +1 -1
  130. package/dist/rpc/request/generate.js +4 -13
  131. package/dist/rpc/request/generate.js.map +1 -1
  132. package/dist/rpc/request/get-languages.js +2 -11
  133. package/dist/rpc/request/get-languages.js.map +1 -1
  134. package/dist/rpc/request/get-marketplace.js +9 -20
  135. package/dist/rpc/request/get-marketplace.js.map +1 -1
  136. package/dist/rpc/request/get-object.js +4 -13
  137. package/dist/rpc/request/get-object.js.map +1 -1
  138. package/dist/rpc/request/install-recipes.js +25 -36
  139. package/dist/rpc/request/install-recipes.js.map +1 -1
  140. package/dist/rpc/request/metrics.js +8 -17
  141. package/dist/rpc/request/metrics.js.map +1 -1
  142. package/dist/rpc/request/parse-project.js +36 -45
  143. package/dist/rpc/request/parse-project.js.map +1 -1
  144. package/dist/rpc/request/parse.js +5 -14
  145. package/dist/rpc/request/parse.js.map +1 -1
  146. package/dist/rpc/request/prepare-recipe.js +37 -52
  147. package/dist/rpc/request/prepare-recipe.js.map +1 -1
  148. package/dist/rpc/request/print.js +5 -14
  149. package/dist/rpc/request/print.js.map +1 -1
  150. package/dist/rpc/request/visit.js +56 -71
  151. package/dist/rpc/request/visit.js.map +1 -1
  152. package/dist/rpc/rewrite-rpc.js +70 -97
  153. package/dist/rpc/rewrite-rpc.js.map +1 -1
  154. package/dist/rpc/server.js +76 -89
  155. package/dist/rpc/server.js.map +1 -1
  156. package/dist/run.js +47 -66
  157. package/dist/run.js.map +1 -1
  158. package/dist/search/is-source-file.js +8 -19
  159. package/dist/search/is-source-file.js.map +1 -1
  160. package/dist/test/rewrite-test.js +154 -188
  161. package/dist/test/rewrite-test.js.map +1 -1
  162. package/dist/text/print.js +23 -38
  163. package/dist/text/print.js.map +1 -1
  164. package/dist/text/rpc.js +29 -44
  165. package/dist/text/rpc.js.map +1 -1
  166. package/dist/text/visitor.js +16 -33
  167. package/dist/text/visitor.js.map +1 -1
  168. package/dist/util.js +13 -24
  169. package/dist/util.js.map +1 -1
  170. package/dist/version.txt +1 -1
  171. package/dist/visitor.js +84 -115
  172. package/dist/visitor.js.map +1 -1
  173. package/dist/yaml/index.d.ts +2 -0
  174. package/dist/yaml/index.d.ts.map +1 -1
  175. package/dist/yaml/index.js +2 -0
  176. package/dist/yaml/index.js.map +1 -1
  177. package/dist/yaml/markers.d.ts +21 -0
  178. package/dist/yaml/markers.d.ts.map +1 -0
  179. package/dist/yaml/markers.js +37 -0
  180. package/dist/yaml/markers.js.map +1 -0
  181. package/dist/yaml/parser.d.ts.map +1 -1
  182. package/dist/yaml/parser.js +4 -1
  183. package/dist/yaml/parser.js.map +1 -1
  184. package/dist/yaml/print.d.ts +1 -1
  185. package/dist/yaml/print.d.ts.map +1 -1
  186. package/dist/yaml/print.js +175 -208
  187. package/dist/yaml/print.js.map +1 -1
  188. package/dist/yaml/rpc.js +154 -219
  189. package/dist/yaml/rpc.js.map +1 -1
  190. package/dist/yaml/visitor.js +78 -113
  191. package/dist/yaml/visitor.js.map +1 -1
  192. package/package.json +1 -1
  193. package/src/javascript/parser.ts +56 -14
  194. package/src/yaml/index.ts +2 -0
  195. package/src/yaml/markers.ts +70 -0
  196. package/src/yaml/parser.ts +5 -1
  197. package/src/yaml/print.ts +5 -2
@@ -32,15 +32,6 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
- return new (P || (P = Promise))(function (resolve, reject) {
38
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
- step((generator = generator.apply(thisArg, _arguments || [])).next());
42
- });
43
- };
44
35
  var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
45
36
  var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
46
37
  if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
@@ -180,56 +171,54 @@ class PackageJsonParser extends parser_1.Parser {
180
171
  /**
181
172
  * Creates a NodeResolutionResult marker from the package.json content and optional lock file.
182
173
  */
183
- createMarker(input, dir) {
184
- return __awaiter(this, void 0, void 0, function* () {
185
- try {
186
- const content = (0, parser_1.parserInputRead)(input);
187
- const packageJson = JSON.parse(content);
188
- // Determine the relative path for the marker
189
- const filePath = (0, parser_1.parserInputFile)(input);
190
- const relativePath = this.relativeTo
191
- ? path.relative(this.relativeTo, filePath)
192
- : filePath;
193
- // Try to read lock file if dependency resolution is not skipped
194
- // First try the directory containing the package.json, then walk up toward relativeTo
195
- let lockContent = undefined;
196
- let packageManager = undefined;
197
- if (!this.skipDependencyResolution) {
198
- // Resolve dir relative to relativeTo if dir is relative (e.g., '.' when package.json is at root)
199
- const absoluteDir = this.relativeTo && !path.isAbsolute(dir)
200
- ? path.resolve(this.relativeTo, dir)
201
- : dir;
202
- const lockResult = yield this.tryReadLockFileWithWalkUp(absoluteDir, this.relativeTo);
203
- lockContent = lockResult === null || lockResult === void 0 ? void 0 : lockResult.content;
204
- packageManager = lockResult === null || lockResult === void 0 ? void 0 : lockResult.packageManager;
205
- }
206
- // Read .npmrc configurations from all scopes
207
- const projectDir = this.relativeTo || dir;
208
- const npmrcConfigs = yield (0, node_resolution_result_1.readNpmrcConfigs)(projectDir);
209
- // Detect workspace member paths if this is a workspace root
210
- // Check both package.json workspaces (npm/yarn) and pnpm-workspace.yaml (pnpm)
211
- let workspacePackagePaths;
174
+ async createMarker(input, dir) {
175
+ try {
176
+ const content = (0, parser_1.parserInputRead)(input);
177
+ const packageJson = JSON.parse(content);
178
+ // Determine the relative path for the marker
179
+ const filePath = (0, parser_1.parserInputFile)(input);
180
+ const relativePath = this.relativeTo
181
+ ? path.relative(this.relativeTo, filePath)
182
+ : filePath;
183
+ // Try to read lock file if dependency resolution is not skipped
184
+ // First try the directory containing the package.json, then walk up toward relativeTo
185
+ let lockContent = undefined;
186
+ let packageManager = undefined;
187
+ if (!this.skipDependencyResolution) {
188
+ // Resolve dir relative to relativeTo if dir is relative (e.g., '.' when package.json is at root)
212
189
  const absoluteDir = this.relativeTo && !path.isAbsolute(dir)
213
190
  ? path.resolve(this.relativeTo, dir)
214
191
  : dir;
215
- if (packageJson.workspaces) {
216
- // npm/yarn style workspaces defined in package.json
217
- workspacePackagePaths = yield this.resolveWorkspacePackagePaths(packageJson.workspaces, absoluteDir, this.relativeTo);
218
- }
219
- else if (packageManager === node_resolution_result_1.PackageManager.Pnpm) {
220
- // pnpm workspaces defined in pnpm-workspace.yaml
221
- const pnpmWorkspacePatterns = yield this.readPnpmWorkspacePatterns(absoluteDir);
222
- if (pnpmWorkspacePatterns && pnpmWorkspacePatterns.length > 0) {
223
- workspacePackagePaths = yield this.resolveWorkspacePackagePaths(pnpmWorkspacePatterns, absoluteDir, this.relativeTo);
224
- }
225
- }
226
- return (0, node_resolution_result_1.createNodeResolutionResultMarker)(relativePath, packageJson, lockContent, workspacePackagePaths, packageManager, npmrcConfigs.length > 0 ? npmrcConfigs : undefined);
227
- }
228
- catch (error) {
229
- console.warn(`Failed to create NodeResolutionResult marker: ${error}`);
230
- return null;
231
- }
232
- });
192
+ const lockResult = await this.tryReadLockFileWithWalkUp(absoluteDir, this.relativeTo);
193
+ lockContent = lockResult === null || lockResult === void 0 ? void 0 : lockResult.content;
194
+ packageManager = lockResult === null || lockResult === void 0 ? void 0 : lockResult.packageManager;
195
+ }
196
+ // Read .npmrc configurations from all scopes
197
+ const projectDir = this.relativeTo || dir;
198
+ const npmrcConfigs = await (0, node_resolution_result_1.readNpmrcConfigs)(projectDir);
199
+ // Detect workspace member paths if this is a workspace root
200
+ // Check both package.json workspaces (npm/yarn) and pnpm-workspace.yaml (pnpm)
201
+ let workspacePackagePaths;
202
+ const absoluteDir = this.relativeTo && !path.isAbsolute(dir)
203
+ ? path.resolve(this.relativeTo, dir)
204
+ : dir;
205
+ if (packageJson.workspaces) {
206
+ // npm/yarn style workspaces defined in package.json
207
+ workspacePackagePaths = await this.resolveWorkspacePackagePaths(packageJson.workspaces, absoluteDir, this.relativeTo);
208
+ }
209
+ else if (packageManager === node_resolution_result_1.PackageManager.Pnpm) {
210
+ // pnpm workspaces defined in pnpm-workspace.yaml
211
+ const pnpmWorkspacePatterns = await this.readPnpmWorkspacePatterns(absoluteDir);
212
+ if (pnpmWorkspacePatterns && pnpmWorkspacePatterns.length > 0) {
213
+ workspacePackagePaths = await this.resolveWorkspacePackagePaths(pnpmWorkspacePatterns, absoluteDir, this.relativeTo);
214
+ }
215
+ }
216
+ return (0, node_resolution_result_1.createNodeResolutionResultMarker)(relativePath, packageJson, lockContent, workspacePackagePaths, packageManager, npmrcConfigs.length > 0 ? npmrcConfigs : undefined);
217
+ }
218
+ catch (error) {
219
+ console.warn(`Failed to create NodeResolutionResult marker: ${error}`);
220
+ return null;
221
+ }
233
222
  }
234
223
  /**
235
224
  * Resolves workspace glob patterns to actual package.json paths.
@@ -244,74 +233,70 @@ class PackageJsonParser extends parser_1.Parser {
244
233
  * @param relativeTo Optional base path for creating relative paths
245
234
  * @returns Array of relative paths to workspace member package.json files
246
235
  */
247
- resolveWorkspacePackagePaths(workspaces, projectDir, relativeTo) {
248
- return __awaiter(this, void 0, void 0, function* () {
249
- // Normalize workspaces to array format
250
- const patterns = Array.isArray(workspaces)
251
- ? workspaces
252
- : workspaces.packages;
253
- if (!patterns || patterns.length === 0) {
254
- return undefined;
255
- }
256
- // Separate include and exclude patterns
257
- const includePatterns = patterns.filter(p => !p.startsWith('!'));
258
- const excludePatterns = patterns.filter(p => p.startsWith('!')).map(p => p.slice(1));
259
- // Create picomatch matchers
260
- const isIncluded = includePatterns.length > 0
261
- ? (0, picomatch_1.default)(includePatterns, { dot: false })
262
- : () => false;
263
- const isExcluded = excludePatterns.length > 0
264
- ? (0, picomatch_1.default)(excludePatterns, { dot: false })
265
- : () => false;
266
- // Collect all candidate directories by walking the project
267
- const candidateDirs = yield this.collectCandidateWorkspaceDirs(projectDir, includePatterns);
268
- const memberPaths = [];
269
- const basePath = relativeTo || projectDir;
270
- for (const candidateDir of candidateDirs) {
271
- // Get relative path from project root for pattern matching
272
- const relativeDir = path.relative(projectDir, candidateDir);
273
- // Check if directory matches include patterns and not exclude patterns
274
- if (isIncluded(relativeDir) && !isExcluded(relativeDir)) {
275
- const packageJsonPath = path.join(candidateDir, 'package.json');
276
- if (fs.existsSync(packageJsonPath)) {
277
- const relativePath = path.relative(basePath, packageJsonPath);
278
- memberPaths.push(relativePath);
279
- }
236
+ async resolveWorkspacePackagePaths(workspaces, projectDir, relativeTo) {
237
+ // Normalize workspaces to array format
238
+ const patterns = Array.isArray(workspaces)
239
+ ? workspaces
240
+ : workspaces.packages;
241
+ if (!patterns || patterns.length === 0) {
242
+ return undefined;
243
+ }
244
+ // Separate include and exclude patterns
245
+ const includePatterns = patterns.filter(p => !p.startsWith('!'));
246
+ const excludePatterns = patterns.filter(p => p.startsWith('!')).map(p => p.slice(1));
247
+ // Create picomatch matchers
248
+ const isIncluded = includePatterns.length > 0
249
+ ? (0, picomatch_1.default)(includePatterns, { dot: false })
250
+ : () => false;
251
+ const isExcluded = excludePatterns.length > 0
252
+ ? (0, picomatch_1.default)(excludePatterns, { dot: false })
253
+ : () => false;
254
+ // Collect all candidate directories by walking the project
255
+ const candidateDirs = await this.collectCandidateWorkspaceDirs(projectDir, includePatterns);
256
+ const memberPaths = [];
257
+ const basePath = relativeTo || projectDir;
258
+ for (const candidateDir of candidateDirs) {
259
+ // Get relative path from project root for pattern matching
260
+ const relativeDir = path.relative(projectDir, candidateDir);
261
+ // Check if directory matches include patterns and not exclude patterns
262
+ if (isIncluded(relativeDir) && !isExcluded(relativeDir)) {
263
+ const packageJsonPath = path.join(candidateDir, 'package.json');
264
+ if (fs.existsSync(packageJsonPath)) {
265
+ const relativePath = path.relative(basePath, packageJsonPath);
266
+ memberPaths.push(relativePath);
280
267
  }
281
268
  }
282
- return memberPaths.length > 0 ? memberPaths : undefined;
283
- });
269
+ }
270
+ return memberPaths.length > 0 ? memberPaths : undefined;
284
271
  }
285
272
  /**
286
273
  * Collects candidate directories that might match workspace patterns.
287
274
  * Uses the patterns to determine how deep to scan.
288
275
  */
289
- collectCandidateWorkspaceDirs(projectDir, patterns) {
290
- return __awaiter(this, void 0, void 0, function* () {
291
- const candidates = [];
292
- // Determine the maximum depth we need to scan based on patterns
293
- // "packages/*" -> depth 1 under packages/
294
- // "packages/**" -> unlimited depth under packages/
295
- // "{apps,libs}/*" -> depth 1 under apps/ and libs/
296
- for (const pattern of patterns) {
297
- // Extract base directories from pattern (before any wildcards)
298
- const baseDirs = this.extractBaseDirs(pattern);
299
- const hasRecursive = pattern.includes('**');
300
- for (const baseDir of baseDirs) {
301
- const absoluteBaseDir = path.join(projectDir, baseDir);
302
- if (!fs.existsSync(absoluteBaseDir)) {
303
- continue;
304
- }
305
- // Use walkDirs with appropriate depth limit
306
- const dirs = yield (0, path_utils_1.walkDirs)(absoluteBaseDir, {
307
- maxDepth: hasRecursive ? undefined : 0,
308
- excludeDirs: path_utils_1.DEFAULT_DIR_EXCLUSIONS
309
- });
310
- candidates.push(...dirs);
276
+ async collectCandidateWorkspaceDirs(projectDir, patterns) {
277
+ const candidates = [];
278
+ // Determine the maximum depth we need to scan based on patterns
279
+ // "packages/*" -> depth 1 under packages/
280
+ // "packages/**" -> unlimited depth under packages/
281
+ // "{apps,libs}/*" -> depth 1 under apps/ and libs/
282
+ for (const pattern of patterns) {
283
+ // Extract base directories from pattern (before any wildcards)
284
+ const baseDirs = this.extractBaseDirs(pattern);
285
+ const hasRecursive = pattern.includes('**');
286
+ for (const baseDir of baseDirs) {
287
+ const absoluteBaseDir = path.join(projectDir, baseDir);
288
+ if (!fs.existsSync(absoluteBaseDir)) {
289
+ continue;
311
290
  }
291
+ // Use walkDirs with appropriate depth limit
292
+ const dirs = await (0, path_utils_1.walkDirs)(absoluteBaseDir, {
293
+ maxDepth: hasRecursive ? undefined : 0,
294
+ excludeDirs: path_utils_1.DEFAULT_DIR_EXCLUSIONS
295
+ });
296
+ candidates.push(...dirs);
312
297
  }
313
- return candidates;
314
- });
298
+ }
299
+ return candidates;
315
300
  }
316
301
  /**
317
302
  * Extracts base directory paths from a glob pattern.
@@ -346,22 +331,20 @@ class PackageJsonParser extends parser_1.Parser {
346
331
  * @param projectDir The absolute path to the project directory
347
332
  * @returns Array of workspace patterns, or undefined if file doesn't exist
348
333
  */
349
- readPnpmWorkspacePatterns(projectDir) {
350
- return __awaiter(this, void 0, void 0, function* () {
351
- const pnpmWorkspacePath = path.join(projectDir, 'pnpm-workspace.yaml');
352
- try {
353
- const content = yield fsp.readFile(pnpmWorkspacePath, 'utf-8');
354
- const parsed = YAML.parse(content);
355
- if (parsed && Array.isArray(parsed.packages)) {
356
- return parsed.packages;
357
- }
358
- return undefined;
359
- }
360
- catch (_a) {
361
- // File doesn't exist or couldn't be parsed
362
- return undefined;
334
+ async readPnpmWorkspacePatterns(projectDir) {
335
+ const pnpmWorkspacePath = path.join(projectDir, 'pnpm-workspace.yaml');
336
+ try {
337
+ const content = await fsp.readFile(pnpmWorkspacePath, 'utf-8');
338
+ const parsed = YAML.parse(content);
339
+ if (parsed && Array.isArray(parsed.packages)) {
340
+ return parsed.packages;
363
341
  }
364
- });
342
+ return undefined;
343
+ }
344
+ catch (_a) {
345
+ // File doesn't exist or couldn't be parsed
346
+ return undefined;
347
+ }
365
348
  }
366
349
  /**
367
350
  * Attempts to find and read a lock file by walking up the directory tree.
@@ -375,30 +358,28 @@ class PackageJsonParser extends parser_1.Parser {
375
358
  * @param rootDir Optional root directory to stop walking at (e.g., relativeTo/git root)
376
359
  * @returns Object with parsed lock file content and detected package manager, or undefined if none found
377
360
  */
378
- tryReadLockFileWithWalkUp(startDir, rootDir) {
379
- return __awaiter(this, void 0, void 0, function* () {
380
- // Normalize paths for comparison
381
- const normalizedRoot = rootDir ? path.resolve(rootDir) : undefined;
382
- let currentDir = path.resolve(startDir);
383
- // Walk up the directory tree looking for a lock file
384
- while (true) {
385
- const result = yield this.tryReadLockFile(currentDir);
386
- if (result) {
387
- return result;
388
- }
389
- // If we've reached rootDir, stop walking (don't go above it)
390
- if (normalizedRoot && currentDir === normalizedRoot) {
391
- break;
392
- }
393
- // Check if we've reached the filesystem root
394
- const parentDir = path.dirname(currentDir);
395
- if (parentDir === currentDir) {
396
- break;
397
- }
398
- currentDir = parentDir;
399
- }
400
- return undefined;
401
- });
361
+ async tryReadLockFileWithWalkUp(startDir, rootDir) {
362
+ // Normalize paths for comparison
363
+ const normalizedRoot = rootDir ? path.resolve(rootDir) : undefined;
364
+ let currentDir = path.resolve(startDir);
365
+ // Walk up the directory tree looking for a lock file
366
+ while (true) {
367
+ const result = await this.tryReadLockFile(currentDir);
368
+ if (result) {
369
+ return result;
370
+ }
371
+ // If we've reached rootDir, stop walking (don't go above it)
372
+ if (normalizedRoot && currentDir === normalizedRoot) {
373
+ break;
374
+ }
375
+ // Check if we've reached the filesystem root
376
+ const parentDir = path.dirname(currentDir);
377
+ if (parentDir === currentDir) {
378
+ break;
379
+ }
380
+ currentDir = parentDir;
381
+ }
382
+ return undefined;
402
383
  }
403
384
  /**
404
385
  * Attempts to read and parse a lock file from the given directory.
@@ -406,76 +387,72 @@ class PackageJsonParser extends parser_1.Parser {
406
387
  *
407
388
  * @returns Object with parsed lock file content and detected package manager, or undefined if no lock file found
408
389
  */
409
- tryReadLockFile(dir) {
410
- return __awaiter(this, void 0, void 0, function* () {
411
- var _a;
412
- // Use shared lock file detection config (first match wins based on priority)
413
- for (const config of (0, package_manager_1.getLockFileDetectionConfig)()) {
414
- const lockPath = path.join(dir, config.filename);
415
- if (!fs.existsSync(lockPath)) {
416
- continue;
417
- }
418
- // Lock file exists - determine package manager
419
- // Once we find a lock file, we commit to this package manager even if parsing fails
420
- try {
421
- const fileContent = yield fsp.readFile(lockPath, 'utf-8');
422
- const packageManager = typeof config.packageManager === 'function'
423
- ? config.packageManager(fileContent)
424
- : config.packageManager;
425
- // For package managers where lock file omits details, prefer node_modules
426
- if (config.preferNodeModules) {
427
- const parsed = yield this.walkNodeModules(dir);
428
- if (parsed) {
429
- return { content: parsed, packageManager };
430
- }
431
- }
432
- // Parse lock file based on package manager
433
- const content = yield this.parseLockFileContent(config.filename, fileContent, dir);
434
- if (content) {
435
- return { content, packageManager };
390
+ async tryReadLockFile(dir) {
391
+ var _a;
392
+ // Use shared lock file detection config (first match wins based on priority)
393
+ for (const config of (0, package_manager_1.getLockFileDetectionConfig)()) {
394
+ const lockPath = path.join(dir, config.filename);
395
+ if (!fs.existsSync(lockPath)) {
396
+ continue;
397
+ }
398
+ // Lock file exists - determine package manager
399
+ // Once we find a lock file, we commit to this package manager even if parsing fails
400
+ try {
401
+ const fileContent = await fsp.readFile(lockPath, 'utf-8');
402
+ const packageManager = typeof config.packageManager === 'function'
403
+ ? config.packageManager(fileContent)
404
+ : config.packageManager;
405
+ // For package managers where lock file omits details, prefer node_modules
406
+ if (config.preferNodeModules) {
407
+ const parsed = await this.walkNodeModules(dir);
408
+ if (parsed) {
409
+ return { content: parsed, packageManager };
436
410
  }
437
- // Lock file exists but couldn't be parsed - still return the package manager
438
- // This ensures we use the correct package manager even without resolved dependencies
439
- return { content: { lockfileVersion: 0, packages: {} }, packageManager };
440
411
  }
441
- catch (error) {
442
- (_a = console.debug) === null || _a === void 0 ? void 0 : _a.call(console, `Failed to parse ${config.filename}: ${error}`);
443
- // Even on error, we found this lock file - return the package manager with empty content
444
- const packageManager = typeof config.packageManager === 'function'
445
- ? node_resolution_result_1.PackageManager.YarnClassic // Default for yarn.lock if we can't read content
446
- : config.packageManager;
447
- return { content: { lockfileVersion: 0, packages: {} }, packageManager };
412
+ // Parse lock file based on package manager
413
+ const content = await this.parseLockFileContent(config.filename, fileContent, dir);
414
+ if (content) {
415
+ return { content, packageManager };
448
416
  }
417
+ // Lock file exists but couldn't be parsed - still return the package manager
418
+ // This ensures we use the correct package manager even without resolved dependencies
419
+ return { content: { lockfileVersion: 0, packages: {} }, packageManager };
449
420
  }
450
- // Fallback: if node_modules exists but no lock file was found (e.g., symlinked from another workspace),
451
- // walk node_modules to get resolved dependency information
452
- const parsed = yield this.walkNodeModules(dir);
453
- if (parsed) {
454
- // Assume npm as the default package manager when only node_modules exists
455
- return { content: parsed, packageManager: node_resolution_result_1.PackageManager.Npm };
421
+ catch (error) {
422
+ (_a = console.debug) === null || _a === void 0 ? void 0 : _a.call(console, `Failed to parse ${config.filename}: ${error}`);
423
+ // Even on error, we found this lock file - return the package manager with empty content
424
+ const packageManager = typeof config.packageManager === 'function'
425
+ ? node_resolution_result_1.PackageManager.YarnClassic // Default for yarn.lock if we can't read content
426
+ : config.packageManager;
427
+ return { content: { lockfileVersion: 0, packages: {} }, packageManager };
456
428
  }
457
- return undefined;
458
- });
429
+ }
430
+ // Fallback: if node_modules exists but no lock file was found (e.g., symlinked from another workspace),
431
+ // walk node_modules to get resolved dependency information
432
+ const parsed = await this.walkNodeModules(dir);
433
+ if (parsed) {
434
+ // Assume npm as the default package manager when only node_modules exists
435
+ return { content: parsed, packageManager: node_resolution_result_1.PackageManager.Npm };
436
+ }
437
+ return undefined;
459
438
  }
460
439
  /**
461
440
  * Parses lock file content based on the lock file type.
462
441
  */
463
- parseLockFileContent(filename, content, dir) {
464
- return __awaiter(this, void 0, void 0, function* () {
465
- switch (filename) {
466
- case 'package-lock.json':
467
- return JSON.parse(content);
468
- case 'bun.lock':
469
- return this.convertBunLockToNpmFormat(this.parseJsonc(content));
470
- case 'pnpm-lock.yaml':
471
- // Fall back to pnpm CLI when node_modules unavailable
472
- return this.getPnpmDependencies(dir);
473
- case 'yarn.lock':
474
- return this.parseYarnLock(content);
475
- default:
476
- return undefined;
477
- }
478
- });
442
+ async parseLockFileContent(filename, content, dir) {
443
+ switch (filename) {
444
+ case 'package-lock.json':
445
+ return JSON.parse(content);
446
+ case 'bun.lock':
447
+ return this.convertBunLockToNpmFormat(this.parseJsonc(content));
448
+ case 'pnpm-lock.yaml':
449
+ // Fall back to pnpm CLI when node_modules unavailable
450
+ return this.getPnpmDependencies(dir);
451
+ case 'yarn.lock':
452
+ return this.parseYarnLock(content);
453
+ default:
454
+ return undefined;
455
+ }
479
456
  }
480
457
  /**
481
458
  * Parses JSONC (JSON with Comments and trailing commas) content.
@@ -492,82 +469,78 @@ class PackageJsonParser extends parser_1.Parser {
492
469
  * @param dir The project directory containing node_modules
493
470
  * @returns npm package-lock.json format with packages map, or undefined if node_modules doesn't exist
494
471
  */
495
- walkNodeModules(dir) {
496
- return __awaiter(this, void 0, void 0, function* () {
497
- const nodeModulesPath = path.join(dir, 'node_modules');
498
- if (!fs.existsSync(nodeModulesPath)) {
499
- return undefined;
500
- }
501
- const packages = {
502
- "": {} // Root package placeholder
503
- };
504
- // Check if this is a pnpm project (has .pnpm directory)
505
- const pnpmPath = path.join(nodeModulesPath, '.pnpm');
506
- if (fs.existsSync(pnpmPath)) {
507
- yield this.walkPnpmNodeModules(pnpmPath, packages);
508
- }
509
- else {
510
- yield this.walkNodeModulesRecursive(nodeModulesPath, 'node_modules', packages);
511
- }
512
- return Object.keys(packages).length > 1 ? {
513
- lockfileVersion: 3,
514
- packages
515
- } : undefined;
516
- });
472
+ async walkNodeModules(dir) {
473
+ const nodeModulesPath = path.join(dir, 'node_modules');
474
+ if (!fs.existsSync(nodeModulesPath)) {
475
+ return undefined;
476
+ }
477
+ const packages = {
478
+ "": {} // Root package placeholder
479
+ };
480
+ // Check if this is a pnpm project (has .pnpm directory)
481
+ const pnpmPath = path.join(nodeModulesPath, '.pnpm');
482
+ if (fs.existsSync(pnpmPath)) {
483
+ await this.walkPnpmNodeModules(pnpmPath, packages);
484
+ }
485
+ else {
486
+ await this.walkNodeModulesRecursive(nodeModulesPath, 'node_modules', packages);
487
+ }
488
+ return Object.keys(packages).length > 1 ? {
489
+ lockfileVersion: 3,
490
+ packages
491
+ } : undefined;
517
492
  }
518
493
  /**
519
494
  * Walks pnpm's .pnpm directory structure to build packages map.
520
495
  * pnpm stores packages in .pnpm/<name>@<version>/node_modules/<name>/
521
496
  */
522
- walkPnpmNodeModules(pnpmPath, packages) {
523
- return __awaiter(this, void 0, void 0, function* () {
524
- let entries;
497
+ async walkPnpmNodeModules(pnpmPath, packages) {
498
+ let entries;
499
+ try {
500
+ entries = await fsp.readdir(pnpmPath, { withFileTypes: true });
501
+ }
502
+ catch (_a) {
503
+ return;
504
+ }
505
+ // Process entries in parallel for better performance
506
+ await Promise.all(entries.map(async (entry) => {
507
+ // Skip non-directories and special files
508
+ if (!entry.isDirectory() || entry.name === 'node_modules') {
509
+ return;
510
+ }
511
+ // Parse name@version from directory name
512
+ // pnpm directory format: <name>@<version> or <name>@<version>_<peer-deps-context>
513
+ // Handle scoped packages: @scope+name@version
514
+ // Example: @babel+helper-module-transforms@7.28.3_@babel+core@7.28.5
515
+ // -> name: @babel/helper-module-transforms, version: 7.28.3
516
+ // First, strip peer dependency context (everything after first _)
517
+ const underscoreIndex = entry.name.indexOf('_');
518
+ const mainPart = underscoreIndex > 0 ? entry.name.substring(0, underscoreIndex) : entry.name;
519
+ // Now parse name@version from the main part
520
+ const atIndex = mainPart.lastIndexOf('@');
521
+ if (atIndex <= 0)
522
+ return;
523
+ let name = mainPart.substring(0, atIndex);
524
+ const version = mainPart.substring(atIndex + 1);
525
+ // pnpm encodes @ as + in scoped packages: @scope+name -> @scope/name
526
+ if (name.startsWith('@') && name.includes('+')) {
527
+ name = name.replace('+', '/');
528
+ }
529
+ // The actual package is at .pnpm/<name>@<version>/node_modules/<name>/
530
+ const pkgDir = path.join(pnpmPath, entry.name, 'node_modules', name.replace('/', path.sep));
531
+ const packageJsonPath = path.join(pkgDir, 'package.json');
532
+ let pkgJson;
525
533
  try {
526
- entries = yield fsp.readdir(pnpmPath, { withFileTypes: true });
534
+ const content = await fsp.readFile(packageJsonPath, 'utf-8');
535
+ pkgJson = JSON.parse(content);
527
536
  }
528
537
  catch (_a) {
529
538
  return;
530
539
  }
531
- // Process entries in parallel for better performance
532
- yield Promise.all(entries.map((entry) => __awaiter(this, void 0, void 0, function* () {
533
- // Skip non-directories and special files
534
- if (!entry.isDirectory() || entry.name === 'node_modules') {
535
- return;
536
- }
537
- // Parse name@version from directory name
538
- // pnpm directory format: <name>@<version> or <name>@<version>_<peer-deps-context>
539
- // Handle scoped packages: @scope+name@version
540
- // Example: @babel+helper-module-transforms@7.28.3_@babel+core@7.28.5
541
- // -> name: @babel/helper-module-transforms, version: 7.28.3
542
- // First, strip peer dependency context (everything after first _)
543
- const underscoreIndex = entry.name.indexOf('_');
544
- const mainPart = underscoreIndex > 0 ? entry.name.substring(0, underscoreIndex) : entry.name;
545
- // Now parse name@version from the main part
546
- const atIndex = mainPart.lastIndexOf('@');
547
- if (atIndex <= 0)
548
- return;
549
- let name = mainPart.substring(0, atIndex);
550
- const version = mainPart.substring(atIndex + 1);
551
- // pnpm encodes @ as + in scoped packages: @scope+name -> @scope/name
552
- if (name.startsWith('@') && name.includes('+')) {
553
- name = name.replace('+', '/');
554
- }
555
- // The actual package is at .pnpm/<name>@<version>/node_modules/<name>/
556
- const pkgDir = path.join(pnpmPath, entry.name, 'node_modules', name.replace('/', path.sep));
557
- const packageJsonPath = path.join(pkgDir, 'package.json');
558
- let pkgJson;
559
- try {
560
- const content = yield fsp.readFile(packageJsonPath, 'utf-8');
561
- pkgJson = JSON.parse(content);
562
- }
563
- catch (_a) {
564
- return;
565
- }
566
- // Use name@version as the key for pnpm (flat structure with version)
567
- const pkgKey = `node_modules/${name}@${version}`;
568
- packages[pkgKey] = PackageJsonParser.extractPackageMetadata(pkgJson, version);
569
- })));
570
- });
540
+ // Use name@version as the key for pnpm (flat structure with version)
541
+ const pkgKey = `node_modules/${name}@${version}`;
542
+ packages[pkgKey] = PackageJsonParser.extractPackageMetadata(pkgJson, version);
543
+ }));
571
544
  }
572
545
  /**
573
546
  * Recursively walks a node_modules directory, reading package.json files
@@ -577,79 +550,75 @@ class PackageJsonParser extends parser_1.Parser {
577
550
  * @param relativePath Relative path from project root (e.g., "node_modules" or "node_modules/foo/node_modules")
578
551
  * @param packages The packages map to populate
579
552
  */
580
- walkNodeModulesRecursive(nodeModulesPath, relativePath, packages) {
581
- return __awaiter(this, void 0, void 0, function* () {
582
- let entries;
583
- try {
584
- entries = yield fsp.readdir(nodeModulesPath, { withFileTypes: true });
553
+ async walkNodeModulesRecursive(nodeModulesPath, relativePath, packages) {
554
+ let entries;
555
+ try {
556
+ entries = await fsp.readdir(nodeModulesPath, { withFileTypes: true });
557
+ }
558
+ catch (_a) {
559
+ return; // Directory not readable
560
+ }
561
+ // Process entries in parallel for better performance
562
+ await Promise.all(entries.map(async (entry) => {
563
+ // Skip hidden files
564
+ if (entry.name.startsWith('.')) {
565
+ return;
585
566
  }
586
- catch (_a) {
587
- return; // Directory not readable
567
+ // Accept directories and symlinks (pnpm uses symlinks)
568
+ const isDirectoryOrSymlink = entry.isDirectory() || entry.isSymbolicLink();
569
+ if (!isDirectoryOrSymlink) {
570
+ return;
588
571
  }
589
- // Process entries in parallel for better performance
590
- yield Promise.all(entries.map((entry) => __awaiter(this, void 0, void 0, function* () {
591
- // Skip hidden files
592
- if (entry.name.startsWith('.')) {
593
- return;
572
+ // Handle scoped packages (@scope/name)
573
+ if (entry.name.startsWith('@')) {
574
+ const scopePath = path.join(nodeModulesPath, entry.name);
575
+ let scopeEntries;
576
+ try {
577
+ scopeEntries = await fsp.readdir(scopePath, { withFileTypes: true });
594
578
  }
595
- // Accept directories and symlinks (pnpm uses symlinks)
596
- const isDirectoryOrSymlink = entry.isDirectory() || entry.isSymbolicLink();
597
- if (!isDirectoryOrSymlink) {
579
+ catch (_a) {
598
580
  return;
599
581
  }
600
- // Handle scoped packages (@scope/name)
601
- if (entry.name.startsWith('@')) {
602
- const scopePath = path.join(nodeModulesPath, entry.name);
603
- let scopeEntries;
604
- try {
605
- scopeEntries = yield fsp.readdir(scopePath, { withFileTypes: true });
606
- }
607
- catch (_a) {
582
+ await Promise.all(scopeEntries.map(async (scopeEntry) => {
583
+ // Accept directories and symlinks for scoped packages too
584
+ if (!scopeEntry.isDirectory() && !scopeEntry.isSymbolicLink())
608
585
  return;
609
- }
610
- yield Promise.all(scopeEntries.map((scopeEntry) => __awaiter(this, void 0, void 0, function* () {
611
- // Accept directories and symlinks for scoped packages too
612
- if (!scopeEntry.isDirectory() && !scopeEntry.isSymbolicLink())
613
- return;
614
- const scopedName = `${entry.name}/${scopeEntry.name}`;
615
- const pkgPath = path.join(scopePath, scopeEntry.name);
616
- yield this.processPackage(pkgPath, `${relativePath}/${scopedName}`, packages);
617
- })));
618
- }
619
- else {
620
- const pkgPath = path.join(nodeModulesPath, entry.name);
621
- yield this.processPackage(pkgPath, `${relativePath}/${entry.name}`, packages);
622
- }
623
- })));
624
- });
586
+ const scopedName = `${entry.name}/${scopeEntry.name}`;
587
+ const pkgPath = path.join(scopePath, scopeEntry.name);
588
+ await this.processPackage(pkgPath, `${relativePath}/${scopedName}`, packages);
589
+ }));
590
+ }
591
+ else {
592
+ const pkgPath = path.join(nodeModulesPath, entry.name);
593
+ await this.processPackage(pkgPath, `${relativePath}/${entry.name}`, packages);
594
+ }
595
+ }));
625
596
  }
626
597
  /**
627
598
  * Processes a single package directory, reading its package.json and
628
599
  * recursively processing nested node_modules.
629
600
  */
630
- processPackage(pkgPath, relativePath, packages) {
631
- return __awaiter(this, void 0, void 0, function* () {
632
- const packageJsonPath = path.join(pkgPath, 'package.json');
633
- // Read and parse the package's package.json
634
- let pkgJson;
635
- try {
636
- const content = yield fsp.readFile(packageJsonPath, 'utf-8');
637
- pkgJson = JSON.parse(content);
638
- }
639
- catch (_a) {
640
- return; // Not a valid package
641
- }
642
- packages[relativePath] = PackageJsonParser.extractPackageMetadata(pkgJson);
643
- // Recursively process nested node_modules
644
- const nestedNodeModules = path.join(pkgPath, 'node_modules');
645
- try {
646
- yield fsp.access(nestedNodeModules);
647
- yield this.walkNodeModulesRecursive(nestedNodeModules, `${relativePath}/node_modules`, packages);
648
- }
649
- catch (_b) {
650
- // No nested node_modules, that's fine
651
- }
652
- });
601
+ async processPackage(pkgPath, relativePath, packages) {
602
+ const packageJsonPath = path.join(pkgPath, 'package.json');
603
+ // Read and parse the package's package.json
604
+ let pkgJson;
605
+ try {
606
+ const content = await fsp.readFile(packageJsonPath, 'utf-8');
607
+ pkgJson = JSON.parse(content);
608
+ }
609
+ catch (_a) {
610
+ return; // Not a valid package
611
+ }
612
+ packages[relativePath] = PackageJsonParser.extractPackageMetadata(pkgJson);
613
+ // Recursively process nested node_modules
614
+ const nestedNodeModules = path.join(pkgPath, 'node_modules');
615
+ try {
616
+ await fsp.access(nestedNodeModules);
617
+ await this.walkNodeModulesRecursive(nestedNodeModules, `${relativePath}/node_modules`, packages);
618
+ }
619
+ catch (_b) {
620
+ // No nested node_modules, that's fine
621
+ }
653
622
  }
654
623
  /**
655
624
  * Converts bun.lock format to npm package-lock.json format for unified processing.