zapier-platform-cli
Version:
The CLI for apps in the Zapier Developer Platform.
152 lines (130 loc) • 5.1 kB
JavaScript
;
var _ = require('lodash');
var display = require('./display');
var globalArgOptsSpec = {
format: { help: 'display format', choices: Object.keys(display.formatStyles), default: 'table' },
help: { help: 'prints this help text', flag: true },
debug: { help: 'print debug API calls and tracebacks', flag: true }
};
var quoteStr = function quoteStr(s) {
return String(s || '').indexOf(' ') === -1 ? s : '"' + s + '"';
};
var choicesStr = function choicesStr(choices) {
return '{' + choices.map(String).join(',') + '}';
};
// Turn process.argv into args/opts.
var argParse = function argParse(argv) {
var args = [],
opts = {};
argv.forEach(function (arg) {
if (arg.startsWith('--')) {
var key = arg.split('=', 1)[0].replace('--', '');
var val = arg.split('=').slice(1).join('=');
if (val === '') {
val = true;
} else if (val.toLowerCase() === 'false') {
val = false;
}
opts[key] = val;
} else if (arg.startsWith('-') && arg.length === 2) {
// single letter
opts[arg[1]] = true;
} else {
args.push(arg);
}
});
return [args, opts];
};
// Given a spec and args/opts - return an array of errors.
var enforceArgSpec = function enforceArgSpec(fullSpec, args, argOpts) {
var argsSpec = fullSpec.argsSpec || [];
var argOptsSpec = fullSpec.argOptsSpec || {};
var errors = [];
var restAfter = -1;
var _argLookback = {};
// Make sure the spec has the provided args.
_.forEach(argsSpec, function (spec, i) {
var arg = args[i];
_argLookback[spec.name] = arg;
var missingCurrent = spec.required && !arg;
var missingLookback = !arg && // is absent (but that could be fine)!
(spec.requiredWith || []).length && // has required friends!
_.every(spec.requiredWith, function (name) {
return _argLookback[name];
}) // friends are missing!
;
if (missingCurrent || missingLookback) {
errors.push('Missing required positional argument ' + (i + 1) + '/' + spec.name);
}
if (arg && spec.choices && spec.choices.length && spec.choices.indexOf(arg) === -1) {
var choices = choicesStr(spec.choices);
errors.push('Unexpected positional argument ' + (i + 1) + '/' + spec.name + ' of ' + quoteStr(arg) + ', must be one of ' + choices);
}
restAfter = i;
if (spec.rest) {
restAfter = 1000;
}
});
// Make sure any leftover provided args are expected.
_.forEach(args, function (arg, i) {
if (i > restAfter) {
errors.push('Unexpected positional argument ' + (i + 1) + ' of ' + quoteStr(arg));
}
});
// Make sure the spec has the provided args opts/keywords.
_.forEach(argOptsSpec, function (spec, name) {
var arg = argOpts[name];
if (spec.flag && arg && arg !== true) {
errors.push('Unexpected keyword argument with value --' + name);
return;
}
if (spec.required && !arg) {
errors.push('Missing required keyword argument --' + name + '=' + quoteStr(arg || spec.example || 'value'));
}
if (arg && spec.choices && spec.choices.length && spec.choices.indexOf(arg) === -1) {
var choices = choicesStr(spec.choices);
errors.push('Unexpected keyword argument --' + name + '=' + quoteStr(arg) + ', must be one of ' + choices);
}
});
// Make sure any leftover provided args opts/keywords are expected.
_.forEach(argOpts, function (arg, name) {
if (!argOptsSpec[name]) {
if (arg === true) {
errors.push('Unexpected keyword argument --' + name);
} else {
errors.push('Unexpected keyword argument --' + name + '=' + quoteStr(arg));
}
}
});
return errors;
};
// Make a markdown list for args.
var argsFragment = function argsFragment(argsSpec) {
return _.map(argsSpec, function (spec) {
var val = spec.example || 'value';
val = spec.choices && spec.choices.length ? choicesStr(spec.choices) : val;
var def = spec.default ? '. Default is `' + spec.default + '`' : '';
return '* `' + spec.name + ' [' + quoteStr(val) + ']` -- ' + (spec.required ? '**required**' : '_optional_') + ', ' + (spec.help || '') + def;
}).join('\n').trim();
};
// Make a markdown list for args opts/keywords.
var argOptsFragment = function argOptsFragment(argOptsSpec) {
return _.map(argOptsSpec, function (spec, name) {
var val = spec.example || spec.default || 'value';
val = spec.choices && spec.choices.length ? choicesStr(spec.choices) : val;
val = spec.flag ? '' : '=' + quoteStr(val);
var def = spec.default ? '. Default is `' + spec.default + '`' : '';
return '* `--' + name + val + '` -- ' + (spec.required ? '**required**' : '_optional_') + ', ' + (spec.help || '') + def;
}).join('\n').trim();
};
var defaultArgOptsFragment = function defaultArgOptsFragment() {
return argOptsFragment(globalArgOptsSpec);
};
module.exports = {
argOptsFragment: argOptsFragment,
argParse: argParse,
argsFragment: argsFragment,
defaultArgOptsFragment: defaultArgOptsFragment,
enforceArgSpec: enforceArgSpec,
globalArgOptsSpec: globalArgOptsSpec
};