pcu 0.5.7 → 0.6.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 (223) hide show
  1. package/bin/pcu.js +1 -1
  2. package/dist/index.js +9559 -32
  3. package/dist/index.js.map +1 -1
  4. package/package.json +36 -84
  5. package/src/cli/commands/checkCommand.ts +227 -0
  6. package/src/cli/commands/initCommand.ts +394 -0
  7. package/src/cli/commands/securityCommand.ts +569 -0
  8. package/src/cli/commands/updateCommand.ts +245 -0
  9. package/src/cli/formatters/outputFormatter.ts +830 -0
  10. package/src/cli/formatters/progressBar.ts +700 -0
  11. package/src/cli/index.ts +565 -0
  12. package/src/cli/interactive/interactivePrompts.ts +517 -0
  13. package/src/cli/options/globalOptions.ts +380 -0
  14. package/src/cli/options/index.ts +5 -0
  15. package/src/cli/themes/colorTheme.ts +379 -0
  16. package/src/cli/validators/commandValidator.ts +395 -0
  17. package/src/cli/validators/index.ts +5 -0
  18. package/src/index.ts +4 -0
  19. package/README.ja.md +0 -587
  20. package/README.md +0 -694
  21. package/README.zh-CN.md +0 -634
  22. package/dist/application/services/CatalogUpdateService.d.ts +0 -209
  23. package/dist/application/services/CatalogUpdateService.d.ts.map +0 -1
  24. package/dist/application/services/CatalogUpdateService.js +0 -839
  25. package/dist/application/services/CatalogUpdateService.js.map +0 -1
  26. package/dist/application/services/WorkspaceService.d.ts +0 -139
  27. package/dist/application/services/WorkspaceService.d.ts.map +0 -1
  28. package/dist/application/services/WorkspaceService.js +0 -340
  29. package/dist/application/services/WorkspaceService.js.map +0 -1
  30. package/dist/cli/commands/CheckCommand.d.ts +0 -40
  31. package/dist/cli/commands/CheckCommand.d.ts.map +0 -1
  32. package/dist/cli/commands/CheckCommand.js +0 -177
  33. package/dist/cli/commands/CheckCommand.js.map +0 -1
  34. package/dist/cli/commands/InitCommand.d.ts +0 -53
  35. package/dist/cli/commands/InitCommand.d.ts.map +0 -1
  36. package/dist/cli/commands/InitCommand.js +0 -338
  37. package/dist/cli/commands/InitCommand.js.map +0 -1
  38. package/dist/cli/commands/SecurityCommand.d.ts +0 -113
  39. package/dist/cli/commands/SecurityCommand.d.ts.map +0 -1
  40. package/dist/cli/commands/SecurityCommand.js +0 -410
  41. package/dist/cli/commands/SecurityCommand.js.map +0 -1
  42. package/dist/cli/commands/UpdateCommand.d.ts +0 -44
  43. package/dist/cli/commands/UpdateCommand.d.ts.map +0 -1
  44. package/dist/cli/commands/UpdateCommand.js +0 -189
  45. package/dist/cli/commands/UpdateCommand.js.map +0 -1
  46. package/dist/cli/formatters/OutputFormatter.d.ts +0 -116
  47. package/dist/cli/formatters/OutputFormatter.d.ts.map +0 -1
  48. package/dist/cli/formatters/OutputFormatter.js +0 -664
  49. package/dist/cli/formatters/OutputFormatter.js.map +0 -1
  50. package/dist/cli/formatters/ProgressBar.d.ts +0 -195
  51. package/dist/cli/formatters/ProgressBar.d.ts.map +0 -1
  52. package/dist/cli/formatters/ProgressBar.js +0 -622
  53. package/dist/cli/formatters/ProgressBar.js.map +0 -1
  54. package/dist/cli/index.d.ts +0 -12
  55. package/dist/cli/index.d.ts.map +0 -1
  56. package/dist/cli/index.js +0 -492
  57. package/dist/cli/index.js.map +0 -1
  58. package/dist/cli/interactive/InteractivePrompts.d.ts +0 -85
  59. package/dist/cli/interactive/InteractivePrompts.d.ts.map +0 -1
  60. package/dist/cli/interactive/InteractivePrompts.js +0 -434
  61. package/dist/cli/interactive/InteractivePrompts.js.map +0 -1
  62. package/dist/cli/options/GlobalOptions.d.ts +0 -117
  63. package/dist/cli/options/GlobalOptions.d.ts.map +0 -1
  64. package/dist/cli/options/GlobalOptions.js +0 -278
  65. package/dist/cli/options/GlobalOptions.js.map +0 -1
  66. package/dist/cli/options/index.d.ts +0 -5
  67. package/dist/cli/options/index.d.ts.map +0 -1
  68. package/dist/cli/options/index.js +0 -5
  69. package/dist/cli/options/index.js.map +0 -1
  70. package/dist/cli/themes/ColorTheme.d.ts +0 -211
  71. package/dist/cli/themes/ColorTheme.d.ts.map +0 -1
  72. package/dist/cli/themes/ColorTheme.js +0 -267
  73. package/dist/cli/themes/ColorTheme.js.map +0 -1
  74. package/dist/cli/validators/CommandValidator.d.ts +0 -60
  75. package/dist/cli/validators/CommandValidator.d.ts.map +0 -1
  76. package/dist/cli/validators/CommandValidator.js +0 -319
  77. package/dist/cli/validators/CommandValidator.js.map +0 -1
  78. package/dist/cli/validators/index.d.ts +0 -5
  79. package/dist/cli/validators/index.d.ts.map +0 -1
  80. package/dist/cli/validators/index.js +0 -5
  81. package/dist/cli/validators/index.js.map +0 -1
  82. package/dist/common/config/Config.d.ts +0 -142
  83. package/dist/common/config/Config.d.ts.map +0 -1
  84. package/dist/common/config/Config.js +0 -382
  85. package/dist/common/config/Config.js.map +0 -1
  86. package/dist/common/config/ConfigLoader.d.ts +0 -49
  87. package/dist/common/config/ConfigLoader.d.ts.map +0 -1
  88. package/dist/common/config/ConfigLoader.js +0 -180
  89. package/dist/common/config/ConfigLoader.js.map +0 -1
  90. package/dist/common/config/PackageFilterConfig.d.ts +0 -56
  91. package/dist/common/config/PackageFilterConfig.d.ts.map +0 -1
  92. package/dist/common/config/PackageFilterConfig.js +0 -94
  93. package/dist/common/config/PackageFilterConfig.js.map +0 -1
  94. package/dist/common/config/index.d.ts +0 -8
  95. package/dist/common/config/index.d.ts.map +0 -1
  96. package/dist/common/config/index.js +0 -8
  97. package/dist/common/config/index.js.map +0 -1
  98. package/dist/common/error-handling/ErrorTracker.d.ts +0 -48
  99. package/dist/common/error-handling/ErrorTracker.d.ts.map +0 -1
  100. package/dist/common/error-handling/ErrorTracker.js +0 -93
  101. package/dist/common/error-handling/ErrorTracker.js.map +0 -1
  102. package/dist/common/error-handling/UserFriendlyErrorHandler.d.ts +0 -74
  103. package/dist/common/error-handling/UserFriendlyErrorHandler.d.ts.map +0 -1
  104. package/dist/common/error-handling/UserFriendlyErrorHandler.js +0 -703
  105. package/dist/common/error-handling/UserFriendlyErrorHandler.js.map +0 -1
  106. package/dist/common/error-handling/index.d.ts +0 -11
  107. package/dist/common/error-handling/index.d.ts.map +0 -1
  108. package/dist/common/error-handling/index.js +0 -9
  109. package/dist/common/error-handling/index.js.map +0 -1
  110. package/dist/common/logger/Logger.d.ts +0 -110
  111. package/dist/common/logger/Logger.d.ts.map +0 -1
  112. package/dist/common/logger/Logger.js +0 -289
  113. package/dist/common/logger/Logger.js.map +0 -1
  114. package/dist/common/logger/index.d.ts +0 -6
  115. package/dist/common/logger/index.d.ts.map +0 -1
  116. package/dist/common/logger/index.js +0 -6
  117. package/dist/common/logger/index.js.map +0 -1
  118. package/dist/common/types/cli.d.ts +0 -265
  119. package/dist/common/types/cli.d.ts.map +0 -1
  120. package/dist/common/types/cli.js +0 -5
  121. package/dist/common/types/cli.js.map +0 -1
  122. package/dist/common/types/core.d.ts +0 -270
  123. package/dist/common/types/core.d.ts.map +0 -1
  124. package/dist/common/types/core.js +0 -32
  125. package/dist/common/types/core.js.map +0 -1
  126. package/dist/common/types/index.d.ts +0 -8
  127. package/dist/common/types/index.d.ts.map +0 -1
  128. package/dist/common/types/index.js +0 -8
  129. package/dist/common/types/index.js.map +0 -1
  130. package/dist/common/utils/VersionChecker.d.ts +0 -54
  131. package/dist/common/utils/VersionChecker.d.ts.map +0 -1
  132. package/dist/common/utils/VersionChecker.js +0 -180
  133. package/dist/common/utils/VersionChecker.js.map +0 -1
  134. package/dist/common/utils/async.d.ts +0 -74
  135. package/dist/common/utils/async.d.ts.map +0 -1
  136. package/dist/common/utils/async.js +0 -228
  137. package/dist/common/utils/async.js.map +0 -1
  138. package/dist/common/utils/format.d.ts +0 -32
  139. package/dist/common/utils/format.d.ts.map +0 -1
  140. package/dist/common/utils/format.js +0 -121
  141. package/dist/common/utils/format.js.map +0 -1
  142. package/dist/common/utils/git.d.ts +0 -44
  143. package/dist/common/utils/git.d.ts.map +0 -1
  144. package/dist/common/utils/git.js +0 -147
  145. package/dist/common/utils/git.js.map +0 -1
  146. package/dist/common/utils/index.d.ts +0 -12
  147. package/dist/common/utils/index.d.ts.map +0 -1
  148. package/dist/common/utils/index.js +0 -12
  149. package/dist/common/utils/index.js.map +0 -1
  150. package/dist/common/utils/string.d.ts +0 -56
  151. package/dist/common/utils/string.d.ts.map +0 -1
  152. package/dist/common/utils/string.js +0 -134
  153. package/dist/common/utils/string.js.map +0 -1
  154. package/dist/common/utils/validation.d.ts +0 -88
  155. package/dist/common/utils/validation.d.ts.map +0 -1
  156. package/dist/common/utils/validation.js +0 -308
  157. package/dist/common/utils/validation.js.map +0 -1
  158. package/dist/domain/entities/Catalog.d.ts +0 -117
  159. package/dist/domain/entities/Catalog.d.ts.map +0 -1
  160. package/dist/domain/entities/Catalog.js +0 -240
  161. package/dist/domain/entities/Catalog.js.map +0 -1
  162. package/dist/domain/entities/Package.d.ts +0 -143
  163. package/dist/domain/entities/Package.d.ts.map +0 -1
  164. package/dist/domain/entities/Package.js +0 -272
  165. package/dist/domain/entities/Package.js.map +0 -1
  166. package/dist/domain/entities/Workspace.d.ts +0 -95
  167. package/dist/domain/entities/Workspace.d.ts.map +0 -1
  168. package/dist/domain/entities/Workspace.js +0 -173
  169. package/dist/domain/entities/Workspace.js.map +0 -1
  170. package/dist/domain/repositories/WorkspaceRepository.d.ts +0 -41
  171. package/dist/domain/repositories/WorkspaceRepository.d.ts.map +0 -1
  172. package/dist/domain/repositories/WorkspaceRepository.js +0 -8
  173. package/dist/domain/repositories/WorkspaceRepository.js.map +0 -1
  174. package/dist/domain/value-objects/CatalogCollection.d.ts +0 -106
  175. package/dist/domain/value-objects/CatalogCollection.d.ts.map +0 -1
  176. package/dist/domain/value-objects/CatalogCollection.js +0 -230
  177. package/dist/domain/value-objects/CatalogCollection.js.map +0 -1
  178. package/dist/domain/value-objects/PackageCollection.d.ts +0 -122
  179. package/dist/domain/value-objects/PackageCollection.d.ts.map +0 -1
  180. package/dist/domain/value-objects/PackageCollection.js +0 -263
  181. package/dist/domain/value-objects/PackageCollection.js.map +0 -1
  182. package/dist/domain/value-objects/Version.d.ts +0 -141
  183. package/dist/domain/value-objects/Version.d.ts.map +0 -1
  184. package/dist/domain/value-objects/Version.js +0 -268
  185. package/dist/domain/value-objects/Version.js.map +0 -1
  186. package/dist/domain/value-objects/WorkspaceConfig.d.ts +0 -144
  187. package/dist/domain/value-objects/WorkspaceConfig.d.ts.map +0 -1
  188. package/dist/domain/value-objects/WorkspaceConfig.js +0 -357
  189. package/dist/domain/value-objects/WorkspaceConfig.js.map +0 -1
  190. package/dist/domain/value-objects/WorkspaceId.d.ts +0 -51
  191. package/dist/domain/value-objects/WorkspaceId.d.ts.map +0 -1
  192. package/dist/domain/value-objects/WorkspaceId.js +0 -104
  193. package/dist/domain/value-objects/WorkspaceId.js.map +0 -1
  194. package/dist/domain/value-objects/WorkspacePath.d.ts +0 -75
  195. package/dist/domain/value-objects/WorkspacePath.d.ts.map +0 -1
  196. package/dist/domain/value-objects/WorkspacePath.js +0 -128
  197. package/dist/domain/value-objects/WorkspacePath.js.map +0 -1
  198. package/dist/index.d.ts +0 -25
  199. package/dist/index.d.ts.map +0 -1
  200. package/dist/infrastructure/cache/Cache.d.ts +0 -161
  201. package/dist/infrastructure/cache/Cache.d.ts.map +0 -1
  202. package/dist/infrastructure/cache/Cache.js +0 -398
  203. package/dist/infrastructure/cache/Cache.js.map +0 -1
  204. package/dist/infrastructure/cache/index.d.ts +0 -6
  205. package/dist/infrastructure/cache/index.d.ts.map +0 -1
  206. package/dist/infrastructure/cache/index.js +0 -6
  207. package/dist/infrastructure/cache/index.js.map +0 -1
  208. package/dist/infrastructure/external-services/NpmRegistryService.d.ts +0 -153
  209. package/dist/infrastructure/external-services/NpmRegistryService.d.ts.map +0 -1
  210. package/dist/infrastructure/external-services/NpmRegistryService.js +0 -511
  211. package/dist/infrastructure/external-services/NpmRegistryService.js.map +0 -1
  212. package/dist/infrastructure/file-system/FileSystemService.d.ts +0 -120
  213. package/dist/infrastructure/file-system/FileSystemService.d.ts.map +0 -1
  214. package/dist/infrastructure/file-system/FileSystemService.js +0 -663
  215. package/dist/infrastructure/file-system/FileSystemService.js.map +0 -1
  216. package/dist/infrastructure/repositories/FileWorkspaceRepository.d.ts +0 -57
  217. package/dist/infrastructure/repositories/FileWorkspaceRepository.d.ts.map +0 -1
  218. package/dist/infrastructure/repositories/FileWorkspaceRepository.js +0 -179
  219. package/dist/infrastructure/repositories/FileWorkspaceRepository.js.map +0 -1
  220. package/dist/infrastructure/utils/NpmrcParser.d.ts +0 -40
  221. package/dist/infrastructure/utils/NpmrcParser.d.ts.map +0 -1
  222. package/dist/infrastructure/utils/NpmrcParser.js +0 -157
  223. package/dist/infrastructure/utils/NpmrcParser.js.map +0 -1
@@ -0,0 +1,395 @@
1
+ /**
2
+ * CLI Command Validation
3
+ *
4
+ * Validates CLI command options and arguments before execution.
5
+ * Provides detailed error messages and suggestions.
6
+ */
7
+
8
+ import { validateCliOptions, ValidationResult } from '@pcu/utils';
9
+ import { getConfig } from '@pcu/utils';
10
+
11
+ export interface ValidatedOptions {
12
+ workspace?: string;
13
+ catalog?: string;
14
+ format?: string;
15
+ target?: string;
16
+ interactive?: boolean;
17
+ dryRun?: boolean;
18
+ force?: boolean;
19
+ prerelease?: boolean;
20
+ include?: string[];
21
+ exclude?: string[];
22
+ createBackup?: boolean;
23
+ verbose?: boolean;
24
+ color?: boolean;
25
+ registry?: string;
26
+ timeout?: number;
27
+ }
28
+
29
+ export class CommandValidator {
30
+ private config = getConfig().getConfig();
31
+
32
+ /**
33
+ * Validate check command options
34
+ */
35
+ validateCheckOptions(options: any): ValidationResult {
36
+ const errors: string[] = [];
37
+ const warnings: string[] = [];
38
+
39
+ // Basic validation using utility
40
+ const basicValidation = validateCliOptions(options);
41
+ errors.push(...basicValidation.errors);
42
+ warnings.push(...basicValidation.warnings);
43
+
44
+ // Check-specific validations
45
+ if (options.catalog && typeof options.catalog !== 'string') {
46
+ errors.push('Catalog name must be a string');
47
+ }
48
+
49
+ // Validate mutually exclusive options
50
+ if (options.interactive && options.format === 'json') {
51
+ warnings.push('Interactive mode is not useful with JSON output format');
52
+ }
53
+
54
+ if (options.verbose && options.silent) {
55
+ errors.push('Cannot use both --verbose and --silent options');
56
+ }
57
+
58
+ return {
59
+ isValid: errors.length === 0,
60
+ errors,
61
+ warnings,
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Validate update command options
67
+ */
68
+ validateUpdateOptions(options: any): ValidationResult {
69
+ const errors: string[] = [];
70
+ const warnings: string[] = [];
71
+
72
+ // Basic validation
73
+ const basicValidation = validateCliOptions(options);
74
+ errors.push(...basicValidation.errors);
75
+ warnings.push(...basicValidation.warnings);
76
+
77
+ // Update-specific validations
78
+ if (options.interactive && options.dryRun) {
79
+ errors.push('Cannot use --interactive with --dry-run');
80
+ }
81
+
82
+ if (options.force && !options.dryRun && !options.createBackup) {
83
+ warnings.push('Using --force without backup. Consider using --create-backup for safety');
84
+ }
85
+
86
+ if (options.target === 'major' && !options.force && !options.interactive) {
87
+ warnings.push(
88
+ 'Major updates may contain breaking changes. Consider using --interactive or --force'
89
+ );
90
+ }
91
+
92
+ // Validate include/exclude patterns
93
+ if (options.include && options.exclude) {
94
+ const overlapping = options.include.some((inc: string) =>
95
+ options.exclude.some((exc: string) => inc === exc)
96
+ );
97
+ if (overlapping) {
98
+ warnings.push('Some patterns appear in both include and exclude lists');
99
+ }
100
+ }
101
+
102
+ return {
103
+ isValid: errors.length === 0,
104
+ errors,
105
+ warnings,
106
+ };
107
+ }
108
+
109
+ /**
110
+ * Validate analyze command arguments
111
+ */
112
+ validateAnalyzeArgs(catalog: string, packageName: string, version?: string): ValidationResult {
113
+ const errors: string[] = [];
114
+ const warnings: string[] = [];
115
+
116
+ // Validate catalog name
117
+ if (!catalog || catalog.trim() === '') {
118
+ errors.push('Catalog name is required');
119
+ } else if (catalog.includes('/') || catalog.includes('\\')) {
120
+ errors.push('Catalog name cannot contain path separators');
121
+ }
122
+
123
+ // Validate package name
124
+ if (!packageName || packageName.trim() === '') {
125
+ errors.push('Package name is required');
126
+ } else {
127
+ // Basic package name validation
128
+ const packageNameRegex = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
129
+ if (!packageNameRegex.test(packageName)) {
130
+ errors.push('Invalid package name format');
131
+ }
132
+ }
133
+
134
+ // Validate version if provided
135
+ if (version) {
136
+ const semverRegex =
137
+ /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
138
+ if (!semverRegex.test(version)) {
139
+ errors.push('Invalid version format. Use semantic versioning (e.g., 1.2.3)');
140
+ }
141
+ }
142
+
143
+ return {
144
+ isValid: errors.length === 0,
145
+ errors,
146
+ warnings,
147
+ };
148
+ }
149
+
150
+ /**
151
+ * Validate workspace command options
152
+ */
153
+ validateWorkspaceOptions(options: any): ValidationResult {
154
+ const errors: string[] = [];
155
+ const warnings: string[] = [];
156
+
157
+ // Basic validation
158
+ const basicValidation = validateCliOptions(options);
159
+ errors.push(...basicValidation.errors);
160
+ warnings.push(...basicValidation.warnings);
161
+
162
+ // Workspace-specific validations
163
+ const actionCount = [options.validate, options.stats, options.info].filter(Boolean).length;
164
+ if (actionCount > 1) {
165
+ errors.push('Cannot use multiple workspace actions simultaneously');
166
+ }
167
+
168
+ return {
169
+ isValid: errors.length === 0,
170
+ errors,
171
+ warnings,
172
+ };
173
+ }
174
+
175
+ /**
176
+ * Validate global options
177
+ */
178
+ validateGlobalOptions(options: any): ValidationResult {
179
+ const errors: string[] = [];
180
+ const warnings: string[] = [];
181
+
182
+ // Validate workspace path
183
+ if (options.workspace) {
184
+ // Future: Add path validation logic here
185
+ // Currently skipped to avoid TypeScript errors
186
+ }
187
+
188
+ // Validate color options
189
+ if (options.noColor && options.color) {
190
+ errors.push('Cannot use both --color and --no-color');
191
+ }
192
+
193
+ // Check for deprecated options (future-proofing)
194
+ const deprecatedOptions = ['silent']; // Example
195
+ for (const deprecated of deprecatedOptions) {
196
+ if (options[deprecated]) {
197
+ warnings.push(
198
+ `Option --${deprecated} is deprecated and will be removed in future versions`
199
+ );
200
+ }
201
+ }
202
+
203
+ return {
204
+ isValid: errors.length === 0,
205
+ errors,
206
+ warnings,
207
+ };
208
+ }
209
+
210
+ /**
211
+ * Validate configuration object
212
+ */
213
+ validateConfigFile(configPath: string): ValidationResult {
214
+ const errors: string[] = [];
215
+ const warnings: string[] = [];
216
+
217
+ try {
218
+ const fs = require('fs');
219
+ // const path = require('path'); // Reserved for future use
220
+
221
+ if (!fs.existsSync(configPath)) {
222
+ errors.push(`Configuration file not found: ${configPath}`);
223
+ return { isValid: false, errors, warnings };
224
+ }
225
+
226
+ let config: any;
227
+
228
+ if (configPath.endsWith('.js')) {
229
+ // JavaScript config file
230
+ try {
231
+ delete require.cache[require.resolve(configPath)];
232
+ config = require(configPath);
233
+ } catch (error) {
234
+ errors.push(`Failed to load JavaScript config: ${error}`);
235
+ return { isValid: false, errors, warnings };
236
+ }
237
+ } else {
238
+ // JSON config file
239
+ try {
240
+ const content = fs.readFileSync(configPath, 'utf-8');
241
+ config = JSON.parse(content);
242
+ } catch (error) {
243
+ errors.push(`Failed to parse JSON config: ${error}`);
244
+ return { isValid: false, errors, warnings };
245
+ }
246
+ }
247
+
248
+ // Validate config structure
249
+ if (typeof config !== 'object' || config === null) {
250
+ errors.push('Configuration must be an object');
251
+ return { isValid: false, errors, warnings };
252
+ }
253
+
254
+ // Validate known configuration sections
255
+ if (config.registry && typeof config.registry !== 'object') {
256
+ errors.push('registry configuration must be an object');
257
+ }
258
+
259
+ if (config.update && typeof config.update !== 'object') {
260
+ errors.push('update configuration must be an object');
261
+ }
262
+
263
+ if (config.output && typeof config.output !== 'object') {
264
+ errors.push('output configuration must be an object');
265
+ }
266
+
267
+ // Check for unknown top-level keys
268
+ const knownKeys = ['registry', 'update', 'output', 'workspace', 'notification', 'logging'];
269
+ const unknownKeys = Object.keys(config).filter((key) => !knownKeys.includes(key));
270
+
271
+ if (unknownKeys.length > 0) {
272
+ warnings.push(`Unknown configuration keys: ${unknownKeys.join(', ')}`);
273
+ }
274
+ } catch (error) {
275
+ errors.push(`Failed to validate configuration file: ${error}`);
276
+ }
277
+
278
+ return {
279
+ isValid: errors.length === 0,
280
+ errors,
281
+ warnings,
282
+ };
283
+ }
284
+
285
+ /**
286
+ * Sanitize and normalize options
287
+ */
288
+ sanitizeOptions(options: any): ValidatedOptions {
289
+ const sanitized: ValidatedOptions = {};
290
+
291
+ // String options
292
+ if (options.workspace) {
293
+ sanitized.workspace = String(options.workspace).trim();
294
+ }
295
+ if (options.catalog) {
296
+ sanitized.catalog = String(options.catalog).trim();
297
+ }
298
+ if (options.format) {
299
+ sanitized.format = String(options.format).toLowerCase().trim();
300
+ }
301
+ if (options.target) {
302
+ sanitized.target = String(options.target).toLowerCase().trim();
303
+ }
304
+ if (options.registry) {
305
+ sanitized.registry = String(options.registry).trim();
306
+ }
307
+
308
+ // Boolean options
309
+ sanitized.interactive = Boolean(options.interactive);
310
+ sanitized.dryRun = Boolean(options.dryRun);
311
+ sanitized.force = Boolean(options.force);
312
+ sanitized.prerelease = Boolean(options.prerelease);
313
+ sanitized.createBackup = Boolean(options.createBackup);
314
+ sanitized.verbose = Boolean(options.verbose);
315
+
316
+ // Handle color option (tri-state: true, false, or undefined)
317
+ if (options.color !== undefined) {
318
+ sanitized.color = Boolean(options.color);
319
+ } else if (options.noColor) {
320
+ sanitized.color = false;
321
+ }
322
+
323
+ // Number options
324
+ if (options.timeout) {
325
+ const timeout = parseInt(String(options.timeout), 10);
326
+ if (!isNaN(timeout) && timeout > 0) {
327
+ sanitized.timeout = timeout;
328
+ }
329
+ }
330
+
331
+ // Array options
332
+ if (options.include) {
333
+ sanitized.include = Array.isArray(options.include)
334
+ ? options.include.map((p: any) => String(p).trim()).filter(Boolean)
335
+ : [String(options.include).trim()].filter(Boolean);
336
+ }
337
+ if (options.exclude) {
338
+ sanitized.exclude = Array.isArray(options.exclude)
339
+ ? options.exclude.map((p: any) => String(p).trim()).filter(Boolean)
340
+ : [String(options.exclude).trim()].filter(Boolean);
341
+ }
342
+
343
+ return sanitized;
344
+ }
345
+
346
+ /**
347
+ * Get validation suggestions based on common mistakes
348
+ */
349
+ getSuggestions(command: string, options: any): string[] {
350
+ const suggestions: string[] = [];
351
+
352
+ switch (command) {
353
+ case 'check':
354
+ if (!options.workspace) {
355
+ suggestions.push('Consider specifying --workspace for non-standard directory structures');
356
+ }
357
+ if (options.format === 'json' && options.verbose) {
358
+ suggestions.push(
359
+ 'JSON output already includes detailed info, --verbose may be redundant'
360
+ );
361
+ }
362
+ break;
363
+
364
+ case 'update':
365
+ if (!options.dryRun && !options.createBackup && !options.force) {
366
+ suggestions.push('Consider using --dry-run first to preview changes');
367
+ }
368
+ if (options.target === 'greatest' && !options.prerelease) {
369
+ suggestions.push('Add --prerelease to include pre-release versions with greatest target');
370
+ }
371
+ break;
372
+
373
+ case 'analyze':
374
+ if (!options.format) {
375
+ suggestions.push('Use --format json for programmatic consumption of analysis data');
376
+ }
377
+ break;
378
+
379
+ case 'workspace':
380
+ if (!options.validate && !options.stats) {
381
+ suggestions.push(
382
+ 'Use --validate to check workspace integrity or --stats for detailed information'
383
+ );
384
+ }
385
+ break;
386
+ }
387
+
388
+ // General suggestions
389
+ if (this.config.output.verbose && !options.verbose) {
390
+ suggestions.push('Global verbose mode is enabled in config');
391
+ }
392
+
393
+ return suggestions;
394
+ }
395
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * CLI Validators Entry Point
3
+ */
4
+
5
+ export * from './commandValidator.js';
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+
3
+ // CLI entry point for pnpm-catalog-updates
4
+ export * from './cli/index';