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