@gunshi/shared 1.0.0-rc.5 → 1.0.0-rc.6
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/lib/index.d.ts +133 -10
- package/lib/index.js +468 -2
- package/package.json +4 -3
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
//#region ../gunshi/src/constants.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The key of the mark on the `json` argument of `jsonArgs`. A string key, not a symbol: `gunshi` and the other
|
|
4
|
+
* packages bundle their own copies of the types, and each copy of a `unique symbol` is a different type.
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
declare const JSON_ARG = "~gunshi.json-arg";
|
|
9
|
+
//#endregion
|
|
1
10
|
//#region ../../node_modules/.pnpm/args-tokens@1.0.2/node_modules/args-tokens/lib/parser-DvPxBZG9.d.ts
|
|
2
11
|
/**
|
|
3
12
|
* Entry point of argument parser.
|
|
@@ -845,7 +854,11 @@ interface CommandEnvironment<G extends GunshiParamsConstraint = DefaultGunshiPar
|
|
|
845
854
|
* (they are still returned as strings) and to silence {@linkcode CommandContext.log}.
|
|
846
855
|
*
|
|
847
856
|
* Output that must still appear — machine-readable results for an agent, warnings for the
|
|
848
|
-
* CLI author — should use `console.log` / `console.warn`, not `ctx.log`.
|
|
857
|
+
* CLI author — should use `console.log` / `console.warn`, not `ctx.log`. A command that spreads
|
|
858
|
+
* `jsonArgs` and is given `--json` prints its result, and its errors, as JSON even with it.
|
|
859
|
+
*
|
|
860
|
+
* The validation errors, and a `CommandError` that the command throws, are not printed either, so
|
|
861
|
+
* `cli()` rejects with them, for the caller to report them.
|
|
849
862
|
*
|
|
850
863
|
* @default false
|
|
851
864
|
* @see {@linkcode CliOptions.usageSilent}
|
|
@@ -905,7 +918,8 @@ interface CommandEnvironment<G extends GunshiParamsConstraint = DefaultGunshiPar
|
|
|
905
918
|
*/
|
|
906
919
|
onBeforeCommand: ((ctx: Readonly<CommandContext<G>>) => Awaitable<void>) | undefined;
|
|
907
920
|
/**
|
|
908
|
-
* Hook that runs after successful command execution
|
|
921
|
+
* Hook that runs after successful command execution. It receives the result of the command only
|
|
922
|
+
* when it is a string.
|
|
909
923
|
*
|
|
910
924
|
* @see {@linkcode CliOptions.onAfterCommand}
|
|
911
925
|
* @since v0.27.0
|
|
@@ -1010,9 +1024,11 @@ interface CommandContext<G extends GunshiParamsConstraint = DefaultGunshiParams>
|
|
|
1010
1024
|
*/
|
|
1011
1025
|
toKebab?: boolean;
|
|
1012
1026
|
/**
|
|
1013
|
-
* Output a message.
|
|
1027
|
+
* Output a message for people.
|
|
1014
1028
|
*
|
|
1015
|
-
* If {@linkcode CommandEnvironment.usageSilent} is true, the message is not output.
|
|
1029
|
+
* If {@linkcode CommandEnvironment.usageSilent} is true, the message is not output. Nor is it when a
|
|
1030
|
+
* command that spreads `jsonArgs` is asked for JSON with `--json`, so that stdout has the JSON only:
|
|
1031
|
+
* the hooks and the plugins get the same function.
|
|
1016
1032
|
*
|
|
1017
1033
|
* @param message - an output message, see {@linkcode console.log}
|
|
1018
1034
|
* @param optionalParams - an optional parameters, see {@linkcode console.log}
|
|
@@ -1233,9 +1249,40 @@ type CommandExamplesFetcher<G extends GunshiParamsConstraint = DefaultGunshiPara
|
|
|
1233
1249
|
* @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of command context.
|
|
1234
1250
|
*
|
|
1235
1251
|
* @param ctx - A {@link CommandContext | command context}
|
|
1236
|
-
* @returns
|
|
1252
|
+
* @returns The result of a command that spreads `jsonArgs`, an object keyed by a noun, which is printed
|
|
1253
|
+
* as JSON with `--json`. For any other command, a string, which `cli()` returns, or nothing. See
|
|
1254
|
+
* {@linkcode CommandRunnerResult}.
|
|
1255
|
+
*/
|
|
1256
|
+
type CommandRunner<G extends GunshiParamsConstraint = DefaultGunshiParams> = (ctx: Readonly<CommandContext<G>>) => CommandRunnerResult<G>;
|
|
1257
|
+
/**
|
|
1258
|
+
* The result of a command that supports `--json`: an object keyed by a noun, such as
|
|
1259
|
+
* `{ project }` or `{ projects }`, so that fields can be added later. The global options plugin prints
|
|
1260
|
+
* it with `JSON.stringify`, so convert what JSON cannot hold, such as a `Map` or a `BigInt`, yourself.
|
|
1261
|
+
*/
|
|
1262
|
+
type JsonResult = Record<string, unknown>;
|
|
1263
|
+
/**
|
|
1264
|
+
* Whether the arguments have the `json` of `jsonArgs`.
|
|
1265
|
+
*
|
|
1266
|
+
* @typeParam A - The arguments of a command
|
|
1237
1267
|
*/
|
|
1238
|
-
type
|
|
1268
|
+
type HasJsonArgs<A> = [A] extends [{
|
|
1269
|
+
readonly json: {
|
|
1270
|
+
readonly [JSON_ARG]: true;
|
|
1271
|
+
};
|
|
1272
|
+
}] ? true : false;
|
|
1273
|
+
/**
|
|
1274
|
+
* What the runner of a command returns: its result for a command that spreads `jsonArgs`, otherwise a string or
|
|
1275
|
+
* nothing.
|
|
1276
|
+
*
|
|
1277
|
+
* @typeParam G - A type extending {@linkcode GunshiParams}
|
|
1278
|
+
*/
|
|
1279
|
+
type CommandRunnerResult<G extends GunshiParamsConstraint = DefaultGunshiParams> = IsAnyArgs<ExtractArgs<G>> extends true ? Awaitable<string | void | JsonResult> : HasJsonArgs<ExtractArgs<G>> extends true ? Awaitable<JsonResult> : Awaitable<string | void>;
|
|
1280
|
+
/**
|
|
1281
|
+
* Whether the arguments are `any`, as in `CommandRunner<any>`. Then a runner may return anything it could before.
|
|
1282
|
+
*
|
|
1283
|
+
* @internal
|
|
1284
|
+
*/
|
|
1285
|
+
type IsAnyArgs<A> = 0 extends 1 & A ? true : false;
|
|
1239
1286
|
//#endregion
|
|
1240
1287
|
//#region ../../node_modules/.pnpm/args-tokens@1.0.2/node_modules/args-tokens/lib/utils.d.ts
|
|
1241
1288
|
/**
|
|
@@ -1258,6 +1305,36 @@ type CommandRunner<G extends GunshiParamsConstraint = DefaultGunshiParams> = (ct
|
|
|
1258
1305
|
declare function kebabnize(str: string): string;
|
|
1259
1306
|
//#endregion
|
|
1260
1307
|
//#region ../gunshi/src/utils.d.ts
|
|
1308
|
+
/**
|
|
1309
|
+
* How `--json` asks a command for JSON.
|
|
1310
|
+
*
|
|
1311
|
+
* - `'declared'`: the command spreads `jsonArgs` into its arguments, and `--json` asks it for JSON
|
|
1312
|
+
* - `'undeclared'`: the command has no `json` argument, and `--json` is given to it
|
|
1313
|
+
*/
|
|
1314
|
+
type JsonRequest = 'declared' | 'undeclared';
|
|
1315
|
+
/**
|
|
1316
|
+
* Check whether an argument schema is the `json` argument of `jsonArgs`, by its mark.
|
|
1317
|
+
*
|
|
1318
|
+
* @param schema - An argument schema
|
|
1319
|
+
* @returns `true` if the schema has the mark of `jsonArgs`
|
|
1320
|
+
*/
|
|
1321
|
+
declare function isJsonArg(schema: unknown): boolean;
|
|
1322
|
+
/**
|
|
1323
|
+
* Resolve whether `--json` asks a command for JSON.
|
|
1324
|
+
*
|
|
1325
|
+
* A command that spreads `jsonArgs` is asked for JSON when the resolved value of its `json` is `true`:
|
|
1326
|
+
* with `--json`, or with a short name that the command gives it, but not with `--json=false`, nor with
|
|
1327
|
+
* `--json` after `--`. The raw tokens are read only when they are given, and only when there is no
|
|
1328
|
+
* value to read: when the command has no `json` argument, and when the core could not resolve the
|
|
1329
|
+
* command and left the values empty. A `json` argument without the mark belongs to the command, and
|
|
1330
|
+
* `--json` is never taken for a request then.
|
|
1331
|
+
*
|
|
1332
|
+
* @param args - The arguments of the command, the global options included
|
|
1333
|
+
* @param values - The resolved values of the arguments
|
|
1334
|
+
* @param tokens - The raw tokens of the arguments, to find a `--json` that no argument declares
|
|
1335
|
+
* @returns How the command is asked for JSON, or `undefined` when it is not
|
|
1336
|
+
*/
|
|
1337
|
+
declare function resolveJsonRequest(args: Readonly<Args>, values: Readonly<Record<string, unknown>>, tokens?: readonly ArgToken[]): JsonRequest | undefined;
|
|
1261
1338
|
/**
|
|
1262
1339
|
* Check if the given command is a {@link LazyCommand}.
|
|
1263
1340
|
*
|
|
@@ -1339,11 +1416,13 @@ type CommonArgType = {
|
|
|
1339
1416
|
};
|
|
1340
1417
|
};
|
|
1341
1418
|
declare const COMMON_ARGS: CommonArgType;
|
|
1342
|
-
declare const COMMAND_BUILTIN_RESOURCE_KEYS: readonly ["USAGE", "COMMAND", "SUBCOMMAND", "COMMANDS", "ARGUMENTS", "OPTIONS", "EXAMPLES", "FORMORE", "NEGATABLE", "DEFAULT", "CHOICES"];
|
|
1419
|
+
declare const COMMAND_BUILTIN_RESOURCE_KEYS: readonly ["USAGE", "COMMAND", "SUBCOMMAND", "COMMANDS", "ARGUMENTS", "OPTIONS", "EXAMPLES", "FORMORE", "NEGATABLE", "DEFAULT", "CHOICES", "CAUSEDBY"];
|
|
1343
1420
|
declare const ARG_ERROR_RESOURCE_KEYS: readonly ["err:arg:required-option", "err:arg:required-positional", "err:arg:invalid-type", "err:arg:invalid-choice", "err:arg:custom-parse", "err:arg:unknown-option", "err:arg:unexpected-value", "err:arg:missing-value", "err:arg:conflict", "err:arg:invalid-default"];
|
|
1344
1421
|
declare const ARG_ERROR_HINT_RESOURCE_KEYS: readonly ["err:arg:missing-value:hint"];
|
|
1345
1422
|
declare const COMMAND_ERROR_RESOURCE_KEYS: readonly ["err:cmd:not-found", "err:cmd:ambiguous", "err:cmd:inconsistent-options", "err:cmd:lazy-schema-mismatch"];
|
|
1346
1423
|
declare const SUGGESTION_ERROR_RESOURCE_KEYS: readonly ["err:suggestion:did-you-mean"];
|
|
1424
|
+
declare const JSON_RESOURCE_KEYS: readonly ["json", "json:invalid-arguments", "json:next:help", "json:next:help-placeholder"];
|
|
1425
|
+
declare const JSON_ERROR_RESOURCE_KEYS: readonly ["err:json:not-supported", "err:json:invalid-result", "err:json:unserializable-result"];
|
|
1347
1426
|
//#endregion
|
|
1348
1427
|
//#region src/types.d.ts
|
|
1349
1428
|
type RemoveIndexSignature<T> = { [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K]; };
|
|
@@ -1387,14 +1466,23 @@ type CommandErrorResourceKeys = (typeof COMMAND_ERROR_RESOURCE_KEYS)[number];
|
|
|
1387
1466
|
* Suggestion error resource keys.
|
|
1388
1467
|
*/
|
|
1389
1468
|
type SuggestionErrorResourceKeys = (typeof SUGGESTION_ERROR_RESOURCE_KEYS)[number];
|
|
1469
|
+
/**
|
|
1470
|
+
* Resource keys of the errors of the JSON output.
|
|
1471
|
+
*/
|
|
1472
|
+
type JsonErrorResourceKeys = (typeof JSON_ERROR_RESOURCE_KEYS)[number];
|
|
1473
|
+
/**
|
|
1474
|
+
* Resource keys of the description of the `json` argument of `jsonArgs`, and of the texts that only
|
|
1475
|
+
* the JSON errors print.
|
|
1476
|
+
*/
|
|
1477
|
+
type JsonResourceKeys = (typeof JSON_RESOURCE_KEYS)[number];
|
|
1390
1478
|
/**
|
|
1391
1479
|
* Error resource keys.
|
|
1392
1480
|
*/
|
|
1393
|
-
type ErrorResourceKeys = ArgErrorResourceKeys | ArgErrorHintResourceKeys | CommandErrorResourceKeys | SuggestionErrorResourceKeys;
|
|
1481
|
+
type ErrorResourceKeys = ArgErrorResourceKeys | ArgErrorHintResourceKeys | CommandErrorResourceKeys | SuggestionErrorResourceKeys | JsonErrorResourceKeys;
|
|
1394
1482
|
/**
|
|
1395
1483
|
* Built-in resource keys.
|
|
1396
1484
|
*/
|
|
1397
|
-
type BuiltinResourceKeys = ErrorResourceKeys | CommandBuiltinArgsKeys | CommandBuiltinResourceKeys;
|
|
1485
|
+
type BuiltinResourceKeys = ErrorResourceKeys | CommandBuiltinArgsKeys | CommandBuiltinResourceKeys | JsonResourceKeys;
|
|
1398
1486
|
/**
|
|
1399
1487
|
* Built-in resource.
|
|
1400
1488
|
*/
|
|
@@ -1478,8 +1566,13 @@ declare const _exports: {
|
|
|
1478
1566
|
NEGATABLE: string;
|
|
1479
1567
|
DEFAULT: string;
|
|
1480
1568
|
CHOICES: string;
|
|
1569
|
+
CAUSEDBY: string;
|
|
1481
1570
|
help: string;
|
|
1482
1571
|
version: string;
|
|
1572
|
+
json: string;
|
|
1573
|
+
"json:invalid-arguments": string;
|
|
1574
|
+
"json:next:help": string;
|
|
1575
|
+
"json:next:help-placeholder": string;
|
|
1483
1576
|
"err:arg:required-option": string;
|
|
1484
1577
|
"err:arg:required-positional": string;
|
|
1485
1578
|
"err:arg:invalid-type": string;
|
|
@@ -1495,6 +1588,9 @@ declare const _exports: {
|
|
|
1495
1588
|
"err:cmd:ambiguous": string;
|
|
1496
1589
|
"err:cmd:inconsistent-options": string;
|
|
1497
1590
|
"err:cmd:lazy-schema-mismatch": string;
|
|
1591
|
+
"err:json:not-supported": string;
|
|
1592
|
+
"err:json:invalid-result": string;
|
|
1593
|
+
"err:json:unserializable-result": string;
|
|
1498
1594
|
"err:suggestion:did-you-mean": string;
|
|
1499
1595
|
};
|
|
1500
1596
|
//#endregion
|
|
@@ -1601,4 +1697,31 @@ declare function resolveOptionNames(args: Args, toKebab?: boolean): Set<string>;
|
|
|
1601
1697
|
*/
|
|
1602
1698
|
declare function resolveCommandArgs<A extends Args = Args>(globalOptions?: ReadonlyMap<string, ArgSchema>, args?: A): A;
|
|
1603
1699
|
//#endregion
|
|
1604
|
-
|
|
1700
|
+
//#region src/validation.d.ts
|
|
1701
|
+
/**
|
|
1702
|
+
* Localize the message of a validation error, as gunshi shows it to the user: with the i18n plugin when
|
|
1703
|
+
* it is installed, and otherwise the message of the error.
|
|
1704
|
+
*
|
|
1705
|
+
* NOTE(kazupon): the renderer plugin renders the validation errors for people, and the global options
|
|
1706
|
+
* plugin prints them as JSON with `--json`. Both take the messages from here, so that a message is the
|
|
1707
|
+
* same in both.
|
|
1708
|
+
*
|
|
1709
|
+
* @param ctx - A {@link CommandContext | command context}
|
|
1710
|
+
* @param error - A validation error: an {@link ArgsValidationError}, a command-not-found error, or a
|
|
1711
|
+
* command-resolution error
|
|
1712
|
+
* @returns The localized message
|
|
1713
|
+
*/
|
|
1714
|
+
declare function localizeValidationError<G extends GunshiParams = DefaultGunshiParams>(ctx: CommandContext<G>, error: Error): Promise<string>;
|
|
1715
|
+
/**
|
|
1716
|
+
* Localize a text of the built-in resources: with the i18n plugin when it is installed and knows the key,
|
|
1717
|
+
* and otherwise the English one.
|
|
1718
|
+
*
|
|
1719
|
+
* @param ctx - A {@link CommandContext | command context}
|
|
1720
|
+
* @param key - The key of the text: `_:<key>` for a text that is not an error, and the key itself for an
|
|
1721
|
+
* error, such as `err:json:not-supported`
|
|
1722
|
+
* @param values - The values of the placeholders of the text
|
|
1723
|
+
* @returns The localized text, or the key when no resource has it
|
|
1724
|
+
*/
|
|
1725
|
+
declare function localizeBuiltinResource<G extends GunshiParams = DefaultGunshiParams>(ctx: CommandContext<G>, key: string, values?: Record<string, unknown>): Promise<string>;
|
|
1726
|
+
//#endregion
|
|
1727
|
+
export { ARG_ERROR_HINT_RESOURCE_KEYS, ARG_ERROR_RESOURCE_KEYS, ARG_NEGATABLE_PREFIX, ARG_PREFIX, ARG_PREFIX_AND_KEY_SEPARATOR, type ArgErrorHintResourceKeys, type ArgErrorResourceKeys, BUILD_IN_PREFIX_AND_KEY_SEPARATOR, BUILT_IN_KEY_SEPARATOR, BUILT_IN_PREFIX, type BuiltinResource, type BuiltinResourceKeys, COMMAND_BUILTIN_RESOURCE_KEYS, COMMAND_ERROR_RESOURCE_KEYS, COMMON_ARGS, type CommandArgKeys, type CommandBuiltinArgsKeys, type CommandBuiltinKeys, type CommandBuiltinResourceKeys, type CommandErrorResourceKeys, type DeepWriteable, _exports as DefaultResource, ERROR_PREFIX, ERROR_PREFIX_AND_KEY_SEPARATOR, type ErrorResourceKeys, type GenerateNamespacedKey, JSON_ERROR_RESOURCE_KEYS, JSON_RESOURCE_KEYS, type JsonErrorResourceKeys, JsonRequest, type JsonResourceKeys, type KeyOfArgs, Localization, PLUGIN_PREFIX, type RemovedIndex, type ResolveTranslationKeys, SUGGESTION_ERROR_RESOURCE_KEYS, type SuggestionErrorResourceKeys, type Translation, create, deepFreeze, formatResource, getCommandSubCommands, isJsonArg, isLazyCommand, kebabnize, localizable, localizeBuiltinResource, localizeValidationError, log, makeShortLongOptionPair, namespacedId, resolveArgKey, resolveBuiltInKey, resolveCommandArgs, resolveDisplayName, resolveExamples, resolveJsonRequest, resolveKey, resolveLazyCommand, resolveOptionNames };
|
package/lib/index.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
//#endregion
|
|
1
6
|
//#region ../../node_modules/.pnpm/args-tokens@1.0.2/node_modules/args-tokens/lib/utils.js
|
|
2
7
|
/**
|
|
3
8
|
* Entry point of utils.
|
|
@@ -26,6 +31,51 @@ function kebabnize(str) {
|
|
|
26
31
|
* @license MIT
|
|
27
32
|
*/
|
|
28
33
|
/**
|
|
34
|
+
* Check whether an argument schema is the `json` argument of `jsonArgs`, by its mark.
|
|
35
|
+
*
|
|
36
|
+
* @param schema - An argument schema
|
|
37
|
+
* @returns `true` if the schema has the mark of `jsonArgs`
|
|
38
|
+
*/
|
|
39
|
+
function isJsonArg(schema) {
|
|
40
|
+
return typeof schema === "object" && schema !== null && schema["~gunshi.json-arg"] === true;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Resolve whether `--json` asks a command for JSON.
|
|
44
|
+
*
|
|
45
|
+
* A command that spreads `jsonArgs` is asked for JSON when the resolved value of its `json` is `true`:
|
|
46
|
+
* with `--json`, or with a short name that the command gives it, but not with `--json=false`, nor with
|
|
47
|
+
* `--json` after `--`. The raw tokens are read only when they are given, and only when there is no
|
|
48
|
+
* value to read: when the command has no `json` argument, and when the core could not resolve the
|
|
49
|
+
* command and left the values empty. A `json` argument without the mark belongs to the command, and
|
|
50
|
+
* `--json` is never taken for a request then.
|
|
51
|
+
*
|
|
52
|
+
* @param args - The arguments of the command, the global options included
|
|
53
|
+
* @param values - The resolved values of the arguments
|
|
54
|
+
* @param tokens - The raw tokens of the arguments, to find a `--json` that no argument declares
|
|
55
|
+
* @returns How the command is asked for JSON, or `undefined` when it is not
|
|
56
|
+
*/
|
|
57
|
+
function resolveJsonRequest(args, values, tokens) {
|
|
58
|
+
const schema = Object.hasOwn(args, "json") ? args.json : void 0;
|
|
59
|
+
if (schema === void 0) return tokens !== void 0 && hasJsonOption(tokens) ? "undeclared" : void 0;
|
|
60
|
+
if (!isJsonArg(schema)) return;
|
|
61
|
+
if (values.json !== void 0) return values.json === true ? "declared" : void 0;
|
|
62
|
+
return tokens !== void 0 && hasJsonOption(tokens) ? "declared" : void 0;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check whether the raw tokens have a `--json` that asks for JSON: `--json` or `--json=true`, before
|
|
66
|
+
* `--`. Without a declaration, a short name of `--json` is not known.
|
|
67
|
+
*
|
|
68
|
+
* @param tokens - The raw tokens of the arguments
|
|
69
|
+
* @returns `true` if a `--json` asks for JSON
|
|
70
|
+
*/
|
|
71
|
+
function hasJsonOption(tokens) {
|
|
72
|
+
for (const token of tokens) {
|
|
73
|
+
if (token.kind === "option-terminator") return false;
|
|
74
|
+
if (token.kind === "option" && token.rawName === "--json" && (token.value === void 0 || token.value === "true")) return true;
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
29
79
|
* Check if the given command is a {@link LazyCommand}.
|
|
30
80
|
*
|
|
31
81
|
* @param cmd - A command to check
|
|
@@ -194,7 +244,8 @@ const COMMAND_BUILTIN_RESOURCE_KEYS = [
|
|
|
194
244
|
"FORMORE",
|
|
195
245
|
"NEGATABLE",
|
|
196
246
|
"DEFAULT",
|
|
197
|
-
"CHOICES"
|
|
247
|
+
"CHOICES",
|
|
248
|
+
"CAUSEDBY"
|
|
198
249
|
];
|
|
199
250
|
const ARG_ERROR_RESOURCE_KEYS = [
|
|
200
251
|
"err:arg:required-option",
|
|
@@ -216,6 +267,17 @@ const COMMAND_ERROR_RESOURCE_KEYS = [
|
|
|
216
267
|
"err:cmd:lazy-schema-mismatch"
|
|
217
268
|
];
|
|
218
269
|
const SUGGESTION_ERROR_RESOURCE_KEYS = ["err:suggestion:did-you-mean"];
|
|
270
|
+
const JSON_RESOURCE_KEYS = [
|
|
271
|
+
"json",
|
|
272
|
+
"json:invalid-arguments",
|
|
273
|
+
"json:next:help",
|
|
274
|
+
"json:next:help-placeholder"
|
|
275
|
+
];
|
|
276
|
+
const JSON_ERROR_RESOURCE_KEYS = [
|
|
277
|
+
"err:json:not-supported",
|
|
278
|
+
"err:json:invalid-result",
|
|
279
|
+
"err:json:unserializable-result"
|
|
280
|
+
];
|
|
219
281
|
//#endregion
|
|
220
282
|
//#region ../resources/locales/en-US.json
|
|
221
283
|
var en_US_default = {
|
|
@@ -230,8 +292,13 @@ var en_US_default = {
|
|
|
230
292
|
NEGATABLE: "Negatable of",
|
|
231
293
|
DEFAULT: "default",
|
|
232
294
|
CHOICES: "choices",
|
|
295
|
+
CAUSEDBY: "Caused by",
|
|
233
296
|
help: "Display this help message",
|
|
234
297
|
version: "Display this version",
|
|
298
|
+
json: "Output the result as JSON",
|
|
299
|
+
"json:invalid-arguments": "{$count} arguments are invalid",
|
|
300
|
+
"json:next:help": "See the arguments of the command",
|
|
301
|
+
"json:next:help-placeholder": "Replace <COMMAND> with how you ran this CLI, to see the arguments of the command",
|
|
235
302
|
"err:arg:required-option": "Option {$displayName} is required",
|
|
236
303
|
"err:arg:required-positional": "Positional argument {$displayName} is required",
|
|
237
304
|
"err:arg:invalid-type": "Invalid value for {$displayName}: expected {$expected}",
|
|
@@ -247,6 +314,9 @@ var en_US_default = {
|
|
|
247
314
|
"err:cmd:ambiguous": "The command is ambiguous. Move options after the command name: {$candidatePaths}",
|
|
248
315
|
"err:cmd:inconsistent-options": "The options do not identify a consistent command. Move options after the command name.",
|
|
249
316
|
"err:cmd:lazy-schema-mismatch": "The lazy command definition does not match its loaded options. Declare leading options in the lazy definition or move options after the command name: {$commandPath}",
|
|
317
|
+
"err:json:not-supported": "This command does not support --json",
|
|
318
|
+
"err:json:invalid-result": "The command finished, but did not return an object to output as JSON. A plugin that decorates the command may have dropped its result",
|
|
319
|
+
"err:json:unserializable-result": "The command finished, but its result cannot be converted to JSON: {$message}",
|
|
250
320
|
"err:suggestion:did-you-mean": "Did you mean {$name}?"
|
|
251
321
|
};
|
|
252
322
|
//#endregion
|
|
@@ -458,6 +528,402 @@ function formatResource(resource, values = Object.create(null)) {
|
|
|
458
528
|
return values[name] == null ? "" : String(values[name]);
|
|
459
529
|
});
|
|
460
530
|
}
|
|
531
|
+
/**
|
|
532
|
+
* forked from `nodejs/node` (`pkgjs/parseargs`)
|
|
533
|
+
* repository url: https://github.com/nodejs/node (https://github.com/pkgjs/parseargs)
|
|
534
|
+
* code url: https://github.com/nodejs/node/blob/main/lib/internal/util/parse_args/parse_args.js
|
|
535
|
+
*
|
|
536
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
537
|
+
* @license MIT
|
|
538
|
+
*/
|
|
539
|
+
"-".codePointAt(0);
|
|
540
|
+
"=".codePointAt(0);
|
|
541
|
+
//#endregion
|
|
542
|
+
//#region ../../node_modules/.pnpm/args-tokens@1.0.2/node_modules/args-tokens/lib/resolver-Cx5Pw6-S.js
|
|
543
|
+
/**
|
|
544
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
545
|
+
* @license MIT
|
|
546
|
+
*/
|
|
547
|
+
/**
|
|
548
|
+
* Entry point of argument options resolver.
|
|
549
|
+
*
|
|
550
|
+
* @module
|
|
551
|
+
*/
|
|
552
|
+
/**
|
|
553
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
554
|
+
* @license MIT
|
|
555
|
+
*/
|
|
556
|
+
/**
|
|
557
|
+
* Machine-readable error codes for {@link ArgsValidationError}.
|
|
558
|
+
*
|
|
559
|
+
* Each code identifies a validation failure category and is also suitable as an
|
|
560
|
+
* i18n resource key for localized rendering.
|
|
561
|
+
*
|
|
562
|
+
* {@link resolveArgs} and `parse()` do not report `unknownOption`. An option that is not in the
|
|
563
|
+
* schema takes the argument after it as its value, unless that argument is an option, and the value
|
|
564
|
+
* is dropped: with no `foo` in the schema, `--foo bar` gives no positional argument.
|
|
565
|
+
*/
|
|
566
|
+
const ArgsValidationErrorKeys = {
|
|
567
|
+
requiredOption: "err:arg:required-option",
|
|
568
|
+
requiredPositional: "err:arg:required-positional",
|
|
569
|
+
invalidType: "err:arg:invalid-type",
|
|
570
|
+
invalidChoice: "err:arg:invalid-choice",
|
|
571
|
+
customParse: "err:arg:custom-parse",
|
|
572
|
+
unknownOption: "err:arg:unknown-option",
|
|
573
|
+
unexpectedValue: "err:arg:unexpected-value",
|
|
574
|
+
missingValue: "err:arg:missing-value",
|
|
575
|
+
conflict: "err:arg:conflict",
|
|
576
|
+
invalidDefault: "err:arg:invalid-default"
|
|
577
|
+
};
|
|
578
|
+
/**
|
|
579
|
+
* Brand that marks {@link ArgsValidationError} instances.
|
|
580
|
+
*
|
|
581
|
+
* The brand is looked up in the global symbol registry with `Symbol.for`, so it stays
|
|
582
|
+
* identical across bundled copies of this module and across realms. It lets
|
|
583
|
+
* {@link isArgsValidationError} recognize errors created by another copy of `args-tokens`,
|
|
584
|
+
* where `instanceof` cannot match.
|
|
585
|
+
*/
|
|
586
|
+
const ARGS_VALIDATION_ERROR_BRAND = Symbol.for("args-tokens.ArgsValidationError");
|
|
587
|
+
/**
|
|
588
|
+
* An error that contains structured metadata for argument validation failures.
|
|
589
|
+
*
|
|
590
|
+
* The `message` remains the English fallback message. Renderers can use `code`
|
|
591
|
+
* and `values` to localize the error, falling back to `message` when localization
|
|
592
|
+
* is unavailable.
|
|
593
|
+
*
|
|
594
|
+
* Each instance carries a non-enumerable brand keyed by
|
|
595
|
+
* `Symbol.for('args-tokens.ArgsValidationError')`, which {@link isArgsValidationError}
|
|
596
|
+
* uses to recognize instances created by another bundled copy of `args-tokens`.
|
|
597
|
+
*/
|
|
598
|
+
var ArgsValidationError = class extends Error {
|
|
599
|
+
/**
|
|
600
|
+
* Machine-readable error code for this validation failure.
|
|
601
|
+
*
|
|
602
|
+
* This code can also be used as an i18n resource key.
|
|
603
|
+
*/
|
|
604
|
+
code;
|
|
605
|
+
/**
|
|
606
|
+
* Interpolation values for `code`.
|
|
607
|
+
*/
|
|
608
|
+
values;
|
|
609
|
+
/**
|
|
610
|
+
* Create an `ArgsValidationError` instance.
|
|
611
|
+
*
|
|
612
|
+
* @param message - fallback error message
|
|
613
|
+
* @param options - structured validation metadata
|
|
614
|
+
*/
|
|
615
|
+
constructor(message, options = {}) {
|
|
616
|
+
super(message, { cause: options.cause });
|
|
617
|
+
this.name = "ArgsValidationError";
|
|
618
|
+
this.code = options.code;
|
|
619
|
+
this.values = options.values ?? {};
|
|
620
|
+
Object.defineProperty(this, ARGS_VALIDATION_ERROR_BRAND, {
|
|
621
|
+
value: true,
|
|
622
|
+
enumerable: false,
|
|
623
|
+
writable: false,
|
|
624
|
+
configurable: false
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
/**
|
|
629
|
+
* Check whether the given value is an {@link ArgsValidationError}.
|
|
630
|
+
*
|
|
631
|
+
* This guard also recognizes errors created by another bundled copy of `args-tokens`
|
|
632
|
+
* (0.29.0 or later), where `instanceof` does not match. Such an error must have an own brand
|
|
633
|
+
* keyed by `Symbol.for('args-tokens.ArgsValidationError')` set to `true`, and a `values` object.
|
|
634
|
+
* The guard does not rely on `error.name`, so subclasses such as {@link ArgResolveError} that
|
|
635
|
+
* override `name` are still recognized.
|
|
636
|
+
*
|
|
637
|
+
* The guard narrows to `ArgsValidationError` only. Across bundled copies,
|
|
638
|
+
* `instanceof ArgResolveError` still does not match.
|
|
639
|
+
*
|
|
640
|
+
* @param error - value to check
|
|
641
|
+
* @returns `true` when the value is an `ArgsValidationError`
|
|
642
|
+
*/
|
|
643
|
+
function isArgsValidationError$1(error) {
|
|
644
|
+
if (error instanceof ArgsValidationError) return true;
|
|
645
|
+
if (typeof error !== "object" || error === null) return false;
|
|
646
|
+
if (!Object.hasOwn(error, ARGS_VALIDATION_ERROR_BRAND) || error[ARGS_VALIDATION_ERROR_BRAND] !== true) return false;
|
|
647
|
+
const values = error.values;
|
|
648
|
+
return typeof values === "object" && values !== null;
|
|
649
|
+
}
|
|
650
|
+
//#endregion
|
|
651
|
+
//#region ../../node_modules/.pnpm/args-tokens@1.0.2/node_modules/args-tokens/lib/index.js
|
|
652
|
+
/**
|
|
653
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
654
|
+
* @license MIT
|
|
655
|
+
*/
|
|
656
|
+
/**
|
|
657
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
658
|
+
* @license MIT
|
|
659
|
+
*/
|
|
660
|
+
//#endregion
|
|
661
|
+
//#region ../gunshi/src/error.ts
|
|
662
|
+
/**
|
|
663
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
664
|
+
* @license MIT
|
|
665
|
+
*/
|
|
666
|
+
/**
|
|
667
|
+
* Brand that marks {@link CommandNotFoundError} instances.
|
|
668
|
+
*
|
|
669
|
+
* The brand is looked up in the global symbol registry with `Symbol.for`, so it stays
|
|
670
|
+
* identical across bundled copies of gunshi (`gunshi`, `@gunshi/plugin`, `@gunshi/bone`)
|
|
671
|
+
* and across realms. It lets {@link isCommandNotFoundError} recognize errors created by
|
|
672
|
+
* another copy, where `instanceof` cannot match.
|
|
673
|
+
*/
|
|
674
|
+
const COMMAND_NOT_FOUND_ERROR_BRAND = Symbol.for("gunshi.CommandNotFoundError");
|
|
675
|
+
const COMMAND_RESOLUTION_ERROR_BRAND = Symbol.for("gunshi.CommandResolutionError");
|
|
676
|
+
/**
|
|
677
|
+
* Error raised when a command cannot be resolved.
|
|
678
|
+
*
|
|
679
|
+
* Each instance carries a non-enumerable brand keyed by
|
|
680
|
+
* `Symbol.for('gunshi.CommandNotFoundError')`, so that {@link isCommandNotFoundError}
|
|
681
|
+
* recognizes it even when it was created by another bundled copy of gunshi.
|
|
682
|
+
*/
|
|
683
|
+
var CommandNotFoundError = class extends Error {
|
|
684
|
+
code;
|
|
685
|
+
values;
|
|
686
|
+
commandName;
|
|
687
|
+
candidates;
|
|
688
|
+
commandPath;
|
|
689
|
+
/**
|
|
690
|
+
* Create a command-not-found error.
|
|
691
|
+
*
|
|
692
|
+
* @param message - Fallback error message
|
|
693
|
+
* @param options - Command-not-found metadata
|
|
694
|
+
*/
|
|
695
|
+
constructor(message, options) {
|
|
696
|
+
super(message, { cause: options.cause });
|
|
697
|
+
this.name = "CommandNotFoundError";
|
|
698
|
+
this.code = options.code;
|
|
699
|
+
this.values = options.values || {};
|
|
700
|
+
this.commandName = options.commandName;
|
|
701
|
+
this.candidates = options.candidates || [];
|
|
702
|
+
this.commandPath = options.commandPath || [];
|
|
703
|
+
Object.defineProperty(this, COMMAND_NOT_FOUND_ERROR_BRAND, {
|
|
704
|
+
value: true,
|
|
705
|
+
enumerable: false,
|
|
706
|
+
writable: false,
|
|
707
|
+
configurable: false
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
/**
|
|
712
|
+
* Error raised when command routing cannot produce one consistent command.
|
|
713
|
+
*
|
|
714
|
+
* The own registry brand is the cross-bundle contract. Unlike the legacy command-not-found
|
|
715
|
+
* guard, the new guard deliberately has no name-based fallback because this error type is new and
|
|
716
|
+
* must not classify arbitrary errors from older versions.
|
|
717
|
+
*/
|
|
718
|
+
var CommandResolutionError = class extends Error {
|
|
719
|
+
code;
|
|
720
|
+
values;
|
|
721
|
+
commandPath;
|
|
722
|
+
candidatePaths;
|
|
723
|
+
/**
|
|
724
|
+
* Create a command resolution error with structured routing metadata.
|
|
725
|
+
*
|
|
726
|
+
* @param message - Human-readable fallback message
|
|
727
|
+
* @param options - Error code and command-routing metadata
|
|
728
|
+
*/
|
|
729
|
+
constructor(message, options = {}) {
|
|
730
|
+
super(message, { cause: options.cause });
|
|
731
|
+
this.name = "CommandResolutionError";
|
|
732
|
+
this.code = options.code;
|
|
733
|
+
this.values = options.values || {};
|
|
734
|
+
this.commandPath = options.commandPath || [];
|
|
735
|
+
this.candidatePaths = options.candidatePaths || [];
|
|
736
|
+
Object.defineProperty(this, COMMAND_RESOLUTION_ERROR_BRAND, {
|
|
737
|
+
value: true,
|
|
738
|
+
enumerable: false,
|
|
739
|
+
writable: false,
|
|
740
|
+
configurable: false
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
/**
|
|
745
|
+
* Check whether an error is a {@link CommandNotFoundError}.
|
|
746
|
+
*
|
|
747
|
+
* `instanceof` alone is not enough: `@gunshi/plugin` is bundled with its own copy of this
|
|
748
|
+
* class (`noExternal: ['gunshi/plugin']`), so an error thrown by `gunshi` is never an instance
|
|
749
|
+
* of the class a plugin imports. Errors from another copy are recognized through the
|
|
750
|
+
* `Symbol.for('gunshi.CommandNotFoundError')` brand, which does not depend on `error.name`.
|
|
751
|
+
*
|
|
752
|
+
* @param error - An unknown error
|
|
753
|
+
* @returns `true` if the error is a {@link CommandNotFoundError}
|
|
754
|
+
*/
|
|
755
|
+
function isCommandNotFoundError(error) {
|
|
756
|
+
if (error instanceof CommandNotFoundError) return true;
|
|
757
|
+
if (!isRecord(error) || !hasCommandNotFoundErrorShape(error)) return false;
|
|
758
|
+
if (Object.hasOwn(error, COMMAND_NOT_FOUND_ERROR_BRAND) && error[COMMAND_NOT_FOUND_ERROR_BRAND] === true) return true;
|
|
759
|
+
return error instanceof Error && error.name === "CommandNotFoundError";
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Check whether an error is a {@link CommandResolutionError}.
|
|
763
|
+
*
|
|
764
|
+
* @param error - An unknown error
|
|
765
|
+
* @returns `true` when the error has the command-resolution brand and shape
|
|
766
|
+
*/
|
|
767
|
+
function isCommandResolutionError(error) {
|
|
768
|
+
if (error instanceof CommandResolutionError) return true;
|
|
769
|
+
if (!isRecord(error) || !hasCommandResolutionErrorShape(error)) return false;
|
|
770
|
+
return Object.hasOwn(error, COMMAND_RESOLUTION_ERROR_BRAND) && error[COMMAND_RESOLUTION_ERROR_BRAND] === true;
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* Check whether an error is an {@link ArgsValidationError}.
|
|
774
|
+
*
|
|
775
|
+
* Prefer this over the `args-tokens` guard of the same name. Both recognize errors from another
|
|
776
|
+
* bundled copy through the `Symbol.for('args-tokens.ArgsValidationError')` brand that
|
|
777
|
+
* `args-tokens` 0.29.0 or later sets, including subclasses such as `ArgResolveError` that
|
|
778
|
+
* override `name` with the argument name. This guard additionally:
|
|
779
|
+
*
|
|
780
|
+
* - recognizes direct `ArgsValidationError` instances from copies bundling `args-tokens`
|
|
781
|
+
* older than 0.29.0, which do not set the brand
|
|
782
|
+
* - checks that `code` and `values` of an error from another copy have the expected types
|
|
783
|
+
*
|
|
784
|
+
* The guard narrows only to {@link ArgsValidationError}: across copies,
|
|
785
|
+
* `instanceof ArgResolveError` still fails, so do not rely on `type` or `schema` for such errors.
|
|
786
|
+
*
|
|
787
|
+
* @param error - An unknown error
|
|
788
|
+
* @returns `true` if the error is an {@link ArgsValidationError}
|
|
789
|
+
*/
|
|
790
|
+
function isArgsValidationError(error) {
|
|
791
|
+
if (error instanceof ArgsValidationError) return true;
|
|
792
|
+
if (!isRecord(error) || !hasArgsValidationErrorShape(error)) return false;
|
|
793
|
+
if (isArgsValidationError$1(error)) return true;
|
|
794
|
+
return error instanceof Error && error.name === "ArgsValidationError";
|
|
795
|
+
}
|
|
796
|
+
function isRecord(value) {
|
|
797
|
+
return typeof value === "object" && value !== null;
|
|
798
|
+
}
|
|
799
|
+
function isStringArray(value) {
|
|
800
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Check whether `code` is an own or inherited property that is a string or `undefined`.
|
|
804
|
+
*
|
|
805
|
+
* Constructors always assign `code`, even when the option is omitted.
|
|
806
|
+
*
|
|
807
|
+
* @param error - An error from another copy
|
|
808
|
+
* @returns `true` if `code` has the expected type
|
|
809
|
+
*/
|
|
810
|
+
function hasOptionalStringCode(error) {
|
|
811
|
+
return "code" in error && (error.code === void 0 || typeof error.code === "string");
|
|
812
|
+
}
|
|
813
|
+
function hasCommandNotFoundErrorShape(error) {
|
|
814
|
+
return hasOptionalStringCode(error) && isRecord(error.values) && typeof error.commandName === "string" && isStringArray(error.candidates) && isStringArray(error.commandPath);
|
|
815
|
+
}
|
|
816
|
+
function hasCommandResolutionErrorShape(error) {
|
|
817
|
+
return hasOptionalStringCode(error) && isRecord(error.values) && isStringArray(error.commandPath) && Array.isArray(error.candidatePaths) && error.candidatePaths.every((path) => isStringArray(path));
|
|
818
|
+
}
|
|
819
|
+
function hasArgsValidationErrorShape(error) {
|
|
820
|
+
return hasOptionalStringCode(error) && isRecord(error.values);
|
|
821
|
+
}
|
|
822
|
+
//#endregion
|
|
823
|
+
//#region ../gunshi/src/plugin.ts
|
|
824
|
+
/**
|
|
825
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
826
|
+
* @license MIT
|
|
827
|
+
*/
|
|
828
|
+
//#endregion
|
|
829
|
+
//#region ../plugin/src/index.ts
|
|
830
|
+
/**
|
|
831
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
832
|
+
* @license MIT
|
|
833
|
+
*/
|
|
834
|
+
//#endregion
|
|
835
|
+
//#region src/validation.ts
|
|
836
|
+
/**
|
|
837
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
838
|
+
* @license MIT
|
|
839
|
+
*/
|
|
840
|
+
const i18nPluginId = namespacedId("i18n");
|
|
841
|
+
const missingValueHintKey = "err:arg:missing-value:hint";
|
|
842
|
+
/**
|
|
843
|
+
* Localize the message of a validation error, as gunshi shows it to the user: with the i18n plugin when
|
|
844
|
+
* it is installed, and otherwise the message of the error.
|
|
845
|
+
*
|
|
846
|
+
* NOTE(kazupon): the renderer plugin renders the validation errors for people, and the global options
|
|
847
|
+
* plugin prints them as JSON with `--json`. Both take the messages from here, so that a message is the
|
|
848
|
+
* same in both.
|
|
849
|
+
*
|
|
850
|
+
* @param ctx - A {@link CommandContext | command context}
|
|
851
|
+
* @param error - A validation error: an {@link ArgsValidationError}, a command-not-found error, or a
|
|
852
|
+
* command-resolution error
|
|
853
|
+
* @returns The localized message
|
|
854
|
+
*/
|
|
855
|
+
async function localizeValidationError(ctx, error) {
|
|
856
|
+
if (isCommandNotFoundError(error) && error.code) {
|
|
857
|
+
const message = await localize(ctx, error.code, error.values);
|
|
858
|
+
if (message && message !== error.code) return message;
|
|
859
|
+
}
|
|
860
|
+
if (isCommandResolutionError(error) && error.code) {
|
|
861
|
+
const message = await localize(ctx, error.code, error.values);
|
|
862
|
+
if (message && message !== error.code) return message;
|
|
863
|
+
}
|
|
864
|
+
if (isArgsValidationError(error) && error.code) {
|
|
865
|
+
const values = await resolveValidationValues(ctx, error);
|
|
866
|
+
const message = await localize(ctx, error.code, values);
|
|
867
|
+
if (message && message !== error.code) {
|
|
868
|
+
const hint = await localizeHint(ctx, error, values);
|
|
869
|
+
return hint ? `${message} ${hint}` : message;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
return error.message;
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Localize a text of the built-in resources: with the i18n plugin when it is installed and knows the key,
|
|
876
|
+
* and otherwise the English one.
|
|
877
|
+
*
|
|
878
|
+
* @param ctx - A {@link CommandContext | command context}
|
|
879
|
+
* @param key - The key of the text: `_:<key>` for a text that is not an error, and the key itself for an
|
|
880
|
+
* error, such as `err:json:not-supported`
|
|
881
|
+
* @param values - The values of the placeholders of the text
|
|
882
|
+
* @returns The localized text, or the key when no resource has it
|
|
883
|
+
*/
|
|
884
|
+
async function localizeBuiltinResource(ctx, key, values) {
|
|
885
|
+
const message = await localize(ctx, key, values);
|
|
886
|
+
if (message && message !== key) return message;
|
|
887
|
+
return formatResource(en_US_default[key.startsWith(BUILD_IN_PREFIX_AND_KEY_SEPARATOR) ? key.slice(BUILD_IN_PREFIX_AND_KEY_SEPARATOR.length) : key], values) || key;
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Localize the hint that args-tokens adds to the message of an error.
|
|
891
|
+
*
|
|
892
|
+
* A translation replaces the whole message, hint included, so the hint is translated by a key of
|
|
893
|
+
* its own and follows the translated error. args-tokens gives one today: for an option given without
|
|
894
|
+
* a value, when the argument after it may be the value, the long form with `=` (`--port=-5` for
|
|
895
|
+
* `--port -5`), in `values.next` and `values.suggestion`.
|
|
896
|
+
*
|
|
897
|
+
* @param ctx - A {@link CommandContext | command context}
|
|
898
|
+
* @param error - An args validation error
|
|
899
|
+
* @param values - The values of the error, as given to its translation
|
|
900
|
+
* @returns The localized hint, or `undefined` when the error has none.
|
|
901
|
+
*/
|
|
902
|
+
async function localizeHint(ctx, error, values) {
|
|
903
|
+
if (error.code !== ArgsValidationErrorKeys.missingValue || typeof values.next !== "string" || typeof values.suggestion !== "string") return;
|
|
904
|
+
const hint = await localize(ctx, missingValueHintKey, values);
|
|
905
|
+
return hint && hint !== missingValueHintKey ? hint : void 0;
|
|
906
|
+
}
|
|
907
|
+
async function resolveValidationValues(ctx, error) {
|
|
908
|
+
if (error.code !== ArgsValidationErrorKeys.customParse) return error.values;
|
|
909
|
+
const { reasonKey, reasonValues } = error.values;
|
|
910
|
+
if (typeof reasonKey !== "string") return error.values;
|
|
911
|
+
const key = resolveKey(reasonKey, ctx.name);
|
|
912
|
+
const localizedReason = await localize(ctx, key, toRecord(reasonValues));
|
|
913
|
+
if (!localizedReason || localizedReason === key) return error.values;
|
|
914
|
+
return {
|
|
915
|
+
...error.values,
|
|
916
|
+
reason: localizedReason
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
async function localize(ctx, key, values) {
|
|
920
|
+
const i18n = ctx.extensions?.[i18nPluginId];
|
|
921
|
+
if (i18n?.translate) return i18n.translate(key, values);
|
|
922
|
+
return key;
|
|
923
|
+
}
|
|
924
|
+
function toRecord(value) {
|
|
925
|
+
return value != null && typeof value === "object" ? value : Object.create(null);
|
|
926
|
+
}
|
|
461
927
|
//#endregion
|
|
462
928
|
//#region src/index.ts
|
|
463
929
|
/**
|
|
@@ -465,4 +931,4 @@ function formatResource(resource, values = Object.create(null)) {
|
|
|
465
931
|
* @license MIT
|
|
466
932
|
*/
|
|
467
933
|
//#endregion
|
|
468
|
-
export { ARG_ERROR_HINT_RESOURCE_KEYS, ARG_ERROR_RESOURCE_KEYS, ARG_NEGATABLE_PREFIX, ARG_PREFIX, ARG_PREFIX_AND_KEY_SEPARATOR, BUILD_IN_PREFIX_AND_KEY_SEPARATOR, BUILT_IN_KEY_SEPARATOR, BUILT_IN_PREFIX, COMMAND_BUILTIN_RESOURCE_KEYS, COMMAND_ERROR_RESOURCE_KEYS, COMMON_ARGS, en_US_default as DefaultResource, ERROR_PREFIX, ERROR_PREFIX_AND_KEY_SEPARATOR, PLUGIN_PREFIX, SUGGESTION_ERROR_RESOURCE_KEYS, create, deepFreeze, formatResource, getCommandSubCommands, isLazyCommand, kebabnize, localizable, log, makeShortLongOptionPair, namespacedId, resolveArgKey, resolveBuiltInKey, resolveCommandArgs, resolveDisplayName, resolveExamples, resolveKey, resolveLazyCommand, resolveOptionNames };
|
|
934
|
+
export { ARG_ERROR_HINT_RESOURCE_KEYS, ARG_ERROR_RESOURCE_KEYS, ARG_NEGATABLE_PREFIX, ARG_PREFIX, ARG_PREFIX_AND_KEY_SEPARATOR, BUILD_IN_PREFIX_AND_KEY_SEPARATOR, BUILT_IN_KEY_SEPARATOR, BUILT_IN_PREFIX, COMMAND_BUILTIN_RESOURCE_KEYS, COMMAND_ERROR_RESOURCE_KEYS, COMMON_ARGS, en_US_default as DefaultResource, ERROR_PREFIX, ERROR_PREFIX_AND_KEY_SEPARATOR, JSON_ERROR_RESOURCE_KEYS, JSON_RESOURCE_KEYS, PLUGIN_PREFIX, SUGGESTION_ERROR_RESOURCE_KEYS, create, deepFreeze, formatResource, getCommandSubCommands, isJsonArg, isLazyCommand, kebabnize, localizable, localizeBuiltinResource, localizeValidationError, log, makeShortLongOptionPair, namespacedId, resolveArgKey, resolveBuiltInKey, resolveCommandArgs, resolveDisplayName, resolveExamples, resolveJsonRequest, resolveKey, resolveLazyCommand, resolveOptionNames };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gunshi/shared",
|
|
3
3
|
"description": "shared utils for gunshi",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.6",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "kazuya kawaguchi",
|
|
7
7
|
"email": "kawakazu80@gmail.com"
|
|
@@ -50,8 +50,9 @@
|
|
|
50
50
|
}
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@gunshi/
|
|
54
|
-
"gunshi": "1.0.0-rc.
|
|
53
|
+
"@gunshi/plugin": "1.0.0-rc.6",
|
|
54
|
+
"@gunshi/resources": "1.0.0-rc.6",
|
|
55
|
+
"gunshi": "1.0.0-rc.6",
|
|
55
56
|
"publint": "^0.3.20",
|
|
56
57
|
"tsdown": "0.22.14"
|
|
57
58
|
},
|