Skip to content

Commit

Permalink
Factory routine to create a new unattached argument (#1497)
Browse files Browse the repository at this point in the history
* Factory routine to create a new unattached argument

* ESM export improvements

* createArgument ESM test

* Add typings for createArgument

* Add tests for createArgument

Co-authored-by: John Gee <john@ruru.gen.nz>
  • Loading branch information
cravler and shadowspawn committed Apr 12, 2021
1 parent 0504945 commit 387b6fc
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 3 deletions.
13 changes: 12 additions & 1 deletion esm.mjs
@@ -1,4 +1,15 @@
import commander from './index.js';

// wrapper to provide named exports for ESM.
export const { program, Option, Command, Argument, CommanderError, InvalidOptionArgumentError, Help, createCommand, createOption } = commander;
export const {
program,
createCommand,
createArgument,
createOption,
CommanderError,
InvalidOptionArgumentError,
Command,
Argument,
Option,
Help
} = commander;
17 changes: 16 additions & 1 deletion index.js
Expand Up @@ -836,6 +836,21 @@ class Command extends EventEmitter {
return this;
};

/**
* Factory routine to create a new unattached argument.
*
* See .argument() for creating an attached argument, which uses this routine to
* create the argument. You can override createArgument to return a custom argument.
*
* @param {string} name
* @param {string} [description]
* @return {Argument} new argument
*/

createArgument(name, description) {
return new Argument(name, description);
};

/**
* Define argument syntax for command.
*
Expand All @@ -852,7 +867,7 @@ class Command extends EventEmitter {
* @return {Command} `this` command for chaining
*/
argument(name, description) {
const argument = new Argument(name, description);
const argument = this.createArgument(name, description);
this.addArgument(argument);
return this;
}
Expand Down
40 changes: 40 additions & 0 deletions tests/command.createArgument.test.js
@@ -0,0 +1,40 @@
const commander = require('../');

class MyArgument extends commander.Argument {
constructor(name, description) {
super(name, description);
this.myProperty = 'MyArgument';
};
}

class MyCommand extends commander.Command {
createArgument(name, description) {
return new MyArgument(name, description);
};

// createCommand for testing .command('sub <file>')
createCommand(name) {
return new MyCommand(name);
}
}

test('when override createArgument then used for argument()', () => {
const program = new MyCommand();
program.argument('<file>');
expect(program._args.length).toEqual(1);
expect(program._args[0].myProperty).toEqual('MyArgument');
});

test('when override createArgument then used for arguments()', () => {
const program = new MyCommand();
program.arguments('<file>');
expect(program._args.length).toEqual(1);
expect(program._args[0].myProperty).toEqual('MyArgument');
});

test('when override createArgument and createCommand then used for argument of command()', () => {
const program = new MyCommand();
const sub = program.command('sub <file>');
expect(sub._args.length).toEqual(1);
expect(sub._args[0].myProperty).toEqual('MyArgument');
});
4 changes: 3 additions & 1 deletion tests/esm-imports-test.mjs
@@ -1,4 +1,4 @@
import { program, Command, Option, Argument, CommanderError, InvalidOptionArgumentError, Help, createCommand, createOption } from '../esm.mjs';
import { program, Command, Option, Argument, CommanderError, InvalidOptionArgumentError, Help, createCommand, createArgument, createOption } from '../esm.mjs';

// Do some simple checks that expected imports are available at runtime.
// Run using `npm run test-esm`.
Expand Down Expand Up @@ -30,6 +30,8 @@ checkClass(new Argument('<file>'), 'Argument');

console.log('Checking createCommand');
check(typeof createCommand === 'function', 'createCommand is function');
console.log('Checking createArgument');
check(typeof createArgument === 'function', 'createArgument is function');
console.log('Checking createOption');
check(typeof createOption === 'function', 'createOption is function');

Expand Down
8 changes: 8 additions & 0 deletions typings/index.d.ts
Expand Up @@ -249,6 +249,14 @@ declare namespace commander {
*/
addCommand(cmd: Command, opts?: CommandOptions): this;

/**
* Factory routine to create a new unattached argument.
*
* See .argument() for creating an attached argument, which uses this routine to
* create the argument. You can override createArgument to return a custom argument.
*/
createArgument(name: string, description?: string): Argument;

/**
* Define argument syntax for command.
*
Expand Down
4 changes: 4 additions & 0 deletions typings/index.test-d.ts
Expand Up @@ -345,3 +345,7 @@ expectType<boolean>(baseArgument.variadic);
// Argument methods
// name
expectType<string>(baseArgument.name());

// createArgument
expectType<commander.Argument>(program.createArgument('<name>'));
expectType<commander.Argument>(program.createArgument('<name>', 'description'));

0 comments on commit 387b6fc

Please sign in to comment.