-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add proof of concept Command type without option properties * Add program * Add tests for exported global, and start refactoring existing tests * Methodically test syntax, instead of just lots of README and example code
- Loading branch information
1 parent
a3f453f
commit 3cf8cff
Showing
2 changed files
with
168 additions
and
141 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,161 +1,187 @@ | ||
import * as program from './index'; | ||
|
||
interface ExtendedOptions extends program.CommandOptions { | ||
isNew: any; | ||
} | ||
|
||
const commandInstance = new program.Command('-f'); | ||
const optionsInstance = new program.Option('-f'); | ||
const errorInstance = new program.CommanderError(1, 'code', 'message'); | ||
|
||
const name = program.name(); | ||
import * as commander from './index'; | ||
import { Script } from 'vm'; | ||
|
||
// Test Commander usage with TypeScript. | ||
// This is NOT a usable program, just used to test for compile errors! | ||
|
||
// Defined stricter type, as the options as properties `[key: string]: any` | ||
// makes the type checking very weak. | ||
// https://github.com/Microsoft/TypeScript/issues/25987#issuecomment-441224690 | ||
type KnownKeys<T> = { | ||
[K in keyof T]: string extends K ? never : number extends K ? never : K | ||
} extends {[_ in keyof T]: infer U} ? ({} extends U ? never : U) : never; | ||
type CommandWithoutOptionsAsProperties = Pick<commander.Command, KnownKeys<commander.Command>>; | ||
|
||
const program: CommandWithoutOptionsAsProperties = commander.program; | ||
const programWithOptions = commander.program; | ||
// program.silly; // <-- Error, hurrah! | ||
|
||
// Check for exported global Command objects | ||
const importedDefaultProgram: commander.Command = commander; | ||
const importedExplicitProgram: commander.Command = commander.program; | ||
|
||
// Check export classes exist | ||
const commandInstance1 = new commander.Command(); | ||
const commandInstance2 = new commander.Command('name'); | ||
const optionsInstance = new commander.Option('-f'); | ||
const errorInstance = new commander.CommanderError(1, 'code', 'message'); | ||
|
||
// Command properties | ||
console.log(programWithOptions.someOption); | ||
console.log(programWithOptions['someOption']); | ||
const theArgs = program.args; | ||
const theCommands: commander.Command[] = program.commands; | ||
|
||
// version | ||
const versionThis1: commander.Command = program.version('1.2.3'); | ||
const versionThis2: commander.Command = program.version('1.2.3', '-r,--revision'); | ||
const versionThis3: commander.Command = program.version('1.2.3', '-r,--revision', 'show revision information'); | ||
|
||
// command (and CommandOptions) | ||
const commandNew1: commander.Command = program.command('action'); | ||
const commandNew2: commander.Command = program.command('action', { isDefault: true, noHelp: true }); | ||
const commandThis1: commander.Command = program.command('exec', 'exec description'); | ||
const commandThis2: commander.Command = program.command('exec', 'exec description', { isDefault: true, noHelp: true, executableFile: 'foo' }); | ||
|
||
// addCommand | ||
const addCommandThis: commander.Command = program.addCommand(new commander.Command('abc')); | ||
|
||
// arguments | ||
const argumentsThis: commander.Command = program.arguments('<cmd> [env]') | ||
|
||
// exitOverride | ||
const exitThis1: commander.Command = program.exitOverride(); | ||
const exitThis2: commander.Command = program.exitOverride((err):never => { | ||
return process.exit(err.exitCode); | ||
}); | ||
const exitThis3: commander.Command = program.exitOverride((err):void => { | ||
if (err.code !== 'commander.executeSubCommandAsync') { | ||
throw err; | ||
} else { | ||
// Async callback from spawn events, not useful to throw. | ||
} | ||
}); | ||
|
||
program.storeOptionsAsProperties(true); | ||
program.passCommandToAction(true); | ||
// action | ||
const actionThis1: commander.Command = program.action(() => { }); | ||
const actionThis2: commander.Command = program.action(async () => { }); | ||
|
||
program | ||
.name('set name') | ||
.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); | ||
// option | ||
const optionThis1: commander.Command = program.option('-a,--alpha'); | ||
const optionThis2: commander.Command = program.option('-p, --peppers', 'Add peppers') | ||
const optionThis3: commander.Command = program.option('-s, --string [value]', 'default string', 'value') | ||
const optionThis4: commander.Command = program.option('-b, --boolean', 'default boolean', false); | ||
|
||
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']); | ||
// example coercion functions from README | ||
|
||
function range(val: string) { | ||
return val.split('..').map(Number); | ||
return val.split('..').map(Number); | ||
} | ||
|
||
function list(val: string) { | ||
return val.split(','); | ||
function myParseInt(value: string, dummyPrevious: number) { | ||
return parseInt(value); | ||
} | ||
|
||
function collect(val: string, memo: string[]) { | ||
memo.push(val); | ||
return memo; | ||
function increaseVerbosity(dummyValue: string, previous: number) { | ||
return previous + 1; | ||
} | ||
|
||
function increaseVerbosity(v: any, total: number) { | ||
return total + 1; | ||
function collect(value: string, previous: string[]) { | ||
return previous.concat([value]); | ||
} | ||
|
||
function syncCall() { | ||
console.log("Sync success!"); | ||
function commaSeparatedList(value: string, dummyPrevious: string[]) { | ||
return value.split(','); | ||
} | ||
|
||
async function asyncCall() { | ||
return; | ||
} | ||
|
||
program | ||
.version('0.0.1') | ||
.usage('[options] <file ...>') | ||
.option('-i, --integer <n>', 'An integer argument', parseInt) | ||
.option('-f, --float <n>', 'A float argument', parseFloat) | ||
.option('-r, --range <a>..<b>', 'A range', range) | ||
.option('-l, --list <items>', '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() | ||
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') | ||
.description("description") | ||
.allowUnknownOption() | ||
.action(() => { | ||
console.log('unknown option is allowed'); | ||
}); | ||
|
||
program | ||
.requiredOption('-a,--aaa', 'description') | ||
.requiredOption('-b,--bbb <value>', 'description') | ||
.requiredOption('-c,--ccc [value]', 'description') | ||
.requiredOption('-d,--ddd <value>', 'description', 'default value') | ||
.requiredOption('-e,--eee <value>', 'description', (value, memo) => { return value; }) | ||
.requiredOption('-f,--fff <value>', 'description', (value, memo) => { return value; }, 'starting value') | ||
.requiredOption('-g,--ggg <value>', 'description') | ||
.requiredOption('-G,--no-ggg <value>', 'description for negation'); | ||
|
||
program | ||
.version('0.0.1') | ||
.arguments('<cmd> [env]') | ||
.action((cmd, env) => { | ||
console.log(cmd, env); | ||
}); | ||
|
||
program | ||
.command("name1", "description") | ||
.command("name2", "description", { isDefault:true }); | ||
|
||
program | ||
.command("name3").action(syncCall) | ||
.command("name4").action(asyncCall); | ||
|
||
const preparedCommand = new program.Command('prepared'); | ||
program.addCommand(preparedCommand); | ||
|
||
program | ||
.exitOverride(); | ||
|
||
program.exitOverride((err):never => { | ||
console.log(err.code); | ||
console.log(err.message); | ||
console.log(err.nestedError); | ||
return process.exit(err.exitCode); | ||
}); | ||
const optionThis5: commander.Command = program.option('-f, --float <number>', 'float argument', parseFloat) | ||
const optionThis6: commander.Command = program.option('-f, --float <number>', 'float argument', parseFloat, 3.2) | ||
const optionThis7: commander.Command = program.option('-i, --integer <number>', 'integer argument', myParseInt) | ||
const optionThis8: commander.Command = program.option('-i, --integer <number>', 'integer argument', myParseInt, 5) | ||
const optionThis9: commander.Command = program.option('-v, --verbose', 'verbosity that can be increased', increaseVerbosity, 0) | ||
const optionThis10: commander.Command = program.option('-c, --collect <value>', 'repeatable value', collect, []) | ||
const optionThis11: commander.Command = program.option('-l, --list <items>', 'comma separated list', commaSeparatedList); | ||
|
||
// requiredOption, same tests as option | ||
const requiredOptionThis1: commander.Command = program.requiredOption('-a,--alpha'); | ||
const requiredOptionThis2: commander.Command = program.requiredOption('-p, --peppers', 'Add peppers') | ||
const requiredOptionThis3: commander.Command = program.requiredOption('-s, --string [value]', 'default string', 'value') | ||
const requiredOptionThis4: commander.Command = program.requiredOption('-b, --boolean', 'default boolean', false); | ||
|
||
const requiredOptionThis5: commander.Command = program.requiredOption('-f, --float <number>', 'float argument', parseFloat) | ||
const requiredOptionThis6: commander.Command = program.requiredOption('-f, --float <number>', 'float argument', parseFloat, 3.2) | ||
const requiredOptionThis7: commander.Command = program.requiredOption('-i, --integer <number>', 'integer argument', myParseInt) | ||
const requiredOptionThis8: commander.Command = program.requiredOption('-i, --integer <number>', 'integer argument', myParseInt, 5) | ||
const requiredOptionThis9: commander.Command = program.requiredOption('-v, --verbose', 'verbosity that can be increased', increaseVerbosity, 0) | ||
const requiredOptionThis10: commander.Command = program.requiredOption('-c, --collect <value>', 'repeatable value', collect, []) | ||
const requiredOptionThis11: commander.Command = program.requiredOption('-l, --list <items>', 'comma separated list', commaSeparatedList); | ||
|
||
// storeOptionsAsProperties | ||
const storeOptionsAsPropertiesThis1: commander.Command = program.storeOptionsAsProperties(); | ||
const storeOptionsAsPropertiesThis2: commander.Command = program.storeOptionsAsProperties(false); | ||
|
||
// passCommandToAction | ||
const passCommandToActionThis1: commander.Command = program.passCommandToAction(); | ||
const passCommandToActionThis2: commander.Command = program.passCommandToAction(false); | ||
|
||
// allowUnknownOption | ||
const allowUnknownOptionThis1: commander.Command = program.allowUnknownOption(); | ||
const allowUnknownOptionThis2: commander.Command = program.allowUnknownOption(false); | ||
|
||
// parse | ||
const parseThis1: commander.Command = program.parse(); | ||
const parseThis2: commander.Command = program.parse(process.argv); | ||
const parseThis3: commander.Command = program.parse(['node', 'script.js'], { from: 'node' }); | ||
const parseThis4: commander.Command = program.parse(['node', 'script.js'], { from: 'electron' }); | ||
const parseThis5: commander.Command = program.parse(['--option'], { from: "user" }); | ||
|
||
// parseAsync, same tests as parse | ||
const parseAsyncThis1: Promise<commander.Command> = program.parseAsync(); | ||
const parseAsyncThis2: Promise<commander.Command> = program.parseAsync(process.argv); | ||
const parseAsyncThis3: Promise<commander.Command> = program.parseAsync(['node', 'script.js'], { from: 'node' }); | ||
const parseAsyncThis4: Promise<commander.Command> = program.parseAsync(['node', 'script.js'], { from: 'electron' }); | ||
const parseAsyncThis5: Promise<commander.Command> = program.parseAsync(['--option'], { from: "user" }); | ||
|
||
// parseOptions (and ParseOptionsResult) | ||
const { operands, unknown } = program.parseOptions(['node', 'script.js', 'hello']); | ||
|
||
// opts | ||
const opts = program.opts(); | ||
const optsVal1 = opts.foo; | ||
const opstVale2 = opts['bar']; | ||
|
||
// description | ||
const descriptionThis: commander.Command = program.description("my description"); | ||
const descriptionValue: string = program.description(); | ||
|
||
// alias | ||
const aliasThis: commander.Command = program.alias("my alias"); | ||
const aliasValue: string = program.alias(); | ||
|
||
// usage | ||
const usageThis: commander.Command = program.usage("my usage"); | ||
const usageValue: string = program.usage(); | ||
|
||
// name | ||
const nameThis: commander.Command = program.name("my-name"); | ||
const nameValue: string = program.name(); | ||
|
||
// outputHelp | ||
program.outputHelp(); | ||
program.outputHelp((str: string) => { return str }); | ||
|
||
program.exitOverride((err):void => { | ||
if (err.code !== 'commander.executeSubCommandAsync') { | ||
throw err; | ||
} else { | ||
// Async callback from spawn events, not useful to throw. | ||
} | ||
}); | ||
// help | ||
program.help(); | ||
program.help((str: string) => { return str }); | ||
|
||
program.parse(process.argv); | ||
program.parse(); | ||
program.parse(["foo"], { from: "user" }); | ||
|
||
program.parseAsync(process.argv).then(() => { | ||
console.log('parseAsync success'); | ||
}).catch(err => { | ||
console.log('parseAsync failed'); | ||
}); | ||
// helpInformation | ||
const helpInformnationValue: string = program.helpInformation(); | ||
|
||
program.help(); | ||
program.outputHelp(); | ||
const info = program.helpInformation(); | ||
// helpOption | ||
const helpOptionThis1: commander.Command = program.helpOption('-h,--help'); | ||
const helpOptionThis2: commander.Command = program.helpOption('-h,--help', 'custom description'); | ||
const helpOptionThis3: commander.Command = program.helpOption(undefined, 'custom description'); | ||
|
||
console.log('stuff'); | ||
// on | ||
const onThis: commander.Command = program.on('--help', () => { }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters