@gunshi/plugin-i18n 0.37.3 → 1.0.0-beta.1

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.
Files changed (3) hide show
  1. package/lib/index.d.ts +147 -63
  2. package/lib/index.js +21 -2
  3. package/package.json +10 -10
package/lib/index.d.ts CHANGED
@@ -1,7 +1,5 @@
1
1
  import { Args, Awaitable, Command, CommandContext, DefaultGunshiParams, ExtendContext, ExtractArgs, ExtractExtensions, GunshiParams, GunshiParamsConstraint, PluginWithExtension, Prettify } from "@gunshi/plugin";
2
-
3
- //#region ../../node_modules/.pnpm/args-tokens@0.29.0/node_modules/args-tokens/lib/resolver.d.ts
4
-
2
+ //#region ../../node_modules/.pnpm/args-tokens@1.0.0-beta.1/node_modules/args-tokens/lib/resolver.d.ts
5
3
  //#region src/resolver.d.ts
6
4
  /**
7
5
  * An argument schema definition for command-line argument parsing.
@@ -47,19 +45,25 @@ interface ArgSchema {
47
45
  /**
48
46
  * Type of the argument value.
49
47
  *
50
- * - `'string'`: Text value (default if not specified)
51
- * - `'boolean'`: `true`/`false` flag (can be negatable with `--no-` prefix)
48
+ * - `'string'`: Text value
49
+ * - `'boolean'`: `true`/`false` flag (can be negatable with `--no-` prefix). `--flag=true` and
50
+ * `--flag=false` set the value explicitly; any other value after `=` is a type error
52
51
  * - `'number'`: Numeric value (parsed as integer or float)
53
- * - `'enum'`: One of predefined string values (requires `choices` property)
52
+ * - `'enum'`: One of predefined string values (requires `choices` property, unless the argument
53
+ * has a `parse` function)
54
54
  * - `'positional'`: Non-option argument by position
55
55
  * - `'custom'`: Custom parsing with user-defined `parse` function
56
56
  *
57
+ * Any other `type`, or no `type`, is a mistake that only untyped code can make: if the argument
58
+ * has no `parse` function, {@link resolveArgs} and `parse()` throw an `Error`, whether or not the
59
+ * argument is given.
60
+ *
57
61
  * @example
58
62
  * Different argument types:
59
63
  * ```ts
60
64
  * {
61
65
  * name: { type: 'string' }, // --name value
62
- * verbose: { type: 'boolean' }, // --verbose or --no-verbose
66
+ * verbose: { type: 'boolean' }, // --verbose (--no-verbose needs negatable: true)
63
67
  * port: { type: 'number' }, // --port 3000
64
68
  * level: { type: 'enum', choices: ['debug', 'info'] },
65
69
  * file: { type: 'positional' }, // first positional arg
@@ -134,14 +138,32 @@ interface ArgSchema {
134
138
  /**
135
139
  * Marks the argument as required.
136
140
  *
137
- * When `true`, the argument must be provided by the user.
138
- * If missing, an `ArgResolveError` with type 'required' will be thrown.
141
+ * When `true`, the argument must be provided by the user. If it is missing, the error is an
142
+ * `ArgResolveError` with type 'required' and the code `err:arg:required-option`
143
+ * ({@link ArgsValidationErrorKeys}.requiredOption), or `err:arg:required-positional`
144
+ * ({@link ArgsValidationErrorKeys}.requiredPositional) for a positional argument. Its
145
+ * `values` has the `displayName` as in the message, such as `'--name'` for an option
146
+ * (`'--name' or '-n'` with the short name `n`) and `'file'` for a positional argument, and
147
+ * the `name`, which is the schema key.
148
+ * An option that is given without a value is reported as `err:arg:missing-value`
149
+ * ({@link ArgsValidationErrorKeys}.missingValue) instead, because the option itself was given.
150
+ * An explicit empty value, such as `--name=` or `-n ''`, is still reported as required, but the
151
+ * option counts as given: it is `true` in `explicit` and takes part in conflicts, as any other
152
+ * given option does.
139
153
  *
140
- * For single-value positional arguments, omitting `required` keeps the argument
141
- * required for compatibility. Set `required: false` to make a positional argument
142
- * optional. Optional positional arguments leave enough input values for later
154
+ * For single-value positional arguments, omitting `required` keeps the argument required for
155
+ * compatibility, unless it has a `default`, which makes it optional. A `multiple` positional
156
+ * argument is optional unless `required: true` is set. Set `required: false` to make a positional
157
+ * argument explicitly optional. Optional positional arguments leave enough input values for later
143
158
  * required positional arguments before consuming a value.
144
159
  *
160
+ * In the type of the values, such as {@link ArgValues}, a single-value positional argument whose
161
+ * `required` may be `false`, such as one of type `boolean`, is optional, as it may be missing,
162
+ * unless it has a `default`. An optional `required` of type `boolean`, as declared here, says
163
+ * nothing, and keeps it required. TypeScript widens a `required: true` to `boolean` in a schema
164
+ * written apart from the call, such as `{ type: 'positional' as const, required: true }`, which
165
+ * types the argument as optional: write such a schema `as const`.
166
+ *
145
167
  * @example
146
168
  * Required arguments:
147
169
  * ```ts
@@ -162,8 +184,9 @@ interface ArgSchema {
162
184
  /**
163
185
  * Allows the argument to accept multiple values.
164
186
  *
165
- * When `true`, the resolved value becomes an array.
166
- * For options: can be specified multiple times (--tag foo --tag bar)
187
+ * When `true`, the resolved value becomes an array. When the argument is not given and has no
188
+ * `default`, its value is `undefined`, not an empty array.
189
+ * For options: can be specified multiple times (--tags foo --tags bar)
167
190
  * For positional: collects remaining positional arguments after preserving values for
168
191
  * later required positional arguments.
169
192
  *
@@ -195,6 +218,12 @@ interface ArgSchema {
195
218
  *
196
219
  * Only applicable to `type: 'boolean'` arguments.
197
220
  *
221
+ * The negated name is always `no-` followed by the full option name. An option named
222
+ * `no-cache` is negated by `--no-no-cache`, and `--no-cache` sets it to `true`.
223
+ *
224
+ * The negated form does not take a value. `--no-flag=<value>` is reported as
225
+ * `err:arg:unexpected-value` ({@link ArgsValidationErrorKeys}.unexpectedValue).
226
+ *
198
227
  * @example
199
228
  * Negatable boolean:
200
229
  * ```ts
@@ -213,8 +242,17 @@ interface ArgSchema {
213
242
  /**
214
243
  * Array of allowed string values for enum-type arguments.
215
244
  *
216
- * Required when `type: 'enum'`. The argument value must be one of these choices,
217
- * otherwise an `ArgResolveError` with type 'type' will be thrown.
245
+ * Required when `type: 'enum'`, unless the argument has a `parse` function: if `choices` is
246
+ * missing or not an array, {@link resolveArgs} and `parse()` throw a `TypeError`, whether or not
247
+ * the argument is given. With a `parse` function and no `choices`, the value is passed to the
248
+ * function as for a `string` argument with a `parse` function.
249
+ *
250
+ * The argument value must be one of these choices, otherwise the error is an `ArgResolveError`
251
+ * with type 'type' and the code `err:arg:invalid-choice`
252
+ * ({@link ArgsValidationErrorKeys}.invalidChoice).
253
+ *
254
+ * The value is checked before `parse` is called, so a `parse` function receives only one of
255
+ * these choices and can change it, for example to upper case.
218
256
  *
219
257
  * Supports both mutable arrays and readonly arrays for type safety.
220
258
  *
@@ -238,18 +276,37 @@ interface ArgSchema {
238
276
  */
239
277
  choices?: string[] | readonly string[];
240
278
  /**
241
- * Default value used when the argument is not provided.
279
+ * Default value used when the argument is not provided. An option that is given without a value,
280
+ * or with a value that is rejected, also gets its default, along with the error.
242
281
  *
243
282
  * The type must match the argument's `type` property:
244
283
  * - `string` type: string default
245
284
  * - `boolean` type: boolean default
246
285
  * - `number` type: number default
247
- * - `enum` type: must be one of the `choices` values
286
+ * - `enum` type: one of the `choices` values, or a value that a `parse` of your own returns
248
287
  * - `positional`/`custom` type: string, boolean, or number default
249
288
  *
250
- * For single-value positional arguments, the default is used when the positional
251
- * value is missing or when the value is preserved for later required positional
252
- * arguments, unless `required: true` is set.
289
+ * The default is used as is and never goes through `parse`, including when an option is given
290
+ * without a value. An explicit empty value, such as `--name=` or `-n ''`, is a value, not a
291
+ * missing one: a `string` option without `parse` gets `''` instead of the default, unless it is
292
+ * `required`. What `parse` returns is a value too, even `undefined` or `null`, and the default
293
+ * does not replace it.
294
+ *
295
+ * The value of a `multiple` argument is an array, so its default becomes the only element of the
296
+ * array: `default: 'latest'` gives `['latest']`.
297
+ *
298
+ * The default of an `enum` option with `choices` is checked when it would be used, that is, when
299
+ * no value from the command line is used: one that is not one of the choices is reported as an
300
+ * `ArgResolveError` with type 'type' and the code `err:arg:invalid-default`
301
+ * ({@link ArgsValidationErrorKeys}.invalidDefault), and is not used. With a `parse` function of
302
+ * your own, or a `map()` transform, the default is a value that the function returns, which need
303
+ * not be one of the choices, and it is not checked. `choice()` returns the value as is, so its
304
+ * default is checked.
305
+ *
306
+ * For positional arguments, `multiple` ones included, the default is used when no value is left
307
+ * for the argument: when the positional values run out, or when the remaining ones are preserved
308
+ * for later required positional arguments. With `required: true`, the default is not used, and
309
+ * the argument is reported as required instead.
253
310
  *
254
311
  * @example
255
312
  * Default values by type:
@@ -282,7 +339,8 @@ interface ArgSchema {
282
339
  * When `true`, a property like `maxCount` becomes available as `--max-count`.
283
340
  * This allows [CAC](https://github.com/cacjs/cac) user-friendly property names while maintaining CLI conventions.
284
341
  *
285
- * Can be overridden globally with `resolveArgs({ toKebab: true })`.
342
+ * The `toKebab` option of {@link resolveArgs} and `parse()` applies it to all arguments, as in
343
+ * `resolveArgs(args, tokens, { toKebab: true })`.
286
344
  *
287
345
  * Note: Only `true` is allowed (not `false`) to make intent explicit.
288
346
  *
@@ -306,8 +364,19 @@ interface ArgSchema {
306
364
  /**
307
365
  * Names of other options that conflict with this option.
308
366
  *
309
- * When this option is used together with any of the conflicting options,
310
- * an `ArgResolveError` with type 'conflict' will be thrown.
367
+ * When this option is used together with any of the conflicting options, the error is an
368
+ * `ArgResolveError` with type 'conflict' and the code `err:arg:conflict`
369
+ * ({@link ArgsValidationErrorKeys}.conflict). Its `values` has the `displayName` and `name` of
370
+ * the argument whose `conflicts` names the other one, and the `conflictDisplayName` and
371
+ * `conflictName` of the other one. `displayName` and `conflictDisplayName` show an option as
372
+ * it was written, such as `'-p'`, and `name` and `conflictName` are the schema keys. When both
373
+ * name each other, `name` is the one that comes first in the schema.
374
+ *
375
+ * A positional argument can be on either side, such as `[file]` and `--stdin`. It conflicts when
376
+ * it is given, and it is shown by its name, such as `'file'` (in kebab-case with `toKebab`), as
377
+ * in its other errors. The message starts with the kind of the argument given as `name`:
378
+ * `Positional argument 'file' conflicts with '--stdin'` or
379
+ * `Optional argument '--stdin' conflicts with 'file'`.
311
380
  *
312
381
  * Conflicts only need to be defined on one side - if option A defines a conflict
313
382
  * with option B, the conflict is automatically detected when both are used,
@@ -345,7 +414,7 @@ interface ArgSchema {
345
414
  * // No conflicts defined, but still cannot use with --summer
346
415
  * }
347
416
  * }
348
- * // Usage: --summer --autumn will throw error
417
+ * // Usage: --summer --autumn reports an error
349
418
  * // Error: "Optional argument '--summer' conflicts with '--autumn'"
350
419
  * ```
351
420
  *
@@ -397,6 +466,10 @@ interface ArgSchema {
397
466
  * Particularly useful for `type: 'custom'` arguments where the type
398
467
  * name would otherwise be unhelpful.
399
468
  *
469
+ * For a `custom` option that is given without a value, it is also the `expected` in the `values`
470
+ * of the `err:arg:missing-value` error ({@link ArgsValidationErrorKeys}.missingValue), which is
471
+ * `'custom'` without it.
472
+ *
400
473
  * @example
401
474
  * Metavar usage:
402
475
  * ```ts
@@ -413,13 +486,37 @@ interface ArgSchema {
413
486
  */
414
487
  metavar?: string;
415
488
  /**
416
- * Custom parsing function for `type: 'custom'` arguments.
489
+ * Custom parsing function, used in place of the parsing of the argument's `type`.
417
490
  *
418
- * Required when `type: 'custom'`. Receives the raw string value and must
419
- * return the parsed result. Should throw an Error (or subclass) if parsing fails.
491
+ * Required when `type: 'custom'`: if it is missing or not a function, {@link resolveArgs} and
492
+ * `parse()` throw a `TypeError`, whether or not the argument is given. The function receives the
493
+ * raw string value and must return the parsed result. It should throw an Error (or subclass) if
494
+ * parsing fails.
420
495
  *
421
496
  * The function's return type becomes the resolved argument type.
422
497
  *
498
+ * `parse` is called synchronously, and what it returns becomes the value, even `undefined` or
499
+ * `null`, so throw to reject a value. An `async` function returns a promise, and the promise
500
+ * becomes the value as is: it is not awaited, and its rejection is not reported as an error.
501
+ * Await the value, or each of its elements with `multiple` (for example with `Promise.all()`),
502
+ * and handle the rejection yourself: a rejection that nothing handles is an unhandled rejection,
503
+ * which ends a Node.js process by default.
504
+ *
505
+ * A `boolean` option calls `parse` with `'true'`, or `'false'` for the negated form. Other
506
+ * options call it only with a value from the command line: when the option is given without a
507
+ * value, `parse` is not called and the missing value is reported as `err:arg:missing-value`
508
+ * ({@link ArgsValidationErrorKeys}.missingValue). When that error may suggest the argument after
509
+ * the option as its value, such as `--port=-5` for `--port -5`, a `parse` function of your own
510
+ * is not called to check it either: only the `parse` functions of `string()`, `number()`,
511
+ * `integer()`, `float()` and `choice()`, which have no side effects, are called for that.
512
+ * An explicit empty value, such as `--name=` or `-n=`, is passed as `''` unless
513
+ * `required: true` is set.
514
+ *
515
+ * An `enum` option with `choices` calls it only with one of them. Any other value, an explicit
516
+ * empty one included, is reported as `err:arg:invalid-choice`
517
+ * ({@link ArgsValidationErrorKeys}.invalidChoice), except that a required option reports an
518
+ * explicit empty value as required.
519
+ *
423
520
  * @param value - Raw string value from command line
424
521
  * @returns Parsed value of any type
425
522
  * @throws {Error} Error or subclass when value is invalid
@@ -464,7 +561,6 @@ interface Args$1 {
464
561
  }
465
562
  //#endregion
466
563
  //#region ../gunshi/src/types.d.ts
467
-
468
564
  /**
469
565
  * Extend command context type. This type is used to extend the command context with additional properties at {@linkcode CommandContext.extensions}.
470
566
  *
@@ -530,27 +626,21 @@ type CommonArgType = {
530
626
  };
531
627
  declare const COMMON_ARGS: CommonArgType;
532
628
  declare const COMMAND_BUILTIN_RESOURCE_KEYS: readonly ["USAGE", "COMMAND", "SUBCOMMAND", "COMMANDS", "ARGUMENTS", "OPTIONS", "EXAMPLES", "FORMORE", "NEGATABLE", "DEFAULT", "CHOICES"];
533
- 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"];
534
- declare const COMMAND_ERROR_RESOURCE_KEYS: readonly ["err:cmd:not-found"];
629
+ 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"];
630
+ declare const ARG_ERROR_HINT_RESOURCE_KEYS: readonly ["err:arg:missing-value:hint"];
631
+ declare const COMMAND_ERROR_RESOURCE_KEYS: readonly ["err:cmd:not-found", "err:cmd:ambiguous", "err:cmd:inconsistent-options", "err:cmd:lazy-schema-mismatch"];
535
632
  declare const SUGGESTION_ERROR_RESOURCE_KEYS: readonly ["err:suggestion:did-you-mean"];
536
- //#endregion
537
- //#region ../gunshi/src/index.d.ts
538
-
539
633
  //#endregion
540
634
  //#region ../shared/src/types.d.ts
541
- type RemoveIndexSignature<T> = { [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K] };
542
- /**
543
- * Make all properties in T deeply writeable (not readonly)
544
- */
545
-
635
+ type RemoveIndexSignature<T> = { [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K]; };
546
636
  /**
547
637
  * Remove index signature from object or record type.
548
638
  */
549
- type RemovedIndex<T> = RemoveIndexSignature<{ [K in keyof T]: T[K] }>;
639
+ type RemovedIndex<T> = RemoveIndexSignature<{ [K in keyof T]: T[K]; }>;
550
640
  /**
551
641
  * Resolve a key on {@link Args}.
552
642
  */
553
- type KeyOfArgs<A extends Args$1> = keyof A | { [K in keyof A]: A[K]['type'] extends 'boolean' ? A[K]['negatable'] extends true ? `no-${Extract<K, string>}` : never : never }[keyof A];
643
+ type KeyOfArgs<A extends Args$1> = keyof A | { [K in keyof A]: A[K]['type'] extends 'boolean' ? A[K]['negatable'] extends true ? `no-${Extract<K, string>}` : never : never; }[keyof A];
554
644
  /**
555
645
  * Generate a namespaced key.
556
646
  */
@@ -567,6 +657,10 @@ type CommandBuiltinResourceKeys = (typeof COMMAND_BUILTIN_RESOURCE_KEYS)[number]
567
657
  * Args validation error resource keys.
568
658
  */
569
659
  type ArgErrorResourceKeys = (typeof ARG_ERROR_RESOURCE_KEYS)[number];
660
+ /**
661
+ * Resource keys of the hints that follow an args validation error.
662
+ */
663
+ type ArgErrorHintResourceKeys = (typeof ARG_ERROR_HINT_RESOURCE_KEYS)[number];
570
664
  /**
571
665
  * Command validation error resource keys.
572
666
  */
@@ -578,7 +672,7 @@ type SuggestionErrorResourceKeys = (typeof SUGGESTION_ERROR_RESOURCE_KEYS)[numbe
578
672
  /**
579
673
  * Error resource keys.
580
674
  */
581
- type ErrorResourceKeys = ArgErrorResourceKeys | CommandErrorResourceKeys | SuggestionErrorResourceKeys;
675
+ type ErrorResourceKeys = ArgErrorResourceKeys | ArgErrorHintResourceKeys | CommandErrorResourceKeys | SuggestionErrorResourceKeys;
582
676
  /**
583
677
  * Built-in resource keys.
584
678
  */
@@ -601,16 +695,11 @@ type CommandArgKeys<A extends Args$1, C = {}, K extends string = GenerateNamespa
601
695
  /**
602
696
  * Resolve translation keys for command context.
603
697
  */
604
- type ResolveTranslationKeys<A extends Args$1, C = {},
605
- // for CommandContext
606
- E extends Record<string, string> = {},
607
- // for extended resources
608
- R extends string = keyof RemovedIndex<E>, T extends string = (C extends {
698
+ type ResolveTranslationKeys<A extends Args$1, C = {} // for CommandContext
699
+ , E extends Record<string, string> = {} // for extended resources
700
+ , R extends string = keyof RemovedIndex<E>, T extends string = C extends {
609
701
  name: infer N;
610
- } ? N extends string ? GenerateNamespacedKey<R, N> : R : R | CommandBuiltinKeys), O = CommandArgKeys<A, C>> = ErrorResourceKeys | CommandBuiltinKeys | O | T;
611
- //#endregion
612
- //#region ../shared/src/localization.d.ts
613
-
702
+ } ? N extends string ? GenerateNamespacedKey<R, N> : R : R | CommandBuiltinKeys, O = CommandArgKeys<A, C>> = ErrorResourceKeys | CommandBuiltinKeys | O | T;
614
703
  //#endregion
615
704
  //#region ../shared/src/utils.d.ts
616
705
  /**
@@ -648,10 +737,7 @@ declare function resolveArgKey<A extends Args$1 = DefaultGunshiParams$1['args'],
648
737
  * @param name - The command name.
649
738
  * @returns Prefixed non-built-in key.
650
739
  */
651
- declare function resolveKey<T extends Record<string, string> = {}, K extends string = (keyof T extends string ? keyof T : string)>(key: K, name?: string): string;
652
- //#endregion
653
- //#region ../shared/src/index.d.ts
654
-
740
+ declare function resolveKey<T extends Record<string, string> = {}, K extends string = keyof T extends string ? keyof T : string>(key: K, name?: string): string;
655
741
  //#endregion
656
742
  //#region src/types.d.ts
657
743
  /**
@@ -686,11 +772,9 @@ interface I18nExtension<G extends GunshiParams<any> = DefaultGunshiParams> {
686
772
  * - For custom keys: returns an empty string ('')
687
773
  * - For built-in keys (prefixed with '_:'): returns the key itself
688
774
  */
689
- translate: <A extends Args = G['args'], C = {},
690
- // for CommandContext
691
- E extends Record<string, string> = {},
692
- // for extended resources
693
- K = ResolveTranslationKeys<A, C, E>>(key: K, values?: Record<string, unknown>) => string;
775
+ translate: <A extends Args = G['args'], C = {} // for CommandContext
776
+ , E extends Record<string, string> = {} // for extended resources
777
+ , K = ResolveTranslationKeys<A, C, E>>(key: K, values?: Record<string, unknown>) => string;
694
778
  /**
695
779
  * Load command resources.
696
780
  *
@@ -793,7 +877,7 @@ type CommandResource<G extends GunshiParamsConstraint = DefaultGunshiParams> = {
793
877
  * Command description.
794
878
  */
795
879
  description: string;
796
- } & { [Arg in GenerateNamespacedKey<KeyOfArgs<RemovedIndex<ExtractArgs<G>>>, typeof ARG_PREFIX>]?: string } & {
880
+ } & { [Arg in GenerateNamespacedKey<KeyOfArgs<RemovedIndex<ExtractArgs<G>>>, typeof ARG_PREFIX>]?: string; } & {
797
881
  [key: string]: string;
798
882
  };
799
883
  /**
@@ -828,7 +912,7 @@ type I18nCommandDefinitionResult<G extends GunshiParamsConstraint = DefaultGunsh
828
912
  resource: CommandResourceFetcher<G>;
829
913
  } : {
830
914
  resource?: CommandResourceFetcher<G> | undefined;
831
- }) & { [K in Exclude<keyof I18nCommand<G>, keyof C | 'resource'>]?: I18nCommand<G>[K] }>;
915
+ }) & { [K in Exclude<keyof I18nCommand<G>, keyof C | 'resource'>]?: I18nCommand<G>[K]; }>;
832
916
  /**
833
917
  * The result type of the {@linkcode withI18nResource} function
834
918
  *
@@ -836,7 +920,7 @@ type I18nCommandDefinitionResult<G extends GunshiParamsConstraint = DefaultGunsh
836
920
  */
837
921
  type WithI18nResourceResult<G extends GunshiParamsConstraint = DefaultGunshiParams, C extends Command<G> = Command<G>> = Prettify<C & {
838
922
  resource: CommandResourceFetcher<G>;
839
- } & { [K in Exclude<keyof I18nCommand<G>, keyof C | 'resource'>]?: I18nCommand<G>[K] }>;
923
+ } & { [K in Exclude<keyof I18nCommand<G>, keyof C | 'resource'>]?: I18nCommand<G>[K]; }>;
840
924
  /**
841
925
  * Define an i18n-aware {@link I18nCommand | command}.
842
926
  *
package/lib/index.js CHANGED
@@ -34,12 +34,20 @@ var en_US_default = {
34
34
  help: "Display this help message",
35
35
  version: "Display this version",
36
36
  "err:arg:required-option": "Optional argument {$displayName} is required",
37
- "err:arg:required-positional": "Positional argument {$name} is required",
37
+ "err:arg:required-positional": "Positional argument {$displayName} is required",
38
38
  "err:arg:invalid-type": "Invalid value for {$displayName}: expected {$expected}",
39
39
  "err:arg:invalid-choice": "Invalid value for {$displayName}: expected one of {$choices}",
40
40
  "err:arg:custom-parse": "Invalid value for {$displayName}: {$reason}",
41
41
  "err:arg:unknown-option": "Unknown option: {$rawName}",
42
+ "err:arg:unexpected-value": "Optional argument {$displayName} does not take a value",
43
+ "err:arg:missing-value": "Optional argument {$displayName} requires a value",
44
+ "err:arg:missing-value:hint": "(to pass '{$next}' as its value, write '{$suggestion}')",
45
+ "err:arg:conflict": "{$displayName} conflicts with {$conflictDisplayName}",
46
+ "err:arg:invalid-default": "Invalid default for {$displayName}: {$actual} is not one of {$choices}",
42
47
  "err:cmd:not-found": "Command not found: {$commandName}",
48
+ "err:cmd:ambiguous": "The command is ambiguous. Move options after the command name: {$candidatePaths}",
49
+ "err:cmd:inconsistent-options": "The options do not identify a consistent command. Move options after the command name.",
50
+ "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}",
43
51
  "err:suggestion:did-you-mean": "Did you mean {$name}?"
44
52
  };
45
53
  //#endregion
@@ -376,6 +384,7 @@ function i18n(options = {}) {
376
384
  fallbackLocale: DEFAULT_LOCALE
377
385
  });
378
386
  const localeBuiltinResources = /* @__PURE__ */ new Map();
387
+ const loadedCommandResources = /* @__PURE__ */ new Map();
379
388
  const builtinGlobalOptions = Object.keys(COMMON_ARGS);
380
389
  const globalOptionResources = /* @__PURE__ */ new Map();
381
390
  return plugin({
@@ -445,7 +454,17 @@ function i18n(options = {}) {
445
454
  const globalOptionKey = resolveArgKey(globalOption, ctx.name);
446
455
  resource[globalOptionKey] = optionResource[localeStr] || optionResource["en-US"] || Object.values(optionResource)[0] || "";
447
456
  }
448
- adapter.setResource(localeStr, Object.assign(Object.create(null), adapter.getResource(localeStr), resource));
457
+ /**
458
+ * NOTE(kazupon): merge into the resource this function handed to the adapter before,
459
+ * when the adapter still holds it. Copying it on every call makes loading N commands
460
+ * cost O(N^2), which shows up when a plugin loads the resources of a whole command tree.
461
+ * Anything else the adapter returns is left alone: a custom adapter may return a copy,
462
+ * the resource of another locale as a fallback, or freeze what it is given.
463
+ */
464
+ const currentResource = adapter.getResource(localeStr);
465
+ const mergedResource = currentResource && loadedCommandResources.get(localeStr) === currentResource && Object.isExtensible(currentResource) ? Object.assign(currentResource, resource) : Object.assign(Object.create(null), currentResource, resource);
466
+ loadedCommandResources.set(localeStr, mergedResource);
467
+ adapter.setResource(localeStr, mergedResource);
449
468
  return loaded;
450
469
  }
451
470
  return {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gunshi/plugin-i18n",
3
3
  "description": "internationalization plugin for gunshi",
4
- "version": "0.37.3",
4
+ "version": "1.0.0-beta.1",
5
5
  "author": {
6
6
  "name": "kazuya kawaguchi",
7
7
  "email": "kawakazu80@gmail.com"
@@ -53,10 +53,10 @@
53
53
  }
54
54
  },
55
55
  "dependencies": {
56
- "@gunshi/plugin": "0.37.3"
56
+ "@gunshi/plugin": "1.0.0-beta.1"
57
57
  },
58
58
  "peerDependencies": {
59
- "@gunshi/plugin-global": "0.37.3"
59
+ "@gunshi/plugin-global": "1.0.0-beta.1"
60
60
  },
61
61
  "peerDependenciesMeta": {
62
62
  "@gunshi/plugin-global": {
@@ -64,19 +64,19 @@
64
64
  }
65
65
  },
66
66
  "devDependencies": {
67
+ "@gunshi/bone": "1.0.0-beta.1",
68
+ "@gunshi/plugin-global": "1.0.0-beta.1",
69
+ "@gunshi/plugin-renderer": "1.0.0-beta.1",
70
+ "@gunshi/resources": "1.0.0-beta.1",
71
+ "@gunshi/shared": "1.0.0-beta.1",
67
72
  "@intlify/core-base": "12.0.0-alpha.4",
68
73
  "deno": "^2.7.14",
74
+ "gunshi": "1.0.0-beta.1",
69
75
  "jsr": "^0.14.3",
70
76
  "jsr-exports-lint": "^0.4.2",
71
77
  "messageformat": "4.0.0",
72
78
  "publint": "^0.3.20",
73
- "tsdown": "0.21.0",
74
- "@gunshi/plugin-global": "0.37.3",
75
- "@gunshi/bone": "0.37.3",
76
- "@gunshi/plugin-renderer": "0.37.3",
77
- "@gunshi/resources": "0.37.3",
78
- "@gunshi/shared": "0.37.3",
79
- "gunshi": "0.37.3"
79
+ "tsdown": "0.22.14"
80
80
  },
81
81
  "scripts": {
82
82
  "build": "tsdown",