This commit is contained in:
2026-02-13 23:49:12 +01:00
parent 206b8f08db
commit 2e02d6d763
36 changed files with 1816 additions and 4178 deletions

View File

@@ -1,8 +1,6 @@
// Type definitions for commander
// Original definitions by: Alan Agius <https://github.com/alan-agius4>, Marcelo Dezem <https://github.com/mdezem>, vvakame <https://github.com/vvakame>, Jules Randolph <https://github.com/sveinburne>
// Using method rather than property for method-signature-style, to document method overloads separately. Allow either.
/* eslint-disable @typescript-eslint/method-signature-style */
/* eslint-disable @typescript-eslint/no-explicit-any */
// This is a trick to encourage editor to suggest the known literals while still
@@ -11,7 +9,9 @@
// - https://github.com/microsoft/TypeScript/issues/29729
// - https://github.com/sindresorhus/type-fest/blob/main/source/literal-union.d.ts
// - https://github.com/sindresorhus/type-fest/blob/main/source/primitive.d.ts
type LiteralUnion<LiteralType, BaseType extends string | number> = LiteralType | (BaseType & Record<never, never>);
type LiteralUnion<LiteralType, BaseType extends string | number> =
| LiteralType
| (BaseType & Record<never, never>);
export class CommanderError extends Error {
code: string;
@@ -24,7 +24,6 @@ export class CommanderError extends Error {
* @param exitCode - suggested exit code which could be used with process.exit
* @param code - an id string representing the error
* @param message - human-readable description of the error
* @constructor
*/
constructor(exitCode: number, code: string, message: string);
}
@@ -33,13 +32,13 @@ export class InvalidArgumentError extends CommanderError {
/**
* Constructs the InvalidArgumentError class
* @param message - explanation of why argument is invalid
* @constructor
*/
constructor(message: string);
}
export { InvalidArgumentError as InvalidOptionArgumentError }; // deprecated old name
export interface ErrorOptions { // optional parameter for error()
export interface ErrorOptions {
// optional parameter for error()
/** an id string representing the error */
code?: string;
/** suggested exit code which could be used with process.exit */
@@ -162,11 +161,6 @@ export class Option {
*/
env(name: string): this;
/**
* Calculate the full description, including defaultValue etc.
*/
fullDescription(): string;
/**
* Set the custom handler for processing CLI option arguments into option values.
*/
@@ -194,7 +188,7 @@ export class Option {
/**
* Return option name, in a camelcase format that can be used
* as a object attribute key.
* as an object attribute key.
*/
attributeName(): string;
@@ -209,12 +203,25 @@ export class Option {
export class Help {
/** output helpWidth, long lines are wrapped to fit */
helpWidth?: number;
minWidthToWrap: number;
sortSubcommands: boolean;
sortOptions: boolean;
showGlobalOptions: boolean;
constructor();
/*
* prepareContext is called by Commander after applying overrides from `Command.configureHelp()`
* and just before calling `formatHelp()`.
*
* Commander just uses the helpWidth and the others are provided for subclasses.
*/
prepareContext(contextOptions: {
error?: boolean;
helpWidth?: number;
outputHasColors?: boolean;
}): void;
/** Get the command term to show in the list of subcommands. */
subcommandTerm(cmd: Command): string;
/** Get the command summary to show in the list of subcommands. */
@@ -250,14 +257,61 @@ export class Help {
longestGlobalOptionTermLength(cmd: Command, helper: Help): number;
/** Get the longest argument term length. */
longestArgumentTermLength(cmd: Command, helper: Help): number;
/** Return display width of string, ignoring ANSI escape sequences. Used in padding and wrapping calculations. */
displayWidth(str: string): number;
/** Style the titles. Called with 'Usage:', 'Options:', etc. */
styleTitle(title: string): string;
/** Usage: <str> */
styleUsage(str: string): string;
/** Style for command name in usage string. */
styleCommandText(str: string): string;
styleCommandDescription(str: string): string;
styleOptionDescription(str: string): string;
styleSubcommandDescription(str: string): string;
styleArgumentDescription(str: string): string;
/** Base style used by descriptions. */
styleDescriptionText(str: string): string;
styleOptionTerm(str: string): string;
styleSubcommandTerm(str: string): string;
styleArgumentTerm(str: string): string;
/** Base style used in terms and usage for options. */
styleOptionText(str: string): string;
/** Base style used in terms and usage for subcommands. */
styleSubcommandText(str: string): string;
/** Base style used in terms and usage for arguments. */
styleArgumentText(str: string): string;
/** Calculate the pad width from the maximum term length. */
padWidth(cmd: Command, helper: Help): number;
/**
* Wrap the given string to width characters per line, with lines after the first indented.
* Do not wrap if insufficient room for wrapping (minColumnWidth), or string is manually formatted.
* Wrap a string at whitespace, preserving existing line breaks.
* Wrapping is skipped if the width is less than `minWidthToWrap`.
*/
wrap(str: string, width: number, indent: number, minColumnWidth?: number): string;
boxWrap(str: string, width: number): string;
/** Detect manually wrapped and indented strings by checking for line break followed by whitespace. */
preformatted(str: string): boolean;
/**
* Format the "item", which consists of a term and description. Pad the term and wrap the description, indenting the following lines.
*
* So "TTT", 5, "DDD DDDD DD DDD" might be formatted for this.helpWidth=17 like so:
* TTT DDD DDDD
* DD DDD
*/
formatItem(
term: string,
termWidth: number,
description: string,
helper: Help,
): string;
/** Generate the built-in help text. */
formatHelp(cmd: Command, helper: Help): string;
@@ -267,26 +321,34 @@ export type HelpConfiguration = Partial<Help>;
export interface ParseOptions {
from: 'node' | 'electron' | 'user';
}
export interface HelpContext { // optional parameter for .help() and .outputHelp()
export interface HelpContext {
// optional parameter for .help() and .outputHelp()
error: boolean;
}
export interface AddHelpTextContext { // passed to text function used with .addHelpText()
export interface AddHelpTextContext {
// passed to text function used with .addHelpText()
error: boolean;
command: Command;
}
export interface OutputConfiguration {
writeOut?(str: string): void;
writeErr?(str: string): void;
getOutHelpWidth?(): number;
getErrHelpWidth?(): number;
outputError?(str: string, write: (str: string) => void): void;
getOutHelpWidth?(): number;
getErrHelpWidth?(): number;
getOutHasColors?(): boolean;
getErrHasColors?(): boolean;
stripColor?(str: string): string;
}
export type AddHelpTextPosition = 'beforeAll' | 'before' | 'after' | 'afterAll';
export type HookEvent = 'preSubcommand' | 'preAction' | 'postAction';
// The source is a string so author can define their own too.
export type OptionValueSource = LiteralUnion<'default' | 'config' | 'env' | 'cli' | 'implied', string> | undefined;
export type OptionValueSource =
| LiteralUnion<'default' | 'config' | 'env' | 'cli' | 'implied', string>
| undefined;
export type OptionValues = Record<string, any>;
@@ -334,7 +396,10 @@ export class Command {
* @param opts - configuration options
* @returns new command
*/
command(nameAndArgs: string, opts?: CommandOptions): ReturnType<this['createCommand']>;
command(
nameAndArgs: string,
opts?: CommandOptions,
): ReturnType<this['createCommand']>;
/**
* Define a command, implemented in a separate executable file.
*
@@ -353,7 +418,11 @@ export class Command {
* @param opts - configuration options
* @returns `this` command for chaining
*/
command(nameAndArgs: string, description: string, opts?: ExecutableCommandOptions): this;
command(
nameAndArgs: string,
description: string,
opts?: ExecutableCommandOptions,
): this;
/**
* Factory routine to create a new unattached command.
@@ -394,7 +463,12 @@ export class Command {
*
* @returns `this` command for chaining
*/
argument<T>(flags: string, description: string, fn: (value: string, previous: T) => T, defaultValue?: T): this;
argument<T>(
flags: string,
description: string,
fn: (value: string, previous: T) => T,
defaultValue?: T,
): this;
argument(name: string, description?: string, defaultValue?: unknown): this;
/**
@@ -419,23 +493,38 @@ export class Command {
arguments(names: string): this;
/**
* Override default decision whether to add implicit help command.
* Customise or override default help command. By default a help command is automatically added if your command has subcommands.
*
* @example
* ```ts
* program.helpCommand('help [cmd]');
* program.helpCommand('help [cmd]', 'show help');
* program.helpCommand(false); // suppress default help command
* program.helpCommand(true); // add help command even if no subcommands
* ```
* addHelpCommand() // force on
* addHelpCommand(false); // force off
* addHelpCommand('help [cmd]', 'display help for [cmd]'); // force on with custom details
* ```
*
* @returns `this` command for chaining
*/
addHelpCommand(enableOrNameAndArgs?: string | boolean, description?: string): this;
helpCommand(nameAndArgs: string, description?: string): this;
helpCommand(enable: boolean): this;
/**
* Add prepared custom help command.
*/
addHelpCommand(cmd: Command): this;
/** @deprecated since v12, instead use helpCommand */
addHelpCommand(nameAndArgs: string, description?: string): this;
/** @deprecated since v12, instead use helpCommand */
addHelpCommand(enable?: boolean): this;
/**
* Add hook for life cycle event.
*/
hook(event: HookEvent, listener: (thisCommand: Command, actionCommand: Command) => void | Promise<void>): this;
hook(
event: HookEvent,
listener: (
thisCommand: Command,
actionCommand: Command,
) => void | Promise<void>,
): this;
/**
* Register callback to use as replacement for calling process.exit.
@@ -513,7 +602,7 @@ export class Command {
*
* @returns `this` command for chaining
*/
action(fn: (...args: any[]) => void | Promise<void>): this;
action(fn: (this: this, ...args: any[]) => void | Promise<void>): this;
/**
* Define option with `flags`, `description`, and optional argument parsing function or `defaultValue` or both.
@@ -528,17 +617,31 @@ export class Command {
* ```js
* program
* .option('-p, --pepper', 'add pepper')
* .option('-p, --pizza-type <TYPE>', 'type of pizza') // required option-argument
* .option('--pt, --pizza-type <TYPE>', 'type of pizza') // required option-argument
* .option('-c, --cheese [CHEESE]', 'add extra cheese', 'mozzarella') // optional option-argument with default
* .option('-t, --tip <VALUE>', 'add tip to purchase cost', parseFloat) // custom parse function
* ```
*
* @returns `this` command for chaining
*/
option(flags: string, description?: string, defaultValue?: string | boolean | string[]): this;
option<T>(flags: string, description: string, parseArg: (value: string, previous: T) => T, defaultValue?: T): this;
option(
flags: string,
description?: string,
defaultValue?: string | boolean | string[],
): this;
option<T>(
flags: string,
description: string,
parseArg: (value: string, previous: T) => T,
defaultValue?: T,
): this;
/** @deprecated since v7, instead use choices or a custom function */
option(flags: string, description: string, regexp: RegExp, defaultValue?: string | boolean | string[]): this;
option(
flags: string,
description: string,
regexp: RegExp,
defaultValue?: string | boolean | string[],
): this;
/**
* Define a required option, which must have a value after parsing. This usually means
@@ -546,10 +649,24 @@ export class Command {
*
* The `flags` string contains the short and/or long flags, separated by comma, a pipe or space.
*/
requiredOption(flags: string, description?: string, defaultValue?: string | boolean | string[]): this;
requiredOption<T>(flags: string, description: string, parseArg: (value: string, previous: T) => T, defaultValue?: T): this;
requiredOption(
flags: string,
description?: string,
defaultValue?: string | boolean | string[],
): this;
requiredOption<T>(
flags: string,
description: string,
parseArg: (value: string, previous: T) => T,
defaultValue?: T,
): this;
/** @deprecated since v7, instead use choices or a custom function */
requiredOption(flags: string, description: string, regexp: RegExp, defaultValue?: string | boolean | string[]): this;
requiredOption(
flags: string,
description: string,
regexp: RegExp,
defaultValue?: string | boolean | string[],
): this;
/**
* Factory routine to create a new unattached option.
@@ -574,7 +691,9 @@ export class Command {
* @returns `this` command for chaining
*/
storeOptionsAsProperties<T extends OptionValues>(): this & T;
storeOptionsAsProperties<T extends OptionValues>(storeAsProperties: true): this & T;
storeOptionsAsProperties<T extends OptionValues>(
storeAsProperties: true,
): this & T;
storeOptionsAsProperties(storeAsProperties?: boolean): this;
/**
@@ -590,7 +709,11 @@ export class Command {
/**
* Store option value and where the value came from.
*/
setOptionValueWithSource(key: string, value: unknown, source: OptionValueSource): this;
setOptionValueWithSource(
key: string,
value: unknown,
source: OptionValueSource,
): this;
/**
* Get source of option value.
@@ -598,7 +721,7 @@ export class Command {
getOptionValueSource(key: string): OptionValueSource | undefined;
/**
* Get source of option value. See also .optsWithGlobals().
* Get source of option value. See also .optsWithGlobals().
*/
getOptionValueSourceWithGlobals(key: string): OptionValueSource | undefined;
@@ -654,43 +777,72 @@ export class Command {
/**
* Parse `argv`, setting options and invoking commands when defined.
*
* The default expectation is that the arguments are from node and have the application as argv[0]
* and the script being run in argv[1], with user parameters after that.
* Use parseAsync instead of parse if any of your action handlers are async.
*
* Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!
*
* Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:
* - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that
* - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged
* - `'user'`: just user arguments
*
* @example
* ```
* program.parse(process.argv);
* program.parse(); // implicitly use process.argv and auto-detect node vs electron conventions
* program.parse(); // parse process.argv and auto-detect electron and special node flags
* program.parse(process.argv); // assume argv[0] is app and argv[1] is script
* program.parse(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]
* ```
*
* @returns `this` command for chaining
*/
parse(argv?: readonly string[], options?: ParseOptions): this;
parse(argv?: readonly string[], parseOptions?: ParseOptions): this;
/**
* Parse `argv`, setting options and invoking commands when defined.
*
* Use parseAsync instead of parse if any of your action handlers are async. Returns a Promise.
* Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!
*
* The default expectation is that the arguments are from node and have the application as argv[0]
* and the script being run in argv[1], with user parameters after that.
* Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:
* - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that
* - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged
* - `'user'`: just user arguments
*
* @example
* ```
* program.parseAsync(process.argv);
* program.parseAsync(); // implicitly use process.argv and auto-detect node vs electron conventions
* program.parseAsync(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]
* await program.parseAsync(); // parse process.argv and auto-detect electron and special node flags
* await program.parseAsync(process.argv); // assume argv[0] is app and argv[1] is script
* await program.parseAsync(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]
* ```
*
* @returns Promise
*/
parseAsync(argv?: readonly string[], options?: ParseOptions): Promise<this>;
parseAsync(
argv?: readonly string[],
parseOptions?: ParseOptions,
): Promise<this>;
/**
* Called the first time parse is called to save state and allow a restore before subsequent calls to parse.
* Not usually called directly, but available for subclasses to save their custom state.
*
* This is called in a lazy way. Only commands used in parsing chain will have state saved.
*/
saveStateBeforeParse(): void;
/**
* Restore state before parse for calls after the first.
* Not usually called directly, but available for subclasses to save their custom state.
*
* This is called in a lazy way. Only commands used in parsing chain will have state restored.
*/
restoreStateBeforeParse(): void;
/**
* Parse options from `argv` removing known options,
* and return argv split into operands and unknown arguments.
*
* Side effects: modifies command by storing options. Does not reset state if called again.
*
* argv => operands, unknown
* --known kkk op => [op], []
* op --known kkk => [op], []
@@ -838,6 +990,12 @@ export class Command {
*/
helpOption(flags?: string | boolean, description?: string): this;
/**
* Supply your own option to use for the built-in help option.
* This is an alternative to using helpOption() to customise the flags and description etc.
*/
addHelpOption(option: Option): this;
/**
* Output help information and exit.
*
@@ -854,7 +1012,10 @@ export class Command {
* and 'beforeAll' or 'afterAll' to affect this command and all its subcommands.
*/
addHelpText(position: AddHelpTextPosition, text: string): this;
addHelpText(position: AddHelpTextPosition, text: (context: AddHelpTextContext) => string): this;
addHelpText(
position: AddHelpTextPosition,
text: (context: AddHelpTextContext) => string,
): this;
/**
* Add a listener (callback) for when events occur. (Implemented using EventEmitter.)