@gunshi/plugin 0.26.3 → 0.27.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/lib/index.d.ts +546 -240
  2. package/lib/index.js +122 -2
  3. package/package.json +5 -5
package/lib/index.d.ts CHANGED
@@ -1,161 +1,395 @@
1
- //#region ../../node_modules/.pnpm/args-tokens@0.20.1/node_modules/args-tokens/lib/parser-FiQIAw-2.d.ts
1
+ //#region ../../node_modules/.pnpm/args-tokens@0.22.0/node_modules/args-tokens/lib/parser-Cbxholql.d.ts
2
2
  //#region src/parser.d.ts
3
3
  /**
4
- * Entry point of argument parser.
5
- * @module
6
- */
7
- /**
8
- * forked from `nodejs/node` (`pkgjs/parseargs`)
9
- * repository url: https://github.com/nodejs/node (https://github.com/pkgjs/parseargs)
10
- * code url: https://github.com/nodejs/node/blob/main/lib/internal/util/parse_args/parse_args.js
11
- *
12
- * @author kazuya kawaguchi (a.k.a. kazupon)
13
- * @license MIT
14
- */
15
- /**
16
- * Argument token Kind.
17
- * - `option`: option token, support short option (e.g. `-x`) and long option (e.g. `--foo`)
18
- * - `option-terminator`: option terminator (`--`) token, see guideline 10 in https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
19
- * - `positional`: positional token
20
- */
21
- type ArgTokenKind = "option" | "option-terminator" | "positional";
22
- /**
23
- * Argument token.
24
- */
4
+ * Entry point of argument parser.
5
+ * @module
6
+ */
7
+ /**
8
+ * forked from `nodejs/node` (`pkgjs/parseargs`)
9
+ * repository url: https://github.com/nodejs/node (https://github.com/pkgjs/parseargs)
10
+ * code url: https://github.com/nodejs/node/blob/main/lib/internal/util/parse_args/parse_args.js
11
+ *
12
+ * @author kazuya kawaguchi (a.k.a. kazupon)
13
+ * @license MIT
14
+ */
15
+ /**
16
+ * Argument token Kind.
17
+ * - `option`: option token, support short option (e.g. `-x`) and long option (e.g. `--foo`)
18
+ * - `option-terminator`: option terminator (`--`) token, see guideline 10 in https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
19
+ * - `positional`: positional token
20
+ */
21
+ type ArgTokenKind = 'option' | 'option-terminator' | 'positional';
22
+ /**
23
+ * Argument token.
24
+ */
25
25
  interface ArgToken {
26
26
  /**
27
- * Argument token kind.
28
- */
27
+ * Argument token kind.
28
+ */
29
29
  kind: ArgTokenKind;
30
30
  /**
31
- * Argument token index, e.g `--foo bar` => `--foo` index is 0, `bar` index is 1.
32
- */
31
+ * Argument token index, e.g `--foo bar` => `--foo` index is 0, `bar` index is 1.
32
+ */
33
33
  index: number;
34
34
  /**
35
- * Option name, e.g. `--foo` => `foo`, `-x` => `x`.
36
- */
35
+ * Option name, e.g. `--foo` => `foo`, `-x` => `x`.
36
+ */
37
37
  name?: string;
38
38
  /**
39
- * Raw option name, e.g. `--foo` => `--foo`, `-x` => `-x`.
40
- */
39
+ * Raw option name, e.g. `--foo` => `--foo`, `-x` => `-x`.
40
+ */
41
41
  rawName?: string;
42
42
  /**
43
- * Option value, e.g. `--foo=bar` => `bar`, `-x=bar` => `bar`.
44
- * If the `allowCompatible` option is `true`, short option value will be same as Node.js `parseArgs` behavior.
45
- */
43
+ * Option value, e.g. `--foo=bar` => `bar`, `-x=bar` => `bar`.
44
+ * If the `allowCompatible` option is `true`, short option value will be same as Node.js `parseArgs` behavior.
45
+ */
46
46
  value?: string;
47
47
  /**
48
- * Inline value, e.g. `--foo=bar` => `true`, `-x=bar` => `true`.
49
- */
48
+ * Inline value, e.g. `--foo=bar` => `true`, `-x=bar` => `true`.
49
+ */
50
50
  inlineValue?: boolean;
51
- } //#endregion
52
- //#region ../../node_modules/.pnpm/args-tokens@0.20.1/node_modules/args-tokens/lib/resolver-U72Jg6Ll.d.ts
53
-
51
+ }
54
52
  /**
55
- * Parser Options.
56
- */
53
+ * Parser Options.
54
+ */
55
+ //#endregion
56
+ //#region ../../node_modules/.pnpm/args-tokens@0.22.0/node_modules/args-tokens/lib/resolver-BoS-UnqX.d.ts
57
57
  //#region src/resolver.d.ts
58
+
58
59
  /**
59
- * An argument schema
60
- * This schema is similar to the schema of the `node:utils`.
61
- * difference is that:
62
- * - `required` property and `description` property are added
63
- * - `type` is not only 'string' and 'boolean', but also 'number', 'enum', 'positional', 'custom' too.
64
- * - `default` property type, not support multiple types
65
- */
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
66
+ */
66
67
  interface ArgSchema {
67
68
  /**
68
- * Type of argument.
69
- */
70
- type: "string" | "boolean" | "number" | "enum" | "positional" | "custom";
69
+ * Type of argument.
70
+ */
71
+ type: 'string' | 'boolean' | 'number' | 'enum' | 'positional' | 'custom';
71
72
  /**
72
- * A single character alias for the argument.
73
- */
73
+ * A single character alias for the argument.
74
+ */
74
75
  short?: string;
75
76
  /**
76
- * A description of the argument.
77
- */
77
+ * A description of the argument.
78
+ */
78
79
  description?: string;
79
80
  /**
80
- * Whether the argument is required or not.
81
- */
81
+ * Whether the argument is required or not.
82
+ */
82
83
  required?: true;
83
84
  /**
84
- * Whether the argument allow multiple values or not.
85
- */
85
+ * Whether the argument allow multiple values or not.
86
+ */
86
87
  multiple?: true;
87
88
  /**
88
- * Whether the negatable option for `boolean` type
89
- */
89
+ * Whether the negatable option for `boolean` type
90
+ */
90
91
  negatable?: boolean;
91
92
  /**
92
- * The allowed values of the argument, and string only. This property is only used when the type is 'enum'.
93
- */
93
+ * The allowed values of the argument, and string only. This property is only used when the type is 'enum'.
94
+ */
94
95
  choices?: string[] | readonly string[];
95
96
  /**
96
- * The default value of the argument.
97
- * if the type is 'enum', the default value must be one of the allowed values.
98
- */
97
+ * The default value of the argument.
98
+ * if the type is 'enum', the default value must be one of the allowed values.
99
+ */
99
100
  default?: string | boolean | number;
100
101
  /**
101
- * Whether to convert the argument name to kebab-case.
102
- */
102
+ * Whether to convert the argument name to kebab-case.
103
+ */
103
104
  toKebab?: true;
104
105
  /**
105
- * A function to parse the value of the argument. if the type is 'custom', this function is required.
106
- * If argument value will be invalid, this function have to throw an error.
107
- * @param value
108
- * @returns Parsed value
109
- * @throws An Error, If the value is invalid. Error type should be `Error` or extends it
110
- */
111
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
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
111
+ */
112
112
  parse?: (value: string) => any;
113
113
  }
114
114
  /**
115
- * An object that contains {@link ArgSchema | argument schema}.
116
- */
115
+ * An object that contains {@link ArgSchema | argument schema}.
116
+ */
117
117
  interface Args {
118
118
  [option: string]: ArgSchema;
119
119
  }
120
120
  /**
121
- * An object that contains the values of the arguments.
122
- */
121
+ * An object that contains the values of the arguments.
122
+ */
123
123
  type ArgValues<T> = T extends Args ? ResolveArgValues<T, { [Arg in keyof T]: ExtractOptionValue<T[Arg]> }> : {
124
124
  [option: string]: string | boolean | number | (string | boolean | number)[] | undefined;
125
125
  };
126
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
127
126
  type IsFunction<T> = T extends ((...args: any[]) => any) ? true : false;
128
127
  /**
129
- * @internal
130
- */
131
- 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>;
132
- type ResolveOptionValue<A extends ArgSchema, T> = A["multiple"] extends true ? T[] : T;
128
+ * @internal
129
+ */
130
+ 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
+ type ResolveOptionValue<A extends ArgSchema, T> = A['multiple'] extends true ? T[] : T;
133
132
  /**
134
- * @internal
135
- */
136
- 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;
133
+ * @internal
134
+ */
135
+ 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;
137
136
  /**
138
- * @internal
139
- */
137
+ * @internal
138
+ */
140
139
  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] };
141
140
  /**
142
- * @internal
143
- */
144
- 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] };
141
+ * @internal
142
+ */
143
+ 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] };
144
+ /**
145
+ * An arguments for {@link resolveArgs | resolve arguments}.
146
+ */
145
147
 
148
+ /**
149
+ * Tracks which arguments were explicitly provided by the user.
150
+ *
151
+ * Each property indicates whether the corresponding argument was explicitly
152
+ * provided (true) or is using a default value or not provided (false).
153
+ */
154
+ type ArgExplicitlyProvided<A extends Args> = { [K in keyof A]: boolean };
155
+ /**
156
+ * Resolve command line arguments.
157
+ * @param args - An arguments that contains {@link ArgSchema | arguments schema}.
158
+ * @param tokens - An array of {@link ArgToken | tokens}.
159
+ * @param resolveArgs - An arguments that contains {@link ResolveArgs | resolve arguments}.
160
+ * @returns An object that contains the values of the arguments, positional arguments, rest arguments, {@link AggregateError | validation errors}, and explicit provision status.
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * // passed tokens: --port 3000
165
+ *
166
+ * const { values, explicit } = resolveArgs({
167
+ * port: {
168
+ * type: 'number',
169
+ * default: 8080
170
+ * },
171
+ * host: {
172
+ * type: 'string',
173
+ * default: 'localhost'
174
+ * }
175
+ * }, parsedTokens)
176
+ *
177
+ * values.port // 3000
178
+ * values.host // 'localhost'
179
+ *
180
+ * explicit.port // true (explicitly provided)
181
+ * explicit.host // false (not provided, fallback to default)
182
+ * ```
183
+ */
146
184
  //#endregion
147
- //#region ../gunshi/src/types.d.ts
185
+ //#region ../gunshi/src/plugin/context.d.ts
186
+ /**
187
+ * Type helper to create GunshiParams from extracted args and extensions
188
+ * @internal
189
+ */
190
+ type ExtractedParams<G extends GunshiParamsConstraint, L extends Record<string, unknown> = {}> = {
191
+ args: ExtractArgs<G>;
192
+ extensions: ExtractExtensions$1<G> & L;
193
+ };
194
+ /**
195
+ * Gunshi plugin context interface.
196
+ * @since v0.27.0
197
+ */
198
+ interface PluginContext<G extends GunshiParamsConstraint = DefaultGunshiParams> {
199
+ /**
200
+ * Get the global options
201
+ * @returns A map of global options.
202
+ */
203
+ readonly globalOptions: Map<string, ArgSchema>;
204
+ /**
205
+ * Get the registered sub commands
206
+ * @returns A map of sub commands.
207
+ */
208
+ readonly subCommands: ReadonlyMap<string, Command<G> | LazyCommand<G>>;
209
+ /**
210
+ * Add a global option.
211
+ * @param name An option name
212
+ * @param schema An {@link ArgSchema} for the option
213
+ */
214
+ addGlobalOption(name: string, schema: ArgSchema): void;
215
+ /**
216
+ * Add a sub command.
217
+ * @param name Command name
218
+ * @param command Command definition
219
+ */
220
+ addCommand(name: string, command: Command<G> | LazyCommand<G>): void;
221
+ /**
222
+ * Check if a command exists.
223
+ * @param name Command name
224
+ * @returns True if the command exists, false otherwise
225
+ */
226
+ hasCommand(name: string): boolean;
227
+ /**
228
+ * Decorate the header renderer.
229
+ * @param decorator - A decorator function that wraps the base header renderer.
230
+ */
231
+ 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;
232
+ /**
233
+ * Decorate the usage renderer.
234
+ * @param decorator - A decorator function that wraps the base usage renderer.
235
+ */
236
+ 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;
237
+ /**
238
+ * Decorate the validation errors renderer.
239
+ * @param decorator - A decorator function that wraps the base validation errors renderer.
240
+ */
241
+ 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;
242
+ /**
243
+ * Decorate the command execution.
244
+ * Decorators are applied in reverse order (last registered is executed first).
245
+ * @param decorator - A decorator function that wraps the command runner
246
+ */
247
+ 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;
248
+ }
249
+ /**
250
+ * Factory function for creating a plugin context.
251
+ * @param decorators - A {@link Decorators} instance.
252
+ * @param initialSubCommands - Initial sub commands map.
253
+ * @returns A new {@link PluginContext} instance.
254
+ */
255
+ //#endregion
256
+ //#region ../gunshi/src/plugin/core.d.ts
257
+ /**
258
+ * Plugin dependency definition
259
+ * @since v0.27.0
260
+ */
261
+ interface PluginDependency {
262
+ /**
263
+ * Dependency plugin id
264
+ */
265
+ id: string;
266
+ /**
267
+ * Optional dependency flag.
268
+ * If true, the plugin will not throw an error if the dependency is not found.
269
+ */
270
+ optional?: boolean;
271
+ }
272
+ /**
273
+ * Plugin function type
274
+ * @since v0.27.0
275
+ */
276
+ type PluginFunction<G extends GunshiParams = DefaultGunshiParams> = (ctx: Readonly<PluginContext<G>>) => Awaitable<void>;
277
+ /**
278
+ * Plugin extension for CommandContext
279
+ * @since v0.27.0
280
+ */
281
+ type PluginExtension<T = Record<string, unknown>, G extends GunshiParams = DefaultGunshiParams> = (ctx: CommandContextCore<G>, cmd: Command<G>) => Awaitable<T>;
282
+ /**
283
+ * Plugin extension callback type
284
+ * @since v0.27.0
285
+ */
286
+ type OnPluginExtension<G extends GunshiParams = DefaultGunshiParams> = (ctx: Readonly<CommandContext<G>>, cmd: Readonly<Command<G>>) => Awaitable<void>;
287
+ /**
288
+ * Plugin definition options
289
+ * @since v0.27.0
290
+ */
291
+ interface PluginOptions<T extends Record<string, unknown> = Record<never, never>, G extends GunshiParams = DefaultGunshiParams> {
292
+ /**
293
+ * Plugin unique identifier
294
+ */
295
+ id: string;
296
+ /**
297
+ * Plugin name
298
+ */
299
+ name?: string;
300
+ /**
301
+ * Plugin dependencies
302
+ */
303
+ dependencies?: (PluginDependency | string)[];
304
+ /**
305
+ * Plugin setup function
306
+ */
307
+ setup?: PluginFunction<G>;
308
+ /**
309
+ * Plugin extension
310
+ */
311
+ extension?: PluginExtension<T, G>;
312
+ /**
313
+ * Callback for when the plugin is extended with `extension` option.
314
+ */
315
+ onExtension?: OnPluginExtension<G>;
316
+ }
148
317
  /**
149
- * An arguments for {@link resolveArgs | resolve arguments}.
150
- */
318
+ * Gunshi plugin, which is a function that receives a PluginContext.
319
+ * @param ctx - A {@link PluginContext}.
320
+ * @returns An {@link Awaitable} that resolves when the plugin is loaded.
321
+ * @since v0.27.0
322
+ */
323
+ type Plugin<E extends GunshiParams['extensions'] = DefaultGunshiParams['extensions']> = PluginFunction & {
324
+ id: string;
325
+ name?: string;
326
+ dependencies?: (PluginDependency | string)[];
327
+ extension?: CommandContextExtension<E>;
328
+ };
329
+ /**
330
+ * Plugin return type with extension
331
+ * @internal
332
+ */
333
+ interface PluginWithExtension<E extends GunshiParams['extensions'] = DefaultGunshiParams['extensions']> extends Plugin<E> {
334
+ id: string;
335
+ name: string;
336
+ dependencies?: (PluginDependency | string)[];
337
+ extension: CommandContextExtension<E>;
338
+ }
339
+ /**
340
+ * Plugin return type without extension
341
+ * @internal
342
+ */
343
+ interface PluginWithoutExtension<E extends GunshiParams['extensions'] = DefaultGunshiParams['extensions']> extends Plugin<E> {
344
+ id: string;
345
+ name: string;
346
+ dependencies?: (PluginDependency | string)[];
347
+ }
348
+ /**
349
+ * Define a plugin with extension capabilities
350
+ * @param options - {@link PluginOptions | plugin options}
351
+ * @return A defined plugin with extension capabilities.
352
+ * @since v0.27.0
353
+ */
354
+ declare function plugin<I extends string, P extends PluginExtension<any, DefaultGunshiParams>>(options: {
355
+ id: I;
356
+ name?: string;
357
+ dependencies?: (PluginDependency | string)[];
358
+ setup?: (ctx: Readonly<PluginContext<GunshiParams<{
359
+ args: Args;
360
+ extensions: { [K in I]: Awaited<ReturnType<P>> };
361
+ }>>>) => Awaitable<void>;
362
+ extension: P;
363
+ onExtension?: OnPluginExtension<{
364
+ args: Args;
365
+ extensions: { [K in I]: Awaited<ReturnType<P>> };
366
+ }>;
367
+ }): PluginWithExtension<Awaited<ReturnType<P>>>;
368
+ /**
369
+ * Define a plugin without extension capabilities
370
+ * @param options - {@link PluginOptions | plugin options} without extension
371
+ * @returns A defined plugin without extension capabilities.
372
+ * @since v0.27.0
373
+ */
374
+ declare function plugin(options: {
375
+ id: string;
376
+ name?: string;
377
+ dependencies?: (PluginDependency | string)[];
378
+ setup?: (ctx: Readonly<PluginContext<DefaultGunshiParams>>) => Awaitable<void>;
379
+ onExtension?: OnPluginExtension<DefaultGunshiParams>;
380
+ }): PluginWithoutExtension<DefaultGunshiParams['extensions']>;
381
+ //#endregion
382
+ //#region ../gunshi/src/types.d.ts
151
383
  type Awaitable<T> = T | Promise<T>;
152
384
  /**
153
385
  * Extend command context type. This type is used to extend the command context with additional properties at {@link CommandContext.extensions}.
386
+ * @since v0.27.0
154
387
  */
155
388
  type ExtendContext = Record<string, unknown>;
156
389
  /**
157
390
  * Gunshi unified parameter type.
158
391
  * This type combines both argument definitions and command context extensions.
392
+ * @since v0.27.0
159
393
  */
160
394
  interface GunshiParams<P extends {
161
395
  args?: Args;
@@ -179,11 +413,13 @@ interface GunshiParams<P extends {
179
413
  }
180
414
  /**
181
415
  * Default Gunshi parameters
416
+ * @since v0.27.0
182
417
  */
183
418
  type DefaultGunshiParams = GunshiParams;
184
419
  /**
185
420
  * Generic constraint for command-related types.
186
421
  * This type constraint allows both GunshiParams and objects with extensions.
422
+ * @since v0.27.0
187
423
  */
188
424
  type GunshiParamsConstraint = GunshiParams<any> | {
189
425
  extensions: ExtendContext;
@@ -193,11 +429,16 @@ type GunshiParamsConstraint = GunshiParams<any> | {
193
429
  * @internal
194
430
  */
195
431
  type ExtractArgs<G> = G extends GunshiParams<any> ? G['args'] : Args;
432
+ /**
433
+ * Type helper to extract explicitly provided argument flags from G
434
+ * @internal
435
+ */
436
+ type ExtractArgExplicitlyProvided<G> = ArgExplicitlyProvided<ExtractArgs<G>>;
196
437
  /**
197
438
  * Type helper to extract extensions from G
198
439
  * @internal
199
440
  */
200
- type ExtractExtensions<G> = G extends GunshiParams<any> ? G['extensions'] : G extends {
441
+ type ExtractExtensions$1<G> = G extends GunshiParams<any> ? G['extensions'] : G extends {
201
442
  extensions: infer E;
202
443
  } ? E : {};
203
444
  /**
@@ -285,23 +526,105 @@ interface CommandEnvironment<G extends GunshiParamsConstraint = DefaultGunshiPar
285
526
  /**
286
527
  * Hook that runs before any command execution
287
528
  * @see {@link CliOptions.onBeforeCommand}
529
+ * @since v0.27.0
288
530
  */
289
531
  onBeforeCommand: ((ctx: Readonly<CommandContext<G>>) => Awaitable<void>) | undefined;
290
532
  /**
291
533
  * Hook that runs after successful command execution
292
534
  * @see {@link CliOptions.onAfterCommand}
535
+ * @since v0.27.0
293
536
  */
294
- onAfterCommand: ((ctx: Readonly<CommandContext<G>>, result: string | void) => Awaitable<void>) | undefined;
537
+ onAfterCommand: ((ctx: Readonly<CommandContext<G>>, result: string | undefined) => Awaitable<void>) | undefined;
295
538
  /**
296
539
  * Hook that runs when a command throws an error
297
540
  * @see {@link CliOptions.onErrorCommand}
541
+ * @since v0.27.0
298
542
  */
299
543
  onErrorCommand: ((ctx: Readonly<CommandContext<G>>, error: Error) => Awaitable<void>) | undefined;
300
544
  }
301
545
  /**
302
546
  * CLI options of `cli` function.
303
547
  */
304
-
548
+ interface CliOptions<G extends GunshiParamsConstraint = DefaultGunshiParams> {
549
+ /**
550
+ * Current working directory.
551
+ */
552
+ cwd?: string;
553
+ /**
554
+ * Command program name.
555
+ */
556
+ name?: string;
557
+ /**
558
+ * Command program description.
559
+ *
560
+ */
561
+ description?: string;
562
+ /**
563
+ * Command program version.
564
+ */
565
+ version?: string;
566
+ /**
567
+ * Sub commands.
568
+ */
569
+ subCommands?: Map<string, Command<any> | LazyCommand<any>>;
570
+ /**
571
+ * Left margin of the command output.
572
+ */
573
+ leftMargin?: number;
574
+ /**
575
+ * Middle margin of the command output.
576
+ */
577
+ middleMargin?: number;
578
+ /**
579
+ * Whether to display the usage optional argument type.
580
+ */
581
+ usageOptionType?: boolean;
582
+ /**
583
+ * Whether to display the optional argument value.
584
+ */
585
+ usageOptionValue?: boolean;
586
+ /**
587
+ * Whether to display the command usage.
588
+ */
589
+ usageSilent?: boolean;
590
+ /**
591
+ * Render function the command usage.
592
+ */
593
+ renderUsage?: ((ctx: Readonly<CommandContext<G>>) => Promise<string>) | null;
594
+ /**
595
+ * Render function the header section in the command usage.
596
+ */
597
+ renderHeader?: ((ctx: Readonly<CommandContext<G>>) => Promise<string>) | null;
598
+ /**
599
+ * Render function the validation errors.
600
+ */
601
+ renderValidationErrors?: ((ctx: Readonly<CommandContext<G>>, error: AggregateError) => Promise<string>) | null;
602
+ /**
603
+ * User plugins.
604
+ * @since v0.27.0
605
+ */
606
+ plugins?: Plugin[];
607
+ /**
608
+ * Hook that runs before any command execution
609
+ * @param ctx - The command context
610
+ * @since v0.27.0
611
+ */
612
+ onBeforeCommand?: (ctx: Readonly<CommandContext<G>>) => Awaitable<void>;
613
+ /**
614
+ * Hook that runs after successful command execution
615
+ * @param ctx - The command context
616
+ * @param result - The command execution result
617
+ * @since v0.27.0
618
+ */
619
+ onAfterCommand?: (ctx: Readonly<CommandContext<G>>, result: string | undefined) => Awaitable<void>;
620
+ /**
621
+ * Hook that runs when a command throws an error
622
+ * @param ctx - The command context
623
+ * @param error - The error thrown during execution
624
+ * @since v0.27.0
625
+ */
626
+ onErrorCommand?: (ctx: Readonly<CommandContext<G>>, error: Error) => Awaitable<void>;
627
+ }
305
628
  /**
306
629
  * Command call mode.
307
630
  */
@@ -331,6 +654,15 @@ interface CommandContext<G extends GunshiParamsConstraint = DefaultGunshiParams>
331
654
  * The command arguments is same {@link Command.args}.
332
655
  */
333
656
  args: ExtractArgs<G>;
657
+ /**
658
+ * Whether arguments were explicitly provided by the user.
659
+ *
660
+ * - `true`: The argument was explicitly provided via command line
661
+ * - `false`: The argument was not explicitly provided. This means either:
662
+ * - The value comes from a default value defined in the argument schema
663
+ * - The value is `undefined` (no explicit input and no default value)
664
+ */
665
+ explicit: ExtractArgExplicitlyProvided<G>;
334
666
  /**
335
667
  * Command values, that is the values of the command that is executed.
336
668
  * Resolve values with `resolveArgs` from command arguments and {@link Command.args}.
@@ -377,9 +709,10 @@ interface CommandContext<G extends GunshiParamsConstraint = DefaultGunshiParams>
377
709
  */
378
710
  log: (message?: any, ...optionalParams: any[]) => void;
379
711
  /**
380
- * Command context extensions.
712
+ * Command context extensions.
713
+ * @since v0.27.0
381
714
  */
382
- extensions: keyof ExtractExtensions<G> extends never ? undefined : ExtractExtensions<G>;
715
+ extensions: keyof ExtractExtensions$1<G> extends never ? undefined : ExtractExtensions$1<G>;
383
716
  /**
384
717
  * Validation error from argument parsing.
385
718
  * This will be set if argument validation fails during CLI execution.
@@ -388,16 +721,45 @@ interface CommandContext<G extends GunshiParamsConstraint = DefaultGunshiParams>
388
721
  }
389
722
  /**
390
723
  * CommandContextCore type (base type without extensions)
724
+ * @since v0.27.0
391
725
  */
392
726
  type CommandContextCore<G extends GunshiParamsConstraint = DefaultGunshiParams> = Readonly<CommandContext<G>>;
393
727
  /**
394
728
  * Command context extension
729
+ * @since v0.27.0
395
730
  */
396
731
  interface CommandContextExtension<E extends GunshiParams['extensions'] = DefaultGunshiParams['extensions']> {
397
732
  readonly key: symbol;
398
733
  readonly factory: (ctx: CommandContextCore, cmd: Command) => Awaitable<E>;
399
734
  readonly onFactory?: (ctx: Readonly<CommandContext>, cmd: Readonly<Command>) => Awaitable<void>;
400
735
  }
736
+ /**
737
+ * Rendering control options
738
+ * @since v0.27.0
739
+ */
740
+ interface RenderingOptions<G extends GunshiParamsConstraint = DefaultGunshiParams> {
741
+ /**
742
+ * Header rendering configuration
743
+ * - `null`: Disable rendering
744
+ * - `function`: Use custom renderer
745
+ * - `undefined` (when omitted): Use default renderer
746
+ */
747
+ header?: ((ctx: Readonly<CommandContext<G>>) => Promise<string>) | null;
748
+ /**
749
+ * Usage rendering configuration
750
+ * - `null`: Disable rendering
751
+ * - `function`: Use custom renderer
752
+ * - `undefined` (when omitted): Use default renderer
753
+ */
754
+ usage?: ((ctx: Readonly<CommandContext<G>>) => Promise<string>) | null;
755
+ /**
756
+ * Validation errors rendering configuration
757
+ * - `null`: Disable rendering
758
+ * - `function`: Use custom renderer
759
+ * - `undefined` (when omitted): Use default renderer
760
+ */
761
+ validationErrors?: ((ctx: Readonly<CommandContext<G>>, error: AggregateError) => Promise<string>) | null;
762
+ }
401
763
  /**
402
764
  * Command interface.
403
765
  */
@@ -431,6 +793,24 @@ interface Command<G extends GunshiParamsConstraint = DefaultGunshiParams> {
431
793
  * If you will set to `true`, All {@link Command.args} names will be converted to kebab-case.
432
794
  */
433
795
  toKebab?: boolean;
796
+ /**
797
+ * Whether this is an internal command.
798
+ * Internal commands are not shown in help usage.
799
+ * @default false
800
+ * @since v0.27.0
801
+ */
802
+ internal?: boolean;
803
+ /**
804
+ * Whether this command is an entry command.
805
+ * @default undefined
806
+ * @since v0.27.0
807
+ */
808
+ entry?: boolean;
809
+ /**
810
+ * Rendering control options
811
+ * @since v0.27.0
812
+ */
813
+ rendering?: RenderingOptions<G>;
434
814
  }
435
815
  /**
436
816
  * Lazy command interface.
@@ -461,7 +841,7 @@ type CommandExamplesFetcher<G extends GunshiParamsConstraint = DefaultGunshiPara
461
841
  * @param ctx A {@link CommandContext | command context}
462
842
  * @returns void or string (for CLI output)
463
843
  */
464
- type CommandRunner<G extends GunshiParamsConstraint = DefaultGunshiParams> = (ctx: Readonly<CommandContext<G>>) => Awaitable<void | string>;
844
+ type CommandRunner<G extends GunshiParamsConstraint = DefaultGunshiParams> = (ctx: Readonly<CommandContext<G>>) => Awaitable<string | void>;
465
845
  /**
466
846
  * Command loader.
467
847
  * A function that returns a command or command runner.
@@ -474,14 +854,16 @@ type CommandRunner<G extends GunshiParamsConstraint = DefaultGunshiParams> = (ct
474
854
  * A function that wraps a command runner to add or modify its behavior.
475
855
  * @param baseRunner The base command runner to decorate
476
856
  * @returns The decorated command runner
857
+ * @since v0.27.0
477
858
  */
478
- type CommandDecorator<G extends GunshiParamsConstraint = DefaultGunshiParams> = (baseRunner: (ctx: Readonly<CommandContext<G>>) => Awaitable<void | string>) => (ctx: Readonly<CommandContext<G>>) => Awaitable<void | string>;
859
+ type CommandDecorator<G extends GunshiParamsConstraint = DefaultGunshiParams> = (baseRunner: (ctx: Readonly<CommandContext<G>>) => Awaitable<string | void>) => (ctx: Readonly<CommandContext<G>>) => Awaitable<string | void>;
479
860
  /**
480
861
  * Renderer decorator type.
481
862
  * A function that wraps a base renderer to add or modify its behavior.
482
863
  * @param baseRenderer The base renderer function to decorate
483
864
  * @param ctx The command context
484
865
  * @returns The decorated result
866
+ * @since v0.27.0
485
867
  */
486
868
  type RendererDecorator<T, G extends GunshiParamsConstraint = DefaultGunshiParams> = (baseRenderer: (ctx: Readonly<CommandContext<G>>) => Promise<T>, ctx: Readonly<CommandContext<G>>) => Promise<T>;
487
869
  /**
@@ -491,177 +873,101 @@ type RendererDecorator<T, G extends GunshiParamsConstraint = DefaultGunshiParams
491
873
  * @param ctx The command context
492
874
  * @param error The aggregate error containing validation errors
493
875
  * @returns The decorated result
876
+ * @since v0.27.0
494
877
  */
495
- type ValidationErrorsDecorator<G extends GunshiParamsConstraint = DefaultGunshiParams> = (baseRenderer: (ctx: Readonly<CommandContext<G>>, error: AggregateError) => Promise<string>, ctx: Readonly<CommandContext<G>>, error: AggregateError) => Promise<string>; //#endregion
496
- //#region ../gunshi/src/plugin/context.d.ts
878
+ type ValidationErrorsDecorator<G extends GunshiParamsConstraint = DefaultGunshiParams> = (baseRenderer: (ctx: Readonly<CommandContext<G>>, error: AggregateError) => Promise<string>, ctx: Readonly<CommandContext<G>>, error: AggregateError) => Promise<string>;
879
+ //#endregion
880
+ //#region ../gunshi/src/constants.d.ts
881
+ declare const ANONYMOUS_COMMAND_NAME = "(anonymous)";
882
+ declare const CLI_OPTIONS_DEFAULT: CliOptions<DefaultGunshiParams>;
883
+ //#endregion
884
+ //#region ../gunshi/src/context.d.ts
497
885
  /**
498
- * Type helper to create GunshiParams from extracted args and extensions
886
+ * Extract extension return types from extensions record
499
887
  * @internal
500
888
  */
501
- type ExtractedParams<G extends GunshiParamsConstraint, L extends Record<string, unknown> = {}> = {
502
- args: ExtractArgs<G>;
503
- extensions: ExtractExtensions<G> & L;
504
- };
889
+ type ExtractExtensions<E extends Record<string, CommandContextExtension>> = { [K in keyof E]: E[K] extends CommandContextExtension<infer T> ? T : never };
505
890
  /**
506
- * Gunshi plugin context interface.
891
+ * Parameters of {@link createCommandContext}
507
892
  */
508
- interface PluginContext<G extends GunshiParamsConstraint = DefaultGunshiParams> {
509
- /**
510
- * Get the global options
511
- * @returns A map of global options.
512
- */
513
- readonly globalOptions: Map<string, ArgSchema>;
893
+ interface CommandContextParams<G extends GunshiParams | {
894
+ extensions: ExtendContext;
895
+ }, V extends ArgValues<ExtractArgs<G>>, C extends Command<G> | LazyCommand<G> = Command<G>, E extends Record<string, CommandContextExtension> = Record<string, CommandContextExtension>> {
514
896
  /**
515
- * Add a global option.
516
- * @param name An option name
517
- * @param schema An {@link ArgSchema} for the option
897
+ * An arguments of target command
518
898
  */
519
- addGlobalOption(name: string, schema: ArgSchema): void;
899
+ args: ExtractArgs<G>;
520
900
  /**
521
- * Decorate the header renderer.
522
- * @param decorator - A decorator function that wraps the base header renderer.
901
+ * Explicitly provided arguments
523
902
  */
524
- 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;
903
+ explicit: ExtractArgExplicitlyProvided<G>;
525
904
  /**
526
- * Decorate the usage renderer.
527
- * @param decorator - A decorator function that wraps the base usage renderer.
905
+ * A values of target command
528
906
  */
529
- 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;
907
+ values: V;
530
908
  /**
531
- * Decorate the validation errors renderer.
532
- * @param decorator - A decorator function that wraps the base validation errors renderer.
909
+ * A positionals arguments, which passed to the target command
533
910
  */
534
- 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;
911
+ positionals: string[];
535
912
  /**
536
- * Decorate the command execution.
537
- * Decorators are applied in reverse order (last registered is executed first).
538
- * @param decorator - A decorator function that wraps the command runner
913
+ * A rest arguments, which passed to the target command
539
914
  */
540
- 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;
541
- }
542
-
543
- //#endregion
544
- //#region ../gunshi/src/plugin/core.d.ts
545
- /**
546
- * Factory function for creating a plugin context.
547
- * @param decorators - A {@link Decorators} instance.
548
- * @returns A new {@link PluginContext} instance.
549
- */
550
- /**
551
- * Plugin dependency definition
552
- */
553
- interface PluginDependency {
915
+ rest: string[];
554
916
  /**
555
- * Dependency plugin id
917
+ * Original command line arguments
556
918
  */
557
- id: string;
919
+ argv: string[];
558
920
  /**
559
- * Optional dependency flag.
560
- * If true, the plugin will not throw an error if the dependency is not found.
921
+ * Argument tokens that are parsed by the `parseArgs` function
561
922
  */
562
- optional?: boolean;
563
- }
564
- /**
565
- * Plugin function type
566
- */
567
- type PluginFunction<G extends GunshiParams = DefaultGunshiParams> = (ctx: Readonly<PluginContext<G>>) => Awaitable<void>;
568
- /**
569
- * Plugin extension for CommandContext
570
- */
571
- type PluginExtension<T = Record<string, unknown>, G extends GunshiParams = DefaultGunshiParams> = (ctx: CommandContextCore<G>, cmd: Command<G>) => T;
572
- /**
573
- * Plugin extension callback type
574
- */
575
- type OnPluginExtension<G extends GunshiParams = DefaultGunshiParams> = (ctx: Readonly<CommandContext<G>>, cmd: Readonly<Command<G>>) => void;
576
- /**
577
- * Plugin definition options
578
- */
579
- interface PluginOptions<T extends Record<string, unknown> = Record<never, never>, G extends GunshiParams = DefaultGunshiParams> {
923
+ tokens: ArgToken[];
580
924
  /**
581
- * Plugin unique identifier
925
+ * Whether the command is omitted
582
926
  */
583
- id: string;
927
+ omitted: boolean;
584
928
  /**
585
- * Plugin name
929
+ * Command call mode.
586
930
  */
587
- name?: string;
931
+ callMode: CommandCallMode;
588
932
  /**
589
- * Plugin dependencies
933
+ * A target command
590
934
  */
591
- dependencies?: (PluginDependency | string)[];
935
+ command: C;
592
936
  /**
593
- * Plugin setup function
937
+ * Plugin extensions to apply as the command context extension.
594
938
  */
595
- setup?: PluginFunction<G>;
939
+ extensions?: E;
596
940
  /**
597
- * Plugin extension
941
+ * A command options, which is spicialized from `cli` function
598
942
  */
599
- extension?: PluginExtension<T, G>;
943
+ cliOptions: CliOptions<G>;
600
944
  /**
601
- * Callback for when the plugin is extended with `extension` option.
945
+ * Validation error from argument parsing.
602
946
  */
603
- onExtension?: OnPluginExtension<G>;
604
- }
605
- /**
606
- * Gunshi plugin, which is a function that receives a PluginContext.
607
- * @param ctx - A {@link PluginContext}.
608
- * @returns An {@link Awaitable} that resolves when the plugin is loaded.
609
- */
610
- type Plugin<E extends GunshiParams['extensions'] = DefaultGunshiParams['extensions']> = PluginFunction & {
611
- id: string;
612
- name?: string;
613
- dependencies?: (PluginDependency | string)[];
614
- extension?: CommandContextExtension<E>;
615
- };
616
- /**
617
- * Plugin return type with extension
618
- * @internal
619
- */
620
- interface PluginWithExtension<E extends GunshiParams['extensions'] = DefaultGunshiParams['extensions']> extends Plugin<E> {
621
- id: string;
622
- name: string;
623
- dependencies?: (PluginDependency | string)[];
624
- extension: CommandContextExtension<E>;
625
- }
626
- /**
627
- * Plugin return type without extension
628
- * @internal
629
- */
630
- interface PluginWithoutExtension<E extends GunshiParams['extensions'] = DefaultGunshiParams['extensions']> extends Plugin<E> {
631
- id: string;
632
- name: string;
633
- dependencies?: (PluginDependency | string)[];
947
+ validationError?: AggregateError;
634
948
  }
635
949
  /**
636
- * Define a plugin with extension capabilities
637
- * @param options - {@link PluginOptions | plugin options}
638
- * @return A defined plugin with extension capabilities.
639
- */
640
- declare function plugin<I extends string, P extends PluginExtension<any, DefaultGunshiParams>>(options: {
641
- id: I;
642
- name?: string;
643
- dependencies?: (PluginDependency | string)[];
644
- setup?: (ctx: Readonly<PluginContext<GunshiParams<{
645
- args: Args;
646
- extensions: { [K in I]: ReturnType<P> };
647
- }>>>) => Awaitable<void>;
648
- extension: P;
649
- onExtension?: OnPluginExtension<{
650
- args: Args;
651
- extensions: { [K in I]: ReturnType<P> };
652
- }>;
653
- }): PluginWithExtension<ReturnType<P>>;
654
- /**
655
- * Define a plugin without extension capabilities
656
- * @param options - {@link PluginOptions | plugin options} without extension
657
- * @returns A defined plugin without extension capabilities.
658
- */
659
- declare function plugin(options: {
660
- id: string;
661
- name?: string;
662
- dependencies?: (PluginDependency | string)[];
663
- setup?: (ctx: Readonly<PluginContext<DefaultGunshiParams>>) => Awaitable<void>;
664
- }): PluginWithoutExtension<DefaultGunshiParams['extensions']>;
665
-
950
+ * Create a {@link CommandContext | command context}
951
+ * @param param A {@link CommandContextParams | parameters} to create a {@link CommandContext | command context}
952
+ * @returns A {@link CommandContext | command context}, which is readonly
953
+ */
954
+ 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> = {}>({
955
+ args,
956
+ explicit,
957
+ values,
958
+ positionals,
959
+ rest,
960
+ argv,
961
+ tokens,
962
+ command,
963
+ extensions,
964
+ cliOptions,
965
+ callMode,
966
+ omitted,
967
+ validationError
968
+ }: CommandContextParams<G, V, C, E>): Promise<{} extends ExtractExtensions<E> ? Readonly<CommandContext<G>> : Readonly<CommandContext<GunshiParams<{
969
+ args: ExtractArgs<G>;
970
+ extensions: ExtractExtensions<E>;
971
+ }>>>>;
666
972
  //#endregion
667
- export { ArgSchema, ArgToken, ArgValues, Args, Awaitable, Command, CommandContext, CommandContextCore, CommandDecorator, CommandExamplesFetcher, CommandRunner, DefaultGunshiParams, ExtendContext, ExtractArgs, GunshiParams, GunshiParamsConstraint, LazyCommand, NormalizeToGunshiParams, OnPluginExtension, Plugin, PluginContext, PluginDependency, PluginExtension, PluginFunction, PluginOptions, PluginWithExtension, PluginWithoutExtension, RendererDecorator, ValidationErrorsDecorator, plugin };
973
+ export { ANONYMOUS_COMMAND_NAME, type ArgSchema, type ArgToken, type ArgValues, type Args, Awaitable, CLI_OPTIONS_DEFAULT, Command, CommandContext, CommandContextCore, CommandContextExtension, CommandDecorator, CommandExamplesFetcher, CommandRunner, DefaultGunshiParams, ExtendContext, ExtractArgs, GunshiParams, GunshiParamsConstraint, LazyCommand, NormalizeToGunshiParams, OnPluginExtension, Plugin, PluginContext, PluginDependency, PluginExtension, PluginFunction, PluginOptions, PluginWithExtension, PluginWithoutExtension, RendererDecorator, ValidationErrorsDecorator, createCommandContext, plugin };
package/lib/index.js CHANGED
@@ -1,11 +1,131 @@
1
+ //#region ../gunshi/src/constants.ts
2
+ const ANONYMOUS_COMMAND_NAME = "(anonymous)";
3
+ const NOOP = () => {};
4
+ const CLI_OPTIONS_DEFAULT = {
5
+ name: void 0,
6
+ description: void 0,
7
+ version: void 0,
8
+ cwd: void 0,
9
+ usageSilent: false,
10
+ subCommands: void 0,
11
+ leftMargin: 2,
12
+ middleMargin: 10,
13
+ usageOptionType: false,
14
+ usageOptionValue: true,
15
+ renderHeader: void 0,
16
+ renderUsage: void 0,
17
+ renderValidationErrors: void 0,
18
+ plugins: void 0
19
+ };
20
+
21
+ //#endregion
22
+ //#region ../gunshi/src/utils.ts
23
+ function isLazyCommand(cmd) {
24
+ return typeof cmd === "function" && "commandName" in cmd && !!cmd.commandName;
25
+ }
26
+ function create(obj = null) {
27
+ return Object.create(obj);
28
+ }
29
+ function log(...args) {
30
+ console.log(...args);
31
+ }
32
+ function deepFreeze(obj, ignores = []) {
33
+ if (obj === null || typeof obj !== "object") return obj;
34
+ for (const key of Object.keys(obj)) {
35
+ const value = obj[key];
36
+ if (ignores.includes(key)) continue;
37
+ if (typeof value === "object" && value !== null) deepFreeze(value, ignores);
38
+ }
39
+ return Object.freeze(obj);
40
+ }
41
+
42
+ //#endregion
43
+ //#region ../gunshi/src/context.ts
44
+ /**
45
+ * Create a {@link CommandContext | command context}
46
+ * @param param A {@link CommandContextParams | parameters} to create a {@link CommandContext | command context}
47
+ * @returns A {@link CommandContext | command context}, which is readonly
48
+ */
49
+ async function createCommandContext({ args, explicit, values, positionals, rest, argv, tokens, command, extensions = {}, cliOptions, callMode = "entry", omitted = false, validationError }) {
50
+ /**
51
+ * normailize the options schema and values, to avoid prototype pollution
52
+ */
53
+ const _args = Object.entries(args).reduce((acc, [key, value]) => {
54
+ acc[key] = Object.assign(create(), value);
55
+ return acc;
56
+ }, create());
57
+ /**
58
+ * setup the environment
59
+ */
60
+ const env = Object.assign(create(), CLI_OPTIONS_DEFAULT, cliOptions);
61
+ /**
62
+ * apply Command definition's rendering option with highest priority
63
+ */
64
+ if (command.rendering) {
65
+ const { header, usage, validationErrors } = command.rendering;
66
+ if (header !== void 0) env.renderHeader = header;
67
+ if (usage !== void 0) env.renderUsage = usage;
68
+ if (validationErrors !== void 0) env.renderValidationErrors = validationErrors;
69
+ }
70
+ /**
71
+ * create the command context
72
+ */
73
+ const core = Object.assign(create(), {
74
+ name: getCommandName(command),
75
+ description: command.description,
76
+ omitted,
77
+ callMode,
78
+ env,
79
+ args: _args,
80
+ explicit,
81
+ values,
82
+ positionals,
83
+ rest,
84
+ _: argv,
85
+ tokens,
86
+ toKebab: command.toKebab,
87
+ log: cliOptions.usageSilent ? NOOP : log,
88
+ validationError
89
+ });
90
+ /**
91
+ * extend the command context with extensions
92
+ */
93
+ if (Object.keys(extensions).length > 0) {
94
+ const ext = create(null);
95
+ Object.defineProperty(core, "extensions", {
96
+ value: ext,
97
+ writable: false,
98
+ enumerable: true,
99
+ configurable: true
100
+ });
101
+ for (const [key, extension] of Object.entries(extensions)) {
102
+ ext[key] = await extension.factory(core, command);
103
+ if (extension.onFactory) await extension.onFactory(core, command);
104
+ }
105
+ }
106
+ const ctx = deepFreeze(core, ["extensions"]);
107
+ return ctx;
108
+ }
109
+ function getCommandName(cmd) {
110
+ if (isLazyCommand(cmd)) return cmd.commandName || cmd.name || ANONYMOUS_COMMAND_NAME;
111
+ else if (typeof cmd === "object") return cmd.name || ANONYMOUS_COMMAND_NAME;
112
+ else return ANONYMOUS_COMMAND_NAME;
113
+ }
114
+
115
+ //#endregion
1
116
  //#region ../gunshi/src/plugin/core.ts
117
+ const NOOP_EXTENSION = () => {
118
+ return Object.create(null);
119
+ };
2
120
  /**
3
121
  * Define a plugin
4
122
  * @param options - {@link PluginOptions | plugin options}
5
123
  * @returns A defined plugin.
124
+ * @since v0.27.0
6
125
  */
7
126
  function plugin(options) {
8
- const { id, name, setup, extension, onExtension, dependencies } = options;
127
+ const { id, name, setup, onExtension, dependencies } = options;
128
+ const extension = options.extension || NOOP_EXTENSION;
9
129
  const pluginFn = async (ctx) => {
10
130
  if (setup) await setup(ctx);
11
131
  };
@@ -42,4 +162,4 @@ function plugin(options) {
42
162
  }
43
163
 
44
164
  //#endregion
45
- export { plugin };
165
+ export { ANONYMOUS_COMMAND_NAME, CLI_OPTIONS_DEFAULT, createCommandContext, plugin };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gunshi/plugin",
3
3
  "description": "utilities for gunshi plugin",
4
- "version": "0.26.3",
4
+ "version": "0.27.0-alpha.10",
5
5
  "author": {
6
6
  "name": "kazuya kawaguchi",
7
7
  "email": "kawakazu80@gmail.com"
@@ -51,12 +51,12 @@
51
51
  }
52
52
  },
53
53
  "devDependencies": {
54
- "deno": "^2.3.3",
55
- "jsr": "^0.13.4",
54
+ "deno": "^2.4.2",
55
+ "jsr": "^0.13.5",
56
56
  "jsr-exports-lint": "^0.4.1",
57
57
  "publint": "^0.3.12",
58
- "tsdown": "^0.12.3",
59
- "gunshi": "0.26.3"
58
+ "tsdown": "^0.13.0",
59
+ "gunshi": "0.27.0-alpha.10"
60
60
  },
61
61
  "scripts": {
62
62
  "build": "tsdown",