@guanghechen/commander 4.0.0 → 4.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # Change Log
2
2
 
3
+ ## 4.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - feat(reporter): add setFlight API for flight tracking feat(commander): unify builtin config for
8
+ options and commands
9
+
10
+ ### Patch Changes
11
+
12
+ - Updated dependencies:
13
+ - @guanghechen/reporter@3.3.0
14
+
15
+ ## 4.1.0
16
+
17
+ ### Minor Changes
18
+
19
+ - ### @guanghechen/reporter
20
+ - feat: add `setLevel` method for dynamic log level change
21
+ - refactor: split source into modular files (`level.ts`, `chalk.ts`, `types.ts`, `reporter.ts`)
22
+ - refactor: move `IReporter` types from `@guanghechen/types` to `@guanghechen/reporter`
23
+ - export: add level utilities (`LogLevelEnum`, `ILogLevel`, `LOG_LEVELS`, `LOG_LEVEL_VALUES`,
24
+ `isLogLevel`, `getLogLevelValue`, `resolveLogLevel`)
25
+ - export: add chalk utilities (`ANSI`, `formatTag`)
26
+
27
+ ### @guanghechen/types
28
+ - refactor: remove `IReporter` and `IReporterLevel` exports (moved to `@guanghechen/reporter`)
29
+
30
+ ### @guanghechen/commander
31
+ - feat: add predefined options `logLevelOption` and `silentOption` with `apply` callback support
32
+ - refactor: use `ILogLevel` from `@guanghechen/reporter` instead of `IReporterLevel`
33
+
34
+ ### Dependent packages
35
+ - chore: bump version for packages depending on `@guanghechen/types`, `@guanghechen/reporter`, or
36
+ `@guanghechen/commander`
37
+
38
+ ### Patch Changes
39
+
40
+ - Updated dependencies:
41
+ - @guanghechen/reporter@3.2.0
42
+
3
43
  ## 4.0.0
4
44
 
5
45
  ### Major Changes
package/lib/cjs/index.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var reporter = require('@guanghechen/reporter');
3
4
  var fs = require('node:fs');
4
5
  var path = require('node:path');
5
6
 
@@ -23,6 +24,57 @@ function _interopNamespaceDefault(e) {
23
24
  var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
24
25
  var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
25
26
 
27
+ const logLevelOption = {
28
+ long: 'logLevel',
29
+ type: 'string',
30
+ args: 'required',
31
+ desc: 'Set log level',
32
+ default: 'info',
33
+ choices: reporter.LOG_LEVELS,
34
+ coerce: (raw) => {
35
+ const level = reporter.resolveLogLevel(raw);
36
+ if (level === undefined) {
37
+ throw new Error(`Invalid log level: ${raw}`);
38
+ }
39
+ return level;
40
+ },
41
+ apply: (value, ctx) => {
42
+ ctx.reporter.setLevel(value);
43
+ },
44
+ };
45
+ const logDateOption = {
46
+ long: 'logDate',
47
+ type: 'boolean',
48
+ args: 'none',
49
+ desc: 'Enable log timestamp',
50
+ default: true,
51
+ apply: (value, ctx) => {
52
+ ctx.reporter.setFlight({ date: Boolean(value) });
53
+ },
54
+ };
55
+ const logColorfulOption = {
56
+ long: 'logColorful',
57
+ type: 'boolean',
58
+ args: 'none',
59
+ desc: 'Enable colorful log output',
60
+ default: true,
61
+ apply: (value, ctx) => {
62
+ ctx.reporter.setFlight({ color: Boolean(value) });
63
+ },
64
+ };
65
+ const silentOption = {
66
+ long: 'silent',
67
+ type: 'boolean',
68
+ args: 'none',
69
+ desc: 'Suppress non-error output',
70
+ default: false,
71
+ apply: (value, ctx) => {
72
+ if (value) {
73
+ ctx.reporter.setLevel('error');
74
+ }
75
+ },
76
+ };
77
+
26
78
  class CommanderError extends Error {
27
79
  kind;
28
80
  commandPath;
@@ -37,20 +89,6 @@ class CommanderError extends Error {
37
89
  }
38
90
  }
39
91
 
40
- class DefaultReporter {
41
- debug(message, ...args) {
42
- console.debug(message, ...args);
43
- }
44
- info(message, ...args) {
45
- console.info(message, ...args);
46
- }
47
- warn(message, ...args) {
48
- console.warn(message, ...args);
49
- }
50
- error(message, ...args) {
51
- console.error(message, ...args);
52
- }
53
- }
54
92
  const LONG_OPTION_REGEX = /^--[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
55
93
  const NEGATIVE_OPTION_REGEX = /^--no-[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
56
94
  function kebabToCamelCase(str) {
@@ -152,11 +190,70 @@ const BUILTIN_VERSION_OPTION = {
152
190
  args: 'none',
153
191
  desc: 'Show version number',
154
192
  };
193
+ function normalizeBuiltinConfig(builtin) {
194
+ const resolved = {
195
+ option: {
196
+ logLevel: true,
197
+ silent: true,
198
+ logDate: true,
199
+ logColorful: true,
200
+ },
201
+ command: {
202
+ help: false,
203
+ },
204
+ };
205
+ if (builtin === undefined) {
206
+ return resolved;
207
+ }
208
+ if (builtin === true) {
209
+ return {
210
+ option: { logLevel: true, silent: true, logDate: true, logColorful: true },
211
+ command: { help: true },
212
+ };
213
+ }
214
+ if (builtin === false) {
215
+ return {
216
+ option: { logLevel: false, silent: false, logDate: false, logColorful: false },
217
+ command: { help: false },
218
+ };
219
+ }
220
+ if (builtin.option !== undefined) {
221
+ if (builtin.option === false) {
222
+ resolved.option = { logLevel: false, silent: false, logDate: false, logColorful: false };
223
+ }
224
+ else if (builtin.option === true) {
225
+ resolved.option = { logLevel: true, silent: true, logDate: true, logColorful: true };
226
+ }
227
+ else {
228
+ if (builtin.option.logLevel !== undefined)
229
+ resolved.option.logLevel = builtin.option.logLevel;
230
+ if (builtin.option.silent !== undefined)
231
+ resolved.option.silent = builtin.option.silent;
232
+ if (builtin.option.logDate !== undefined)
233
+ resolved.option.logDate = builtin.option.logDate;
234
+ if (builtin.option.logColorful !== undefined) {
235
+ resolved.option.logColorful = builtin.option.logColorful;
236
+ }
237
+ }
238
+ }
239
+ if (builtin.command !== undefined) {
240
+ if (builtin.command === false) {
241
+ resolved.command = { help: false };
242
+ }
243
+ else if (builtin.command === true) {
244
+ resolved.command = { help: true };
245
+ }
246
+ else if (builtin.command.help !== undefined) {
247
+ resolved.command.help = builtin.command.help;
248
+ }
249
+ }
250
+ return resolved;
251
+ }
155
252
  class Command {
156
253
  #name;
157
254
  #desc;
158
255
  #version;
159
- #helpSubcommandEnabled;
256
+ #builtin;
160
257
  #reporter;
161
258
  #parent;
162
259
  #options = [];
@@ -168,7 +265,7 @@ class Command {
168
265
  this.#name = config.name ?? '';
169
266
  this.#desc = config.desc;
170
267
  this.#version = config.version;
171
- this.#helpSubcommandEnabled = config.help ?? false;
268
+ this.#builtin = normalizeBuiltinConfig(config.builtin);
172
269
  this.#reporter = config.reporter;
173
270
  }
174
271
  get name() {
@@ -208,7 +305,7 @@ class Command {
208
305
  return this;
209
306
  }
210
307
  subcommand(name, cmd) {
211
- if (this.#helpSubcommandEnabled && name === 'help') {
308
+ if (this.#builtin.command.help && name === 'help') {
212
309
  throw new CommanderError('ConfigurationError', '"help" is a reserved subcommand name when help subcommand is enabled', this.#getCommandPath());
213
310
  }
214
311
  if (cmd.#parent && cmd.#parent !== this) {
@@ -228,7 +325,7 @@ class Command {
228
325
  return this;
229
326
  }
230
327
  async run(params) {
231
- const { argv, envs, reporter } = params;
328
+ const { argv, envs, reporter: reporter$1 } = params;
232
329
  try {
233
330
  const processedArgv = this.#processHelpSubcommand(argv);
234
331
  const routeResult = this.#route(processedArgv);
@@ -253,7 +350,7 @@ class Command {
253
350
  const ctx = {
254
351
  cmd: leafCommand,
255
352
  envs,
256
- reporter: reporter ?? this.#reporter ?? new DefaultReporter(),
353
+ reporter: reporter$1 ?? this.#reporter ?? new reporter.Reporter(),
257
354
  argv,
258
355
  };
259
356
  const parseResult = this.#parse(chain, resolveResult, ctx, restArgs);
@@ -283,7 +380,7 @@ class Command {
283
380
  }
284
381
  }
285
382
  parse(params) {
286
- const { argv, envs, reporter } = params;
383
+ const { argv, envs, reporter: reporter$1 } = params;
287
384
  const processedArgv = this.#processHelpSubcommand(argv);
288
385
  const routeResult = this.#route(processedArgv);
289
386
  const { chain, remaining } = routeResult;
@@ -294,7 +391,7 @@ class Command {
294
391
  const ctx = {
295
392
  cmd: leafCommand,
296
393
  envs,
297
- reporter: reporter ?? this.#reporter ?? new DefaultReporter(),
394
+ reporter: reporter$1 ?? this.#reporter ?? new reporter.Reporter(),
298
395
  argv,
299
396
  };
300
397
  return this.#parse(chain, resolveResult, ctx, restArgs);
@@ -355,7 +452,7 @@ class Command {
355
452
  }
356
453
  lines.push('');
357
454
  }
358
- const showHelpSubcommand = this.#helpSubcommandEnabled && this.#subcommandsList.length > 0;
455
+ const showHelpSubcommand = this.#builtin.command.help && this.#subcommandsList.length > 0;
359
456
  if (this.#subcommandsList.length > 0) {
360
457
  lines.push('Commands:');
361
458
  const cmdLines = [];
@@ -406,7 +503,7 @@ class Command {
406
503
  };
407
504
  }
408
505
  #processHelpSubcommand(argv) {
409
- if (!this.#helpSubcommandEnabled)
506
+ if (!this.#builtin.command.help)
410
507
  return argv;
411
508
  if (argv.length < 1 || argv[0] !== 'help')
412
509
  return argv;
@@ -735,12 +832,28 @@ class Command {
735
832
  const optionMap = new Map();
736
833
  const hasUserHelp = this.#options.some(o => o.long === 'help');
737
834
  const hasUserVersion = this.#options.some(o => o.long === 'version');
835
+ const hasUserLogLevel = this.#options.some(o => o.long === 'logLevel');
836
+ const hasUserSilent = this.#options.some(o => o.long === 'silent');
837
+ const hasUserLogDate = this.#options.some(o => o.long === 'logDate');
838
+ const hasUserLogColorful = this.#options.some(o => o.long === 'logColorful');
738
839
  if (!hasUserHelp) {
739
840
  optionMap.set('help', BUILTIN_HELP_OPTION);
740
841
  }
741
842
  if (!hasUserVersion && includeVersion) {
742
843
  optionMap.set('version', BUILTIN_VERSION_OPTION);
743
844
  }
845
+ if (this.#builtin.option.logLevel && !hasUserLogLevel) {
846
+ optionMap.set('logLevel', logLevelOption);
847
+ }
848
+ if (this.#builtin.option.silent && !hasUserSilent) {
849
+ optionMap.set('silent', silentOption);
850
+ }
851
+ if (this.#builtin.option.logDate && !hasUserLogDate) {
852
+ optionMap.set('logDate', logDateOption);
853
+ }
854
+ if (this.#builtin.option.logColorful && !hasUserLogColorful) {
855
+ optionMap.set('logColorful', logColorfulOption);
856
+ }
744
857
  for (const opt of this.#options) {
745
858
  optionMap.set(opt.long, opt);
746
859
  }
@@ -1220,3 +1333,7 @@ exports.CommanderError = CommanderError;
1220
1333
  exports.CompletionCommand = CompletionCommand;
1221
1334
  exports.FishCompletion = FishCompletion;
1222
1335
  exports.PwshCompletion = PwshCompletion;
1336
+ exports.logColorfulOption = logColorfulOption;
1337
+ exports.logDateOption = logDateOption;
1338
+ exports.logLevelOption = logLevelOption;
1339
+ exports.silentOption = silentOption;
package/lib/esm/index.mjs CHANGED
@@ -1,6 +1,58 @@
1
+ import { LOG_LEVELS, resolveLogLevel, Reporter } from '@guanghechen/reporter';
1
2
  import * as fs from 'node:fs';
2
3
  import * as path from 'node:path';
3
4
 
5
+ const logLevelOption = {
6
+ long: 'logLevel',
7
+ type: 'string',
8
+ args: 'required',
9
+ desc: 'Set log level',
10
+ default: 'info',
11
+ choices: LOG_LEVELS,
12
+ coerce: (raw) => {
13
+ const level = resolveLogLevel(raw);
14
+ if (level === undefined) {
15
+ throw new Error(`Invalid log level: ${raw}`);
16
+ }
17
+ return level;
18
+ },
19
+ apply: (value, ctx) => {
20
+ ctx.reporter.setLevel(value);
21
+ },
22
+ };
23
+ const logDateOption = {
24
+ long: 'logDate',
25
+ type: 'boolean',
26
+ args: 'none',
27
+ desc: 'Enable log timestamp',
28
+ default: true,
29
+ apply: (value, ctx) => {
30
+ ctx.reporter.setFlight({ date: Boolean(value) });
31
+ },
32
+ };
33
+ const logColorfulOption = {
34
+ long: 'logColorful',
35
+ type: 'boolean',
36
+ args: 'none',
37
+ desc: 'Enable colorful log output',
38
+ default: true,
39
+ apply: (value, ctx) => {
40
+ ctx.reporter.setFlight({ color: Boolean(value) });
41
+ },
42
+ };
43
+ const silentOption = {
44
+ long: 'silent',
45
+ type: 'boolean',
46
+ args: 'none',
47
+ desc: 'Suppress non-error output',
48
+ default: false,
49
+ apply: (value, ctx) => {
50
+ if (value) {
51
+ ctx.reporter.setLevel('error');
52
+ }
53
+ },
54
+ };
55
+
4
56
  class CommanderError extends Error {
5
57
  kind;
6
58
  commandPath;
@@ -15,20 +67,6 @@ class CommanderError extends Error {
15
67
  }
16
68
  }
17
69
 
18
- class DefaultReporter {
19
- debug(message, ...args) {
20
- console.debug(message, ...args);
21
- }
22
- info(message, ...args) {
23
- console.info(message, ...args);
24
- }
25
- warn(message, ...args) {
26
- console.warn(message, ...args);
27
- }
28
- error(message, ...args) {
29
- console.error(message, ...args);
30
- }
31
- }
32
70
  const LONG_OPTION_REGEX = /^--[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
33
71
  const NEGATIVE_OPTION_REGEX = /^--no-[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
34
72
  function kebabToCamelCase(str) {
@@ -130,11 +168,70 @@ const BUILTIN_VERSION_OPTION = {
130
168
  args: 'none',
131
169
  desc: 'Show version number',
132
170
  };
171
+ function normalizeBuiltinConfig(builtin) {
172
+ const resolved = {
173
+ option: {
174
+ logLevel: true,
175
+ silent: true,
176
+ logDate: true,
177
+ logColorful: true,
178
+ },
179
+ command: {
180
+ help: false,
181
+ },
182
+ };
183
+ if (builtin === undefined) {
184
+ return resolved;
185
+ }
186
+ if (builtin === true) {
187
+ return {
188
+ option: { logLevel: true, silent: true, logDate: true, logColorful: true },
189
+ command: { help: true },
190
+ };
191
+ }
192
+ if (builtin === false) {
193
+ return {
194
+ option: { logLevel: false, silent: false, logDate: false, logColorful: false },
195
+ command: { help: false },
196
+ };
197
+ }
198
+ if (builtin.option !== undefined) {
199
+ if (builtin.option === false) {
200
+ resolved.option = { logLevel: false, silent: false, logDate: false, logColorful: false };
201
+ }
202
+ else if (builtin.option === true) {
203
+ resolved.option = { logLevel: true, silent: true, logDate: true, logColorful: true };
204
+ }
205
+ else {
206
+ if (builtin.option.logLevel !== undefined)
207
+ resolved.option.logLevel = builtin.option.logLevel;
208
+ if (builtin.option.silent !== undefined)
209
+ resolved.option.silent = builtin.option.silent;
210
+ if (builtin.option.logDate !== undefined)
211
+ resolved.option.logDate = builtin.option.logDate;
212
+ if (builtin.option.logColorful !== undefined) {
213
+ resolved.option.logColorful = builtin.option.logColorful;
214
+ }
215
+ }
216
+ }
217
+ if (builtin.command !== undefined) {
218
+ if (builtin.command === false) {
219
+ resolved.command = { help: false };
220
+ }
221
+ else if (builtin.command === true) {
222
+ resolved.command = { help: true };
223
+ }
224
+ else if (builtin.command.help !== undefined) {
225
+ resolved.command.help = builtin.command.help;
226
+ }
227
+ }
228
+ return resolved;
229
+ }
133
230
  class Command {
134
231
  #name;
135
232
  #desc;
136
233
  #version;
137
- #helpSubcommandEnabled;
234
+ #builtin;
138
235
  #reporter;
139
236
  #parent;
140
237
  #options = [];
@@ -146,7 +243,7 @@ class Command {
146
243
  this.#name = config.name ?? '';
147
244
  this.#desc = config.desc;
148
245
  this.#version = config.version;
149
- this.#helpSubcommandEnabled = config.help ?? false;
246
+ this.#builtin = normalizeBuiltinConfig(config.builtin);
150
247
  this.#reporter = config.reporter;
151
248
  }
152
249
  get name() {
@@ -186,7 +283,7 @@ class Command {
186
283
  return this;
187
284
  }
188
285
  subcommand(name, cmd) {
189
- if (this.#helpSubcommandEnabled && name === 'help') {
286
+ if (this.#builtin.command.help && name === 'help') {
190
287
  throw new CommanderError('ConfigurationError', '"help" is a reserved subcommand name when help subcommand is enabled', this.#getCommandPath());
191
288
  }
192
289
  if (cmd.#parent && cmd.#parent !== this) {
@@ -231,7 +328,7 @@ class Command {
231
328
  const ctx = {
232
329
  cmd: leafCommand,
233
330
  envs,
234
- reporter: reporter ?? this.#reporter ?? new DefaultReporter(),
331
+ reporter: reporter ?? this.#reporter ?? new Reporter(),
235
332
  argv,
236
333
  };
237
334
  const parseResult = this.#parse(chain, resolveResult, ctx, restArgs);
@@ -272,7 +369,7 @@ class Command {
272
369
  const ctx = {
273
370
  cmd: leafCommand,
274
371
  envs,
275
- reporter: reporter ?? this.#reporter ?? new DefaultReporter(),
372
+ reporter: reporter ?? this.#reporter ?? new Reporter(),
276
373
  argv,
277
374
  };
278
375
  return this.#parse(chain, resolveResult, ctx, restArgs);
@@ -333,7 +430,7 @@ class Command {
333
430
  }
334
431
  lines.push('');
335
432
  }
336
- const showHelpSubcommand = this.#helpSubcommandEnabled && this.#subcommandsList.length > 0;
433
+ const showHelpSubcommand = this.#builtin.command.help && this.#subcommandsList.length > 0;
337
434
  if (this.#subcommandsList.length > 0) {
338
435
  lines.push('Commands:');
339
436
  const cmdLines = [];
@@ -384,7 +481,7 @@ class Command {
384
481
  };
385
482
  }
386
483
  #processHelpSubcommand(argv) {
387
- if (!this.#helpSubcommandEnabled)
484
+ if (!this.#builtin.command.help)
388
485
  return argv;
389
486
  if (argv.length < 1 || argv[0] !== 'help')
390
487
  return argv;
@@ -713,12 +810,28 @@ class Command {
713
810
  const optionMap = new Map();
714
811
  const hasUserHelp = this.#options.some(o => o.long === 'help');
715
812
  const hasUserVersion = this.#options.some(o => o.long === 'version');
813
+ const hasUserLogLevel = this.#options.some(o => o.long === 'logLevel');
814
+ const hasUserSilent = this.#options.some(o => o.long === 'silent');
815
+ const hasUserLogDate = this.#options.some(o => o.long === 'logDate');
816
+ const hasUserLogColorful = this.#options.some(o => o.long === 'logColorful');
716
817
  if (!hasUserHelp) {
717
818
  optionMap.set('help', BUILTIN_HELP_OPTION);
718
819
  }
719
820
  if (!hasUserVersion && includeVersion) {
720
821
  optionMap.set('version', BUILTIN_VERSION_OPTION);
721
822
  }
823
+ if (this.#builtin.option.logLevel && !hasUserLogLevel) {
824
+ optionMap.set('logLevel', logLevelOption);
825
+ }
826
+ if (this.#builtin.option.silent && !hasUserSilent) {
827
+ optionMap.set('silent', silentOption);
828
+ }
829
+ if (this.#builtin.option.logDate && !hasUserLogDate) {
830
+ optionMap.set('logDate', logDateOption);
831
+ }
832
+ if (this.#builtin.option.logColorful && !hasUserLogColorful) {
833
+ optionMap.set('logColorful', logColorfulOption);
834
+ }
722
835
  for (const opt of this.#options) {
723
836
  optionMap.set(opt.long, opt);
724
837
  }
@@ -1192,4 +1305,4 @@ class PwshCompletion {
1192
1305
  }
1193
1306
  }
1194
1307
 
1195
- export { BashCompletion, Command, CommanderError, CompletionCommand, FishCompletion, PwshCompletion };
1308
+ export { BashCompletion, Command, CommanderError, CompletionCommand, FishCompletion, PwshCompletion, logColorfulOption, logDateOption, logLevelOption, silentOption };
@@ -1,18 +1,11 @@
1
+ import { IReporter } from '@guanghechen/reporter';
2
+
1
3
  /**
2
4
  * Type definitions for @guanghechen/commander
3
5
  *
4
6
  * @module @guanghechen/commander
5
7
  */
6
- /**
7
- * Reporter interface for logging.
8
- * Provided by @guanghechen/reporter or user implementation.
9
- */
10
- interface IReporter {
11
- debug(message: string, ...args: unknown[]): void;
12
- info(message: string, ...args: unknown[]): void;
13
- warn(message: string, ...args: unknown[]): void;
14
- error(message: string, ...args: unknown[]): void;
15
- }
8
+
16
9
  /** Token type: long option, short option, or positional */
17
10
  type ICommandTokenType = 'long' | 'short' | 'none';
18
11
  /**
@@ -99,6 +92,26 @@ interface ICommandArgumentConfig<T = unknown> {
99
92
  /** Custom value transformation (takes precedence over type conversion) */
100
93
  coerce?: (rawValue: string) => T;
101
94
  }
95
+ interface ICommandBuiltinOptionConfig {
96
+ /** Enable built-in --log-level option */
97
+ logLevel?: boolean;
98
+ /** Enable built-in --silent option */
99
+ silent?: boolean;
100
+ /** Enable built-in --log-date/--no-log-date option */
101
+ logDate?: boolean;
102
+ /** Enable built-in --log-colorful/--no-log-colorful option */
103
+ logColorful?: boolean;
104
+ }
105
+ interface ICommandBuiltinCommandConfig {
106
+ /** Enable built-in help subcommand */
107
+ help?: boolean;
108
+ }
109
+ interface ICommandBuiltinConfig {
110
+ /** Built-in options configuration */
111
+ option?: boolean | ICommandBuiltinOptionConfig;
112
+ /** Built-in command configuration */
113
+ command?: boolean | ICommandBuiltinCommandConfig;
114
+ }
102
115
  /** Command configuration */
103
116
  interface ICommandConfig {
104
117
  /** Command name (only for root command) */
@@ -107,8 +120,8 @@ interface ICommandConfig {
107
120
  desc: string;
108
121
  /** Version (for root --version) */
109
122
  version?: string;
110
- /** Enable built-in "help" subcommand */
111
- help?: boolean;
123
+ /** Built-in features configuration */
124
+ builtin?: boolean | ICommandBuiltinConfig;
112
125
  /** Default reporter for this command */
113
126
  reporter?: IReporter;
114
127
  }
@@ -326,5 +339,88 @@ declare class PwshCompletion {
326
339
  generate(): string;
327
340
  }
328
341
 
329
- export { BashCompletion, Command, CommanderError, CompletionCommand, FishCompletion, PwshCompletion };
330
- 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, IReporter };
342
+ /**
343
+ * Pre-defined common options for @guanghechen/commander
344
+ *
345
+ * @module @guanghechen/commander/options
346
+ */
347
+
348
+ /**
349
+ * Pre-defined --log-level option for setting log verbosity.
350
+ *
351
+ * Supports: debug | info | hint | warn | error (case-insensitive)
352
+ *
353
+ * | Property | Value |
354
+ * | --------- | ---------------------------------- |
355
+ * | long | 'logLevel' |
356
+ * | type | 'string' |
357
+ * | args | 'required' |
358
+ * | default | 'info' |
359
+ * | choices | LOG_LEVELS |
360
+ * | coerce | resolveLogLevel (case-insensitive) |
361
+ * | apply | ctx.reporter.setLevel(value) |
362
+ *
363
+ * @example
364
+ * ```typescript
365
+ * import { logLevelOption } from '@guanghechen/commander'
366
+ *
367
+ * const cmd = new Command('app')
368
+ * .option(logLevelOption)
369
+ * .action(({ opts }) => {
370
+ * console.log(opts.logLevel) // 'debug' | 'info' | 'hint' | 'warn' | 'error'
371
+ * })
372
+ *
373
+ * // Override with spread syntax
374
+ * .option({ ...logLevelOption, default: 'warn' })
375
+ * ```
376
+ */
377
+ declare const logLevelOption: ICommandOptionConfig<string>;
378
+ /**
379
+ * Pre-defined --log-date option for controlling timestamp output.
380
+ *
381
+ * | Property | Value |
382
+ * | --------- | --------- |
383
+ * | long | 'logDate' |
384
+ * | type | 'boolean' |
385
+ * | args | 'none' |
386
+ * | default | true |
387
+ */
388
+ declare const logDateOption: ICommandOptionConfig<boolean>;
389
+ /**
390
+ * Pre-defined --log-colorful option for controlling colorful output.
391
+ *
392
+ * | Property | Value |
393
+ * | --------- | ------------- |
394
+ * | long | 'logColorful' |
395
+ * | type | 'boolean' |
396
+ * | args | 'none' |
397
+ * | default | true |
398
+ */
399
+ declare const logColorfulOption: ICommandOptionConfig<boolean>;
400
+ /**
401
+ * Pre-defined --silent option for suppressing non-error output.
402
+ *
403
+ * | Property | Value |
404
+ * | --------- | --------- |
405
+ * | long | 'silent' |
406
+ * | type | 'boolean' |
407
+ * | args | 'none' |
408
+ * | default | false |
409
+ *
410
+ * @example
411
+ * ```typescript
412
+ * import { silentOption } from '@guanghechen/commander'
413
+ *
414
+ * const cmd = new Command('app')
415
+ * .option(silentOption)
416
+ * .action(({ opts }) => {
417
+ * if (!opts.silent) {
418
+ * console.log('Processing...')
419
+ * }
420
+ * })
421
+ * ```
422
+ */
423
+ declare const silentOption: ICommandOptionConfig<boolean>;
424
+
425
+ export { BashCompletion, Command, CommanderError, CompletionCommand, FishCompletion, PwshCompletion, logColorfulOption, logDateOption, logLevelOption, silentOption };
426
+ export type { ICommand, ICommandAction, ICommandActionParams, ICommandArgumentConfig, ICommandArgumentKind, ICommandArgumentType, ICommandBuiltinCommandConfig, ICommandBuiltinConfig, ICommandBuiltinOptionConfig, ICommandConfig, ICommandContext, ICommandOptionArgs, ICommandOptionConfig, ICommandOptionType, ICommandParseResult, ICommandParsedArgs, ICommandParsedOpts, ICommandResolveResult, ICommandRouteResult, ICommandRunParams, ICommandShiftResult, ICommandToken, ICommandTokenType, ICommandTokenizeResult, ICommanderErrorKind, ICompletionCommandConfig, ICompletionMeta, ICompletionOptionMeta, ICompletionPaths, ICompletionShellType };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guanghechen/commander",
3
- "version": "4.0.0",
3
+ "version": "4.2.0",
4
4
  "description": "A minimal, type-safe command-line interface builder with fluent API",
5
5
  "author": {
6
6
  "name": "guanghechen",
@@ -40,6 +40,9 @@
40
40
  "LICENSE",
41
41
  "README.md"
42
42
  ],
43
+ "dependencies": {
44
+ "@guanghechen/reporter": "^3.3.0"
45
+ },
43
46
  "scripts": {
44
47
  "build": "rollup -c ../../rollup.config.mjs",
45
48
  "clean": "rimraf lib",