Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update for Commander v11.1.0 #48

Merged
merged 7 commits into from Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 24 additions & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,26 @@ The version numbering does not follow semantic versioning but instead aligns wit
<!-- markdownlint-disable MD024 -->
<!-- markdownlint-disable MD004 -->

## [11.1.0] (2023-10-15)

### Added

- `Option` properties: `envVar`, `presetArg` ([#48])
- `Argument` properties: `argChoices`, `defaultValue`, `defaultValueDescription` ([#48])
- `Command` properties: `options`, `registeredArguments` ([#50])

### Changed

- `commands` property of `Command` is now readonly ([#48])
- update `peerDependencies` to `commander@11.1.x` ([#48])

### Fixed

- remove unused `Option.optionFlags` property ([#48])
- add that `Command.version()` can also be used as getter ([#48])
- add null return type to `Commands.executableDir()`, for when not configured ([#48])
- preserve option typings when adding arguments to `Command` ([#49])

## [11.0.0] (2023-06-16)

### Changed
Expand Down Expand Up @@ -113,6 +133,7 @@ The version numbering does not follow semantic versioning but instead aligns wit
- inferred types for `.action()`
- inferred types for `.opts()`

[11.1.0]: https://github.com/commander-js/extra-typings/compare/v11.0.0...v11.1.0
[11.0.0]: https://github.com/commander-js/extra-typings/compare/v10.0.3...v11.0.0
[10.0.3]: https://github.com/commander-js/extra-typings/compare/v10.0.2...v10.0.3
[10.0.2]: https://github.com/commander-js/extra-typings/compare/v10.0.1...v10.0.2
Expand All @@ -132,3 +153,6 @@ The version numbering does not follow semantic versioning but instead aligns wit
[#29]: https://github.com/commander-js/extra-typings/pull/29
[#31]: https://github.com/commander-js/extra-typings/pull/31
[#33]: https://github.com/commander-js/extra-typings/pull/33
[#48]: https://github.com/commander-js/extra-typings/pull/48
[#49]: https://github.com/commander-js/extra-typings/pull/49
[#50]: https://github.com/commander-js/extra-typings/pull/50
75 changes: 28 additions & 47 deletions index.d.ts
Expand Up @@ -212,7 +212,10 @@ export class CommanderError extends Error {
description: string;
required: boolean;
variadic: boolean;

defaultValue?: any;
defaultValueDescription?: string;
argChoices?: string[];

/**
* Initialize a new command argument with the given name and description.
* The default is that the argument is required, and you can explicitly
Expand Down Expand Up @@ -259,12 +262,13 @@ export class CommanderError extends Error {
optional: boolean; // A value is optional when the option is specified.
variadic: boolean;
mandatory: boolean; // The option must have a value after parsing, which usually means it must be specified on command line.
optionFlags: string;
short?: string;
long?: string;
negate: boolean;
defaultValue?: any;
defaultValueDescription?: string;
presetArg?: unknown;
envVar?: string;
parseArg?: <T>(value: string, previous: T) => T;
hidden: boolean;
argChoices?: string[];
Expand Down Expand Up @@ -446,14 +450,12 @@ export class CommanderError extends Error {
// The source is a string so author can define their own too.
export type OptionValueSource = LiteralUnion<'default' | 'config' | 'env' | 'cli' | 'implied', string> | undefined;

export interface OptionValues {
[key: string]: unknown;
}
export type OptionValues = Record<string, unknown>;

export class Command<Args extends any[] = [], Opts extends OptionValues = {}> {
args: string[];
processedArgs: Args;
commands: CommandUnknownOpts[];
readonly commands: readonly CommandUnknownOpts[];
readonly options: readonly Option[];
readonly registeredArguments: readonly Argument[];
parent: CommandUnknownOpts | null;
Expand All @@ -469,7 +471,10 @@ export class CommanderError extends Error {
* You can optionally supply the flags and description to override the defaults.
*/
version(str: string, flags?: string, description?: string): this;

/**
* Get the program version.
*/
version(): string | undefined;
/**
* Define a command, implemented using an action handler.
*
Expand Down Expand Up @@ -681,45 +686,21 @@ export class CommanderError extends Error {
action(fn: (...args: [...Args, Opts, this]) => void | Promise<void>): this;

/**
* Define option with `flags`, `description` and optional
* coercion `fn`.
* Define option with `flags`, `description`, and optional argument parsing function or `defaultValue` or both.
*
* The `flags` string contains the short and/or long flags,
* separated by comma, a pipe or space. The following are all valid
* all will output this way when `--help` is used.
* The `flags` string contains the short and/or long flags, separated by comma, a pipe or space. A required
* option-argument is indicated by `<>` and an optional option-argument by `[]`.
*
* "-p, --pepper"
* "-p|--pepper"
* "-p --pepper"
* See the README for more details, and see also addOption() and requiredOption().
*
* @example
* ```
* // simple boolean defaulting to false
* program.option('-p, --pepper', 'add pepper');
*
* --pepper
* program.pepper
* // => Boolean
*
* // simple boolean defaulting to true
* program.option('-C, --no-cheese', 'remove cheese');
*
* program.cheese
* // => true
*
* --no-cheese
* program.cheese
* // => false
*
* // required argument
* program.option('-C, --chdir <path>', 'change the working directory');
*
* --chdir /tmp
* program.chdir
* // => "/tmp"
*
* // optional argument
* program.option('-c, --cheese [type]', 'add cheese [marble]');
* ```js
* program
* .option('-p, --pepper', 'add pepper')
* .option('-p, --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
Expand All @@ -729,9 +710,9 @@ export class CommanderError extends Error {
option<S extends string, DefaultT extends string | boolean | string[] | []>(
usage: S, description?: string, defaultValue?: DefaultT): Command<Args, InferOptions<Opts, S, DefaultT, undefined, false>>;
option<S extends string, T>(
usage: S, description: string, fn: (value: string, previous: T) => T): Command<Args, InferOptions<Opts, S, undefined, T, false>>;
usage: S, description: string, parseArg: (value: string, previous: T) => T): Command<Args, InferOptions<Opts, S, undefined, T, false>>;
option<S extends string, T>(
usage: S, description: string, fn: (value: string, previous: T) => T, defaultValue?: T): Command<Args, InferOptions<Opts, S, T, T, false>>;
usage: S, description: string, parseArg: (value: string, previous: T) => T, defaultValue?: T): Command<Args, InferOptions<Opts, S, T, T, false>>;

/**
* Define a required option, which must have a value after parsing. This usually means
Expand All @@ -744,9 +725,9 @@ export class CommanderError extends Error {
requiredOption<S extends string, DefaultT extends string | boolean | string[]>(
usage: S, description?: string, defaultValue?: DefaultT): Command<Args, InferOptions<Opts, S, DefaultT, undefined, true>>;
requiredOption<S extends string, T>(
usage: S, description: string, fn: (value: string, previous: T) => T): Command<Args, InferOptions<Opts, S, undefined, T, true>>;
usage: S, description: string, parseArg: (value: string, previous: T) => T): Command<Args, InferOptions<Opts, S, undefined, T, true>>;
requiredOption<S extends string, T, D extends T>(
usage: S, description: string, fn: (value: string, previous: T) => T, defaultValue?: D): Command<Args, InferOptions<Opts, S, D, T, true>>;
usage: S, description: string, parseArg: (value: string, previous: T) => T, defaultValue?: D): Command<Args, InferOptions<Opts, S, D, T, true>>;

/**
* Factory routine to create a new unattached option.
Expand Down Expand Up @@ -920,7 +901,7 @@ export class CommanderError extends Error {

description(str: string): this;
/** @deprecated since v8, instead use .argument to add command argument with description */
description(str: string, argsDescription: {[argName: string]: string}): this;
description(str: string, argsDescription: Record<string, string>): this;
/**
* Get the description.
*/
Expand Down Expand Up @@ -1017,7 +998,7 @@ export class CommanderError extends Error {
/**
* Get the executable search directory.
*/
executableDir(): string;
executableDir(): string | null;

/**
* Output help information for this command.
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "@commander-js/extra-typings",
"version": "11.0.0",
"version": "11.1.0",
"description": "Infer strong typings for commander options and action handlers",
"main": "index.js",
"scripts": {
Expand Down Expand Up @@ -45,7 +45,7 @@
]
},
"peerDependencies": {
"commander": "11.0.x"
"commander": "11.1.x"
},
"devDependencies": {
"@types/jest": "^29.2.6",
Expand Down
27 changes: 24 additions & 3 deletions tests/commander.test-d.ts
Expand Up @@ -40,7 +40,7 @@ expectType<commander.Argument>(commander.createArgument('<foo>'));
expectType<string[]>(program.args);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
expectType<[]>(program.processedArgs);
expectType<commander.CommandUnknownOpts[]>(program.commands);
expectType<readonly commander.CommandUnknownOpts[]>(program.commands);
expectType<readonly commander.Option[]>(program.options);
expectType<readonly commander.Argument[]>(program.registeredArguments);
expectType<commander.CommandUnknownOpts | null>(program.parent);
Expand All @@ -49,6 +49,7 @@ expectType<commander.CommandUnknownOpts | null>(program.parent);
expectChainedCommand(program.version('1.2.3'));
expectChainedCommand(program.version('1.2.3', '-r,--revision'));
expectChainedCommand(program.version('1.2.3', '-r,--revision', 'show revision information'));
expectType<string | undefined>(program.version());

// command (and CommandOptions)
expectChainedCommand(program.command('action'));
Expand Down Expand Up @@ -294,7 +295,7 @@ expectChainedCommand(program.nameFromFilename(__filename));

// executableDir
expectChainedCommand(program.executableDir(__dirname));
expectType<string>(program.executableDir());
expectType<string | null>(program.executableDir());

// outputHelp
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
Expand Down Expand Up @@ -416,9 +417,26 @@ expectType<string>(helper.wrap('a b c', 50, 3));

expectType<string>(helper.formatHelp(helperCommand, helper));

// Option methods
// Option properties

const baseOption = new commander.Option('-f,--foo', 'foo description');
expectType<string>(baseOption.flags);
expectType<string>(baseOption.description);
expectType<boolean>(baseOption.required);
expectType<boolean>(baseOption.optional);
expectType<boolean>(baseOption.variadic);
expectType<boolean>(baseOption.mandatory);
expectType<string | undefined>(baseOption.short);
expectType<string | undefined>(baseOption.long);
expectType<boolean>(baseOption.negate);
expectType<any>(baseOption.defaultValue);
expectType<string | undefined>(baseOption.defaultValueDescription);
expectType<unknown>(baseOption.presetArg);
expectType<string | undefined>(baseOption.envVar);
expectType<boolean>(baseOption.hidden);
expectType<string[] | undefined>(baseOption.argChoices);

// Option methods

// default
expectType<commander.Option>(baseOption.default(3));
Expand Down Expand Up @@ -472,6 +490,9 @@ const baseArgument = new commander.Argument('<foo');
expectType<string>(baseArgument.description);
expectType<boolean>(baseArgument.required);
expectType<boolean>(baseArgument.variadic);
expectType<any>(baseArgument.defaultValue);
expectType<string | undefined>(baseArgument.defaultValueDescription);
expectType<string[] | undefined>(baseArgument.argChoices);

// Argument methods

Expand Down