@gunshi/plugin-renderer 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 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
  > usage renderer plugin for gunshi.
8
7
 
@@ -20,9 +19,6 @@ pnpm add @gunshi/plugin-renderer
20
19
  # yarn
21
20
  yarn add @gunshi/plugin-renderer
22
21
 
23
- # deno
24
- deno add jsr:@gunshi/plugin-renderer
25
-
26
22
  # bun
27
23
  bun add @gunshi/plugin-renderer
28
24
  ```
@@ -119,7 +115,7 @@ EXAMPLES:
119
115
 
120
116
  - **`renderHeader(ctx: CommandContext): Promise<string>`**: Renders the command header section
121
117
  - **`renderUsage(ctx: CommandContext): Promise<string>`**: Renders the complete usage/help information
122
- - **`renderValidationErrors(ctx: CommandContext, error: AggregateError): Promise<string>`**: Renders validation errors
118
+ - **`renderValidationErrors(ctx: CommandContext, error: AggregateError): Promise<string>`**: Renders validation errors. With `--json`, the global options plugin prints the validation errors as one line of JSON, and does not call the renderer of the validation errors
123
119
 
124
120
  ## 🧩 Context Extensions
125
121
 
@@ -270,6 +266,4 @@ See the [API References](./docs/index.md)
270
266
 
271
267
  [npm-version-src]: https://img.shields.io/npm/v/@gunshi/plugin-renderer?style=flat
272
268
  [npm-version-href]: https://npmjs.com/package/@gunshi/plugin-renderer@alpha
273
- [jsr-src]: https://jsr.io/badges/@gunshi/plugin-renderer
274
- [jsr-href]: https://jsr.io/@gunshi/plugin-renderer
275
269
  [install-size-src]: https://pkg-size.dev/badge/install/101075
package/lib/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { Args, Command, CommandContext, DefaultGunshiParams, GunshiParams, PluginWithExtension } from "@gunshi/plugin";
2
2
  import "@gunshi/plugin-i18n";
3
- //#region ../../node_modules/.pnpm/args-tokens@1.0.0/node_modules/args-tokens/lib/resolver.d.ts
4
- //#region src/resolver.d.ts
3
+ //#region ../../node_modules/.pnpm/args-tokens@1.0.2/node_modules/args-tokens/lib/resolver.d.ts
5
4
  /**
6
5
  * An argument schema definition for command-line argument parsing.
7
6
  *
@@ -363,9 +362,9 @@ interface ArgSchema {
363
362
  */
364
363
  toKebab?: true;
365
364
  /**
366
- * Names of other options that conflict with this option.
365
+ * Names of other arguments that conflict with this argument.
367
366
  *
368
- * When this option is used together with any of the conflicting options, the error is an
367
+ * When this argument is used together with any of the conflicting arguments, the error is an
369
368
  * `ArgResolveError` with type 'conflict' and the code `err:arg:conflict`
370
369
  * ({@link ArgsValidationErrorKeys}.conflict). Its `values` has the `displayName` and `name` of
371
370
  * the argument whose `conflicts` names the other one, and the `conflictDisplayName` and
@@ -375,9 +374,8 @@ interface ArgSchema {
375
374
  *
376
375
  * A positional argument can be on either side, such as `[file]` and `--stdin`. It conflicts when
377
376
  * it is given, and it is shown by its name, such as `'file'` (in kebab-case with `toKebab`), as
378
- * in its other errors. The message starts with the kind of the argument given as `name`:
379
- * `Positional argument 'file' conflicts with '--stdin'` or
380
- * `Optional argument '--stdin' conflicts with 'file'`.
377
+ * in its other errors. The message names the argument given as `name` first:
378
+ * `'file' conflicts with '--stdin'` or `'--stdin' conflicts with 'file'`.
381
379
  *
382
380
  * Conflicts only need to be defined on one side - if option A defines a conflict
383
381
  * with option B, the conflict is automatically detected when both are used,
@@ -416,7 +414,7 @@ interface ArgSchema {
416
414
  * }
417
415
  * }
418
416
  * // Usage: --summer --autumn reports an error
419
- * // Error: "Optional argument '--summer' conflicts with '--autumn'"
417
+ * // Error: "'--summer' conflicts with '--autumn'"
420
418
  * ```
421
419
  *
422
420
  * @example
@@ -456,7 +454,7 @@ interface ArgSchema {
456
454
  * toKebab: true // Accessible as --autumn-season
457
455
  * }
458
456
  * }
459
- * // Error: "Optional argument '--summer-season' conflicts with '--autumn-season'"
457
+ * // Error: "'--summer-season' conflicts with '--autumn-season'"
460
458
  * ```
461
459
  */
462
460
  conflicts?: string | string[];
@@ -583,11 +581,12 @@ type CommonArgType = {
583
581
  };
584
582
  };
585
583
  declare const COMMON_ARGS: CommonArgType;
586
- declare const COMMAND_BUILTIN_RESOURCE_KEYS: readonly ["USAGE", "COMMAND", "SUBCOMMAND", "COMMANDS", "ARGUMENTS", "OPTIONS", "EXAMPLES", "FORMORE", "NEGATABLE", "DEFAULT", "CHOICES"];
584
+ declare const COMMAND_BUILTIN_RESOURCE_KEYS: readonly ["USAGE", "COMMAND", "SUBCOMMAND", "COMMANDS", "ARGUMENTS", "OPTIONS", "EXAMPLES", "FORMORE", "NEGATABLE", "DEFAULT", "CHOICES", "CAUSEDBY"];
587
585
  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"];
588
586
  declare const ARG_ERROR_HINT_RESOURCE_KEYS: readonly ["err:arg:missing-value:hint"];
589
587
  declare const COMMAND_ERROR_RESOURCE_KEYS: readonly ["err:cmd:not-found", "err:cmd:ambiguous", "err:cmd:inconsistent-options", "err:cmd:lazy-schema-mismatch"];
590
588
  declare const SUGGESTION_ERROR_RESOURCE_KEYS: readonly ["err:suggestion:did-you-mean"];
589
+ declare const JSON_ERROR_RESOURCE_KEYS: readonly ["err:json:not-supported", "err:json:invalid-result", "err:json:unserializable-result"];
591
590
  //#endregion
592
591
  //#region ../shared/src/types.d.ts
593
592
  type RemoveIndexSignature<T> = { [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K]; };
@@ -627,10 +626,14 @@ type CommandErrorResourceKeys = (typeof COMMAND_ERROR_RESOURCE_KEYS)[number];
627
626
  * Suggestion error resource keys.
628
627
  */
629
628
  type SuggestionErrorResourceKeys = (typeof SUGGESTION_ERROR_RESOURCE_KEYS)[number];
629
+ /**
630
+ * Resource keys of the errors of the JSON output.
631
+ */
632
+ type JsonErrorResourceKeys = (typeof JSON_ERROR_RESOURCE_KEYS)[number];
630
633
  /**
631
634
  * Error resource keys.
632
635
  */
633
- type ErrorResourceKeys = ArgErrorResourceKeys | ArgErrorHintResourceKeys | CommandErrorResourceKeys | SuggestionErrorResourceKeys;
636
+ type ErrorResourceKeys = ArgErrorResourceKeys | ArgErrorHintResourceKeys | CommandErrorResourceKeys | SuggestionErrorResourceKeys | JsonErrorResourceKeys;
634
637
  /**
635
638
  * Command built-in keys.
636
639
  */
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ANONYMOUS_COMMAND_NAME, ArgsValidationErrorKeys, createCommandContext, isArgsValidationError, isCommandNotFoundError, isCommandResolutionError, plugin } from "@gunshi/plugin";
2
- //#region ../../node_modules/.pnpm/args-tokens@1.0.0/node_modules/args-tokens/lib/utils.js
2
+ //#region ../../node_modules/.pnpm/args-tokens@1.0.2/node_modules/args-tokens/lib/utils.js
3
3
  /**
4
4
  * Entry point of utils.
5
5
  *
@@ -150,16 +150,21 @@ var en_US_default = {
150
150
  NEGATABLE: "Negatable of",
151
151
  DEFAULT: "default",
152
152
  CHOICES: "choices",
153
+ CAUSEDBY: "Caused by",
153
154
  help: "Display this help message",
154
155
  version: "Display this version",
155
- "err:arg:required-option": "Optional argument {$displayName} is required",
156
+ json: "Output the result as JSON",
157
+ "json:invalid-arguments": "{$count} arguments are invalid",
158
+ "json:next:help": "See the arguments of the command",
159
+ "json:next:help-placeholder": "Replace <COMMAND> with how you ran this CLI, to see the arguments of the command",
160
+ "err:arg:required-option": "Option {$displayName} is required",
156
161
  "err:arg:required-positional": "Positional argument {$displayName} is required",
157
162
  "err:arg:invalid-type": "Invalid value for {$displayName}: expected {$expected}",
158
163
  "err:arg:invalid-choice": "Invalid value for {$displayName}: expected one of {$choices}",
159
164
  "err:arg:custom-parse": "Invalid value for {$displayName}: {$reason}",
160
165
  "err:arg:unknown-option": "Unknown option: {$rawName}",
161
- "err:arg:unexpected-value": "Optional argument {$displayName} does not take a value",
162
- "err:arg:missing-value": "Optional argument {$displayName} requires a value",
166
+ "err:arg:unexpected-value": "Option {$displayName} does not take a value",
167
+ "err:arg:missing-value": "Option {$displayName} requires a value",
163
168
  "err:arg:missing-value:hint": "(to pass '{$next}' as its value, write '{$suggestion}')",
164
169
  "err:arg:conflict": "{$displayName} conflicts with {$conflictDisplayName}",
165
170
  "err:arg:invalid-default": "Invalid default for {$displayName}: {$actual} is not one of {$choices}",
@@ -167,6 +172,9 @@ var en_US_default = {
167
172
  "err:cmd:ambiguous": "The command is ambiguous. Move options after the command name: {$candidatePaths}",
168
173
  "err:cmd:inconsistent-options": "The options do not identify a consistent command. Move options after the command name.",
169
174
  "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}",
175
+ "err:json:not-supported": "This command does not support --json",
176
+ "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",
177
+ "err:json:unserializable-result": "The command finished, but its result cannot be converted to JSON: {$message}",
170
178
  "err:suggestion:did-you-mean": "Did you mean {$name}?"
171
179
  };
172
180
  //#endregion
@@ -344,6 +352,84 @@ function formatResource(resource, values = Object.create(null)) {
344
352
  });
345
353
  }
346
354
  //#endregion
355
+ //#region ../shared/src/validation.ts
356
+ /**
357
+ * @author kazuya kawaguchi (a.k.a. kazupon)
358
+ * @license MIT
359
+ */
360
+ const i18nPluginId$1 = namespacedId("i18n");
361
+ const missingValueHintKey = "err:arg:missing-value:hint";
362
+ /**
363
+ * Localize the message of a validation error, as gunshi shows it to the user: with the i18n plugin when
364
+ * it is installed, and otherwise the message of the error.
365
+ *
366
+ * NOTE(kazupon): the renderer plugin renders the validation errors for people, and the global options
367
+ * plugin prints them as JSON with `--json`. Both take the messages from here, so that a message is the
368
+ * same in both.
369
+ *
370
+ * @param ctx - A {@link CommandContext | command context}
371
+ * @param error - A validation error: an {@link ArgsValidationError}, a command-not-found error, or a
372
+ * command-resolution error
373
+ * @returns The localized message
374
+ */
375
+ async function localizeValidationError(ctx, error) {
376
+ if (isCommandNotFoundError(error) && error.code) {
377
+ const message = await localize(ctx, error.code, error.values);
378
+ if (message && message !== error.code) return message;
379
+ }
380
+ if (isCommandResolutionError(error) && error.code) {
381
+ const message = await localize(ctx, error.code, error.values);
382
+ if (message && message !== error.code) return message;
383
+ }
384
+ if (isArgsValidationError(error) && error.code) {
385
+ const values = await resolveValidationValues(ctx, error);
386
+ const message = await localize(ctx, error.code, values);
387
+ if (message && message !== error.code) {
388
+ const hint = await localizeHint(ctx, error, values);
389
+ return hint ? `${message} ${hint}` : message;
390
+ }
391
+ }
392
+ return error.message;
393
+ }
394
+ /**
395
+ * Localize the hint that args-tokens adds to the message of an error.
396
+ *
397
+ * A translation replaces the whole message, hint included, so the hint is translated by a key of
398
+ * its own and follows the translated error. args-tokens gives one today: for an option given without
399
+ * a value, when the argument after it may be the value, the long form with `=` (`--port=-5` for
400
+ * `--port -5`), in `values.next` and `values.suggestion`.
401
+ *
402
+ * @param ctx - A {@link CommandContext | command context}
403
+ * @param error - An args validation error
404
+ * @param values - The values of the error, as given to its translation
405
+ * @returns The localized hint, or `undefined` when the error has none.
406
+ */
407
+ async function localizeHint(ctx, error, values) {
408
+ if (error.code !== ArgsValidationErrorKeys.missingValue || typeof values.next !== "string" || typeof values.suggestion !== "string") return;
409
+ const hint = await localize(ctx, missingValueHintKey, values);
410
+ return hint && hint !== missingValueHintKey ? hint : void 0;
411
+ }
412
+ async function resolveValidationValues(ctx, error) {
413
+ if (error.code !== ArgsValidationErrorKeys.customParse) return error.values;
414
+ const { reasonKey, reasonValues } = error.values;
415
+ if (typeof reasonKey !== "string") return error.values;
416
+ const key = resolveKey(reasonKey, ctx.name);
417
+ const localizedReason = await localize(ctx, key, toRecord(reasonValues));
418
+ if (!localizedReason || localizedReason === key) return error.values;
419
+ return {
420
+ ...error.values,
421
+ reason: localizedReason
422
+ };
423
+ }
424
+ async function localize(ctx, key, values) {
425
+ const i18n = ctx.extensions?.[i18nPluginId$1];
426
+ if (i18n?.translate) return i18n.translate(key, values);
427
+ return key;
428
+ }
429
+ function toRecord(value) {
430
+ return value != null && typeof value === "object" ? value : Object.create(null);
431
+ }
432
+ //#endregion
347
433
  //#region ../shared/src/index.ts
348
434
  /**
349
435
  * @author kazuya kawaguchi (a.k.a. kazupon)
@@ -795,8 +881,6 @@ function isRequiredSinglePositionalArg(arg) {
795
881
  * @author kazuya kawaguchi (a.k.a. kazupon)
796
882
  * @license MIT
797
883
  */
798
- const i18nPluginId$1 = namespacedId("i18n");
799
- const missingValueHintKey = "err:arg:missing-value:hint";
800
884
  /**
801
885
  * Render the validation errors.
802
886
  *
@@ -806,66 +890,9 @@ const missingValueHintKey = "err:arg:missing-value:hint";
806
890
  */
807
891
  async function renderValidationErrors(ctx, error) {
808
892
  const messages = [];
809
- for (const err of error.errors) messages.push(await renderValidationError(ctx, err));
893
+ for (const err of error.errors) messages.push(await localizeValidationError(ctx, err));
810
894
  return messages.join("\n");
811
895
  }
812
- async function renderValidationError(ctx, error) {
813
- if (isCommandNotFoundError(error) && error.code) {
814
- const message = await localize(ctx, error.code, error.values);
815
- if (message && message !== error.code) return message;
816
- }
817
- if (isCommandResolutionError(error) && error.code) {
818
- const message = await localize(ctx, error.code, error.values);
819
- if (message && message !== error.code) return message;
820
- }
821
- if (isArgsValidationError(error) && error.code) {
822
- const values = await resolveValidationValues(ctx, error);
823
- const message = await localize(ctx, error.code, values);
824
- if (message && message !== error.code) {
825
- const hint = await localizeHint(ctx, error, values);
826
- return hint ? `${message} ${hint}` : message;
827
- }
828
- }
829
- return error.message;
830
- }
831
- /**
832
- * Localize the hint that args-tokens adds to the message of an error.
833
- *
834
- * A translation replaces the whole message, hint included, so the hint is translated by a key of
835
- * its own and follows the translated error. args-tokens gives one today: for an option given without
836
- * a value, when the argument after it may be the value, the long form with `=` (`--port=-5` for
837
- * `--port -5`), in `values.next` and `values.suggestion`.
838
- *
839
- * @param ctx - A {@link CommandContext | command context}
840
- * @param error - An args validation error
841
- * @param values - The values of the error, as given to its translation
842
- * @returns The localized hint, or `undefined` when the error has none.
843
- */
844
- async function localizeHint(ctx, error, values) {
845
- if (error.code !== ArgsValidationErrorKeys.missingValue || typeof values.next !== "string" || typeof values.suggestion !== "string") return;
846
- const hint = await localize(ctx, missingValueHintKey, values);
847
- return hint && hint !== missingValueHintKey ? hint : void 0;
848
- }
849
- async function resolveValidationValues(ctx, error) {
850
- if (error.code !== ArgsValidationErrorKeys.customParse) return error.values;
851
- const { reasonKey, reasonValues } = error.values;
852
- if (typeof reasonKey !== "string") return error.values;
853
- const key = resolveKey(reasonKey, ctx.name);
854
- const localizedReason = await localize(ctx, key, toRecord(reasonValues));
855
- if (!localizedReason || localizedReason === key) return error.values;
856
- return {
857
- ...error.values,
858
- reason: localizedReason
859
- };
860
- }
861
- async function localize(ctx, key, values) {
862
- const i18n = ctx.extensions?.[i18nPluginId$1];
863
- if (i18n?.translate) return i18n.translate(key, values);
864
- return key;
865
- }
866
- function toRecord(value) {
867
- return value != null && typeof value === "object" ? value : Object.create(null);
868
- }
869
896
  //#endregion
870
897
  //#region src/index.ts
871
898
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gunshi/plugin-renderer",
3
3
  "description": "usage renderer plugin for gunshi",
4
- "version": "1.0.0-rc.4",
4
+ "version": "1.0.0-rc.6",
5
5
  "author": {
6
6
  "name": "kazuya kawaguchi",
7
7
  "email": "kawakazu80@gmail.com"
@@ -53,23 +53,18 @@
53
53
  }
54
54
  },
55
55
  "dependencies": {
56
- "@gunshi/plugin": "1.0.0-rc.4"
56
+ "@gunshi/plugin": "1.0.0-rc.6"
57
57
  },
58
58
  "peerDependencies": {
59
- "@gunshi/plugin-i18n": "1.0.0-rc.4"
59
+ "@gunshi/plugin-i18n": "1.0.0-rc.6"
60
60
  },
61
61
  "devDependencies": {
62
- "@gunshi/shared": "1.0.0-rc.4",
63
- "deno": "^2.7.14",
64
- "jsr": "^0.14.3",
65
- "jsr-exports-lint": "^0.4.2",
62
+ "@gunshi/shared": "1.0.0-rc.6",
66
63
  "publint": "^0.3.20",
67
64
  "tsdown": "0.22.14"
68
65
  },
69
66
  "scripts": {
70
67
  "build": "tsdown",
71
- "build:docs": "tsx ../../scripts/api-references.ts",
72
- "lint:jsr": "jsr publish --dry-run --allow-dirty",
73
- "typecheck:deno": "deno check --import-map=../../importmap.json ./src"
68
+ "build:docs": "tsx ../../scripts/api-references.ts"
74
69
  }
75
70
  }