yargs-common-bin
Abstraction bin tool wrap yargs, to provide more convenient usage, support async / generator.
Install
$ npm i yargs-common-bin --save
Build a bin tool for your team
You maybe need a custom xxx-bin to implement more custom features.
Now you can implement a Command sub class to do that.
git
command
Example: Write your own This example will show you how to create a new my-git
tool.
- Full demo: my-git
test/fixtures/my-git├── bin│ └── my-git.js├── command│ ├── remote│ │ ├── add.js│ │ └── remove.js│ ├── clone.js│ └── remote.js├── index.js└── package.json
my-git.js
#!/usr/bin/env node 'use strict'; const Command = ;start;
Main Command
Just extend Command
, and use as your bin start point.
You can use this.yargs
to custom yargs config, see http://yargs.js.org/docs for more detail.
const Command = ;const pkg = ; { superrawArgv; thisusage = 'Usage: my-git <command> [options]'; // load entire command directory this; // or load special command file // this.add(path.join(__dirname, 'test_command.js')); // more custom with `yargs` api, such as you can use `my-git -V` thisyargs; } moduleexports = MainCommand;
CloneCommand
const Command = ; { superrawArgv; thisoptions = depth: type: 'number' description: 'Create a shallow clone with a history truncated to the specified number of commits' ); } * { console; } { return 'Clone a repository into a new directory'; } { return 'command-aliases' 'ca' } moduleexports = CloneCommand;
Run result
$ my-git clone gh://node-modules/common-bin dist --depth=1 git clone gh://node-modules/common-bin to dist with depth 1
Concept
Command
Define the main logic of command
Method:
start()
- start your program, only use once in your bin file.run(context)
- should implement this to provide command handler, will exec when not found sub command.
- Support generator / async function / normal function which return promise.
context
is{ cwd, env, argv, rawArgv }
cwd
-process.cwd()
env
- clone env object fromprocess.env
argv
- argv parse result by yargs,{ _: [ 'start' ], '$0': '/usr/local/bin/common-bin', baseDir: 'simple'}
rawArgv
- the raw argv,[ "--baseDir=simple" ]
load(fullPath)
- register the entire directory to commandsadd(name, target)
- register special command with command name,target
could be full path of file or Class.showHelp()
- print usage message to console.options=
- a setter, shortcut foryargs.options
usage=
- a setter, shortcut foryargs.usage
Properties:
description
- {String} a getter, only show this description when it's a sub command in help consolehelper
- {Object} helper instanceyargs
- {Object} yargs instance for advanced custom usageoptions
- {Object} a setter, set yargs' optionsversion
- {String} customize version, can be defined as a getter to support lazy load.aliases
- {Array} current command aliasesparserOptions
- {Object} controlcontext
parse rule.execArgv
- {Boolean} whether extractexecArgv
tocontext.execArgv
removeAlias
- {Boolean} whether remove alias key fromargv
removeCamelCase
- {Boolean} whether remove camel case key fromargv
You can define options by set this.options
thisoptions = baseDir: alias: 'b' demandOption: true description: 'the target directory' path depth: description: 'level to clone' type: 'number' default: 1 size: description: 'choose a size' choices: 'xs' 's' 'm' 'l' 'xl' ;
You can define version by define this.version
getter:
{ return 'v1.0.0';}
Helper
forkNode(modulePath, args, opt)
- fork child process, wrap with promise and gracefull exitspawn(cmd, args, opt)
- spawn a new process, wrap with promise and gracefull exitnpmInstall(npmCli, name, cwd)
- install node modules, wrap with promise* callFn(fn, args, thisArg)
- call fn, support gernerator / async / normal function return promiseunparseArgv(argv, opts)
- unparse argv and change it to array style
Extend Helper
// index.jsconst Command = ;const helper = ; { superrawArgv; // load sub command this; // custom helper Object; }
Advanced Usage
Single Command
Just need to provide options
and run()
.
const Command = ; { superrawArgv; thisoptions = baseDir: description: 'target directory' ; } * { console; }
Sub Command
Also support sub command such as my-git remote add <name> <url> --tags
.
// test/fixtures/my-git/command/remote.js { // DO NOT forgot to pass params to super superrawArgv; // load sub command for directory this; } * { console; } { return 'Manage set of tracked repositories'; } // test/fixtures/my-git/command/remote/add.js { superrawArgv; thisoptions = tags: type: 'boolean' default: false description: 'imports every tag from the remote repository' ; } * { console; } { return 'Adds a remote named <name> for the repository at <url>'; }
see remote.js for more detail.
Async Support
async { await ; console; } { return 'sleep showcase'; } { return ;}
see async-bin for more detail.