pnpm-catalog-updates 0.3.5 → 0.4.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 (49) hide show
  1. package/README.md +45 -0
  2. package/README.zh-CN.md +64 -0
  3. package/dist/application/services/CatalogUpdateService.d.ts +15 -8
  4. package/dist/application/services/CatalogUpdateService.d.ts.map +1 -1
  5. package/dist/application/services/CatalogUpdateService.js +259 -47
  6. package/dist/application/services/CatalogUpdateService.js.map +1 -1
  7. package/dist/cli/commands/CheckCommand.d.ts +2 -3
  8. package/dist/cli/commands/CheckCommand.d.ts.map +1 -1
  9. package/dist/cli/commands/CheckCommand.js +16 -9
  10. package/dist/cli/commands/CheckCommand.js.map +1 -1
  11. package/dist/cli/commands/SecurityCommand.d.ts +113 -0
  12. package/dist/cli/commands/SecurityCommand.d.ts.map +1 -0
  13. package/dist/cli/commands/SecurityCommand.js +412 -0
  14. package/dist/cli/commands/SecurityCommand.js.map +1 -0
  15. package/dist/cli/commands/UpdateCommand.d.ts +2 -3
  16. package/dist/cli/commands/UpdateCommand.d.ts.map +1 -1
  17. package/dist/cli/commands/UpdateCommand.js +19 -12
  18. package/dist/cli/commands/UpdateCommand.js.map +1 -1
  19. package/dist/cli/formatters/OutputFormatter.d.ts +17 -0
  20. package/dist/cli/formatters/OutputFormatter.d.ts.map +1 -1
  21. package/dist/cli/formatters/OutputFormatter.js +113 -0
  22. package/dist/cli/formatters/OutputFormatter.js.map +1 -1
  23. package/dist/cli/index.d.ts.map +1 -1
  24. package/dist/cli/index.js +66 -13
  25. package/dist/cli/index.js.map +1 -1
  26. package/dist/common/config/Config.d.ts +2 -2
  27. package/dist/common/config/Config.d.ts.map +1 -1
  28. package/dist/common/config/Config.js +31 -4
  29. package/dist/common/config/Config.js.map +1 -1
  30. package/dist/common/config/ConfigLoader.d.ts +45 -0
  31. package/dist/common/config/ConfigLoader.d.ts.map +1 -0
  32. package/dist/common/config/ConfigLoader.js +157 -0
  33. package/dist/common/config/ConfigLoader.js.map +1 -0
  34. package/dist/common/config/PackageFilterConfig.d.ts +54 -0
  35. package/dist/common/config/PackageFilterConfig.d.ts.map +1 -0
  36. package/dist/common/config/PackageFilterConfig.js +67 -0
  37. package/dist/common/config/PackageFilterConfig.js.map +1 -0
  38. package/dist/common/config/index.d.ts +2 -0
  39. package/dist/common/config/index.d.ts.map +1 -1
  40. package/dist/common/config/index.js +2 -0
  41. package/dist/common/config/index.js.map +1 -1
  42. package/dist/common/utils/validation.d.ts.map +1 -1
  43. package/dist/common/utils/validation.js +29 -2
  44. package/dist/common/utils/validation.js.map +1 -1
  45. package/dist/infrastructure/external-services/NpmRegistryService.d.ts +10 -2
  46. package/dist/infrastructure/external-services/NpmRegistryService.d.ts.map +1 -1
  47. package/dist/infrastructure/external-services/NpmRegistryService.js +48 -18
  48. package/dist/infrastructure/external-services/NpmRegistryService.js.map +1 -1
  49. package/package.json +4 -4
package/README.md CHANGED
@@ -323,6 +323,51 @@ Create a `.pcurc.json` file in your project root:
323
323
  }
324
324
  ```
325
325
 
326
+ #### Package Filtering Configuration
327
+
328
+ You can also configure package-specific update rules by creating a `.pcurc.json`
329
+ with filtering options:
330
+
331
+ ```json
332
+ {
333
+ // Exclude packages you never want to update
334
+ "exclude": ["typescript", "@types/node", "react", "react-dom"],
335
+
336
+ // Only update specific packages (optional - if not specified, all packages are considered)
337
+ "include": ["lodash*", "chalk", "commander"],
338
+
339
+ // Package-specific update rules
340
+ "packageRules": [
341
+ {
342
+ "patterns": ["@types/*"],
343
+ "target": "latest", // Always update type definitions to latest
344
+ "autoUpdate": true
345
+ },
346
+ {
347
+ "patterns": ["react", "react-dom"],
348
+ "target": "patch", // Only patch updates for React
349
+ "requireConfirmation": true // Always ask before updating
350
+ },
351
+ {
352
+ "patterns": ["eslint*", "prettier"],
353
+ "target": "minor", // Minor updates for dev tools
354
+ "groupUpdate": true // Update related packages together
355
+ }
356
+ ],
357
+
358
+ // Override defaults
359
+ "defaults": {
360
+ "target": "minor",
361
+ "createBackup": true
362
+ }
363
+ }
364
+ ```
365
+
366
+ **Configuration priority**: Package rules > CLI options > Default configuration
367
+
368
+ **Pattern matching**: Supports glob patterns like `react*`, `@types/*`,
369
+ `eslint*`
370
+
326
371
  ## 📁 Project Structure
327
372
 
328
373
  This project follows Domain-Driven Design (DDD) principles:
package/README.zh-CN.md CHANGED
@@ -316,6 +316,70 @@ pcu -t --interactive # 交互式主题设置
316
316
  }
317
317
  ```
318
318
 
319
+ #### 包过滤配置
320
+
321
+ 您还可以通过创建包含过滤选项的 `.pcurc.json` 来配置特定包的更新规则:
322
+
323
+ ```json
324
+ {
325
+ // 排除您永远不想更新的包
326
+ "exclude": ["typescript", "@types/node", "react", "react-dom"],
327
+
328
+ // 仅更新特定包(可选 - 如果不指定,将考虑所有包)
329
+ "include": ["lodash*", "chalk", "commander"],
330
+
331
+ // 特定包的更新规则
332
+ "packageRules": [
333
+ {
334
+ "patterns": ["@types/*"],
335
+ "target": "latest", // 类型定义总是更新到最新版本
336
+ "autoUpdate": true
337
+ },
338
+ {
339
+ "patterns": ["react", "react-dom"],
340
+ "target": "patch", // React 只进行 patch 更新
341
+ "requireConfirmation": true // 更新前总是询问
342
+ },
343
+ {
344
+ "patterns": ["eslint*", "prettier"],
345
+ "target": "minor", // 开发工具进行 minor 更新
346
+ "groupUpdate": true // 相关包一起更新
347
+ }
348
+ ],
349
+
350
+ // 安全配置
351
+ "security": {
352
+ "autoFixVulnerabilities": true, // 自动检查并修复安全漏洞
353
+ "allowMajorForSecurity": true, // 为安全修复允许主版本升级
354
+ "notifyOnSecurityUpdate": true // 安全更新时显示通知
355
+ },
356
+
357
+ // 高级配置
358
+ "advanced": {
359
+ "concurrency": 5, // 并发网络请求数量(默认: 5)
360
+ "timeout": 30000, // 网络请求超时时间(毫秒,默认: 30000)
361
+ "retries": 3, // 失败重试次数(默认: 3)
362
+ "cacheValidityMinutes": 60 // 缓存有效期(分钟,默认: 60,设为0禁用缓存)
363
+ },
364
+
365
+ // Monorepo 配置
366
+ "monorepo": {
367
+ "syncVersions": ["react", "react-dom"], // 需要在多个 catalog 间同步版本的包
368
+ "catalogPriority": ["default", "latest", "react17"] // catalog 优先级顺序
369
+ },
370
+
371
+ // 覆盖默认设置
372
+ "defaults": {
373
+ "target": "minor",
374
+ "createBackup": true
375
+ }
376
+ }
377
+ ```
378
+
379
+ **配置优先级**: 包规则 > CLI 选项 > 默认配置
380
+
381
+ **模式匹配**: 支持 glob 模式,如 `react*`、`@types/*`、`eslint*`
382
+
319
383
  ## 📁 项目结构
320
384
 
321
385
  本项目遵循领域驱动设计 (DDD) 原则:
@@ -63,6 +63,9 @@ export interface PlannedUpdate {
63
63
  updateType: 'major' | 'minor' | 'patch';
64
64
  reason: string;
65
65
  affectedPackages: string[];
66
+ requireConfirmation?: boolean;
67
+ autoUpdate?: boolean;
68
+ groupUpdate?: boolean;
66
69
  }
67
70
  export interface VersionConflict {
68
71
  packageName: string;
@@ -134,6 +137,10 @@ export declare class CatalogUpdateService {
134
137
  private readonly workspaceRepository;
135
138
  private readonly registryService;
136
139
  constructor(workspaceRepository: WorkspaceRepository, registryService: NpmRegistryService);
140
+ /**
141
+ * Create a new CatalogUpdateService with advanced configuration
142
+ */
143
+ static createWithConfig(workspaceRepository: WorkspaceRepository, workspacePath?: string): CatalogUpdateService;
137
144
  /**
138
145
  * Check for outdated catalog dependencies
139
146
  */
@@ -150,14 +157,6 @@ export declare class CatalogUpdateService {
150
157
  * Analyze the impact of updating a specific dependency
151
158
  */
152
159
  analyzeImpact(catalogName: string, packageName: string, newVersion: string, workspacePath?: string): Promise<ImpactAnalysis>;
153
- /**
154
- * Check if a specific package should be updated based on filters
155
- */
156
- private shouldCheckPackage;
157
- /**
158
- * Check if package matches a pattern (simple glob-like matching)
159
- */
160
- private matchesPattern;
161
160
  /**
162
161
  * Check if a package needs updating
163
162
  */
@@ -186,5 +185,13 @@ export declare class CatalogUpdateService {
186
185
  * Generate recommendations based on analysis
187
186
  */
188
187
  private generateRecommendations;
188
+ /**
189
+ * Create sync version updates for packages that should be synchronized across catalogs
190
+ */
191
+ private createSyncVersionUpdates;
192
+ /**
193
+ * Resolve version conflicts using catalog priority
194
+ */
195
+ private resolveVersionConflict;
189
196
  }
190
197
  //# sourceMappingURL=CatalogUpdateService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CatalogUpdateService.d.ts","sourceRoot":"","sources":["../../../src/application/services/CatalogUpdateService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CatalogUpdateService.d.ts","sourceRoot":"","sources":["../../../src/application/services/CatalogUpdateService.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,8 @@
7
7
  */
8
8
  import { WorkspacePath } from '../../domain/value-objects/WorkspacePath.js';
9
9
  import { Version } from '../../domain/value-objects/Version.js';
10
+ import { NpmRegistryService } from '../../infrastructure/external-services/NpmRegistryService.js';
11
+ import { ConfigLoader } from '../../common/config/ConfigLoader.js';
10
12
  export class CatalogUpdateService {
11
13
  workspaceRepository;
12
14
  registryService;
@@ -14,11 +16,35 @@ export class CatalogUpdateService {
14
16
  this.workspaceRepository = workspaceRepository;
15
17
  this.registryService = registryService;
16
18
  }
19
+ /**
20
+ * Create a new CatalogUpdateService with advanced configuration
21
+ */
22
+ static createWithConfig(workspaceRepository, workspacePath) {
23
+ const config = ConfigLoader.loadConfig(workspacePath || process.cwd());
24
+ // Create registry service with advanced configuration
25
+ const advancedConfig = {};
26
+ if (config.advanced?.concurrency !== undefined) {
27
+ advancedConfig.concurrency = config.advanced.concurrency;
28
+ }
29
+ if (config.advanced?.timeout !== undefined) {
30
+ advancedConfig.timeout = config.advanced.timeout;
31
+ }
32
+ if (config.advanced?.retries !== undefined) {
33
+ advancedConfig.retries = config.advanced.retries;
34
+ }
35
+ if (config.advanced?.cacheValidityMinutes !== undefined) {
36
+ advancedConfig.cacheValidityMinutes = config.advanced.cacheValidityMinutes;
37
+ }
38
+ const registryService = new NpmRegistryService('https://registry.npmjs.org/', advancedConfig);
39
+ return new CatalogUpdateService(workspaceRepository, registryService);
40
+ }
17
41
  /**
18
42
  * Check for outdated catalog dependencies
19
43
  */
20
44
  async checkOutdatedDependencies(options = {}) {
21
45
  const workspacePath = WorkspacePath.fromString(options.workspacePath || process.cwd());
46
+ // Load configuration
47
+ const config = ConfigLoader.loadConfig(workspacePath.toString());
22
48
  // Load workspace
23
49
  const workspace = await this.workspaceRepository.findByPath(workspacePath);
24
50
  if (!workspace) {
@@ -44,21 +70,49 @@ export class CatalogUpdateService {
44
70
  }
45
71
  const dependencies = catalog.getDependencies();
46
72
  for (const [packageName, currentRange] of dependencies) {
47
- // Apply include/exclude filters
48
- if (!this.shouldCheckPackage(packageName, options.include, options.exclude)) {
73
+ // Apply configuration filters
74
+ const packageConfig = ConfigLoader.getPackageConfig(packageName, config);
75
+ if (!packageConfig.shouldUpdate) {
49
76
  continue;
50
77
  }
78
+ // Override target from package-specific configuration, considering security settings
79
+ let effectiveTarget = packageConfig.target;
80
+ // Check for security vulnerabilities if security config is enabled
81
+ let hasSecurityVulnerabilities = false;
82
+ if (config.security?.autoFixVulnerabilities) {
83
+ try {
84
+ const currentVersion = currentRange.getMinVersion()?.toString();
85
+ if (currentVersion) {
86
+ const securityReport = await this.registryService.checkSecurityVulnerabilities(packageName, currentVersion);
87
+ hasSecurityVulnerabilities = securityReport.hasVulnerabilities;
88
+ // Allow major updates for security fixes if configured
89
+ if (hasSecurityVulnerabilities && config.security.allowMajorForSecurity) {
90
+ effectiveTarget = 'latest';
91
+ }
92
+ }
93
+ }
94
+ catch (error) {
95
+ console.warn(`Failed to check security for ${packageName}:`, error);
96
+ }
97
+ }
51
98
  try {
52
- const outdatedInfo = await this.checkPackageUpdate(packageName, currentRange, options.target || 'latest', options.includePrerelease || false);
99
+ const outdatedInfo = await this.checkPackageUpdate(packageName, currentRange, effectiveTarget, options.includePrerelease || config.defaults?.includePrerelease || false);
53
100
  if (outdatedInfo) {
54
101
  // Get affected packages
55
102
  const affectedPackages = workspace
56
103
  .getPackagesUsingCatalogDependency(catalog.getName(), packageName)
57
104
  .getPackageNames();
58
- outdatedDependencies.push({
105
+ // Override security update flag based on security check
106
+ const finalOutdatedInfo = {
59
107
  ...outdatedInfo,
60
108
  affectedPackages,
61
- });
109
+ isSecurityUpdate: hasSecurityVulnerabilities || outdatedInfo.isSecurityUpdate,
110
+ };
111
+ outdatedDependencies.push(finalOutdatedInfo);
112
+ // Log security notifications if enabled
113
+ if (hasSecurityVulnerabilities && config.security?.notifyOnSecurityUpdate) {
114
+ console.warn(`🔒 Security vulnerability detected in ${packageName}@${outdatedInfo.currentVersion}`);
115
+ }
62
116
  }
63
117
  }
64
118
  catch (error) {
@@ -91,9 +145,14 @@ export class CatalogUpdateService {
91
145
  const outdatedReport = await this.checkOutdatedDependencies(options);
92
146
  const updates = [];
93
147
  const conflicts = [];
148
+ // Load configuration for package rules and monorepo settings
149
+ const workspacePath = options.workspacePath || process.cwd();
150
+ const config = ConfigLoader.loadConfig(workspacePath);
94
151
  // Convert outdated dependencies to planned updates
95
152
  for (const catalogInfo of outdatedReport.catalogs) {
96
153
  for (const outdated of catalogInfo.outdatedDependencies) {
154
+ // Get package-specific configuration
155
+ const packageConfig = ConfigLoader.getPackageConfig(outdated.packageName, config);
97
156
  const update = {
98
157
  catalogName: catalogInfo.catalogName,
99
158
  packageName: outdated.packageName,
@@ -102,10 +161,21 @@ export class CatalogUpdateService {
102
161
  updateType: outdated.updateType,
103
162
  reason: this.getUpdateReason(outdated),
104
163
  affectedPackages: outdated.affectedPackages,
164
+ requireConfirmation: packageConfig.requireConfirmation,
165
+ autoUpdate: packageConfig.autoUpdate,
166
+ groupUpdate: packageConfig.groupUpdate,
105
167
  };
106
168
  updates.push(update);
107
169
  }
108
170
  }
171
+ // Handle syncVersions - ensure packages in syncVersions list are synchronized across catalogs
172
+ if (config.monorepo?.syncVersions && config.monorepo.syncVersions.length > 0) {
173
+ const workspacePathObj = WorkspacePath.fromString(workspacePath);
174
+ const workspace = await this.workspaceRepository.findByPath(workspacePathObj);
175
+ if (workspace) {
176
+ updates.push(...(await this.createSyncVersionUpdates(config.monorepo.syncVersions, workspace, updates)));
177
+ }
178
+ }
109
179
  // Detect conflicts (same package in multiple catalogs with different versions)
110
180
  const packageCatalogMap = new Map();
111
181
  for (const update of updates) {
@@ -114,20 +184,15 @@ export class CatalogUpdateService {
114
184
  }
115
185
  packageCatalogMap.get(update.packageName).push(update);
116
186
  }
187
+ // Handle conflicts with catalogPriority
117
188
  for (const [packageName, packageUpdates] of packageCatalogMap) {
118
189
  if (packageUpdates.length > 1) {
119
190
  const uniqueVersions = new Set(packageUpdates.map((u) => u.newVersion));
120
191
  if (uniqueVersions.size > 1) {
121
- const conflict = {
122
- packageName,
123
- catalogs: packageUpdates.map((u) => ({
124
- catalogName: u.catalogName,
125
- currentVersion: u.currentVersion,
126
- proposedVersion: u.newVersion,
127
- })),
128
- recommendation: `Consider using the same version across all catalogs`,
129
- };
130
- conflicts.push(conflict);
192
+ const resolvedConflict = this.resolveVersionConflict(packageName, packageUpdates, config.monorepo?.catalogPriority || ['default']);
193
+ if (resolvedConflict) {
194
+ conflicts.push(resolvedConflict);
195
+ }
131
196
  }
132
197
  }
133
198
  }
@@ -144,6 +209,8 @@ export class CatalogUpdateService {
144
209
  */
145
210
  async executeUpdates(plan, options) {
146
211
  const workspacePath = WorkspacePath.fromString(plan.workspace.path);
212
+ // Load configuration for security settings
213
+ const config = ConfigLoader.loadConfig(workspacePath.toString());
147
214
  // Load workspace
148
215
  const workspace = await this.workspaceRepository.findByPath(workspacePath);
149
216
  if (!workspace) {
@@ -152,6 +219,8 @@ export class CatalogUpdateService {
152
219
  const updatedDependencies = [];
153
220
  const skippedDependencies = [];
154
221
  const errors = [];
222
+ // Track security updates for notification
223
+ const securityUpdates = [];
155
224
  // Execute updates
156
225
  for (const update of plan.updates) {
157
226
  try {
@@ -168,6 +237,20 @@ export class CatalogUpdateService {
168
237
  continue;
169
238
  }
170
239
  }
240
+ // Check if this is a security update and track it
241
+ let isSecurityUpdate = false;
242
+ if (config.security?.notifyOnSecurityUpdate) {
243
+ try {
244
+ const securityReport = await this.registryService.checkSecurityVulnerabilities(update.packageName, update.currentVersion);
245
+ if (securityReport.hasVulnerabilities) {
246
+ isSecurityUpdate = true;
247
+ securityUpdates.push(`${update.packageName}@${update.currentVersion} → ${update.newVersion}`);
248
+ }
249
+ }
250
+ catch (error) {
251
+ console.warn(`Failed to check security for ${update.packageName}:`, error);
252
+ }
253
+ }
171
254
  // Perform the update
172
255
  workspace.updateCatalogDependency(update.catalogName, update.packageName, update.newVersion);
173
256
  updatedDependencies.push({
@@ -177,6 +260,10 @@ export class CatalogUpdateService {
177
260
  toVersion: update.newVersion,
178
261
  updateType: update.updateType,
179
262
  });
263
+ // Log security update notification
264
+ if (isSecurityUpdate && config.security?.notifyOnSecurityUpdate) {
265
+ console.log(`✅ Security fix applied: ${update.packageName}@${update.currentVersion} → ${update.newVersion}`);
266
+ }
180
267
  }
181
268
  catch (error) {
182
269
  errors.push({
@@ -191,6 +278,44 @@ export class CatalogUpdateService {
191
278
  if (!options.dryRun && updatedDependencies.length > 0) {
192
279
  try {
193
280
  await this.workspaceRepository.save(workspace);
281
+ // Show summary of security updates if any
282
+ if (securityUpdates.length > 0 && config.security?.notifyOnSecurityUpdate) {
283
+ console.log(`\n🔒 Security Updates Summary:`);
284
+ console.log(` Applied ${securityUpdates.length} security fix(es):`);
285
+ securityUpdates.forEach((update) => console.log(` • ${update}`));
286
+ }
287
+ // Show summary of synced version updates
288
+ const syncUpdates = updatedDependencies.filter((u) => plan.updates.find((pu) => pu.packageName === u.packageName &&
289
+ pu.catalogName === u.catalogName &&
290
+ pu.reason.includes('Sync version')));
291
+ if (syncUpdates.length > 0) {
292
+ console.log(`\n🔄 Version Sync Summary:`);
293
+ const syncedPackages = new Set(syncUpdates.map((u) => u.packageName));
294
+ console.log(` Synchronized ${syncedPackages.size} package(s) across catalogs:`);
295
+ // Group by package name
296
+ const syncByPackage = new Map();
297
+ syncUpdates.forEach((update) => {
298
+ if (!syncByPackage.has(update.packageName)) {
299
+ syncByPackage.set(update.packageName, []);
300
+ }
301
+ syncByPackage.get(update.packageName).push(update);
302
+ });
303
+ syncByPackage.forEach((updates, packageName) => {
304
+ const catalogs = updates.map((u) => u.catalogName).join(', ');
305
+ const version = updates[0]?.toVersion;
306
+ console.log(` • ${packageName}@${version} in catalogs: ${catalogs}`);
307
+ });
308
+ }
309
+ // Show catalog priority resolution if any
310
+ if (plan.hasConflicts &&
311
+ plan.conflicts.some((c) => c.recommendation.includes('Priority catalog'))) {
312
+ console.log(`\n📋 Catalog Priority Resolutions:`);
313
+ plan.conflicts
314
+ .filter((c) => c.recommendation.includes('Priority catalog'))
315
+ .forEach((conflict) => {
316
+ console.log(` • ${conflict.packageName}: ${conflict.recommendation}`);
317
+ });
318
+ }
194
319
  }
195
320
  catch (error) {
196
321
  errors.push({
@@ -274,38 +399,6 @@ export class CatalogUpdateService {
274
399
  recommendations,
275
400
  };
276
401
  }
277
- /**
278
- * Check if a specific package should be updated based on filters
279
- */
280
- shouldCheckPackage(packageName, include, exclude) {
281
- // Check exclude patterns first
282
- if (exclude && exclude.length > 0) {
283
- for (const pattern of exclude) {
284
- if (this.matchesPattern(packageName, pattern)) {
285
- return false;
286
- }
287
- }
288
- }
289
- // Check include patterns
290
- if (include && include.length > 0) {
291
- for (const pattern of include) {
292
- if (this.matchesPattern(packageName, pattern)) {
293
- return true;
294
- }
295
- }
296
- return false; // If include patterns exist, package must match one
297
- }
298
- return true; // Include by default if no patterns
299
- }
300
- /**
301
- * Check if package matches a pattern (simple glob-like matching)
302
- */
303
- matchesPattern(packageName, pattern) {
304
- // Convert glob pattern to regex
305
- const regexPattern = pattern.replace(/\*/g, '.*').replace(/\?/g, '.');
306
- const regex = new RegExp(`^${regexPattern}$`, 'i');
307
- return regex.test(packageName);
308
- }
309
402
  /**
310
403
  * Check if a package needs updating
311
404
  */
@@ -517,5 +610,124 @@ export class CatalogUpdateService {
517
610
  }
518
611
  return recommendations;
519
612
  }
613
+ /**
614
+ * Create sync version updates for packages that should be synchronized across catalogs
615
+ */
616
+ async createSyncVersionUpdates(syncVersions, workspace, existingUpdates) {
617
+ const syncUpdates = [];
618
+ const catalogs = workspace.getCatalogs();
619
+ const allCatalogs = catalogs.getAll();
620
+ for (const packageName of syncVersions) {
621
+ // Check if this package exists in multiple catalogs
622
+ const catalogsWithPackage = allCatalogs.filter((catalog) => catalog && catalog.getDependencyVersion(packageName));
623
+ if (catalogsWithPackage.length <= 1) {
624
+ continue; // No need to sync if package is only in one catalog
625
+ }
626
+ // Find the highest version from existing updates or determine target version
627
+ let targetVersion = null;
628
+ let targetUpdateType = 'patch';
629
+ // Check if this package has any existing updates
630
+ const existingUpdate = existingUpdates.find((u) => u.packageName === packageName);
631
+ if (existingUpdate) {
632
+ targetVersion = existingUpdate.newVersion;
633
+ targetUpdateType = existingUpdate.updateType;
634
+ }
635
+ else {
636
+ // Get latest version for this package
637
+ try {
638
+ const packageInfo = await this.registryService.getPackageInfo(packageName);
639
+ targetVersion = packageInfo.latestVersion;
640
+ }
641
+ catch (error) {
642
+ console.warn(`Failed to get version info for sync package ${packageName}:`, error);
643
+ continue;
644
+ }
645
+ }
646
+ if (!targetVersion)
647
+ continue;
648
+ // Create sync updates for all catalogs that need updating
649
+ for (const catalog of catalogsWithPackage) {
650
+ const currentRange = catalog.getDependencyVersion(packageName);
651
+ if (!currentRange)
652
+ continue;
653
+ const currentVersion = currentRange.getMinVersion();
654
+ if (!currentVersion)
655
+ continue;
656
+ const currentVersionString = currentVersion.toString();
657
+ // Skip if already at target version
658
+ if (currentVersionString === targetVersion)
659
+ continue;
660
+ // Check if this update already exists
661
+ const existingUpdateForCatalog = existingUpdates.find((u) => u.packageName === packageName && u.catalogName === catalog.getName());
662
+ if (existingUpdateForCatalog) {
663
+ // Update the existing update to use the sync version
664
+ existingUpdateForCatalog.newVersion = targetVersion;
665
+ existingUpdateForCatalog.reason = `Sync version across catalogs: ${existingUpdateForCatalog.reason}`;
666
+ }
667
+ else {
668
+ // Create new sync update
669
+ const affectedPackages = workspace
670
+ .getPackagesUsingCatalogDependency(catalog.getName(), packageName)
671
+ .getPackageNames();
672
+ const syncUpdate = {
673
+ catalogName: catalog.getName(),
674
+ packageName: packageName,
675
+ currentVersion: currentVersionString,
676
+ newVersion: targetVersion,
677
+ updateType: targetUpdateType,
678
+ reason: `Sync version with other catalogs`,
679
+ affectedPackages,
680
+ requireConfirmation: true, // Sync updates should be confirmed
681
+ autoUpdate: false,
682
+ groupUpdate: true,
683
+ };
684
+ syncUpdates.push(syncUpdate);
685
+ }
686
+ }
687
+ }
688
+ return syncUpdates;
689
+ }
690
+ /**
691
+ * Resolve version conflicts using catalog priority
692
+ */
693
+ resolveVersionConflict(packageName, packageUpdates, catalogPriority) {
694
+ // Find the highest priority catalog with an update for this package
695
+ let priorityCatalog = null;
696
+ for (const catalogName of catalogPriority) {
697
+ const catalogUpdate = packageUpdates.find((u) => u.catalogName === catalogName);
698
+ if (catalogUpdate) {
699
+ priorityCatalog = catalogUpdate;
700
+ break;
701
+ }
702
+ }
703
+ // If no priority catalog found, use the first one
704
+ if (!priorityCatalog) {
705
+ priorityCatalog = packageUpdates[0] || null;
706
+ }
707
+ // Update all other catalogs to use the priority catalog's version
708
+ const priorityVersion = priorityCatalog?.newVersion;
709
+ if (priorityVersion && priorityCatalog) {
710
+ for (const update of packageUpdates) {
711
+ if (update.catalogName !== priorityCatalog.catalogName) {
712
+ update.newVersion = priorityVersion;
713
+ update.reason = `Using version from priority catalog (${priorityCatalog.catalogName}): ${update.reason}`;
714
+ }
715
+ }
716
+ }
717
+ // Create conflict record for reporting
718
+ const uniqueVersions = new Set(packageUpdates.map((u) => u.newVersion));
719
+ if (uniqueVersions.size > 1) {
720
+ return {
721
+ packageName,
722
+ catalogs: packageUpdates.map((u) => ({
723
+ catalogName: u.catalogName,
724
+ currentVersion: u.currentVersion,
725
+ proposedVersion: u.newVersion,
726
+ })),
727
+ recommendation: `Resolved using catalog priority. Priority catalog '${priorityCatalog?.catalogName}' version '${priorityVersion}' selected.`,
728
+ };
729
+ }
730
+ return null;
731
+ }
520
732
  }
521
733
  //# sourceMappingURL=CatalogUpdateService.js.map