pnpm-catalog-updates 1.0.3 → 1.1.2
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 +15 -0
- package/dist/index.js +22031 -10684
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
- package/src/cli/__tests__/commandRegistrar.test.ts +248 -0
- package/src/cli/commandRegistrar.ts +785 -0
- package/src/cli/commands/__tests__/aiCommand.test.ts +161 -0
- package/src/cli/commands/__tests__/analyzeCommand.test.ts +283 -0
- package/src/cli/commands/__tests__/checkCommand.test.ts +435 -0
- package/src/cli/commands/__tests__/graphCommand.test.ts +312 -0
- package/src/cli/commands/__tests__/initCommand.test.ts +317 -0
- package/src/cli/commands/__tests__/rollbackCommand.test.ts +400 -0
- package/src/cli/commands/__tests__/securityCommand.test.ts +467 -0
- package/src/cli/commands/__tests__/themeCommand.test.ts +166 -0
- package/src/cli/commands/__tests__/updateCommand.test.ts +720 -0
- package/src/cli/commands/__tests__/workspaceCommand.test.ts +286 -0
- package/src/cli/commands/aiCommand.ts +163 -0
- package/src/cli/commands/analyzeCommand.ts +219 -0
- package/src/cli/commands/checkCommand.ts +91 -98
- package/src/cli/commands/graphCommand.ts +475 -0
- package/src/cli/commands/initCommand.ts +64 -54
- package/src/cli/commands/rollbackCommand.ts +334 -0
- package/src/cli/commands/securityCommand.ts +165 -100
- package/src/cli/commands/themeCommand.ts +148 -0
- package/src/cli/commands/updateCommand.ts +215 -263
- package/src/cli/commands/workspaceCommand.ts +73 -0
- package/src/cli/constants/cliChoices.ts +93 -0
- package/src/cli/formatters/__tests__/__snapshots__/outputFormatter.test.ts.snap +557 -0
- package/src/cli/formatters/__tests__/ciFormatter.test.ts +526 -0
- package/src/cli/formatters/__tests__/outputFormatter.test.ts +448 -0
- package/src/cli/formatters/__tests__/progressBar.test.ts +709 -0
- package/src/cli/formatters/ciFormatter.ts +964 -0
- package/src/cli/formatters/colorUtils.ts +145 -0
- package/src/cli/formatters/outputFormatter.ts +615 -332
- package/src/cli/formatters/progressBar.ts +43 -52
- package/src/cli/formatters/versionFormatter.ts +132 -0
- package/src/cli/handlers/aiAnalysisHandler.ts +205 -0
- package/src/cli/handlers/changelogHandler.ts +113 -0
- package/src/cli/handlers/index.ts +9 -0
- package/src/cli/handlers/installHandler.ts +130 -0
- package/src/cli/index.ts +175 -726
- package/src/cli/interactive/InteractiveOptionsCollector.ts +387 -0
- package/src/cli/interactive/interactivePrompts.ts +189 -83
- package/src/cli/interactive/optionUtils.ts +89 -0
- package/src/cli/themes/colorTheme.ts +43 -16
- package/src/cli/utils/cliOutput.ts +118 -0
- package/src/cli/utils/commandHelpers.ts +249 -0
- package/src/cli/validators/commandValidator.ts +321 -336
- package/src/cli/validators/index.ts +37 -2
- package/src/cli/options/globalOptions.ts +0 -437
- package/src/cli/options/index.ts +0 -5
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI Validators
|
|
2
|
+
* CLI Validators
|
|
3
|
+
*
|
|
4
|
+
* QUAL-002: Centralized validation exports
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
|
-
export
|
|
7
|
+
export {
|
|
8
|
+
type AIOptions,
|
|
9
|
+
// Types
|
|
10
|
+
type BaseCommandOptions,
|
|
11
|
+
// Composable validation utilities
|
|
12
|
+
composeValidators,
|
|
13
|
+
errorsOnly,
|
|
14
|
+
// Help text utilities
|
|
15
|
+
formatChoicesHelp,
|
|
16
|
+
type GraphOptions,
|
|
17
|
+
type InteractiveOptions,
|
|
18
|
+
type PatternOptions,
|
|
19
|
+
type SecurityOptions,
|
|
20
|
+
severityChoicesHelp,
|
|
21
|
+
type TargetOptions,
|
|
22
|
+
targetChoicesHelp,
|
|
23
|
+
validateAIOptions,
|
|
24
|
+
// Pre-composed validators for common commands
|
|
25
|
+
validateAnalyzeOptions,
|
|
26
|
+
validateCheckOptions,
|
|
27
|
+
// Individual validation rules (can be composed)
|
|
28
|
+
validateFormat,
|
|
29
|
+
validateGraphFormat,
|
|
30
|
+
validateGraphOptions,
|
|
31
|
+
validateGraphType,
|
|
32
|
+
validateInitOptions,
|
|
33
|
+
validateInteractiveConflicts,
|
|
34
|
+
validatePatterns,
|
|
35
|
+
validateSecurityOptions,
|
|
36
|
+
validateSeverity,
|
|
37
|
+
validateTarget,
|
|
38
|
+
validateUpdateOptions,
|
|
39
|
+
validateWorkspacePath,
|
|
40
|
+
} from './commandValidator.js'
|
|
@@ -1,437 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Global CLI Options
|
|
3
|
-
*
|
|
4
|
-
* Defines standardized option definitions for all CLI commands.
|
|
5
|
-
* Provides consistent option parsing and validation.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { Option } from 'commander'
|
|
9
|
-
|
|
10
|
-
export interface GlobalCliOptions {
|
|
11
|
-
workspace?: string
|
|
12
|
-
verbose?: boolean
|
|
13
|
-
color?: boolean
|
|
14
|
-
registry?: string
|
|
15
|
-
timeout?: number
|
|
16
|
-
config?: string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface CheckCliOptions extends GlobalCliOptions {
|
|
20
|
-
catalog?: string
|
|
21
|
-
format?: 'table' | 'json' | 'yaml' | 'minimal'
|
|
22
|
-
target?: 'latest' | 'greatest' | 'minor' | 'patch' | 'newest'
|
|
23
|
-
prerelease?: boolean
|
|
24
|
-
include?: string[]
|
|
25
|
-
exclude?: string[]
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface UpdateCliOptions extends CheckCliOptions {
|
|
29
|
-
interactive?: boolean
|
|
30
|
-
dryRun?: boolean
|
|
31
|
-
force?: boolean
|
|
32
|
-
createBackup?: boolean
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface AnalyzeCliOptions extends GlobalCliOptions {
|
|
36
|
-
format?: 'table' | 'json' | 'yaml' | 'minimal'
|
|
37
|
-
ai?: boolean
|
|
38
|
-
provider?: 'auto' | 'claude' | 'gemini' | 'codex'
|
|
39
|
-
analysisType?: 'impact' | 'security' | 'compatibility' | 'recommend'
|
|
40
|
-
skipCache?: boolean
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface WorkspaceCliOptions extends GlobalCliOptions {
|
|
44
|
-
validate?: boolean
|
|
45
|
-
stats?: boolean
|
|
46
|
-
info?: boolean
|
|
47
|
-
format?: 'table' | 'json' | 'yaml' | 'minimal'
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Global options available to all commands
|
|
52
|
-
*/
|
|
53
|
-
export const globalOptions = [
|
|
54
|
-
new Option('-w, --workspace <path>', 'workspace directory path').env('PCU_WORKSPACE'),
|
|
55
|
-
|
|
56
|
-
new Option('-v, --verbose', 'enable verbose logging').env('PCU_VERBOSE'),
|
|
57
|
-
|
|
58
|
-
new Option('--no-color', 'disable colored output').env('PCU_NO_COLOR'),
|
|
59
|
-
|
|
60
|
-
new Option('--registry <url>', 'NPM registry URL').env('PCU_REGISTRY'),
|
|
61
|
-
|
|
62
|
-
new Option('--timeout <ms>', 'request timeout in milliseconds')
|
|
63
|
-
.argParser(parseInt)
|
|
64
|
-
.env('PCU_TIMEOUT'),
|
|
65
|
-
|
|
66
|
-
new Option('--config <path>', 'path to configuration file').env('PCU_CONFIG'),
|
|
67
|
-
]
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Check command specific options
|
|
71
|
-
*/
|
|
72
|
-
export const checkOptions = [
|
|
73
|
-
...globalOptions,
|
|
74
|
-
|
|
75
|
-
new Option('--catalog <name>', 'check specific catalog only').env('PCU_CATALOG'),
|
|
76
|
-
|
|
77
|
-
new Option('-f, --format <type>', 'output format')
|
|
78
|
-
.choices(['table', 'json', 'yaml', 'minimal'])
|
|
79
|
-
.default('table')
|
|
80
|
-
.env('PCU_OUTPUT_FORMAT'),
|
|
81
|
-
|
|
82
|
-
new Option('-t, --target <type>', 'update target')
|
|
83
|
-
.choices(['latest', 'greatest', 'minor', 'patch', 'newest'])
|
|
84
|
-
.default('latest')
|
|
85
|
-
.env('PCU_UPDATE_TARGET'),
|
|
86
|
-
|
|
87
|
-
new Option('--prerelease', 'include prerelease versions').env('PCU_PRERELEASE'),
|
|
88
|
-
|
|
89
|
-
new Option('--include <pattern...>', 'include packages matching pattern').env('PCU_INCLUDE'),
|
|
90
|
-
|
|
91
|
-
new Option('--exclude <pattern...>', 'exclude packages matching pattern').env('PCU_EXCLUDE'),
|
|
92
|
-
]
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Update command specific options
|
|
96
|
-
*/
|
|
97
|
-
export const updateOptions = [
|
|
98
|
-
...checkOptions,
|
|
99
|
-
|
|
100
|
-
new Option('-i, --interactive', 'interactive mode to choose updates').env('PCU_INTERACTIVE'),
|
|
101
|
-
|
|
102
|
-
new Option('-d, --dry-run', 'preview changes without writing files').env('PCU_DRY_RUN'),
|
|
103
|
-
|
|
104
|
-
new Option('--force', 'force updates even if risky').env('PCU_FORCE'),
|
|
105
|
-
|
|
106
|
-
new Option('--create-backup', 'create backup files before updating').env('PCU_CREATE_BACKUP'),
|
|
107
|
-
]
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Analyze command specific options
|
|
111
|
-
*/
|
|
112
|
-
export const analyzeOptions = [
|
|
113
|
-
...globalOptions,
|
|
114
|
-
|
|
115
|
-
new Option('-f, --format <type>', 'output format')
|
|
116
|
-
.choices(['table', 'json', 'yaml', 'minimal'])
|
|
117
|
-
.default('table')
|
|
118
|
-
.env('PCU_OUTPUT_FORMAT'),
|
|
119
|
-
|
|
120
|
-
new Option('--ai', 'enable AI-powered analysis').env('PCU_AI_ENABLED'),
|
|
121
|
-
|
|
122
|
-
new Option('--provider <name>', 'AI provider to use')
|
|
123
|
-
.choices(['auto', 'claude', 'gemini', 'codex'])
|
|
124
|
-
.default('auto')
|
|
125
|
-
.env('PCU_AI_PROVIDER'),
|
|
126
|
-
|
|
127
|
-
new Option('--analysis-type <type>', 'type of AI analysis')
|
|
128
|
-
.choices(['impact', 'security', 'compatibility', 'recommend'])
|
|
129
|
-
.default('impact')
|
|
130
|
-
.env('PCU_AI_ANALYSIS_TYPE'),
|
|
131
|
-
|
|
132
|
-
new Option('--skip-cache', 'skip AI analysis cache').env('PCU_AI_SKIP_CACHE'),
|
|
133
|
-
]
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Workspace command specific options
|
|
137
|
-
*/
|
|
138
|
-
export const workspaceOptions = [
|
|
139
|
-
...globalOptions,
|
|
140
|
-
|
|
141
|
-
new Option('--validate', 'validate workspace configuration'),
|
|
142
|
-
|
|
143
|
-
new Option('--stats', 'show workspace statistics'),
|
|
144
|
-
|
|
145
|
-
new Option('--info', 'show workspace information'),
|
|
146
|
-
|
|
147
|
-
new Option('-f, --format <type>', 'output format')
|
|
148
|
-
.choices(['table', 'json', 'yaml', 'minimal'])
|
|
149
|
-
.default('table')
|
|
150
|
-
.env('PCU_OUTPUT_FORMAT'),
|
|
151
|
-
]
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Option groups for better help organization
|
|
155
|
-
*/
|
|
156
|
-
export const optionGroups = {
|
|
157
|
-
global: {
|
|
158
|
-
title: 'Global Options',
|
|
159
|
-
options: globalOptions,
|
|
160
|
-
},
|
|
161
|
-
output: {
|
|
162
|
-
title: 'Output Options',
|
|
163
|
-
options: [
|
|
164
|
-
new Option('-f, --format <type>', 'output format')
|
|
165
|
-
.choices(['table', 'json', 'yaml', 'minimal'])
|
|
166
|
-
.default('table'),
|
|
167
|
-
new Option('--no-color', 'disable colored output'),
|
|
168
|
-
new Option('-v, --verbose', 'enable verbose logging'),
|
|
169
|
-
],
|
|
170
|
-
},
|
|
171
|
-
filtering: {
|
|
172
|
-
title: 'Filtering Options',
|
|
173
|
-
options: [
|
|
174
|
-
new Option('--catalog <name>', 'check specific catalog only'),
|
|
175
|
-
new Option('--include <pattern...>', 'include packages matching pattern'),
|
|
176
|
-
new Option('--exclude <pattern...>', 'exclude packages matching pattern'),
|
|
177
|
-
],
|
|
178
|
-
},
|
|
179
|
-
update: {
|
|
180
|
-
title: 'Update Options',
|
|
181
|
-
options: [
|
|
182
|
-
new Option('-t, --target <type>', 'update target')
|
|
183
|
-
.choices(['latest', 'greatest', 'minor', 'patch', 'newest'])
|
|
184
|
-
.default('latest'),
|
|
185
|
-
new Option('--prerelease', 'include prerelease versions'),
|
|
186
|
-
new Option('-i, --interactive', 'interactive mode'),
|
|
187
|
-
new Option('-d, --dry-run', 'preview changes only'),
|
|
188
|
-
new Option('--force', 'force updates'),
|
|
189
|
-
new Option('--create-backup', 'create backup files'),
|
|
190
|
-
],
|
|
191
|
-
},
|
|
192
|
-
registry: {
|
|
193
|
-
title: 'Registry Options',
|
|
194
|
-
options: [
|
|
195
|
-
new Option('--registry <url>', 'NPM registry URL'),
|
|
196
|
-
new Option('--timeout <ms>', 'request timeout').argParser(parseInt),
|
|
197
|
-
],
|
|
198
|
-
},
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Utility functions for option handling
|
|
203
|
-
*/
|
|
204
|
-
export class OptionUtils {
|
|
205
|
-
private static parseBoolean(value: unknown): boolean {
|
|
206
|
-
if (value === undefined || value === null) return false
|
|
207
|
-
if (typeof value === 'boolean') return value
|
|
208
|
-
if (typeof value === 'number') return value !== 0
|
|
209
|
-
if (typeof value === 'string') {
|
|
210
|
-
const normalized = value.trim().toLowerCase()
|
|
211
|
-
if (normalized === '') return false
|
|
212
|
-
if (['false', '0', 'no', 'off', 'n'].includes(normalized)) return false
|
|
213
|
-
if (['true', '1', 'yes', 'on', 'y'].includes(normalized)) return true
|
|
214
|
-
return true
|
|
215
|
-
}
|
|
216
|
-
return Boolean(value)
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Parse and validate global options
|
|
221
|
-
*/
|
|
222
|
-
static parseGlobalOptions(options: any): GlobalCliOptions {
|
|
223
|
-
const parsed: GlobalCliOptions = {}
|
|
224
|
-
|
|
225
|
-
if (options.workspace) {
|
|
226
|
-
parsed.workspace = String(options.workspace).trim()
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (options.verbose !== undefined) {
|
|
230
|
-
parsed.verbose = OptionUtils.parseBoolean(options.verbose)
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
if (options.color !== undefined) {
|
|
234
|
-
parsed.color = OptionUtils.parseBoolean(options.color)
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (options.registry) {
|
|
238
|
-
parsed.registry = String(options.registry).trim()
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (options.timeout) {
|
|
242
|
-
const timeout = parseInt(String(options.timeout), 10)
|
|
243
|
-
if (!Number.isNaN(timeout) && timeout > 0) {
|
|
244
|
-
parsed.timeout = timeout
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (options.config) {
|
|
249
|
-
parsed.config = String(options.config).trim()
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return parsed
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Parse check command options
|
|
257
|
-
*/
|
|
258
|
-
static parseCheckOptions(options: any): CheckCliOptions {
|
|
259
|
-
const global = OptionUtils.parseGlobalOptions(options)
|
|
260
|
-
const check: CheckCliOptions = { ...global }
|
|
261
|
-
|
|
262
|
-
if (options.catalog) {
|
|
263
|
-
check.catalog = String(options.catalog).trim()
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
if (options.format && typeof options.format === 'string') {
|
|
267
|
-
check.format = options.format as Exclude<CheckCliOptions['format'], undefined>
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if (options.target && typeof options.target === 'string') {
|
|
271
|
-
check.target = options.target as Exclude<CheckCliOptions['target'], undefined>
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (options.prerelease !== undefined) {
|
|
275
|
-
check.prerelease = OptionUtils.parseBoolean(options.prerelease)
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (options.include) {
|
|
279
|
-
check.include = Array.isArray(options.include)
|
|
280
|
-
? options.include.map((p: any) => String(p).trim()).filter(Boolean)
|
|
281
|
-
: [String(options.include).trim()].filter(Boolean)
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (options.exclude) {
|
|
285
|
-
check.exclude = Array.isArray(options.exclude)
|
|
286
|
-
? options.exclude.map((p: any) => String(p).trim()).filter(Boolean)
|
|
287
|
-
: [String(options.exclude).trim()].filter(Boolean)
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
return check
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Parse update command options
|
|
295
|
-
*/
|
|
296
|
-
static parseUpdateOptions(options: any): UpdateCliOptions {
|
|
297
|
-
const check = OptionUtils.parseCheckOptions(options)
|
|
298
|
-
const update: UpdateCliOptions = { ...check }
|
|
299
|
-
|
|
300
|
-
if (options.interactive !== undefined) {
|
|
301
|
-
update.interactive = OptionUtils.parseBoolean(options.interactive)
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (options.dryRun !== undefined) {
|
|
305
|
-
update.dryRun = OptionUtils.parseBoolean(options.dryRun)
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
if (options.force !== undefined) {
|
|
309
|
-
update.force = OptionUtils.parseBoolean(options.force)
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (options.createBackup !== undefined) {
|
|
313
|
-
update.createBackup = OptionUtils.parseBoolean(options.createBackup)
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
return update
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* Parse analyze command options
|
|
321
|
-
*/
|
|
322
|
-
static parseAnalyzeOptions(options: any): AnalyzeCliOptions {
|
|
323
|
-
const global = OptionUtils.parseGlobalOptions(options)
|
|
324
|
-
const analyze: AnalyzeCliOptions = { ...global }
|
|
325
|
-
|
|
326
|
-
if (options.format && typeof options.format === 'string') {
|
|
327
|
-
analyze.format = options.format as Exclude<AnalyzeCliOptions['format'], undefined>
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (options.ai !== undefined) {
|
|
331
|
-
analyze.ai = OptionUtils.parseBoolean(options.ai)
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
if (options.provider && typeof options.provider === 'string') {
|
|
335
|
-
analyze.provider = options.provider as Exclude<AnalyzeCliOptions['provider'], undefined>
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
if (options.analysisType && typeof options.analysisType === 'string') {
|
|
339
|
-
analyze.analysisType = options.analysisType as Exclude<
|
|
340
|
-
AnalyzeCliOptions['analysisType'],
|
|
341
|
-
undefined
|
|
342
|
-
>
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
if (options.skipCache !== undefined) {
|
|
346
|
-
analyze.skipCache = OptionUtils.parseBoolean(options.skipCache)
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return analyze
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Parse workspace command options
|
|
354
|
-
*/
|
|
355
|
-
static parseWorkspaceOptions(options: any): WorkspaceCliOptions {
|
|
356
|
-
const global = OptionUtils.parseGlobalOptions(options)
|
|
357
|
-
const workspace: WorkspaceCliOptions = { ...global }
|
|
358
|
-
|
|
359
|
-
if (options.validate !== undefined) {
|
|
360
|
-
workspace.validate = OptionUtils.parseBoolean(options.validate)
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
if (options.stats !== undefined) {
|
|
364
|
-
workspace.stats = OptionUtils.parseBoolean(options.stats)
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
if (options.info !== undefined) {
|
|
368
|
-
workspace.info = OptionUtils.parseBoolean(options.info)
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
if (options.format && typeof options.format === 'string') {
|
|
372
|
-
workspace.format = options.format as Exclude<WorkspaceCliOptions['format'], undefined>
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
return workspace
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* Generate help text for option group
|
|
380
|
-
*/
|
|
381
|
-
static generateHelpText(groupName: keyof typeof optionGroups): string {
|
|
382
|
-
const group = optionGroups[groupName]
|
|
383
|
-
if (!group) return ''
|
|
384
|
-
|
|
385
|
-
const lines = [`${group.title}:`]
|
|
386
|
-
|
|
387
|
-
for (const option of group.options) {
|
|
388
|
-
const flags = option.flags
|
|
389
|
-
const description = option.description || ''
|
|
390
|
-
const choices = option.argChoices ? ` (choices: ${option.argChoices.join(', ')})` : ''
|
|
391
|
-
const defaultValue = option.defaultValue ? ` (default: ${option.defaultValue})` : ''
|
|
392
|
-
|
|
393
|
-
lines.push(` ${flags.padEnd(30)} ${description}${choices}${defaultValue}`)
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
return lines.join('\n')
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* Validate option combinations
|
|
401
|
-
*/
|
|
402
|
-
static validateOptionCombinations(command: string, options: any): string[] {
|
|
403
|
-
const errors: string[] = []
|
|
404
|
-
|
|
405
|
-
switch (command) {
|
|
406
|
-
case 'update':
|
|
407
|
-
if (
|
|
408
|
-
OptionUtils.parseBoolean(options.interactive) &&
|
|
409
|
-
OptionUtils.parseBoolean(options.dryRun)
|
|
410
|
-
) {
|
|
411
|
-
errors.push('Cannot use --interactive with --dry-run')
|
|
412
|
-
}
|
|
413
|
-
break
|
|
414
|
-
|
|
415
|
-
case 'workspace': {
|
|
416
|
-
const actionCount = [options.validate, options.stats, options.info].filter((v) =>
|
|
417
|
-
OptionUtils.parseBoolean(v)
|
|
418
|
-
).length
|
|
419
|
-
if (actionCount > 1) {
|
|
420
|
-
errors.push('Cannot use multiple workspace actions simultaneously')
|
|
421
|
-
}
|
|
422
|
-
if (actionCount === 0) {
|
|
423
|
-
// Default to info
|
|
424
|
-
options.info = true
|
|
425
|
-
}
|
|
426
|
-
break
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
// Global validations
|
|
431
|
-
if (OptionUtils.parseBoolean(options.verbose) && OptionUtils.parseBoolean(options.silent)) {
|
|
432
|
-
errors.push('Cannot use both --verbose and --silent')
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
return errors
|
|
436
|
-
}
|
|
437
|
-
}
|