@flowscripter/dynamic-cli-framework 1.2.1 → 1.3.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.
- package/README/core-service-providers.md +2 -2
- package/README/development.md +3 -6
- package/README/implementation-details.md +17 -17
- package/README/key-concepts.md +17 -17
- package/README.md +4 -4
- package/bun.lock +0 -2
- package/index.ts +22 -30
- package/package.json +19 -19
- package/src/api/argument/Argument.ts +1 -1
- package/src/api/argument/ArgumentValueTypes.ts +3 -10
- package/src/api/argument/ComplexOption.ts +5 -9
- package/src/api/command/GlobalCommand.ts +1 -4
- package/src/api/service/core/ArgumentPrompterService.ts +1 -3
- package/src/api/service/core/AsciiBannerGeneratorService.ts +1 -4
- package/src/api/service/core/CompletionService.ts +2 -6
- package/src/api/service/core/ImagePrinterService.ts +1 -2
- package/src/api/service/core/KeyValueService.ts +1 -2
- package/src/api/service/core/PrettyPrinterService.ts +1 -4
- package/src/api/service/core/PrinterService.ts +8 -9
- package/src/api/service/core/PrompterService.ts +4 -11
- package/src/api/service/core/ShutdownService.ts +1 -2
- package/src/api/service/core/SyntaxHighlighterService.ts +1 -5
- package/src/api/service/core/Table.ts +7 -25
- package/src/api/service/core/TreePrinterService.ts +1 -2
- package/src/cli/BaseCLI.ts +17 -47
- package/src/cli/DefaultRuntimeCLI.ts +1 -4
- package/src/command/CompletionCommand.ts +19 -45
- package/src/command/MultiCommandCliHelpCommand.ts +45 -92
- package/src/command/SingleCommandCliHelpCommand.ts +17 -28
- package/src/command/UsageCommand.ts +6 -12
- package/src/command/VersionCommand.ts +2 -6
- package/src/launcher.ts +4 -2
- package/src/runtime/DefaultContext.ts +2 -5
- package/src/runtime/argument/ArgumentTypeGuards.ts +1 -3
- package/src/runtime/command/CommandTypeGuards.ts +5 -14
- package/src/runtime/command/CommandValidator.ts +56 -118
- package/src/runtime/parser.ts +13 -17
- package/src/runtime/registry/CommandRegistry.ts +2 -7
- package/src/runtime/registry/DefaultCommandRegistry.ts +32 -84
- package/src/runtime/registry/DefaultServiceProviderRegistry.ts +3 -9
- package/src/runtime/runner.ts +103 -142
- package/src/runtime/scanner.ts +28 -46
- package/src/runtime/values/ValuePopulationResult.ts +1 -2
- package/src/runtime/values/argumentValueMerge.ts +16 -28
- package/src/runtime/values/argumentValueValidation.ts +21 -67
- package/src/runtime/values/globalCommandValuePopulation.ts +9 -18
- package/src/runtime/values/subCommandValuePopulation.ts +42 -65
- package/src/service/argumentPrompter/ArgumentPrompterServiceProvider.ts +3 -10
- package/src/service/argumentPrompter/DefaultArgumentPrompterService.ts +22 -59
- package/src/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.ts +5 -14
- package/src/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.ts +59 -77
- package/src/service/banner/BannerServiceProvider.ts +13 -35
- package/src/service/banner/command/NoBannerCommand.ts +2 -8
- package/src/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.ts +5 -10
- package/src/service/completion/CompletionServiceProvider.ts +20 -48
- package/src/service/completion/DefaultCompletionService.ts +17 -56
- package/src/service/completion/shell/ShellHandler.ts +1 -3
- package/src/service/completion/shell/fish.ts +1 -1
- package/src/service/completion/shell/powershell.ts +2 -12
- package/src/service/completion/shell/zsh.ts +1 -1
- package/src/service/configuration/ConfigurationServiceProvider.ts +40 -133
- package/src/service/configuration/DefaultKeyValueService.ts +6 -20
- package/src/service/configuration/DefaultSecretService.ts +10 -14
- package/src/service/configuration/command/ConfigCommand.ts +1 -4
- package/src/service/configuration/command/DumpConfigCommand.ts +9 -21
- package/src/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.ts +5 -14
- package/src/service/dataDumpGenerator/DefaultDataDumpGeneratorService.ts +5 -12
- package/src/service/imagePrinter/DefaultImagePrinterService.ts +1 -5
- package/src/service/imagePrinter/ImagePrinterServiceProvider.ts +1 -4
- package/src/service/prettyPrinter/DefaultPrettyPrinterService.ts +4 -12
- package/src/service/prettyPrinter/PrettyPrinterServiceProvider.ts +3 -10
- package/src/service/printer/DefaultPrinterService.ts +20 -83
- package/src/service/printer/PrinterServiceProvider.ts +3 -11
- package/src/service/printer/command/DarkModeCommand.ts +3 -10
- package/src/service/printer/command/LogLevelCommand.ts +7 -26
- package/src/service/printer/command/NoColorCommand.ts +3 -10
- package/src/service/printer/command/NoHyperlinksCommand.ts +3 -10
- package/src/service/printer/terminal/Progress.ts +99 -90
- package/src/service/printer/terminal/Spinner.ts +7 -26
- package/src/service/prompter/DefaultPrompterService.ts +2 -6
- package/src/service/prompter/PrompterServiceProvider.ts +3 -11
- package/src/service/prompter/command/NoPromptCommand.ts +3 -10
- package/src/service/prompter/prompt/PromptContext.ts +5 -18
- package/src/service/prompter/prompt/promptMultiSelect.ts +6 -21
- package/src/service/prompter/prompt/promptOpenUrl.ts +7 -22
- package/src/service/prompter/prompt/promptSingleSelect.ts +6 -23
- package/src/service/prompter/prompt/promptText.ts +10 -27
- package/src/service/prompter/prompt/promptToggle.ts +8 -8
- package/src/service/shutdown/ShutdownServiceProvider.ts +3 -10
- package/src/service/syntaxHighlighter/DefaultSyntaxHighlighterService.ts +13 -26
- package/src/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.ts +8 -21
- package/src/service/tableGenerator/DefaultTableGeneratorService.ts +44 -68
- package/src/service/tableGenerator/TableGeneratorServiceProvider.ts +7 -16
- package/src/service/treePrinter/DefaultTreePrinterService.ts +2 -7
- package/src/service/treePrinter/TreePrinterServiceProvider.ts +4 -12
- package/src/terminal/ImageRenderer.ts +35 -54
- package/src/terminal/PngDecoder.ts +10 -19
- package/src/terminal/TtyStyler.ts +11 -9
- package/src/terminal/TtyTerminal.ts +2 -10
- package/src/terminal/supportsHyperlinks.ts +4 -10
- package/src/util/configHelper.ts +3 -10
- package/src/util/envVarHelper.ts +50 -88
- package/src/util/helpHelper.ts +123 -193
- package/src/util/logger.ts +12 -42
- package/src/util/runnerHelper.ts +20 -61
- package/tests/cli/BaseCLI.test.ts +23 -80
- package/tests/command/CompletionCommand.test.ts +1 -6
- package/tests/command/MultiCommandCliHelpCommand.test.ts +51 -205
- package/tests/command/SingleCommandCliHelpCommand.test.ts +21 -103
- package/tests/command/UsageCommand.test.ts +4 -10
- package/tests/fixtures/Command.ts +87 -68
- package/tests/fixtures/CommandRegistry.ts +1 -3
- package/tests/fixtures/Context.ts +3 -11
- package/tests/fixtures/ServiceProviderRegistry.ts +1 -1
- package/tests/fixtures/prettierPluginFoo.ts +1 -1
- package/tests/fixtures/util.ts +2 -8
- package/tests/runtime/argument/ArgumentTypeGuards.test.ts +1 -3
- package/tests/runtime/command/CommandValidator.test.ts +881 -604
- package/tests/runtime/parser.test.ts +222 -246
- package/tests/runtime/registry/DefaultCommandRegistry.test.ts +15 -37
- package/tests/runtime/registry/DefaultServiceProviderRegistry.test.ts +2 -8
- package/tests/runtime/runner.test.ts +231 -281
- package/tests/runtime/scanner.test.ts +277 -475
- package/tests/runtime/values/argumentValueMerge.test.ts +133 -81
- package/tests/runtime/values/argumentValueValidation.test.ts +444 -588
- package/tests/runtime/values/globalCommandValuePopulation.test.ts +71 -253
- package/tests/runtime/values/subCommandValuePopulation.test.ts +1342 -1570
- package/tests/service/argumentPrompter/ArgumentPrompterServiceProvider.test.ts +3 -12
- package/tests/service/argumentPrompter/DefaultArgumentPrompterService.test.ts +36 -45
- package/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.ts +2 -8
- package/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.ts +40 -62
- package/tests/service/banner/BannerServiceProvider.test.ts +5 -18
- package/tests/service/banner/command/NoBannerCommand.test.ts +1 -4
- package/tests/service/completion/CompletionServiceProvider.test.ts +145 -214
- package/tests/service/completion/DefaultCompletionService.test.ts +17 -79
- package/tests/service/completion/shell/fish.test.ts +1 -3
- package/tests/service/configuration/ConfigurationServiceProvider.test.ts +26 -75
- package/tests/service/configuration/DefaultKeyValueService.test.ts +9 -21
- package/tests/service/configuration/DefaultSecretService.test.ts +7 -15
- package/tests/service/configuration/command/DumpConfigCommand.test.ts +4 -13
- package/tests/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.test.ts +6 -12
- package/tests/service/dataDumpGenerator/DefaultDataDumpGeneratorService.test.ts +1 -10
- package/tests/service/imagePrinter/DefaultImagePrinterService.test.ts +5 -70
- package/tests/service/prettyPrinter/DefaultPrettyPrinterService.test.ts +4 -11
- package/tests/service/prettyPrinter/PrettyPrinterServiceProvider.test.ts +2 -6
- package/tests/service/printer/DefaultPrinterService.test.ts +57 -255
- package/tests/service/printer/PrinterServiceProvider.test.ts +2 -8
- package/tests/service/printer/command/DarkModeCommand.test.ts +4 -12
- package/tests/service/printer/command/LogLevelCommand.test.ts +4 -17
- package/tests/service/printer/command/NoColorCommand.test.ts +4 -12
- package/tests/service/printer/command/NoHyperlinksCommand.test.ts +7 -21
- package/tests/service/printer/terminal/Progress.test.ts +1 -3
- package/tests/service/printer/terminal/Spinner.test.ts +2 -8
- package/tests/service/prompter/DefaultPrompterService.test.ts +52 -69
- package/tests/service/prompter/PrompterServiceProvider.test.ts +2 -8
- package/tests/service/shutdown/ShutdownServiceProvider.test.ts +1 -3
- package/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.ts +13 -99
- package/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.ts +2 -7
- package/tests/service/tableGenerator/DefaultTableGeneratorService.test.ts +12 -33
- package/tests/service/tableGenerator/TableGeneratorServiceProvider.test.ts +2 -2
- package/tests/service/treePrinter/DefaultTreePrinterService.test.ts +4 -6
- package/tests/service/treePrinter/TreePrinterServiceProvider.test.ts +4 -8
- package/tests/terminal/ImageRenderer.test.ts +2 -11
- package/tests/terminal/PngDecoder.test.ts +2 -6
- package/tests/util/configHelper.test.ts +55 -137
- package/tests/util/envVarHelper.test.ts +46 -110
|
@@ -36,12 +36,8 @@ function doClone(
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function arrayMerge(
|
|
39
|
-
override:
|
|
40
|
-
|
|
41
|
-
| Array<PopulatedArgumentValues | undefined>,
|
|
42
|
-
base:
|
|
43
|
-
| Array<PopulatedArgumentSingleValueType>
|
|
44
|
-
| Array<PopulatedArgumentValues>,
|
|
39
|
+
override: Array<PopulatedArgumentSingleValueType> | Array<PopulatedArgumentValues | undefined>,
|
|
40
|
+
base: Array<PopulatedArgumentSingleValueType> | Array<PopulatedArgumentValues>,
|
|
45
41
|
nestingLevel: number,
|
|
46
42
|
): Array<PopulatedArgumentSingleValueType> | Array<PopulatedArgumentValues> {
|
|
47
43
|
if (override.length > MAXIMUM_ARGUMENT_ARRAY_SIZE) {
|
|
@@ -55,16 +51,13 @@ function arrayMerge(
|
|
|
55
51
|
override.forEach((argValue, index) => {
|
|
56
52
|
if (Array.isArray(argValue)) {
|
|
57
53
|
throw new Error(
|
|
58
|
-
`Array of array values discovered, this is not supported: ${
|
|
59
|
-
JSON.stringify(argValue)
|
|
60
|
-
}`,
|
|
54
|
+
`Array of array values discovered, this is not supported: ${JSON.stringify(argValue)}`,
|
|
61
55
|
);
|
|
62
56
|
}
|
|
63
57
|
if (index >= base.length) {
|
|
64
58
|
result.push(
|
|
65
|
-
doClone(argValue, nestingLevel) as
|
|
66
|
-
|
|
67
|
-
& PopulatedArgumentValues,
|
|
59
|
+
doClone(argValue, nestingLevel) as PopulatedArgumentSingleValueType &
|
|
60
|
+
PopulatedArgumentValues,
|
|
68
61
|
);
|
|
69
62
|
} else {
|
|
70
63
|
result[index] = doMerge(argValue, base[index], nestingLevel) as
|
|
@@ -81,9 +74,7 @@ function objectMerge(
|
|
|
81
74
|
nestingLevel: number,
|
|
82
75
|
): PopulatedArgumentValues {
|
|
83
76
|
if (nestingLevel > MAXIMUM_COMPLEX_OPTION_NESTING_DEPTH) {
|
|
84
|
-
throw new Error(
|
|
85
|
-
`Maximum complex option nesting depth exceeded: ${nestingLevel}`,
|
|
86
|
-
);
|
|
77
|
+
throw new Error(`Maximum complex option nesting depth exceeded: ${nestingLevel}`);
|
|
87
78
|
}
|
|
88
79
|
|
|
89
80
|
nestingLevel++;
|
|
@@ -120,15 +111,12 @@ function doMerge(
|
|
|
120
111
|
| PopulatedArgumentValueType
|
|
121
112
|
| Array<PopulatedArgumentValues | undefined>,
|
|
122
113
|
nestingLevel: number,
|
|
123
|
-
):
|
|
124
|
-
| PopulatedArgumentValues
|
|
125
|
-
| PopulatedArgumentValueType
|
|
126
|
-
| Array<PopulatedArgumentValues> {
|
|
114
|
+
): PopulatedArgumentValues | PopulatedArgumentValueType | Array<PopulatedArgumentValues> {
|
|
127
115
|
if (defaults === undefined) {
|
|
128
116
|
throw new Error(
|
|
129
|
-
`Undefined value provided in merge: override = ${
|
|
130
|
-
|
|
131
|
-
}, defaults = undefined`,
|
|
117
|
+
`Undefined value provided in merge: override = ${JSON.stringify(
|
|
118
|
+
override,
|
|
119
|
+
)}, defaults = undefined`,
|
|
132
120
|
);
|
|
133
121
|
}
|
|
134
122
|
if (typeof override !== typeof defaults) {
|
|
@@ -147,17 +135,17 @@ function doMerge(
|
|
|
147
135
|
}
|
|
148
136
|
} // check if we need to convert from single non-string value to single string value
|
|
149
137
|
else if (
|
|
150
|
-
|
|
151
|
-
(
|
|
138
|
+
typeof override === "string" &&
|
|
139
|
+
(typeof defaults == "number" || typeof defaults == "boolean")
|
|
152
140
|
) {
|
|
153
141
|
defaults = `${defaults}`;
|
|
154
142
|
}
|
|
155
143
|
}
|
|
156
|
-
if (override !== undefined &&
|
|
144
|
+
if (override !== undefined && typeof override !== typeof defaults) {
|
|
157
145
|
throw new Error(
|
|
158
|
-
`Incompatible value types provided in merge: override = ${
|
|
159
|
-
|
|
160
|
-
}, defaults = ${JSON.stringify(defaults)}`,
|
|
146
|
+
`Incompatible value types provided in merge: override = ${JSON.stringify(
|
|
147
|
+
override,
|
|
148
|
+
)}, defaults = ${JSON.stringify(defaults)}`,
|
|
161
149
|
);
|
|
162
150
|
}
|
|
163
151
|
|
|
@@ -61,7 +61,7 @@ function validatePrimitiveValue(
|
|
|
61
61
|
let castValue: string | undefined;
|
|
62
62
|
switch (argument.type) {
|
|
63
63
|
case ArgumentValueTypeName.BOOLEAN:
|
|
64
|
-
if (
|
|
64
|
+
if (value === true || value === false) {
|
|
65
65
|
convertedValue = value;
|
|
66
66
|
break;
|
|
67
67
|
}
|
|
@@ -116,14 +116,9 @@ function validatePrimitiveValue(
|
|
|
116
116
|
let searchValue = convertedValue;
|
|
117
117
|
let allowableValues = argument.allowableValues;
|
|
118
118
|
|
|
119
|
-
if (
|
|
120
|
-
(argument.type === ArgumentValueTypeName.STRING) &&
|
|
121
|
-
argument.isCaseInsensitive
|
|
122
|
-
) {
|
|
119
|
+
if (argument.type === ArgumentValueTypeName.STRING && argument.isCaseInsensitive) {
|
|
123
120
|
searchValue = (convertedValue as string).toLowerCase();
|
|
124
|
-
allowableValues = argument.allowableValues.map((v) =>
|
|
125
|
-
(v as string).toLowerCase()
|
|
126
|
-
);
|
|
121
|
+
allowableValues = argument.allowableValues.map((v) => (v as string).toLowerCase());
|
|
127
122
|
}
|
|
128
123
|
if (!allowableValues.includes(searchValue)) {
|
|
129
124
|
return {
|
|
@@ -164,12 +159,9 @@ function validatePrimitiveValue(
|
|
|
164
159
|
|
|
165
160
|
function validateArrayValue(
|
|
166
161
|
subCommandArgument: SubCommandArgument | ComplexOption,
|
|
167
|
-
arrayValue: Array<
|
|
168
|
-
PopulatedArgumentSingleValueType | PopulatedArgumentValues | undefined
|
|
169
|
-
>,
|
|
162
|
+
arrayValue: Array<PopulatedArgumentSingleValueType | PopulatedArgumentValues | undefined>,
|
|
170
163
|
): ArrayValueValidationResult {
|
|
171
|
-
const convertedArrayValue: Array<ArgumentSingleValueType | ArgumentValues> =
|
|
172
|
-
[];
|
|
164
|
+
const convertedArrayValue: Array<ArgumentSingleValueType | ArgumentValues> = [];
|
|
173
165
|
|
|
174
166
|
for (let i = 0; i < arrayValue.length; i += 1) {
|
|
175
167
|
const singleValue = arrayValue[i];
|
|
@@ -185,9 +177,7 @@ function validateArrayValue(
|
|
|
185
177
|
};
|
|
186
178
|
}
|
|
187
179
|
|
|
188
|
-
let validationResult:
|
|
189
|
-
| SingleValueValidationResult
|
|
190
|
-
| ObjectValueValidationResult;
|
|
180
|
+
let validationResult: SingleValueValidationResult | ObjectValueValidationResult;
|
|
191
181
|
|
|
192
182
|
if (Array.isArray(singleValue)) {
|
|
193
183
|
throw new Error(
|
|
@@ -205,10 +195,7 @@ function validateArrayValue(
|
|
|
205
195
|
},
|
|
206
196
|
};
|
|
207
197
|
}
|
|
208
|
-
validationResult = validateObjectValue(
|
|
209
|
-
subCommandArgument as ComplexOption,
|
|
210
|
-
singleValue,
|
|
211
|
-
);
|
|
198
|
+
validationResult = validateObjectValue(subCommandArgument as ComplexOption, singleValue);
|
|
212
199
|
} // if not array and not object, then must be primitive
|
|
213
200
|
else {
|
|
214
201
|
if (isComplexOption(subCommandArgument)) {
|
|
@@ -239,9 +226,7 @@ function validateArrayValue(
|
|
|
239
226
|
invalidArgument: {
|
|
240
227
|
argument: validationResult.invalidArgument.argument,
|
|
241
228
|
name: `[${i}]${
|
|
242
|
-
validationResult.invalidArgument.name
|
|
243
|
-
? validationResult.invalidArgument.name
|
|
244
|
-
: ""
|
|
229
|
+
validationResult.invalidArgument.name ? validationResult.invalidArgument.name : ""
|
|
245
230
|
}`,
|
|
246
231
|
value: validationResult.invalidArgument.value,
|
|
247
232
|
reason: validationResult.invalidArgument.reason,
|
|
@@ -253,9 +238,7 @@ function validateArrayValue(
|
|
|
253
238
|
invalidArgument: {
|
|
254
239
|
argument: validationResult.invalidArgument.argument,
|
|
255
240
|
name: `[${i}]${
|
|
256
|
-
validationResult.invalidArgument.name
|
|
257
|
-
? validationResult.invalidArgument.name
|
|
258
|
-
: ""
|
|
241
|
+
validationResult.invalidArgument.name ? validationResult.invalidArgument.name : ""
|
|
259
242
|
}`,
|
|
260
243
|
reason: validationResult.invalidArgument.reason,
|
|
261
244
|
},
|
|
@@ -339,10 +322,7 @@ function validateObjectValue(
|
|
|
339
322
|
},
|
|
340
323
|
};
|
|
341
324
|
}
|
|
342
|
-
validationResult = validatePrimitiveValue(
|
|
343
|
-
propertyArg as SubCommandArgument,
|
|
344
|
-
propertyValue,
|
|
345
|
-
);
|
|
325
|
+
validationResult = validatePrimitiveValue(propertyArg as SubCommandArgument, propertyValue);
|
|
346
326
|
}
|
|
347
327
|
if (validationResult.validValue !== undefined) {
|
|
348
328
|
convertedObjectValue[propertyArg.name] = validationResult.validValue as
|
|
@@ -358,9 +338,7 @@ function validateObjectValue(
|
|
|
358
338
|
invalidArgument: {
|
|
359
339
|
argument: validationResult.invalidArgument.argument,
|
|
360
340
|
name: `.${propertyArg.name}${
|
|
361
|
-
validationResult.invalidArgument.name
|
|
362
|
-
? validationResult.invalidArgument.name
|
|
363
|
-
: ""
|
|
341
|
+
validationResult.invalidArgument.name ? validationResult.invalidArgument.name : ""
|
|
364
342
|
}`,
|
|
365
343
|
value: validationResult.invalidArgument.value,
|
|
366
344
|
reason: validationResult.invalidArgument.reason,
|
|
@@ -372,9 +350,7 @@ function validateObjectValue(
|
|
|
372
350
|
invalidArgument: {
|
|
373
351
|
argument: validationResult.invalidArgument.argument,
|
|
374
352
|
name: `.${propertyArg.name}${
|
|
375
|
-
validationResult.invalidArgument.name
|
|
376
|
-
? validationResult.invalidArgument.name
|
|
377
|
-
: ""
|
|
353
|
+
validationResult.invalidArgument.name ? validationResult.invalidArgument.name : ""
|
|
378
354
|
}`,
|
|
379
355
|
reason: validationResult.invalidArgument.reason,
|
|
380
356
|
},
|
|
@@ -396,10 +372,7 @@ function doSubCommandArgumentValidation(
|
|
|
396
372
|
isArray: boolean,
|
|
397
373
|
isOptional: boolean,
|
|
398
374
|
invalidArguments: Array<InvalidArgument>,
|
|
399
|
-
):
|
|
400
|
-
| PopulatedArgumentValueType
|
|
401
|
-
| PopulatedArgumentValues
|
|
402
|
-
| Array<PopulatedArgumentValues> {
|
|
375
|
+
): PopulatedArgumentValueType | PopulatedArgumentValues | Array<PopulatedArgumentValues> {
|
|
403
376
|
// if there is a value, check if it is valid
|
|
404
377
|
if (value !== undefined) {
|
|
405
378
|
let validationResult;
|
|
@@ -436,10 +409,7 @@ function doSubCommandArgumentValidation(
|
|
|
436
409
|
});
|
|
437
410
|
return undefined;
|
|
438
411
|
}
|
|
439
|
-
validationResult = validatePrimitiveValue(
|
|
440
|
-
argument as SubCommandArgument,
|
|
441
|
-
value,
|
|
442
|
-
);
|
|
412
|
+
validationResult = validatePrimitiveValue(argument as SubCommandArgument, value);
|
|
443
413
|
}
|
|
444
414
|
|
|
445
415
|
if (validationResult.invalidArgument !== undefined) {
|
|
@@ -447,9 +417,7 @@ function doSubCommandArgumentValidation(
|
|
|
447
417
|
validationResult.invalidArgument = {
|
|
448
418
|
argument: validationResult.invalidArgument.argument,
|
|
449
419
|
name: `${argument.name}${
|
|
450
|
-
validationResult.invalidArgument.name
|
|
451
|
-
? validationResult.invalidArgument.name
|
|
452
|
-
: ""
|
|
420
|
+
validationResult.invalidArgument.name ? validationResult.invalidArgument.name : ""
|
|
453
421
|
}`,
|
|
454
422
|
value: validationResult.invalidArgument.value,
|
|
455
423
|
reason: validationResult.invalidArgument.reason,
|
|
@@ -458,9 +426,7 @@ function doSubCommandArgumentValidation(
|
|
|
458
426
|
validationResult.invalidArgument = {
|
|
459
427
|
argument: validationResult.invalidArgument.argument,
|
|
460
428
|
name: `${argument.name}${
|
|
461
|
-
validationResult.invalidArgument.name
|
|
462
|
-
? validationResult.invalidArgument.name
|
|
463
|
-
: ""
|
|
429
|
+
validationResult.invalidArgument.name ? validationResult.invalidArgument.name : ""
|
|
464
430
|
}`,
|
|
465
431
|
reason: validationResult.invalidArgument.reason,
|
|
466
432
|
};
|
|
@@ -473,10 +439,7 @@ function doSubCommandArgumentValidation(
|
|
|
473
439
|
}
|
|
474
440
|
if (argument.validate && validationResult.validValue !== undefined) {
|
|
475
441
|
const customError = argument.validate(
|
|
476
|
-
validationResult.validValue as
|
|
477
|
-
| ArgumentValueType
|
|
478
|
-
| ArgumentValues
|
|
479
|
-
| Array<ArgumentValues>,
|
|
442
|
+
validationResult.validValue as ArgumentValueType | ArgumentValues | Array<ArgumentValues>,
|
|
480
443
|
);
|
|
481
444
|
if (customError !== undefined) {
|
|
482
445
|
invalidArguments.push({
|
|
@@ -520,10 +483,7 @@ export function validateOptionValue(
|
|
|
520
483
|
| PopulatedArgumentValues
|
|
521
484
|
| Array<PopulatedArgumentValues | undefined>,
|
|
522
485
|
invalidArguments: Array<InvalidArgument>,
|
|
523
|
-
):
|
|
524
|
-
| PopulatedArgumentValueType
|
|
525
|
-
| PopulatedArgumentValues
|
|
526
|
-
| Array<PopulatedArgumentValues> {
|
|
486
|
+
): PopulatedArgumentValueType | PopulatedArgumentValues | Array<PopulatedArgumentValues> {
|
|
527
487
|
return doSubCommandArgumentValidation(
|
|
528
488
|
option,
|
|
529
489
|
value,
|
|
@@ -572,10 +532,7 @@ export function validateGlobalCommandArgumentValue(
|
|
|
572
532
|
|
|
573
533
|
// if there is a value, check if it is valid
|
|
574
534
|
if (value !== undefined) {
|
|
575
|
-
const validationResult = validatePrimitiveValue(
|
|
576
|
-
globalCommandArgument,
|
|
577
|
-
value,
|
|
578
|
-
);
|
|
535
|
+
const validationResult = validatePrimitiveValue(globalCommandArgument, value);
|
|
579
536
|
|
|
580
537
|
if (validationResult.invalidArgument) {
|
|
581
538
|
if (validationResult.invalidArgument.value !== undefined) {
|
|
@@ -595,10 +552,7 @@ export function validateGlobalCommandArgumentValue(
|
|
|
595
552
|
return undefined;
|
|
596
553
|
}
|
|
597
554
|
|
|
598
|
-
if (
|
|
599
|
-
globalCommandArgument.validate &&
|
|
600
|
-
validationResult.validValue !== undefined
|
|
601
|
-
) {
|
|
555
|
+
if (globalCommandArgument.validate && validationResult.validValue !== undefined) {
|
|
602
556
|
const customError = globalCommandArgument.validate(
|
|
603
557
|
validationResult.validValue as ArgumentValueType,
|
|
604
558
|
);
|
|
@@ -632,7 +586,7 @@ export function getInvalidArgumentString(
|
|
|
632
586
|
skipArgName: boolean,
|
|
633
587
|
): string {
|
|
634
588
|
let nameString = "";
|
|
635
|
-
if (!skipArgName &&
|
|
589
|
+
if (!skipArgName && invalidArgument.name !== undefined) {
|
|
636
590
|
nameString = invalidArgument.name;
|
|
637
591
|
}
|
|
638
592
|
let valueString = "";
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import type GlobalCommand from "../../api/command/GlobalCommand.ts";
|
|
2
2
|
import type { GlobalCommandValuePopulationResult } from "./ValuePopulationResult.ts";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
} from "../../api/argument/ArgumentValueTypes.ts";
|
|
6
|
-
import type {
|
|
7
|
-
PopulatedArgumentSingleValueType,
|
|
8
|
-
} from "../../api/argument/ArgumentValueTypes.ts";
|
|
3
|
+
import { ArgumentValueTypeName } from "../../api/argument/ArgumentValueTypes.ts";
|
|
4
|
+
import type { PopulatedArgumentSingleValueType } from "../../api/argument/ArgumentValueTypes.ts";
|
|
9
5
|
import getLogger from "../../util/logger.ts";
|
|
10
6
|
import { InvalidArgumentReason } from "../../api/RunResult.ts";
|
|
11
7
|
|
|
@@ -24,10 +20,9 @@ export default function populateGlobalCommandValue(
|
|
|
24
20
|
defaultValue: PopulatedArgumentSingleValueType,
|
|
25
21
|
): GlobalCommandValuePopulationResult {
|
|
26
22
|
logger.debug(() => {
|
|
27
|
-
const message =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}`;
|
|
23
|
+
const message = `Populating value for global command: '${globalCommand.name}' using potential args: ${potentialArgs.join(
|
|
24
|
+
" ",
|
|
25
|
+
)}`;
|
|
31
26
|
if (defaultValue !== undefined) {
|
|
32
27
|
return `${message} and configured value: '${defaultValue}'`;
|
|
33
28
|
}
|
|
@@ -51,10 +46,7 @@ export default function populateGlobalCommandValue(
|
|
|
51
46
|
if (argument.type === ArgumentValueTypeName.BOOLEAN) {
|
|
52
47
|
const firstPotentialArgLower = firstPotentialArg!.toLowerCase();
|
|
53
48
|
|
|
54
|
-
if (
|
|
55
|
-
(firstPotentialArgLower !== "true") &&
|
|
56
|
-
(firstPotentialArgLower !== "false")
|
|
57
|
-
) {
|
|
49
|
+
if (firstPotentialArgLower !== "true" && firstPotentialArgLower !== "false") {
|
|
58
50
|
// ...instead, use the fact that the argument is present as the value true
|
|
59
51
|
return {
|
|
60
52
|
populatedArgumentValue: "true",
|
|
@@ -67,9 +59,8 @@ export default function populateGlobalCommandValue(
|
|
|
67
59
|
unusedArgs = potentialArgs.slice(1);
|
|
68
60
|
} // check if argument type is boolean and therefore command being specified is an implicit value of true
|
|
69
61
|
else if (
|
|
70
|
-
|
|
71
|
-
(
|
|
72
|
-
(argument.defaultValue === false))
|
|
62
|
+
argument.type === ArgumentValueTypeName.BOOLEAN &&
|
|
63
|
+
(populatedArgumentValue === undefined || argument.defaultValue === false)
|
|
73
64
|
) {
|
|
74
65
|
return {
|
|
75
66
|
populatedArgumentValue: "true",
|
|
@@ -78,7 +69,7 @@ export default function populateGlobalCommandValue(
|
|
|
78
69
|
}
|
|
79
70
|
|
|
80
71
|
// check if there is no value and the global command argument is not optional
|
|
81
|
-
if (
|
|
72
|
+
if (populatedArgumentValue === undefined && !argument.isOptional) {
|
|
82
73
|
return {
|
|
83
74
|
populatedArgumentValue,
|
|
84
75
|
unusedArgs,
|
|
@@ -11,14 +11,9 @@ import getLogger from "../../util/logger.ts";
|
|
|
11
11
|
import argumentValueMerge from "./argumentValueMerge.ts";
|
|
12
12
|
import type { SubCommandValuePopulationResult } from "./ValuePopulationResult.ts";
|
|
13
13
|
import type ComplexOption from "../../api/argument/ComplexOption.ts";
|
|
14
|
-
import {
|
|
15
|
-
MAXIMUM_COMPLEX_OPTION_NESTING_DEPTH,
|
|
16
|
-
} from "../../api/argument/ComplexOption.ts";
|
|
14
|
+
import { MAXIMUM_COMPLEX_OPTION_NESTING_DEPTH } from "../../api/argument/ComplexOption.ts";
|
|
17
15
|
import { isComplexOption } from "../argument/ArgumentTypeGuards.ts";
|
|
18
|
-
import {
|
|
19
|
-
type InvalidArgument,
|
|
20
|
-
InvalidArgumentReason,
|
|
21
|
-
} from "../../api/RunResult.ts";
|
|
16
|
+
import { type InvalidArgument, InvalidArgumentReason } from "../../api/RunResult.ts";
|
|
22
17
|
import { MAXIMUM_ARGUMENT_ARRAY_SIZE } from "../../api/argument/SubCommandArgument.ts";
|
|
23
18
|
|
|
24
19
|
const logger = getLogger("subCommandValuePopulation");
|
|
@@ -150,10 +145,7 @@ class ParseContext {
|
|
|
150
145
|
this.currentOption = undefined;
|
|
151
146
|
|
|
152
147
|
// split up the path into elements
|
|
153
|
-
const complexPathElements = optionPath.split(
|
|
154
|
-
".",
|
|
155
|
-
MAXIMUM_COMPLEX_OPTION_NESTING_DEPTH + 1,
|
|
156
|
-
);
|
|
148
|
+
const complexPathElements = optionPath.split(".", MAXIMUM_COMPLEX_OPTION_NESTING_DEPTH + 1);
|
|
157
149
|
|
|
158
150
|
// check nesting depth
|
|
159
151
|
if (complexPathElements.length > MAXIMUM_COMPLEX_OPTION_NESTING_DEPTH) {
|
|
@@ -179,10 +171,9 @@ class ParseContext {
|
|
|
179
171
|
|
|
180
172
|
// look for array index
|
|
181
173
|
if (complexPathElement.endsWith("]")) {
|
|
182
|
-
[complexPathElement, arrayIndexString] = complexPathElement
|
|
183
|
-
0,
|
|
184
|
-
|
|
185
|
-
).split("[") as [string, string | undefined];
|
|
174
|
+
[complexPathElement, arrayIndexString] = complexPathElement
|
|
175
|
+
.slice(0, complexPathElement.length - 1)
|
|
176
|
+
.split("[") as [string, string | undefined];
|
|
186
177
|
}
|
|
187
178
|
|
|
188
179
|
let lookupPath = this.subCommand.name;
|
|
@@ -235,9 +226,10 @@ class ParseContext {
|
|
|
235
226
|
});
|
|
236
227
|
this.optionLookupMapsByPath.set(lookupPath, lookupMap);
|
|
237
228
|
}
|
|
238
|
-
option = this.optionLookupMapsByPath.get(lookupPath)!.get(
|
|
239
|
-
|
|
240
|
-
|
|
229
|
+
option = this.optionLookupMapsByPath.get(lookupPath)!.get(complexPathElement) as
|
|
230
|
+
| Option
|
|
231
|
+
| ComplexOption
|
|
232
|
+
| undefined;
|
|
241
233
|
|
|
242
234
|
// now we are parsing properties of complex options it is an error if we cannot match an option name or alias
|
|
243
235
|
if (option === undefined) {
|
|
@@ -272,7 +264,7 @@ class ParseContext {
|
|
|
272
264
|
}
|
|
273
265
|
|
|
274
266
|
// check for indexing when not allowed
|
|
275
|
-
if (!option.isArray &&
|
|
267
|
+
if (!option.isArray && arrayIndex !== undefined) {
|
|
276
268
|
this.invalidArgument = {
|
|
277
269
|
argument: option,
|
|
278
270
|
name: optionPath,
|
|
@@ -282,15 +274,10 @@ class ParseContext {
|
|
|
282
274
|
return false;
|
|
283
275
|
}
|
|
284
276
|
|
|
285
|
-
if (
|
|
286
|
-
(currentValue as PopulatedArgumentValues)[complexPathElement] ===
|
|
287
|
-
undefined
|
|
288
|
-
) {
|
|
277
|
+
if ((currentValue as PopulatedArgumentValues)[complexPathElement] === undefined) {
|
|
289
278
|
// ensure we have a placeholder value
|
|
290
279
|
if (option.isArray) {
|
|
291
|
-
currentValue =
|
|
292
|
-
(currentValue as PopulatedArgumentValues)[complexPathElement] =
|
|
293
|
-
[];
|
|
280
|
+
currentValue = (currentValue as PopulatedArgumentValues)[complexPathElement] = [];
|
|
294
281
|
|
|
295
282
|
if (isComplexOption(option)) {
|
|
296
283
|
// if we are retrieving a property by name only use the last entry in the array by default
|
|
@@ -302,9 +289,7 @@ class ParseContext {
|
|
|
302
289
|
currentValue = currentValue[index] = {};
|
|
303
290
|
}
|
|
304
291
|
} else if (isComplexOption(option)) {
|
|
305
|
-
currentValue =
|
|
306
|
-
(currentValue as PopulatedArgumentValues)[complexPathElement] =
|
|
307
|
-
{};
|
|
292
|
+
currentValue = (currentValue as PopulatedArgumentValues)[complexPathElement] = {};
|
|
308
293
|
}
|
|
309
294
|
} else {
|
|
310
295
|
currentValue = (currentValue as PopulatedArgumentValues)[
|
|
@@ -318,7 +303,7 @@ class ParseContext {
|
|
|
318
303
|
index = arrayIndex;
|
|
319
304
|
}
|
|
320
305
|
|
|
321
|
-
if (
|
|
306
|
+
if (currentValue[index] === undefined && isComplexOption(option)) {
|
|
322
307
|
// ensure we have a placeholder value
|
|
323
308
|
currentValue = currentValue[index] = {};
|
|
324
309
|
} else {
|
|
@@ -380,13 +365,11 @@ class ParseContext {
|
|
|
380
365
|
// if on last path element, set the value
|
|
381
366
|
if (i === optionPath.length - 1) {
|
|
382
367
|
if (typeof pathElement === "string") {
|
|
383
|
-
const currentValue =
|
|
384
|
-
(optionValue as PopulatedArgumentValues)[pathElement as string];
|
|
368
|
+
const currentValue = (optionValue as PopulatedArgumentValues)[pathElement as string];
|
|
385
369
|
|
|
386
370
|
// if we haven't populated the argument value before...
|
|
387
371
|
if (currentValue === undefined) {
|
|
388
|
-
(optionValue as PopulatedArgumentValues)[pathElement as string] =
|
|
389
|
-
value;
|
|
372
|
+
(optionValue as PopulatedArgumentValues)[pathElement as string] = value;
|
|
390
373
|
} // if we have already populated the argument value as an array...
|
|
391
374
|
else if (Array.isArray(currentValue)) {
|
|
392
375
|
if (currentValue.length === MAXIMUM_ARGUMENT_ARRAY_SIZE) {
|
|
@@ -399,9 +382,7 @@ class ParseContext {
|
|
|
399
382
|
return false;
|
|
400
383
|
}
|
|
401
384
|
// push the new value
|
|
402
|
-
(currentValue as Array<PopulatedArgumentSingleValueType>).push(
|
|
403
|
-
value,
|
|
404
|
-
);
|
|
385
|
+
(currentValue as Array<PopulatedArgumentSingleValueType>).push(value);
|
|
405
386
|
} // else the value to add would make an array where it is not allowed
|
|
406
387
|
else {
|
|
407
388
|
this.invalidArgument = {
|
|
@@ -414,9 +395,9 @@ class ParseContext {
|
|
|
414
395
|
}
|
|
415
396
|
} else {
|
|
416
397
|
// set the new value on the array
|
|
417
|
-
(optionValue as Array<
|
|
418
|
-
|
|
419
|
-
|
|
398
|
+
(optionValue as Array<PopulatedArgumentValueType | PopulatedArgumentValues>)[
|
|
399
|
+
pathElement as number
|
|
400
|
+
] = value;
|
|
420
401
|
}
|
|
421
402
|
} // otherwise continue to navigate the path
|
|
422
403
|
else {
|
|
@@ -429,16 +410,15 @@ class ParseContext {
|
|
|
429
410
|
| PopulatedArgumentValues
|
|
430
411
|
| PopulatedArgumentValueType;
|
|
431
412
|
} else {
|
|
432
|
-
optionValue =
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
| PopulatedArgumentValueType;
|
|
413
|
+
optionValue = (optionValue as PopulatedArgumentValues)[pathElement as string] as
|
|
414
|
+
| Array<PopulatedArgumentValues>
|
|
415
|
+
| PopulatedArgumentValues
|
|
416
|
+
| PopulatedArgumentValueType;
|
|
437
417
|
}
|
|
438
418
|
} else {
|
|
439
|
-
optionValue = (
|
|
440
|
-
PopulatedArgumentSingleValueType | PopulatedArgumentValues
|
|
441
|
-
|
|
419
|
+
optionValue = (
|
|
420
|
+
optionValue as Array<PopulatedArgumentSingleValueType | PopulatedArgumentValues>
|
|
421
|
+
)[pathElement as number];
|
|
442
422
|
}
|
|
443
423
|
}
|
|
444
424
|
}
|
|
@@ -459,8 +439,7 @@ class ParseContext {
|
|
|
459
439
|
* @param value the value to attempt to set.
|
|
460
440
|
*/
|
|
461
441
|
setPositionalValue(value: ArgumentSingleValueType): boolean {
|
|
462
|
-
const positional = this.subCommand
|
|
463
|
-
.positionals[this.currentPositionalIndex]!;
|
|
442
|
+
const positional = this.subCommand.positionals[this.currentPositionalIndex]!;
|
|
464
443
|
const currentValue = this.populatedArgumentValues[positional.name];
|
|
465
444
|
|
|
466
445
|
// if we haven't populated the argument value before...
|
|
@@ -483,7 +462,7 @@ class ParseContext {
|
|
|
483
462
|
return false;
|
|
484
463
|
}
|
|
485
464
|
this.populatedArgumentValues[positional.name] = [
|
|
486
|
-
...currentValue as Array<PopulatedArgumentSingleValueType
|
|
465
|
+
...(currentValue as Array<PopulatedArgumentSingleValueType>),
|
|
487
466
|
value,
|
|
488
467
|
] as Array<PopulatedArgumentSingleValueType>;
|
|
489
468
|
}
|
|
@@ -509,7 +488,8 @@ class ParseContext {
|
|
|
509
488
|
// assume the boolean value was implicitly `true` and treat
|
|
510
489
|
// the potential arg as a following option arg or positional value
|
|
511
490
|
if (
|
|
512
|
-
|
|
491
|
+
potentialArg !== "true" &&
|
|
492
|
+
potentialArg !== "false" &&
|
|
513
493
|
this.currentOption!.type === ArgumentValueTypeName.BOOLEAN
|
|
514
494
|
) {
|
|
515
495
|
// Set the value to implicit value of true and return ony error.
|
|
@@ -536,8 +516,11 @@ class ParseContext {
|
|
|
536
516
|
|
|
537
517
|
// check for option AND value
|
|
538
518
|
if (potentialOptionPath.includes("=")) {
|
|
539
|
-
[potentialOptionPath, potentialOptionValue] = potentialOptionPath
|
|
540
|
-
|
|
519
|
+
[potentialOptionPath, potentialOptionValue] = potentialOptionPath.split(/=(.*)/) as [
|
|
520
|
+
string,
|
|
521
|
+
string | undefined,
|
|
522
|
+
...string[],
|
|
523
|
+
];
|
|
541
524
|
|
|
542
525
|
// check for illegal syntax e.g. --optionName=
|
|
543
526
|
if (potentialOptionValue === "") {
|
|
@@ -608,14 +591,11 @@ export default function populateSubCommandValues(
|
|
|
608
591
|
defaultValues: PopulatedArgumentValues | undefined,
|
|
609
592
|
): SubCommandValuePopulationResult {
|
|
610
593
|
logger.debug(() => {
|
|
611
|
-
const message =
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
}`;
|
|
594
|
+
const message = `Populating values for sub-command: '${subCommand.name}' using potential args: ${potentialArgs.join(
|
|
595
|
+
" ",
|
|
596
|
+
)}`;
|
|
615
597
|
if (defaultValues !== undefined) {
|
|
616
|
-
return `${message} and configured values: ${
|
|
617
|
-
JSON.stringify(defaultValues)
|
|
618
|
-
}`;
|
|
598
|
+
return `${message} and configured values: ${JSON.stringify(defaultValues)}`;
|
|
619
599
|
}
|
|
620
600
|
return message;
|
|
621
601
|
});
|
|
@@ -668,10 +648,7 @@ export default function populateSubCommandValues(
|
|
|
668
648
|
// merge the configured values with the parsed values
|
|
669
649
|
let populatedArgumentValues = parseContext.populatedArgumentValues;
|
|
670
650
|
if (defaultValues) {
|
|
671
|
-
populatedArgumentValues = argumentValueMerge(
|
|
672
|
-
populatedArgumentValues,
|
|
673
|
-
defaultValues,
|
|
674
|
-
);
|
|
651
|
+
populatedArgumentValues = argumentValueMerge(populatedArgumentValues, defaultValues);
|
|
675
652
|
}
|
|
676
653
|
|
|
677
654
|
return {
|
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
import type Context from "../../api/Context.ts";
|
|
2
|
-
import type {
|
|
3
|
-
ServiceInfo,
|
|
4
|
-
ServiceProvider,
|
|
5
|
-
} from "../../api/service/ServiceProvider.ts";
|
|
2
|
+
import type { ServiceInfo, ServiceProvider } from "../../api/service/ServiceProvider.ts";
|
|
6
3
|
import type ArgumentPrompterService from "../../api/service/core/ArgumentPrompterService.ts";
|
|
7
4
|
import { ARGUMENT_PROMPTER_SERVICE_ID } from "../../api/service/core/ArgumentPrompterService.ts";
|
|
8
5
|
import type CLIConfig from "../../api/CLIConfig.ts";
|
|
9
6
|
|
|
10
|
-
export default class ArgumentPrompterServiceProvider
|
|
11
|
-
implements ServiceProvider {
|
|
7
|
+
export default class ArgumentPrompterServiceProvider implements ServiceProvider {
|
|
12
8
|
readonly serviceId: string = ARGUMENT_PROMPTER_SERVICE_ID;
|
|
13
9
|
readonly servicePriority: number;
|
|
14
10
|
readonly argumentPrompterService: ArgumentPrompterService;
|
|
15
11
|
|
|
16
|
-
public constructor(
|
|
17
|
-
servicePriority: number,
|
|
18
|
-
argumentPrompterService: ArgumentPrompterService,
|
|
19
|
-
) {
|
|
12
|
+
public constructor(servicePriority: number, argumentPrompterService: ArgumentPrompterService) {
|
|
20
13
|
this.servicePriority = servicePriority;
|
|
21
14
|
this.argumentPrompterService = argumentPrompterService;
|
|
22
15
|
}
|