fh-fhc
Version:
A Command Line Interface for FeedHenry
111 lines (102 loc) • 3.51 kB
JavaScript
var _ = require('underscore');
var ini = require('./ini.js');
/*
@param argsIntoCommand: the argv array
Normalises an argv array, and returns a yargified object
*/
exports.normaliseToYargs = function(argsIntoCommand, cmd) {
argsIntoCommand = _normaliseFlagsAndArs(argsIntoCommand, cmd);
var yargs = require('yargs')(argsIntoCommand);
_setupArgsInIniConfig(yargs);
return yargs;
};
/*
Performs the actual validation
@param yargs: An already set up yargs object, typically the response from normaliseToYargs
@param cmd: Command definition
*/
exports.validate = function(yargs, cmd) {
_setupForValidation(yargs, cmd);
// the return from this is never used, but caling .argv causes validation
return yargs.argv;
};
/*
Returns usage information
@param yargs: An already set up yargs object, typically the response from normaliseToYargs
@param cmd: Command definition
*/
exports.yargsUsage = function(cmd) {
var yargs = new require('yargs')([]); // If not provided, start anew - we don't care about the passed process.argv
var compiledYargs = _setupForValidation(yargs, cmd);
try {
// Need to have appended the parsed yargs object - the call to which will fail, before we print out the help
yargs.parse([]);
} catch (err) {
// Intentionally empty - don't care about handling this, we just want the usage string.
}
return compiledYargs.help();
};
/*
Normalise argument based positional aliases, e.g.
fhc app list 1a2b will become fhc app list --project=1a2b3c
Converts all arguments to flags
@param argsIntoCommand: The arguments passed thru to the command, less the command itself (so no 'fhc' or 'app')
@param cmd: The command definition object
*/
function _normaliseFlagsAndArs(argsIntoCommand, cmd) {
if (_.isEmpty(cmd.alias)) {
// bail on old style commands
return argsIntoCommand;
}
var processArgs = _.clone(process.argv);
_.each(cmd.alias, function(alias, key) {
if (key.match(/[0-9]/)) {
var position = parseInt(key, 10),
arg = argsIntoCommand[position];
var hasArgumentAtPosition = !isNaN(position) && typeof arg !== 'undefined' && !arg.match(/^--/) && arg.indexOf('=') === -1;
if (hasArgumentAtPosition) {
var idx = processArgs.indexOf(arg);
if (idx > -1) {
processArgs[idx] = '--' + alias + '=' + arg;
}
}
}
});
return processArgs;
}
/*
Sets up a yargs object from a command definition, but doesn't trigger the validation yet
*/
function _setupForValidation(yargs, cmd) {
// yargs errors out with our numeric positional aliases which we process in _normaliseFlagsAndArs -
// delete them before handing off to yargs
var nonNumericAliases = _.clone(cmd.alias);
_.each(nonNumericAliases, function(value, key) {
if (key.toString().match(/[0-9]/)) {
delete nonNumericAliases[key];
}
});
yargs.exitProcess(false)
.usage(cmd.usage)
.demand(cmd.demand)
.alias(nonNumericAliases)
.describe(cmd.describe || cmd.desc);
_.each(cmd.examples, function(ex) {
yargs.example(ex.cmd, ex.desc || '');
});
_.each(cmd.defaults, function(value, key) {
yargs.default(key, value);
});
return yargs;
}
/*
Globals are still read from ini.get - e.g. ini.get('table').
Until all legacy commands are migrated, we need to support this.
*/
function _setupArgsInIniConfig(yargs) {
var argv = yargs.argv;
argv = _.omit(argv, '_', '$0');
_.each(argv, function(value, key) {
ini.set(key, value);
});
}