@guanghechen/commander 4.7.0 → 4.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/esm/node.mjs CHANGED
@@ -1415,7 +1415,7 @@ class Command {
1415
1415
  return this.#options.some(option => option.long === long);
1416
1416
  }
1417
1417
  #supportsBuiltinVersion() {
1418
- return this.#parent === undefined && this.#version !== undefined && this.#builtin.option.version;
1418
+ return this.#version !== undefined && this.#builtin.option.version;
1419
1419
  }
1420
1420
  #resolveOptionPolicy() {
1421
1421
  const optionMap = new Map();
@@ -93,7 +93,7 @@ interface ICommandArgumentConfig<T = unknown> {
93
93
  coerce?: (rawValue: string) => T;
94
94
  }
95
95
  interface ICommandBuiltinOptionConfig {
96
- /** Enable built-in --version option (root only, requires configured version) */
96
+ /** Enable built-in --version option (requires configured version on target command) */
97
97
  version?: boolean;
98
98
  /** Enable built-in --color/--no-color option for help rendering (defaults respect NO_COLOR) */
99
99
  color?: boolean;
@@ -0,0 +1,384 @@
1
+ import { IReporter } from '@guanghechen/reporter';
2
+
3
+ /**
4
+ * Type definitions for @guanghechen/commander
5
+ *
6
+ * @module @guanghechen/commander
7
+ */
8
+
9
+ /** Token type: long option, short option, or positional */
10
+ type ICommandTokenType = 'long' | 'short' | 'none';
11
+ /**
12
+ * Command token after preprocessing.
13
+ *
14
+ * - original: raw input for error messages (e.g., --LOG-LEVEL=info, -v)
15
+ * - resolved: normalized form (e.g., --logLevel=info, -v)
16
+ * - name: option name for matching (e.g., logLevel, v, '')
17
+ * - type: token type (long/short/none)
18
+ */
19
+ interface ICommandToken {
20
+ /** Raw input, used for error display */
21
+ original: string;
22
+ /** Normalized form, used for parsing */
23
+ resolved: string;
24
+ /** Option name for matching: camelCase for long, single char for short, '' for positional */
25
+ name: string;
26
+ /** Token type */
27
+ type: ICommandTokenType;
28
+ }
29
+ /** Option value type */
30
+ type ICommandOptionType = 'boolean' | 'number' | 'string';
31
+ /** Option argument mode */
32
+ type ICommandOptionArgs = 'none' | 'required' | 'variadic';
33
+ /**
34
+ * Option configuration.
35
+ *
36
+ * `type` and `args` must be specified together. Valid combinations:
37
+ * - boolean + none → boolean
38
+ * - string + required → string
39
+ * - number + required → number
40
+ * - string + variadic → string[]
41
+ * - number + variadic → number[]
42
+ *
43
+ * @template T - The type of the option value
44
+ */
45
+ interface ICommandOptionConfig<T = unknown> {
46
+ /** Long option name (camelCase, required) */
47
+ long: string;
48
+ /** Short option (single character) */
49
+ short?: string;
50
+ /** Value type (required) */
51
+ type: ICommandOptionType;
52
+ /** Argument mode (required) */
53
+ args: ICommandOptionArgs;
54
+ /** Description for help text */
55
+ desc: string;
56
+ /** Whether this option is required (mutually exclusive with default) */
57
+ required?: boolean;
58
+ /** Default value when not provided */
59
+ default?: T;
60
+ /** Allowed values for validation and completion */
61
+ choices?: T extends Array<infer U> ? U[] : T[];
62
+ /** Single value transformation (called for each value, before choices validation) */
63
+ coerce?: (rawValue: string) => T extends Array<infer U> ? U : T;
64
+ /** Callback after parsing, applies value to context */
65
+ apply?: (value: T, ctx: ICommandContext) => void;
66
+ }
67
+ /** Argument kind */
68
+ type ICommandArgumentKind = 'required' | 'optional' | 'variadic';
69
+ /** Argument value type */
70
+ type ICommandArgumentType = 'string' | 'number';
71
+ /**
72
+ * Positional argument configuration.
73
+ *
74
+ * Constraints:
75
+ * - required arguments must come before optional
76
+ * - variadic can only appear once, and must be last
77
+ * - required cannot have default
78
+ *
79
+ * @template T - The type of the argument value
80
+ */
81
+ interface ICommandArgumentConfig<T = unknown> {
82
+ /** Argument name */
83
+ name: string;
84
+ /** Argument description */
85
+ desc: string;
86
+ /** Argument kind: required / optional / variadic */
87
+ kind: ICommandArgumentKind;
88
+ /** Value type, defaults to 'string' */
89
+ type?: ICommandArgumentType;
90
+ /** Default value when not provided (only for optional arguments) */
91
+ default?: T;
92
+ /** Custom value transformation (takes precedence over type conversion) */
93
+ coerce?: (rawValue: string) => T;
94
+ }
95
+ /** Command configuration */
96
+ interface ICommandConfig {
97
+ /** Command name (only for root command) */
98
+ name?: string;
99
+ /** Command description */
100
+ desc: string;
101
+ /** Version (for root --version) */
102
+ version?: string;
103
+ /** Enable built-in "help" subcommand */
104
+ help?: boolean;
105
+ /** Default reporter for this command */
106
+ reporter?: IReporter;
107
+ }
108
+ /** Command interface */
109
+ interface ICommand {
110
+ readonly name: string | undefined;
111
+ readonly description: string;
112
+ readonly version: string | undefined;
113
+ readonly parent: ICommand | undefined;
114
+ readonly options: ICommandOptionConfig[];
115
+ readonly arguments: ICommandArgumentConfig[];
116
+ readonly subcommands: Map<string, ICommand>;
117
+ }
118
+ /** Execution context */
119
+ interface ICommandContext {
120
+ /** Current command node */
121
+ cmd: ICommand;
122
+ /** Environment variables */
123
+ envs: Record<string, string | undefined>;
124
+ /** Reporter instance */
125
+ reporter: IReporter;
126
+ /** Original argv */
127
+ argv: string[];
128
+ }
129
+ /** Action callback parameters */
130
+ interface ICommandActionParams {
131
+ /** Execution context */
132
+ ctx: ICommandContext;
133
+ /** Parsed options (keyed by long name) */
134
+ opts: ICommandParsedOpts;
135
+ /** Parsed positional arguments (keyed by argument name) */
136
+ args: ICommandParsedArgs;
137
+ /** Raw positional argument strings (before type conversion) */
138
+ rawArgs: string[];
139
+ }
140
+ /** Action handler function */
141
+ type ICommandAction = (params: ICommandActionParams) => void | Promise<void>;
142
+ /** run() / parse() method parameters */
143
+ interface ICommandRunParams {
144
+ /** Command line arguments (usually process.argv.slice(2)) */
145
+ argv: string[];
146
+ /** Environment variables (usually process.env) */
147
+ envs: Record<string, string | undefined>;
148
+ /** Optional reporter override */
149
+ reporter?: IReporter;
150
+ }
151
+ /** Parsed options record */
152
+ type ICommandParsedOpts = Record<string, unknown>;
153
+ /** Parsed arguments record */
154
+ type ICommandParsedArgs = Record<string, unknown>;
155
+ /** Route stage result */
156
+ interface ICommandRouteResult {
157
+ /** Command chain from root to leaf */
158
+ chain: ICommand[];
159
+ /** Remaining argv after routing */
160
+ remaining: string[];
161
+ }
162
+ /** Tokenize stage result */
163
+ interface ICommandTokenizeResult {
164
+ /** Option tokens (before --) */
165
+ optionTokens: ICommandToken[];
166
+ /** Arguments after -- */
167
+ restArgs: string[];
168
+ }
169
+ /** Resolve stage result */
170
+ interface ICommandResolveResult {
171
+ /** Tokens consumed by each command */
172
+ consumedTokens: Map<ICommand, ICommandToken[]>;
173
+ /** Argument tokens (non-option tokens) */
174
+ argTokens: ICommandToken[];
175
+ }
176
+ /** shift() method result (internal) */
177
+ interface ICommandShiftResult {
178
+ /** Tokens consumed by this command */
179
+ consumed: ICommandToken[];
180
+ /** Remaining tokens to pass to parent */
181
+ remaining: ICommandToken[];
182
+ }
183
+ /** Parse stage result */
184
+ interface ICommandParseResult {
185
+ /** Execution context */
186
+ ctx: ICommandContext;
187
+ /** Parsed options */
188
+ opts: ICommandParsedOpts;
189
+ /** Parsed arguments */
190
+ args: ICommandParsedArgs;
191
+ /** Raw argument strings */
192
+ rawArgs: string[];
193
+ }
194
+ /** Error kinds for command parsing */
195
+ type ICommanderErrorKind = 'InvalidOptionFormat' | 'InvalidNegativeOption' | 'NegativeOptionWithValue' | 'NegativeOptionType' | 'UnknownOption' | 'UnexpectedArgument' | 'MissingValue' | 'InvalidType' | 'UnsupportedShortSyntax' | 'OptionConflict' | 'MissingRequired' | 'InvalidChoice' | 'InvalidBooleanValue' | 'MissingRequiredArgument' | 'TooManyArguments' | 'ConfigurationError';
196
+ /** Commander error with structured information */
197
+ declare class CommanderError extends Error {
198
+ readonly kind: ICommanderErrorKind;
199
+ readonly commandPath: string;
200
+ constructor(kind: ICommanderErrorKind, message: string, commandPath: string);
201
+ /** Format error with help hint */
202
+ format(): string;
203
+ }
204
+ /** Shell type for completion */
205
+ type ICompletionShellType = 'bash' | 'fish' | 'pwsh';
206
+ /** Option metadata for completion */
207
+ interface ICompletionOptionMeta {
208
+ /** Long option name (camelCase) */
209
+ long: string;
210
+ /** Short option */
211
+ short?: string;
212
+ /** Description */
213
+ desc: string;
214
+ /** Whether option takes value (args !== 'none') */
215
+ takesValue: boolean;
216
+ /** Allowed values */
217
+ choices?: string[];
218
+ }
219
+ /** Command metadata for completion */
220
+ interface ICompletionMeta {
221
+ /** Command name */
222
+ name: string;
223
+ /** Description */
224
+ desc: string;
225
+ /** Command aliases */
226
+ aliases: string[];
227
+ /** Options */
228
+ options: ICompletionOptionMeta[];
229
+ /** Subcommands */
230
+ subcommands: ICompletionMeta[];
231
+ }
232
+ /** Shell completion paths configuration */
233
+ interface ICompletionPaths {
234
+ /** Bash completion file path */
235
+ bash: string;
236
+ /** Fish completion file path */
237
+ fish: string;
238
+ /** PowerShell completion file path */
239
+ pwsh: string;
240
+ }
241
+ /** CompletionCommand configuration */
242
+ interface ICompletionCommandConfig {
243
+ /** Program name for completion scripts (defaults to root.name) */
244
+ programName?: string;
245
+ /** Default completion file paths for each shell */
246
+ paths: ICompletionPaths;
247
+ }
248
+
249
+ /**
250
+ * Command class - CLI command builder with fluent API
251
+ *
252
+ * Execution flow: route → tokenize → resolve → parse → run
253
+ *
254
+ * @module @guanghechen/commander
255
+ */
256
+
257
+ declare class Command implements ICommand {
258
+ #private;
259
+ constructor(config: ICommandConfig);
260
+ get name(): string | undefined;
261
+ get description(): string;
262
+ get version(): string | undefined;
263
+ get parent(): Command | undefined;
264
+ get options(): ICommandOptionConfig[];
265
+ get arguments(): ICommandArgumentConfig[];
266
+ get subcommands(): Map<string, ICommand>;
267
+ option<T>(opt: ICommandOptionConfig<T>): this;
268
+ argument<T>(arg: ICommandArgumentConfig<T>): this;
269
+ action(fn: ICommandAction): this;
270
+ subcommand(name: string, cmd: Command): this;
271
+ run(params: ICommandRunParams): Promise<void>;
272
+ parse(params: ICommandRunParams): ICommandParseResult;
273
+ formatHelp(): string;
274
+ getCompletionMeta(): ICompletionMeta;
275
+ }
276
+
277
+ /**
278
+ * Shell completion generators
279
+ *
280
+ * @module @guanghechen/commander
281
+ */
282
+
283
+ /**
284
+ * Built-in completion command that generates shell completion scripts.
285
+ *
286
+ * @example
287
+ * ```typescript
288
+ * const root = new Command({ name: 'mycli', desc: 'My CLI' })
289
+ * root.subcommand('completion', new CompletionCommand(root, {
290
+ * paths: {
291
+ * bash: `~/.local/share/bash-completion/completions/mycli`,
292
+ * fish: `~/.config/fish/completions/mycli.fish`,
293
+ * pwsh: `~/.config/powershell/Microsoft.PowerShell_profile.ps1`,
294
+ * }
295
+ * }))
296
+ *
297
+ * // Usage:
298
+ * // mycli completion --bash > ~/.local/share/bash-completion/completions/mycli
299
+ * // mycli completion --fish --write (writes to default path)
300
+ * // mycli completion --fish --write /custom/path.fish
301
+ * ```
302
+ */
303
+ declare class CompletionCommand extends Command {
304
+ constructor(root: Command, config: ICompletionCommandConfig);
305
+ }
306
+ declare class BashCompletion {
307
+ #private;
308
+ constructor(meta: ICompletionMeta, programName: string);
309
+ generate(): string;
310
+ }
311
+ declare class FishCompletion {
312
+ #private;
313
+ constructor(meta: ICompletionMeta, programName: string);
314
+ generate(): string;
315
+ }
316
+ declare class PwshCompletion {
317
+ #private;
318
+ constructor(meta: ICompletionMeta, programName: string);
319
+ generate(): string;
320
+ }
321
+
322
+ /**
323
+ * Pre-defined common options for @guanghechen/commander
324
+ *
325
+ * @module @guanghechen/commander/options
326
+ */
327
+
328
+ /**
329
+ * Pre-defined --log-level option for setting log verbosity.
330
+ *
331
+ * Supports: debug | info | hint | warn | error (case-insensitive)
332
+ *
333
+ * | Property | Value |
334
+ * | --------- | ---------------------------------- |
335
+ * | long | 'logLevel' |
336
+ * | type | 'string' |
337
+ * | args | 'required' |
338
+ * | default | 'info' |
339
+ * | choices | LOG_LEVELS |
340
+ * | coerce | resolveLogLevel (case-insensitive) |
341
+ * | apply | ctx.reporter.setLevel(value) |
342
+ *
343
+ * @example
344
+ * ```typescript
345
+ * import { logLevelOption } from '@guanghechen/commander'
346
+ *
347
+ * const cmd = new Command('app')
348
+ * .option(logLevelOption)
349
+ * .action(({ opts }) => {
350
+ * console.log(opts.logLevel) // 'debug' | 'info' | 'hint' | 'warn' | 'error'
351
+ * })
352
+ *
353
+ * // Override with spread syntax
354
+ * .option({ ...logLevelOption, default: 'warn' })
355
+ * ```
356
+ */
357
+ declare const logLevelOption: ICommandOptionConfig<string>;
358
+ /**
359
+ * Pre-defined --silent option for suppressing non-error output.
360
+ *
361
+ * | Property | Value |
362
+ * | --------- | --------- |
363
+ * | long | 'silent' |
364
+ * | type | 'boolean' |
365
+ * | args | 'none' |
366
+ * | default | false |
367
+ *
368
+ * @example
369
+ * ```typescript
370
+ * import { silentOption } from '@guanghechen/commander'
371
+ *
372
+ * const cmd = new Command('app')
373
+ * .option(silentOption)
374
+ * .action(({ opts }) => {
375
+ * if (!opts.silent) {
376
+ * console.log('Processing...')
377
+ * }
378
+ * })
379
+ * ```
380
+ */
381
+ declare const silentOption: ICommandOptionConfig<boolean>;
382
+
383
+ export { BashCompletion, Command, CommanderError, CompletionCommand, FishCompletion, PwshCompletion, logLevelOption, silentOption };
384
+ export type { ICommand, ICommandAction, ICommandActionParams, ICommandArgumentConfig, ICommandArgumentKind, ICommandArgumentType, ICommandConfig, ICommandContext, ICommandOptionArgs, ICommandOptionConfig, ICommandOptionType, ICommandParseResult, ICommandParsedArgs, ICommandParsedOpts, ICommandResolveResult, ICommandRouteResult, ICommandRunParams, ICommandShiftResult, ICommandToken, ICommandTokenType, ICommandTokenizeResult, ICommanderErrorKind, ICompletionCommandConfig, ICompletionMeta, ICompletionOptionMeta, ICompletionPaths, ICompletionShellType };
@@ -93,7 +93,7 @@ interface ICommandArgumentConfig<T = unknown> {
93
93
  coerce?: (rawValue: string) => T;
94
94
  }
95
95
  interface ICommandBuiltinOptionConfig {
96
- /** Enable built-in --version option (root only, requires configured version) */
96
+ /** Enable built-in --version option (requires configured version on target command) */
97
97
  version?: boolean;
98
98
  /** Enable built-in --color/--no-color option for help rendering (defaults respect NO_COLOR) */
99
99
  color?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guanghechen/commander",
3
- "version": "4.7.0",
3
+ "version": "4.7.1",
4
4
  "description": "A minimal, type-safe command-line interface builder with fluent API",
5
5
  "author": {
6
6
  "name": "guanghechen",
@@ -44,8 +44,8 @@
44
44
  "README.md"
45
45
  ],
46
46
  "dependencies": {
47
- "@guanghechen/reporter": "^3.3.0",
48
- "@guanghechen/env": "^2.0.2"
47
+ "@guanghechen/env": "^2.0.2",
48
+ "@guanghechen/reporter": "^3.3.0"
49
49
  },
50
50
  "scripts": {
51
51
  "build": "rollup -c ../../rollup.config.mjs",