CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes48downloads
command.js2510 linesDownload Raw Back to lib
1const EventEmitter = require('node:events').EventEmitter;2const childProcess = require('node:child_process');3const path = require('node:path');4const fs = require('node:fs');5const process = require('node:process');6 7const { Argument, humanReadableArgName } = require('./argument.js');8const { CommanderError } = require('./error.js');9const { Help } = require('./help.js');10const { Option, DualOptions } = require('./option.js');11const { suggestSimilar } = require('./suggestSimilar');12 13class Command extends EventEmitter {14  /**15   * Initialize a new `Command`.16   *17   * @param {string} [name]18   */19 20  constructor(name) {21    super();22    /** @type {Command[]} */23    this.commands = [];24    /** @type {Option[]} */25    this.options = [];26    this.parent = null;27    this._allowUnknownOption = false;28    this._allowExcessArguments = true;29    /** @type {Argument[]} */30    this.registeredArguments = [];31    this._args = this.registeredArguments; // deprecated old name32    /** @type {string[]} */33    this.args = []; // cli args with options removed34    this.rawArgs = [];35    this.processedArgs = []; // like .args but after custom processing and collecting variadic36    this._scriptPath = null;37    this._name = name || '';38    this._optionValues = {};39    this._optionValueSources = {}; // default, env, cli etc40    this._storeOptionsAsProperties = false;41    this._actionHandler = null;42    this._executableHandler = false;43    this._executableFile = null; // custom name for executable44    this._executableDir = null; // custom search directory for subcommands45    this._defaultCommandName = null;46    this._exitCallback = null;47    this._aliases = [];48    this._combineFlagAndOptionalValue = true;49    this._description = '';50    this._summary = '';51    this._argsDescription = undefined; // legacy52    this._enablePositionalOptions = false;53    this._passThroughOptions = false;54    this._lifeCycleHooks = {}; // a hash of arrays55    /** @type {(boolean | string)} */56    this._showHelpAfterError = false;57    this._showSuggestionAfterError = true;58 59    // see .configureOutput() for docs60    this._outputConfiguration = {61      writeOut: (str) => process.stdout.write(str),62      writeErr: (str) => process.stderr.write(str),63      getOutHelpWidth: () =>64        process.stdout.isTTY ? process.stdout.columns : undefined,65      getErrHelpWidth: () =>66        process.stderr.isTTY ? process.stderr.columns : undefined,67      outputError: (str, write) => write(str),68    };69 70    this._hidden = false;71    /** @type {(Option | null | undefined)} */72    this._helpOption = undefined; // Lazy created on demand. May be null if help option is disabled.73    this._addImplicitHelpCommand = undefined; // undecided whether true or false yet, not inherited74    /** @type {Command} */75    this._helpCommand = undefined; // lazy initialised, inherited76    this._helpConfiguration = {};77  }78 79  /**80   * Copy settings that are useful to have in common across root command and subcommands.81   *82   * (Used internally when adding a command using `.command()` so subcommands inherit parent settings.)83   *84   * @param {Command} sourceCommand85   * @return {Command} `this` command for chaining86   */87  copyInheritedSettings(sourceCommand) {88    this._outputConfiguration = sourceCommand._outputConfiguration;89    this._helpOption = sourceCommand._helpOption;90    this._helpCommand = sourceCommand._helpCommand;91    this._helpConfiguration = sourceCommand._helpConfiguration;92    this._exitCallback = sourceCommand._exitCallback;93    this._storeOptionsAsProperties = sourceCommand._storeOptionsAsProperties;94    this._combineFlagAndOptionalValue =95      sourceCommand._combineFlagAndOptionalValue;96    this._allowExcessArguments = sourceCommand._allowExcessArguments;97    this._enablePositionalOptions = sourceCommand._enablePositionalOptions;98    this._showHelpAfterError = sourceCommand._showHelpAfterError;99    this._showSuggestionAfterError = sourceCommand._showSuggestionAfterError;100 101    return this;102  }103 104  /**105   * @returns {Command[]}106   * @private107   */108 109  _getCommandAndAncestors() {110    const result = [];111    // eslint-disable-next-line @typescript-eslint/no-this-alias112    for (let command = this; command; command = command.parent) {113      result.push(command);114    }115    return result;116  }117 118  /**119   * Define a command.120   *121   * There are two styles of command: pay attention to where to put the description.122   *123   * @example124   * // Command implemented using action handler (description is supplied separately to `.command`)125   * program126   *   .command('clone <source> [destination]')127   *   .description('clone a repository into a newly created directory')128   *   .action((source, destination) => {129   *     console.log('clone command called');130   *   });131   *132   * // Command implemented using separate executable file (description is second parameter to `.command`)133   * program134   *   .command('start <service>', 'start named service')135   *   .command('stop [service]', 'stop named service, or all if no name supplied');136   *137   * @param {string} nameAndArgs - command name and arguments, args are `<required>` or `[optional]` and last may also be `variadic...`138   * @param {(object | string)} [actionOptsOrExecDesc] - configuration options (for action), or description (for executable)139   * @param {object} [execOpts] - configuration options (for executable)140   * @return {Command} returns new command for action handler, or `this` for executable command141   */142 143  command(nameAndArgs, actionOptsOrExecDesc, execOpts) {144    let desc = actionOptsOrExecDesc;145    let opts = execOpts;146    if (typeof desc === 'object' && desc !== null) {147      opts = desc;148      desc = null;149    }150    opts = opts || {};151    const [, name, args] = nameAndArgs.match(/([^ ]+) *(.*)/);152 153    const cmd = this.createCommand(name);154    if (desc) {155      cmd.description(desc);156      cmd._executableHandler = true;157    }158    if (opts.isDefault) this._defaultCommandName = cmd._name;159    cmd._hidden = !!(opts.noHelp || opts.hidden); // noHelp is deprecated old name for hidden160    cmd._executableFile = opts.executableFile || null; // Custom name for executable file, set missing to null to match constructor161    if (args) cmd.arguments(args);162    this._registerCommand(cmd);163    cmd.parent = this;164    cmd.copyInheritedSettings(this);165 166    if (desc) return this;167    return cmd;168  }169 170  /**171   * Factory routine to create a new unattached command.172   *173   * See .command() for creating an attached subcommand, which uses this routine to174   * create the command. You can override createCommand to customise subcommands.175   *176   * @param {string} [name]177   * @return {Command} new command178   */179 180  createCommand(name) {181    return new Command(name);182  }183 184  /**185   * You can customise the help with a subclass of Help by overriding createHelp,186   * or by overriding Help properties using configureHelp().187   *188   * @return {Help}189   */190 191  createHelp() {192    return Object.assign(new Help(), this.configureHelp());193  }194 195  /**196   * You can customise the help by overriding Help properties using configureHelp(),197   * or with a subclass of Help by overriding createHelp().198   *199   * @param {object} [configuration] - configuration options200   * @return {(Command | object)} `this` command for chaining, or stored configuration201   */202 203  configureHelp(configuration) {204    if (configuration === undefined) return this._helpConfiguration;205 206    this._helpConfiguration = configuration;207    return this;208  }209 210  /**211   * The default output goes to stdout and stderr. You can customise this for special212   * applications. You can also customise the display of errors by overriding outputError.213   *214   * The configuration properties are all functions:215   *216   *     // functions to change where being written, stdout and stderr217   *     writeOut(str)218   *     writeErr(str)219   *     // matching functions to specify width for wrapping help220   *     getOutHelpWidth()221   *     getErrHelpWidth()222   *     // functions based on what is being written out223   *     outputError(str, write) // used for displaying errors, and not used for displaying help224   *225   * @param {object} [configuration] - configuration options226   * @return {(Command | object)} `this` command for chaining, or stored configuration227   */228 229  configureOutput(configuration) {230    if (configuration === undefined) return this._outputConfiguration;231 232    Object.assign(this._outputConfiguration, configuration);233    return this;234  }235 236  /**237   * Display the help or a custom message after an error occurs.238   *239   * @param {(boolean|string)} [displayHelp]240   * @return {Command} `this` command for chaining241   */242  showHelpAfterError(displayHelp = true) {243    if (typeof displayHelp !== 'string') displayHelp = !!displayHelp;244    this._showHelpAfterError = displayHelp;245    return this;246  }247 248  /**249   * Display suggestion of similar commands for unknown commands, or options for unknown options.250   *251   * @param {boolean} [displaySuggestion]252   * @return {Command} `this` command for chaining253   */254  showSuggestionAfterError(displaySuggestion = true) {255    this._showSuggestionAfterError = !!displaySuggestion;256    return this;257  }258 259  /**260   * Add a prepared subcommand.261   *262   * See .command() for creating an attached subcommand which inherits settings from its parent.263   *264   * @param {Command} cmd - new subcommand265   * @param {object} [opts] - configuration options266   * @return {Command} `this` command for chaining267   */268 269  addCommand(cmd, opts) {270    if (!cmd._name) {271      throw new Error(`Command passed to .addCommand() must have a name272- specify the name in Command constructor or using .name()`);273    }274 275    opts = opts || {};276    if (opts.isDefault) this._defaultCommandName = cmd._name;277    if (opts.noHelp || opts.hidden) cmd._hidden = true; // modifying passed command due to existing implementation278 279    this._registerCommand(cmd);280    cmd.parent = this;281    cmd._checkForBrokenPassThrough();282 283    return this;284  }285 286  /**287   * Factory routine to create a new unattached argument.288   *289   * See .argument() for creating an attached argument, which uses this routine to290   * create the argument. You can override createArgument to return a custom argument.291   *292   * @param {string} name293   * @param {string} [description]294   * @return {Argument} new argument295   */296 297  createArgument(name, description) {298    return new Argument(name, description);299  }300 301  /**302   * Define argument syntax for command.303   *304   * The default is that the argument is required, and you can explicitly305   * indicate this with <> around the name. Put [] around the name for an optional argument.306   *307   * @example308   * program.argument('<input-file>');309   * program.argument('[output-file]');310   *311   * @param {string} name312   * @param {string} [description]313   * @param {(Function|*)} [fn] - custom argument processing function314   * @param {*} [defaultValue]315   * @return {Command} `this` command for chaining316   */317  argument(name, description, fn, defaultValue) {318    const argument = this.createArgument(name, description);319    if (typeof fn === 'function') {320      argument.default(defaultValue).argParser(fn);321    } else {322      argument.default(fn);323    }324    this.addArgument(argument);325    return this;326  }327 328  /**329   * Define argument syntax for command, adding multiple at once (without descriptions).330   *331   * See also .argument().332   *333   * @example334   * program.arguments('<cmd> [env]');335   *336   * @param {string} names337   * @return {Command} `this` command for chaining338   */339 340  arguments(names) {341    names342      .trim()343      .split(/ +/)344      .forEach((detail) => {345        this.argument(detail);346      });347    return this;348  }349 350  /**351   * Define argument syntax for command, adding a prepared argument.352   *353   * @param {Argument} argument354   * @return {Command} `this` command for chaining355   */356  addArgument(argument) {357    const previousArgument = this.registeredArguments.slice(-1)[0];358    if (previousArgument && previousArgument.variadic) {359      throw new Error(360        `only the last argument can be variadic '${previousArgument.name()}'`,361      );362    }363    if (364      argument.required &&365      argument.defaultValue !== undefined &&366      argument.parseArg === undefined367    ) {368      throw new Error(369        `a default value for a required argument is never used: '${argument.name()}'`,370      );371    }372    this.registeredArguments.push(argument);373    return this;374  }375 376  /**377   * Customise or override default help command. By default a help command is automatically added if your command has subcommands.378   *379   * @example380   *    program.helpCommand('help [cmd]');381   *    program.helpCommand('help [cmd]', 'show help');382   *    program.helpCommand(false); // suppress default help command383   *    program.helpCommand(true); // add help command even if no subcommands384   *385   * @param {string|boolean} enableOrNameAndArgs - enable with custom name and/or arguments, or boolean to override whether added386   * @param {string} [description] - custom description387   * @return {Command} `this` command for chaining388   */389 390  helpCommand(enableOrNameAndArgs, description) {391    if (typeof enableOrNameAndArgs === 'boolean') {392      this._addImplicitHelpCommand = enableOrNameAndArgs;393      return this;394    }395 396    enableOrNameAndArgs = enableOrNameAndArgs ?? 'help [command]';397    const [, helpName, helpArgs] = enableOrNameAndArgs.match(/([^ ]+) *(.*)/);398    const helpDescription = description ?? 'display help for command';399 400    const helpCommand = this.createCommand(helpName);401    helpCommand.helpOption(false);402    if (helpArgs) helpCommand.arguments(helpArgs);403    if (helpDescription) helpCommand.description(helpDescription);404 405    this._addImplicitHelpCommand = true;406    this._helpCommand = helpCommand;407 408    return this;409  }410 411  /**412   * Add prepared custom help command.413   *414   * @param {(Command|string|boolean)} helpCommand - custom help command, or deprecated enableOrNameAndArgs as for `.helpCommand()`415   * @param {string} [deprecatedDescription] - deprecated custom description used with custom name only416   * @return {Command} `this` command for chaining417   */418  addHelpCommand(helpCommand, deprecatedDescription) {419    // If not passed an object, call through to helpCommand for backwards compatibility,420    // as addHelpCommand was originally used like helpCommand is now.421    if (typeof helpCommand !== 'object') {422      this.helpCommand(helpCommand, deprecatedDescription);423      return this;424    }425 426    this._addImplicitHelpCommand = true;427    this._helpCommand = helpCommand;428    return this;429  }430 431  /**432   * Lazy create help command.433   *434   * @return {(Command|null)}435   * @package436   */437  _getHelpCommand() {438    const hasImplicitHelpCommand =439      this._addImplicitHelpCommand ??440      (this.commands.length &&441        !this._actionHandler &&442        !this._findCommand('help'));443 444    if (hasImplicitHelpCommand) {445      if (this._helpCommand === undefined) {446        this.helpCommand(undefined, undefined); // use default name and description447      }448      return this._helpCommand;449    }450    return null;451  }452 453  /**454   * Add hook for life cycle event.455   *456   * @param {string} event457   * @param {Function} listener458   * @return {Command} `this` command for chaining459   */460 461  hook(event, listener) {462    const allowedValues = ['preSubcommand', 'preAction', 'postAction'];463    if (!allowedValues.includes(event)) {464      throw new Error(`Unexpected value for event passed to hook : '${event}'.465Expecting one of '${allowedValues.join("', '")}'`);466    }467    if (this._lifeCycleHooks[event]) {468      this._lifeCycleHooks[event].push(listener);469    } else {470      this._lifeCycleHooks[event] = [listener];471    }472    return this;473  }474 475  /**476   * Register callback to use as replacement for calling process.exit.477   *478   * @param {Function} [fn] optional callback which will be passed a CommanderError, defaults to throwing479   * @return {Command} `this` command for chaining480   */481 482  exitOverride(fn) {483    if (fn) {484      this._exitCallback = fn;485    } else {486      this._exitCallback = (err) => {487        if (err.code !== 'commander.executeSubCommandAsync') {488          throw err;489        } else {490          // Async callback from spawn events, not useful to throw.491        }492      };493    }494    return this;495  }496 497  /**498   * Call process.exit, and _exitCallback if defined.499   *500   * @param {number} exitCode exit code for using with process.exit501   * @param {string} code an id string representing the error502   * @param {string} message human-readable description of the error503   * @return never504   * @private505   */506 507  _exit(exitCode, code, message) {508    if (this._exitCallback) {509      this._exitCallback(new CommanderError(exitCode, code, message));510      // Expecting this line is not reached.511    }512    process.exit(exitCode);513  }514 515  /**516   * Register callback `fn` for the command.517   *518   * @example519   * program520   *   .command('serve')521   *   .description('start service')522   *   .action(function() {523   *      // do work here524   *   });525   *526   * @param {Function} fn527   * @return {Command} `this` command for chaining528   */529 530  action(fn) {531    const listener = (args) => {532      // The .action callback takes an extra parameter which is the command or options.533      const expectedArgsCount = this.registeredArguments.length;534      const actionArgs = args.slice(0, expectedArgsCount);535      if (this._storeOptionsAsProperties) {536        actionArgs[expectedArgsCount] = this; // backwards compatible "options"537      } else {538        actionArgs[expectedArgsCount] = this.opts();539      }540      actionArgs.push(this);541 542      return fn.apply(this, actionArgs);543    };544    this._actionHandler = listener;545    return this;546  }547 548  /**549   * Factory routine to create a new unattached option.550   *551   * See .option() for creating an attached option, which uses this routine to552   * create the option. You can override createOption to return a custom option.553   *554   * @param {string} flags555   * @param {string} [description]556   * @return {Option} new option557   */558 559  createOption(flags, description) {560    return new Option(flags, description);561  }562 563  /**564   * Wrap parseArgs to catch 'commander.invalidArgument'.565   *566   * @param {(Option | Argument)} target567   * @param {string} value568   * @param {*} previous569   * @param {string} invalidArgumentMessage570   * @private571   */572 573  _callParseArg(target, value, previous, invalidArgumentMessage) {574    try {575      return target.parseArg(value, previous);576    } catch (err) {577      if (err.code === 'commander.invalidArgument') {578        const message = `${invalidArgumentMessage} ${err.message}`;579        this.error(message, { exitCode: err.exitCode, code: err.code });580      }581      throw err;582    }583  }584 585  /**586   * Check for option flag conflicts.587   * Register option if no conflicts found, or throw on conflict.588   *589   * @param {Option} option590   * @private591   */592 593  _registerOption(option) {594    const matchingOption =595      (option.short && this._findOption(option.short)) ||596      (option.long && this._findOption(option.long));597    if (matchingOption) {598      const matchingFlag =599        option.long && this._findOption(option.long)600          ? option.long601          : option.short;602      throw new Error(`Cannot add option '${option.flags}'${this._name && ` to command '${this._name}'`} due to conflicting flag '${matchingFlag}'603-  already used by option '${matchingOption.flags}'`);604    }605 606    this.options.push(option);607  }608 609  /**610   * Check for command name and alias conflicts with existing commands.611   * Register command if no conflicts found, or throw on conflict.612   *613   * @param {Command} command614   * @private615   */616 617  _registerCommand(command) {618    const knownBy = (cmd) => {619      return [cmd.name()].concat(cmd.aliases());620    };621 622    const alreadyUsed = knownBy(command).find((name) =>623      this._findCommand(name),624    );625    if (alreadyUsed) {626      const existingCmd = knownBy(this._findCommand(alreadyUsed)).join('|');627      const newCmd = knownBy(command).join('|');628      throw new Error(629        `cannot add command '${newCmd}' as already have command '${existingCmd}'`,630      );631    }632 633    this.commands.push(command);634  }635 636  /**637   * Add an option.638   *639   * @param {Option} option640   * @return {Command} `this` command for chaining641   */642  addOption(option) {643    this._registerOption(option);644 645    const oname = option.name();646    const name = option.attributeName();647 648    // store default value649    if (option.negate) {650      // --no-foo is special and defaults foo to true, unless a --foo option is already defined651      const positiveLongFlag = option.long.replace(/^--no-/, '--');652      if (!this._findOption(positiveLongFlag)) {653        this.setOptionValueWithSource(654          name,655          option.defaultValue === undefined ? true : option.defaultValue,656          'default',657        );658      }659    } else if (option.defaultValue !== undefined) {660      this.setOptionValueWithSource(name, option.defaultValue, 'default');661    }662 663    // handler for cli and env supplied values664    const handleOptionValue = (val, invalidValueMessage, valueSource) => {665      // val is null for optional option used without an optional-argument.666      // val is undefined for boolean and negated option.667      if (val == null && option.presetArg !== undefined) {668        val = option.presetArg;669      }670 671      // custom processing672      const oldValue = this.getOptionValue(name);673      if (val !== null && option.parseArg) {674        val = this._callParseArg(option, val, oldValue, invalidValueMessage);675      } else if (val !== null && option.variadic) {676        val = option._concatValue(val, oldValue);677      }678 679      // Fill-in appropriate missing values. Long winded but easy to follow.680      if (val == null) {681        if (option.negate) {682          val = false;683        } else if (option.isBoolean() || option.optional) {684          val = true;685        } else {686          val = ''; // not normal, parseArg might have failed or be a mock function for testing687        }688      }689      this.setOptionValueWithSource(name, val, valueSource);690    };691 692    this.on('option:' + oname, (val) => {693      const invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`;694      handleOptionValue(val, invalidValueMessage, 'cli');695    });696 697    if (option.envVar) {698      this.on('optionEnv:' + oname, (val) => {699        const invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`;700        handleOptionValue(val, invalidValueMessage, 'env');701      });702    }703 704    return this;705  }706 707  /**708   * Internal implementation shared by .option() and .requiredOption()709   *710   * @return {Command} `this` command for chaining711   * @private712   */713  _optionEx(config, flags, description, fn, defaultValue) {714    if (typeof flags === 'object' && flags instanceof Option) {715      throw new Error(716        'To add an Option object use addOption() instead of option() or requiredOption()',717      );718    }719    const option = this.createOption(flags, description);720    option.makeOptionMandatory(!!config.mandatory);721    if (typeof fn === 'function') {722      option.default(defaultValue).argParser(fn);723    } else if (fn instanceof RegExp) {724      // deprecated725      const regex = fn;726      fn = (val, def) => {727        const m = regex.exec(val);728        return m ? m[0] : def;729      };730      option.default(defaultValue).argParser(fn);731    } else {732      option.default(fn);733    }734 735    return this.addOption(option);736  }737 738  /**739   * Define option with `flags`, `description`, and optional argument parsing function or `defaultValue` or both.740   *741   * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space. A required742   * option-argument is indicated by `<>` and an optional option-argument by `[]`.743   *744   * See the README for more details, and see also addOption() and requiredOption().745   *746   * @example747   * program748   *     .option('-p, --pepper', 'add pepper')749   *     .option('-p, --pizza-type <TYPE>', 'type of pizza') // required option-argument750   *     .option('-c, --cheese [CHEESE]', 'add extra cheese', 'mozzarella') // optional option-argument with default751   *     .option('-t, --tip <VALUE>', 'add tip to purchase cost', parseFloat) // custom parse function752   *753   * @param {string} flags754   * @param {string} [description]755   * @param {(Function|*)} [parseArg] - custom option processing function or default value756   * @param {*} [defaultValue]757   * @return {Command} `this` command for chaining758   */759 760  option(flags, description, parseArg, defaultValue) {761    return this._optionEx({}, flags, description, parseArg, defaultValue);762  }763 764  /**765   * Add a required option which must have a value after parsing. This usually means766   * the option must be specified on the command line. (Otherwise the same as .option().)767   *768   * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space.769   *770   * @param {string} flags771   * @param {string} [description]772   * @param {(Function|*)} [parseArg] - custom option processing function or default value773   * @param {*} [defaultValue]774   * @return {Command} `this` command for chaining775   */776 777  requiredOption(flags, description, parseArg, defaultValue) {778    return this._optionEx(779      { mandatory: true },780      flags,781      description,782      parseArg,783      defaultValue,784    );785  }786 787  /**788   * Alter parsing of short flags with optional values.789   *790   * @example791   * // for `.option('-f,--flag [value]'):792   * program.combineFlagAndOptionalValue(true);  // `-f80` is treated like `--flag=80`, this is the default behaviour793   * program.combineFlagAndOptionalValue(false) // `-fb` is treated like `-f -b`794   *795   * @param {boolean} [combine] - if `true` or omitted, an optional value can be specified directly after the flag.796   * @return {Command} `this` command for chaining797   */798  combineFlagAndOptionalValue(combine = true) {799    this._combineFlagAndOptionalValue = !!combine;800    return this;801  }802 803  /**804   * Allow unknown options on the command line.805   *806   * @param {boolean} [allowUnknown] - if `true` or omitted, no error will be thrown for unknown options.807   * @return {Command} `this` command for chaining808   */809  allowUnknownOption(allowUnknown = true) {810    this._allowUnknownOption = !!allowUnknown;811    return this;812  }813 814  /**815   * Allow excess command-arguments on the command line. Pass false to make excess arguments an error.816   *817   * @param {boolean} [allowExcess] - if `true` or omitted, no error will be thrown for excess arguments.818   * @return {Command} `this` command for chaining819   */820  allowExcessArguments(allowExcess = true) {821    this._allowExcessArguments = !!allowExcess;822    return this;823  }824 825  /**826   * Enable positional options. Positional means global options are specified before subcommands which lets827   * subcommands reuse the same option names, and also enables subcommands to turn on passThroughOptions.828   * The default behaviour is non-positional and global options may appear anywhere on the command line.829   *830   * @param {boolean} [positional]831   * @return {Command} `this` command for chaining832   */833  enablePositionalOptions(positional = true) {834    this._enablePositionalOptions = !!positional;835    return this;836  }837 838  /**839   * Pass through options that come after command-arguments rather than treat them as command-options,840   * so actual command-options come before command-arguments. Turning this on for a subcommand requires841   * positional options to have been enabled on the program (parent commands).842   * The default behaviour is non-positional and options may appear before or after command-arguments.843   *844   * @param {boolean} [passThrough] for unknown options.845   * @return {Command} `this` command for chaining846   */847  passThroughOptions(passThrough = true) {848    this._passThroughOptions = !!passThrough;849    this._checkForBrokenPassThrough();850    return this;851  }852 853  /**854   * @private855   */856 857  _checkForBrokenPassThrough() {858    if (859      this.parent &&860      this._passThroughOptions &&861      !this.parent._enablePositionalOptions862    ) {863      throw new Error(864        `passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`,865      );866    }867  }868 869  /**870   * Whether to store option values as properties on command object,871   * or store separately (specify false). In both cases the option values can be accessed using .opts().872   *873   * @param {boolean} [storeAsProperties=true]874   * @return {Command} `this` command for chaining875   */876 877  storeOptionsAsProperties(storeAsProperties = true) {878    if (this.options.length) {879      throw new Error('call .storeOptionsAsProperties() before adding options');880    }881    if (Object.keys(this._optionValues).length) {882      throw new Error(883        'call .storeOptionsAsProperties() before setting option values',884      );885    }886    this._storeOptionsAsProperties = !!storeAsProperties;887    return this;888  }889 890  /**891   * Retrieve option value.892   *893   * @param {string} key894   * @return {object} value895   */896 897  getOptionValue(key) {898    if (this._storeOptionsAsProperties) {899      return this[key];900    }901    return this._optionValues[key];902  }903 904  /**905   * Store option value.906   *907   * @param {string} key908   * @param {object} value909   * @return {Command} `this` command for chaining910   */911 912  setOptionValue(key, value) {913    return this.setOptionValueWithSource(key, value, undefined);914  }915 916  /**917   * Store option value and where the value came from.918   *919   * @param {string} key920   * @param {object} value921   * @param {string} source - expected values are default/config/env/cli/implied922   * @return {Command} `this` command for chaining923   */924 925  setOptionValueWithSource(key, value, source) {926    if (this._storeOptionsAsProperties) {927      this[key] = value;928    } else {929      this._optionValues[key] = value;930    }931    this._optionValueSources[key] = source;932    return this;933  }934 935  /**936   * Get source of option value.937   * Expected values are default | config | env | cli | implied938   *939   * @param {string} key940   * @return {string}941   */942 943  getOptionValueSource(key) {944    return this._optionValueSources[key];945  }946 947  /**948   * Get source of option value. See also .optsWithGlobals().949   * Expected values are default | config | env | cli | implied950   *951   * @param {string} key952   * @return {string}953   */954 955  getOptionValueSourceWithGlobals(key) {956    // global overwrites local, like optsWithGlobals957    let source;958    this._getCommandAndAncestors().forEach((cmd) => {959      if (cmd.getOptionValueSource(key) !== undefined) {960        source = cmd.getOptionValueSource(key);961      }962    });963    return source;964  }965 966  /**967   * Get user arguments from implied or explicit arguments.968   * Side-effects: set _scriptPath if args included script. Used for default program name, and subcommand searches.969   *970   * @private971   */972 973  _prepareUserArgs(argv, parseOptions) {974    if (argv !== undefined && !Array.isArray(argv)) {975      throw new Error('first parameter to parse must be array or undefined');976    }977    parseOptions = parseOptions || {};978 979    // auto-detect argument conventions if nothing supplied980    if (argv === undefined && parseOptions.from === undefined) {981      if (process.versions?.electron) {982        parseOptions.from = 'electron';983      }984      // check node specific options for scenarios where user CLI args follow executable without scriptname985      const execArgv = process.execArgv ?? [];986      if (987        execArgv.includes('-e') ||988        execArgv.includes('--eval') ||989        execArgv.includes('-p') ||990        execArgv.includes('--print')991      ) {992        parseOptions.from = 'eval'; // internal usage, not documented993      }994    }995 996    // default to using process.argv997    if (argv === undefined) {998      argv = process.argv;999    }1000    this.rawArgs = argv.slice();1001 1002    // extract the user args and scriptPath1003    let userArgs;1004    switch (parseOptions.from) {1005      case undefined:1006      case 'node':1007        this._scriptPath = argv[1];1008        userArgs = argv.slice(2);1009        break;1010      case 'electron':1011        // @ts-ignore: because defaultApp is an unknown property1012        if (process.defaultApp) {1013          this._scriptPath = argv[1];1014          userArgs = argv.slice(2);1015        } else {1016          userArgs = argv.slice(1);1017        }1018        break;1019      case 'user':1020        userArgs = argv.slice(0);1021        break;1022      case 'eval':1023        userArgs = argv.slice(1);1024        break;1025      default:1026        throw new Error(1027          `unexpected parse option { from: '${parseOptions.from}' }`,1028        );1029    }1030 1031    // Find default name for program from arguments.1032    if (!this._name && this._scriptPath)1033      this.nameFromFilename(this._scriptPath);1034    this._name = this._name || 'program';1035 1036    return userArgs;1037  }1038 1039  /**1040   * Parse `argv`, setting options and invoking commands when defined.1041   *1042   * Use parseAsync instead of parse if any of your action handlers are async.1043   *1044   * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!1045   *1046   * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:1047   * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that1048   * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged1049   * - `'user'`: just user arguments1050   *1051   * @example1052   * program.parse(); // parse process.argv and auto-detect electron and special node flags1053   * program.parse(process.argv); // assume argv[0] is app and argv[1] is script1054   * program.parse(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]1055   *1056   * @param {string[]} [argv] - optional, defaults to process.argv1057   * @param {object} [parseOptions] - optionally specify style of options with from: node/user/electron1058   * @param {string} [parseOptions.from] - where the args are from: 'node', 'user', 'electron'1059   * @return {Command} `this` command for chaining1060   */1061 1062  parse(argv, parseOptions) {1063    const userArgs = this._prepareUserArgs(argv, parseOptions);1064    this._parseCommand([], userArgs);1065 1066    return this;1067  }1068 1069  /**1070   * Parse `argv`, setting options and invoking commands when defined.1071   *1072   * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!1073   *1074   * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:1075   * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that1076   * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged1077   * - `'user'`: just user arguments1078   *1079   * @example1080   * await program.parseAsync(); // parse process.argv and auto-detect electron and special node flags1081   * await program.parseAsync(process.argv); // assume argv[0] is app and argv[1] is script1082   * await program.parseAsync(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]1083   *1084   * @param {string[]} [argv]1085   * @param {object} [parseOptions]1086   * @param {string} parseOptions.from - where the args are from: 'node', 'user', 'electron'1087   * @return {Promise}1088   */1089 1090  async parseAsync(argv, parseOptions) {1091    const userArgs = this._prepareUserArgs(argv, parseOptions);1092    await this._parseCommand([], userArgs);1093 1094    return this;1095  }1096 1097  /**1098   * Execute a sub-command executable.1099   *1100   * @private1101   */1102 1103  _executeSubCommand(subcommand, args) {1104    args = args.slice();1105    let launchWithNode = false; // Use node for source targets so do not need to get permissions correct, and on Windows.1106    const sourceExt = ['.js', '.ts', '.tsx', '.mjs', '.cjs'];1107 1108    function findFile(baseDir, baseName) {1109      // Look for specified file1110      const localBin = path.resolve(baseDir, baseName);1111      if (fs.existsSync(localBin)) return localBin;1112 1113      // Stop looking if candidate already has an expected extension.1114      if (sourceExt.includes(path.extname(baseName))) return undefined;1115 1116      // Try all the extensions.1117      const foundExt = sourceExt.find((ext) =>1118        fs.existsSync(`${localBin}${ext}`),1119      );1120      if (foundExt) return `${localBin}${foundExt}`;1121 1122      return undefined;1123    }1124 1125    // Not checking for help first. Unlikely to have mandatory and executable, and can't robustly test for help flags in external command.1126    this._checkForMissingMandatoryOptions();1127    this._checkForConflictingOptions();1128 1129    // executableFile and executableDir might be full path, or just a name1130    let executableFile =1131      subcommand._executableFile || `${this._name}-${subcommand._name}`;1132    let executableDir = this._executableDir || '';1133    if (this._scriptPath) {1134      let resolvedScriptPath; // resolve possible symlink for installed npm binary1135      try {1136        resolvedScriptPath = fs.realpathSync(this._scriptPath);1137      } catch (err) {1138        resolvedScriptPath = this._scriptPath;1139      }1140      executableDir = path.resolve(1141        path.dirname(resolvedScriptPath),1142        executableDir,1143      );1144    }1145 1146    // Look for a local file in preference to a command in PATH.1147    if (executableDir) {1148      let localFile = findFile(executableDir, executableFile);1149 1150      // Legacy search using prefix of script name instead of command name1151      if (!localFile && !subcommand._executableFile && this._scriptPath) {1152        const legacyName = path.basename(1153          this._scriptPath,1154          path.extname(this._scriptPath),1155        );1156        if (legacyName !== this._name) {1157          localFile = findFile(1158            executableDir,1159            `${legacyName}-${subcommand._name}`,1160          );1161        }1162      }1163      executableFile = localFile || executableFile;1164    }1165 1166    launchWithNode = sourceExt.includes(path.extname(executableFile));1167 1168    let proc;1169    if (process.platform !== 'win32') {1170      if (launchWithNode) {1171        args.unshift(executableFile);1172        // add executable arguments to spawn1173        args = incrementNodeInspectorPort(process.execArgv).concat(args);1174 1175        proc = childProcess.spawn(process.argv[0], args, { stdio: 'inherit' });1176      } else {1177        proc = childProcess.spawn(executableFile, args, { stdio: 'inherit' });1178      }1179    } else {1180      args.unshift(executableFile);1181      // add executable arguments to spawn1182      args = incrementNodeInspectorPort(process.execArgv).concat(args);1183      proc = childProcess.spawn(process.execPath, args, { stdio: 'inherit' });1184    }1185 1186    if (!proc.killed) {1187      // testing mainly to avoid leak warnings during unit tests with mocked spawn1188      const signals = ['SIGUSR1', 'SIGUSR2', 'SIGTERM', 'SIGINT', 'SIGHUP'];1189      signals.forEach((signal) => {1190        process.on(signal, () => {1191          if (proc.killed === false && proc.exitCode === null) {1192            // @ts-ignore because signals not typed to known strings1193            proc.kill(signal);1194          }1195        });1196      });1197    }1198 1199    // By default terminate process when spawned process terminates.1200    const exitCallback = this._exitCallback;

Showing the first 1,200 of 2510 lines. Download the file for the rest.

basant307/AI_Governance_Project · CoolFace