// validation-type-stuff, missing params, // bad implications, custom checks. module.exports = function (yargs, usage) { var self = {}; // validate appropriate # of non-option // arguments were provided, i.e., '_'. self.nonOptionCount = function(argv) { var demanded = yargs.getDemanded(); if (demanded._ && argv._.length < demanded._.count) { if (demanded._.msg !== undefined) { usage.fail(demanded._.msg); } else { usage.fail('Not enough non-option arguments: got ' + argv._.length + ', need at least ' + demanded._.count ); } } }; // make sure that any args that require an // value (--foo=bar), have a value. self.missingArgumentValue = function(argv) { var options = yargs.getOptions(); if (options.requiresArg.length > 0) { var missingRequiredArgs = []; options.requiresArg.forEach(function(key) { var value = argv[key]; // parser sets --foo value to true / --no-foo to false if (value === true || value === false) { missingRequiredArgs.push(key); } }); if (missingRequiredArgs.length == 1) { usage.fail("Missing argument value: " + missingRequiredArgs[0]); } else if (missingRequiredArgs.length > 1) { var message = "Missing argument values: " + missingRequiredArgs.join(", "); usage.fail(message); } } }; // make sure all the required arguments are present. self.requiredArguments = function(argv) { var demanded = yargs.getDemanded(), missing = null; Object.keys(demanded).forEach(function (key) { if (!argv.hasOwnProperty(key)) { missing = missing || {}; missing[key] = demanded[key]; } }); if (missing) { var customMsgs = []; Object.keys(missing).forEach(function(key) { var msg = missing[key].msg; if (msg && customMsgs.indexOf(msg) < 0) { customMsgs.push(msg); } }); var customMsg = customMsgs.length ? '\n' + customMsgs.join('\n') : ''; usage.fail('Missing required arguments: ' + Object.keys(missing).join(', ') + customMsg); } }; // check for unknown arguments (strict-mode). self.unknownArguments = function(argv, aliases) { var descriptions = usage.getDescriptions(), demanded = yargs.getDemanded(), unknown = [], aliasLookup = {}; Object.keys(aliases).forEach(function (key) { aliases[key].forEach(function (alias) { aliasLookup[alias] = key; }); }); Object.keys(argv).forEach(function (key) { if (key !== "$0" && key !== "_" && !descriptions.hasOwnProperty(key) && !demanded.hasOwnProperty(key) && !aliasLookup.hasOwnProperty(key)) { unknown.push(key); } }); if (unknown.length == 1) { usage.fail("Unknown argument: " + unknown[0]); } else if (unknown.length > 1) { usage.fail("Unknown arguments: " + unknown.join(", ")); } }; // custom checks, added using the `check` option on yargs. var checks = []; self.check = function (f) { checks.push(f); }; self.customChecks = function(argv, aliases) { checks.forEach(function (f) { try { var result = f(argv, aliases); if (!result) { usage.fail('Argument check failed: ' + f.toString()); } else if (typeof result === 'string') { usage.fail(result); } } catch (err) { usage.fail(err) } }); }; // check implications, argument foo implies => argument bar. var implied = {}; self.implies = function (key, value) { if (typeof key === 'object') { Object.keys(key).forEach(function (k) { self.implies(k, key[k]); }); } else { implied[key] = value; } }; self.getImplied = function() { return implied; } self.implications = function(argv) { var implyFail = []; Object.keys(implied).forEach(function (key) { var num, origKey = key, value = implied[key]; // convert string '1' to number 1 var num = Number(key); key = isNaN(num) ? key : num; if (typeof key === 'number') { // check length of argv._ key = argv._.length >= key; } else if (key.match(/^--no-.+/)) { // check if key doesn't exist key = key.match(/^--no-(.+)/)[1]; key = !argv[key]; } else { // check if key exists key = argv[key]; } num = Number(value); value = isNaN(num) ? value : num; if (typeof value === 'number') { value = argv._.length >= value; } else if (value.match(/^--no-.+/)) { value = value.match(/^--no-(.+)/)[1]; value = !argv[value]; } else { value = argv[value]; } if (key && !value) { implyFail.push(origKey); } }); if (implyFail.length) { var msg = 'Implications failed:\n'; implyFail.forEach(function (key) { msg += (' ' + key + ' -> ' + implied[key]); }); usage.fail(msg); } } return self; }