UNPKG

lambda-layer-packager

Version:

A professional CLI tool designed to package Node.js modules into a zip file for AWS Lambda Layers, facilitating efficient deployment and management of serverless applications.

1,209 lines (1,175 loc) 1.07 MB
import {EventEmitter as $7P9PB$EventEmitter} from "events"; import {spawn as $7P9PB$spawn, exec as $7P9PB$exec} from "child_process"; import * as $7P9PB$path from "path"; import * as $7P9PB$fs from "fs"; import * as $7P9PB$process from "process"; import * as $7P9PB$stream from "stream"; import * as $7P9PB$util from "util"; import * as $7P9PB$buffer from "buffer"; import * as $7P9PB$assert from "assert"; import * as $7P9PB$constants1 from "constants"; import {DeflateRaw as $7P9PB$DeflateRaw, createGzip as $7P9PB$createGzip} from "zlib"; import {StringDecoder as $7P9PB$StringDecoder} from "string_decoder"; function $parcel$export(e, n, v, s) { Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true}); } var $parcel$global = globalThis; function $parcel$interopDefault(a) { return a && a.__esModule ? a.default : a; } var $parcel$modules = {}; var $parcel$inits = {}; var parcelRequire = $parcel$global["parcelRequire94c2"]; if (parcelRequire == null) { parcelRequire = function(id) { if (id in $parcel$modules) { return $parcel$modules[id].exports; } if (id in $parcel$inits) { var init = $parcel$inits[id]; delete $parcel$inits[id]; var module = {id: id, exports: {}}; $parcel$modules[id] = module; init.call(module.exports, module, module.exports); return module.exports; } var err = new Error("Cannot find module '" + id + "'"); err.code = 'MODULE_NOT_FOUND'; throw err; }; parcelRequire.register = function register(id, init) { $parcel$inits[id] = init; }; $parcel$global["parcelRequire94c2"] = parcelRequire; } var parcelRegister = parcelRequire.register; parcelRegister("4SHYO", function(module, exports) { var $hATzO = parcelRequire("hATzO"); var $38de520d36fb05b7$require$Argument = $hATzO.Argument; var $nnts3 = parcelRequire("nnts3"); var $38de520d36fb05b7$require$Command = $nnts3.Command; var $5Kwvq = parcelRequire("5Kwvq"); var $38de520d36fb05b7$require$CommanderError = $5Kwvq.CommanderError; var $38de520d36fb05b7$require$InvalidArgumentError = $5Kwvq.InvalidArgumentError; var $5xqpG = parcelRequire("5xqpG"); var $38de520d36fb05b7$require$Help = $5xqpG.Help; var $8wDLy = parcelRequire("8wDLy"); var $38de520d36fb05b7$require$Option = $8wDLy.Option; // @ts-check /** * Expose the root command. */ exports = module.exports = new $38de520d36fb05b7$require$Command(); exports.program = exports; // More explicit access to global command. // Implicit export of createArgument, createCommand, and createOption. /** * Expose classes */ exports.Argument = $38de520d36fb05b7$require$Argument; exports.Command = $38de520d36fb05b7$require$Command; exports.CommanderError = $38de520d36fb05b7$require$CommanderError; exports.Help = $38de520d36fb05b7$require$Help; exports.InvalidArgumentError = $38de520d36fb05b7$require$InvalidArgumentError; exports.InvalidOptionArgumentError = $38de520d36fb05b7$require$InvalidArgumentError; // Deprecated exports.Option = $38de520d36fb05b7$require$Option; }); parcelRegister("hATzO", function(module, exports) { $parcel$export(module.exports, "Argument", () => $ccf0e8d65c065218$export$84637ea037d2e218, (v) => $ccf0e8d65c065218$export$84637ea037d2e218 = v); $parcel$export(module.exports, "humanReadableArgName", () => $ccf0e8d65c065218$export$6e65b3a729b8c0d8, (v) => $ccf0e8d65c065218$export$6e65b3a729b8c0d8 = v); var $ccf0e8d65c065218$export$84637ea037d2e218; var $ccf0e8d65c065218$export$6e65b3a729b8c0d8; var $5Kwvq = parcelRequire("5Kwvq"); var $ccf0e8d65c065218$require$InvalidArgumentError = $5Kwvq.InvalidArgumentError; // @ts-check class $ccf0e8d65c065218$var$Argument { /** * Initialize a new command argument with the given name and description. * The default is that the argument is required, and you can explicitly * indicate this with <> around the name. Put [] around the name for an optional argument. * * @param {string} name * @param {string} [description] */ constructor(name, description){ this.description = description || ''; this.variadic = false; this.parseArg = undefined; this.defaultValue = undefined; this.defaultValueDescription = undefined; this.argChoices = undefined; switch(name[0]){ case '<': this.required = true; this._name = name.slice(1, -1); break; case '[': this.required = false; this._name = name.slice(1, -1); break; default: this.required = true; this._name = name; break; } if (this._name.length > 3 && this._name.slice(-3) === '...') { this.variadic = true; this._name = this._name.slice(0, -3); } } /** * Return argument name. * * @return {string} */ name() { return this._name; } /** * @api private */ _concatValue(value, previous) { if (previous === this.defaultValue || !Array.isArray(previous)) return [ value ]; return previous.concat(value); } /** * Set the default value, and optionally supply the description to be displayed in the help. * * @param {any} value * @param {string} [description] * @return {Argument} */ default(value, description) { this.defaultValue = value; this.defaultValueDescription = description; return this; } /** * Set the custom handler for processing CLI command arguments into argument values. * * @param {Function} [fn] * @return {Argument} */ argParser(fn) { this.parseArg = fn; return this; } /** * Only allow argument value to be one of choices. * * @param {string[]} values * @return {Argument} */ choices(values) { this.argChoices = values.slice(); this.parseArg = (arg, previous)=>{ if (!this.argChoices.includes(arg)) throw new $ccf0e8d65c065218$require$InvalidArgumentError(`Allowed choices are ${this.argChoices.join(', ')}.`); if (this.variadic) return this._concatValue(arg, previous); return arg; }; return this; } /** * Make argument required. */ argRequired() { this.required = true; return this; } /** * Make argument optional. */ argOptional() { this.required = false; return this; } } /** * Takes an argument and returns its human readable equivalent for help usage. * * @param {Argument} arg * @return {string} * @api private */ function $ccf0e8d65c065218$var$humanReadableArgName(arg) { const nameOutput = arg.name() + (arg.variadic === true ? '...' : ''); return arg.required ? '<' + nameOutput + '>' : '[' + nameOutput + ']'; } $ccf0e8d65c065218$export$84637ea037d2e218 = $ccf0e8d65c065218$var$Argument; $ccf0e8d65c065218$export$6e65b3a729b8c0d8 = $ccf0e8d65c065218$var$humanReadableArgName; }); parcelRegister("5Kwvq", function(module, exports) { $parcel$export(module.exports, "CommanderError", () => $42fa769743cb6497$export$e42852c0d9bd9ade, (v) => $42fa769743cb6497$export$e42852c0d9bd9ade = v); $parcel$export(module.exports, "InvalidArgumentError", () => $42fa769743cb6497$export$9c711d4a95378233, (v) => $42fa769743cb6497$export$9c711d4a95378233 = v); // @ts-check /** * CommanderError class * @class */ var $42fa769743cb6497$export$e42852c0d9bd9ade; var $42fa769743cb6497$export$9c711d4a95378233; class $42fa769743cb6497$var$CommanderError extends Error { /** * Constructs the CommanderError class * @param {number} exitCode suggested exit code which could be used with process.exit * @param {string} code an id string representing the error * @param {string} message human-readable description of the error * @constructor */ constructor(exitCode, code, message){ super(message); // properly capture stack trace in Node.js Error.captureStackTrace(this, this.constructor); this.name = this.constructor.name; this.code = code; this.exitCode = exitCode; this.nestedError = undefined; } } /** * InvalidArgumentError class * @class */ class $42fa769743cb6497$var$InvalidArgumentError extends $42fa769743cb6497$var$CommanderError { /** * Constructs the InvalidArgumentError class * @param {string} [message] explanation of why argument is invalid * @constructor */ constructor(message){ super(1, 'commander.invalidArgument', message); // properly capture stack trace in Node.js Error.captureStackTrace(this, this.constructor); this.name = this.constructor.name; } } $42fa769743cb6497$export$e42852c0d9bd9ade = $42fa769743cb6497$var$CommanderError; $42fa769743cb6497$export$9c711d4a95378233 = $42fa769743cb6497$var$InvalidArgumentError; }); parcelRegister("nnts3", function(module, exports) { $parcel$export(module.exports, "Command", () => $04645b8ca176286a$export$cc7e12c76513e857, (v) => $04645b8ca176286a$export$cc7e12c76513e857 = v); var $04645b8ca176286a$export$cc7e12c76513e857; var $04645b8ca176286a$require$EventEmitter = $7P9PB$EventEmitter; var $hATzO = parcelRequire("hATzO"); var $04645b8ca176286a$require$Argument = $hATzO.Argument; var $04645b8ca176286a$require$humanReadableArgName = $hATzO.humanReadableArgName; var $5Kwvq = parcelRequire("5Kwvq"); var $04645b8ca176286a$require$CommanderError = $5Kwvq.CommanderError; var $5xqpG = parcelRequire("5xqpG"); var $04645b8ca176286a$require$Help = $5xqpG.Help; var $8wDLy = parcelRequire("8wDLy"); var $04645b8ca176286a$require$Option = $8wDLy.Option; var $04645b8ca176286a$require$splitOptionFlags = $8wDLy.splitOptionFlags; var $04645b8ca176286a$require$DualOptions = $8wDLy.DualOptions; var $8rXP9 = parcelRequire("8rXP9"); var $04645b8ca176286a$require$suggestSimilar = $8rXP9.suggestSimilar; // @ts-check class $04645b8ca176286a$var$Command extends $04645b8ca176286a$require$EventEmitter { /** * Initialize a new `Command`. * * @param {string} [name] */ constructor(name){ super(); /** @type {Command[]} */ this.commands = []; /** @type {Option[]} */ this.options = []; this.parent = null; this._allowUnknownOption = false; this._allowExcessArguments = true; /** @type {Argument[]} */ this._args = []; /** @type {string[]} */ this.args = []; // cli args with options removed this.rawArgs = []; this.processedArgs = []; // like .args but after custom processing and collecting variadic this._scriptPath = null; this._name = name || ''; this._optionValues = {}; this._optionValueSources = {}; // default, env, cli etc this._storeOptionsAsProperties = false; this._actionHandler = null; this._executableHandler = false; this._executableFile = null; // custom name for executable this._executableDir = null; // custom search directory for subcommands this._defaultCommandName = null; this._exitCallback = null; this._aliases = []; this._combineFlagAndOptionalValue = true; this._description = ''; this._summary = ''; this._argsDescription = undefined; // legacy this._enablePositionalOptions = false; this._passThroughOptions = false; this._lifeCycleHooks = {}; // a hash of arrays /** @type {boolean | string} */ this._showHelpAfterError = false; this._showSuggestionAfterError = true; // see .configureOutput() for docs this._outputConfiguration = { writeOut: (str)=>$7P9PB$process.stdout.write(str), writeErr: (str)=>$7P9PB$process.stderr.write(str), getOutHelpWidth: ()=>$7P9PB$process.stdout.isTTY ? $7P9PB$process.stdout.columns : undefined, getErrHelpWidth: ()=>$7P9PB$process.stderr.isTTY ? $7P9PB$process.stderr.columns : undefined, outputError: (str, write)=>write(str) }; this._hidden = false; this._hasHelpOption = true; this._helpFlags = '-h, --help'; this._helpDescription = 'display help for command'; this._helpShortFlag = '-h'; this._helpLongFlag = '--help'; this._addImplicitHelpCommand = undefined; // Deliberately undefined, not decided whether true or false this._helpCommandName = 'help'; this._helpCommandnameAndArgs = 'help [command]'; this._helpCommandDescription = 'display help for command'; this._helpConfiguration = {}; } /** * Copy settings that are useful to have in common across root command and subcommands. * * (Used internally when adding a command using `.command()` so subcommands inherit parent settings.) * * @param {Command} sourceCommand * @return {Command} `this` command for chaining */ copyInheritedSettings(sourceCommand) { this._outputConfiguration = sourceCommand._outputConfiguration; this._hasHelpOption = sourceCommand._hasHelpOption; this._helpFlags = sourceCommand._helpFlags; this._helpDescription = sourceCommand._helpDescription; this._helpShortFlag = sourceCommand._helpShortFlag; this._helpLongFlag = sourceCommand._helpLongFlag; this._helpCommandName = sourceCommand._helpCommandName; this._helpCommandnameAndArgs = sourceCommand._helpCommandnameAndArgs; this._helpCommandDescription = sourceCommand._helpCommandDescription; this._helpConfiguration = sourceCommand._helpConfiguration; this._exitCallback = sourceCommand._exitCallback; this._storeOptionsAsProperties = sourceCommand._storeOptionsAsProperties; this._combineFlagAndOptionalValue = sourceCommand._combineFlagAndOptionalValue; this._allowExcessArguments = sourceCommand._allowExcessArguments; this._enablePositionalOptions = sourceCommand._enablePositionalOptions; this._showHelpAfterError = sourceCommand._showHelpAfterError; this._showSuggestionAfterError = sourceCommand._showSuggestionAfterError; return this; } /** * Define a command. * * There are two styles of command: pay attention to where to put the description. * * @example * // Command implemented using action handler (description is supplied separately to `.command`) * program * .command('clone <source> [destination]') * .description('clone a repository into a newly created directory') * .action((source, destination) => { * console.log('clone command called'); * }); * * // Command implemented using separate executable file (description is second parameter to `.command`) * program * .command('start <service>', 'start named service') * .command('stop [service]', 'stop named service, or all if no name supplied'); * * @param {string} nameAndArgs - command name and arguments, args are `<required>` or `[optional]` and last may also be `variadic...` * @param {Object|string} [actionOptsOrExecDesc] - configuration options (for action), or description (for executable) * @param {Object} [execOpts] - configuration options (for executable) * @return {Command} returns new command for action handler, or `this` for executable command */ command(nameAndArgs, actionOptsOrExecDesc, execOpts) { let desc = actionOptsOrExecDesc; let opts = execOpts; if (typeof desc === 'object' && desc !== null) { opts = desc; desc = null; } opts = opts || {}; const [, name, args] = nameAndArgs.match(/([^ ]+) *(.*)/); const cmd = this.createCommand(name); if (desc) { cmd.description(desc); cmd._executableHandler = true; } if (opts.isDefault) this._defaultCommandName = cmd._name; cmd._hidden = !!(opts.noHelp || opts.hidden); // noHelp is deprecated old name for hidden cmd._executableFile = opts.executableFile || null; // Custom name for executable file, set missing to null to match constructor if (args) cmd.arguments(args); this.commands.push(cmd); cmd.parent = this; cmd.copyInheritedSettings(this); if (desc) return this; return cmd; } /** * Factory routine to create a new unattached command. * * See .command() for creating an attached subcommand, which uses this routine to * create the command. You can override createCommand to customise subcommands. * * @param {string} [name] * @return {Command} new command */ createCommand(name) { return new $04645b8ca176286a$var$Command(name); } /** * You can customise the help with a subclass of Help by overriding createHelp, * or by overriding Help properties using configureHelp(). * * @return {Help} */ createHelp() { return Object.assign(new $04645b8ca176286a$require$Help(), this.configureHelp()); } /** * You can customise the help by overriding Help properties using configureHelp(), * or with a subclass of Help by overriding createHelp(). * * @param {Object} [configuration] - configuration options * @return {Command|Object} `this` command for chaining, or stored configuration */ configureHelp(configuration) { if (configuration === undefined) return this._helpConfiguration; this._helpConfiguration = configuration; return this; } /** * The default output goes to stdout and stderr. You can customise this for special * applications. You can also customise the display of errors by overriding outputError. * * The configuration properties are all functions: * * // functions to change where being written, stdout and stderr * writeOut(str) * writeErr(str) * // matching functions to specify width for wrapping help * getOutHelpWidth() * getErrHelpWidth() * // functions based on what is being written out * outputError(str, write) // used for displaying errors, and not used for displaying help * * @param {Object} [configuration] - configuration options * @return {Command|Object} `this` command for chaining, or stored configuration */ configureOutput(configuration) { if (configuration === undefined) return this._outputConfiguration; Object.assign(this._outputConfiguration, configuration); return this; } /** * Display the help or a custom message after an error occurs. * * @param {boolean|string} [displayHelp] * @return {Command} `this` command for chaining */ showHelpAfterError(displayHelp = true) { if (typeof displayHelp !== 'string') displayHelp = !!displayHelp; this._showHelpAfterError = displayHelp; return this; } /** * Display suggestion of similar commands for unknown commands, or options for unknown options. * * @param {boolean} [displaySuggestion] * @return {Command} `this` command for chaining */ showSuggestionAfterError(displaySuggestion = true) { this._showSuggestionAfterError = !!displaySuggestion; return this; } /** * Add a prepared subcommand. * * See .command() for creating an attached subcommand which inherits settings from its parent. * * @param {Command} cmd - new subcommand * @param {Object} [opts] - configuration options * @return {Command} `this` command for chaining */ addCommand(cmd, opts) { if (!cmd._name) throw new Error(`Command passed to .addCommand() must have a name - specify the name in Command constructor or using .name()`); opts = opts || {}; if (opts.isDefault) this._defaultCommandName = cmd._name; if (opts.noHelp || opts.hidden) cmd._hidden = true; // modifying passed command due to existing implementation this.commands.push(cmd); cmd.parent = this; return this; } /** * Factory routine to create a new unattached argument. * * See .argument() for creating an attached argument, which uses this routine to * create the argument. You can override createArgument to return a custom argument. * * @param {string} name * @param {string} [description] * @return {Argument} new argument */ createArgument(name, description) { return new $04645b8ca176286a$require$Argument(name, description); } /** * Define argument syntax for command. * * The default is that the argument is required, and you can explicitly * indicate this with <> around the name. Put [] around the name for an optional argument. * * @example * program.argument('<input-file>'); * program.argument('[output-file]'); * * @param {string} name * @param {string} [description] * @param {Function|*} [fn] - custom argument processing function * @param {*} [defaultValue] * @return {Command} `this` command for chaining */ argument(name, description, fn, defaultValue) { const argument = this.createArgument(name, description); if (typeof fn === 'function') argument.default(defaultValue).argParser(fn); else argument.default(fn); this.addArgument(argument); return this; } /** * Define argument syntax for command, adding multiple at once (without descriptions). * * See also .argument(). * * @example * program.arguments('<cmd> [env]'); * * @param {string} names * @return {Command} `this` command for chaining */ arguments(names) { names.split(/ +/).forEach((detail)=>{ this.argument(detail); }); return this; } /** * Define argument syntax for command, adding a prepared argument. * * @param {Argument} argument * @return {Command} `this` command for chaining */ addArgument(argument) { const previousArgument = this._args.slice(-1)[0]; if (previousArgument && previousArgument.variadic) throw new Error(`only the last argument can be variadic '${previousArgument.name()}'`); if (argument.required && argument.defaultValue !== undefined && argument.parseArg === undefined) throw new Error(`a default value for a required argument is never used: '${argument.name()}'`); this._args.push(argument); return this; } /** * Override default decision whether to add implicit help command. * * addHelpCommand() // force on * addHelpCommand(false); // force off * addHelpCommand('help [cmd]', 'display help for [cmd]'); // force on with custom details * * @return {Command} `this` command for chaining */ addHelpCommand(enableOrNameAndArgs, description) { if (enableOrNameAndArgs === false) this._addImplicitHelpCommand = false; else { this._addImplicitHelpCommand = true; if (typeof enableOrNameAndArgs === 'string') { this._helpCommandName = enableOrNameAndArgs.split(' ')[0]; this._helpCommandnameAndArgs = enableOrNameAndArgs; } this._helpCommandDescription = description || this._helpCommandDescription; } return this; } /** * @return {boolean} * @api private */ _hasImplicitHelpCommand() { if (this._addImplicitHelpCommand === undefined) return this.commands.length && !this._actionHandler && !this._findCommand('help'); return this._addImplicitHelpCommand; } /** * Add hook for life cycle event. * * @param {string} event * @param {Function} listener * @return {Command} `this` command for chaining */ hook(event, listener) { const allowedValues = [ 'preSubcommand', 'preAction', 'postAction' ]; if (!allowedValues.includes(event)) throw new Error(`Unexpected value for event passed to hook : '${event}'. Expecting one of '${allowedValues.join("', '")}'`); if (this._lifeCycleHooks[event]) this._lifeCycleHooks[event].push(listener); else this._lifeCycleHooks[event] = [ listener ]; return this; } /** * Register callback to use as replacement for calling process.exit. * * @param {Function} [fn] optional callback which will be passed a CommanderError, defaults to throwing * @return {Command} `this` command for chaining */ exitOverride(fn) { if (fn) this._exitCallback = fn; else this._exitCallback = (err)=>{ if (err.code !== 'commander.executeSubCommandAsync') throw err; }; return this; } /** * Call process.exit, and _exitCallback if defined. * * @param {number} exitCode exit code for using with process.exit * @param {string} code an id string representing the error * @param {string} message human-readable description of the error * @return never * @api private */ _exit(exitCode, code, message) { if (this._exitCallback) this._exitCallback(new $04645b8ca176286a$require$CommanderError(exitCode, code, message)); $7P9PB$process.exit(exitCode); } /** * Register callback `fn` for the command. * * @example * program * .command('serve') * .description('start service') * .action(function() { * // do work here * }); * * @param {Function} fn * @return {Command} `this` command for chaining */ action(fn) { const listener = (args)=>{ // The .action callback takes an extra parameter which is the command or options. const expectedArgsCount = this._args.length; const actionArgs = args.slice(0, expectedArgsCount); if (this._storeOptionsAsProperties) actionArgs[expectedArgsCount] = this; // backwards compatible "options" else actionArgs[expectedArgsCount] = this.opts(); actionArgs.push(this); return fn.apply(this, actionArgs); }; this._actionHandler = listener; return this; } /** * Factory routine to create a new unattached option. * * See .option() for creating an attached option, which uses this routine to * create the option. You can override createOption to return a custom option. * * @param {string} flags * @param {string} [description] * @return {Option} new option */ createOption(flags, description) { return new $04645b8ca176286a$require$Option(flags, description); } /** * Add an option. * * @param {Option} option * @return {Command} `this` command for chaining */ addOption(option) { const oname = option.name(); const name = option.attributeName(); // store default value if (option.negate) { // --no-foo is special and defaults foo to true, unless a --foo option is already defined const positiveLongFlag = option.long.replace(/^--no-/, '--'); if (!this._findOption(positiveLongFlag)) this.setOptionValueWithSource(name, option.defaultValue === undefined ? true : option.defaultValue, 'default'); } else if (option.defaultValue !== undefined) this.setOptionValueWithSource(name, option.defaultValue, 'default'); // register the option this.options.push(option); // handler for cli and env supplied values const handleOptionValue = (val, invalidValueMessage, valueSource)=>{ // val is null for optional option used without an optional-argument. // val is undefined for boolean and negated option. if (val == null && option.presetArg !== undefined) val = option.presetArg; // custom processing const oldValue = this.getOptionValue(name); if (val !== null && option.parseArg) try { val = option.parseArg(val, oldValue); } catch (err) { if (err.code === 'commander.invalidArgument') { const message = `${invalidValueMessage} ${err.message}`; this.error(message, { exitCode: err.exitCode, code: err.code }); } throw err; } else if (val !== null && option.variadic) val = option._concatValue(val, oldValue); // Fill-in appropriate missing values. Long winded but easy to follow. if (val == null) { if (option.negate) val = false; else if (option.isBoolean() || option.optional) val = true; else val = ''; // not normal, parseArg might have failed or be a mock function for testing } this.setOptionValueWithSource(name, val, valueSource); }; this.on('option:' + oname, (val)=>{ const invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`; handleOptionValue(val, invalidValueMessage, 'cli'); }); if (option.envVar) this.on('optionEnv:' + oname, (val)=>{ const invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`; handleOptionValue(val, invalidValueMessage, 'env'); }); return this; } /** * Internal implementation shared by .option() and .requiredOption() * * @api private */ _optionEx(config, flags, description, fn, defaultValue) { if (typeof flags === 'object' && flags instanceof $04645b8ca176286a$require$Option) throw new Error('To add an Option object use addOption() instead of option() or requiredOption()'); const option = this.createOption(flags, description); option.makeOptionMandatory(!!config.mandatory); if (typeof fn === 'function') option.default(defaultValue).argParser(fn); else if (fn instanceof RegExp) { // deprecated const regex = fn; fn = (val, def)=>{ const m = regex.exec(val); return m ? m[0] : def; }; option.default(defaultValue).argParser(fn); } else option.default(fn); return this.addOption(option); } /** * Define option with `flags`, `description` and optional * coercion `fn`. * * The `flags` string contains the short and/or long flags, * separated by comma, a pipe or space. The following are all valid * all will output this way when `--help` is used. * * "-p, --pepper" * "-p|--pepper" * "-p --pepper" * * @example * // simple boolean defaulting to undefined * program.option('-p, --pepper', 'add pepper'); * * program.pepper * // => undefined * * --pepper * program.pepper * // => true * * // simple boolean defaulting to true (unless non-negated option is also defined) * program.option('-C, --no-cheese', 'remove cheese'); * * program.cheese * // => true * * --no-cheese * program.cheese * // => false * * // required argument * program.option('-C, --chdir <path>', 'change the working directory'); * * --chdir /tmp * program.chdir * // => "/tmp" * * // optional argument * program.option('-c, --cheese [type]', 'add cheese [marble]'); * * @param {string} flags * @param {string} [description] * @param {Function|*} [fn] - custom option processing function or default value * @param {*} [defaultValue] * @return {Command} `this` command for chaining */ option(flags, description, fn, defaultValue) { return this._optionEx({}, flags, description, fn, defaultValue); } /** * Add a required option which must have a value after parsing. This usually means * the option must be specified on the command line. (Otherwise the same as .option().) * * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space. * * @param {string} flags * @param {string} [description] * @param {Function|*} [fn] - custom option processing function or default value * @param {*} [defaultValue] * @return {Command} `this` command for chaining */ requiredOption(flags, description, fn, defaultValue) { return this._optionEx({ mandatory: true }, flags, description, fn, defaultValue); } /** * Alter parsing of short flags with optional values. * * @example * // for `.option('-f,--flag [value]'): * program.combineFlagAndOptionalValue(true); // `-f80` is treated like `--flag=80`, this is the default behaviour * program.combineFlagAndOptionalValue(false) // `-fb` is treated like `-f -b` * * @param {Boolean} [combine=true] - if `true` or omitted, an optional value can be specified directly after the flag. */ combineFlagAndOptionalValue(combine = true) { this._combineFlagAndOptionalValue = !!combine; return this; } /** * Allow unknown options on the command line. * * @param {Boolean} [allowUnknown=true] - if `true` or omitted, no error will be thrown * for unknown options. */ allowUnknownOption(allowUnknown = true) { this._allowUnknownOption = !!allowUnknown; return this; } /** * Allow excess command-arguments on the command line. Pass false to make excess arguments an error. * * @param {Boolean} [allowExcess=true] - if `true` or omitted, no error will be thrown * for excess arguments. */ allowExcessArguments(allowExcess = true) { this._allowExcessArguments = !!allowExcess; return this; } /** * Enable positional options. Positional means global options are specified before subcommands which lets * subcommands reuse the same option names, and also enables subcommands to turn on passThroughOptions. * The default behaviour is non-positional and global options may appear anywhere on the command line. * * @param {Boolean} [positional=true] */ enablePositionalOptions(positional = true) { this._enablePositionalOptions = !!positional; return this; } /** * Pass through options that come after command-arguments rather than treat them as command-options, * so actual command-options come before command-arguments. Turning this on for a subcommand requires * positional options to have been enabled on the program (parent commands). * The default behaviour is non-positional and options may appear before or after command-arguments. * * @param {Boolean} [passThrough=true] * for unknown options. */ passThroughOptions(passThrough = true) { this._passThroughOptions = !!passThrough; if (!!this.parent && passThrough && !this.parent._enablePositionalOptions) throw new Error('passThroughOptions can not be used without turning on enablePositionalOptions for parent command(s)'); return this; } /** * Whether to store option values as properties on command object, * or store separately (specify false). In both cases the option values can be accessed using .opts(). * * @param {boolean} [storeAsProperties=true] * @return {Command} `this` command for chaining */ storeOptionsAsProperties(storeAsProperties = true) { this._storeOptionsAsProperties = !!storeAsProperties; if (this.options.length) throw new Error('call .storeOptionsAsProperties() before adding options'); return this; } /** * Retrieve option value. * * @param {string} key * @return {Object} value */ getOptionValue(key) { if (this._storeOptionsAsProperties) return this[key]; return this._optionValues[key]; } /** * Store option value. * * @param {string} key * @param {Object} value * @return {Command} `this` command for chaining */ setOptionValue(key, value) { return this.setOptionValueWithSource(key, value, undefined); } /** * Store option value and where the value came from. * * @param {string} key * @param {Object} value * @param {string} source - expected values are default/config/env/cli/implied * @return {Command} `this` command for chaining */ setOptionValueWithSource(key, value, source) { if (this._storeOptionsAsProperties) this[key] = value; else this._optionValues[key] = value; this._optionValueSources[key] = source; return this; } /** * Get source of option value. * Expected values are default | config | env | cli | implied * * @param {string} key * @return {string} */ getOptionValueSource(key) { return this._optionValueSources[key]; } /** * Get source of option value. See also .optsWithGlobals(). * Expected values are default | config | env | cli | implied * * @param {string} key * @return {string} */ getOptionValueSourceWithGlobals(key) { // global overwrites local, like optsWithGlobals let source; $04645b8ca176286a$var$getCommandAndParents(this).forEach((cmd)=>{ if (cmd.getOptionValueSource(key) !== undefined) source = cmd.getOptionValueSource(key); }); return source; } /** * Get user arguments from implied or explicit arguments. * Side-effects: set _scriptPath if args included script. Used for default program name, and subcommand searches. * * @api private */ _prepareUserArgs(argv, parseOptions) { if (argv !== undefined && !Array.isArray(argv)) throw new Error('first parameter to parse must be array or undefined'); parseOptions = parseOptions || {}; // Default to using process.argv if (argv === undefined) { argv = $7P9PB$process.argv; // @ts-ignore: unknown property if ($7P9PB$process.versions && $7P9PB$process.versions.electron) parseOptions.from = 'electron'; } this.rawArgs = argv.slice(); // make it a little easier for callers by supporting various argv conventions let userArgs; switch(parseOptions.from){ case undefined: case 'node': this._scriptPath = argv[1]; userArgs = argv.slice(2); break; case 'electron': // @ts-ignore: unknown property if ($7P9PB$process.defaultApp) { this._scriptPath = argv[1]; userArgs = argv.slice(2); } else userArgs = argv.slice(1); break; case 'user': userArgs = argv.slice(0); break; default: throw new Error(`unexpected parse option { from: '${parseOptions.from}' }`); } // Find default name for program from arguments. if (!this._name && this._scriptPath) this.nameFromFilename(this._scriptPath); this._name = this._name || 'program'; return userArgs; } /** * Parse `argv`, setting options and invoking commands when defined. * * The default expectation is that the arguments are from node and have the application as argv[0] * and the script being run in argv[1], with user parameters after that. * * @example * program.parse(process.argv); * program.parse(); // implicitly use process.argv and auto-detect node vs electron conventions * program.parse(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0] * * @param {string[]} [argv] - optional, defaults to process.argv * @param {Object} [parseOptions] - optionally specify style of options with from: node/user/electron * @param {string} [parseOptions.from] - where the args are from: 'node', 'user', 'electron' * @return {Command} `this` command for chaining */ parse(argv, parseOptions) { const userArgs = this._prepareUserArgs(argv, parseOptions); this._parseCommand([], userArgs); return this; } /** * Parse `argv`, setting options and invoking commands when defined. * * Use parseAsync instead of parse if any of your action handlers are async. Returns a Promise. * * The default expectation is that the arguments are from node and have the application as argv[0] * and the script being run in argv[1], with user parameters after that. * * @example * await program.parseAsync(process.argv); * await program.parseAsync(); // implicitly use process.argv and auto-detect node vs electron conventions * await program.parseAsync(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0] * * @param {string[]} [argv] * @param {Object} [parseOptions] * @param {string} parseOptions.from - where the args are from: 'node', 'user', 'electron' * @return {Promise} */ async parseAsync(argv, parseOptions) { const userArgs = this._prepareUserArgs(argv, parseOptions); await this._parseCommand([], userArgs); return this; } /** * Execute a sub-command executable. * * @api private */ _executeSubCommand(subcommand, args) { args = args.slice(); let launchWithNode = false; // Use node for source targets so do not need to get permissions correct, and on Windows. const sourceExt = [ '.js', '.ts', '.tsx', '.mjs', '.cjs' ]; function findFile(baseDir, baseName) { // Look for specified file const localBin = $7P9PB$resolve(baseDir, baseName); if ($7P9PB$existsSync(localBin)) return localBin; // Stop looking if candidate already has an expected extension. if (sourceExt.includes($7P9PB$extname(baseName))) return undefined; // Try all the extensions. const foundExt = sourceExt.find((ext)=>$7P9PB$existsSync(`${localBin}${ext}`)); if (foundExt) return `${localBin}${foundExt}`; return undefined; } // Not checking for help first. Unlikely to have mandatory and executable, and can't robustly test for help flags in external command. this._checkForMissingMandatoryOptions(); this._checkForConflictingOptions(); // executableFile and executableDir might be full path, or just a name let executableFile = subcommand._executableFile || `${this._name}-${subcommand._name}`; let executableDir = this._executableDir || ''; if (this._scriptPath) { let resolvedScriptPath; // resolve possible symlink for installed npm binary try { resolvedScriptPath = $7P9PB$realpathSync(this._scriptPath); } catch (err) { resolvedScriptPath = this._scriptPath; } executableDir = $7P9PB$resolve($7P9PB$dirname(resolvedScriptPath), executableDir); } // Look for a local file in preference to a command in PATH. if (executableDir) { let localFile = findFile(executableDir, executableFile); // Legacy search using prefix of script name instead of command name if (!localFile && !subcommand._executableFile && this._scriptPath) { const legacyName = $7P9PB$basename(this._scriptPath, $7P9PB$extname(this._scriptPath)); if (legacyName !== this._name) localFile = findFile(executableDir, `${legacyName}-${subcommand._name}`); } executableFile = localFile || executableFile; } launchWithNode = sourceExt.includes($7P9PB$extname(executableFile)); let proc; if ($7P9PB$process.platform !== 'win32') { if (launchWithNode) { args.unshift(executableFile); // add executable arguments to spawn args = $04645b8ca176286a$var$incrementNodeInspectorPort($7P9PB$process.execArgv).concat(args); proc = $7P9PB$spawn($7P9PB$process.argv[0], args, { stdio: 'inherit' }); } else proc = $7P9PB$spawn(executableFile, args, { stdio: 'inherit' }); } else { args.unshift(executableFile); // add executable arguments to spawn args = $04645b8ca176286a$var$incrementNodeInspectorPort($7P9PB$process.execArgv).concat(args); proc = $7P9PB$spawn($7P9PB$process.execPath, args, { stdio: 'inherit' }); } if (!proc.killed) { const signals = [ 'SIGUSR1', 'SIGUSR2', 'SIGTERM', 'SIGINT', 'SIGHUP' ]; signals.forEach((signal)=>{ // @ts-ignore $7P9PB$process.on(signal, ()=>{ if (proc.killed === false && proc.exitCode === null) proc.kill(signal); }); }); } // By default terminate process when spawned process terminates. // Suppressing the exit if exitCallback defined is a bit messy and of limited use, but does allow process to stay running! const exitCallback = this._exitCallback; if (!exitCallback) proc.on('close', $7P9PB$process.exit.bind($7P9PB$process)); else proc.on('close', ()=>{ exitCallback(new $04645b8ca176286a$require$CommanderError($7P9PB$process.exitCode || 0, 'commander.executeSubCommandAsync', '(close)')); }); proc.on('error', (err)=>{ // @ts-ignore if (err.code === 'ENOENT') { const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : 'no directory for search for local subcommand, use .executableDir() to supply a custom directory'; const executableMissing = `'${executableFile}' does not exist - if '${subcommand._name}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead - if the default executable name is not suitable, use the executableFile option to supply a custom name or path - ${executableDirMessage}`; throw new Error(executableMissing); // @ts-ignore } else if (err.code === 'EACCES') throw new Error(`'${executableFile}' not executable`); if (!exitCallback) $7P9PB$process.exit(1); else { const wrappedError = new $04645b8ca176286a$require$CommanderError(1, 'commander.executeSubCommandAsync', '(error)'); wrappedError.nestedError = err; exitCallback(wrappedError); } }); // Store the reference to the child process this.runningCommand = proc; } /** * @api private */ _dispatchSubcommand(commandName, operands, unknown) { const subCommand = this._findCommand(commandName); if (!subCommand) this.help({ error: true }); let hookResult; hookResult = this._chainOrCallSubCommandHook(hookResult, subCommand, 'preSubcommand'); hookResult = this._chainOrCall(hookResult, ()=>{ if (subCommand._executableHandler) this._executeSubCommand(subCommand, operands.concat(unknown)); else return subCommand._parseCommand(operands, unknown); }); return hookResult; } /** * Check this.args against expected this._args. * * @api private */ _checkNumberOfArguments() { // too few this._args.forEach((arg, i)=>{ if (arg.required && this.args[i] == null) this.missingArgument(arg.name()); }); // too many if (this._args.length > 0 && this._args[this._args.length - 1].variadic) return; if (this.args.length > this._args.length) this._excessArguments(this.args); } /** * Process this.args using this._args and save as this.processedArgs! * * @api private */ _processArguments() { const myParseArg = (argument, value, previous)=>{ // Extra processing for nice error message on parsing failure. let parsedValue = value; if (value !== null && argument.parseArg) try { parsedValue = argument.parseArg(value, previous); } catch (err) { if (err.code === 'commander.invalidArgument') { const message = `error: command-argument value '${value}' is invalid for argument '${argument.name()}'. ${err.message}`; this.error(message, { exitCode: err.exitCode, code: err.code }); } throw err; } return parsedValue; }; this._checkNumberOfArguments(); const processedArgs = []; this._args.forEach((declaredArg, index)=>{ let value = declaredArg.defaultValue; if (declaredArg.variadic) { // Collect together remaining arguments for passing together as an array. if (index < this.args.length) { value = this.args.slice(index); if (declaredArg.parseArg) value = value.reduce((processed, v)=>{ return myParseArg(declaredArg, v, processed); }, declaredArg.defaultValue); } else if (value === undefined) value = []; } else if (index < this.args.length) { value = this.args[index]; if (declaredArg.parseArg) value = myParseArg(declaredArg, value, declaredArg.defaultValue); } processedArgs[index] = value; }); this.processedArgs = processedArgs; } /** * Once we have a promise we chain, but call synchronously until then. * * @param {Promise|undefined} promise * @par