@gunshi/plugin 1.0.0-rc.4 → 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/README.md +0 -3
- package/lib/index.d.ts +249 -29
- package/lib/index.js +221 -4
- package/package.json +3 -8
package/README.md
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
[![Version][npm-version-src]][npm-version-href]
|
|
4
4
|
[![InstallSize][install-size-src]][install-size-src]
|
|
5
|
-
[![JSR][jsr-src]][jsr-href]
|
|
6
5
|
|
|
7
6
|
> plugin development kit for gunshi
|
|
8
7
|
|
|
@@ -26,6 +25,4 @@ About details, See [the plugin development guides](https://gunshi.dev/guide/plug
|
|
|
26
25
|
|
|
27
26
|
[npm-version-src]: https://img.shields.io/npm/v/@gunshi/plugin?style=flat
|
|
28
27
|
[npm-version-href]: https://npmjs.com/package/@gunshi/plugin@alpha
|
|
29
|
-
[jsr-src]: https://jsr.io/badges/@gunshi/plugin
|
|
30
|
-
[jsr-href]: https://jsr.io/@gunshi/plugin
|
|
31
28
|
[install-size-src]: https://pkg-size.dev/badge/install/27672
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
//#region ../../node_modules/.pnpm/args-tokens@1.0.
|
|
2
|
-
//#region src/parser.d.ts
|
|
1
|
+
//#region ../../node_modules/.pnpm/args-tokens@1.0.2/node_modules/args-tokens/lib/parser-DvPxBZG9.d.ts
|
|
3
2
|
/**
|
|
4
3
|
* Entry point of argument parser.
|
|
5
4
|
*
|
|
@@ -56,8 +55,7 @@ interface ArgToken {
|
|
|
56
55
|
inlineValue?: boolean | undefined;
|
|
57
56
|
}
|
|
58
57
|
//#endregion
|
|
59
|
-
//#region ../../node_modules/.pnpm/args-tokens@1.0.
|
|
60
|
-
//#region src/resolver.d.ts
|
|
58
|
+
//#region ../../node_modules/.pnpm/args-tokens@1.0.2/node_modules/args-tokens/lib/resolver.d.ts
|
|
61
59
|
/**
|
|
62
60
|
* An argument schema definition for command-line argument parsing.
|
|
63
61
|
*
|
|
@@ -419,9 +417,9 @@ interface ArgSchema {
|
|
|
419
417
|
*/
|
|
420
418
|
toKebab?: true;
|
|
421
419
|
/**
|
|
422
|
-
* Names of other
|
|
420
|
+
* Names of other arguments that conflict with this argument.
|
|
423
421
|
*
|
|
424
|
-
* When this
|
|
422
|
+
* When this argument is used together with any of the conflicting arguments, the error is an
|
|
425
423
|
* `ArgResolveError` with type 'conflict' and the code `err:arg:conflict`
|
|
426
424
|
* ({@link ArgsValidationErrorKeys}.conflict). Its `values` has the `displayName` and `name` of
|
|
427
425
|
* the argument whose `conflicts` names the other one, and the `conflictDisplayName` and
|
|
@@ -431,9 +429,8 @@ interface ArgSchema {
|
|
|
431
429
|
*
|
|
432
430
|
* A positional argument can be on either side, such as `[file]` and `--stdin`. It conflicts when
|
|
433
431
|
* it is given, and it is shown by its name, such as `'file'` (in kebab-case with `toKebab`), as
|
|
434
|
-
* in its other errors. The message
|
|
435
|
-
* `
|
|
436
|
-
* `Optional argument '--stdin' conflicts with 'file'`.
|
|
432
|
+
* in its other errors. The message names the argument given as `name` first:
|
|
433
|
+
* `'file' conflicts with '--stdin'` or `'--stdin' conflicts with 'file'`.
|
|
437
434
|
*
|
|
438
435
|
* Conflicts only need to be defined on one side - if option A defines a conflict
|
|
439
436
|
* with option B, the conflict is automatically detected when both are used,
|
|
@@ -472,7 +469,7 @@ interface ArgSchema {
|
|
|
472
469
|
* }
|
|
473
470
|
* }
|
|
474
471
|
* // Usage: --summer --autumn reports an error
|
|
475
|
-
* // Error: "
|
|
472
|
+
* // Error: "'--summer' conflicts with '--autumn'"
|
|
476
473
|
* ```
|
|
477
474
|
*
|
|
478
475
|
* @example
|
|
@@ -512,7 +509,7 @@ interface ArgSchema {
|
|
|
512
509
|
* toKebab: true // Accessible as --autumn-season
|
|
513
510
|
* }
|
|
514
511
|
* }
|
|
515
|
-
* // Error: "
|
|
512
|
+
* // Error: "'--summer-season' conflicts with '--autumn-season'"
|
|
516
513
|
* ```
|
|
517
514
|
*/
|
|
518
515
|
conflicts?: string | string[];
|
|
@@ -796,7 +793,7 @@ interface PluginContext<G extends GunshiParamsConstraint = DefaultGunshiParams>
|
|
|
796
793
|
* @param name - Command name
|
|
797
794
|
* @param command - Command definition
|
|
798
795
|
*/
|
|
799
|
-
addCommand(name: string, command:
|
|
796
|
+
addCommand(name: string, command: SubCommandable): void;
|
|
800
797
|
/**
|
|
801
798
|
* Check if a command exists.
|
|
802
799
|
*
|
|
@@ -837,7 +834,7 @@ interface PluginContext<G extends GunshiParamsConstraint = DefaultGunshiParams>
|
|
|
837
834
|
*
|
|
838
835
|
* @param decorator - A decorator function that wraps the command runner
|
|
839
836
|
*/
|
|
840
|
-
decorateCommand<L extends Record<string, unknown> = DefaultGunshiParams['extensions']>(decorator: (baseRunner: (ctx: Readonly<CommandContext<MergeGunshiExtensions<G, L>>>) => Awaitable<void | string>) => (ctx: Readonly<CommandContext<MergeGunshiExtensions<G, L>>>) => Awaitable<void | string>): void;
|
|
837
|
+
decorateCommand<L extends Record<string, unknown> = DefaultGunshiParams['extensions']>(decorator: (baseRunner: (ctx: Readonly<CommandContext<MergeGunshiExtensions<G, L>>>) => Awaitable<void | string | JsonResult>) => (ctx: Readonly<CommandContext<MergeGunshiExtensions<G, L>>>) => Awaitable<void | string | JsonResult>): void;
|
|
841
838
|
}
|
|
842
839
|
//#endregion
|
|
843
840
|
//#region ../gunshi/src/plugin/core.d.ts
|
|
@@ -1274,7 +1271,11 @@ interface CommandEnvironment<G extends GunshiParamsConstraint = DefaultGunshiPar
|
|
|
1274
1271
|
* (they are still returned as strings) and to silence {@linkcode CommandContext.log}.
|
|
1275
1272
|
*
|
|
1276
1273
|
* Output that must still appear — machine-readable results for an agent, warnings for the
|
|
1277
|
-
* CLI author — should use `console.log` / `console.warn`, not `ctx.log`.
|
|
1274
|
+
* CLI author — should use `console.log` / `console.warn`, not `ctx.log`. A command that spreads
|
|
1275
|
+
* `jsonArgs` and is given `--json` prints its result, and its errors, as JSON even with it.
|
|
1276
|
+
*
|
|
1277
|
+
* The validation errors, and a `CommandError` that the command throws, are not printed either, so
|
|
1278
|
+
* `cli()` rejects with them, for the caller to report them.
|
|
1278
1279
|
*
|
|
1279
1280
|
* @default false
|
|
1280
1281
|
* @see {@linkcode CliOptions.usageSilent}
|
|
@@ -1334,7 +1335,8 @@ interface CommandEnvironment<G extends GunshiParamsConstraint = DefaultGunshiPar
|
|
|
1334
1335
|
*/
|
|
1335
1336
|
onBeforeCommand: ((ctx: Readonly<CommandContext<G>>) => Awaitable<void>) | undefined;
|
|
1336
1337
|
/**
|
|
1337
|
-
* Hook that runs after successful command execution
|
|
1338
|
+
* Hook that runs after successful command execution. It receives the result of the command only
|
|
1339
|
+
* when it is a string.
|
|
1338
1340
|
*
|
|
1339
1341
|
* @see {@linkcode CliOptions.onAfterCommand}
|
|
1340
1342
|
* @since v0.27.0
|
|
@@ -1399,10 +1401,12 @@ interface CliOptions<G extends GunshiParamsConstraint = DefaultGunshiParams> {
|
|
|
1399
1401
|
* (they are still returned as strings) and to silence {@linkcode CommandContext.log}.
|
|
1400
1402
|
*
|
|
1401
1403
|
* Output that must still appear — machine-readable results for an agent, warnings for the
|
|
1402
|
-
* CLI author — should use `console.log` / `console.warn`, not `ctx.log`.
|
|
1404
|
+
* CLI author — should use `console.log` / `console.warn`, not `ctx.log`. A command that spreads
|
|
1405
|
+
* `jsonArgs` and is given `--json` prints its result, and its errors, as JSON even with it.
|
|
1403
1406
|
*
|
|
1404
|
-
* The validation errors
|
|
1405
|
-
* report them (see
|
|
1407
|
+
* The validation errors, and a `CommandError` that the command throws, are not printed either, so
|
|
1408
|
+
* `cli()` rejects with them, for the caller to report them (see
|
|
1409
|
+
* {@linkcode CliOptions.renderValidationErrors}). The exit code is left alone.
|
|
1406
1410
|
*
|
|
1407
1411
|
* @default false
|
|
1408
1412
|
*/
|
|
@@ -1414,6 +1418,10 @@ interface CliOptions<G extends GunshiParamsConstraint = DefaultGunshiParams> {
|
|
|
1414
1418
|
* arguments or installed global options are reported as validation errors
|
|
1415
1419
|
* before the command runner is executed.
|
|
1416
1420
|
*
|
|
1421
|
+
* `--json` is not reported, since gunshi knows what it means: given to a command that does not
|
|
1422
|
+
* spread `jsonArgs`, the global options plugin reports `json_not_supported` for it instead, with or
|
|
1423
|
+
* without `strict`. `--json=false` asks for no JSON, and is reported.
|
|
1424
|
+
*
|
|
1417
1425
|
* @default false
|
|
1418
1426
|
*/
|
|
1419
1427
|
strict?: boolean;
|
|
@@ -1433,6 +1441,9 @@ interface CliOptions<G extends GunshiParamsConstraint = DefaultGunshiParams> {
|
|
|
1433
1441
|
* Set it to `null` to report the validation errors yourself: nothing is printed, and `cli()` rejects
|
|
1434
1442
|
* with the `AggregateError`. A renderer that returns an empty message, and
|
|
1435
1443
|
* {@linkcode CliOptions.usageSilent}, also leave them to the caller.
|
|
1444
|
+
*
|
|
1445
|
+
* With `--json`, the plugin prints the validation errors as one line of JSON, and does not call
|
|
1446
|
+
* the renderer. `null` and {@linkcode CliOptions.usageSilent} still leave them to the caller.
|
|
1436
1447
|
*/
|
|
1437
1448
|
renderValidationErrors?: ((ctx: Readonly<CommandContext<G>>, error: AggregateError) => Promise<string>) | null;
|
|
1438
1449
|
/**
|
|
@@ -1459,15 +1470,17 @@ interface CliOptions<G extends GunshiParamsConstraint = DefaultGunshiParams> {
|
|
|
1459
1470
|
* Hook that runs after successful command execution
|
|
1460
1471
|
*
|
|
1461
1472
|
* @param ctx - The command context
|
|
1462
|
-
* @param result - The command
|
|
1473
|
+
* @param result - The result of the command, when it is a string. The result of a command that
|
|
1474
|
+
* prints JSON with `--json` is printed, not passed, so it is `undefined`
|
|
1463
1475
|
* @since v0.27.0
|
|
1464
1476
|
*/
|
|
1465
1477
|
onAfterCommand?: (ctx: Readonly<CommandContext<G>>, result: string | undefined) => Awaitable<void>;
|
|
1466
1478
|
/**
|
|
1467
1479
|
* Hook that runs when a command throws an error, or when the arguments fail validation
|
|
1468
1480
|
*
|
|
1469
|
-
* For the validation errors that the global options plugin has printed, the
|
|
1470
|
-
* when the hook runs
|
|
1481
|
+
* For the validation errors and a `CommandError` that the global options plugin has printed, the
|
|
1482
|
+
* exit code is already set when the hook runs (`1` for the validation errors, and the `exitCode` of
|
|
1483
|
+
* a `CommandError`), so the hook can set another one, and `cli()` resolves after it. Any other
|
|
1471
1484
|
* error rejects `cli()` after the hook.
|
|
1472
1485
|
*
|
|
1473
1486
|
* @param ctx - The command context
|
|
@@ -1567,9 +1580,11 @@ interface CommandContext<G extends GunshiParamsConstraint = DefaultGunshiParams>
|
|
|
1567
1580
|
*/
|
|
1568
1581
|
toKebab?: boolean;
|
|
1569
1582
|
/**
|
|
1570
|
-
* Output a message.
|
|
1583
|
+
* Output a message for people.
|
|
1571
1584
|
*
|
|
1572
|
-
* If {@linkcode CommandEnvironment.usageSilent} is true, the message is not output.
|
|
1585
|
+
* If {@linkcode CommandEnvironment.usageSilent} is true, the message is not output. Nor is it when a
|
|
1586
|
+
* command that spreads `jsonArgs` is asked for JSON with `--json`, so that stdout has the JSON only:
|
|
1587
|
+
* the hooks and the plugins get the same function.
|
|
1573
1588
|
*
|
|
1574
1589
|
* @param message - an output message, see {@linkcode console.log}
|
|
1575
1590
|
* @param optionalParams - an optional parameters, see {@linkcode console.log}
|
|
@@ -1813,14 +1828,49 @@ type CommandExamplesFetcher<G extends GunshiParamsConstraint = DefaultGunshiPara
|
|
|
1813
1828
|
* @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of command context.
|
|
1814
1829
|
*
|
|
1815
1830
|
* @param ctx - A {@link CommandContext | command context}
|
|
1816
|
-
* @returns
|
|
1831
|
+
* @returns The result of a command that spreads `jsonArgs`, an object keyed by a noun, which is printed
|
|
1832
|
+
* as JSON with `--json`. For any other command, a string, which `cli()` returns, or nothing. See
|
|
1833
|
+
* {@linkcode CommandRunnerResult}.
|
|
1834
|
+
*/
|
|
1835
|
+
type CommandRunner<G extends GunshiParamsConstraint = DefaultGunshiParams> = (ctx: Readonly<CommandContext<G>>) => CommandRunnerResult<G>;
|
|
1836
|
+
/**
|
|
1837
|
+
* The result of a command that supports `--json`: an object keyed by a noun, such as
|
|
1838
|
+
* `{ project }` or `{ projects }`, so that fields can be added later. The global options plugin prints
|
|
1839
|
+
* it with `JSON.stringify`, so convert what JSON cannot hold, such as a `Map` or a `BigInt`, yourself.
|
|
1840
|
+
*/
|
|
1841
|
+
type JsonResult = Record<string, unknown>;
|
|
1842
|
+
/**
|
|
1843
|
+
* Whether the arguments have the `json` of `jsonArgs`.
|
|
1844
|
+
*
|
|
1845
|
+
* @typeParam A - The arguments of a command
|
|
1846
|
+
*/
|
|
1847
|
+
type HasJsonArgs<A> = [A] extends [{
|
|
1848
|
+
readonly json: {
|
|
1849
|
+
readonly [JSON_ARG]: true;
|
|
1850
|
+
};
|
|
1851
|
+
}] ? true : false;
|
|
1852
|
+
/**
|
|
1853
|
+
* What the runner of a command returns: its result for a command that spreads `jsonArgs`, otherwise a string or
|
|
1854
|
+
* nothing.
|
|
1855
|
+
*
|
|
1856
|
+
* @typeParam G - A type extending {@linkcode GunshiParams}
|
|
1817
1857
|
*/
|
|
1818
|
-
type
|
|
1858
|
+
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>;
|
|
1859
|
+
/**
|
|
1860
|
+
* Whether the arguments are `any`, as in `CommandRunner<any>`. Then a runner may return anything it could before.
|
|
1861
|
+
*
|
|
1862
|
+
* @internal
|
|
1863
|
+
*/
|
|
1864
|
+
type IsAnyArgs<A> = 0 extends 1 & A ? true : false;
|
|
1819
1865
|
/**
|
|
1820
1866
|
* Command decorator.
|
|
1821
1867
|
*
|
|
1822
1868
|
* A function that wraps a command runner to add or modify its behavior.
|
|
1823
1869
|
*
|
|
1870
|
+
* The decorated runner returns what the base runner returns, as it is: the result of a command that
|
|
1871
|
+
* spreads `jsonArgs` must reach the global options plugin, which prints it as JSON with `--json`. A
|
|
1872
|
+
* decorator prints with `ctx.log`, which is silenced then.
|
|
1873
|
+
*
|
|
1824
1874
|
* @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of command context.
|
|
1825
1875
|
*
|
|
1826
1876
|
* @param baseRunner - The base command runner to decorate
|
|
@@ -1828,7 +1878,7 @@ type CommandRunner<G extends GunshiParamsConstraint = DefaultGunshiParams> = (ct
|
|
|
1828
1878
|
*
|
|
1829
1879
|
* @since v0.27.0
|
|
1830
1880
|
*/
|
|
1831
|
-
type CommandDecorator<G extends GunshiParamsConstraint = DefaultGunshiParams> = (baseRunner: (ctx: Readonly<CommandContext<G>>) => Awaitable<string | void>) => (ctx: Readonly<CommandContext<G>>) => Awaitable<string | void>;
|
|
1881
|
+
type CommandDecorator<G extends GunshiParamsConstraint = DefaultGunshiParams> = (baseRunner: (ctx: Readonly<CommandContext<G>>) => Awaitable<string | void | JsonResult>) => (ctx: Readonly<CommandContext<G>>) => Awaitable<string | void | JsonResult>;
|
|
1832
1882
|
/**
|
|
1833
1883
|
* Renderer decorator type.
|
|
1834
1884
|
*
|
|
@@ -1862,6 +1912,13 @@ type ValidationErrorsDecorator<G extends GunshiParamsConstraint = DefaultGunshiP
|
|
|
1862
1912
|
//#region ../gunshi/src/constants.d.ts
|
|
1863
1913
|
declare const ANONYMOUS_COMMAND_NAME = "(anonymous)";
|
|
1864
1914
|
declare const CLI_OPTIONS_DEFAULT: CliOptions<DefaultGunshiParams>;
|
|
1915
|
+
/**
|
|
1916
|
+
* The key of the mark on the `json` argument of `jsonArgs`. A string key, not a symbol: `gunshi` and the other
|
|
1917
|
+
* packages bundle their own copies of the types, and each copy of a `unique symbol` is a different type.
|
|
1918
|
+
*
|
|
1919
|
+
* @internal
|
|
1920
|
+
*/
|
|
1921
|
+
declare const JSON_ARG = "~gunshi.json-arg";
|
|
1865
1922
|
//#endregion
|
|
1866
1923
|
//#region ../gunshi/src/context.d.ts
|
|
1867
1924
|
/**
|
|
@@ -1886,7 +1943,7 @@ interface CommandContextParams<G extends GunshiParams | {
|
|
|
1886
1943
|
args: Args;
|
|
1887
1944
|
} | {
|
|
1888
1945
|
extensions: ExtendContext;
|
|
1889
|
-
}, V extends ArgValues<ExtractArgs<G>>, C extends Command<G> | LazyCommand<G> = Command<G>, E extends Record<string, CommandContextExtension> = Record<string, CommandContextExtension>> {
|
|
1946
|
+
}, V extends ArgValues<ExtractArgs<G>>, C extends Command<G> | LazyCommand<G> | SubCommandable = Command<G>, E extends Record<string, CommandContextExtension> = Record<string, CommandContextExtension>> {
|
|
1890
1947
|
/**
|
|
1891
1948
|
* An arguments of target command
|
|
1892
1949
|
*/
|
|
@@ -1950,7 +2007,7 @@ interface CommandContextParams<G extends GunshiParams | {
|
|
|
1950
2007
|
* @param param - A {@link CommandContextParams | parameters} to create a command context.
|
|
1951
2008
|
* @returns A {@link CommandContext | command context}, which is readonly.
|
|
1952
2009
|
*/
|
|
1953
|
-
declare function createCommandContext<G extends GunshiParamsConstraint = DefaultGunshiParams, V extends ArgValues<ExtractArgs<G>> = ArgValues<ExtractArgs<G>>, C extends Command<G> | LazyCommand<G> = Command<G>, E extends Record<string, CommandContextExtension> = {}>({ args, explicit, values, positionals, rest, argv, tokens, command, extensions, cliOptions, callMode, commandPath, omitted, validationError }: CommandContextParams<G, V, C, E>): Promise<CommandContextResult<G, E>>;
|
|
2010
|
+
declare function createCommandContext<G extends GunshiParamsConstraint = DefaultGunshiParams, V extends ArgValues<ExtractArgs<G>> = ArgValues<ExtractArgs<G>>, C extends Command<G> | LazyCommand<G> | SubCommandable = Command<G>, E extends Record<string, CommandContextExtension> = {}>({ args, explicit, values, positionals, rest, argv, tokens, command, extensions, cliOptions, callMode, commandPath, omitted, validationError }: CommandContextParams<G, V, C, E>): Promise<CommandContextResult<G, E>>;
|
|
1954
2011
|
//#endregion
|
|
1955
2012
|
//#region ../gunshi/src/error.d.ts
|
|
1956
2013
|
/**
|
|
@@ -1977,6 +2034,18 @@ declare const CommandResolutionErrorKeys: {
|
|
|
1977
2034
|
};
|
|
1978
2035
|
/** Command resolution error code. */
|
|
1979
2036
|
type CommandResolutionErrorCode = (typeof CommandResolutionErrorKeys)[keyof typeof CommandResolutionErrorKeys];
|
|
2037
|
+
/**
|
|
2038
|
+
* The resource keys of the errors of the JSON output, which are the codes of {@link JsonOutputError}.
|
|
2039
|
+
*/
|
|
2040
|
+
declare const JsonOutputErrorKeys: {
|
|
2041
|
+
readonly notSupported: "err:json:not-supported";
|
|
2042
|
+
readonly invalidResult: "err:json:invalid-result";
|
|
2043
|
+
readonly unserializableResult: "err:json:unserializable-result";
|
|
2044
|
+
};
|
|
2045
|
+
/**
|
|
2046
|
+
* The code of a {@link JsonOutputError}.
|
|
2047
|
+
*/
|
|
2048
|
+
type JsonOutputErrorCode = (typeof JsonOutputErrorKeys)[keyof typeof JsonOutputErrorKeys];
|
|
1980
2049
|
/**
|
|
1981
2050
|
* Options for {@link CommandNotFoundError}.
|
|
1982
2051
|
*/
|
|
@@ -2019,6 +2088,31 @@ type CommandResolutionErrorOptions = {
|
|
|
2019
2088
|
/** Underlying cause. */
|
|
2020
2089
|
cause?: unknown;
|
|
2021
2090
|
};
|
|
2091
|
+
/**
|
|
2092
|
+
* Options for {@link CommandError}. All of them are optional.
|
|
2093
|
+
*/
|
|
2094
|
+
type CommandErrorOptions = {
|
|
2095
|
+
/**
|
|
2096
|
+
* The name of the failure, for programs to read, such as `not_found`. snake_case is recommended.
|
|
2097
|
+
*
|
|
2098
|
+
* It is not printed to the user. With `--json`, it is the `reason` of the JSON error, as it is.
|
|
2099
|
+
*/
|
|
2100
|
+
code?: string;
|
|
2101
|
+
/**
|
|
2102
|
+
* The exit code of the process, an integer from 1 to 255. Defaults to 1, and any other value is
|
|
2103
|
+
* replaced with 1, since the command has failed.
|
|
2104
|
+
*/
|
|
2105
|
+
exitCode?: number;
|
|
2106
|
+
/**
|
|
2107
|
+
* The error that caused the failure.
|
|
2108
|
+
*
|
|
2109
|
+
* Its message is printed as is, on a `Caused by:` line after the message of the
|
|
2110
|
+
* {@link CommandError}, and so is the message of its own cause. With `--json`, the messages are in
|
|
2111
|
+
* `data.causes` of the JSON error. Do not pass an error whose message may contain a secret, such as
|
|
2112
|
+
* a token in a URL: write the message of the {@link CommandError} yourself instead.
|
|
2113
|
+
*/
|
|
2114
|
+
cause?: unknown;
|
|
2115
|
+
};
|
|
2022
2116
|
/**
|
|
2023
2117
|
* Error raised when a command cannot be resolved.
|
|
2024
2118
|
*
|
|
@@ -2060,6 +2154,62 @@ declare class CommandResolutionError extends Error {
|
|
|
2060
2154
|
*/
|
|
2061
2155
|
constructor(message: string, options?: CommandResolutionErrorOptions);
|
|
2062
2156
|
}
|
|
2157
|
+
/**
|
|
2158
|
+
* Error for a failure that a command expects, such as a project that does not exist.
|
|
2159
|
+
*
|
|
2160
|
+
* When a command throws it from `run`, or a plugin throws it from a command decorator, the global
|
|
2161
|
+
* options plugin prints its message to stderr, followed by a `Caused by:` line for each cause,
|
|
2162
|
+
* without a stack trace. It sets the exit code of the process to {@link CommandError.exitCode},
|
|
2163
|
+
* and `cli()` resolves with `undefined`. `onErrorCommand` is still called with the error, after the
|
|
2164
|
+
* exit code is set, so the hook can change it.
|
|
2165
|
+
*
|
|
2166
|
+
* It is not printed, and `cli()` rejects with it, in these cases:
|
|
2167
|
+
*
|
|
2168
|
+
* - `usageSilent` is set, for the caller to report it
|
|
2169
|
+
* - it is thrown from a hook, while a plugin extends the command context, or while a lazy command
|
|
2170
|
+
* loads, outside the command decorators
|
|
2171
|
+
* - the CLI runs without the global options plugin, as `gunshi/bone` does
|
|
2172
|
+
*
|
|
2173
|
+
* Any other error thrown from a command is not printed either, and `cli()` rejects with it.
|
|
2174
|
+
*
|
|
2175
|
+
* Each package of gunshi (`gunshi`, `@gunshi/plugin`, `@gunshi/definition`) bundles its own copy of
|
|
2176
|
+
* this class, so `instanceof` does not match an error from another copy. Use
|
|
2177
|
+
* {@link isCommandError} to tell it.
|
|
2178
|
+
*
|
|
2179
|
+
* @example
|
|
2180
|
+
* ```js
|
|
2181
|
+
* import { CommandError, define } from 'gunshi'
|
|
2182
|
+
*
|
|
2183
|
+
* export default define({
|
|
2184
|
+
* name: 'show',
|
|
2185
|
+
* args: { project: { type: 'positional', description: 'Project name' } },
|
|
2186
|
+
* run: async ctx => {
|
|
2187
|
+
* const project = await findProject(ctx.values.project)
|
|
2188
|
+
* if (!project) {
|
|
2189
|
+
* throw new CommandError(`Project ${ctx.values.project} not found`, { code: 'not_found' })
|
|
2190
|
+
* }
|
|
2191
|
+
* ctx.log(project.description)
|
|
2192
|
+
* }
|
|
2193
|
+
* })
|
|
2194
|
+
* ```
|
|
2195
|
+
*/
|
|
2196
|
+
declare class CommandError extends Error {
|
|
2197
|
+
/**
|
|
2198
|
+
* The name of the failure, for programs to read. See {@link CommandErrorOptions.code}.
|
|
2199
|
+
*/
|
|
2200
|
+
readonly code?: string;
|
|
2201
|
+
/**
|
|
2202
|
+
* The exit code of the process, an integer from 1 to 255.
|
|
2203
|
+
*/
|
|
2204
|
+
readonly exitCode: number;
|
|
2205
|
+
/**
|
|
2206
|
+
* Create an error for a failure that a command expects.
|
|
2207
|
+
*
|
|
2208
|
+
* @param message - The message printed to the user. It may have more than one line.
|
|
2209
|
+
* @param options - The code, the exit code and the cause of the failure
|
|
2210
|
+
*/
|
|
2211
|
+
constructor(message: string, options?: CommandErrorOptions);
|
|
2212
|
+
}
|
|
2063
2213
|
/**
|
|
2064
2214
|
* Check whether an error is a {@link CommandNotFoundError}.
|
|
2065
2215
|
*
|
|
@@ -2079,6 +2229,76 @@ declare function isCommandNotFoundError(error: unknown): error is CommandNotFoun
|
|
|
2079
2229
|
* @returns `true` when the error has the command-resolution brand and shape
|
|
2080
2230
|
*/
|
|
2081
2231
|
declare function isCommandResolutionError(error: unknown): error is CommandResolutionError;
|
|
2232
|
+
/**
|
|
2233
|
+
* Check whether an error is a {@link CommandError}.
|
|
2234
|
+
*
|
|
2235
|
+
* An error from another copy of gunshi is recognized through the `Symbol.for('gunshi.CommandError')`
|
|
2236
|
+
* brand. It is not recognized by `error.name`, so an error of the app that is also named
|
|
2237
|
+
* `CommandError` is not taken for one.
|
|
2238
|
+
*
|
|
2239
|
+
* @param error - An unknown error
|
|
2240
|
+
* @returns `true` if the error is a {@link CommandError}
|
|
2241
|
+
*/
|
|
2242
|
+
declare function isCommandError(error: unknown): error is CommandError;
|
|
2243
|
+
/**
|
|
2244
|
+
* Options for {@link JsonOutputError}.
|
|
2245
|
+
*/
|
|
2246
|
+
type JsonOutputErrorOptions = {
|
|
2247
|
+
/**
|
|
2248
|
+
* The code of the error, which is also the resource key of its message.
|
|
2249
|
+
*/
|
|
2250
|
+
code: JsonOutputErrorCode;
|
|
2251
|
+
/**
|
|
2252
|
+
* Values used when localizing the message.
|
|
2253
|
+
*/
|
|
2254
|
+
values?: Record<string, unknown>;
|
|
2255
|
+
/**
|
|
2256
|
+
* Underlying cause, such as the error of `JSON.stringify`.
|
|
2257
|
+
*/
|
|
2258
|
+
cause?: unknown;
|
|
2259
|
+
};
|
|
2260
|
+
/**
|
|
2261
|
+
* Error raised by the global options plugin for the JSON output, when a command is given `--json`.
|
|
2262
|
+
*
|
|
2263
|
+
* - `err:json:not-supported`: the command does not spread `jsonArgs`. It is raised before the command
|
|
2264
|
+
* runs, and thrown in an `AggregateError`, as the argument errors are.
|
|
2265
|
+
* - `err:json:invalid-result`: the command finished, but did not return an object to output as JSON
|
|
2266
|
+
* - `err:json:unserializable-result`: the command finished, but its result cannot be converted to
|
|
2267
|
+
* JSON, such as an object with a `BigInt`
|
|
2268
|
+
*
|
|
2269
|
+
* The plugin prints it as one line of JSON to stderr, and `cli()` resolves with `undefined`. For
|
|
2270
|
+
* `err:json:not-supported`, with `renderValidationErrors: null` or `usageSilent`, nothing is printed
|
|
2271
|
+
* and `cli()` rejects with the `AggregateError`, as it does for the argument errors.
|
|
2272
|
+
*
|
|
2273
|
+
* Use {@link isJsonOutputError} to tell it, since each package bundles its own copy of this class.
|
|
2274
|
+
*/
|
|
2275
|
+
declare class JsonOutputError extends Error {
|
|
2276
|
+
/**
|
|
2277
|
+
* The code of the error, which is also the resource key of its message.
|
|
2278
|
+
*/
|
|
2279
|
+
readonly code: JsonOutputErrorCode;
|
|
2280
|
+
/**
|
|
2281
|
+
* Values used when localizing the message.
|
|
2282
|
+
*/
|
|
2283
|
+
readonly values: Record<string, unknown>;
|
|
2284
|
+
/**
|
|
2285
|
+
* Create an error of the JSON output.
|
|
2286
|
+
*
|
|
2287
|
+
* @param message - Fallback error message
|
|
2288
|
+
* @param options - The code of the error, and the values of its message
|
|
2289
|
+
*/
|
|
2290
|
+
constructor(message: string, options: JsonOutputErrorOptions);
|
|
2291
|
+
}
|
|
2292
|
+
/**
|
|
2293
|
+
* Check whether an error is a {@link JsonOutputError}.
|
|
2294
|
+
*
|
|
2295
|
+
* An error from another copy of gunshi is recognized through the
|
|
2296
|
+
* `Symbol.for('gunshi.JsonOutputError')` brand, not by `error.name`.
|
|
2297
|
+
*
|
|
2298
|
+
* @param error - An unknown error
|
|
2299
|
+
* @returns `true` if the error is a {@link JsonOutputError}
|
|
2300
|
+
*/
|
|
2301
|
+
declare function isJsonOutputError(error: unknown): error is JsonOutputError;
|
|
2082
2302
|
/**
|
|
2083
2303
|
* Check whether an error is an {@link ArgsValidationError}.
|
|
2084
2304
|
*
|
|
@@ -2106,4 +2326,4 @@ declare function isArgsValidationError(error: unknown): error is ArgsValidationE
|
|
|
2106
2326
|
*/
|
|
2107
2327
|
declare function hasPriorityValidationError(error: AggregateError | undefined): boolean;
|
|
2108
2328
|
//#endregion
|
|
2109
|
-
export { ANONYMOUS_COMMAND_NAME, type ArgSchema, type ArgToken, type ArgValues, type Args, ArgsValidationError, type ArgsValidationErrorCode, ArgsValidationErrorKeys, type Awaitable, CLI_OPTIONS_DEFAULT, type Command, type CommandContext, type CommandContextCore, type CommandContextExtension, type CommandContextParams, type CommandDecorator, type CommandExamplesFetcher, CommandNotFoundError, type CommandNotFoundErrorCode, CommandNotFoundErrorKeys, type CommandNotFoundErrorOptions, CommandResolutionError, type CommandResolutionErrorCode, CommandResolutionErrorKeys, type CommandResolutionErrorOptions, type CommandRunner, type DefaultGunshiParams, type ExtendContext, type ExtractArgs, type ExtractExtensions, type GunshiParams, type GunshiParamsConstraint, type LazyCommand, type MergeGunshiExtensions, type NormalizeToGunshiParams, type OnPluginExtension, type Plugin, type PluginContext, type PluginDependency, type PluginExtension, type PluginFunction, type PluginOptions, type PluginWithExtension, type PluginWithoutExtension, type Prettify, type RendererDecorator, type ValidationErrorsDecorator, createCommandContext, hasPriorityValidationError, isArgsValidationError, isCommandNotFoundError, isCommandResolutionError, plugin };
|
|
2329
|
+
export { ANONYMOUS_COMMAND_NAME, type ArgSchema, type ArgToken, type ArgValues, type Args, ArgsValidationError, type ArgsValidationErrorCode, ArgsValidationErrorKeys, type Awaitable, CLI_OPTIONS_DEFAULT, type Command, type CommandContext, type CommandContextCore, type CommandContextExtension, type CommandContextParams, type CommandDecorator, CommandError, type CommandErrorOptions, type CommandExamplesFetcher, CommandNotFoundError, type CommandNotFoundErrorCode, CommandNotFoundErrorKeys, type CommandNotFoundErrorOptions, CommandResolutionError, type CommandResolutionErrorCode, CommandResolutionErrorKeys, type CommandResolutionErrorOptions, type CommandRunner, type CommandRunnerResult, type DefaultGunshiParams, type ExtendContext, type ExtractArgs, type ExtractExtensions, type GunshiParams, type GunshiParamsConstraint, JsonOutputError, type JsonOutputErrorCode, JsonOutputErrorKeys, type JsonOutputErrorOptions, type JsonResult, type LazyCommand, type MergeGunshiExtensions, type NormalizeToGunshiParams, type OnPluginExtension, type Plugin, type PluginContext, type PluginDependency, type PluginExtension, type PluginFunction, type PluginOptions, type PluginWithExtension, type PluginWithoutExtension, type Prettify, type RendererDecorator, type SubCommandable, type ValidationErrorsDecorator, createCommandContext, hasPriorityValidationError, isArgsValidationError, isCommandError, isCommandNotFoundError, isCommandResolutionError, isJsonOutputError, plugin };
|
package/lib/index.js
CHANGED
|
@@ -33,6 +33,51 @@ const CLI_OPTIONS_DEFAULT = {
|
|
|
33
33
|
* @license MIT
|
|
34
34
|
*/
|
|
35
35
|
/**
|
|
36
|
+
* Check whether an argument schema is the `json` argument of `jsonArgs`, by its mark.
|
|
37
|
+
*
|
|
38
|
+
* @param schema - An argument schema
|
|
39
|
+
* @returns `true` if the schema has the mark of `jsonArgs`
|
|
40
|
+
*/
|
|
41
|
+
function isJsonArg(schema) {
|
|
42
|
+
return typeof schema === "object" && schema !== null && schema["~gunshi.json-arg"] === true;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolve whether `--json` asks a command for JSON.
|
|
46
|
+
*
|
|
47
|
+
* A command that spreads `jsonArgs` is asked for JSON when the resolved value of its `json` is `true`:
|
|
48
|
+
* with `--json`, or with a short name that the command gives it, but not with `--json=false`, nor with
|
|
49
|
+
* `--json` after `--`. The raw tokens are read only when they are given, and only when there is no
|
|
50
|
+
* value to read: when the command has no `json` argument, and when the core could not resolve the
|
|
51
|
+
* command and left the values empty. A `json` argument without the mark belongs to the command, and
|
|
52
|
+
* `--json` is never taken for a request then.
|
|
53
|
+
*
|
|
54
|
+
* @param args - The arguments of the command, the global options included
|
|
55
|
+
* @param values - The resolved values of the arguments
|
|
56
|
+
* @param tokens - The raw tokens of the arguments, to find a `--json` that no argument declares
|
|
57
|
+
* @returns How the command is asked for JSON, or `undefined` when it is not
|
|
58
|
+
*/
|
|
59
|
+
function resolveJsonRequest(args, values, tokens) {
|
|
60
|
+
const schema = Object.hasOwn(args, "json") ? args.json : void 0;
|
|
61
|
+
if (schema === void 0) return tokens !== void 0 && hasJsonOption(tokens) ? "undeclared" : void 0;
|
|
62
|
+
if (!isJsonArg(schema)) return;
|
|
63
|
+
if (values.json !== void 0) return values.json === true ? "declared" : void 0;
|
|
64
|
+
return tokens !== void 0 && hasJsonOption(tokens) ? "declared" : void 0;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Check whether the raw tokens have a `--json` that asks for JSON: `--json` or `--json=true`, before
|
|
68
|
+
* `--`. Without a declaration, a short name of `--json` is not known.
|
|
69
|
+
*
|
|
70
|
+
* @param tokens - The raw tokens of the arguments
|
|
71
|
+
* @returns `true` if a `--json` asks for JSON
|
|
72
|
+
*/
|
|
73
|
+
function hasJsonOption(tokens) {
|
|
74
|
+
for (const token of tokens) {
|
|
75
|
+
if (token.kind === "option-terminator") return false;
|
|
76
|
+
if (token.kind === "option" && token.rawName === "--json" && (token.value === void 0 || token.value === "true")) return true;
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
36
81
|
* Check if the given command is a {@link LazyCommand}.
|
|
37
82
|
*
|
|
38
83
|
* @param cmd - A command to check
|
|
@@ -124,6 +169,14 @@ async function createCommandContext({ args = {}, explicit = {}, values = {}, pos
|
|
|
124
169
|
/**
|
|
125
170
|
* create the command context
|
|
126
171
|
*/
|
|
172
|
+
/**
|
|
173
|
+
* NOTE(kazupon): a command that spreads `jsonArgs` and is asked for JSON prints its result as JSON, so
|
|
174
|
+
* the human output of `ctx.log` is silenced, as it is with `usageSilent`. The hooks and the decorators
|
|
175
|
+
* get the same context, so their `ctx.log` is silenced too. Only the resolved value of the `json`
|
|
176
|
+
* argument counts here, not the raw tokens: a command that does not support `--json` keeps its output,
|
|
177
|
+
* and the global options plugin reports the `--json` given to it.
|
|
178
|
+
*/
|
|
179
|
+
const silent = cliOptions.usageSilent || resolveJsonRequest(_args, values) === "declared";
|
|
127
180
|
const core = Object.assign(create(), {
|
|
128
181
|
name: getCommandName(command),
|
|
129
182
|
description: command.description,
|
|
@@ -139,7 +192,7 @@ async function createCommandContext({ args = {}, explicit = {}, values = {}, pos
|
|
|
139
192
|
_: argv,
|
|
140
193
|
tokens,
|
|
141
194
|
toKebab: command.toKebab,
|
|
142
|
-
log:
|
|
195
|
+
log: silent ? NOOP : log,
|
|
143
196
|
validationError
|
|
144
197
|
});
|
|
145
198
|
/**
|
|
@@ -176,7 +229,7 @@ function getCommandName(cmd) {
|
|
|
176
229
|
"-".codePointAt(0);
|
|
177
230
|
"=".codePointAt(0);
|
|
178
231
|
//#endregion
|
|
179
|
-
//#region ../../node_modules/.pnpm/args-tokens@1.0.
|
|
232
|
+
//#region ../../node_modules/.pnpm/args-tokens@1.0.2/node_modules/args-tokens/lib/resolver-Cx5Pw6-S.js
|
|
180
233
|
/**
|
|
181
234
|
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
182
235
|
* @license MIT
|
|
@@ -285,7 +338,7 @@ function isArgsValidationError$1(error) {
|
|
|
285
338
|
return typeof values === "object" && values !== null;
|
|
286
339
|
}
|
|
287
340
|
//#endregion
|
|
288
|
-
//#region ../../node_modules/.pnpm/args-tokens@1.0.
|
|
341
|
+
//#region ../../node_modules/.pnpm/args-tokens@1.0.2/node_modules/args-tokens/lib/index.js
|
|
289
342
|
/**
|
|
290
343
|
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
291
344
|
* @license MIT
|
|
@@ -317,6 +370,14 @@ const CommandResolutionErrorKeys = {
|
|
|
317
370
|
lazySchemaMismatch: "err:cmd:lazy-schema-mismatch"
|
|
318
371
|
};
|
|
319
372
|
/**
|
|
373
|
+
* The resource keys of the errors of the JSON output, which are the codes of {@link JsonOutputError}.
|
|
374
|
+
*/
|
|
375
|
+
const JsonOutputErrorKeys = {
|
|
376
|
+
notSupported: "err:json:not-supported",
|
|
377
|
+
invalidResult: "err:json:invalid-result",
|
|
378
|
+
unserializableResult: "err:json:unserializable-result"
|
|
379
|
+
};
|
|
380
|
+
/**
|
|
320
381
|
* Brand that marks {@link CommandNotFoundError} instances.
|
|
321
382
|
*
|
|
322
383
|
* The brand is looked up in the global symbol registry with `Symbol.for`, so it stays
|
|
@@ -326,6 +387,8 @@ const CommandResolutionErrorKeys = {
|
|
|
326
387
|
*/
|
|
327
388
|
const COMMAND_NOT_FOUND_ERROR_BRAND = Symbol.for("gunshi.CommandNotFoundError");
|
|
328
389
|
const COMMAND_RESOLUTION_ERROR_BRAND = Symbol.for("gunshi.CommandResolutionError");
|
|
390
|
+
const COMMAND_ERROR_BRAND = Symbol.for("gunshi.CommandError");
|
|
391
|
+
const JSON_OUTPUT_ERROR_BRAND = Symbol.for("gunshi.JsonOutputError");
|
|
329
392
|
/**
|
|
330
393
|
* Error raised when a command cannot be resolved.
|
|
331
394
|
*
|
|
@@ -395,6 +458,73 @@ var CommandResolutionError = class extends Error {
|
|
|
395
458
|
}
|
|
396
459
|
};
|
|
397
460
|
/**
|
|
461
|
+
* Error for a failure that a command expects, such as a project that does not exist.
|
|
462
|
+
*
|
|
463
|
+
* When a command throws it from `run`, or a plugin throws it from a command decorator, the global
|
|
464
|
+
* options plugin prints its message to stderr, followed by a `Caused by:` line for each cause,
|
|
465
|
+
* without a stack trace. It sets the exit code of the process to {@link CommandError.exitCode},
|
|
466
|
+
* and `cli()` resolves with `undefined`. `onErrorCommand` is still called with the error, after the
|
|
467
|
+
* exit code is set, so the hook can change it.
|
|
468
|
+
*
|
|
469
|
+
* It is not printed, and `cli()` rejects with it, in these cases:
|
|
470
|
+
*
|
|
471
|
+
* - `usageSilent` is set, for the caller to report it
|
|
472
|
+
* - it is thrown from a hook, while a plugin extends the command context, or while a lazy command
|
|
473
|
+
* loads, outside the command decorators
|
|
474
|
+
* - the CLI runs without the global options plugin, as `gunshi/bone` does
|
|
475
|
+
*
|
|
476
|
+
* Any other error thrown from a command is not printed either, and `cli()` rejects with it.
|
|
477
|
+
*
|
|
478
|
+
* Each package of gunshi (`gunshi`, `@gunshi/plugin`, `@gunshi/definition`) bundles its own copy of
|
|
479
|
+
* this class, so `instanceof` does not match an error from another copy. Use
|
|
480
|
+
* {@link isCommandError} to tell it.
|
|
481
|
+
*
|
|
482
|
+
* @example
|
|
483
|
+
* ```js
|
|
484
|
+
* import { CommandError, define } from 'gunshi'
|
|
485
|
+
*
|
|
486
|
+
* export default define({
|
|
487
|
+
* name: 'show',
|
|
488
|
+
* args: { project: { type: 'positional', description: 'Project name' } },
|
|
489
|
+
* run: async ctx => {
|
|
490
|
+
* const project = await findProject(ctx.values.project)
|
|
491
|
+
* if (!project) {
|
|
492
|
+
* throw new CommandError(`Project ${ctx.values.project} not found`, { code: 'not_found' })
|
|
493
|
+
* }
|
|
494
|
+
* ctx.log(project.description)
|
|
495
|
+
* }
|
|
496
|
+
* })
|
|
497
|
+
* ```
|
|
498
|
+
*/
|
|
499
|
+
var CommandError = class extends Error {
|
|
500
|
+
/**
|
|
501
|
+
* The name of the failure, for programs to read. See {@link CommandErrorOptions.code}.
|
|
502
|
+
*/
|
|
503
|
+
code;
|
|
504
|
+
/**
|
|
505
|
+
* The exit code of the process, an integer from 1 to 255.
|
|
506
|
+
*/
|
|
507
|
+
exitCode;
|
|
508
|
+
/**
|
|
509
|
+
* Create an error for a failure that a command expects.
|
|
510
|
+
*
|
|
511
|
+
* @param message - The message printed to the user. It may have more than one line.
|
|
512
|
+
* @param options - The code, the exit code and the cause of the failure
|
|
513
|
+
*/
|
|
514
|
+
constructor(message, options = {}) {
|
|
515
|
+
super(message, { cause: options.cause });
|
|
516
|
+
this.name = "CommandError";
|
|
517
|
+
this.code = options.code;
|
|
518
|
+
this.exitCode = isFailureExitCode(options.exitCode) ? options.exitCode : 1;
|
|
519
|
+
Object.defineProperty(this, COMMAND_ERROR_BRAND, {
|
|
520
|
+
value: true,
|
|
521
|
+
enumerable: false,
|
|
522
|
+
writable: false,
|
|
523
|
+
configurable: false
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
/**
|
|
398
528
|
* Check whether an error is a {@link CommandNotFoundError}.
|
|
399
529
|
*
|
|
400
530
|
* `instanceof` alone is not enough: `@gunshi/plugin` is bundled with its own copy of this
|
|
@@ -423,6 +553,78 @@ function isCommandResolutionError(error) {
|
|
|
423
553
|
return Object.hasOwn(error, COMMAND_RESOLUTION_ERROR_BRAND) && error[COMMAND_RESOLUTION_ERROR_BRAND] === true;
|
|
424
554
|
}
|
|
425
555
|
/**
|
|
556
|
+
* Check whether an error is a {@link CommandError}.
|
|
557
|
+
*
|
|
558
|
+
* An error from another copy of gunshi is recognized through the `Symbol.for('gunshi.CommandError')`
|
|
559
|
+
* brand. It is not recognized by `error.name`, so an error of the app that is also named
|
|
560
|
+
* `CommandError` is not taken for one.
|
|
561
|
+
*
|
|
562
|
+
* @param error - An unknown error
|
|
563
|
+
* @returns `true` if the error is a {@link CommandError}
|
|
564
|
+
*/
|
|
565
|
+
function isCommandError(error) {
|
|
566
|
+
if (error instanceof CommandError) return true;
|
|
567
|
+
if (!isRecord(error) || !Object.hasOwn(error, COMMAND_ERROR_BRAND) || error[COMMAND_ERROR_BRAND] !== true) return false;
|
|
568
|
+
return hasCommandErrorShape(error);
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Error raised by the global options plugin for the JSON output, when a command is given `--json`.
|
|
572
|
+
*
|
|
573
|
+
* - `err:json:not-supported`: the command does not spread `jsonArgs`. It is raised before the command
|
|
574
|
+
* runs, and thrown in an `AggregateError`, as the argument errors are.
|
|
575
|
+
* - `err:json:invalid-result`: the command finished, but did not return an object to output as JSON
|
|
576
|
+
* - `err:json:unserializable-result`: the command finished, but its result cannot be converted to
|
|
577
|
+
* JSON, such as an object with a `BigInt`
|
|
578
|
+
*
|
|
579
|
+
* The plugin prints it as one line of JSON to stderr, and `cli()` resolves with `undefined`. For
|
|
580
|
+
* `err:json:not-supported`, with `renderValidationErrors: null` or `usageSilent`, nothing is printed
|
|
581
|
+
* and `cli()` rejects with the `AggregateError`, as it does for the argument errors.
|
|
582
|
+
*
|
|
583
|
+
* Use {@link isJsonOutputError} to tell it, since each package bundles its own copy of this class.
|
|
584
|
+
*/
|
|
585
|
+
var JsonOutputError = class extends Error {
|
|
586
|
+
/**
|
|
587
|
+
* The code of the error, which is also the resource key of its message.
|
|
588
|
+
*/
|
|
589
|
+
code;
|
|
590
|
+
/**
|
|
591
|
+
* Values used when localizing the message.
|
|
592
|
+
*/
|
|
593
|
+
values;
|
|
594
|
+
/**
|
|
595
|
+
* Create an error of the JSON output.
|
|
596
|
+
*
|
|
597
|
+
* @param message - Fallback error message
|
|
598
|
+
* @param options - The code of the error, and the values of its message
|
|
599
|
+
*/
|
|
600
|
+
constructor(message, options) {
|
|
601
|
+
super(message, { cause: options.cause });
|
|
602
|
+
this.name = "JsonOutputError";
|
|
603
|
+
this.code = options.code;
|
|
604
|
+
this.values = options.values || {};
|
|
605
|
+
Object.defineProperty(this, JSON_OUTPUT_ERROR_BRAND, {
|
|
606
|
+
value: true,
|
|
607
|
+
enumerable: false,
|
|
608
|
+
writable: false,
|
|
609
|
+
configurable: false
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
/**
|
|
614
|
+
* Check whether an error is a {@link JsonOutputError}.
|
|
615
|
+
*
|
|
616
|
+
* An error from another copy of gunshi is recognized through the
|
|
617
|
+
* `Symbol.for('gunshi.JsonOutputError')` brand, not by `error.name`.
|
|
618
|
+
*
|
|
619
|
+
* @param error - An unknown error
|
|
620
|
+
* @returns `true` if the error is a {@link JsonOutputError}
|
|
621
|
+
*/
|
|
622
|
+
function isJsonOutputError(error) {
|
|
623
|
+
if (error instanceof JsonOutputError) return true;
|
|
624
|
+
if (!isRecord(error) || !Object.hasOwn(error, JSON_OUTPUT_ERROR_BRAND) || error[JSON_OUTPUT_ERROR_BRAND] !== true) return false;
|
|
625
|
+
return hasJsonOutputErrorShape(error);
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
426
628
|
* Check whether an error is an {@link ArgsValidationError}.
|
|
427
629
|
*
|
|
428
630
|
* Prefer this over the `args-tokens` guard of the same name. Both recognize errors from another
|
|
@@ -472,6 +674,21 @@ function hasCommandResolutionErrorShape(error) {
|
|
|
472
674
|
function hasArgsValidationErrorShape(error) {
|
|
473
675
|
return hasOptionalStringCode(error) && isRecord(error.values);
|
|
474
676
|
}
|
|
677
|
+
function hasCommandErrorShape(error) {
|
|
678
|
+
return hasOptionalStringCode(error) && typeof error.message === "string" && isFailureExitCode(error.exitCode);
|
|
679
|
+
}
|
|
680
|
+
function hasJsonOutputErrorShape(error) {
|
|
681
|
+
return Object.values(JsonOutputErrorKeys).includes(error.code) && isRecord(error.values);
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Check whether a value is an exit code of a failure: an integer from 1 to 255.
|
|
685
|
+
*
|
|
686
|
+
* @param value - The value to check
|
|
687
|
+
* @returns `true` if the value is an exit code of a failure
|
|
688
|
+
*/
|
|
689
|
+
function isFailureExitCode(value) {
|
|
690
|
+
return Number.isInteger(value) && value >= 1 && value <= 255;
|
|
691
|
+
}
|
|
475
692
|
/**
|
|
476
693
|
* Check whether validation errors should be handled before version, help, or command execution.
|
|
477
694
|
*
|
|
@@ -546,4 +763,4 @@ function plugin(options = {}) {
|
|
|
546
763
|
* @license MIT
|
|
547
764
|
*/
|
|
548
765
|
//#endregion
|
|
549
|
-
export { ANONYMOUS_COMMAND_NAME, ArgsValidationError, ArgsValidationErrorKeys, CLI_OPTIONS_DEFAULT, CommandNotFoundError, CommandNotFoundErrorKeys, CommandResolutionError, CommandResolutionErrorKeys, createCommandContext, hasPriorityValidationError, isArgsValidationError, isCommandNotFoundError, isCommandResolutionError, plugin };
|
|
766
|
+
export { ANONYMOUS_COMMAND_NAME, ArgsValidationError, ArgsValidationErrorKeys, CLI_OPTIONS_DEFAULT, CommandError, CommandNotFoundError, CommandNotFoundErrorKeys, CommandResolutionError, CommandResolutionErrorKeys, JsonOutputError, JsonOutputErrorKeys, createCommandContext, hasPriorityValidationError, isArgsValidationError, isCommandError, isCommandNotFoundError, isCommandResolutionError, isJsonOutputError, plugin };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gunshi/plugin",
|
|
3
3
|
"description": "plugin development kit 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"
|
|
@@ -51,16 +51,11 @@
|
|
|
51
51
|
}
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"
|
|
55
|
-
"gunshi": "1.0.0-rc.4",
|
|
56
|
-
"jsr": "^0.14.3",
|
|
57
|
-
"jsr-exports-lint": "^0.4.2",
|
|
54
|
+
"gunshi": "1.0.0-rc.6",
|
|
58
55
|
"publint": "^0.3.20",
|
|
59
56
|
"tsdown": "0.22.14"
|
|
60
57
|
},
|
|
61
58
|
"scripts": {
|
|
62
|
-
"build": "tsdown"
|
|
63
|
-
"lint:jsr": "jsr publish --dry-run --allow-dirty",
|
|
64
|
-
"typecheck:deno": "deno check --import-map=../../importmap.json ./src"
|
|
59
|
+
"build": "tsdown"
|
|
65
60
|
}
|
|
66
61
|
}
|