@openrewrite/rewrite 8.68.0-20251204-054843 → 8.68.0-20251204-145030

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 (76) hide show
  1. package/dist/index.d.ts.map +1 -1
  2. package/dist/index.js +4 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/javascript/index.d.ts +3 -0
  5. package/dist/javascript/index.d.ts.map +1 -1
  6. package/dist/javascript/index.js +3 -0
  7. package/dist/javascript/index.js.map +1 -1
  8. package/dist/javascript/package-json-parser.d.ts +0 -5
  9. package/dist/javascript/package-json-parser.d.ts.map +1 -1
  10. package/dist/javascript/package-json-parser.js +13 -25
  11. package/dist/javascript/package-json-parser.js.map +1 -1
  12. package/dist/javascript/package-manager.d.ts +131 -0
  13. package/dist/javascript/package-manager.d.ts.map +1 -0
  14. package/dist/javascript/package-manager.js +372 -0
  15. package/dist/javascript/package-manager.js.map +1 -0
  16. package/dist/javascript/recipes/index.d.ts +2 -0
  17. package/dist/javascript/recipes/index.d.ts.map +1 -0
  18. package/dist/javascript/recipes/index.js +33 -0
  19. package/dist/javascript/recipes/index.js.map +1 -0
  20. package/dist/javascript/recipes/upgrade-dependency-version.d.ts +105 -0
  21. package/dist/javascript/recipes/upgrade-dependency-version.d.ts.map +1 -0
  22. package/dist/javascript/recipes/upgrade-dependency-version.js +493 -0
  23. package/dist/javascript/recipes/upgrade-dependency-version.js.map +1 -0
  24. package/dist/javascript/search/find-dependency.d.ts +32 -0
  25. package/dist/javascript/search/find-dependency.d.ts.map +1 -0
  26. package/dist/javascript/search/find-dependency.js +312 -0
  27. package/dist/javascript/search/find-dependency.js.map +1 -0
  28. package/dist/javascript/search/index.d.ts +1 -0
  29. package/dist/javascript/search/index.d.ts.map +1 -1
  30. package/dist/javascript/search/index.js +1 -0
  31. package/dist/javascript/search/index.js.map +1 -1
  32. package/dist/json/print.js +1 -1
  33. package/dist/json/print.js.map +1 -1
  34. package/dist/markers.d.ts +67 -0
  35. package/dist/markers.d.ts.map +1 -1
  36. package/dist/markers.js +101 -0
  37. package/dist/markers.js.map +1 -1
  38. package/dist/print.d.ts.map +1 -1
  39. package/dist/print.js +0 -1
  40. package/dist/print.js.map +1 -1
  41. package/dist/recipe.js +3 -3
  42. package/dist/recipe.js.map +1 -1
  43. package/dist/rpc/index.js +72 -0
  44. package/dist/rpc/index.js.map +1 -1
  45. package/dist/rpc/request/generate.js +1 -1
  46. package/dist/rpc/request/generate.js.map +1 -1
  47. package/dist/rpc/request/get-languages.d.ts.map +1 -1
  48. package/dist/rpc/request/get-languages.js +2 -1
  49. package/dist/rpc/request/get-languages.js.map +1 -1
  50. package/dist/rpc/request/visit.d.ts.map +1 -1
  51. package/dist/rpc/request/visit.js +27 -0
  52. package/dist/rpc/request/visit.js.map +1 -1
  53. package/dist/run.js +2 -2
  54. package/dist/run.js.map +1 -1
  55. package/dist/test/rewrite-test.js +1 -1
  56. package/dist/test/rewrite-test.js.map +1 -1
  57. package/dist/version.txt +1 -1
  58. package/package.json +1 -1
  59. package/src/index.ts +4 -0
  60. package/src/javascript/index.ts +3 -0
  61. package/src/javascript/package-json-parser.ts +14 -33
  62. package/src/javascript/package-manager.ts +428 -0
  63. package/src/javascript/recipes/index.ts +17 -0
  64. package/src/javascript/recipes/upgrade-dependency-version.ts +586 -0
  65. package/src/javascript/search/find-dependency.ts +303 -0
  66. package/src/javascript/search/index.ts +1 -0
  67. package/src/json/print.ts +1 -1
  68. package/src/markers.ts +146 -0
  69. package/src/print.ts +0 -1
  70. package/src/recipe.ts +3 -3
  71. package/src/rpc/index.ts +65 -1
  72. package/src/rpc/request/generate.ts +1 -1
  73. package/src/rpc/request/get-languages.ts +2 -1
  74. package/src/rpc/request/visit.ts +32 -1
  75. package/src/run.ts +2 -2
  76. package/src/test/rewrite-test.ts +1 -1
@@ -0,0 +1,428 @@
1
+ /*
2
+ * Copyright 2025 the original author or authors.
3
+ * <p>
4
+ * Licensed under the Moderne Source Available License (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ * <p>
8
+ * https://docs.moderne.io/licensing/moderne-source-available-license
9
+ * <p>
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import {PackageManager} from "./node-resolution-result";
18
+ import * as fs from "fs";
19
+ import * as path from "path";
20
+ import {spawnSync} from "child_process";
21
+
22
+ /**
23
+ * Configuration for each package manager.
24
+ */
25
+ interface PackageManagerConfig {
26
+ /** The lock file name for this package manager */
27
+ lockFile: string;
28
+
29
+ /** Command to install dependencies and update lock file only (no node_modules) */
30
+ installLockOnlyCommand: string[];
31
+
32
+ /** Command to install dependencies fully */
33
+ installCommand: string[];
34
+
35
+ /** Command to list dependencies in JSON format (if supported) */
36
+ listCommand?: string[];
37
+ }
38
+
39
+ /**
40
+ * Package manager configurations.
41
+ */
42
+ const PACKAGE_MANAGER_CONFIGS: Record<PackageManager, PackageManagerConfig> = {
43
+ [PackageManager.Npm]: {
44
+ lockFile: 'package-lock.json',
45
+ installLockOnlyCommand: ['npm', 'install', '--package-lock-only'],
46
+ installCommand: ['npm', 'install'],
47
+ listCommand: ['npm', 'list', '--json', '--all'],
48
+ },
49
+ [PackageManager.YarnClassic]: {
50
+ lockFile: 'yarn.lock',
51
+ // Yarn Classic doesn't have a lock-only mode
52
+ installLockOnlyCommand: ['yarn', 'install', '--ignore-scripts'],
53
+ installCommand: ['yarn', 'install'],
54
+ listCommand: ['yarn', 'list', '--json'],
55
+ },
56
+ [PackageManager.YarnBerry]: {
57
+ lockFile: 'yarn.lock',
58
+ // Yarn Berry's mode skip-build skips post-install scripts
59
+ installLockOnlyCommand: ['yarn', 'install', '--mode', 'skip-build'],
60
+ installCommand: ['yarn', 'install'],
61
+ listCommand: ['yarn', 'info', '--all', '--json'],
62
+ },
63
+ [PackageManager.Pnpm]: {
64
+ lockFile: 'pnpm-lock.yaml',
65
+ installLockOnlyCommand: ['pnpm', 'install', '--lockfile-only'],
66
+ installCommand: ['pnpm', 'install'],
67
+ listCommand: ['pnpm', 'list', '--json', '--depth=Infinity'],
68
+ },
69
+ [PackageManager.Bun]: {
70
+ lockFile: 'bun.lock',
71
+ // Bun doesn't have a lock-only mode, but is very fast anyway
72
+ installLockOnlyCommand: ['bun', 'install', '--ignore-scripts'],
73
+ installCommand: ['bun', 'install'],
74
+ },
75
+ };
76
+
77
+ /**
78
+ * Configuration for lock file detection.
79
+ */
80
+ export interface LockFileDetectionConfig {
81
+ /** The lock file name */
82
+ filename: string;
83
+ /** The package manager, or a function to detect it from file content */
84
+ packageManager: PackageManager | ((content: string) => PackageManager);
85
+ /** If true, prefer walking node_modules over parsing lock file (lock file may omit details) */
86
+ preferNodeModules?: boolean;
87
+ }
88
+
89
+ /**
90
+ * Lock file detection configuration with priority order.
91
+ * Priority order determines which package manager is detected when multiple lock files exist.
92
+ */
93
+ const LOCK_FILE_DETECTION: ReadonlyArray<LockFileDetectionConfig> = [
94
+ {filename: 'package-lock.json', packageManager: PackageManager.Npm},
95
+ {filename: 'bun.lock', packageManager: PackageManager.Bun},
96
+ {filename: 'pnpm-lock.yaml', packageManager: PackageManager.Pnpm, preferNodeModules: true},
97
+ {
98
+ filename: 'yarn.lock',
99
+ packageManager: (content) =>
100
+ content.includes('__metadata:') ? PackageManager.YarnBerry : PackageManager.YarnClassic,
101
+ // yarn.lock omits transitive dependency details (engines/license), so prefer node_modules
102
+ preferNodeModules: true
103
+ },
104
+ ];
105
+
106
+ /**
107
+ * Result of running a package manager command.
108
+ */
109
+ export interface PackageManagerResult {
110
+ success: boolean;
111
+ stdout?: string;
112
+ stderr?: string;
113
+ error?: string;
114
+ }
115
+
116
+ /**
117
+ * Options for running package manager install.
118
+ */
119
+ export interface InstallOptions {
120
+ /** Working directory */
121
+ cwd: string;
122
+
123
+ /** If true, only update lock file without installing to node_modules */
124
+ lockOnly?: boolean;
125
+
126
+ /** Timeout in milliseconds (default: 120000 = 2 minutes) */
127
+ timeout?: number;
128
+
129
+ /** Additional environment variables */
130
+ env?: Record<string, string>;
131
+ }
132
+
133
+ /**
134
+ * Detects the package manager used in a directory by checking for lock files.
135
+ *
136
+ * @param dir The directory to check
137
+ * @returns The detected package manager, or undefined if none found
138
+ */
139
+ export function detectPackageManager(dir: string): PackageManager | undefined {
140
+ for (const config of LOCK_FILE_DETECTION) {
141
+ const lockPath = path.join(dir, config.filename);
142
+ if (fs.existsSync(lockPath)) {
143
+ if (typeof config.packageManager === 'function') {
144
+ try {
145
+ const content = fs.readFileSync(lockPath, 'utf-8');
146
+ return config.packageManager(content);
147
+ } catch {
148
+ continue;
149
+ }
150
+ }
151
+ return config.packageManager;
152
+ }
153
+ }
154
+ return undefined;
155
+ }
156
+
157
+ /**
158
+ * Gets the lock file detection configuration.
159
+ * Returns the array of lock file configs in priority order.
160
+ */
161
+ export function getLockFileDetectionConfig(): ReadonlyArray<LockFileDetectionConfig> {
162
+ return LOCK_FILE_DETECTION;
163
+ }
164
+
165
+ /**
166
+ * Gets the configuration for a package manager.
167
+ */
168
+ export function getPackageManagerConfig(pm: PackageManager): PackageManagerConfig {
169
+ return PACKAGE_MANAGER_CONFIGS[pm];
170
+ }
171
+
172
+ /**
173
+ * Gets the lock file name for a package manager.
174
+ */
175
+ export function getLockFileName(pm: PackageManager): string {
176
+ return PACKAGE_MANAGER_CONFIGS[pm].lockFile;
177
+ }
178
+
179
+ /**
180
+ * Gets all supported lock file names.
181
+ */
182
+ export function getAllLockFileNames(): string[] {
183
+ return LOCK_FILE_DETECTION.map(c => c.filename);
184
+ }
185
+
186
+ /**
187
+ * Checks if a file path is a lock file.
188
+ */
189
+ export function isLockFile(filePath: string): boolean {
190
+ const fileName = path.basename(filePath);
191
+ return getAllLockFileNames().includes(fileName);
192
+ }
193
+
194
+ /**
195
+ * Runs the package manager install command.
196
+ *
197
+ * @param pm The package manager to use
198
+ * @param options Install options
199
+ * @returns Result of the install command
200
+ */
201
+ export function runInstall(pm: PackageManager, options: InstallOptions): PackageManagerResult {
202
+ const config = PACKAGE_MANAGER_CONFIGS[pm];
203
+ const command = options.lockOnly ? config.installLockOnlyCommand : config.installCommand;
204
+ const [cmd, ...args] = command;
205
+
206
+ try {
207
+ const result = spawnSync(cmd, args, {
208
+ cwd: options.cwd,
209
+ encoding: 'utf-8',
210
+ stdio: ['pipe', 'pipe', 'pipe'],
211
+ timeout: options.timeout ?? 120000,
212
+ env: options.env ? {...process.env, ...options.env} : process.env,
213
+ });
214
+
215
+ if (result.error) {
216
+ return {
217
+ success: false,
218
+ error: result.error.message,
219
+ stderr: result.stderr,
220
+ };
221
+ }
222
+
223
+ if (result.status !== 0) {
224
+ return {
225
+ success: false,
226
+ stdout: result.stdout,
227
+ stderr: result.stderr,
228
+ error: `Command exited with code ${result.status}`,
229
+ };
230
+ }
231
+
232
+ return {
233
+ success: true,
234
+ stdout: result.stdout,
235
+ stderr: result.stderr,
236
+ };
237
+ } catch (error: any) {
238
+ return {
239
+ success: false,
240
+ error: error.message,
241
+ };
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Options for adding/upgrading a package.
247
+ */
248
+ export interface AddPackageOptions {
249
+ /** Working directory */
250
+ cwd: string;
251
+
252
+ /** Package name to add/upgrade */
253
+ packageName: string;
254
+
255
+ /** Version constraint (e.g., "^5.0.0") */
256
+ version: string;
257
+
258
+ /** If true, only update lock file without installing to node_modules */
259
+ lockOnly?: boolean;
260
+
261
+ /** Timeout in milliseconds (default: 120000 = 2 minutes) */
262
+ timeout?: number;
263
+
264
+ /** Additional environment variables */
265
+ env?: Record<string, string>;
266
+ }
267
+
268
+ /**
269
+ * Runs a package manager command to add or upgrade a package.
270
+ * This updates both package.json and the lock file.
271
+ *
272
+ * @param pm The package manager to use
273
+ * @param options Add package options
274
+ * @returns Result of the command
275
+ */
276
+ export function runAddPackage(pm: PackageManager, options: AddPackageOptions): PackageManagerResult {
277
+ const packageSpec = `${options.packageName}@${options.version}`;
278
+
279
+ // Build command based on package manager
280
+ let cmd: string;
281
+ let args: string[];
282
+
283
+ switch (pm) {
284
+ case PackageManager.Npm:
285
+ cmd = 'npm';
286
+ args = ['install', packageSpec];
287
+ if (options.lockOnly) {
288
+ args.push('--package-lock-only');
289
+ }
290
+ break;
291
+ case PackageManager.YarnClassic:
292
+ cmd = 'yarn';
293
+ args = ['add', packageSpec];
294
+ if (options.lockOnly) {
295
+ args.push('--ignore-scripts');
296
+ }
297
+ break;
298
+ case PackageManager.YarnBerry:
299
+ cmd = 'yarn';
300
+ args = ['add', packageSpec];
301
+ if (options.lockOnly) {
302
+ args.push('--mode', 'skip-build');
303
+ }
304
+ break;
305
+ case PackageManager.Pnpm:
306
+ cmd = 'pnpm';
307
+ args = ['add', packageSpec];
308
+ if (options.lockOnly) {
309
+ args.push('--lockfile-only');
310
+ }
311
+ break;
312
+ case PackageManager.Bun:
313
+ cmd = 'bun';
314
+ args = ['add', packageSpec];
315
+ if (options.lockOnly) {
316
+ args.push('--ignore-scripts');
317
+ }
318
+ break;
319
+ }
320
+
321
+ try {
322
+ const result = spawnSync(cmd, args, {
323
+ cwd: options.cwd,
324
+ encoding: 'utf-8',
325
+ stdio: ['pipe', 'pipe', 'pipe'],
326
+ timeout: options.timeout ?? 120000,
327
+ env: options.env ? {...process.env, ...options.env} : process.env,
328
+ });
329
+
330
+ if (result.error) {
331
+ return {
332
+ success: false,
333
+ error: result.error.message,
334
+ stderr: result.stderr,
335
+ };
336
+ }
337
+
338
+ if (result.status !== 0) {
339
+ return {
340
+ success: false,
341
+ stdout: result.stdout,
342
+ stderr: result.stderr,
343
+ error: `Command exited with code ${result.status}`,
344
+ };
345
+ }
346
+
347
+ return {
348
+ success: true,
349
+ stdout: result.stdout,
350
+ stderr: result.stderr,
351
+ };
352
+ } catch (error: any) {
353
+ return {
354
+ success: false,
355
+ error: error.message,
356
+ };
357
+ }
358
+ }
359
+
360
+ /**
361
+ * Runs a package manager list command to get dependency information.
362
+ *
363
+ * @param pm The package manager to use
364
+ * @param cwd Working directory
365
+ * @param timeout Timeout in milliseconds
366
+ * @returns The JSON output, or undefined if failed
367
+ */
368
+ export function runList(pm: PackageManager, cwd: string, timeout: number = 30000): string | undefined {
369
+ const config = PACKAGE_MANAGER_CONFIGS[pm];
370
+ if (!config.listCommand) {
371
+ return undefined;
372
+ }
373
+
374
+ const [cmd, ...args] = config.listCommand;
375
+
376
+ const result = spawnSync(cmd, args, {
377
+ cwd,
378
+ encoding: 'utf-8',
379
+ stdio: ['pipe', 'pipe', 'pipe'],
380
+ timeout,
381
+ });
382
+
383
+ if (result.error || result.status !== 0) {
384
+ return undefined;
385
+ }
386
+
387
+ return result.stdout;
388
+ }
389
+
390
+ /**
391
+ * Checks if a package manager is available on the system.
392
+ *
393
+ * @param pm The package manager to check
394
+ * @returns True if the package manager is available
395
+ */
396
+ export function isPackageManagerAvailable(pm: PackageManager): boolean {
397
+ const config = PACKAGE_MANAGER_CONFIGS[pm];
398
+ const cmd = config.installCommand[0];
399
+
400
+ try {
401
+ const result = spawnSync(cmd, ['--version'], {
402
+ encoding: 'utf-8',
403
+ stdio: ['pipe', 'pipe', 'pipe'],
404
+ timeout: 5000,
405
+ });
406
+ return result.status === 0;
407
+ } catch {
408
+ return false;
409
+ }
410
+ }
411
+
412
+ /**
413
+ * Gets a human-readable name for a package manager.
414
+ */
415
+ export function getPackageManagerDisplayName(pm: PackageManager): string {
416
+ switch (pm) {
417
+ case PackageManager.Npm:
418
+ return 'npm';
419
+ case PackageManager.YarnClassic:
420
+ return 'Yarn Classic';
421
+ case PackageManager.YarnBerry:
422
+ return 'Yarn Berry';
423
+ case PackageManager.Pnpm:
424
+ return 'pnpm';
425
+ case PackageManager.Bun:
426
+ return 'Bun';
427
+ }
428
+ }
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Copyright 2025 the original author or authors.
3
+ * <p>
4
+ * Licensed under the Moderne Source Available License (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ * <p>
8
+ * https://docs.moderne.io/licensing/moderne-source-available-license
9
+ * <p>
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ export * from "./upgrade-dependency-version";