@flowscripter/dynamic-cli-framework 9.1.3 → 10.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/command/MultiCommandCliHelpCommand.d.ts.map +1 -1
- package/dist/src/command/MultiCommandCliHelpCommand.js +1 -1
- package/dist/src/runtime/command/CommandValidator.d.ts.map +1 -1
- package/dist/src/runtime/command/CommandValidator.js +9 -2
- package/dist/src/runtime/parser.d.ts +8 -2
- package/dist/src/runtime/parser.d.ts.map +1 -1
- package/dist/src/runtime/parser.js +11 -6
- package/dist/src/runtime/runner.d.ts.map +1 -1
- package/dist/src/runtime/runner.js +5 -2
- package/dist/src/runtime/values/ValuePopulationResult.d.ts +4 -0
- package/dist/src/runtime/values/ValuePopulationResult.d.ts.map +1 -1
- package/dist/src/runtime/values/globalCommandValuePopulation.d.ts.map +1 -1
- package/dist/src/runtime/values/globalCommandValuePopulation.js +11 -3
- package/dist/src/runtime/values/subCommandValuePopulation.d.ts.map +1 -1
- package/dist/src/runtime/values/subCommandValuePopulation.js +39 -9
- package/dist/src/service/configuration/ConfigurationServiceProvider.d.ts +12 -3
- package/dist/src/service/configuration/ConfigurationServiceProvider.d.ts.map +1 -1
- package/dist/src/service/configuration/ConfigurationServiceProvider.js +16 -7
- package/dist/src/util/configHelper.d.ts +4 -1
- package/dist/src/util/configHelper.d.ts.map +1 -1
- package/dist/src/util/configHelper.js +6 -1
- package/dist/src/util/envVarHelper.d.ts +4 -1
- package/dist/src/util/envVarHelper.d.ts.map +1 -1
- package/dist/src/util/envVarHelper.js +8 -5
- package/dist/src/util/helpHelper.d.ts +1 -1
- package/dist/src/util/helpHelper.d.ts.map +1 -1
- package/dist/src/util/helpHelper.js +8 -16
- package/dist/src/util/runnerHelper.d.ts +2 -0
- package/dist/src/util/runnerHelper.d.ts.map +1 -1
- package/dist/src/util/runnerHelper.js +10 -0
- package/dist/src/util/secretRedaction.d.ts +11 -0
- package/dist/src/util/secretRedaction.d.ts.map +1 -0
- package/dist/src/util/secretRedaction.js +45 -0
- package/package.json +1 -1
- package/src/command/MultiCommandCliHelpCommand.ts +7 -1
- package/src/runtime/command/CommandValidator.ts +8 -1
- package/src/runtime/parser.ts +22 -16
- package/src/runtime/runner.ts +5 -0
- package/src/runtime/values/ValuePopulationResult.ts +5 -0
- package/src/runtime/values/globalCommandValuePopulation.ts +12 -5
- package/src/runtime/values/subCommandValuePopulation.ts +47 -12
- package/src/service/configuration/ConfigurationServiceProvider.ts +18 -6
- package/src/util/configHelper.ts +7 -0
- package/src/util/envVarHelper.ts +19 -3
- package/src/util/helpHelper.ts +34 -13
- package/src/util/runnerHelper.ts +18 -0
- package/src/util/secretRedaction.ts +81 -0
|
@@ -8,11 +8,12 @@ function getKeySegment(segment) {
|
|
|
8
8
|
}
|
|
9
9
|
return keySegment;
|
|
10
10
|
}
|
|
11
|
-
function getSubCommandArgumentKeyPrefix(cliConfig, command, subCommandArgument) {
|
|
11
|
+
function getSubCommandArgumentKeyPrefix(cliConfig, command, subCommandArgument, groupCommand) {
|
|
12
12
|
if (subCommandArgument.configurationKey) {
|
|
13
13
|
return subCommandArgument.configurationKey;
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
const groupSegment = groupCommand ? `${getKeySegment(groupCommand.name)}_` : "";
|
|
16
|
+
return `${getKeySegment(cliConfig.name)}_${groupSegment}${getKeySegment(command.name)}_${getKeySegment(subCommandArgument.name)}`;
|
|
16
17
|
}
|
|
17
18
|
function getGlobalArgumentKeyPrefix(cliConfig, command, globalCommandArgument) {
|
|
18
19
|
if (globalCommandArgument.configurationKey) {
|
|
@@ -146,13 +147,15 @@ function getOptionValuesFromEnvVars(envVarValues, potentialEnvVarNames, env, opt
|
|
|
146
147
|
* @param cliConfig the {@link CLIConfig} to use for determining the default configuration key.
|
|
147
148
|
* @param command the {@link SubCommand} to use for determining the default configuration key and containing
|
|
148
149
|
* {@link Positional} and {@link Option} instances to populate values for.
|
|
150
|
+
* @param groupCommand the {@link GroupCommand} if the command is a group member, in which case the group name
|
|
151
|
+
* is an additional env var name segment.
|
|
149
152
|
*/
|
|
150
|
-
export function getSubCommandValuesFromEnvVars(cliConfig, command) {
|
|
153
|
+
export function getSubCommandValuesFromEnvVars(cliConfig, command, groupCommand) {
|
|
151
154
|
const envVarValues = Object.create(null);
|
|
152
155
|
if (command.options) {
|
|
153
156
|
for (const option of command.options) {
|
|
154
157
|
const potentialEnvVarNames = Object.keys(process.env);
|
|
155
|
-
const optionPrefix = getSubCommandArgumentKeyPrefix(cliConfig, command, option);
|
|
158
|
+
const optionPrefix = getSubCommandArgumentKeyPrefix(cliConfig, command, option, groupCommand);
|
|
156
159
|
getOptionValuesFromEnvVars(envVarValues, potentialEnvVarNames, process.env ?? {}, option, optionPrefix);
|
|
157
160
|
}
|
|
158
161
|
}
|
|
@@ -163,7 +166,7 @@ export function getSubCommandValuesFromEnvVars(cliConfig, command) {
|
|
|
163
166
|
positional.name === "prototype") {
|
|
164
167
|
throw new Error(`Unsafe key name in use: ${positional.name}, CodeQL Rule ID: js/prototype-polluting-assignment`);
|
|
165
168
|
}
|
|
166
|
-
let envVarNamePrefix = getSubCommandArgumentKeyPrefix(cliConfig, command, positional);
|
|
169
|
+
let envVarNamePrefix = getSubCommandArgumentKeyPrefix(cliConfig, command, positional, groupCommand);
|
|
167
170
|
if (positional.isVarargMultiple) {
|
|
168
171
|
envVarNamePrefix = `${envVarNamePrefix}_`;
|
|
169
172
|
const matches = Object.keys(process.env).filter((envVarName) => envVarName.startsWith(envVarNamePrefix));
|
|
@@ -19,7 +19,7 @@ export interface HelpSection {
|
|
|
19
19
|
export declare function printHelpSections(printerService: PrinterService, tableGeneratorService: TableGeneratorService, sections: Array<HelpSection>): Promise<void>;
|
|
20
20
|
export declare function getGlobalArgumentHelpEntry(cliConfig: CLIConfig, includeEnvVars: boolean, globalCommand: GlobalCommand): HelpEntry;
|
|
21
21
|
export declare function getSubCommandArgumentsSyntax(subCommand: SubCommand): string;
|
|
22
|
-
export declare function getCommandArgsHelpSections(cliConfig: CLIConfig, includeEnvVars: boolean, subCommand: SubCommand, isSingleCommandApp: boolean): Array<HelpSection>;
|
|
22
|
+
export declare function getCommandArgsHelpSections(cliConfig: CLIConfig, includeEnvVars: boolean, subCommand: SubCommand, isSingleCommandApp: boolean, groupCommand?: GroupCommand): Array<HelpSection>;
|
|
23
23
|
export declare function getCommandExamplesHelpSections(printerService: PrinterService, context: Context, subCommand: SubCommand): Array<HelpSection>;
|
|
24
24
|
export declare function getMultiCommandAppSyntax(context: Context, globalModifierCommands: ReadonlyArray<GlobalModifierCommand>, globalCommands: ReadonlyArray<GlobalCommand>, groupCommands: ReadonlyArray<GroupCommand>, subCommands: ReadonlyArray<SubCommand>): string;
|
|
25
25
|
export declare function findPossibleCommandNames(commandName: string, groupCommands: ReadonlyArray<GroupCommand>, subCommands: ReadonlyArray<SubCommand>): string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpHelper.d.ts","sourceRoot":"","sources":["../../../src/util/helpHelper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAG7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAIvE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AACrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAM5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAG9E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAiCrF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;CACxC;AAsDD,wBAAsB,iBAAiB,CACrC,cAAc,EAAE,cAAc,EAC9B,qBAAqB,EAAE,qBAAqB,EAC5C,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,GAC3B,OAAO,CAAC,IAAI,CAAC,CA2Cf;AA2BD,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,OAAO,EACvB,aAAa,EAAE,aAAa,GAC3B,SAAS,CA6DX;AAED,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CA+C3E;
|
|
1
|
+
{"version":3,"file":"helpHelper.d.ts","sourceRoot":"","sources":["../../../src/util/helpHelper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAG7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAIvE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AACrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAM5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAG9E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAiCrF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;CACxC;AAsDD,wBAAsB,iBAAiB,CACrC,cAAc,EAAE,cAAc,EAC9B,qBAAqB,EAAE,qBAAqB,EAC5C,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,GAC3B,OAAO,CAAC,IAAI,CAAC,CA2Cf;AA2BD,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,OAAO,EACvB,aAAa,EAAE,aAAa,GAC3B,SAAS,CA6DX;AAED,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CA+C3E;AA8LD,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,OAAO,EACvB,UAAU,EAAE,UAAU,EACtB,kBAAkB,EAAE,OAAO,EAC3B,YAAY,CAAC,EAAE,YAAY,GAC1B,KAAK,CAAC,WAAW,CAAC,CA4BpB;AACD,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,UAAU,GACrB,KAAK,CAAC,WAAW,CAAC,CAgCpB;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,OAAO,EAChB,sBAAsB,EAAE,aAAa,CAAC,qBAAqB,CAAC,EAC5D,cAAc,EAAE,aAAa,CAAC,aAAa,CAAC,EAC5C,aAAa,EAAE,aAAa,CAAC,YAAY,CAAC,EAC1C,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,GACrC,MAAM,CA8IR;AAED,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,aAAa,CAAC,YAAY,CAAC,EAC1C,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,GACrC,MAAM,EAAE,CAkBV"}
|
|
@@ -216,7 +216,7 @@ export function getSubCommandArgumentsSyntax(subCommand) {
|
|
|
216
216
|
});
|
|
217
217
|
return syntax;
|
|
218
218
|
}
|
|
219
|
-
function getOptionHelpEntry(cliConfig, includeEnvVars, command, option, subEntryIndent = 0, optionAncestry = []) {
|
|
219
|
+
function getOptionHelpEntry(cliConfig, includeEnvVars, command, option, subEntryIndent = 0, optionAncestry = [], groupCommand) {
|
|
220
220
|
let subEntries;
|
|
221
221
|
let optionCharacters = "--";
|
|
222
222
|
let aliasCharacter = "-";
|
|
@@ -230,10 +230,7 @@ function getOptionHelpEntry(cliConfig, includeEnvVars, command, option, subEntry
|
|
|
230
230
|
if (option.type === ComplexValueTypeName.COMPLEX) {
|
|
231
231
|
subEntries = [];
|
|
232
232
|
option.properties.forEach((property) => {
|
|
233
|
-
subEntries.push(getOptionHelpEntry(cliConfig, includeEnvVars, command, property, newSubEntryIndent, [
|
|
234
|
-
...optionAncestry,
|
|
235
|
-
option,
|
|
236
|
-
]));
|
|
233
|
+
subEntries.push(getOptionHelpEntry(cliConfig, includeEnvVars, command, property, newSubEntryIndent, [...optionAncestry, option], groupCommand));
|
|
237
234
|
});
|
|
238
235
|
}
|
|
239
236
|
else {
|
|
@@ -279,10 +276,7 @@ function getOptionHelpEntry(cliConfig, includeEnvVars, command, option, subEntry
|
|
|
279
276
|
notesItems.push("array");
|
|
280
277
|
}
|
|
281
278
|
if (includeEnvVars && option.type !== ComplexValueTypeName.COMPLEX) {
|
|
282
|
-
const configurationKey = getSubCommandArgumentConfigurationKey(cliConfig, command, [
|
|
283
|
-
...optionAncestry,
|
|
284
|
-
option,
|
|
285
|
-
]);
|
|
279
|
+
const configurationKey = getSubCommandArgumentConfigurationKey(cliConfig, command, [...optionAncestry, option], groupCommand);
|
|
286
280
|
if (configurationKey !== undefined) {
|
|
287
281
|
notesItems.push(`env var: ${configurationKey}`);
|
|
288
282
|
}
|
|
@@ -303,7 +297,7 @@ function getOptionHelpEntry(cliConfig, includeEnvVars, command, option, subEntry
|
|
|
303
297
|
helpSubEntries: subEntries,
|
|
304
298
|
};
|
|
305
299
|
}
|
|
306
|
-
function getPositionalHelpEntry(cliConfig, includeEnvVars, command, positional) {
|
|
300
|
+
function getPositionalHelpEntry(cliConfig, includeEnvVars, command, positional, groupCommand) {
|
|
307
301
|
const notesItems = [];
|
|
308
302
|
if (positional.allowableValues !== undefined && positional.allowableValues.length > 0) {
|
|
309
303
|
notesItems.push(`valid values: ${userInputList(positional.allowableValues, "|")}`);
|
|
@@ -341,9 +335,7 @@ function getPositionalHelpEntry(cliConfig, includeEnvVars, command, positional)
|
|
|
341
335
|
notesItems.push("array");
|
|
342
336
|
}
|
|
343
337
|
if (includeEnvVars) {
|
|
344
|
-
const configurationKey = getSubCommandArgumentConfigurationKey(cliConfig, command, [
|
|
345
|
-
positional,
|
|
346
|
-
]);
|
|
338
|
+
const configurationKey = getSubCommandArgumentConfigurationKey(cliConfig, command, [positional], groupCommand);
|
|
347
339
|
if (configurationKey !== undefined) {
|
|
348
340
|
notesItems.push(`env var: ${configurationKey}`);
|
|
349
341
|
}
|
|
@@ -362,7 +354,7 @@ function getPositionalHelpEntry(cliConfig, includeEnvVars, command, positional)
|
|
|
362
354
|
description,
|
|
363
355
|
};
|
|
364
356
|
}
|
|
365
|
-
export function getCommandArgsHelpSections(cliConfig, includeEnvVars, subCommand, isSingleCommandApp) {
|
|
357
|
+
export function getCommandArgsHelpSections(cliConfig, includeEnvVars, subCommand, isSingleCommandApp, groupCommand) {
|
|
366
358
|
const helpSections = [];
|
|
367
359
|
if (subCommand.options.length > 0 || subCommand.positionals.length > 0) {
|
|
368
360
|
const argumentsSection = {
|
|
@@ -370,10 +362,10 @@ export function getCommandArgsHelpSections(cliConfig, includeEnvVars, subCommand
|
|
|
370
362
|
helpEntries: [],
|
|
371
363
|
};
|
|
372
364
|
subCommand.options.forEach((option) => {
|
|
373
|
-
argumentsSection.helpEntries.push(getOptionHelpEntry(cliConfig, includeEnvVars, subCommand, option));
|
|
365
|
+
argumentsSection.helpEntries.push(getOptionHelpEntry(cliConfig, includeEnvVars, subCommand, option, 0, [], groupCommand));
|
|
374
366
|
});
|
|
375
367
|
subCommand.positionals.forEach((positional) => {
|
|
376
|
-
argumentsSection.helpEntries.push(getPositionalHelpEntry(cliConfig, includeEnvVars, subCommand, positional));
|
|
368
|
+
argumentsSection.helpEntries.push(getPositionalHelpEntry(cliConfig, includeEnvVars, subCommand, positional, groupCommand));
|
|
377
369
|
});
|
|
378
370
|
helpSections.push(argumentsSection);
|
|
379
371
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SecretAwareParseResult } from "../runtime/parser.ts";
|
|
1
2
|
import type { ParseResult } from "../runtime/parser.ts";
|
|
2
3
|
import type { Context } from "@flowscripter/dynamic-cli-framework-api";
|
|
3
4
|
import type { CommandRegistry } from "@flowscripter/dynamic-cli-framework-api";
|
|
@@ -7,4 +8,5 @@ export declare function printRuntimeError(context: Context, err: Error): Promise
|
|
|
7
8
|
export declare function printNoCommandSpecifiedError(context: Context): Promise<void>;
|
|
8
9
|
export declare function printNoCommandRecognisedError(context: Context, commandRegistry: CommandRegistry, availableArgs: ReadonlyArray<string>): Promise<void>;
|
|
9
10
|
export declare function printUnusedArgsWarning(context: Context, overallUnusedArgs: ReadonlyArray<string>): Promise<void>;
|
|
11
|
+
export declare function printSecretArgsWarning(context: Context, parseResult: SecretAwareParseResult): Promise<void>;
|
|
10
12
|
//# sourceMappingURL=runnerHelper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runnerHelper.d.ts","sourceRoot":"","sources":["../../../src/util/runnerHelper.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAEvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAY/E,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,gBAAgB,UAAQ,iBAiBzB;AAED,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,GAAG,EAAE,KAAK,EACV,gBAAgB,UAAQ,iBAiBzB;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,iBAMnE;AAED,wBAAsB,4BAA4B,CAAC,OAAO,EAAE,OAAO,iBAGlE;AAED,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,iBAgCrC;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,OAAO,EAChB,iBAAiB,EAAE,aAAa,CAAC,MAAM,CAAC,iBAQzC"}
|
|
1
|
+
{"version":3,"file":"runnerHelper.d.ts","sourceRoot":"","sources":["../../../src/util/runnerHelper.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAEvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAY/E,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,gBAAgB,UAAQ,iBAiBzB;AAED,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,GAAG,EAAE,KAAK,EACV,gBAAgB,UAAQ,iBAiBzB;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,iBAMnE;AAED,wBAAsB,4BAA4B,CAAC,OAAO,EAAE,OAAO,iBAGlE;AAED,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,iBAgCrC;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,OAAO,EAChB,iBAAiB,EAAE,aAAa,CAAC,MAAM,CAAC,iBAQzC;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,sBAAsB,iBAapC"}
|
|
@@ -78,3 +78,13 @@ export async function printUnusedArgsWarning(context, overallUnusedArgs) {
|
|
|
78
78
|
await printerService.warn(`Unused args: ${overallUnusedArgs.join(" ")}\n\n`, Icon.ALERT);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
+
export async function printSecretArgsWarning(context, parseResult) {
|
|
82
|
+
const secretArgumentNames = parseResult.secretArgumentNames;
|
|
83
|
+
if (!secretArgumentNames || secretArgumentNames.length === 0) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const printerService = context.getServiceById(PRINTER_SERVICE_ID);
|
|
87
|
+
await printerService.warn(`SECRET value passed as a plain argument: ${secretArgumentNames.join(", ")}. ` +
|
|
88
|
+
"This is not recommended as it may be exposed via shell history and process listings. " +
|
|
89
|
+
"Use an environment variable, a prompt or a configuration file default instead.\n\n", Icon.ALERT);
|
|
90
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type GlobalCommand, type PopulatedSingleValueType, type PopulatedValues, type SubCommand } from "@flowscripter/dynamic-cli-framework-api";
|
|
2
|
+
export declare const REDACTED = "***";
|
|
3
|
+
/**
|
|
4
|
+
* Copy of the provided values suitable for logging, with the values of any SECRET options or positionals replaced.
|
|
5
|
+
*/
|
|
6
|
+
export declare function redactSubCommandValues<T extends PopulatedValues | undefined>(subCommand: SubCommand, values: T): T;
|
|
7
|
+
/**
|
|
8
|
+
* Copy of the provided value suitable for logging, with the value replaced if the global command argument is a SECRET.
|
|
9
|
+
*/
|
|
10
|
+
export declare function redactGlobalCommandValue(globalCommand: GlobalCommand, value: PopulatedSingleValueType): PopulatedSingleValueType;
|
|
11
|
+
//# sourceMappingURL=secretRedaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secretRedaction.d.ts","sourceRoot":"","sources":["../../../src/util/secretRedaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAElB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EAEpB,KAAK,UAAU,EAChB,MAAM,yCAAyC,CAAC;AAGjD,eAAO,MAAM,QAAQ,QAAQ,CAAC;AA4C9B;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,eAAe,GAAG,SAAS,EAC1E,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,CAAC,GACR,CAAC,CAKH;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,wBAAwB,GAC9B,wBAAwB,CAK1B"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ValueTypeName, } from "@flowscripter/dynamic-cli-framework-api";
|
|
2
|
+
import { isComplexOption } from "../runtime/argument/ArgumentTypeGuards.js";
|
|
3
|
+
export const REDACTED = "***";
|
|
4
|
+
function redactValue(definition, value) {
|
|
5
|
+
if (value === undefined || value === null) {
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
if (isComplexOption(definition)) {
|
|
9
|
+
const properties = definition.properties;
|
|
10
|
+
if (Array.isArray(value)) {
|
|
11
|
+
return value.map((v) => redactValue(definition, v));
|
|
12
|
+
}
|
|
13
|
+
return redactDefinedValues(properties, [], value);
|
|
14
|
+
}
|
|
15
|
+
if (definition.type === ValueTypeName.SECRET) {
|
|
16
|
+
return Array.isArray(value) ? value.map(() => REDACTED) : REDACTED;
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
function redactDefinedValues(options, positionals, values) {
|
|
21
|
+
const redacted = {};
|
|
22
|
+
for (const [name, value] of Object.entries(values)) {
|
|
23
|
+
const definition = options.find((o) => o.name === name) ?? positionals.find((p) => p.name === name);
|
|
24
|
+
redacted[name] = definition ? redactValue(definition, value) : value;
|
|
25
|
+
}
|
|
26
|
+
return redacted;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Copy of the provided values suitable for logging, with the values of any SECRET options or positionals replaced.
|
|
30
|
+
*/
|
|
31
|
+
export function redactSubCommandValues(subCommand, values) {
|
|
32
|
+
if (values === undefined) {
|
|
33
|
+
return values;
|
|
34
|
+
}
|
|
35
|
+
return redactDefinedValues(subCommand.options, subCommand.positionals, values);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Copy of the provided value suitable for logging, with the value replaced if the global command argument is a SECRET.
|
|
39
|
+
*/
|
|
40
|
+
export function redactGlobalCommandValue(globalCommand, value) {
|
|
41
|
+
if (value !== undefined && globalCommand.argument?.type === ValueTypeName.SECRET) {
|
|
42
|
+
return REDACTED;
|
|
43
|
+
}
|
|
44
|
+
return value;
|
|
45
|
+
}
|
package/package.json
CHANGED
|
@@ -288,7 +288,13 @@ abstract class MultiCommandCliAbstractHelpCommand {
|
|
|
288
288
|
});
|
|
289
289
|
|
|
290
290
|
helpSections.push(
|
|
291
|
-
...getCommandArgsHelpSections(
|
|
291
|
+
...getCommandArgsHelpSections(
|
|
292
|
+
context.cliConfig,
|
|
293
|
+
this.#includeEnvVars,
|
|
294
|
+
subCommand,
|
|
295
|
+
false,
|
|
296
|
+
groupCommand,
|
|
297
|
+
),
|
|
292
298
|
);
|
|
293
299
|
|
|
294
300
|
helpSections.push(...getCommandExamplesHelpSections(printerService, context, subCommand));
|
|
@@ -165,6 +165,7 @@ function validateSubCommandArgument(subCommandArgument: SubCommandArgument): voi
|
|
|
165
165
|
export default class CommandValidator {
|
|
166
166
|
readonly #cliConfig: CLIConfig;
|
|
167
167
|
readonly #configurationKeys: Array<string> = [];
|
|
168
|
+
#currentGroupCommand: GroupCommand | undefined;
|
|
168
169
|
|
|
169
170
|
public constructor(cliConfig: CLIConfig) {
|
|
170
171
|
this.#cliConfig = cliConfig;
|
|
@@ -265,7 +266,12 @@ export default class CommandValidator {
|
|
|
265
266
|
);
|
|
266
267
|
}
|
|
267
268
|
subCommandNames.push(subCommand.name);
|
|
268
|
-
this.#
|
|
269
|
+
this.#currentGroupCommand = groupCommand;
|
|
270
|
+
try {
|
|
271
|
+
this.#validateSubCommand(subCommand);
|
|
272
|
+
} finally {
|
|
273
|
+
this.#currentGroupCommand = undefined;
|
|
274
|
+
}
|
|
269
275
|
});
|
|
270
276
|
}
|
|
271
277
|
|
|
@@ -365,6 +371,7 @@ export default class CommandValidator {
|
|
|
365
371
|
this.#cliConfig,
|
|
366
372
|
command,
|
|
367
373
|
argumentAncestry,
|
|
374
|
+
this.#currentGroupCommand,
|
|
368
375
|
);
|
|
369
376
|
|
|
370
377
|
if (configurationKey !== undefined) {
|
package/src/runtime/parser.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
validatePositionalValue,
|
|
14
14
|
} from "./values/argumentValueValidation.ts";
|
|
15
15
|
import getLogger from "../util/logger.ts";
|
|
16
|
+
import { redactGlobalCommandValue, redactSubCommandValues } from "../util/secretRedaction.ts";
|
|
16
17
|
import populateSubCommandValues from "./values/subCommandValuePopulation.ts";
|
|
17
18
|
import type { GlobalCommand } from "@flowscripter/dynamic-cli-framework-api";
|
|
18
19
|
import type { SubCommand } from "@flowscripter/dynamic-cli-framework-api";
|
|
@@ -21,6 +22,13 @@ const logger = getLogger("parser");
|
|
|
21
22
|
|
|
22
23
|
export type { ParseResult } from "@flowscripter/dynamic-cli-framework-api";
|
|
23
24
|
|
|
25
|
+
/**
|
|
26
|
+
* A {@link ParseResult} which also reports any SECRET arguments supplied as plain command line arguments.
|
|
27
|
+
*/
|
|
28
|
+
export type SecretAwareParseResult = ParseResult & {
|
|
29
|
+
readonly secretArgumentNames?: ReadonlyArray<string>;
|
|
30
|
+
};
|
|
31
|
+
|
|
24
32
|
/**
|
|
25
33
|
* Parse the arguments for the specified {@link CommandClause} assuming it contains a {@link SubCommand}.
|
|
26
34
|
*
|
|
@@ -30,7 +38,7 @@ export type { ParseResult } from "@flowscripter/dynamic-cli-framework-api";
|
|
|
30
38
|
export function parseSubCommandClause(
|
|
31
39
|
commandClause: CommandClause,
|
|
32
40
|
defaultValues?: PopulatedValues,
|
|
33
|
-
):
|
|
41
|
+
): SecretAwareParseResult {
|
|
34
42
|
const command = commandClause.command as SubCommand;
|
|
35
43
|
const potentialArgs = commandClause.potentialArgs;
|
|
36
44
|
const groupCommand = commandClause.groupCommand;
|
|
@@ -48,11 +56,8 @@ export function parseSubCommandClause(
|
|
|
48
56
|
};
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
const { populatedArgumentValues, unusedArgs, invalidArgument } =
|
|
52
|
-
command,
|
|
53
|
-
potentialArgs,
|
|
54
|
-
defaultValues,
|
|
55
|
-
);
|
|
59
|
+
const { populatedArgumentValues, unusedArgs, invalidArgument, secretArgumentNames } =
|
|
60
|
+
populateSubCommandValues(command, potentialArgs, defaultValues);
|
|
56
61
|
|
|
57
62
|
if (invalidArgument) {
|
|
58
63
|
invalidArguments.push(invalidArgument);
|
|
@@ -73,7 +78,7 @@ export function parseSubCommandClause(
|
|
|
73
78
|
|
|
74
79
|
logger.debug(
|
|
75
80
|
"Command arguments after options validated: %O with invalid args: %O",
|
|
76
|
-
populatedArgumentValues,
|
|
81
|
+
redactSubCommandValues(command, populatedArgumentValues),
|
|
77
82
|
invalidArguments,
|
|
78
83
|
);
|
|
79
84
|
|
|
@@ -91,11 +96,12 @@ export function parseSubCommandClause(
|
|
|
91
96
|
});
|
|
92
97
|
logger.debug(
|
|
93
98
|
"Command arguments after positionals validated: %O with invalid args: %O",
|
|
94
|
-
populatedArgumentValues,
|
|
99
|
+
redactSubCommandValues(command, populatedArgumentValues),
|
|
95
100
|
invalidArguments,
|
|
96
101
|
);
|
|
97
102
|
}
|
|
98
103
|
}
|
|
104
|
+
const secrets = secretArgumentNames ? { secretArgumentNames } : {};
|
|
99
105
|
if (groupCommand) {
|
|
100
106
|
return {
|
|
101
107
|
command,
|
|
@@ -103,6 +109,7 @@ export function parseSubCommandClause(
|
|
|
103
109
|
groupCommand,
|
|
104
110
|
invalidArguments,
|
|
105
111
|
unusedArgs,
|
|
112
|
+
...secrets,
|
|
106
113
|
};
|
|
107
114
|
}
|
|
108
115
|
return {
|
|
@@ -110,6 +117,7 @@ export function parseSubCommandClause(
|
|
|
110
117
|
populatedArgumentValues,
|
|
111
118
|
invalidArguments,
|
|
112
119
|
unusedArgs: unusedArgs,
|
|
120
|
+
...secrets,
|
|
113
121
|
};
|
|
114
122
|
}
|
|
115
123
|
|
|
@@ -122,7 +130,7 @@ export function parseSubCommandClause(
|
|
|
122
130
|
export function parseGlobalCommandClause(
|
|
123
131
|
commandClause: CommandClause,
|
|
124
132
|
defaultValue?: PopulatedSingleValueType,
|
|
125
|
-
):
|
|
133
|
+
): SecretAwareParseResult {
|
|
126
134
|
const command = commandClause.command as GlobalCommand;
|
|
127
135
|
const potentialArgs = commandClause.potentialArgs;
|
|
128
136
|
const invalidArguments: Array<InvalidArgument> = [];
|
|
@@ -137,11 +145,8 @@ export function parseGlobalCommandClause(
|
|
|
137
145
|
};
|
|
138
146
|
}
|
|
139
147
|
|
|
140
|
-
let { populatedArgumentValue, unusedArgs, invalidArgument } =
|
|
141
|
-
command,
|
|
142
|
-
potentialArgs,
|
|
143
|
-
defaultValue,
|
|
144
|
-
);
|
|
148
|
+
let { populatedArgumentValue, unusedArgs, invalidArgument, secretArgumentNames } =
|
|
149
|
+
populateGlobalCommandValue(command, potentialArgs, defaultValue);
|
|
145
150
|
|
|
146
151
|
if (invalidArgument) {
|
|
147
152
|
invalidArguments.push(invalidArgument);
|
|
@@ -150,7 +155,7 @@ export function parseGlobalCommandClause(
|
|
|
150
155
|
logger.debug(
|
|
151
156
|
"Command arguments for command: %s after value population: %O with invalid args: %O and unused args: %O",
|
|
152
157
|
command.name,
|
|
153
|
-
populatedArgumentValue,
|
|
158
|
+
redactGlobalCommandValue(command, populatedArgumentValue),
|
|
154
159
|
invalidArguments,
|
|
155
160
|
unusedArgs,
|
|
156
161
|
);
|
|
@@ -170,7 +175,7 @@ export function parseGlobalCommandClause(
|
|
|
170
175
|
logger.debug(
|
|
171
176
|
"Command arguments for command: %s after value validation: %O with invalid args: %O",
|
|
172
177
|
command.name,
|
|
173
|
-
populatedArgumentValue,
|
|
178
|
+
redactGlobalCommandValue(command, populatedArgumentValue),
|
|
174
179
|
invalidArguments,
|
|
175
180
|
);
|
|
176
181
|
|
|
@@ -179,5 +184,6 @@ export function parseGlobalCommandClause(
|
|
|
179
184
|
populatedArgumentValues: populatedArgumentValue,
|
|
180
185
|
invalidArguments,
|
|
181
186
|
unusedArgs,
|
|
187
|
+
...(secretArgumentNames && { secretArgumentNames }),
|
|
182
188
|
};
|
|
183
189
|
}
|
package/src/runtime/runner.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
printNoCommandRecognisedError,
|
|
16
16
|
printNoCommandSpecifiedError,
|
|
17
17
|
printParseResultError,
|
|
18
|
+
printSecretArgsWarning,
|
|
18
19
|
printUnusedArgsWarning,
|
|
19
20
|
} from "../util/runnerHelper.ts";
|
|
20
21
|
import { scanForGlobalModifierCommandClauses, scanForNonModifierCommandClause } from "./scanner.ts";
|
|
@@ -198,6 +199,7 @@ async function findAndExecuteGlobalModifierCommands(
|
|
|
198
199
|
globalModifierCommandClause,
|
|
199
200
|
defaultArgumentValues as PopulatedSingleValueType,
|
|
200
201
|
);
|
|
202
|
+
await printSecretArgsWarning(context, parseResult);
|
|
201
203
|
|
|
202
204
|
if (parseResult.invalidArguments.length > 0) {
|
|
203
205
|
await printParseResultError(context, parseResult);
|
|
@@ -314,6 +316,7 @@ async function findAndExecuteNonModifierCommand(
|
|
|
314
316
|
? await configurationServiceProvider.getDefaultArgumentValues(
|
|
315
317
|
context.cliConfig,
|
|
316
318
|
scanResult.nonModifierCommandClause.command,
|
|
319
|
+
scanResult.nonModifierCommandClause.groupCommand,
|
|
317
320
|
)
|
|
318
321
|
: undefined;
|
|
319
322
|
|
|
@@ -328,6 +331,7 @@ async function findAndExecuteNonModifierCommand(
|
|
|
328
331
|
defaultArgumentValues as PopulatedValues,
|
|
329
332
|
);
|
|
330
333
|
}
|
|
334
|
+
await printSecretArgsWarning(context, parseResult);
|
|
331
335
|
|
|
332
336
|
if (parseResult.invalidArguments.length > 0) {
|
|
333
337
|
const prompted = await attemptPromptForMissingArguments(parseResult, context);
|
|
@@ -463,6 +467,7 @@ async function findAndExecuteDefaultNonModifierCommand(
|
|
|
463
467
|
defaultArgumentValues as PopulatedValues,
|
|
464
468
|
);
|
|
465
469
|
}
|
|
470
|
+
await printSecretArgsWarning(context, parseResult);
|
|
466
471
|
|
|
467
472
|
// add any unused args back to the list of still unused args
|
|
468
473
|
if (parseResult.unusedArgs.length > 0) {
|
|
@@ -17,6 +17,11 @@ export interface ValuePopulationResult {
|
|
|
17
17
|
* Any invalid argument discovered while populating values.
|
|
18
18
|
*/
|
|
19
19
|
readonly invalidArgument?: InvalidArgument;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Names of any SECRET arguments whose values were supplied as plain command line arguments.
|
|
23
|
+
*/
|
|
24
|
+
readonly secretArgumentNames?: ReadonlyArray<string>;
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
/**
|
|
@@ -3,6 +3,7 @@ import type { GlobalCommandValuePopulationResult } from "./ValuePopulationResult
|
|
|
3
3
|
import { ValueTypeName } from "@flowscripter/dynamic-cli-framework-api";
|
|
4
4
|
import type { PopulatedSingleValueType } from "@flowscripter/dynamic-cli-framework-api";
|
|
5
5
|
import getLogger from "../../util/logger.ts";
|
|
6
|
+
import { REDACTED } from "../../util/secretRedaction.ts";
|
|
6
7
|
import { InvalidArgumentReason } from "@flowscripter/dynamic-cli-framework-api";
|
|
7
8
|
|
|
8
9
|
const logger = getLogger("globalCommandValuePopulation");
|
|
@@ -19,16 +20,21 @@ export default function populateGlobalCommandValue(
|
|
|
19
20
|
potentialArgs: ReadonlyArray<string>,
|
|
20
21
|
defaultValue: PopulatedSingleValueType,
|
|
21
22
|
): GlobalCommandValuePopulationResult {
|
|
23
|
+
const argument = globalCommand.argument!;
|
|
24
|
+
const isSecret = argument.type === ValueTypeName.SECRET;
|
|
22
25
|
logger.debug(() => {
|
|
23
|
-
const message = `Populating value for global command: '${globalCommand.name}' using potential args: ${
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
const message = `Populating value for global command: '${globalCommand.name}' using potential args: ${(isSecret
|
|
27
|
+
? potentialArgs
|
|
28
|
+
.slice(0, 1)
|
|
29
|
+
.map(() => REDACTED)
|
|
30
|
+
.concat(potentialArgs.slice(1))
|
|
31
|
+
: potentialArgs
|
|
32
|
+
).join(" ")}`;
|
|
26
33
|
if (defaultValue !== undefined) {
|
|
27
|
-
return `${message} and configured value: '${defaultValue}'`;
|
|
34
|
+
return `${message} and configured value: '${isSecret ? REDACTED : defaultValue}'`;
|
|
28
35
|
}
|
|
29
36
|
return message;
|
|
30
37
|
});
|
|
31
|
-
const argument = globalCommand.argument!;
|
|
32
38
|
|
|
33
39
|
// default to defined argument default value
|
|
34
40
|
let populatedArgumentValue = argument.defaultValue;
|
|
@@ -83,5 +89,6 @@ export default function populateGlobalCommandValue(
|
|
|
83
89
|
return {
|
|
84
90
|
populatedArgumentValue,
|
|
85
91
|
unusedArgs,
|
|
92
|
+
...(isSecret && potentialArgs.length > 0 && { secretArgumentNames: [globalCommand.name] }),
|
|
86
93
|
};
|
|
87
94
|
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type PopulatedValueType,
|
|
9
9
|
} from "@flowscripter/dynamic-cli-framework-api";
|
|
10
10
|
import getLogger from "../../util/logger.ts";
|
|
11
|
+
import { REDACTED, redactSubCommandValues } from "../../util/secretRedaction.ts";
|
|
11
12
|
import argumentValueMerge from "./argumentValueMerge.ts";
|
|
12
13
|
import type { SubCommandValuePopulationResult } from "./ValuePopulationResult.ts";
|
|
13
14
|
import type { ComplexOption } from "@flowscripter/dynamic-cli-framework-api";
|
|
@@ -87,6 +88,20 @@ class ParseContext {
|
|
|
87
88
|
*/
|
|
88
89
|
currentPositionalIndex;
|
|
89
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Set when the most recent argument supplied a value for a SECRET option or positional.
|
|
93
|
+
*/
|
|
94
|
+
secretArgument?: { name: string; inline: boolean };
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Return and clear the {@link secretArgument} recorded by the most recent {@link parse}.
|
|
98
|
+
*/
|
|
99
|
+
takeSecretArgument(): { name: string; inline: boolean } | undefined {
|
|
100
|
+
const secretArgument = this.secretArgument;
|
|
101
|
+
this.secretArgument = undefined;
|
|
102
|
+
return secretArgument;
|
|
103
|
+
}
|
|
104
|
+
|
|
90
105
|
/**
|
|
91
106
|
* Use to store lazily created map of option paths e.g. --alpha.b.g and -a.b.gamma for {@link ComplexOption} or {@link Option} instances.
|
|
92
107
|
*/
|
|
@@ -351,7 +366,10 @@ class ParseContext {
|
|
|
351
366
|
* @return `false` if there is a problem populating the value, in which case the {@link state} will be set to
|
|
352
367
|
* {@link ParseState.ERROR} and {@link invalidArgument} will be populated.
|
|
353
368
|
*/
|
|
354
|
-
setOptionValue(value: SingleValueType): boolean {
|
|
369
|
+
setOptionValue(value: SingleValueType, inline = false): boolean {
|
|
370
|
+
if (this.currentOption!.type === ValueTypeName.SECRET) {
|
|
371
|
+
this.secretArgument = { name: this.currentOption!.name, inline };
|
|
372
|
+
}
|
|
355
373
|
let optionValue: Array<PopulatedValues> | PopulatedValues | PopulatedValueType =
|
|
356
374
|
this.populatedArgumentValues;
|
|
357
375
|
const optionPath = this.currentOptionPath as Array<string | number>;
|
|
@@ -439,6 +457,10 @@ class ParseContext {
|
|
|
439
457
|
const positional = this.subCommand.positionals[this.currentPositionalIndex]!;
|
|
440
458
|
const currentValue = this.populatedArgumentValues[positional.name];
|
|
441
459
|
|
|
460
|
+
if (positional.type === ValueTypeName.SECRET) {
|
|
461
|
+
this.secretArgument = { name: positional.name, inline: false };
|
|
462
|
+
}
|
|
463
|
+
|
|
442
464
|
// if we haven't populated the argument value before...
|
|
443
465
|
if (currentValue === undefined) {
|
|
444
466
|
if (positional.isVarargMultiple) {
|
|
@@ -546,7 +568,7 @@ class ParseContext {
|
|
|
546
568
|
// try to set the value if we have one
|
|
547
569
|
if (potentialOptionValue !== undefined) {
|
|
548
570
|
// set the value
|
|
549
|
-
this.setOptionValue(potentialOptionValue);
|
|
571
|
+
this.setOptionValue(potentialOptionValue, true);
|
|
550
572
|
|
|
551
573
|
// return regardless
|
|
552
574
|
return;
|
|
@@ -587,24 +609,23 @@ export default function populateSubCommandValues(
|
|
|
587
609
|
potentialArgs: ReadonlyArray<string>,
|
|
588
610
|
defaultValues: PopulatedValues | undefined,
|
|
589
611
|
): SubCommandValuePopulationResult {
|
|
590
|
-
logger.debug(() => {
|
|
591
|
-
const message = `Populating values for sub-command: '${subCommand.name}' using potential args: ${potentialArgs.join(
|
|
592
|
-
" ",
|
|
593
|
-
)}`;
|
|
594
|
-
if (defaultValues !== undefined) {
|
|
595
|
-
return `${message} and configured values: ${JSON.stringify(defaultValues)}`;
|
|
596
|
-
}
|
|
597
|
-
return message;
|
|
598
|
-
});
|
|
599
|
-
|
|
600
612
|
const parseContext = new ParseContext(subCommand);
|
|
601
613
|
const unusedArgs: Array<string> = [];
|
|
614
|
+
const loggedArgs = [...potentialArgs];
|
|
615
|
+
const secretArgumentNames = new Set<string>();
|
|
602
616
|
|
|
603
617
|
for (let i = 0; i < potentialArgs.length; i++) {
|
|
604
618
|
const potentialArg = potentialArgs[i]!;
|
|
605
619
|
|
|
606
620
|
// parse the next arg
|
|
607
621
|
parseContext.parse(potentialArg);
|
|
622
|
+
const secretArgument = parseContext.takeSecretArgument();
|
|
623
|
+
if (secretArgument) {
|
|
624
|
+
secretArgumentNames.add(secretArgument.name);
|
|
625
|
+
loggedArgs[i] = secretArgument.inline
|
|
626
|
+
? `${potentialArg.slice(0, potentialArg.indexOf("=") + 1)}${REDACTED}`
|
|
627
|
+
: REDACTED;
|
|
628
|
+
}
|
|
608
629
|
|
|
609
630
|
// check if we had a parsing error, record the error, flush the remaining args and stop parsing
|
|
610
631
|
if (parseContext.state === ParseState.ERROR) {
|
|
@@ -620,6 +641,18 @@ export default function populateSubCommandValues(
|
|
|
620
641
|
}
|
|
621
642
|
}
|
|
622
643
|
|
|
644
|
+
logger.debug(() => {
|
|
645
|
+
const message = `Populated values for sub-command: '${subCommand.name}' using potential args: ${loggedArgs.join(
|
|
646
|
+
" ",
|
|
647
|
+
)}`;
|
|
648
|
+
if (defaultValues !== undefined) {
|
|
649
|
+
return `${message} and configured values: ${JSON.stringify(
|
|
650
|
+
redactSubCommandValues(subCommand, defaultValues),
|
|
651
|
+
)}`;
|
|
652
|
+
}
|
|
653
|
+
return message;
|
|
654
|
+
});
|
|
655
|
+
|
|
623
656
|
// Check if the last arg specified an option but no value
|
|
624
657
|
if (parseContext.state === ParseState.OPTION_VALUE_EXPECTED) {
|
|
625
658
|
// special case if the last arg was for a boolean option where the value was implicitly `true`
|
|
@@ -639,6 +672,7 @@ export default function populateSubCommandValues(
|
|
|
639
672
|
populatedArgumentValues: parseContext.populatedArgumentValues,
|
|
640
673
|
unusedArgs: unusedArgs,
|
|
641
674
|
invalidArgument: parseContext.invalidArgument,
|
|
675
|
+
...(secretArgumentNames.size > 0 && { secretArgumentNames: [...secretArgumentNames] }),
|
|
642
676
|
};
|
|
643
677
|
}
|
|
644
678
|
|
|
@@ -651,5 +685,6 @@ export default function populateSubCommandValues(
|
|
|
651
685
|
return {
|
|
652
686
|
populatedArgumentValues,
|
|
653
687
|
unusedArgs: unusedArgs,
|
|
688
|
+
...(secretArgumentNames.size > 0 && { secretArgumentNames: [...secretArgumentNames] }),
|
|
654
689
|
};
|
|
655
690
|
}
|