@gunshi/definition 0.27.0-alpha.8 → 0.27.0-beta.0

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,7 +1,8 @@
1
- //#region ../../node_modules/.pnpm/args-tokens@0.22.0/node_modules/args-tokens/lib/parser-Cbxholql.d.ts
1
+ //#region ../../node_modules/.pnpm/args-tokens@0.23.0/node_modules/args-tokens/lib/parser-C6MbpZjd.d.ts
2
2
  //#region src/parser.d.ts
3
3
  /**
4
4
  * Entry point of argument parser.
5
+ *
5
6
  * @module
6
7
  */
7
8
  /**
@@ -14,6 +15,7 @@
14
15
  */
15
16
  /**
16
17
  * Argument token Kind.
18
+ *
17
19
  * - `option`: option token, support short option (e.g. `-x`) and long option (e.g. `--foo`)
18
20
  * - `option-terminator`: option terminator (`--`) token, see guideline 10 in https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
19
21
  * - `positional`: positional token
@@ -53,91 +55,462 @@ interface ArgToken {
53
55
  * Parser Options.
54
56
  */
55
57
  //#endregion
56
- //#region ../../node_modules/.pnpm/args-tokens@0.22.0/node_modules/args-tokens/lib/resolver-BoS-UnqX.d.ts
58
+ //#region ../../node_modules/.pnpm/args-tokens@0.23.0/node_modules/args-tokens/lib/resolver-D64nGlCD.d.ts
57
59
  //#region src/resolver.d.ts
58
60
 
59
61
  /**
60
- * An argument schema
61
- * This schema is similar to the schema of the `node:utils`.
62
- * difference is that:
63
- * - `required` property and `description` property are added
64
- * - `type` is not only 'string' and 'boolean', but also 'number', 'enum', 'positional', 'custom' too.
65
- * - `default` property type, not support multiple types
62
+ * An argument schema definition for command-line argument parsing.
63
+ *
64
+ * This schema is similar to the schema of Node.js `util.parseArgs` but with extended features:
65
+ * - Additional `required` and `description` properties
66
+ * - Extended `type` support: 'string', 'boolean', 'number', 'enum', 'positional', 'custom'
67
+ * - Simplified `default` property (single type, not union types)
68
+ *
69
+ * @example
70
+ * Basic string argument:
71
+ * ```ts
72
+ * const schema: ArgSchema = {
73
+ * type: 'string',
74
+ * description: 'Server hostname',
75
+ * default: 'localhost'
76
+ * }
77
+ * ```
78
+ *
79
+ * @example
80
+ * Required number argument with alias:
81
+ * ```ts
82
+ * const schema: ArgSchema = {
83
+ * type: 'number',
84
+ * short: 'p',
85
+ * description: 'Port number to listen on',
86
+ * required: true
87
+ * }
88
+ * ```
89
+ *
90
+ * @example
91
+ * Enum argument with choices:
92
+ * ```ts
93
+ * const schema: ArgSchema = {
94
+ * type: 'enum',
95
+ * choices: ['info', 'warn', 'error'],
96
+ * description: 'Logging level',
97
+ * default: 'info'
98
+ * }
99
+ * ```
66
100
  */
67
101
  interface ArgSchema {
68
102
  /**
69
- * Type of argument.
103
+ * Type of the argument value.
104
+ *
105
+ * - `'string'`: Text value (default if not specified)
106
+ * - `'boolean'`: `true`/`false` flag (can be negatable with `--no-` prefix)
107
+ * - `'number'`: Numeric value (parsed as integer or float)
108
+ * - `'enum'`: One of predefined string values (requires `choices` property)
109
+ * - `'positional'`: Non-option argument by position
110
+ * - `'custom'`: Custom parsing with user-defined `parse` function
111
+ *
112
+ * @example
113
+ * Different argument types:
114
+ * ```ts
115
+ * {
116
+ * name: { type: 'string' }, // --name value
117
+ * verbose: { type: 'boolean' }, // --verbose or --no-verbose
118
+ * port: { type: 'number' }, // --port 3000
119
+ * level: { type: 'enum', choices: ['debug', 'info'] },
120
+ * file: { type: 'positional' }, // first positional arg
121
+ * config: { type: 'custom', parse: JSON.parse }
122
+ * }
123
+ * ```
70
124
  */
71
125
  type: 'string' | 'boolean' | 'number' | 'enum' | 'positional' | 'custom';
72
126
  /**
73
- * A single character alias for the argument.
127
+ * Single character alias for the long option name.
128
+ *
129
+ * As example, allows users to use `-x` instead of `--extended-option`.
130
+ * Only valid for non-positional argument types.
131
+ *
132
+ * @example
133
+ * Short alias usage:
134
+ * ```ts
135
+ * {
136
+ * verbose: {
137
+ * type: 'boolean',
138
+ * short: 'v' // Enables both --verbose and -v
139
+ * },
140
+ * port: {
141
+ * type: 'number',
142
+ * short: 'p' // Enables both --port 3000 and -p 3000
143
+ * }
144
+ * }
145
+ * ```
74
146
  */
75
147
  short?: string;
76
148
  /**
77
- * A description of the argument.
149
+ * Human-readable description of the argument's purpose.
150
+ *
151
+ * Used for help text generation and documentation.
152
+ * Should be concise but descriptive enough to understand the argument's role.
153
+ *
154
+ * @example
155
+ * Descriptive help text:
156
+ * ```ts
157
+ * {
158
+ * config: {
159
+ * type: 'string',
160
+ * description: 'Path to configuration file'
161
+ * },
162
+ * timeout: {
163
+ * type: 'number',
164
+ * description: 'Request timeout in milliseconds'
165
+ * }
166
+ * }
167
+ * ```
78
168
  */
79
169
  description?: string;
80
170
  /**
81
- * Whether the argument is required or not.
171
+ * Marks the argument as required.
172
+ *
173
+ * When `true`, the argument must be provided by the user.
174
+ * If missing, an `ArgResolveError` with type 'required' will be thrown.
175
+ *
176
+ * Note: Only `true` is allowed (not `false`) to make intent explicit.
177
+ *
178
+ * @example
179
+ * Required arguments:
180
+ * ```ts
181
+ * {
182
+ * input: {
183
+ * type: 'string',
184
+ * required: true, // Must be provided: --input file.txt
185
+ * description: 'Input file path'
186
+ * },
187
+ * source: {
188
+ * type: 'positional',
189
+ * required: true // First positional argument must exist
190
+ * }
191
+ * }
192
+ * ```
82
193
  */
83
194
  required?: true;
84
195
  /**
85
- * Whether the argument allow multiple values or not.
196
+ * Allows the argument to accept multiple values.
197
+ *
198
+ * When `true`, the resolved value becomes an array.
199
+ * For options: can be specified multiple times (--tag foo --tag bar)
200
+ * For positional: collects remaining positional arguments
201
+ *
202
+ * Note: Only `true` is allowed (not `false`) to make intent explicit.
203
+ *
204
+ * @example
205
+ * Multiple values:
206
+ * ```ts
207
+ * {
208
+ * tags: {
209
+ * type: 'string',
210
+ * multiple: true, // --tags foo --tags bar → ['foo', 'bar']
211
+ * description: 'Tags to apply'
212
+ * },
213
+ * files: {
214
+ * type: 'positional',
215
+ * multiple: true // Collects all remaining positional args
216
+ * }
217
+ * }
218
+ * ```
86
219
  */
87
220
  multiple?: true;
88
221
  /**
89
- * Whether the negatable option for `boolean` type
222
+ * Enables negation for boolean arguments using `--no-` prefix.
223
+ *
224
+ * When `true`, allows users to explicitly set the boolean to `false`
225
+ * using `--no-option-name`. When `false` or omitted, only positive
226
+ * form is available.
227
+ *
228
+ * Only applicable to `type: 'boolean'` arguments.
229
+ *
230
+ * @example
231
+ * Negatable boolean:
232
+ * ```ts
233
+ * {
234
+ * color: {
235
+ * type: 'boolean',
236
+ * negatable: true,
237
+ * default: true,
238
+ * description: 'Enable colorized output'
239
+ * }
240
+ * // Usage: --color (true), --no-color (false)
241
+ * }
242
+ * ```
90
243
  */
91
244
  negatable?: boolean;
92
245
  /**
93
- * The allowed values of the argument, and string only. This property is only used when the type is 'enum'.
246
+ * Array of allowed string values for enum-type arguments.
247
+ *
248
+ * Required when `type: 'enum'`. The argument value must be one of these choices,
249
+ * otherwise an `ArgResolveError` with type 'type' will be thrown.
250
+ *
251
+ * Supports both mutable arrays and readonly arrays for type safety.
252
+ *
253
+ * @example
254
+ * Enum choices:
255
+ * ```ts
256
+ * {
257
+ * logLevel: {
258
+ * type: 'enum',
259
+ * choices: ['debug', 'info', 'warn', 'error'] as const,
260
+ * default: 'info',
261
+ * description: 'Logging verbosity level'
262
+ * },
263
+ * format: {
264
+ * type: 'enum',
265
+ * choices: ['json', 'yaml', 'toml'],
266
+ * description: 'Output format'
267
+ * }
268
+ * }
269
+ * ```
94
270
  */
95
271
  choices?: string[] | readonly string[];
96
272
  /**
97
- * The default value of the argument.
98
- * if the type is 'enum', the default value must be one of the allowed values.
273
+ * Default value used when the argument is not provided.
274
+ *
275
+ * The type must match the argument's `type` property:
276
+ * - `string` type: string default
277
+ * - `boolean` type: boolean default
278
+ * - `number` type: number default
279
+ * - `enum` type: must be one of the `choices` values
280
+ * - `positional`/`custom` type: any appropriate default
281
+ *
282
+ * @example
283
+ * Default values by type:
284
+ * ```ts
285
+ * {
286
+ * host: {
287
+ * type: 'string',
288
+ * default: 'localhost' // string default
289
+ * },
290
+ * verbose: {
291
+ * type: 'boolean',
292
+ * default: false // boolean default
293
+ * },
294
+ * port: {
295
+ * type: 'number',
296
+ * default: 8080 // number default
297
+ * },
298
+ * level: {
299
+ * type: 'enum',
300
+ * choices: ['low', 'high'],
301
+ * default: 'low' // must be in choices
302
+ * }
303
+ * }
304
+ * ```
99
305
  */
100
306
  default?: string | boolean | number;
101
307
  /**
102
- * Whether to convert the argument name to kebab-case.
308
+ * Converts the argument name from camelCase to kebab-case for CLI usage.
309
+ *
310
+ * When `true`, a property like `maxCount` becomes available as `--max-count`.
311
+ * This allows [CAC](https://github.com/cacjs/cac) user-friendly property names while maintaining CLI conventions.
312
+ *
313
+ * Can be overridden globally with `resolveArgs({ toKebab: true })`.
314
+ *
315
+ * Note: Only `true` is allowed (not `false`) to make intent explicit.
316
+ *
317
+ * @example
318
+ * Kebab-case conversion:
319
+ * ```ts
320
+ * {
321
+ * maxRetries: {
322
+ * type: 'number',
323
+ * toKebab: true, // Accessible as --max-retries
324
+ * description: 'Maximum retry attempts'
325
+ * },
326
+ * enableLogging: {
327
+ * type: 'boolean',
328
+ * toKebab: true // Accessible as --enable-logging
329
+ * }
330
+ * }
331
+ * ```
103
332
  */
104
333
  toKebab?: true;
105
334
  /**
106
- * A function to parse the value of the argument. if the type is 'custom', this function is required.
107
- * If argument value will be invalid, this function have to throw an error.
108
- * @param value
109
- * @returns Parsed value
110
- * @throws An Error, If the value is invalid. Error type should be `Error` or extends it
335
+ * Names of other options that conflict with this option.
336
+ *
337
+ * When this option is used together with any of the conflicting options,
338
+ * an `ArgResolveError` with type 'conflict' will be thrown.
339
+ *
340
+ * Conflicts only need to be defined on one side - if option A defines a conflict
341
+ * with option B, the conflict is automatically detected when both are used,
342
+ * regardless of whether B also defines a conflict with A.
343
+ *
344
+ * Supports both single option name or array of option names.
345
+ * Option names must match the property keys in the schema object exactly
346
+ * (no automatic conversion between camelCase and kebab-case).
347
+ *
348
+ * @example
349
+ * Single conflict (bidirectional definition):
350
+ * ```ts
351
+ * {
352
+ * summer: {
353
+ * type: 'boolean',
354
+ * conflicts: 'autumn' // Cannot use --summer with --autumn
355
+ * },
356
+ * autumn: {
357
+ * type: 'boolean',
358
+ * conflicts: 'summer' // Can define on both sides for clarity
359
+ * }
360
+ * }
361
+ * ```
362
+ *
363
+ * @example
364
+ * Single conflict (one-way definition):
365
+ * ```ts
366
+ * {
367
+ * summer: {
368
+ * type: 'boolean',
369
+ * conflicts: 'autumn' // Only defined on summer side
370
+ * },
371
+ * autumn: {
372
+ * type: 'boolean'
373
+ * // No conflicts defined, but still cannot use with --summer
374
+ * }
375
+ * }
376
+ * // Usage: --summer --autumn will throw error
377
+ * // Error: "Optional argument '--summer' conflicts with '--autumn'"
378
+ * ```
379
+ *
380
+ * @example
381
+ * Multiple conflicts:
382
+ * ```ts
383
+ * {
384
+ * port: {
385
+ * type: 'number',
386
+ * conflicts: ['socket', 'pipe'], // Cannot use with --socket or --pipe
387
+ * description: 'TCP port number'
388
+ * },
389
+ * socket: {
390
+ * type: 'string',
391
+ * conflicts: ['port', 'pipe'], // Cannot use with --port or --pipe
392
+ * description: 'Unix socket path'
393
+ * },
394
+ * pipe: {
395
+ * type: 'string',
396
+ * conflicts: ['port', 'socket'], // Cannot use with --port or --socket
397
+ * description: 'Named pipe path'
398
+ * }
399
+ * }
400
+ * // These three options are mutually exclusive
401
+ * ```
402
+ *
403
+ * @example
404
+ * With kebab-case conversion:
405
+ * ```ts
406
+ * {
407
+ * summerSeason: {
408
+ * type: 'boolean',
409
+ * toKebab: true, // Accessible as --summer-season
410
+ * conflicts: 'autumnSeason' // Must use property key, not CLI name
411
+ * },
412
+ * autumnSeason: {
413
+ * type: 'boolean',
414
+ * toKebab: true // Accessible as --autumn-season
415
+ * }
416
+ * }
417
+ * // Error: "Optional argument '--summer-season' conflicts with '--autumn-season'"
418
+ * ```
419
+ */
420
+ conflicts?: string | string[];
421
+ /**
422
+ * Custom parsing function for `type: 'custom'` arguments.
423
+ *
424
+ * Required when `type: 'custom'`. Receives the raw string value and must
425
+ * return the parsed result. Should throw an Error (or subclass) if parsing fails.
426
+ *
427
+ * The function's return type becomes the resolved argument type.
428
+ *
429
+ * @param value - Raw string value from command line
430
+ * @returns Parsed value of any type
431
+ * @throws Error or subclass when value is invalid
432
+ *
433
+ * @example
434
+ * Custom parsing functions:
435
+ * ```ts
436
+ * {
437
+ * config: {
438
+ * type: 'custom',
439
+ * parse: (value: string) => {
440
+ * try {
441
+ * return JSON.parse(value) // Parse JSON config
442
+ * } catch {
443
+ * throw new Error('Invalid JSON configuration')
444
+ * }
445
+ * },
446
+ * description: 'JSON configuration object'
447
+ * },
448
+ * date: {
449
+ * type: 'custom',
450
+ * parse: (value: string) => {
451
+ * const date = new Date(value)
452
+ * if (isNaN(date.getTime())) {
453
+ * throw new Error('Invalid date format')
454
+ * }
455
+ * return date
456
+ * }
457
+ * }
458
+ * }
459
+ * ```
111
460
  */
112
461
  parse?: (value: string) => any;
113
462
  }
114
463
  /**
115
464
  * An object that contains {@link ArgSchema | argument schema}.
465
+ *
466
+ * This type is used to define the structure and validation rules for command line arguments.
116
467
  */
117
468
  interface Args {
118
469
  [option: string]: ArgSchema;
119
470
  }
120
471
  /**
121
472
  * An object that contains the values of the arguments.
473
+ *
474
+ * @typeParam T - {@link Args | Arguments} which is an object that defines the command line arguments.
122
475
  */
123
476
  type ArgValues<T> = T extends Args ? ResolveArgValues<T, { [Arg in keyof T]: ExtractOptionValue<T[Arg]> }> : {
124
477
  [option: string]: string | boolean | number | (string | boolean | number)[] | undefined;
125
478
  };
126
479
  type IsFunction<T> = T extends ((...args: any[]) => any) ? true : false;
127
480
  /**
481
+ * Extracts the value type from the argument schema.
482
+ *
483
+ * @typeParam A - {@link ArgSchema | Argument schema} which is an object that defines command line arguments.
484
+ *
128
485
  * @internal
129
486
  */
130
487
  type ExtractOptionValue<A extends ArgSchema> = A['type'] extends 'string' ? ResolveOptionValue<A, string> : A['type'] extends 'boolean' ? ResolveOptionValue<A, boolean> : A['type'] extends 'number' ? ResolveOptionValue<A, number> : A['type'] extends 'positional' ? ResolveOptionValue<A, string> : A['type'] extends 'enum' ? A['choices'] extends string[] | readonly string[] ? ResolveOptionValue<A, A['choices'][number]> : never : A['type'] extends 'custom' ? IsFunction<A['parse']> extends true ? ResolveOptionValue<A, ReturnType<NonNullable<A['parse']>>> : never : ResolveOptionValue<A, string | boolean | number>;
131
488
  type ResolveOptionValue<A extends ArgSchema, T> = A['multiple'] extends true ? T[] : T;
132
489
  /**
490
+ * Resolved argument values.
491
+ *
492
+ * @typeParam A - {@link Arguments | Args} which is an object that defines the command line arguments.
493
+ * @typeParam V - Resolvable argument values.
494
+ *
133
495
  * @internal
134
496
  */
135
497
  type ResolveArgValues<A extends Args, V extends Record<keyof A, unknown>> = { -readonly [Arg in keyof A]?: V[Arg] } & FilterArgs<A, V, 'default'> & FilterArgs<A, V, 'required'> & FilterPositionalArgs<A, V> extends infer P ? { [K in keyof P]: P[K] } : never;
136
498
  /**
499
+ * Filters the arguments based on their default values.
500
+ *
501
+ * @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
502
+ * @typeParam V - Resolvable argument values.
503
+ * @typeParam K - Key of the {@link ArgSchema | argument schema} to filter by.
504
+ *
137
505
  * @internal
138
506
  */
139
507
  type FilterArgs<A extends Args, V extends Record<keyof A, unknown>, K extends keyof ArgSchema> = { [Arg in keyof A as A[Arg][K] extends {} ? Arg : never]: V[Arg] };
140
508
  /**
509
+ * Filters positional arguments from the argument schema.
510
+ *
511
+ * @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
512
+ * @typeParam V - Resolvable argument values.
513
+ *
141
514
  * @internal
142
515
  */
143
516
  type FilterPositionalArgs<A extends Args, V extends Record<keyof A, unknown>> = { [Arg in keyof A as A[Arg]['type'] extends 'positional' ? Arg : never]: V[Arg] };
@@ -150,10 +523,15 @@ type FilterPositionalArgs<A extends Args, V extends Record<keyof A, unknown>> =
150
523
  *
151
524
  * Each property indicates whether the corresponding argument was explicitly
152
525
  * provided (true) or is using a default value or not provided (false).
526
+ *
527
+ * @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
153
528
  */
154
529
  type ArgExplicitlyProvided<A extends Args> = { [K in keyof A]: boolean };
155
530
  /**
156
531
  * Resolve command line arguments.
532
+ *
533
+ * @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
534
+ *
157
535
  * @param args - An arguments that contains {@link ArgSchema | arguments schema}.
158
536
  * @param tokens - An array of {@link ArgToken | tokens}.
159
537
  * @param resolveArgs - An arguments that contains {@link ResolveArgs | resolve arguments}.
@@ -182,16 +560,161 @@ type ArgExplicitlyProvided<A extends Args> = { [K in keyof A]: boolean };
182
560
  * ```
183
561
  */
184
562
  //#endregion
563
+ //#region ../gunshi/src/plugin/context.d.ts
564
+ /**
565
+ * Type helper to create GunshiParams from extracted args and extensions
566
+ *
567
+ * @internal
568
+ */
569
+ type ExtractedParams<G extends GunshiParamsConstraint, L extends Record<string, unknown> = {}> = {
570
+ args: ExtractArgs<G>;
571
+ extensions: ExtractExtensions<G> & L;
572
+ };
573
+ /**
574
+ * Gunshi plugin context interface.
575
+ *
576
+ * @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of command parameters.
577
+ *
578
+ * @since v0.27.0
579
+ */
580
+ interface PluginContext<G extends GunshiParamsConstraint = DefaultGunshiParams> {
581
+ /**
582
+ * Get the global options
583
+ *
584
+ * @returns A map of global options.
585
+ */
586
+ readonly globalOptions: Map<string, ArgSchema>;
587
+ /**
588
+ * Get the registered sub commands
589
+ *
590
+ * @returns A map of sub commands.
591
+ */
592
+ readonly subCommands: ReadonlyMap<string, Command<G> | LazyCommand<G>>;
593
+ /**
594
+ * Add a global option.
595
+ *
596
+ * @param name - An option name
597
+ * @param schema - An {@linkcode ArgSchema} for the option
598
+ */
599
+ addGlobalOption(name: string, schema: ArgSchema): void;
600
+ /**
601
+ * Add a sub command.
602
+ *
603
+ * @param name - Command name
604
+ * @param command - Command definition
605
+ */
606
+ addCommand(name: string, command: Command<G> | LazyCommand<G>): void;
607
+ /**
608
+ * Check if a command exists.
609
+ *
610
+ * @param name - Command name
611
+ * @returns True if the command exists, false otherwise
612
+ */
613
+ hasCommand(name: string): boolean;
614
+ /**
615
+ * Decorate the header renderer.
616
+ *
617
+ * @typeParam L - An extensions type to specify the shape of {@linkcode CommandContext}'s extensions.
618
+ *
619
+ * @param decorator - A decorator function that wraps the base header renderer.
620
+ */
621
+ decorateHeaderRenderer<L extends Record<string, unknown> = DefaultGunshiParams['extensions']>(decorator: (baseRenderer: (ctx: Readonly<CommandContext<ExtractedParams<G, L>>>) => Promise<string>, ctx: Readonly<CommandContext<ExtractedParams<G, L>>>) => Promise<string>): void;
622
+ /**
623
+ * Decorate the usage renderer.
624
+ *
625
+ * @typeParam L - An extensions type to specify the shape of {@linkcode CommandContext}'s extensions.
626
+ *
627
+ * @param decorator - A decorator function that wraps the base usage renderer.
628
+ */
629
+ decorateUsageRenderer<L extends Record<string, unknown> = DefaultGunshiParams['extensions']>(decorator: (baseRenderer: (ctx: Readonly<CommandContext<ExtractedParams<G, L>>>) => Promise<string>, ctx: Readonly<CommandContext<ExtractedParams<G, L>>>) => Promise<string>): void;
630
+ /**
631
+ * Decorate the validation errors renderer.
632
+ *
633
+ * @typeParam L - An extensions type to specify the shape of {@linkcode CommandContext}'s extensions.
634
+ *
635
+ * @param decorator - A decorator function that wraps the base validation errors renderer.
636
+ */
637
+ decorateValidationErrorsRenderer<L extends Record<string, unknown> = DefaultGunshiParams['extensions']>(decorator: (baseRenderer: (ctx: Readonly<CommandContext<ExtractedParams<G, L>>>, error: AggregateError) => Promise<string>, ctx: Readonly<CommandContext<ExtractedParams<G, L>>>, error: AggregateError) => Promise<string>): void;
638
+ /**
639
+ * Decorate the command execution.
640
+ *
641
+ * Decorators are applied in reverse order (last registered is executed first).
642
+ *
643
+ * @typeParam L - An extensions type to specify the shape of {@linkcode CommandContext}'s extensions.
644
+ *
645
+ * @param decorator - A decorator function that wraps the command runner
646
+ */
647
+ decorateCommand<L extends Record<string, unknown> = DefaultGunshiParams['extensions']>(decorator: (baseRunner: (ctx: Readonly<CommandContext<ExtractedParams<G, L>>>) => Awaitable<void | string>) => (ctx: Readonly<CommandContext<ExtractedParams<G, L>>>) => Awaitable<void | string>): void;
648
+ }
649
+ //#endregion
650
+ //#region ../gunshi/src/plugin/core.d.ts
651
+ /**
652
+ * Plugin dependency definition
653
+ *
654
+ * @since v0.27.0
655
+ */
656
+ interface PluginDependency {
657
+ /**
658
+ * Dependency plugin id
659
+ */
660
+ id: string;
661
+ /**
662
+ * Optional dependency flag.
663
+ * If `true`, the plugin will not throw an error if the dependency is not found
664
+ */
665
+ optional?: boolean;
666
+ }
667
+ /**
668
+ * Plugin function type
669
+ *
670
+ * @typeParam G - A type extending {@linkcode GunshiParams} to specify the {@linkcode PluginContext}.
671
+ *
672
+ * @since v0.27.0
673
+ */
674
+ type PluginFunction<G extends GunshiParams = DefaultGunshiParams> = (ctx: Readonly<PluginContext<G>>) => Awaitable<void>;
675
+ /**
676
+ * Gunshi plugin, which is a function that receives a PluginContext.
677
+ *
678
+ * @typeParam E - A type extending {@link GunshiParams} to specify the shape of {@linkcode CommandContext}'s extensions.
679
+ *
680
+ * @param ctx - A {@linkcode PluginContext}.
681
+ * @returns An {@linkcode Awaitable} that resolves when the plugin is loaded.
682
+ *
683
+ * @since v0.27.0
684
+ */
685
+ type Plugin<E extends GunshiParams['extensions'] = DefaultGunshiParams['extensions']> = PluginFunction & {
686
+ id: string;
687
+ name?: string;
688
+ dependencies?: (PluginDependency | string)[];
689
+ extension?: CommandContextExtension<E>;
690
+ };
691
+ //#endregion
185
692
  //#region ../gunshi/src/types.d.ts
693
+ /**
694
+ * Awaitable type.
695
+ *
696
+ * @typeParam T - The type of the value that can be awaited.
697
+ */
186
698
  type Awaitable<T> = T | Promise<T>;
187
699
  /**
188
- * Extend command context type. This type is used to extend the command context with additional properties at {@link CommandContext.extensions}.
700
+ * Prettify a type by flattening its structure.
701
+ *
702
+ * @typeParam T - The type to be prettified.
703
+ */
704
+ type Prettify<T> = { [K in keyof T]: T[K] } & {};
705
+ /**
706
+ * Extend command context type. This type is used to extend the command context with additional properties at {@linkcode CommandContext.extensions}.
707
+ *
189
708
  * @since v0.27.0
190
709
  */
191
710
  type ExtendContext = Record<string, unknown>;
192
711
  /**
193
712
  * Gunshi unified parameter type.
713
+ *
194
714
  * This type combines both argument definitions and command context extensions.
715
+ *
716
+ * @typeParam P - The type of parameters, which can include `args` and `extensions`.
717
+ *
195
718
  * @since v0.27.0
196
719
  */
197
720
  interface GunshiParams<P extends {
@@ -202,111 +725,131 @@ interface GunshiParams<P extends {
202
725
  extensions: {};
203
726
  }> {
204
727
  /**
205
- * Command argument definitions
728
+ * Command argument definitions.
206
729
  */
207
730
  args: P extends {
208
731
  args: infer A extends Args;
209
732
  } ? A : Args;
210
733
  /**
211
- * Command context extensions
734
+ * Command context extensions.
212
735
  */
213
736
  extensions: P extends {
214
737
  extensions: infer E extends ExtendContext;
215
738
  } ? E : {};
216
739
  }
217
740
  /**
218
- * Default Gunshi parameters
741
+ * Default Gunshi parameters.
742
+ *
219
743
  * @since v0.27.0
220
744
  */
221
745
  type DefaultGunshiParams = GunshiParams;
222
746
  /**
223
747
  * Generic constraint for command-related types.
224
- * This type constraint allows both GunshiParams and objects with extensions.
748
+ *
749
+ * This type constraint allows both {@linkcode GunshiParams} and objects with extensions.
750
+ *
225
751
  * @since v0.27.0
226
752
  */
227
753
  type GunshiParamsConstraint = GunshiParams<any> | {
754
+ args: Args;
755
+ } | {
228
756
  extensions: ExtendContext;
229
757
  };
230
758
  /**
231
- * Type helper to extract args from G
759
+ * Type helper to extract args
760
+ *
761
+ * @typeParam G - The type of {@linkcode GunshiParams} or an object with {@linkcode Args}.
762
+ *
232
763
  * @internal
233
764
  */
234
- type ExtractArgs<G> = G extends GunshiParams<any> ? G['args'] : Args;
765
+ type ExtractArgs<G> = G extends GunshiParams<any> ? G['args'] : G extends {
766
+ args: infer A extends Args;
767
+ } ? A : Args;
235
768
  /**
236
- * Type helper to extract explicitly provided argument flags from G
769
+ * Type helper to extract explicitly provided argument flags.
770
+ *
771
+ * @typeParam G - The type of {@linkcode GunshiParams}.
772
+ *
237
773
  * @internal
238
774
  */
239
775
  type ExtractArgExplicitlyProvided<G> = ArgExplicitlyProvided<ExtractArgs<G>>;
240
776
  /**
241
777
  * Type helper to extract extensions from G
778
+ *
242
779
  * @internal
243
780
  */
244
781
  type ExtractExtensions<G> = G extends GunshiParams<any> ? G['extensions'] : G extends {
245
782
  extensions: infer E;
246
783
  } ? E : {};
247
- /**
248
- * Type helper to normalize G to GunshiParams
249
- * @internal
250
- */
251
-
252
784
  /**
253
785
  * Command environment.
786
+ *
787
+ * @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of command environments.
254
788
  */
255
789
  interface CommandEnvironment<G extends GunshiParamsConstraint = DefaultGunshiParams> {
256
790
  /**
257
791
  * Current working directory.
258
- * @see {@link CliOptions.cwd}
792
+ *
793
+ * @see {@linkcode CliOptions.cwd}
259
794
  */
260
795
  cwd: string | undefined;
261
796
  /**
262
797
  * Command name.
263
- * @see {@link CliOptions.name}
798
+ *
799
+ * @see {@linkcode CliOptions.name}
264
800
  */
265
801
  name: string | undefined;
266
802
  /**
267
803
  * Command description.
268
- * @see {@link CliOptions.description}
269
804
  *
805
+ * @see {@linkcode CliOptions.description}
270
806
  */
271
807
  description: string | undefined;
272
808
  /**
273
809
  * Command version.
274
- * @see {@link CliOptions.version}
810
+ *
811
+ * @see {@linkcode CliOptions.version}
275
812
  */
276
813
  version: string | undefined;
277
814
  /**
278
815
  * Left margin of the command output.
816
+ *
279
817
  * @default 2
280
- * @see {@link CliOptions.leftMargin}
818
+ * @see {@linkcode CliOptions.leftMargin}
281
819
  */
282
820
  leftMargin: number;
283
821
  /**
284
822
  * Middle margin of the command output.
823
+ *
285
824
  * @default 10
286
- * @see {@link CliOptions.middleMargin}
825
+ * @see {@linkcode CliOptions.middleMargin}
287
826
  */
288
827
  middleMargin: number;
289
828
  /**
290
829
  * Whether to display the usage option type.
830
+ *
291
831
  * @default false
292
- * @see {@link CliOptions.usageOptionType}
832
+ * @see {@linkcode CliOptions.usageOptionType}
293
833
  */
294
834
  usageOptionType: boolean;
295
835
  /**
296
836
  * Whether to display the option value.
837
+ *
297
838
  * @default true
298
- * @see {@link CliOptions.usageOptionValue}
839
+ * @see {@linkcode CliOptions.usageOptionValue}
299
840
  */
300
841
  usageOptionValue: boolean;
301
842
  /**
302
843
  * Whether to display the command usage.
844
+ *
303
845
  * @default false
304
- * @see {@link CliOptions.usageSilent}
846
+ * @see {@linkcode CliOptions.usageSilent}
305
847
  */
306
848
  usageSilent: boolean;
307
849
  /**
308
850
  * Sub commands.
309
- * @see {@link CliOptions.subCommands}
851
+ *
852
+ * @see {@linkcode CliOptions.subCommands}
310
853
  */
311
854
  subCommands: Map<string, Command<any> | LazyCommand<any>> | undefined;
312
855
  /**
@@ -323,54 +866,155 @@ interface CommandEnvironment<G extends GunshiParamsConstraint = DefaultGunshiPar
323
866
  renderValidationErrors: ((ctx: Readonly<CommandContext<G>>, error: AggregateError) => Promise<string>) | null | undefined;
324
867
  /**
325
868
  * Hook that runs before any command execution
326
- * @see {@link CliOptions.onBeforeCommand}
869
+ *
870
+ * @see {@linkcode CliOptions.onBeforeCommand}
327
871
  * @since v0.27.0
328
872
  */
329
873
  onBeforeCommand: ((ctx: Readonly<CommandContext<G>>) => Awaitable<void>) | undefined;
330
874
  /**
331
875
  * Hook that runs after successful command execution
332
- * @see {@link CliOptions.onAfterCommand}
876
+ *
877
+ * @see {@linkcode CliOptions.onAfterCommand}
333
878
  * @since v0.27.0
334
879
  */
335
880
  onAfterCommand: ((ctx: Readonly<CommandContext<G>>, result: string | undefined) => Awaitable<void>) | undefined;
336
881
  /**
337
882
  * Hook that runs when a command throws an error
338
- * @see {@link CliOptions.onErrorCommand}
883
+ *
884
+ * @see {@linkcode CliOptions.onErrorCommand}
339
885
  * @since v0.27.0
340
886
  */
341
887
  onErrorCommand: ((ctx: Readonly<CommandContext<G>>, error: Error) => Awaitable<void>) | undefined;
342
888
  }
343
889
  /**
344
- * CLI options of `cli` function.
890
+ * CLI options of {@linkcode cli} function.
891
+ *
892
+ * @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of cli options.
345
893
  */
346
-
894
+ interface CliOptions<G extends GunshiParamsConstraint = DefaultGunshiParams> {
895
+ /**
896
+ * Current working directory.
897
+ */
898
+ cwd?: string;
899
+ /**
900
+ * Command program name.
901
+ */
902
+ name?: string;
903
+ /**
904
+ * Command program description.
905
+ *
906
+ */
907
+ description?: string;
908
+ /**
909
+ * Command program version.
910
+ */
911
+ version?: string;
912
+ /**
913
+ * Sub commands.
914
+ */
915
+ subCommands?: Record<string, Command<any> | LazyCommand<any>> | Map<string, Command<any> | LazyCommand<any>>;
916
+ /**
917
+ * Left margin of the command output.
918
+ */
919
+ leftMargin?: number;
920
+ /**
921
+ * Middle margin of the command output.
922
+ */
923
+ middleMargin?: number;
924
+ /**
925
+ * Whether to display the usage optional argument type.
926
+ */
927
+ usageOptionType?: boolean;
928
+ /**
929
+ * Whether to display the optional argument value.
930
+ */
931
+ usageOptionValue?: boolean;
932
+ /**
933
+ * Whether to display the command usage.
934
+ */
935
+ usageSilent?: boolean;
936
+ /**
937
+ * Render function the command usage.
938
+ */
939
+ renderUsage?: ((ctx: Readonly<CommandContext<G>>) => Promise<string>) | null;
940
+ /**
941
+ * Render function the header section in the command usage.
942
+ */
943
+ renderHeader?: ((ctx: Readonly<CommandContext<G>>) => Promise<string>) | null;
944
+ /**
945
+ * Render function the validation errors.
946
+ */
947
+ renderValidationErrors?: ((ctx: Readonly<CommandContext<G>>, error: AggregateError) => Promise<string>) | null;
948
+ /**
949
+ * Whether to fallback to entry command when the sub-command is not found.
950
+ *
951
+ * @default false
952
+ * @since v0.27.0
953
+ */
954
+ fallbackToEntry?: boolean;
955
+ /**
956
+ * User plugins.
957
+ *
958
+ * @since v0.27.0
959
+ */
960
+ plugins?: Plugin[];
961
+ /**
962
+ * Hook that runs before any command execution
963
+ *
964
+ * @param ctx - The command context
965
+ * @since v0.27.0
966
+ */
967
+ onBeforeCommand?: (ctx: Readonly<CommandContext<G>>) => Awaitable<void>;
968
+ /**
969
+ * Hook that runs after successful command execution
970
+ *
971
+ * @param ctx - The command context
972
+ * @param result - The command execution result
973
+ * @since v0.27.0
974
+ */
975
+ onAfterCommand?: (ctx: Readonly<CommandContext<G>>, result: string | undefined) => Awaitable<void>;
976
+ /**
977
+ * Hook that runs when a command throws an error
978
+ *
979
+ * @param ctx - The command context
980
+ * @param error - The error thrown during execution
981
+ * @since v0.27.0
982
+ */
983
+ onErrorCommand?: (ctx: Readonly<CommandContext<G>>, error: Error) => Awaitable<void>;
984
+ }
347
985
  /**
348
986
  * Command call mode.
987
+ *
988
+ * - `entry`: The command is executed as an entry command.
989
+ * - `subCommand`: The command is executed as a sub-command.
349
990
  */
350
991
  type CommandCallMode = 'entry' | 'subCommand' | 'unexpected';
351
992
  /**
352
993
  * Command context.
994
+ *
353
995
  * Command context is the context of the command execution.
996
+ *
997
+ * @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of command context.
354
998
  */
355
999
  interface CommandContext<G extends GunshiParamsConstraint = DefaultGunshiParams> {
356
1000
  /**
357
1001
  * Command name, that is the command that is executed.
358
- * The command name is same {@link CommandEnvironment.name}.
1002
+ * The command name is same {@linkcode CommandEnvironment.name}.
359
1003
  */
360
1004
  name: string | undefined;
361
1005
  /**
362
1006
  * Command description, that is the description of the command that is executed.
363
- * The command description is same {@link CommandEnvironment.description}.
1007
+ * The command description is same {@linkcode CommandEnvironment.description}.
364
1008
  */
365
1009
  description: string | undefined;
366
1010
  /**
367
1011
  * Command environment, that is the environment of the command that is executed.
368
- * The command environment is same {@link CommandEnvironment}.
1012
+ * The command environment is same {@linkcode CommandEnvironment}.
369
1013
  */
370
1014
  env: Readonly<CommandEnvironment<G>>;
371
1015
  /**
372
1016
  * Command arguments, that is the arguments of the command that is executed.
373
- * The command arguments is same {@link Command.args}.
1017
+ * The command arguments is same {@linkcode Command.args}.
374
1018
  */
375
1019
  args: ExtractArgs<G>;
376
1020
  /**
@@ -384,7 +1028,7 @@ interface CommandContext<G extends GunshiParamsConstraint = DefaultGunshiParams>
384
1028
  explicit: ExtractArgExplicitlyProvided<G>;
385
1029
  /**
386
1030
  * Command values, that is the values of the command that is executed.
387
- * Resolve values with `resolveArgs` from command arguments and {@link Command.args}.
1031
+ * Resolve values with `resolveArgs` from command arguments and {@linkcode Command.args}.
388
1032
  */
389
1033
  values: ArgValues<ExtractArgs<G>>;
390
1034
  /**
@@ -416,22 +1060,24 @@ interface CommandContext<G extends GunshiParamsConstraint = DefaultGunshiParams>
416
1060
  callMode: CommandCallMode;
417
1061
  /**
418
1062
  * Whether to convert the camel-case style argument name to kebab-case.
419
- * This context value is set from {@link Command.toKebab} option.
1063
+ * This context value is set from {@linkcode Command.toKebab} option.
420
1064
  */
421
1065
  toKebab?: boolean;
422
1066
  /**
423
1067
  * Output a message.
424
- * If {@link CommandEnvironment.usageSilent} is true, the message is not output.
425
- * @param message an output message, @see {@link console.log}
426
- * @param optionalParams an optional parameters, @see {@link console.log}
427
- * @internal
1068
+ *
1069
+ * If {@linkcode CommandEnvironment.usageSilent} is true, the message is not output.
1070
+ *
1071
+ * @param message - an output message, see {@linkcode console.log}
1072
+ * @param optionalParams - an optional parameters, see {@linkcode console.log}
428
1073
  */
429
1074
  log: (message?: any, ...optionalParams: any[]) => void;
430
1075
  /**
431
1076
  * Command context extensions.
1077
+ *
432
1078
  * @since v0.27.0
433
1079
  */
434
- extensions: keyof ExtractExtensions<G> extends never ? undefined : ExtractExtensions<G>;
1080
+ extensions: keyof ExtractExtensions<G> extends never ? any : ExtractExtensions<G>;
435
1081
  /**
436
1082
  * Validation error from argument parsing.
437
1083
  * This will be set if argument validation fails during CLI execution.
@@ -440,11 +1086,67 @@ interface CommandContext<G extends GunshiParamsConstraint = DefaultGunshiParams>
440
1086
  }
441
1087
  /**
442
1088
  * CommandContextCore type (base type without extensions)
1089
+ *
1090
+ * @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of command context.
1091
+ *
443
1092
  * @since v0.27.0
444
1093
  */
445
-
1094
+ type CommandContextCore<G extends GunshiParamsConstraint = DefaultGunshiParams> = Readonly<CommandContext<G>>;
1095
+ /**
1096
+ * Command context extension
1097
+ *
1098
+ * @typeParam E - A type extending {@linkcode GunshiParams.extensions} to specify the shape of the extension.
1099
+ *
1100
+ * @since v0.27.0
1101
+ */
1102
+ interface CommandContextExtension<E extends GunshiParams['extensions'] = DefaultGunshiParams['extensions']> {
1103
+ /**
1104
+ * Plugin identifier
1105
+ */
1106
+ readonly key: symbol;
1107
+ /**
1108
+ * Plugin extension factory
1109
+ */
1110
+ readonly factory: (ctx: CommandContextCore, cmd: Command) => Awaitable<E>;
1111
+ /**
1112
+ * Plugin extension factory after hook
1113
+ */
1114
+ readonly onFactory?: (ctx: Readonly<CommandContext>, cmd: Readonly<Command>) => Awaitable<void>;
1115
+ }
1116
+ /**
1117
+ * Rendering control options
1118
+ *
1119
+ * @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of render options.
1120
+ *
1121
+ * @since v0.27.0
1122
+ */
1123
+ interface RenderingOptions<G extends GunshiParamsConstraint = DefaultGunshiParams> {
1124
+ /**
1125
+ * Header rendering configuration
1126
+ * - `null`: Disable rendering
1127
+ * - `function`: Use custom renderer
1128
+ * - `undefined` (when omitted): Use default renderer
1129
+ */
1130
+ header?: ((ctx: Readonly<CommandContext<G>>) => Promise<string>) | null;
1131
+ /**
1132
+ * Usage rendering configuration
1133
+ * - `null`: Disable rendering
1134
+ * - `function`: Use custom renderer
1135
+ * - `undefined` (when omitted): Use default renderer
1136
+ */
1137
+ usage?: ((ctx: Readonly<CommandContext<G>>) => Promise<string>) | null;
1138
+ /**
1139
+ * Validation errors rendering configuration
1140
+ * - `null`: Disable rendering
1141
+ * - `function`: Use custom renderer
1142
+ * - `undefined` (when omitted): Use default renderer
1143
+ */
1144
+ validationErrors?: ((ctx: Readonly<CommandContext<G>>, error: AggregateError) => Promise<string>) | null;
1145
+ }
446
1146
  /**
447
1147
  * Command interface.
1148
+ *
1149
+ * @typeParam G - The Gunshi parameters constraint
448
1150
  */
449
1151
  interface Command<G extends GunshiParamsConstraint = DefaultGunshiParams> {
450
1152
  /**
@@ -473,100 +1175,281 @@ interface Command<G extends GunshiParamsConstraint = DefaultGunshiParams> {
473
1175
  run?: CommandRunner<G>;
474
1176
  /**
475
1177
  * Whether to convert the camel-case style argument name to kebab-case.
476
- * If you will set to `true`, All {@link Command.args} names will be converted to kebab-case.
1178
+ * If you will set to `true`, All {@linkcode Command.args} names will be converted to kebab-case.
477
1179
  */
478
1180
  toKebab?: boolean;
479
1181
  /**
480
1182
  * Whether this is an internal command.
481
1183
  * Internal commands are not shown in help usage.
1184
+ *
482
1185
  * @default false
483
1186
  * @since v0.27.0
484
1187
  */
485
1188
  internal?: boolean;
486
1189
  /**
487
1190
  * Whether this command is an entry command.
1191
+ *
488
1192
  * @default undefined
489
1193
  * @since v0.27.0
490
1194
  */
491
1195
  entry?: boolean;
1196
+ /**
1197
+ * Rendering control options
1198
+ *
1199
+ * @since v0.27.0
1200
+ */
1201
+ rendering?: RenderingOptions<G>;
492
1202
  }
493
1203
  /**
494
1204
  * Lazy command interface.
1205
+ *
495
1206
  * Lazy command that's not loaded until it is executed.
1207
+ *
1208
+ * @typeParam G - The Gunshi parameters constraint
1209
+ * @typeParam D - The partial command definition provided to lazy function
496
1210
  */
497
- type LazyCommand<G extends GunshiParamsConstraint = DefaultGunshiParams> = {
1211
+ type LazyCommand<G extends GunshiParamsConstraint = DefaultGunshiParams, D extends Partial<Command<G>> = {}> = {
498
1212
  /**
499
1213
  * Command load function
500
1214
  */
501
1215
  (): Awaitable<Command<G> | CommandRunner<G>>;
502
- /**
503
- * Command name
504
- */
1216
+ } & (D extends {
1217
+ name: infer N;
1218
+ } ? {
1219
+ commandName: N;
1220
+ } : {
505
1221
  commandName?: string;
506
- } & Omit<Command<G>, 'run' | 'name'>;
507
- /**
508
- * Define a command type.
509
- */
510
-
1222
+ }) & Omit<D, 'name' | 'run'> & Partial<Omit<Command<G>, keyof D | 'run' | 'name'>>;
511
1223
  /**
512
1224
  * Command examples fetcher.
513
- * @param ctx A {@link CommandContext | command context}
1225
+ *
1226
+ * @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of command context.
1227
+ *
1228
+ * @param ctx - A {@link CommandContext | command context}
514
1229
  * @returns A fetched command examples.
515
1230
  */
516
1231
  type CommandExamplesFetcher<G extends GunshiParamsConstraint = DefaultGunshiParams> = (ctx: Readonly<CommandContext<G>>) => Awaitable<string>;
517
1232
  /**
518
1233
  * Command runner.
519
- * @param ctx A {@link CommandContext | command context}
1234
+ *
1235
+ * @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of command context.
1236
+ *
1237
+ * @param ctx - A {@link CommandContext | command context}
520
1238
  * @returns void or string (for CLI output)
521
1239
  */
522
1240
  type CommandRunner<G extends GunshiParamsConstraint = DefaultGunshiParams> = (ctx: Readonly<CommandContext<G>>) => Awaitable<string | void>;
523
1241
  /**
524
1242
  * Command loader.
1243
+ *
525
1244
  * A function that returns a command or command runner.
526
1245
  * This is used to lazily load commands.
1246
+ *
1247
+ * @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of command context and command runner.
1248
+ *
527
1249
  * @returns A command or command runner
528
1250
  */
529
1251
  type CommandLoader<G extends GunshiParamsConstraint = DefaultGunshiParams> = () => Awaitable<Command<G> | CommandRunner<G>>;
1252
+ //#endregion
1253
+ //#region ../gunshi/src/context.d.ts
530
1254
  /**
531
- * Command decorator.
532
- * A function that wraps a command runner to add or modify its behavior.
533
- * @param baseRunner The base command runner to decorate
534
- * @returns The decorated command runner
535
- * @since v0.27.0
1255
+ * Extract extension return types from extensions record
1256
+ *
1257
+ * @internal
1258
+ */
1259
+ type ExtractExtensions$1<E extends Record<string, CommandContextExtension>> = { [K in keyof E]: E[K] extends CommandContextExtension<infer T> ? T : never };
1260
+ /**
1261
+ * Parameters of {@link createCommandContext}
1262
+ */
1263
+ interface CommandContextParams<G extends GunshiParams | {
1264
+ args: Args;
1265
+ } | {
1266
+ extensions: ExtendContext;
1267
+ }, V extends ArgValues<ExtractArgs<G>>, C extends Command<G> | LazyCommand<G> = Command<G>, E extends Record<string, CommandContextExtension> = Record<string, CommandContextExtension>> {
1268
+ /**
1269
+ * An arguments of target command
1270
+ */
1271
+ args?: ExtractArgs<G>;
1272
+ /**
1273
+ * Explicitly provided arguments
1274
+ */
1275
+ explicit?: ExtractArgExplicitlyProvided<G>;
1276
+ /**
1277
+ * A values of target command
1278
+ */
1279
+ values?: V;
1280
+ /**
1281
+ * A positionals arguments, which passed to the target command
1282
+ */
1283
+ positionals?: string[];
1284
+ /**
1285
+ * A rest arguments, which passed to the target command
1286
+ */
1287
+ rest?: string[];
1288
+ /**
1289
+ * Original command line arguments
1290
+ */
1291
+ argv?: string[];
1292
+ /**
1293
+ * Argument tokens that are parsed by the `parseArgs` function
1294
+ */
1295
+ tokens?: ArgToken[];
1296
+ /**
1297
+ * Whether the command is omitted
1298
+ */
1299
+ omitted?: boolean;
1300
+ /**
1301
+ * Command call mode.
1302
+ */
1303
+ callMode?: CommandCallMode;
1304
+ /**
1305
+ * A target command
1306
+ */
1307
+ command?: C;
1308
+ /**
1309
+ * Plugin extensions to apply as the command context extension.
1310
+ */
1311
+ extensions?: E;
1312
+ /**
1313
+ * A command options, which is spicialized from `cli` function
1314
+ */
1315
+ cliOptions?: CliOptions<G>;
1316
+ /**
1317
+ * Validation error from argument parsing.
1318
+ */
1319
+ validationError?: AggregateError;
1320
+ }
1321
+ /**
1322
+ * Create a command context.
1323
+ *
1324
+ * @param param - A {@link CommandContextParams | parameters} to create a command context.
1325
+ * @returns A {@link CommandContext | command context}, which is readonly.
536
1326
  */
1327
+ 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> = {}>({
1328
+ args,
1329
+ explicit,
1330
+ values,
1331
+ positionals,
1332
+ rest,
1333
+ argv,
1334
+ tokens,
1335
+ command,
1336
+ extensions,
1337
+ cliOptions,
1338
+ callMode,
1339
+ omitted,
1340
+ validationError
1341
+ }: CommandContextParams<G, V, C, E>): Promise<{} extends ExtractExtensions$1<E> ? Readonly<CommandContext<G>> : Readonly<CommandContext<GunshiParams<{
1342
+ args: ExtractArgs<G>;
1343
+ extensions: ExtractExtensions$1<E>;
1344
+ }>>>>;
537
1345
  //#endregion
538
1346
  //#region ../gunshi/src/definition.d.ts
539
1347
  /**
540
- * Define a {@link Command | command}
541
- * @param definition A {@link Command | command} definition
1348
+ * Infer command properties excluding for {@link define} function
1349
+ *
1350
+ * @internal
542
1351
  */
543
- declare function define<A extends Args>(definition: Command<{
544
- args: A;
545
- extensions: {};
546
- }>): Command<{
1352
+ type InferCommandProps<G extends GunshiParamsConstraint = DefaultGunshiParams> = Pick<Command<G>, Exclude<keyof Command<G>, keyof Command<G>>>;
1353
+ /**
1354
+ * The result type of the {@link define} function
1355
+ *
1356
+ * @internal
1357
+ */
1358
+ type CommandDefinitionResult<G extends GunshiParamsConstraint = DefaultGunshiParams, C extends Command<G> = Command<G>> = Prettify<Pick<C, keyof C> & Partial<Pick<Command<G>, Exclude<keyof Command<G>, keyof C>>>>;
1359
+ /**
1360
+ * Define a {@link Command | command}.
1361
+ *
1362
+ * @example
1363
+ * ```ts
1364
+ * const command = define({
1365
+ * name: 'test',
1366
+ * description: 'A test command',
1367
+ * args: {
1368
+ * debug: {
1369
+ * type: 'boolean',
1370
+ * description: 'Enable debug mode',
1371
+ * default: false
1372
+ * }
1373
+ * },
1374
+ * run: ctx => {
1375
+ * if (ctx.values.debug) {
1376
+ * console.debug('Debug mode is enabled');
1377
+ * }
1378
+ * }
1379
+ * })
1380
+ * ```
1381
+ *
1382
+ * @typeParam G - A {@link GunshiParamsConstraint} type
1383
+ * @typeParam A - An {@link Args} type extracted from {@link GunshiParamsConstraint}
1384
+ * @typeParam C - A {@link Command} type inferred from {@link GunshiParamsConstraint}
1385
+ *
1386
+ * @param definition - A {@link Command | command} definition
1387
+ * @returns A defined {@link Command | command}
1388
+ */
1389
+ declare function define<G extends GunshiParamsConstraint = DefaultGunshiParams, A extends Args = ExtractArgs<G>, C extends InferCommandProps<G> = InferCommandProps<G>>(definition: C & Command<{
547
1390
  args: A;
548
- extensions: {};
549
- }>;
1391
+ extensions: ExtractExtensions<G>;
1392
+ }>): CommandDefinitionResult<G, C>;
550
1393
  /**
551
- * Define a {@link Command | command}
552
- * @param definition A {@link Command | command} definition
1394
+ * Return type for defineWithTypes
1395
+ *
1396
+ * @typeParam DefaultExtensions - The {@link ExtendContext} type extracted from G
1397
+ *
1398
+ * @internal
553
1399
  */
554
- declare function define<E extends ExtendContext>(definition: Command<{
555
- args: Args;
556
- extensions: E;
557
- }>): Command<{
558
- args: Args;
559
- extensions: E;
560
- }>;
1400
+ type DefineWithTypesReturn<DefaultExtensions extends ExtendContext, DefaultArgs extends Args> = <A extends DefaultArgs = DefaultArgs, C extends Partial<Command<{
1401
+ args: A;
1402
+ extensions: DefaultExtensions;
1403
+ }>> = {}>(definition: C & Command<{
1404
+ args: A;
1405
+ extensions: DefaultExtensions;
1406
+ }>) => CommandDefinitionResult<{
1407
+ args: A;
1408
+ extensions: DefaultExtensions;
1409
+ }, C>;
561
1410
  /**
562
- * Define a {@link Command | command}
563
- * @param definition A {@link Command | command} definition
1411
+ * Define a {@link Command | command} with types
1412
+ *
1413
+ * This helper function allows specifying the type parameter of {@link GunshiParams}
1414
+ * while inferring the {@link Args} type, {@link ExtendContext} type from the definition.
1415
+ *
1416
+ * @example
1417
+ * ```ts
1418
+ * // Define a command with specific extensions type
1419
+ * type MyExtensions = { logger: { log: (message: string) => void } }
1420
+ *
1421
+ * const command = defineWithTypes<{ extensions: MyExtensions }>()({
1422
+ * name: 'greet',
1423
+ * args: {
1424
+ * name: { type: 'string' }
1425
+ * },
1426
+ * run: ctx => {
1427
+ * // ctx.values is inferred as { name?: string }
1428
+ * // ctx.extensions is MyExtensions
1429
+ * }
1430
+ * })
1431
+ * ```
1432
+ *
1433
+ * @typeParam G - A {@link GunshiParams} type
1434
+ *
1435
+ * @returns A function that takes a command definition via {@link define}
1436
+ *
1437
+ * @since v0.27.0
564
1438
  */
565
- declare function define<G extends GunshiParamsConstraint = DefaultGunshiParams>(definition: Command<G>): Command<G>;
1439
+ declare function defineWithTypes<G extends GunshiParamsConstraint>(): DefineWithTypesReturn<ExtractExtensions<G>, ExtractArgs<G>>;
566
1440
  /**
567
- * Define a {@link LazyCommand | lazy command}
568
- * @param loader A {@link CommandLoader | command loader}
569
- * @returns A {@link LazyCommand | lazy command} loader
1441
+ * Define a {@link LazyCommand | lazy command}.
1442
+ *
1443
+ * @example
1444
+ * ```ts
1445
+ * // load command with dynamic importing
1446
+ * const test = lazy(() => import('./commands/test'))
1447
+ * ```
1448
+ *
1449
+ * @typeParam A - An {@link Args} type
1450
+ *
1451
+ * @param loader - A {@link CommandLoader | command loader}
1452
+ * @returns A {@link LazyCommand | lazy command} with loader
570
1453
  */
571
1454
  declare function lazy<A extends Args>(loader: CommandLoader<{
572
1455
  args: A;
@@ -574,63 +1457,121 @@ declare function lazy<A extends Args>(loader: CommandLoader<{
574
1457
  }>): LazyCommand<{
575
1458
  args: A;
576
1459
  extensions: {};
577
- }>;
1460
+ }, {}>;
578
1461
  /**
579
1462
  * Define a {@link LazyCommand | lazy command} with definition.
580
- * @param loader A {@link CommandLoader | command loader} function that returns a command definition
581
- * @param definition An optional {@link Command | command} definition
1463
+ *
1464
+ * @example
1465
+ * ```ts
1466
+ * // define command without command runner
1467
+ * const testDefinition = define({
1468
+ * name: 'test',
1469
+ * description: 'Test command',
1470
+ * args: {
1471
+ * debug: {
1472
+ * type: 'boolean',
1473
+ * description: 'Enable debug mode',
1474
+ * default: false
1475
+ * }
1476
+ * },
1477
+ * })
1478
+ *
1479
+ * // define load command with command runner and defined command
1480
+ * const test = lazy((): CommandRunner<{ args: typeof testDefinition.args; extensions: {} }> => {
1481
+ * return ctx => {
1482
+ * if (ctx.values.debug) {
1483
+ * console.debug('Debug mode is enabled');
1484
+ * }
1485
+ * }
1486
+ * }, testDefinition)
1487
+ * ```
1488
+ *
1489
+ * @typeParam A - An {@link Args} type
1490
+ * @typeParam D - A partial {@link Command} definition type
1491
+ *
1492
+ * @param loader - A {@link CommandLoader | command loader} function that returns a command definition
1493
+ * @param definition - An optional {@link Command | command} definition
582
1494
  * @returns A {@link LazyCommand | lazy command} that can be executed later
583
1495
  */
584
- declare function lazy<A extends Args>(loader: CommandLoader<{
1496
+ declare function lazy<G extends GunshiParamsConstraint = DefaultGunshiParams, A extends ExtractArgs<G> = ExtractArgs<G>, D extends Partial<Command<{
585
1497
  args: A;
586
1498
  extensions: {};
587
- }>, definition: Command<{
1499
+ }>> = Partial<Command<{
588
1500
  args: A;
589
1501
  extensions: {};
590
- }>): LazyCommand<{
1502
+ }>>>(loader: CommandLoader<{
591
1503
  args: A;
592
1504
  extensions: {};
593
- }>;
594
- /**
595
- * Define a {@link LazyCommand | lazy command}
596
- * @param loader A {@link CommandLoader | command loader}
597
- * @returns A {@link LazyCommand | lazy command} loader
598
- */
599
- declare function lazy<E extends ExtendContext>(loader: CommandLoader<{
600
- args: Args;
601
- extensions: E;
602
- }>): LazyCommand<{
603
- args: Args;
604
- extensions: E;
605
- }>;
1505
+ }>, definition: D): LazyCommand<{
1506
+ args: A;
1507
+ extensions: {};
1508
+ }, D>;
606
1509
  /**
607
- * Define a {@link LazyCommand | lazy command} with definition.
608
- * @param loader A {@link CommandLoader | command loader} function that returns a command definition
609
- * @param definition An optional {@link Command | command} definition
610
- * @returns A {@link LazyCommand | lazy command} that can be executed later
1510
+ * Normalize G to a full GunshiParams type
1511
+ *
1512
+ * @typeParam G - A {@link GunshiParamsConstraint} type
1513
+ *
1514
+ * @internal
611
1515
  */
612
- declare function lazy<E extends ExtendContext>(loader: CommandLoader<{
613
- args: Args;
614
- extensions: E;
615
- }>, definition: Command<{
616
- args: Args;
1516
+ type NormalizeGunshiParams<G extends GunshiParamsConstraint> = G extends GunshiParams<any> ? G : G extends {
1517
+ args: infer A;
1518
+ extensions: infer E;
1519
+ } ? {
1520
+ args: A;
617
1521
  extensions: E;
618
- }>): LazyCommand<{
1522
+ } : G extends {
1523
+ args: infer A;
1524
+ } ? {
1525
+ args: A;
1526
+ extensions: {};
1527
+ } : G extends {
1528
+ extensions: infer E;
1529
+ } ? {
619
1530
  args: Args;
620
1531
  extensions: E;
621
- }>;
1532
+ } : DefaultGunshiParams;
622
1533
  /**
623
- * Define a {@link LazyCommand | lazy command}
624
- * @param loader A {@link CommandLoader | command loader}
625
- * @returns A {@link LazyCommand | lazy command} loader
1534
+ * Return type for lazyWithTypes
1535
+ *
1536
+ * @typeParam FullG - The normalized {@link GunshiParams} type
1537
+ *
1538
+ * @internal
626
1539
  */
627
- declare function lazy<G extends GunshiParamsConstraint = DefaultGunshiParams>(loader: CommandLoader<G>): LazyCommand<G>;
1540
+ type LazyWithTypesReturn<FullG extends GunshiParamsConstraint> = <D extends Partial<Command<FullG>> = {}>(loader: CommandLoader<FullG>, definition?: D) => LazyCommand<FullG, D>;
628
1541
  /**
629
- * Define a {@link LazyCommand | lazy command} with definition.
630
- * @param loader A {@link CommandLoader | command loader} function that returns a command definition
631
- * @param definition An optional {@link Command | command} definition
632
- * @returns A {@link LazyCommand | lazy command} that can be executed later
1542
+ * Define a {@link LazyCommand | lazy command} with specific type parameters.
1543
+ *
1544
+ * This helper function allows specifying the type parameter of {@link GunshiParams}
1545
+ * while inferring the {@link Args} type, {@link ExtendContext} type from the definition.
1546
+ *
1547
+ * @example
1548
+ * ```ts
1549
+ * type MyExtensions = { logger: { log: (message: string) => void } }
1550
+ *
1551
+ * const command = lazyWithTypes<{ extensions: MyExtensions }>()(
1552
+ * () => {
1553
+ * return ctx => {
1554
+ * // Command runner implementation
1555
+ * ctx.extensions.logger?.log('Command executed')
1556
+ * },
1557
+ * {
1558
+ * name: 'lazy-command',
1559
+ * args: {
1560
+ * opt: {
1561
+ * type: 'string',
1562
+ * description: 'An optional string argument',
1563
+ * required: false,
1564
+ * },
1565
+ * },
1566
+ * )
1567
+ * ```
1568
+ *
1569
+ * @typeParam G - A {@link GunshiParams} type
1570
+ *
1571
+ * @returns A function that takes a lazy command definition via {@link lazy}
1572
+ *
1573
+ * @since v0.27.0
633
1574
  */
634
- declare function lazy<G extends GunshiParamsConstraint = DefaultGunshiParams>(loader: CommandLoader<G>, definition: Command<G>): LazyCommand<G>;
1575
+ declare function lazyWithTypes<G extends GunshiParamsConstraint>(): LazyWithTypesReturn<NormalizeGunshiParams<G>>;
635
1576
  //#endregion
636
- export { ArgSchema, ArgValues, Args, Command, CommandLoader, CommandRunner, DefaultGunshiParams, ExtendContext, GunshiParams, LazyCommand, define, lazy };
1577
+ export { type ArgSchema, type ArgValues, type Args, type Command, type CommandContextParams, type CommandLoader, type CommandRunner, type DefaultGunshiParams, type ExtendContext, type GunshiParams, type LazyCommand, createCommandContext, define, defineWithTypes, lazy, lazyWithTypes };