UNPKG

appcenter-cli

Version:

Command line tool for Visual Studio App Center

120 lines (119 loc) 4.43 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseOptions = void 0; const minimist = require("minimist"); const util = require("util"); const debug = require("debug")("appcenter-cli:util:commandline:option-parser"); function optionKey(option) { return option.shortName || option.longName; } function optionDisplayName(options) { const short = options.shortName ? "-" + options.shortName : null; const long = options.longName ? "--" + options.longName : null; return [short, long].filter((x) => !!x).join(" / "); } function descriptionToMinimistOpts(options) { const parseOpts = { boolean: [], string: [], alias: {}, default: {}, unknown: (arg) => { if (arg.charAt(0) === "-") { throw new Error(`Unknown argument ${arg}`); } return true; }, }; Object.keys(options) .map((key) => options[key]) .forEach((option) => { const key = optionKey(option); // Is option a boolean or has a value? if (option.hasArg) { parseOpts.string.push(key); } else { parseOpts.boolean.push(key); } // If both names are given, set up alias if (option.shortName && option.longName) { parseOpts.alias[option.shortName] = option.longName; } if (option.defaultValue !== undefined) { parseOpts.default[key] = option.defaultValue; } }); return parseOpts; } function parseOptions(...params) { let flagOptions; let positionalOptions; let target; let args; if (params.length === 4) { debug(`Parser called with 4 args: ${util.inspect(params)}`); [flagOptions, positionalOptions, target, args] = params; } else { debug(`Parser called with 3 args: ${util.inspect(params)}`); [flagOptions, target, args] = params; positionalOptions = []; } debug(`Parsing command line ${args.join(" ")}`); const minimistOptions = descriptionToMinimistOpts(flagOptions); const parsed = minimist(args, minimistOptions); debug(`Raw parsed command line = ${util.inspect(parsed)}`); // handle flag args Object.keys(flagOptions).forEach((targetPropertyName) => { const option = flagOptions[targetPropertyName]; const optKey = optionKey(option); // Skip required args if help or version have been invoked if (!parsed["help"] && !parsed["version"] && option.required && !parsed[optKey]) { // TODO: Replace this with auto-prompting throw new Error(`Missing required option ${optionDisplayName(option)}`); } target[targetPropertyName] = parsed[optKey]; }); // Handle positional args const positionalArgs = parsed["_"] || []; positionalOptions.sort((a, b) => { if (a.position === null) { return +1; } if (b.position === null) { return -1; } return b.position - a.position; }); // Check for leftover positional parameters, fail if found const hasRestOption = positionalOptions.some((o) => o.position === null); if (!hasRestOption && positionalArgs.length > positionalOptions.length) { const unknownArgs = positionalArgs.slice(positionalOptions.length); throw new Error(`Unknown arguments: ${unknownArgs.join(" ")}`); } positionalOptions.forEach((opt, index) => { debug(`Checking for ${opt.required ? "required" : "optional"} option ${opt.name} at position ${opt.position}`); if (positionalArgs.length - 1 < opt.position) { if (!parsed["help"] && opt.required) { throw new Error(`Missing required positional argument ${opt.name}`); } else if (opt.defaultValue) { target[opt.propertyName] = opt.defaultValue; return; } else { return; } } if (opt.position !== null) { target[opt.propertyName] = positionalArgs[opt.position]; positionalArgs[opt.position] = null; } else { // This is the rest argument, pick up whatever's left target[opt.propertyName] = positionalArgs.filter((opt) => opt !== null); } }); } exports.parseOptions = parseOptions;