@gunshi/plugin-renderer 1.0.0-beta.0 → 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.
package/lib/index.d.ts CHANGED
@@ -1,18 +1,567 @@
1
1
  import { Args, Command, CommandContext, DefaultGunshiParams, GunshiParams, PluginWithExtension } from "@gunshi/plugin";
2
- import { Args as Args$1 } from "args-tokens";
3
-
4
- //#region ../gunshi/src/types.d.ts
5
- /**
6
- * @author kazuya kawaguchi (a.k.a. kazupon)
7
- * @license MIT
8
- */
9
-
2
+ import "@gunshi/plugin-i18n";
3
+ //#region ../../node_modules/.pnpm/args-tokens@1.0.0-beta.1/node_modules/args-tokens/lib/resolver.d.ts
4
+ //#region src/resolver.d.ts
5
+ /**
6
+ * An argument schema definition for command-line argument parsing.
7
+ *
8
+ * This schema is similar to the schema of Node.js `util.parseArgs` but with extended features:
9
+ * - Additional `required`, `description`, and `hidden` properties
10
+ * - Extended `type` support: 'string', 'boolean', 'number', 'enum', 'positional', 'custom'
11
+ * - Simplified `default` property (single type, not union types)
12
+ *
13
+ * @example
14
+ * Basic string argument:
15
+ * ```ts
16
+ * const schema: ArgSchema = {
17
+ * type: 'string',
18
+ * description: 'Server hostname',
19
+ * default: 'localhost'
20
+ * }
21
+ * ```
22
+ *
23
+ * @example
24
+ * Required number argument with alias:
25
+ * ```ts
26
+ * const schema: ArgSchema = {
27
+ * type: 'number',
28
+ * short: 'p',
29
+ * description: 'Port number to listen on',
30
+ * required: true
31
+ * }
32
+ * ```
33
+ *
34
+ * @example
35
+ * Enum argument with choices:
36
+ * ```ts
37
+ * const schema: ArgSchema = {
38
+ * type: 'enum',
39
+ * choices: ['info', 'warn', 'error'],
40
+ * description: 'Logging level',
41
+ * default: 'info'
42
+ * }
43
+ * ```
44
+ */
45
+ interface ArgSchema {
46
+ /**
47
+ * Type of the argument value.
48
+ *
49
+ * - `'string'`: Text value
50
+ * - `'boolean'`: `true`/`false` flag (can be negatable with `--no-` prefix). `--flag=true` and
51
+ * `--flag=false` set the value explicitly; any other value after `=` is a type error
52
+ * - `'number'`: Numeric value (parsed as integer or float)
53
+ * - `'enum'`: One of predefined string values (requires `choices` property, unless the argument
54
+ * has a `parse` function)
55
+ * - `'positional'`: Non-option argument by position
56
+ * - `'custom'`: Custom parsing with user-defined `parse` function
57
+ *
58
+ * Any other `type`, or no `type`, is a mistake that only untyped code can make: if the argument
59
+ * has no `parse` function, {@link resolveArgs} and `parse()` throw an `Error`, whether or not the
60
+ * argument is given.
61
+ *
62
+ * @example
63
+ * Different argument types:
64
+ * ```ts
65
+ * {
66
+ * name: { type: 'string' }, // --name value
67
+ * verbose: { type: 'boolean' }, // --verbose (--no-verbose needs negatable: true)
68
+ * port: { type: 'number' }, // --port 3000
69
+ * level: { type: 'enum', choices: ['debug', 'info'] },
70
+ * file: { type: 'positional' }, // first positional arg
71
+ * config: { type: 'custom', parse: JSON.parse }
72
+ * }
73
+ * ```
74
+ */
75
+ type: 'string' | 'boolean' | 'number' | 'enum' | 'positional' | 'custom';
76
+ /**
77
+ * Single character alias for the long option name.
78
+ *
79
+ * As example, allows users to use `-x` instead of `--extended-option`.
80
+ * Only valid for non-positional argument types.
81
+ *
82
+ * @example
83
+ * Short alias usage:
84
+ * ```ts
85
+ * {
86
+ * verbose: {
87
+ * type: 'boolean',
88
+ * short: 'v' // Enables both --verbose and -v
89
+ * },
90
+ * port: {
91
+ * type: 'number',
92
+ * short: 'p' // Enables both --port 3000 and -p 3000
93
+ * }
94
+ * }
95
+ * ```
96
+ */
97
+ short?: string;
98
+ /**
99
+ * Human-readable description of the argument's purpose.
100
+ *
101
+ * Used for help text generation and documentation.
102
+ * Should be concise but descriptive enough to understand the argument's role.
103
+ *
104
+ * @example
105
+ * Descriptive help text:
106
+ * ```ts
107
+ * {
108
+ * config: {
109
+ * type: 'string',
110
+ * description: 'Path to configuration file'
111
+ * },
112
+ * timeout: {
113
+ * type: 'number',
114
+ * description: 'Request timeout in milliseconds'
115
+ * }
116
+ * }
117
+ * ```
118
+ */
119
+ description?: string;
120
+ /**
121
+ * Hide the argument from generated help or usage output.
122
+ *
123
+ * This is metadata for renderers. It does not affect parsing, validation,
124
+ * required checks, defaults, conflicts, or resolved values.
125
+ *
126
+ * @example
127
+ * Hidden compatibility option:
128
+ * ```ts
129
+ * {
130
+ * legacy: {
131
+ * type: 'string',
132
+ * hidden: true,
133
+ * description: 'Deprecated compatibility option'
134
+ * }
135
+ * }
136
+ * ```
137
+ */
138
+ hidden?: boolean;
139
+ /**
140
+ * Marks the argument as required.
141
+ *
142
+ * When `true`, the argument must be provided by the user. If it is missing, the error is an
143
+ * `ArgResolveError` with type 'required' and the code `err:arg:required-option`
144
+ * ({@link ArgsValidationErrorKeys}.requiredOption), or `err:arg:required-positional`
145
+ * ({@link ArgsValidationErrorKeys}.requiredPositional) for a positional argument. Its
146
+ * `values` has the `displayName` as in the message, such as `'--name'` for an option
147
+ * (`'--name' or '-n'` with the short name `n`) and `'file'` for a positional argument, and
148
+ * the `name`, which is the schema key.
149
+ * An option that is given without a value is reported as `err:arg:missing-value`
150
+ * ({@link ArgsValidationErrorKeys}.missingValue) instead, because the option itself was given.
151
+ * An explicit empty value, such as `--name=` or `-n ''`, is still reported as required, but the
152
+ * option counts as given: it is `true` in `explicit` and takes part in conflicts, as any other
153
+ * given option does.
154
+ *
155
+ * For single-value positional arguments, omitting `required` keeps the argument required for
156
+ * compatibility, unless it has a `default`, which makes it optional. A `multiple` positional
157
+ * argument is optional unless `required: true` is set. Set `required: false` to make a positional
158
+ * argument explicitly optional. Optional positional arguments leave enough input values for later
159
+ * required positional arguments before consuming a value.
160
+ *
161
+ * In the type of the values, such as {@link ArgValues}, a single-value positional argument whose
162
+ * `required` may be `false`, such as one of type `boolean`, is optional, as it may be missing,
163
+ * unless it has a `default`. An optional `required` of type `boolean`, as declared here, says
164
+ * nothing, and keeps it required. TypeScript widens a `required: true` to `boolean` in a schema
165
+ * written apart from the call, such as `{ type: 'positional' as const, required: true }`, which
166
+ * types the argument as optional: write such a schema `as const`.
167
+ *
168
+ * @example
169
+ * Required arguments:
170
+ * ```ts
171
+ * {
172
+ * input: {
173
+ * type: 'string',
174
+ * required: true, // Must be provided: --input file.txt
175
+ * description: 'Input file path'
176
+ * },
177
+ * source: {
178
+ * type: 'positional',
179
+ * required: true // First positional argument must exist
180
+ * }
181
+ * }
182
+ * ```
183
+ */
184
+ required?: boolean;
185
+ /**
186
+ * Allows the argument to accept multiple values.
187
+ *
188
+ * When `true`, the resolved value becomes an array. When the argument is not given and has no
189
+ * `default`, its value is `undefined`, not an empty array.
190
+ * For options: can be specified multiple times (--tags foo --tags bar)
191
+ * For positional: collects remaining positional arguments after preserving values for
192
+ * later required positional arguments.
193
+ *
194
+ * Note: Only `true` is allowed (not `false`) to make intent explicit.
195
+ *
196
+ * @example
197
+ * Multiple values:
198
+ * ```ts
199
+ * {
200
+ * tags: {
201
+ * type: 'string',
202
+ * multiple: true, // --tags foo --tags bar → ['foo', 'bar']
203
+ * description: 'Tags to apply'
204
+ * },
205
+ * files: {
206
+ * type: 'positional',
207
+ * multiple: true // Collects all remaining positional args
208
+ * }
209
+ * }
210
+ * ```
211
+ */
212
+ multiple?: true;
213
+ /**
214
+ * Enables negation for boolean arguments using `--no-` prefix.
215
+ *
216
+ * When `true`, allows users to explicitly set the boolean to `false`
217
+ * using `--no-option-name`. When `false` or omitted, only positive
218
+ * form is available.
219
+ *
220
+ * Only applicable to `type: 'boolean'` arguments.
221
+ *
222
+ * The negated name is always `no-` followed by the full option name. An option named
223
+ * `no-cache` is negated by `--no-no-cache`, and `--no-cache` sets it to `true`.
224
+ *
225
+ * The negated form does not take a value. `--no-flag=<value>` is reported as
226
+ * `err:arg:unexpected-value` ({@link ArgsValidationErrorKeys}.unexpectedValue).
227
+ *
228
+ * @example
229
+ * Negatable boolean:
230
+ * ```ts
231
+ * {
232
+ * color: {
233
+ * type: 'boolean',
234
+ * negatable: true,
235
+ * default: true,
236
+ * description: 'Enable colorized output'
237
+ * }
238
+ * // Usage: --color (true), --no-color (false)
239
+ * }
240
+ * ```
241
+ */
242
+ negatable?: boolean;
243
+ /**
244
+ * Array of allowed string values for enum-type arguments.
245
+ *
246
+ * Required when `type: 'enum'`, unless the argument has a `parse` function: if `choices` is
247
+ * missing or not an array, {@link resolveArgs} and `parse()` throw a `TypeError`, whether or not
248
+ * the argument is given. With a `parse` function and no `choices`, the value is passed to the
249
+ * function as for a `string` argument with a `parse` function.
250
+ *
251
+ * The argument value must be one of these choices, otherwise the error is an `ArgResolveError`
252
+ * with type 'type' and the code `err:arg:invalid-choice`
253
+ * ({@link ArgsValidationErrorKeys}.invalidChoice).
254
+ *
255
+ * The value is checked before `parse` is called, so a `parse` function receives only one of
256
+ * these choices and can change it, for example to upper case.
257
+ *
258
+ * Supports both mutable arrays and readonly arrays for type safety.
259
+ *
260
+ * @example
261
+ * Enum choices:
262
+ * ```ts
263
+ * {
264
+ * logLevel: {
265
+ * type: 'enum',
266
+ * choices: ['debug', 'info', 'warn', 'error'] as const,
267
+ * default: 'info',
268
+ * description: 'Logging verbosity level'
269
+ * },
270
+ * format: {
271
+ * type: 'enum',
272
+ * choices: ['json', 'yaml', 'toml'],
273
+ * description: 'Output format'
274
+ * }
275
+ * }
276
+ * ```
277
+ */
278
+ choices?: string[] | readonly string[];
279
+ /**
280
+ * Default value used when the argument is not provided. An option that is given without a value,
281
+ * or with a value that is rejected, also gets its default, along with the error.
282
+ *
283
+ * The type must match the argument's `type` property:
284
+ * - `string` type: string default
285
+ * - `boolean` type: boolean default
286
+ * - `number` type: number default
287
+ * - `enum` type: one of the `choices` values, or a value that a `parse` of your own returns
288
+ * - `positional`/`custom` type: string, boolean, or number default
289
+ *
290
+ * The default is used as is and never goes through `parse`, including when an option is given
291
+ * without a value. An explicit empty value, such as `--name=` or `-n ''`, is a value, not a
292
+ * missing one: a `string` option without `parse` gets `''` instead of the default, unless it is
293
+ * `required`. What `parse` returns is a value too, even `undefined` or `null`, and the default
294
+ * does not replace it.
295
+ *
296
+ * The value of a `multiple` argument is an array, so its default becomes the only element of the
297
+ * array: `default: 'latest'` gives `['latest']`.
298
+ *
299
+ * The default of an `enum` option with `choices` is checked when it would be used, that is, when
300
+ * no value from the command line is used: one that is not one of the choices is reported as an
301
+ * `ArgResolveError` with type 'type' and the code `err:arg:invalid-default`
302
+ * ({@link ArgsValidationErrorKeys}.invalidDefault), and is not used. With a `parse` function of
303
+ * your own, or a `map()` transform, the default is a value that the function returns, which need
304
+ * not be one of the choices, and it is not checked. `choice()` returns the value as is, so its
305
+ * default is checked.
306
+ *
307
+ * For positional arguments, `multiple` ones included, the default is used when no value is left
308
+ * for the argument: when the positional values run out, or when the remaining ones are preserved
309
+ * for later required positional arguments. With `required: true`, the default is not used, and
310
+ * the argument is reported as required instead.
311
+ *
312
+ * @example
313
+ * Default values by type:
314
+ * ```ts
315
+ * {
316
+ * host: {
317
+ * type: 'string',
318
+ * default: 'localhost' // string default
319
+ * },
320
+ * verbose: {
321
+ * type: 'boolean',
322
+ * default: false // boolean default
323
+ * },
324
+ * port: {
325
+ * type: 'number',
326
+ * default: 8080 // number default
327
+ * },
328
+ * level: {
329
+ * type: 'enum',
330
+ * choices: ['low', 'high'],
331
+ * default: 'low' // must be in choices
332
+ * }
333
+ * }
334
+ * ```
335
+ */
336
+ default?: string | boolean | number;
337
+ /**
338
+ * Converts the argument name from camelCase to kebab-case for CLI usage.
339
+ *
340
+ * When `true`, a property like `maxCount` becomes available as `--max-count`.
341
+ * This allows [CAC](https://github.com/cacjs/cac) user-friendly property names while maintaining CLI conventions.
342
+ *
343
+ * The `toKebab` option of {@link resolveArgs} and `parse()` applies it to all arguments, as in
344
+ * `resolveArgs(args, tokens, { toKebab: true })`.
345
+ *
346
+ * Note: Only `true` is allowed (not `false`) to make intent explicit.
347
+ *
348
+ * @example
349
+ * Kebab-case conversion:
350
+ * ```ts
351
+ * {
352
+ * maxRetries: {
353
+ * type: 'number',
354
+ * toKebab: true, // Accessible as --max-retries
355
+ * description: 'Maximum retry attempts'
356
+ * },
357
+ * enableLogging: {
358
+ * type: 'boolean',
359
+ * toKebab: true // Accessible as --enable-logging
360
+ * }
361
+ * }
362
+ * ```
363
+ */
364
+ toKebab?: true;
365
+ /**
366
+ * Names of other options that conflict with this option.
367
+ *
368
+ * When this option is used together with any of the conflicting options, the error is an
369
+ * `ArgResolveError` with type 'conflict' and the code `err:arg:conflict`
370
+ * ({@link ArgsValidationErrorKeys}.conflict). Its `values` has the `displayName` and `name` of
371
+ * the argument whose `conflicts` names the other one, and the `conflictDisplayName` and
372
+ * `conflictName` of the other one. `displayName` and `conflictDisplayName` show an option as
373
+ * it was written, such as `'-p'`, and `name` and `conflictName` are the schema keys. When both
374
+ * name each other, `name` is the one that comes first in the schema.
375
+ *
376
+ * A positional argument can be on either side, such as `[file]` and `--stdin`. It conflicts when
377
+ * 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'`.
381
+ *
382
+ * Conflicts only need to be defined on one side - if option A defines a conflict
383
+ * with option B, the conflict is automatically detected when both are used,
384
+ * regardless of whether B also defines a conflict with A.
385
+ *
386
+ * Supports both single option name or array of option names.
387
+ * Option names must match the property keys in the schema object exactly
388
+ * (no automatic conversion between camelCase and kebab-case).
389
+ *
390
+ * @example
391
+ * Single conflict (bidirectional definition):
392
+ * ```ts
393
+ * {
394
+ * summer: {
395
+ * type: 'boolean',
396
+ * conflicts: 'autumn' // Cannot use --summer with --autumn
397
+ * },
398
+ * autumn: {
399
+ * type: 'boolean',
400
+ * conflicts: 'summer' // Can define on both sides for clarity
401
+ * }
402
+ * }
403
+ * ```
404
+ *
405
+ * @example
406
+ * Single conflict (one-way definition):
407
+ * ```ts
408
+ * {
409
+ * summer: {
410
+ * type: 'boolean',
411
+ * conflicts: 'autumn' // Only defined on summer side
412
+ * },
413
+ * autumn: {
414
+ * type: 'boolean'
415
+ * // No conflicts defined, but still cannot use with --summer
416
+ * }
417
+ * }
418
+ * // Usage: --summer --autumn reports an error
419
+ * // Error: "Optional argument '--summer' conflicts with '--autumn'"
420
+ * ```
421
+ *
422
+ * @example
423
+ * Multiple conflicts:
424
+ * ```ts
425
+ * {
426
+ * port: {
427
+ * type: 'number',
428
+ * conflicts: ['socket', 'pipe'], // Cannot use with --socket or --pipe
429
+ * description: 'TCP port number'
430
+ * },
431
+ * socket: {
432
+ * type: 'string',
433
+ * conflicts: ['port', 'pipe'], // Cannot use with --port or --pipe
434
+ * description: 'Unix socket path'
435
+ * },
436
+ * pipe: {
437
+ * type: 'string',
438
+ * conflicts: ['port', 'socket'], // Cannot use with --port or --socket
439
+ * description: 'Named pipe path'
440
+ * }
441
+ * }
442
+ * // These three options are mutually exclusive
443
+ * ```
444
+ *
445
+ * @example
446
+ * With kebab-case conversion:
447
+ * ```ts
448
+ * {
449
+ * summerSeason: {
450
+ * type: 'boolean',
451
+ * toKebab: true, // Accessible as --summer-season
452
+ * conflicts: 'autumnSeason' // Must use property key, not CLI name
453
+ * },
454
+ * autumnSeason: {
455
+ * type: 'boolean',
456
+ * toKebab: true // Accessible as --autumn-season
457
+ * }
458
+ * }
459
+ * // Error: "Optional argument '--summer-season' conflicts with '--autumn-season'"
460
+ * ```
461
+ */
462
+ conflicts?: string | string[];
463
+ /**
464
+ * Display name hint for help text generation.
465
+ *
466
+ * Provides a meaningful type hint for the argument value in help output.
467
+ * Particularly useful for `type: 'custom'` arguments where the type
468
+ * name would otherwise be unhelpful.
469
+ *
470
+ * For a `custom` option that is given without a value, it is also the `expected` in the `values`
471
+ * of the `err:arg:missing-value` error ({@link ArgsValidationErrorKeys}.missingValue), which is
472
+ * `'custom'` without it.
473
+ *
474
+ * @example
475
+ * Metavar usage:
476
+ * ```ts
477
+ * {
478
+ * port: {
479
+ * type: 'custom',
480
+ * parse: (v: string) => parseInt(v, 10),
481
+ * metavar: 'integer',
482
+ * description: 'Port number (1-65535)'
483
+ * }
484
+ * }
485
+ * // Help output: --port <integer> Port number (1-65535)
486
+ * ```
487
+ */
488
+ metavar?: string;
489
+ /**
490
+ * Custom parsing function, used in place of the parsing of the argument's `type`.
491
+ *
492
+ * Required when `type: 'custom'`: if it is missing or not a function, {@link resolveArgs} and
493
+ * `parse()` throw a `TypeError`, whether or not the argument is given. The function receives the
494
+ * raw string value and must return the parsed result. It should throw an Error (or subclass) if
495
+ * parsing fails.
496
+ *
497
+ * The function's return type becomes the resolved argument type.
498
+ *
499
+ * `parse` is called synchronously, and what it returns becomes the value, even `undefined` or
500
+ * `null`, so throw to reject a value. An `async` function returns a promise, and the promise
501
+ * becomes the value as is: it is not awaited, and its rejection is not reported as an error.
502
+ * Await the value, or each of its elements with `multiple` (for example with `Promise.all()`),
503
+ * and handle the rejection yourself: a rejection that nothing handles is an unhandled rejection,
504
+ * which ends a Node.js process by default.
505
+ *
506
+ * A `boolean` option calls `parse` with `'true'`, or `'false'` for the negated form. Other
507
+ * options call it only with a value from the command line: when the option is given without a
508
+ * value, `parse` is not called and the missing value is reported as `err:arg:missing-value`
509
+ * ({@link ArgsValidationErrorKeys}.missingValue). When that error may suggest the argument after
510
+ * the option as its value, such as `--port=-5` for `--port -5`, a `parse` function of your own
511
+ * is not called to check it either: only the `parse` functions of `string()`, `number()`,
512
+ * `integer()`, `float()` and `choice()`, which have no side effects, are called for that.
513
+ * An explicit empty value, such as `--name=` or `-n=`, is passed as `''` unless
514
+ * `required: true` is set.
515
+ *
516
+ * An `enum` option with `choices` calls it only with one of them. Any other value, an explicit
517
+ * empty one included, is reported as `err:arg:invalid-choice`
518
+ * ({@link ArgsValidationErrorKeys}.invalidChoice), except that a required option reports an
519
+ * explicit empty value as required.
520
+ *
521
+ * @param value - Raw string value from command line
522
+ * @returns Parsed value of any type
523
+ * @throws {Error} Error or subclass when value is invalid
524
+ *
525
+ * @example
526
+ * Custom parsing functions:
527
+ * ```ts
528
+ * {
529
+ * config: {
530
+ * type: 'custom',
531
+ * parse: (value: string) => {
532
+ * try {
533
+ * return JSON.parse(value) // Parse JSON config
534
+ * } catch {
535
+ * throw new Error('Invalid JSON configuration')
536
+ * }
537
+ * },
538
+ * description: 'JSON configuration object'
539
+ * },
540
+ * date: {
541
+ * type: 'custom',
542
+ * parse: (value: string) => {
543
+ * const date = new Date(value)
544
+ * if (isNaN(date.getTime())) {
545
+ * throw new Error('Invalid date format')
546
+ * }
547
+ * return date
548
+ * }
549
+ * }
550
+ * }
551
+ * ```
552
+ */
553
+ parse?: (value: string) => any;
554
+ }
555
+ /**
556
+ * An object that contains {@link ArgSchema | argument schema}.
557
+ *
558
+ * This type is used to define the structure and validation rules for command line arguments.
559
+ */
560
+ interface Args$1 {
561
+ [option: string]: ArgSchema;
562
+ }
10
563
  //#endregion
11
564
  //#region ../shared/src/constants.d.ts
12
- /**
13
- * @author kazuya kawaguchi (a.k.a. kazupon)
14
- * @license MIT
15
- */
16
565
  /**
17
566
  * @author kazuya kawaguchi (a.k.a. kazupon)
18
567
  * @license MIT
@@ -36,35 +585,20 @@ type CommonArgType = {
36
585
  declare const COMMON_ARGS: CommonArgType;
37
586
  declare const COMMAND_BUILTIN_RESOURCE_KEYS: readonly ["USAGE", "COMMAND", "SUBCOMMAND", "COMMANDS", "ARGUMENTS", "OPTIONS", "EXAMPLES", "FORMORE", "NEGATABLE", "DEFAULT", "CHOICES"];
38
587
  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
+ declare const ARG_ERROR_HINT_RESOURCE_KEYS: readonly ["err:arg:missing-value:hint"];
39
589
  declare const COMMAND_ERROR_RESOURCE_KEYS: readonly ["err:cmd:not-found", "err:cmd:ambiguous", "err:cmd:inconsistent-options", "err:cmd:lazy-schema-mismatch"];
40
590
  declare const SUGGESTION_ERROR_RESOURCE_KEYS: readonly ["err:suggestion:did-you-mean"];
41
- //#endregion
42
- //#region ../plugin-i18n/src/types.d.ts
43
-
44
- //#endregion
45
- //#region ../plugin-i18n/src/helpers.d.ts
46
-
47
- //#endregion
48
- //#region ../plugin-i18n/src/translation.d.ts
49
-
50
- //#endregion
51
- //#region ../gunshi/src/index.d.ts
52
-
53
591
  //#endregion
54
592
  //#region ../shared/src/types.d.ts
55
- type RemoveIndexSignature<T> = { [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K] };
56
- /**
57
- * Make all properties in T deeply writeable (not readonly)
58
- */
59
-
593
+ type RemoveIndexSignature<T> = { [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K]; };
60
594
  /**
61
595
  * Remove index signature from object or record type.
62
596
  */
63
- type RemovedIndex<T> = RemoveIndexSignature<{ [K in keyof T]: T[K] }>;
597
+ type RemovedIndex<T> = RemoveIndexSignature<{ [K in keyof T]: T[K]; }>;
64
598
  /**
65
599
  * Resolve a key on {@link Args}.
66
600
  */
67
- 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];
601
+ 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];
68
602
  /**
69
603
  * Generate a namespaced key.
70
604
  */
@@ -81,6 +615,10 @@ type CommandBuiltinResourceKeys = (typeof COMMAND_BUILTIN_RESOURCE_KEYS)[number]
81
615
  * Args validation error resource keys.
82
616
  */
83
617
  type ArgErrorResourceKeys = (typeof ARG_ERROR_RESOURCE_KEYS)[number];
618
+ /**
619
+ * Resource keys of the hints that follow an args validation error.
620
+ */
621
+ type ArgErrorHintResourceKeys = (typeof ARG_ERROR_HINT_RESOURCE_KEYS)[number];
84
622
  /**
85
623
  * Command validation error resource keys.
86
624
  */
@@ -92,7 +630,7 @@ type SuggestionErrorResourceKeys = (typeof SUGGESTION_ERROR_RESOURCE_KEYS)[numbe
92
630
  /**
93
631
  * Error resource keys.
94
632
  */
95
- type ErrorResourceKeys = ArgErrorResourceKeys | CommandErrorResourceKeys | SuggestionErrorResourceKeys;
633
+ type ErrorResourceKeys = ArgErrorResourceKeys | ArgErrorHintResourceKeys | CommandErrorResourceKeys | SuggestionErrorResourceKeys;
96
634
  /**
97
635
  * Command built-in keys.
98
636
  */
@@ -107,22 +645,11 @@ type CommandArgKeys<A extends Args$1, C = {}, K extends string = GenerateNamespa
107
645
  /**
108
646
  * Resolve translation keys for command context.
109
647
  */
110
- type ResolveTranslationKeys<A extends Args$1, C = {},
111
- // for CommandContext
112
- E extends Record<string, string> = {},
113
- // for extended resources
114
- R extends string = keyof RemovedIndex<E>, T extends string = (C extends {
648
+ type ResolveTranslationKeys<A extends Args$1, C = {} // for CommandContext
649
+ , E extends Record<string, string> = {} // for extended resources
650
+ , R extends string = keyof RemovedIndex<E>, T extends string = C extends {
115
651
  name: infer N;
116
- } ? N extends string ? GenerateNamespacedKey<R, N> : R : R | CommandBuiltinKeys), O = CommandArgKeys<A, C>> = ErrorResourceKeys | CommandBuiltinKeys | O | T;
117
- //#endregion
118
- //#region ../shared/src/localization.d.ts
119
-
120
- //#endregion
121
- //#region ../shared/src/utils.d.ts
122
-
123
- //#endregion
124
- //#region ../shared/src/index.d.ts
125
-
652
+ } ? N extends string ? GenerateNamespacedKey<R, N> : R : R | CommandBuiltinKeys, O = CommandArgKeys<A, C>> = ErrorResourceKeys | CommandBuiltinKeys | O | T;
126
653
  //#endregion
127
654
  //#region src/types.d.ts
128
655
  /**
@@ -151,11 +678,9 @@ interface UsageRendererExtension<G extends GunshiParams<any> = DefaultGunshiPara
151
678
  * @param values - An optional record of values to interpolate into the translation string.
152
679
  * @returns The resolved translation string with interpolated values if provided.
153
680
  */
154
- text: <A extends Args = G['args'], C = {},
155
- // for CommandContext
156
- E extends Record<string, string> = {},
157
- // for extended resources
158
- K = ResolveTranslationKeys<A, C, E>>(key: K, values?: Record<string, unknown>) => Promise<string>;
681
+ text: <A extends Args = G['args'], C = {} // for CommandContext
682
+ , E extends Record<string, string> = {} // for extended resources
683
+ , K = ResolveTranslationKeys<A, C, E>>(key: K, values?: Record<string, unknown>) => Promise<string>;
159
684
  /**
160
685
  * Load commands
161
686
  *
package/lib/index.js CHANGED
@@ -153,13 +153,14 @@ var en_US_default = {
153
153
  help: "Display this help message",
154
154
  version: "Display this version",
155
155
  "err:arg:required-option": "Optional argument {$displayName} is required",
156
- "err:arg:required-positional": "Positional argument {$name} is required",
156
+ "err:arg:required-positional": "Positional argument {$displayName} is required",
157
157
  "err:arg:invalid-type": "Invalid value for {$displayName}: expected {$expected}",
158
158
  "err:arg:invalid-choice": "Invalid value for {$displayName}: expected one of {$choices}",
159
159
  "err:arg:custom-parse": "Invalid value for {$displayName}: {$reason}",
160
160
  "err:arg:unknown-option": "Unknown option: {$rawName}",
161
161
  "err:arg:unexpected-value": "Optional argument {$displayName} does not take a value",
162
162
  "err:arg:missing-value": "Optional argument {$displayName} requires a value",
163
+ "err:arg:missing-value:hint": "(to pass '{$next}' as its value, write '{$suggestion}')",
163
164
  "err:arg:conflict": "{$displayName} conflicts with {$conflictDisplayName}",
164
165
  "err:arg:invalid-default": "Invalid default for {$displayName}: {$actual} is not one of {$choices}",
165
166
  "err:cmd:not-found": "Command not found: {$commandName}",
@@ -442,10 +443,10 @@ function isHiddenArg(schema) {
442
443
  return schema.hidden === true;
443
444
  }
444
445
  function getVisibleOptionalArgs(args) {
445
- return Object.entries(args).filter(([_, schema]) => schema.type !== "positional" && !isHiddenArg(schema));
446
+ return Object.entries(args).filter(([, schema]) => schema.type !== "positional" && !isHiddenArg(schema));
446
447
  }
447
448
  function getVisiblePositionalArgs(args) {
448
- return Object.entries(args).filter(([_, schema]) => schema.type === "positional" && !isHiddenArg(schema));
449
+ return Object.entries(args).filter(([, schema]) => schema.type === "positional" && !isHiddenArg(schema));
449
450
  }
450
451
  /**
451
452
  * Render the usage.
@@ -661,7 +662,7 @@ function hasAllDefaultOptions(args) {
661
662
  * NOTE(kazupon): an argument has a default when one is declared, whatever its value. `0`, `''` and
662
663
  * `false` are defaults like any other, and an option that has one is not required (#750).
663
664
  */
664
- return visibleOptionalArgs.length > 0 && visibleOptionalArgs.every(([_, arg]) => arg.default !== void 0);
665
+ return visibleOptionalArgs.length > 0 && visibleOptionalArgs.every(([, arg]) => arg.default !== void 0);
665
666
  }
666
667
  /**
667
668
  * Generate options symbols for usage
@@ -731,7 +732,7 @@ async function resolveDisplayValue(ctx, key) {
731
732
  async function generateOptionalArgsUsage(ctx, optionsPairs) {
732
733
  const optionsPairsEntries = Object.entries(optionsPairs);
733
734
  if (optionsPairsEntries.length === 0) return "";
734
- const optionsMaxLength = Math.max(...optionsPairsEntries.map(([_, value]) => displayWidth(value)));
735
+ const optionsMaxLength = Math.max(...optionsPairsEntries.map(([, value]) => displayWidth(value)));
735
736
  const optionSchemaMaxLength = ctx.env.usageOptionType ? Math.max(...optionsPairsEntries.map(([key]) => displayWidth(resolveNegatableType(key, ctx)))) : 0;
736
737
  return (await Promise.all(optionsPairsEntries.map(async ([key, value]) => {
737
738
  let rawDesc = await ctx.extensions[pluginId].text(resolveArgKey(key, ctx.name));
@@ -790,6 +791,7 @@ function isRequiredSinglePositionalArg(arg) {
790
791
  * @license MIT
791
792
  */
792
793
  const i18nPluginId$1 = namespacedId("i18n");
794
+ const missingValueHintKey = "err:arg:missing-value:hint";
793
795
  /**
794
796
  * Render the validation errors.
795
797
  *
@@ -814,10 +816,31 @@ async function renderValidationError(ctx, error) {
814
816
  if (isArgsValidationError(error) && error.code) {
815
817
  const values = await resolveValidationValues(ctx, error);
816
818
  const message = await localize(ctx, error.code, values);
817
- if (message && message !== error.code) return message;
819
+ if (message && message !== error.code) {
820
+ const hint = await localizeHint(ctx, error, values);
821
+ return hint ? `${message} ${hint}` : message;
822
+ }
818
823
  }
819
824
  return error.message;
820
825
  }
826
+ /**
827
+ * Localize the hint that args-tokens adds to the message of an error.
828
+ *
829
+ * A translation replaces the whole message, hint included, so the hint is translated by a key of
830
+ * its own and follows the translated error. args-tokens gives one today: for an option given without
831
+ * a value, when the argument after it may be the value, the long form with `=` (`--port=-5` for
832
+ * `--port -5`), in `values.next` and `values.suggestion`.
833
+ *
834
+ * @param ctx - A {@link CommandContext | command context}
835
+ * @param error - An args validation error
836
+ * @param values - The values of the error, as given to its translation
837
+ * @returns The localized hint, or `undefined` when the error has none.
838
+ */
839
+ async function localizeHint(ctx, error, values) {
840
+ if (error.code !== ArgsValidationErrorKeys.missingValue || typeof values.next !== "string" || typeof values.suggestion !== "string") return;
841
+ const hint = await localize(ctx, missingValueHintKey, values);
842
+ return hint && hint !== missingValueHintKey ? hint : void 0;
843
+ }
821
844
  async function resolveValidationValues(ctx, error) {
822
845
  if (error.code !== ArgsValidationErrorKeys.customParse) return error.values;
823
846
  const { reasonKey, reasonValues } = error.values;
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-beta.0",
4
+ "version": "1.0.0-beta.1",
5
5
  "author": {
6
6
  "name": "kazuya kawaguchi",
7
7
  "email": "kawakazu80@gmail.com"
@@ -53,18 +53,18 @@
53
53
  }
54
54
  },
55
55
  "dependencies": {
56
- "@gunshi/plugin": "1.0.0-beta.0"
56
+ "@gunshi/plugin": "1.0.0-beta.1"
57
57
  },
58
58
  "peerDependencies": {
59
- "@gunshi/plugin-i18n": "1.0.0-beta.0"
59
+ "@gunshi/plugin-i18n": "1.0.0-beta.1"
60
60
  },
61
61
  "devDependencies": {
62
+ "@gunshi/shared": "1.0.0-beta.1",
62
63
  "deno": "^2.7.14",
63
64
  "jsr": "^0.14.3",
64
65
  "jsr-exports-lint": "^0.4.2",
65
66
  "publint": "^0.3.20",
66
- "tsdown": "0.21.0",
67
- "@gunshi/shared": "1.0.0-beta.0"
67
+ "tsdown": "0.22.14"
68
68
  },
69
69
  "scripts": {
70
70
  "build": "tsdown",