@flowscripter/dynamic-cli-framework 11.0.0 → 11.1.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/dist/src/cli/BaseCLI.d.ts.map +1 -1
- package/dist/src/cli/BaseCLI.js +6 -2
- package/dist/src/runtime/DefaultContext.d.ts +2 -1
- package/dist/src/runtime/DefaultContext.d.ts.map +1 -1
- package/dist/src/runtime/DefaultContext.js +3 -1
- package/dist/src/runtime/command/CommandValidator.d.ts.map +1 -1
- package/dist/src/runtime/command/CommandValidator.js +18 -6
- package/dist/src/runtime/parser.d.ts.map +1 -1
- package/dist/src/runtime/parser.js +13 -4
- package/dist/src/runtime/values/argumentValueValidation.d.ts +26 -4
- package/dist/src/runtime/values/argumentValueValidation.d.ts.map +1 -1
- package/dist/src/runtime/values/argumentValueValidation.js +53 -50
- package/dist/src/service/argumentPrompter/DefaultArgumentPrompterService.d.ts +4 -0
- package/dist/src/service/argumentPrompter/DefaultArgumentPrompterService.d.ts.map +1 -1
- package/dist/src/service/argumentPrompter/DefaultArgumentPrompterService.js +53 -21
- package/dist/src/service/configuration/KeyValueServiceProvider.d.ts.map +1 -1
- package/dist/src/service/configuration/KeyValueServiceProvider.js +1 -0
- package/package.json +2 -2
- package/src/cli/BaseCLI.ts +6 -2
- package/src/runtime/DefaultContext.ts +4 -1
- package/src/runtime/command/CommandValidator.ts +35 -5
- package/src/runtime/parser.ts +14 -0
- package/src/runtime/values/argumentValueValidation.ts +82 -50
- package/src/service/argumentPrompter/DefaultArgumentPrompterService.ts +92 -26
- package/src/service/configuration/KeyValueServiceProvider.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseCLI.d.ts","sourceRoot":"","sources":["../../../src/cli/BaseCLI.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,yCAAyC,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAGvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAU3E,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AAGpD,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAC;AAChD,OAAO,KAAK,SAAS,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,qBAAqB,MAAM,4BAA4B,CAAC;AAqCpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,CAAC,OAAO,OAAO,OAAQ,YAAW,GAAG;;IAazC,YACE,SAAS,EAAE,SAAS,EACpB,oBAAoB,EAAE,cAAc,EACpC,oBAAoB,EAAE,cAAc,EACpC,aAAa,EAAE,OAAO,EACtB,aAAa,EAAE,OAAO,EACtB,cAAc,EAAE,QAAQ,EACxB,cAAc,EAAE,QAAQ,EACxB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,OAAO,CAAC,EAAE,qBAAqB,
|
|
1
|
+
{"version":3,"file":"BaseCLI.d.ts","sourceRoot":"","sources":["../../../src/cli/BaseCLI.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,yCAAyC,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAGvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAU3E,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AAGpD,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAC;AAChD,OAAO,KAAK,SAAS,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,qBAAqB,MAAM,4BAA4B,CAAC;AAqCpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,CAAC,OAAO,OAAO,OAAQ,YAAW,GAAG;;IAazC,YACE,SAAS,EAAE,SAAS,EACpB,oBAAoB,EAAE,cAAc,EACpC,oBAAoB,EAAE,cAAc,EACpC,aAAa,EAAE,OAAO,EACtB,aAAa,EAAE,OAAO,EACtB,cAAc,EAAE,QAAQ,EACxB,cAAc,EAAE,QAAQ,EACxB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,OAAO,CAAC,EAAE,qBAAqB,EAuEhC;IAED;;;;;;;OAOG;IACI,kBAAkB,CAAC,eAAe,EAAE,eAAe,QAEzD;IAED;;;;;;;;OAQG;IACH;;;;;OAKG;IACI,cAAc,CAAC,IAAI,EAAE,WAAW,QAEtC;IAEM,UAAU,CAAC,OAAO,EAAE,OAAO,QAQjC;IAEK,GAAG,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAqQzD;CACF"}
|
package/dist/src/cli/BaseCLI.js
CHANGED
|
@@ -130,7 +130,11 @@ export default class BaseCLI {
|
|
|
130
130
|
// create a command registry
|
|
131
131
|
this.#commandRegistry = new DefaultCommandRegistry([], commandValidator);
|
|
132
132
|
// create a context
|
|
133
|
-
this.#context = new DefaultContext(this.#cliConfig
|
|
133
|
+
this.#context = new DefaultContext(this.#cliConfig, {
|
|
134
|
+
stdin: keyReader !== undefined,
|
|
135
|
+
stdout: stdoutTerminal.isTty(),
|
|
136
|
+
stderr: stderrTerminal.isTty(),
|
|
137
|
+
});
|
|
134
138
|
this.#startupServiceProvider = new StartupServiceProvider(STARTUP_SERVICE_PRIORITY);
|
|
135
139
|
this.#stdoutTerminal = stdoutTerminal;
|
|
136
140
|
this.#printerService = new DefaultPrinterService(stdoutWritableStream, stderrWritableStream, stdoutIsColor, stderrIsColor, stdoutTerminal, stderrTerminal, styler);
|
|
@@ -187,7 +191,7 @@ export default class BaseCLI {
|
|
|
187
191
|
this.addServiceProvider(this.#startupServiceProvider);
|
|
188
192
|
this.addServiceProvider(new PrinterServiceProvider(PRINTER_SERVICE_PRIORITY, this.#printerService));
|
|
189
193
|
this.addServiceProvider(new TableGeneratorServiceProvider(TABLE_GENERATOR_SERVICE_PRIORITY));
|
|
190
|
-
const canPrompt = this.#
|
|
194
|
+
const canPrompt = this.#context.isTty.stdin && this.#context.isTty.stderr;
|
|
191
195
|
if (this.#options.promptingEnabled && !canPrompt) {
|
|
192
196
|
throw new Error("promptingEnabled requires a keyReader and a TTY stderr terminal");
|
|
193
197
|
}
|
|
@@ -6,7 +6,8 @@ import type { CLIConfig } from "@flowscripter/dynamic-cli-framework-api";
|
|
|
6
6
|
export default class DefaultContext implements Context {
|
|
7
7
|
#private;
|
|
8
8
|
readonly cliConfig: CLIConfig;
|
|
9
|
-
|
|
9
|
+
readonly isTty: Context["isTty"];
|
|
10
|
+
constructor(cliConfig: CLIConfig, isTty?: Context["isTty"]);
|
|
10
11
|
addServiceInstance(id: string, serviceInstance: unknown): void;
|
|
11
12
|
getServiceById(id: string): unknown;
|
|
12
13
|
doesServiceExist(id: string): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultContext.d.ts","sourceRoot":"","sources":["../../../src/runtime/DefaultContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,cAAe,YAAW,OAAO;;
|
|
1
|
+
{"version":3,"file":"DefaultContext.d.ts","sourceRoot":"","sources":["../../../src/runtime/DefaultContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,cAAe,YAAW,OAAO;;IAIlD,QAAQ,CAAC,SAAS,EAAE,SAAS;IAC7B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC;IAFlC,YACW,SAAS,EAAE,SAAS,EACpB,KAAK,GAAE,OAAO,CAAC,OAAO,CAAkD,EAC/E;IAEG,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,QAK7D;IAEM,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAKzC;IAEM,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE3C;CACF"}
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export default class DefaultContext {
|
|
5
5
|
cliConfig;
|
|
6
|
+
isTty;
|
|
6
7
|
#serviceInstancesById = new Map();
|
|
7
|
-
constructor(cliConfig) {
|
|
8
|
+
constructor(cliConfig, isTty = { stdin: false, stdout: false, stderr: false }) {
|
|
8
9
|
this.cliConfig = cliConfig;
|
|
10
|
+
this.isTty = isTty;
|
|
9
11
|
}
|
|
10
12
|
addServiceInstance(id, serviceInstance) {
|
|
11
13
|
if (this.#serviceInstancesById.has(id)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommandValidator.d.ts","sourceRoot":"","sources":["../../../../src/runtime/command/CommandValidator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"CommandValidator.d.ts","sourceRoot":"","sources":["../../../../src/runtime/command/CommandValidator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAmBvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmJzE,MAAM,CAAC,OAAO,OAAO,gBAAgB;;IAKnC,YAAmB,SAAS,EAAE,SAAS,EAEtC;IAED;;;;;;OAMG;IACI,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAUtC;CAkYF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isGroupCommand, isSubCommand } from "./CommandTypeGuards.js";
|
|
2
2
|
import { ValueTypeName, ComplexValueTypeName } from "@flowscripter/dynamic-cli-framework-api";
|
|
3
3
|
import { isComplexOption } from "../argument/ArgumentTypeGuards.js";
|
|
4
|
-
import { getInvalidArgumentString, validateGlobalCommandArgumentValue, validateOptionValue, } from "../values/argumentValueValidation.js";
|
|
4
|
+
import { getInvalidArgumentString, validateGlobalCommandArgumentValue, validateOptionValue, runCustomValidation, } from "../values/argumentValueValidation.js";
|
|
5
5
|
import getLogger from "../../util/logger.js";
|
|
6
6
|
import { getGlobalCommandArgumentConfigurationKey, getSubCommandArgumentConfigurationKey, } from "../../util/configHelper.js";
|
|
7
7
|
const logger = getLogger("commandValidation");
|
|
@@ -145,7 +145,11 @@ export default class CommandValidator {
|
|
|
145
145
|
validateArgument(argument, globalCommand.name);
|
|
146
146
|
if (argument.defaultValue) {
|
|
147
147
|
const invalidArguments = [];
|
|
148
|
-
|
|
148
|
+
const deferred = [];
|
|
149
|
+
validateGlobalCommandArgumentValue(globalCommand, argument.defaultValue, invalidArguments, deferred);
|
|
150
|
+
if (invalidArguments.length === 0) {
|
|
151
|
+
runCustomValidation(deferred, globalCommand, argument.defaultValue, invalidArguments);
|
|
152
|
+
}
|
|
149
153
|
if (invalidArguments.length > 0) {
|
|
150
154
|
throw new Error(`Illegal default value for global command: '${globalCommand.name}' => ${invalidArguments
|
|
151
155
|
.map((invalidArgument) => getInvalidArgumentString(invalidArgument, true))
|
|
@@ -303,18 +307,22 @@ export default class CommandValidator {
|
|
|
303
307
|
]);
|
|
304
308
|
}
|
|
305
309
|
else {
|
|
306
|
-
this.#validateOption(option, currentOptionPaths, allOptionPaths);
|
|
310
|
+
this.#validateOption(subCommand, option, currentOptionPaths, allOptionPaths);
|
|
307
311
|
this.#validateSubCommandArgumentConfigurationKey(subCommand, [...argumentAncestry, option]);
|
|
308
312
|
}
|
|
309
313
|
}
|
|
310
|
-
#validateOption(option, currentOptionPaths, allOptionPaths) {
|
|
314
|
+
#validateOption(subCommand, option, currentOptionPaths, allOptionPaths) {
|
|
311
315
|
validateSubCommandArgument(option);
|
|
312
316
|
if (Array.isArray(option.defaultValue) && !option.isArray) {
|
|
313
317
|
throw new Error(`Illegal array default value: '${option.defaultValue.join(",")}' for non-array option: '${option.name}'`);
|
|
314
318
|
}
|
|
315
319
|
if (option.defaultValue) {
|
|
316
320
|
const invalidArguments = [];
|
|
317
|
-
|
|
321
|
+
const deferred = [];
|
|
322
|
+
validateOptionValue(option, option.defaultValue, invalidArguments, deferred);
|
|
323
|
+
if (invalidArguments.length === 0) {
|
|
324
|
+
runCustomValidation(deferred, subCommand, { [option.name]: option.defaultValue }, invalidArguments);
|
|
325
|
+
}
|
|
318
326
|
if (invalidArguments.length > 0) {
|
|
319
327
|
throw new Error(`Illegal default value for option: '${option.name}' => ${invalidArguments
|
|
320
328
|
.map((invalidArgument) => getInvalidArgumentString(invalidArgument, true))
|
|
@@ -350,7 +358,11 @@ export default class CommandValidator {
|
|
|
350
358
|
}
|
|
351
359
|
if (complexOption.defaultValue) {
|
|
352
360
|
const invalidArguments = [];
|
|
353
|
-
|
|
361
|
+
const deferred = [];
|
|
362
|
+
validateOptionValue(complexOption, complexOption.defaultValue, invalidArguments, deferred);
|
|
363
|
+
if (invalidArguments.length === 0) {
|
|
364
|
+
runCustomValidation(deferred, subCommand, { [complexOption.name]: complexOption.defaultValue }, invalidArguments);
|
|
365
|
+
}
|
|
354
366
|
if (invalidArguments.length > 0) {
|
|
355
367
|
throw new Error(`Illegal default value for option: '${complexOption.name}' => ${invalidArguments
|
|
356
368
|
.map((invalidArgument) => getInvalidArgumentString(invalidArgument, true))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/runtime/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,wBAAwB,EACxB,eAAe,EAChB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/runtime/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,wBAAwB,EACxB,eAAe,EAChB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAiBlD,YAAY,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAE3E;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,WAAW,GAAG;IACjD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACtD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,aAAa,EAC5B,aAAa,CAAC,EAAE,eAAe,GAC9B,sBAAsB,CAwFxB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,aAAa,EAC5B,YAAY,CAAC,EAAE,wBAAwB,GACtC,sBAAsB,CA6DxB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import populateGlobalCommandValue from "./values/globalCommandValuePopulation.js";
|
|
2
|
-
import { validateGlobalCommandArgumentValue, validateOptionValue, validatePositionalValue, } from "./values/argumentValueValidation.js";
|
|
2
|
+
import { validateGlobalCommandArgumentValue, validateOptionValue, validatePositionalValue, runCustomValidation, } from "./values/argumentValueValidation.js";
|
|
3
3
|
import getLogger from "../util/logger.js";
|
|
4
4
|
import { redactGlobalCommandValue, redactSubCommandValues } from "../util/secretRedaction.js";
|
|
5
5
|
import populateSubCommandValues from "./values/subCommandValuePopulation.js";
|
|
@@ -30,9 +30,10 @@ export function parseSubCommandClause(commandClause, defaultValues) {
|
|
|
30
30
|
invalidArguments.push(invalidArgument);
|
|
31
31
|
}
|
|
32
32
|
if (invalidArguments.length === 0) {
|
|
33
|
+
const deferred = [];
|
|
33
34
|
// validate the option values
|
|
34
35
|
command.options.forEach((option) => {
|
|
35
|
-
const validatedValue = validateOptionValue(option, populatedArgumentValues[option.name] || option.defaultValue, invalidArguments);
|
|
36
|
+
const validatedValue = validateOptionValue(option, populatedArgumentValues[option.name] || option.defaultValue, invalidArguments, deferred);
|
|
36
37
|
if (validatedValue !== undefined) {
|
|
37
38
|
populatedArgumentValues[option.name] = validatedValue;
|
|
38
39
|
}
|
|
@@ -41,11 +42,15 @@ export function parseSubCommandClause(commandClause, defaultValues) {
|
|
|
41
42
|
if (invalidArguments.length === 0) {
|
|
42
43
|
// validate the positional values
|
|
43
44
|
command.positionals.forEach((positional) => {
|
|
44
|
-
const validatedValue = validatePositionalValue(positional, populatedArgumentValues[positional.name], invalidArguments);
|
|
45
|
+
const validatedValue = validatePositionalValue(positional, populatedArgumentValues[positional.name], invalidArguments, deferred);
|
|
45
46
|
if (validatedValue !== undefined) {
|
|
46
47
|
populatedArgumentValues[positional.name] = validatedValue;
|
|
47
48
|
}
|
|
48
49
|
});
|
|
50
|
+
if (invalidArguments.length === 0) {
|
|
51
|
+
// custom validators run once all built-in validation has passed and see all values
|
|
52
|
+
runCustomValidation(deferred, command, populatedArgumentValues, invalidArguments);
|
|
53
|
+
}
|
|
49
54
|
logger.debug("Command arguments after positionals validated: %O with invalid args: %O", redactSubCommandValues(command, populatedArgumentValues), invalidArguments);
|
|
50
55
|
}
|
|
51
56
|
}
|
|
@@ -94,10 +99,14 @@ export function parseGlobalCommandClause(commandClause, defaultValue) {
|
|
|
94
99
|
logger.debug("Command arguments for command: %s after value population: %O with invalid args: %O and unused args: %O", command.name, redactGlobalCommandValue(command, populatedArgumentValue), invalidArguments, unusedArgs);
|
|
95
100
|
// don't validate the value if the argument is already invalid
|
|
96
101
|
if (invalidArguments.length === 0) {
|
|
97
|
-
const
|
|
102
|
+
const deferred = [];
|
|
103
|
+
const validatedValue = validateGlobalCommandArgumentValue(command, populatedArgumentValue, invalidArguments, deferred);
|
|
98
104
|
if (validatedValue !== undefined) {
|
|
99
105
|
populatedArgumentValue = validatedValue;
|
|
100
106
|
}
|
|
107
|
+
if (invalidArguments.length === 0) {
|
|
108
|
+
runCustomValidation(deferred, command, populatedArgumentValue, invalidArguments);
|
|
109
|
+
}
|
|
101
110
|
}
|
|
102
111
|
logger.debug("Command arguments for command: %s after value validation: %O with invalid args: %O", command.name, redactGlobalCommandValue(command, populatedArgumentValue), invalidArguments);
|
|
103
112
|
return {
|
|
@@ -1,25 +1,46 @@
|
|
|
1
|
-
import type { PopulatedSingleValueType, PopulatedValues, PopulatedValueType } from "@flowscripter/dynamic-cli-framework-api";
|
|
1
|
+
import type { SingleValueType, Values, PopulatedSingleValueType, PopulatedValues, PopulatedValueType } from "@flowscripter/dynamic-cli-framework-api";
|
|
2
2
|
import type { Positional } from "@flowscripter/dynamic-cli-framework-api";
|
|
3
3
|
import type { Option } from "@flowscripter/dynamic-cli-framework-api";
|
|
4
4
|
import type { ComplexOption } from "@flowscripter/dynamic-cli-framework-api";
|
|
5
5
|
import type { InvalidArgument } from "@flowscripter/dynamic-cli-framework-api";
|
|
6
|
+
import type { Argument } from "@flowscripter/dynamic-cli-framework-api";
|
|
6
7
|
import type { GlobalCommand } from "@flowscripter/dynamic-cli-framework-api";
|
|
8
|
+
import type { Command } from "@flowscripter/dynamic-cli-framework-api";
|
|
9
|
+
/**
|
|
10
|
+
* A custom validation to be invoked once all built-in validation has passed.
|
|
11
|
+
*/
|
|
12
|
+
export interface DeferredCustomValidation {
|
|
13
|
+
readonly argument: Argument | ComplexOption;
|
|
14
|
+
readonly path: string;
|
|
15
|
+
readonly value: SingleValueType | Values | Array<SingleValueType | Values>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Invokes the recorded custom validations in order, stopping at the first failure.
|
|
19
|
+
*
|
|
20
|
+
* @param deferred the validations recorded while validating the values of the command.
|
|
21
|
+
* @param command the {@link Command} the validated values belong to.
|
|
22
|
+
* @param values all validated and converted values of the command.
|
|
23
|
+
* @param invalidArguments an array of {@link InvalidArgument} which is added to if a custom validation fails.
|
|
24
|
+
*/
|
|
25
|
+
export declare function runCustomValidation(deferred: ReadonlyArray<DeferredCustomValidation>, command: Command, values: PopulatedValues | PopulatedSingleValueType, invalidArguments: Array<InvalidArgument>): void;
|
|
7
26
|
/**
|
|
8
27
|
* Validates the provided value against the provided {@link Option}.
|
|
9
28
|
*
|
|
10
29
|
* @param option the {@link Option} to validate against.
|
|
11
30
|
* @param value the value (if any) for the {@link Option}.
|
|
12
31
|
* @param invalidArguments an array of {@link InvalidArgument} which may be added to if the provided value is invalid.
|
|
32
|
+
* @param deferred if provided, custom validations are recorded here for later invocation by {@link runCustomValidation}. If omitted, custom validations are not invoked.
|
|
13
33
|
*/
|
|
14
|
-
export declare function validateOptionValue(option: Option | ComplexOption, value: PopulatedValueType | PopulatedValues | Array<PopulatedValues | undefined>, invalidArguments: Array<InvalidArgument>): PopulatedValueType | PopulatedValues | Array<PopulatedValues>;
|
|
34
|
+
export declare function validateOptionValue(option: Option | ComplexOption, value: PopulatedValueType | PopulatedValues | Array<PopulatedValues | undefined>, invalidArguments: Array<InvalidArgument>, deferred?: Array<DeferredCustomValidation>): PopulatedValueType | PopulatedValues | Array<PopulatedValues>;
|
|
15
35
|
/**
|
|
16
36
|
* Validates the provided value against the provided {@link Positional}.
|
|
17
37
|
*
|
|
18
38
|
* @param positional the {@link Positional} to validate against.
|
|
19
39
|
* @param value the value (if any) for the {@link Positional}.
|
|
20
40
|
* @param invalidArguments an array of {@link InvalidArgument} which may be added to if the provided value is invalid.
|
|
41
|
+
* @param deferred if provided, custom validations are recorded here for later invocation by {@link runCustomValidation}. If omitted, custom validations are not invoked.
|
|
21
42
|
*/
|
|
22
|
-
export declare function validatePositionalValue(positional: Positional, value: PopulatedValueType, invalidArguments: Array<InvalidArgument>): PopulatedValueType;
|
|
43
|
+
export declare function validatePositionalValue(positional: Positional, value: PopulatedValueType, invalidArguments: Array<InvalidArgument>, deferred?: Array<DeferredCustomValidation>): PopulatedValueType;
|
|
23
44
|
/**
|
|
24
45
|
* Validates the provided value against the {@link GlobalCommandArgument} provided by the {@link GlobalCommand} and returns the validated
|
|
25
46
|
* value or undefined if the value was invalid.
|
|
@@ -27,7 +48,8 @@ export declare function validatePositionalValue(positional: Positional, value: P
|
|
|
27
48
|
* @param globalCommand the {@link GlobalCommand} providing the {@link GlobalCommandArgument}.
|
|
28
49
|
* @param value the value (if any) for the {@link GlobalCommandArgument}.
|
|
29
50
|
* @param invalidArguments an array of {@link InvalidArgument} which may be added to if the provided value is invalid.
|
|
51
|
+
* @param deferred if provided, custom validations are recorded here for later invocation by {@link runCustomValidation}. If omitted, custom validations are not invoked.
|
|
30
52
|
*/
|
|
31
|
-
export declare function validateGlobalCommandArgumentValue(globalCommand: GlobalCommand, value: PopulatedSingleValueType, invalidArguments: Array<InvalidArgument>): PopulatedSingleValueType;
|
|
53
|
+
export declare function validateGlobalCommandArgumentValue(globalCommand: GlobalCommand, value: PopulatedSingleValueType, invalidArguments: Array<InvalidArgument>, deferred?: Array<DeferredCustomValidation>): PopulatedSingleValueType;
|
|
32
54
|
export declare function getInvalidArgumentString(invalidArgument: InvalidArgument, skipArgName: boolean): string;
|
|
33
55
|
//# sourceMappingURL=argumentValueValidation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"argumentValueValidation.d.ts","sourceRoot":"","sources":["../../../../src/runtime/values/argumentValueValidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"argumentValueValidation.d.ts","sourceRoot":"","sources":["../../../../src/runtime/values/argumentValueValidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,MAAM,EAEN,wBAAwB,EACxB,eAAe,EACf,kBAAkB,EACnB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAE7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAG/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yCAAyC,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAyBvE;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,aAAa,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,GAAG,KAAK,CAAC,eAAe,GAAG,MAAM,CAAC,CAAC;CAC5E;AAiBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,aAAa,CAAC,wBAAwB,CAAC,EACjD,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,eAAe,GAAG,wBAAwB,EAClD,gBAAgB,EAAE,KAAK,CAAC,eAAe,CAAC,GACvC,IAAI,CAmBN;AAyXD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,aAAa,EAC9B,KAAK,EAAE,kBAAkB,GAAG,eAAe,GAAG,KAAK,CAAC,eAAe,GAAG,SAAS,CAAC,EAChF,gBAAgB,EAAE,KAAK,CAAC,eAAe,CAAC,EACxC,QAAQ,CAAC,EAAE,KAAK,CAAC,wBAAwB,CAAC,GACzC,kBAAkB,GAAG,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC,CAS/D;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,kBAAkB,EACzB,gBAAgB,EAAE,KAAK,CAAC,eAAe,CAAC,EACxC,QAAQ,CAAC,EAAE,KAAK,CAAC,wBAAwB,CAAC,GACzC,kBAAkB,CASpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,kCAAkC,CAChD,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,wBAAwB,EAC/B,gBAAgB,EAAE,KAAK,CAAC,eAAe,CAAC,EACxC,QAAQ,CAAC,EAAE,KAAK,CAAC,wBAAwB,CAAC,GACzC,wBAAwB,CA4C1B;AAED,wBAAgB,wBAAwB,CACtC,eAAe,EAAE,eAAe,EAChC,WAAW,EAAE,OAAO,GACnB,MAAM,CA+DR"}
|
|
@@ -8,28 +8,41 @@ function withPrefix(invalidArgument, prefix) {
|
|
|
8
8
|
return { ...invalidArgument, name: `${prefix}${invalidArgument.name ?? ""}` };
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
* {@link
|
|
13
|
-
*
|
|
14
|
-
* @param argument the {@link Argument} providing the custom validate function.
|
|
15
|
-
* @param name the name to use for the {@link InvalidArgument}.
|
|
16
|
-
* @param value the validated and type-converted value.
|
|
11
|
+
* Records a custom validation of the provided {@link Argument} (if it has one) for later invocation by
|
|
12
|
+
* {@link runCustomValidation}. Deferred validations are recorded bottom-up and depth-first.
|
|
17
13
|
*/
|
|
18
|
-
function
|
|
19
|
-
if (argument.validate
|
|
20
|
-
|
|
14
|
+
function deferCustomValidation(deferred, argument, path, value) {
|
|
15
|
+
if (deferred !== undefined && argument.validate !== undefined) {
|
|
16
|
+
deferred.push({ argument, path, value });
|
|
21
17
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Invokes the recorded custom validations in order, stopping at the first failure.
|
|
21
|
+
*
|
|
22
|
+
* @param deferred the validations recorded while validating the values of the command.
|
|
23
|
+
* @param command the {@link Command} the validated values belong to.
|
|
24
|
+
* @param values all validated and converted values of the command.
|
|
25
|
+
* @param invalidArguments an array of {@link InvalidArgument} which is added to if a custom validation fails.
|
|
26
|
+
*/
|
|
27
|
+
export function runCustomValidation(deferred, command, values, invalidArguments) {
|
|
28
|
+
for (const { argument, path, value } of deferred) {
|
|
29
|
+
const message = argument.validate(value, {
|
|
30
|
+
argument: argument,
|
|
31
|
+
path,
|
|
32
|
+
values,
|
|
33
|
+
command,
|
|
34
|
+
});
|
|
35
|
+
if (message !== undefined) {
|
|
36
|
+
invalidArguments.push({
|
|
37
|
+
argument,
|
|
38
|
+
name: path,
|
|
39
|
+
value: value,
|
|
40
|
+
reason: InvalidArgumentReason.CUSTOM_VALIDATION,
|
|
41
|
+
message,
|
|
42
|
+
});
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
25
45
|
}
|
|
26
|
-
return {
|
|
27
|
-
argument,
|
|
28
|
-
name,
|
|
29
|
-
value: value,
|
|
30
|
-
reason: InvalidArgumentReason.CUSTOM_VALIDATION,
|
|
31
|
-
message,
|
|
32
|
-
};
|
|
33
46
|
}
|
|
34
47
|
/**
|
|
35
48
|
* Validates the provided primitive value against the provided {@link Argument}.
|
|
@@ -141,7 +154,7 @@ function validatePrimitiveValue(argument, value) {
|
|
|
141
154
|
}
|
|
142
155
|
return { validValue: convertedValue };
|
|
143
156
|
}
|
|
144
|
-
function validateArrayValue(subCommandArgument, arrayValue) {
|
|
157
|
+
function validateArrayValue(subCommandArgument, arrayValue, path, deferred) {
|
|
145
158
|
const convertedArrayValue = [];
|
|
146
159
|
for (let i = 0; i < arrayValue.length; i += 1) {
|
|
147
160
|
const singleValue = arrayValue[i];
|
|
@@ -171,7 +184,7 @@ function validateArrayValue(subCommandArgument, arrayValue) {
|
|
|
171
184
|
},
|
|
172
185
|
};
|
|
173
186
|
}
|
|
174
|
-
validationResult = validateObjectValue(subCommandArgument, singleValue);
|
|
187
|
+
validationResult = validateObjectValue(subCommandArgument, singleValue, `${path}[${i}]`, deferred);
|
|
175
188
|
} // if not array and not object, then must be primitive
|
|
176
189
|
else {
|
|
177
190
|
if (isComplexOption(subCommandArgument)) {
|
|
@@ -202,10 +215,11 @@ function validateArrayValue(subCommandArgument, arrayValue) {
|
|
|
202
215
|
validValue: convertedArrayValue,
|
|
203
216
|
};
|
|
204
217
|
}
|
|
205
|
-
function validateObjectValue(argument, objectValue) {
|
|
218
|
+
function validateObjectValue(argument, objectValue, path, deferred) {
|
|
206
219
|
const convertedObjectValue = {};
|
|
207
220
|
for (let i = 0; i < argument.properties.length; i++) {
|
|
208
221
|
const propertyArg = argument.properties[i];
|
|
222
|
+
const propertyPath = `${path}.${propertyArg.name}`;
|
|
209
223
|
let propertyValue = objectValue[propertyArg.name];
|
|
210
224
|
if (propertyValue === undefined && propertyArg.defaultValue !== undefined) {
|
|
211
225
|
propertyValue = propertyArg.defaultValue;
|
|
@@ -236,7 +250,7 @@ function validateObjectValue(argument, objectValue) {
|
|
|
236
250
|
},
|
|
237
251
|
};
|
|
238
252
|
}
|
|
239
|
-
validationResult = validateArrayValue(propertyArg, propertyValue);
|
|
253
|
+
validationResult = validateArrayValue(propertyArg, propertyValue, propertyPath, deferred);
|
|
240
254
|
}
|
|
241
255
|
else if (typeof propertyValue === "object") {
|
|
242
256
|
if (propertyArg.type !== ComplexValueTypeName.COMPLEX) {
|
|
@@ -250,7 +264,7 @@ function validateObjectValue(argument, objectValue) {
|
|
|
250
264
|
},
|
|
251
265
|
};
|
|
252
266
|
}
|
|
253
|
-
validationResult = validateObjectValue(propertyArg, propertyValue);
|
|
267
|
+
validationResult = validateObjectValue(propertyArg, propertyValue, propertyPath, deferred);
|
|
254
268
|
} // if not array and not object, then must be primitive
|
|
255
269
|
else {
|
|
256
270
|
if (isComplexOption(propertyArg)) {
|
|
@@ -276,20 +290,14 @@ function validateObjectValue(argument, objectValue) {
|
|
|
276
290
|
invalidArgument: withPrefix(validationResult.invalidArgument, `.${propertyArg.name}`),
|
|
277
291
|
};
|
|
278
292
|
}
|
|
279
|
-
// custom validation
|
|
280
|
-
|
|
281
|
-
if (customInvalidArgument !== undefined) {
|
|
282
|
-
return {
|
|
283
|
-
validValue: convertedObjectValue,
|
|
284
|
-
invalidArgument: customInvalidArgument,
|
|
285
|
-
};
|
|
286
|
-
}
|
|
293
|
+
// custom validation is deferred until all built-in validation has passed
|
|
294
|
+
deferCustomValidation(deferred, propertyArg, propertyPath, validationResult.validValue);
|
|
287
295
|
}
|
|
288
296
|
return {
|
|
289
297
|
validValue: convertedObjectValue,
|
|
290
298
|
};
|
|
291
299
|
}
|
|
292
|
-
function doSubCommandArgumentValidation(argument, value, isArray, isOptional, invalidArguments) {
|
|
300
|
+
function doSubCommandArgumentValidation(argument, value, isArray, isOptional, invalidArguments, deferred) {
|
|
293
301
|
// if there is a value, check if it is valid
|
|
294
302
|
if (value !== undefined) {
|
|
295
303
|
let validationResult;
|
|
@@ -303,7 +311,7 @@ function doSubCommandArgumentValidation(argument, value, isArray, isOptional, in
|
|
|
303
311
|
});
|
|
304
312
|
return undefined;
|
|
305
313
|
}
|
|
306
|
-
validationResult = validateArrayValue(argument, value);
|
|
314
|
+
validationResult = validateArrayValue(argument, value, argument.name, deferred);
|
|
307
315
|
}
|
|
308
316
|
else if (typeof value === "object") {
|
|
309
317
|
if (!isComplexOption(argument)) {
|
|
@@ -315,7 +323,7 @@ function doSubCommandArgumentValidation(argument, value, isArray, isOptional, in
|
|
|
315
323
|
});
|
|
316
324
|
return undefined;
|
|
317
325
|
}
|
|
318
|
-
validationResult = validateObjectValue(argument, value);
|
|
326
|
+
validationResult = validateObjectValue(argument, value, argument.name, deferred);
|
|
319
327
|
}
|
|
320
328
|
else {
|
|
321
329
|
if (isComplexOption(argument)) {
|
|
@@ -333,11 +341,7 @@ function doSubCommandArgumentValidation(argument, value, isArray, isOptional, in
|
|
|
333
341
|
invalidArguments.push(withPrefix(validationResult.invalidArgument, argument.name));
|
|
334
342
|
return undefined;
|
|
335
343
|
}
|
|
336
|
-
|
|
337
|
-
if (customInvalidArgument !== undefined) {
|
|
338
|
-
invalidArguments.push(customInvalidArgument);
|
|
339
|
-
return undefined;
|
|
340
|
-
}
|
|
344
|
+
deferCustomValidation(deferred, argument, argument.name, validationResult.validValue);
|
|
341
345
|
return validationResult.validValue;
|
|
342
346
|
}
|
|
343
347
|
// if there is no value, check if it was optional
|
|
@@ -356,9 +360,10 @@ function doSubCommandArgumentValidation(argument, value, isArray, isOptional, in
|
|
|
356
360
|
* @param option the {@link Option} to validate against.
|
|
357
361
|
* @param value the value (if any) for the {@link Option}.
|
|
358
362
|
* @param invalidArguments an array of {@link InvalidArgument} which may be added to if the provided value is invalid.
|
|
363
|
+
* @param deferred if provided, custom validations are recorded here for later invocation by {@link runCustomValidation}. If omitted, custom validations are not invoked.
|
|
359
364
|
*/
|
|
360
|
-
export function validateOptionValue(option, value, invalidArguments) {
|
|
361
|
-
return doSubCommandArgumentValidation(option, value, option.isArray || false, option.isOptional || false, invalidArguments);
|
|
365
|
+
export function validateOptionValue(option, value, invalidArguments, deferred) {
|
|
366
|
+
return doSubCommandArgumentValidation(option, value, option.isArray || false, option.isOptional || false, invalidArguments, deferred);
|
|
362
367
|
}
|
|
363
368
|
/**
|
|
364
369
|
* Validates the provided value against the provided {@link Positional}.
|
|
@@ -366,9 +371,10 @@ export function validateOptionValue(option, value, invalidArguments) {
|
|
|
366
371
|
* @param positional the {@link Positional} to validate against.
|
|
367
372
|
* @param value the value (if any) for the {@link Positional}.
|
|
368
373
|
* @param invalidArguments an array of {@link InvalidArgument} which may be added to if the provided value is invalid.
|
|
374
|
+
* @param deferred if provided, custom validations are recorded here for later invocation by {@link runCustomValidation}. If omitted, custom validations are not invoked.
|
|
369
375
|
*/
|
|
370
|
-
export function validatePositionalValue(positional, value, invalidArguments) {
|
|
371
|
-
return doSubCommandArgumentValidation(positional, value, positional.isVarargMultiple || false, positional.isVarargOptional || false, invalidArguments);
|
|
376
|
+
export function validatePositionalValue(positional, value, invalidArguments, deferred) {
|
|
377
|
+
return doSubCommandArgumentValidation(positional, value, positional.isVarargMultiple || false, positional.isVarargOptional || false, invalidArguments, deferred);
|
|
372
378
|
}
|
|
373
379
|
/**
|
|
374
380
|
* Validates the provided value against the {@link GlobalCommandArgument} provided by the {@link GlobalCommand} and returns the validated
|
|
@@ -377,8 +383,9 @@ export function validatePositionalValue(positional, value, invalidArguments) {
|
|
|
377
383
|
* @param globalCommand the {@link GlobalCommand} providing the {@link GlobalCommandArgument}.
|
|
378
384
|
* @param value the value (if any) for the {@link GlobalCommandArgument}.
|
|
379
385
|
* @param invalidArguments an array of {@link InvalidArgument} which may be added to if the provided value is invalid.
|
|
386
|
+
* @param deferred if provided, custom validations are recorded here for later invocation by {@link runCustomValidation}. If omitted, custom validations are not invoked.
|
|
380
387
|
*/
|
|
381
|
-
export function validateGlobalCommandArgumentValue(globalCommand, value, invalidArguments) {
|
|
388
|
+
export function validateGlobalCommandArgumentValue(globalCommand, value, invalidArguments, deferred) {
|
|
382
389
|
// if this function is called it is because the argument is defined
|
|
383
390
|
const globalCommandArgument = globalCommand.argument;
|
|
384
391
|
// if there is a value, check if it is valid
|
|
@@ -402,11 +409,7 @@ export function validateGlobalCommandArgumentValue(globalCommand, value, invalid
|
|
|
402
409
|
}
|
|
403
410
|
return undefined;
|
|
404
411
|
}
|
|
405
|
-
|
|
406
|
-
if (customInvalidArgument !== undefined) {
|
|
407
|
-
invalidArguments.push(customInvalidArgument);
|
|
408
|
-
return undefined;
|
|
409
|
-
}
|
|
412
|
+
deferCustomValidation(deferred, globalCommandArgument, globalCommand.name, validationResult.validValue);
|
|
410
413
|
return validationResult.validValue;
|
|
411
414
|
}
|
|
412
415
|
// if there is no value, check if it was optional
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { ArgumentPrompterService } from "@flowscripter/dynamic-cli-framework-api";
|
|
2
2
|
import type { ParseResult } from "../../runtime/parser.ts";
|
|
3
3
|
import type { PrompterService } from "@flowscripter/dynamic-cli-framework-api";
|
|
4
|
+
import { type Values } from "@flowscripter/dynamic-cli-framework-api";
|
|
5
|
+
import type { Option } from "@flowscripter/dynamic-cli-framework-api";
|
|
6
|
+
import type { ComplexOption } from "@flowscripter/dynamic-cli-framework-api";
|
|
4
7
|
export default class DefaultArgumentPrompterService implements ArgumentPrompterService {
|
|
5
8
|
#private;
|
|
6
9
|
constructor(prompterService: PrompterService);
|
|
7
10
|
promptForMissingArguments(parseResult: ParseResult): Promise<ParseResult>;
|
|
11
|
+
promptForArguments(args: ReadonlyArray<Option | ComplexOption>, existing?: Values): Promise<Values | undefined>;
|
|
8
12
|
}
|
|
9
13
|
//# sourceMappingURL=DefaultArgumentPrompterService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultArgumentPrompterService.d.ts","sourceRoot":"","sources":["../../../../src/service/argumentPrompter/DefaultArgumentPrompterService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"DefaultArgumentPrompterService.d.ts","sourceRoot":"","sources":["../../../../src/service/argumentPrompter/DefaultArgumentPrompterService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAQ/E,OAAO,EAML,KAAK,MAAM,EACZ,MAAM,yCAAyC,CAAC;AAGjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AAEtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAmB7E,MAAM,CAAC,OAAO,OAAO,8BAA+B,YAAW,uBAAuB;;IAGpF,YAAmB,eAAe,EAAE,eAAe,EAElD;IAEK,yBAAyB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CA+B9E;IAEK,kBAAkB,CACtB,IAAI,EAAE,aAAa,CAAC,MAAM,GAAG,aAAa,CAAC,EAC3C,QAAQ,GAAE,MAAW,GACpB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAiB7B;CA8PF"}
|
|
@@ -2,6 +2,11 @@ import { PromptType, } from "@flowscripter/dynamic-cli-framework-api";
|
|
|
2
2
|
import { InvalidArgumentReason } from "@flowscripter/dynamic-cli-framework-api";
|
|
3
3
|
import { ValueTypeName, ComplexValueTypeName, } from "@flowscripter/dynamic-cli-framework-api";
|
|
4
4
|
import { isGlobalCommand, isSubCommand } from "../../runtime/command/CommandTypeGuards.js";
|
|
5
|
+
/**
|
|
6
|
+
* Used as {@link ValidationContext.command} when prompting via {@link ArgumentPrompterService.promptForArguments},
|
|
7
|
+
* which is not associated with a specific command.
|
|
8
|
+
*/
|
|
9
|
+
const NO_COMMAND = { name: "" };
|
|
5
10
|
export default class DefaultArgumentPrompterService {
|
|
6
11
|
#prompterService;
|
|
7
12
|
constructor(prompterService) {
|
|
@@ -34,12 +39,40 @@ export default class DefaultArgumentPrompterService {
|
|
|
34
39
|
}
|
|
35
40
|
return parseResult;
|
|
36
41
|
}
|
|
42
|
+
async promptForArguments(args, existing = {}) {
|
|
43
|
+
if (!this.#prompterService.promptEnabled) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const prompted = {};
|
|
47
|
+
const merged = { ...existing };
|
|
48
|
+
const scope = { command: NO_COMMAND, values: merged };
|
|
49
|
+
for (const arg of args) {
|
|
50
|
+
if (arg.name in existing) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const value = (await this.#promptForArgument(arg.name, arg, scope));
|
|
54
|
+
prompted[arg.name] = value;
|
|
55
|
+
merged[arg.name] = value;
|
|
56
|
+
}
|
|
57
|
+
return prompted;
|
|
58
|
+
}
|
|
59
|
+
async #promptForArgument(name, arg, scope) {
|
|
60
|
+
if ("type" in arg && arg.type === ComplexValueTypeName.COMPLEX) {
|
|
61
|
+
return await this.#promptForComplexOption(name, arg, scope);
|
|
62
|
+
}
|
|
63
|
+
if (DefaultArgumentPrompterService.#isArrayArgument(arg)) {
|
|
64
|
+
return await this.#promptForArrayArgument(name, arg, scope);
|
|
65
|
+
}
|
|
66
|
+
const prompt = DefaultArgumentPrompterService.#argumentToPrompt(name, arg.description ?? name, arg, name, scope);
|
|
67
|
+
const result = await this.#prompterService.prompt(prompt);
|
|
68
|
+
return DefaultArgumentPrompterService.#coerceValue(result.value, arg.type);
|
|
69
|
+
}
|
|
37
70
|
async #promptForGlobalCommand(parseResult) {
|
|
38
71
|
const command = parseResult.command;
|
|
39
72
|
if (!command.argument) {
|
|
40
73
|
return parseResult;
|
|
41
74
|
}
|
|
42
|
-
const prompt = DefaultArgumentPrompterService.#argumentToPrompt(command.name, command.name, command.argument);
|
|
75
|
+
const prompt = DefaultArgumentPrompterService.#argumentToPrompt(command.name, command.name, command.argument, command.name, { command, values: undefined });
|
|
43
76
|
const result = await this.#prompterService.prompt(prompt);
|
|
44
77
|
const value = DefaultArgumentPrompterService.#coerceValue(result.value, command.argument.type);
|
|
45
78
|
return {
|
|
@@ -57,6 +90,7 @@ export default class DefaultArgumentPrompterService {
|
|
|
57
90
|
...existingValues,
|
|
58
91
|
};
|
|
59
92
|
const remainingInvalid = [];
|
|
93
|
+
const scope = { command, values: newValues };
|
|
60
94
|
for (const invalid of parseResult.invalidArguments) {
|
|
61
95
|
if (invalid.reason !== InvalidArgumentReason.MISSING_VALUE || !invalid.name) {
|
|
62
96
|
remainingInvalid.push(invalid);
|
|
@@ -67,19 +101,7 @@ export default class DefaultArgumentPrompterService {
|
|
|
67
101
|
remainingInvalid.push(invalid);
|
|
68
102
|
continue;
|
|
69
103
|
}
|
|
70
|
-
|
|
71
|
-
const complexValues = await this.#promptForComplexOption(invalid.name, arg);
|
|
72
|
-
newValues[invalid.name] = complexValues;
|
|
73
|
-
}
|
|
74
|
-
else if (DefaultArgumentPrompterService.#isArrayArgument(arg)) {
|
|
75
|
-
const arrayValues = await this.#promptForArrayArgument(invalid.name, arg);
|
|
76
|
-
newValues[invalid.name] = arrayValues;
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
const prompt = DefaultArgumentPrompterService.#argumentToPrompt(invalid.name, arg.description ?? invalid.name, arg);
|
|
80
|
-
const result = await this.#prompterService.prompt(prompt);
|
|
81
|
-
newValues[invalid.name] = DefaultArgumentPrompterService.#coerceValue(result.value, arg.type);
|
|
82
|
-
}
|
|
104
|
+
newValues[invalid.name] = await this.#promptForArgument(invalid.name, arg, scope);
|
|
83
105
|
}
|
|
84
106
|
return {
|
|
85
107
|
command: parseResult.command,
|
|
@@ -89,28 +111,28 @@ export default class DefaultArgumentPrompterService {
|
|
|
89
111
|
unusedArgs: parseResult.unusedArgs,
|
|
90
112
|
};
|
|
91
113
|
}
|
|
92
|
-
async #promptForComplexOption(name, complexOption) {
|
|
114
|
+
async #promptForComplexOption(name, complexOption, scope) {
|
|
93
115
|
const values = {};
|
|
94
116
|
for (const prop of complexOption.properties) {
|
|
95
117
|
if ("type" in prop && prop.type === ComplexValueTypeName.COMPLEX) {
|
|
96
|
-
values[prop.name] = await this.#promptForComplexOption(`${name}.${prop.name}`, prop);
|
|
118
|
+
values[prop.name] = await this.#promptForComplexOption(`${name}.${prop.name}`, prop, scope);
|
|
97
119
|
}
|
|
98
120
|
else {
|
|
99
121
|
const option = prop;
|
|
100
122
|
if (option.isOptional && option.defaultValue !== undefined) {
|
|
101
123
|
continue;
|
|
102
124
|
}
|
|
103
|
-
const prompt = DefaultArgumentPrompterService.#argumentToPrompt(`${name}.${option.name}`, option.description ?? `${name}.${option.name}`, option);
|
|
125
|
+
const prompt = DefaultArgumentPrompterService.#argumentToPrompt(`${name}.${option.name}`, option.description ?? `${name}.${option.name}`, option, `${name}.${option.name}`, scope);
|
|
104
126
|
const result = await this.#prompterService.prompt(prompt);
|
|
105
127
|
values[option.name] = DefaultArgumentPrompterService.#coerceValue(result.value, option.type);
|
|
106
128
|
}
|
|
107
129
|
}
|
|
108
130
|
return values;
|
|
109
131
|
}
|
|
110
|
-
async #promptForArrayArgument(name, arg) {
|
|
132
|
+
async #promptForArrayArgument(name, arg, scope) {
|
|
111
133
|
const values = [];
|
|
112
134
|
while (true) {
|
|
113
|
-
const prompt = DefaultArgumentPrompterService.#argumentToPrompt(name, `${arg.description ?? name}${values.length > 0 ? ` [${values.length + 1}]` : ""}`, arg);
|
|
135
|
+
const prompt = DefaultArgumentPrompterService.#argumentToPrompt(name, `${arg.description ?? name}${values.length > 0 ? ` [${values.length + 1}]` : ""}`, arg, name, scope);
|
|
114
136
|
const result = await this.#prompterService.prompt(prompt);
|
|
115
137
|
values.push(DefaultArgumentPrompterService.#coerceValue(result.value, arg.type));
|
|
116
138
|
const addAnother = {
|
|
@@ -126,7 +148,7 @@ export default class DefaultArgumentPrompterService {
|
|
|
126
148
|
}
|
|
127
149
|
return values;
|
|
128
150
|
}
|
|
129
|
-
static #argumentToPrompt(name, description, arg) {
|
|
151
|
+
static #argumentToPrompt(name, description, arg, path, scope) {
|
|
130
152
|
if (arg.type === ValueTypeName.BOOLEAN) {
|
|
131
153
|
return {
|
|
132
154
|
name,
|
|
@@ -152,7 +174,17 @@ export default class DefaultArgumentPrompterService {
|
|
|
152
174
|
returnedValue: "",
|
|
153
175
|
min: arg.minValueInclusive,
|
|
154
176
|
max: arg.maxValueInclusive,
|
|
155
|
-
validate: arg.validate
|
|
177
|
+
validate: arg.validate
|
|
178
|
+
? (v) => {
|
|
179
|
+
const value = DefaultArgumentPrompterService.#coerceValue(v, arg.type);
|
|
180
|
+
return arg.validate(value, {
|
|
181
|
+
argument: arg,
|
|
182
|
+
path,
|
|
183
|
+
values: scope.values === undefined ? value : scope.values,
|
|
184
|
+
command: scope.command,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
: undefined,
|
|
156
188
|
};
|
|
157
189
|
return {
|
|
158
190
|
name,
|