From 4b75c375b5b9dbf57889a35137133754bf20ea39 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Sat, 24 Jun 2017 10:42:11 +0200 Subject: [PATCH 1/4] feat(typings): add typings to support for TypeScript in favor of `@types/commander` --- package.json | 9 +- tsconfig.json | 20 +++ typings/commander-tests.ts | 96 ++++++++++++ typings/index.d.ts | 289 +++++++++++++++++++++++++++++++++++++ 4 files changed, 411 insertions(+), 3 deletions(-) create mode 100644 tsconfig.json create mode 100644 typings/commander-tests.ts create mode 100644 typings/index.d.ts diff --git a/package.json b/package.json index cc0ba957d..34d2096d7 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,12 @@ }, "devDependencies": { "should": ">= 0.0.1 <9.0.0", - "sinon": ">=1.17.1" + "sinon": ">=1.17.1", + "typescript": "^2.3.4" }, "scripts": { - "test": "make test" + "test": "make test && npm run test-typings", + "test-typings": "node_modules/typescript/bin/tsc -p tsconfig.json" }, "main": "index", "engines": { @@ -30,5 +32,6 @@ ], "dependencies": { "graceful-readlink": ">= 1.0.0" - } + }, + "typings": "typings/index.d.ts" } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..dee4c88b9 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": false, + "types": [ + "node" + ], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "typings/index.d.ts", + "typings/commander-tests.ts" + ] +} \ No newline at end of file diff --git a/typings/commander-tests.ts b/typings/commander-tests.ts new file mode 100644 index 000000000..e4d68d3f5 --- /dev/null +++ b/typings/commander-tests.ts @@ -0,0 +1,96 @@ +import * as program from './index'; + +interface ExtendedOptions extends program.CommandOptions { + isNew: any; +} + +const commandInstance = new program.Command('-f'); +const optionsInstance = new program.Option('-f'); + +program + .version('0.0.1') + .option('-p, --peppers', 'Add peppers') + .option('-P, --pineapple', 'Add pineapple') + .option('-b, --bbq', 'Add bbq sauce') + .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') + .parse(process.argv); + +console.log('you ordered a pizza with:'); +if (program['peppers']) console.log(' - peppers'); +if (program['pineapple']) console.log(' - pineapple'); +if (program['bbq']) console.log(' - bbq'); +console.log(' - %s cheese', program['cheese']); + +function range(val: string) { + return val.split('..').map(Number); +} + +function list(val: string) { + return val.split(','); +} + +function collect(val: string, memo: string[]) { + memo.push(val); + return memo; +} + +function increaseVerbosity(v: any, total: number) { + return total + 1; +} + +program + .version('0.0.1') + .usage('[options] ') + .option('-i, --integer ', 'An integer argument', parseInt) + .option('-f, --float ', 'A float argument', parseFloat) + .option('-r, --range ..', 'A range', range) + .option('-l, --list ', 'A list', list) + .option('-o, --optional [value]', 'An optional value') + .option('-c, --collect [value]', 'A repeatable value', collect, []) + .option('-v, --verbose', 'A value that can be increased', increaseVerbosity, 0) + .parse(process.argv); + +console.log(' int: %j', program['integer']); +console.log(' float: %j', program['float']); +console.log(' optional: %j', program['optional']); +program['range'] = program['range'] || []; +console.log(' range: %j..%j', program['range'][0], program['range'][1]); +console.log(' list: %j', program['list']); +console.log(' collect: %j', program['collect']); +console.log(' verbosity: %j', program['verbose']); +console.log(' args: %j', program['args']); + +program + .version('0.0.1') + .option('-f, --foo', 'enable some foo') + .option('-b, --bar', 'enable some bar') + .option('-B, --baz', 'enable some baz'); + +// must be before .parse() since +// node's emit() is immediate + +program.on('--help', () => { + console.log(' Examples:'); + console.log(''); + console.log(' $ custom-help --help'); + console.log(' $ custom-help -h'); + console.log(''); +}); + +program + .command('allow-unknown-option') + .allowUnknownOption() + .action(() => { + console.log('unknown option is allowed'); + }); + +program + .version('0.0.1') + .arguments(' [env]') + .action((cmd, env) => { + console.log(cmd, env); + }); + +program.parse(process.argv); + +console.log('stuff'); \ No newline at end of file diff --git a/typings/index.d.ts b/typings/index.d.ts new file mode 100644 index 000000000..edea38a30 --- /dev/null +++ b/typings/index.d.ts @@ -0,0 +1,289 @@ +// Type definitions for commander 2.9 +// Project: https://github.com/visionmedia/commander.js +// Definitions by: Alan Agius , Marcelo Dezem , vvakame +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare class Option { + flags: string; + required: boolean; + optional: boolean; + bool: boolean; + short?: string; + long: string; + description: string; + + /** + * Initialize a new `Option` with the given `flags` and `description`. + * + * @param {string} flags + * @param {string} [description] + */ + constructor(flags: string, description?: string); +} + +declare class Command extends NodeJS.EventEmitter { + [key: string]: any; + + args: string[]; + + /** + * Initialize a new `Command`. + * + * @param {string} [name] + */ + constructor(name?: string); + + /** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {string} str + * @param {string} [flags] + * @returns {Command} for chaining + */ + version(str: string, flags?: string): Command; + + /** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * @example + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function() { + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd) { + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('teardown [otherDirs...]') + * .description('run teardown commands') + * .action(function(dir, otherDirs) { + * console.log('dir "%s"', dir); + * if (otherDirs) { + * otherDirs.forEach(function (oDir) { + * console.log('dir "%s"', oDir); + * }); + * } + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env) { + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {string} name + * @param {string} [desc] for git-style sub-commands + * @param {CommandOptions} [opts] command options + * @returns {Command} the new command + */ + command(name: string, desc?: string, opts?: commander.CommandOptions): Command; + + /** + * Define argument syntax for the top-level command. + * + * @param {string} desc + * @returns {Command} for chaining + */ + arguments(desc: string): Command; + + /** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {string[]} args + * @returns {Command} for chaining + */ + parseExpectedArgs(args: string[]): Command; + /** + * Register callback `fn` for the command. + * + * @example + * program + * .command('help') + * .description('display verbose help') + * .action(function() { + * // output help here + * }); + * + * @param {(...args: any[]) => void} fn + * @returns {Command} for chaining + */ + action(fn: (...args: any[]) => void): Command; + + /** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + * @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 ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {string} flags + * @param {string} [description] + * @param {((arg1: any, arg2: any) => void) | RegExp} [fn] function or default + * @param {*} [defaultValue] + * @returns {Command} for chaining + */ + option(flags: string, description?: string, fn?: ((arg1: any, arg2: any) => void) | RegExp, defaultValue?: any): Command; + option(flags: string, description?: string, defaultValue?: any): Command; + + /** + * Allow unknown options on the command line. + * + * @param {boolean} [arg] if `true` or omitted, no error will be thrown for unknown options. + * @returns {Command} for chaining + */ + allowUnknownOption(arg?: boolean): Command; + + /** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {string[]} argv + * @returns {Command} for chaining + */ + parse(argv: string[]): Command; + + /** + * Parse options from `argv` returning `argv` void of these options. + * + * @param {string[]} argv + * @returns {ParseOptionsResult} + */ + parseOptions(argv: string[]): commander.ParseOptionsResult; + + /** + * Return an object containing options as key-value pairs + * + * @returns {{[key: string]: string}} + */ + opts(): { [key: string]: string }; + + /** + * Set the description to `str`. + * + * @param {string} str + * @return {(Command | string)} + */ + description(str: string): Command; + description(): string; + + /** + * Set an alias for the command. + * + * @param {string} alias + * @return {(Command | string)} + */ + alias(alias: string): Command; + alias(): string; + + /** + * Set or get the command usage. + * + * @param {string} str + * @return {(Command | string)} + */ + usage(str: string): Command; + usage(): string; + + /** + * Get the name of the command. + * + * @return {string} + */ + name(): string; + + /** + * Output help information for this command. + * + * @param {() => void} [cb] Callback method + */ + outputHelp(cb?: () => void): void; + + /** Output help information and exit. */ + help(): void; +} + +declare namespace commander { + + interface CommandOptions { + noHelp?: boolean; + isDefault?: boolean; + } + + interface ParseOptionsResult { + args: string[]; + unknown: string[]; + } + + interface CommanderStatic extends Command { + Command: typeof Command; + Option: typeof Option; + CommandOptions: CommandOptions; + ParseOptionsResult: ParseOptionsResult; + } + +} + +declare const commander: commander.CommanderStatic; +export = commander; \ No newline at end of file From 0822eb9d1bb7b7f26f4661a0a304c697f3768cd0 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Sat, 24 Jun 2017 10:48:53 +0200 Subject: [PATCH 2/4] packages: add `@types/node` --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 34d2096d7..ab63150ef 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "index.js" ], "dependencies": { + "@types/node": "^8.0.2", "graceful-readlink": ">= 1.0.0" }, "typings": "typings/index.d.ts" From 43362c958f620f24f5b499a9bf59d0d13cb581e6 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Sat, 24 Jun 2017 10:50:37 +0200 Subject: [PATCH 3/4] typings: remove definitions statement --- typings/index.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index edea38a30..d870be31f 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1,7 +1,6 @@ // Type definitions for commander 2.9 // Project: https://github.com/visionmedia/commander.js // Definitions by: Alan Agius , Marcelo Dezem , vvakame -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped declare class Option { flags: string; From 57e043eebffe17e0c04d47dde0a049443ea86209 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Sun, 23 Jul 2017 17:05:29 +0200 Subject: [PATCH 4/4] packages: use `@types/node` `7.0.39` --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 77d8e42ed..8cd9da652 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "index.js" ], "dependencies": { - "@types/node": "^8.0.2" + "@types/node": "^7.0.39" }, "devDependencies": { "should": "^11.2.1",