A tool for Node.js to make applications easier to write, easier to use.
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
docs/images
lib
test
.gitignore
.npmignore
.travis.yml
CHANGELOG.md
LICENSE
README.md
main.js
package.json

README.md

Admiral-Cli

Admiral-CLI

A tool for Node.js to make applications easier to write, easier to use.

Admiral-CLI is a Command Line Framework (CLI) framework for Node.js. There are other CLI frameworks available for Node.js already, however Admiral adds validation and some callbacks in key places to make apps easier to write. We wanted to create a framework with less configuration but stronger validation.

Configuration should be easy to understand while CLI parameters are strictly validated and appropriate error messages are passed on to the user. A CLI is a user interface, let's treat it like one.

Master: Build Status Coverage Status

Dependencies: Dependency Status devDependency Status

Development: Build Status

This project sponsored in part by:

AerisWeather - Empowering the next generation, aerisweather.com

Installation

NPM

Available via npm.

npm install --save admiral-cli

Tested on NodeJS: v5, v4.1, v0.12 and iojs. See .travis.yml for more info.

Usage

Quick Example:

var Cli = require('admiral-cli'),

var cli = new Cli();
cli
    // Command Groups are for fixed options, like 'commit' and 'checkout' in git
    .commandGroup({
        name: 'cmd',
        description: 'Commands are single words, no - or --s, and are one of the following:',
        commands: [
            new CliCommand({
                name: 'add',
                description: 'The variable cmd will be set to add in this case',
                callback: function (command) {
                    var doSome = 'stuff';
                }
            }),
            new CliCommand({
                name: 'another',
                description: 'A user could also specify another'
            })
        ],
        callback: function commandLevelCallback(command) {
            var theCommandObjThatWasChosen = command;
        },
        required: true
    })
    // Flags are for true/false switches
    .flag({
        name: 'flagName',
        description: 'Flags are single phrases, set as a boolean',
        shortFlag: '-f',
        longFlag: '--flag'
    })
    .flag({
        name: 'notPassed',
        description: "Flags that aren't passed are set as false",
        shortFlag: '-n',
        longFlag: '--notPassed'
    })
    // Options are two parts, a key and a user supplied value.
    .option({
        name: 'optName',
        description: 'Options are two parts, a key and a user supplied value',
        shortFlag: '-o',
        longFlag: '--option',
        type: 'string',
        length: 1
        required: true
    });

//Parse Cli arguments
try {
    cli.parse();
}
catch (error) {
    console.error(error);
    if (error instanceof Cli.InvalidInputError) {
        // User input something wrong, will display help by default.
        process.exit(2);
    }
    else if (error instanceof Cli.ConfigError) {
        console.error('Doh, configured something wrong.', error);
        process.exit(1);
    }
}
//Could call script with cliExample.js add --option myExample -f
//cli.params would be { 'cmd': 'add', 'flagName': true, 'nonPassed': false, 'optName': 'myExample' }

This library is well tested, make sure to check out the tests directory for other examples.

CLI Options

There are some options for configuring Admiral-Cli that may be passed to the constructor.

Option Type (default) Description
scriptName String (null) The name of CLI script, this is automatically parsed, but use this as an override. Used in displaying documentation.
verboseEnabled Boolean (true) Automatically parse -v, -vv, -vvv, and --verbose
helpEnabled Boolean (true) Enable help text output when passing --help
helpOnNoArgs Boolean (true) Enable help text when no arguments are passed
exitOnHelp Boolean (true) Exit after help is run.
allowExtraArgs Boolean (false) If the script should allow extra arguments, throws InvalidInput error by default.

Pass these options as an object to the constructor:

var Cli = require('cli');

var cli = new Cli({
	scriptName: 'theNextBigThing.js',
	verboseEnabled: true
});

parse() and Params

The parse() method parses the command line arguments (or a passed array) with the configured, command groups, flags, and options. This will set the Cli object's params object with keys of the configured properties and the passed variables.

Currently ConfigError errors will be thrown if something is wrong when creating the Cli object. InvalidInput options will be thrown if a parameter isn't passed and is required, also if there is an extra parameter that is passed but wasn't configured.

Commands and Command Groups

A Command Group is a collection of possible Commands. One command can be chosen by the user at a time, per Command Group. Multiple command groups can be added at a time, but order matters.

For example: git push origin One command group would be added for push (and other top level commands like commit and pull), then another command group added for the remotes origin, home-server, etc.

Command Group Options:

Option Type (default) Description
name String (null) Name of the Command Group, used for validation messages
description String (null) Description of this Command Group, used for help text.
commands Commands[] ([]) The set of possible Commands
required Boolean (true) This command is required, one of the Commands must be passed.
callback Function (null) A callback to call when a command from this command group is parsed, function([Cli], [Command])

Command Options:

Option Type (default) Description
name String (null) Name of the Command, used when parsing, so push or commit from the example above.
description String (null) Description of this Command, used for help text.
callback Function (null) A callback to call when a command from this command group is parsed, function([Cli], [Command])

Creating a tree structure for command routing isn't hard, just add more CommandGroups to the first argument (the base Cli) in the callback

var cli = new Cli();

var finalResult;
cli
    .commandGroup({
        name: 'cmd1',
        description: 'main route for the program',
        commands: [
            new Command({
                name: 'test1',
                description: 'The first command option',
                callback: function(command) {
                    // Append additional subgroups when this one is chosen.
                    cli.commandGroup({
                        name: 'test1Sub',
                        description: 'the sub command to test1',
                        commands: [
                            new Command({
                                name: 'foo',
                                description: 'Foo should equal bar',
                                callback: function(command) {
                                    finalResult = 'bar';
                                }
                            })
                        ],
                        required: true
                    });
                }
            }),
            new Command({
                name: 'test2',
                description: 'The second command option'
            })
        ],
        required: true
    });
    
// Calling with: `node ./my-script.sh test1 foo` will set `finalResult` to 'bar'
// The script will also be able to be called with `node ./my-script.sh test2`

Flag

A flag is a single phrase that is set as a boolean and can be passed in any order. Flags that aren't passed are set as false.

For example: rm -f would use the short property of the flag, force. So force could be defined as:

cli.flag({
    name: 'force', 
    description: 'Force removes things, for real', 
    shortFlag: '-f', 
    longFlag: '--force'
});

Would also allow rm --force

Flags can be combined, like rm -rf and options force (defined with '-f') and recursive (defined with -r) would both be true.

Flag Options:

Option Type (default) Description
name String (null) Name of the Flag, used for invalid messages and help text.
description String (null) Description of this Flag, used for help text.
shortFlag String (null) A string starting with "-" and a single character, the shortened flag a user may pass.
longFlag String (null) A string starting with "--" and any number of characters, the long flag a user may pass.
value any (true) The value to assign the resulting output when the flag is passed, defaults to true

Option

Options are key/value pairs, e.g. -n myName. They can be in any order. The have both a short and long version, much like flags, but they require a value after them.

Option Options (ha):

Option Type (default) Description
name String (null) Name of the Option, used for invalid messages and help text.
description String (null) Description of this Option, used for help text.
shortFlag String (null) A string starting with "-" and a single character, the shortened flag a user may pass denoting the next value will be the value(s) of this option.
longFlag String (null) A string starting with "--" and any number of characters, the long flag a user may pass denoting the next value will be the value(s) of this option.
type String ("string") The type of this option, int and float/doubles will be parsed accordingly and error if they do not match the provided type. paths will be turned into absolute paths using the cwd.
length Integer (1) How many space separated arguments are required. -1 is any number (will parse until another flag or command is hit, will return an array) , 1 is a single value, >1 is a fixed number (will return an array)
required Boolean (true) This Option is required, this Option must be provided.
default * (undefined) If this Option isn't required, a default value can be set that will be used in place of a user provided value.

EnvVar

For parsing Environment Variables. Will verify an environment variable with a certain name was provided and will parse/validate it to the desired type.

EnvVar Options:

Option Type (default) Description
name String (null) Name of the EnvVar, the key of the element in process.env, "HELLO_WORLD" for example.
description String (null) Description of this EnvVar, used for help text.
type String ("string") The type of this EnvVar, int and float/doubles will be parsed accordingly and error if they do not match the provided type.
required Boolean (true) This EnvVar is required, this EnvVar must be provided.

Development

Latest feelings:

  • Verbose configuration is good. It takes a little longer to type, but it is so much more understandable later. After not touching the cli params parsing stuff for an app after a while, the old way of doing arguments got confusing.

Ideas from:

Goals:

  • Commands
    • Provide events for command based routing, e.g. git pull origin development
    • Auto-complete on commands (Phase 2)
  • Options
    • Short and long options, e.g. ssh -i ~/key-file.pem
    • Description
    • Required
    • Validation
  • Flags
    • Allow for single flags, e.g. rm -f
    • Combined flags, e.g. rm -rf
  • Order
    • Allow any order for flags and options, but order for commands.
  • Errors
    • InvalidInput Errors
    • Configuration Errors

Contributing

Please feel free to contribute in any way. Feature requests with use cases, bug reports, forks and code contributions are all welcome.