| // 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(), |
| defaultValues = [true, false, ''] |
| |
| if (options.requiresArg.length > 0) { |
| var missingRequiredArgs = [] |
| |
| options.requiresArg.forEach(function (key) { |
| var value = argv[key] |
| |
| // if a value is explicitly requested, |
| // flag argument as missing if it does not |
| // look like foo=bar was entered. |
| if (~defaultValues.indexOf(value) |
| || (Array.isArray(value) && !value.length)) { |
| 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.message ? err.message : 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 |
| 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 |
| } |