diff options
Diffstat (limited to 'node_modules/arg')
| -rw-r--r-- | node_modules/arg/LICENSE.md | 21 | ||||
| -rw-r--r-- | node_modules/arg/README.md | 317 | ||||
| -rw-r--r-- | node_modules/arg/index.d.ts | 44 | ||||
| -rw-r--r-- | node_modules/arg/index.js | 195 | ||||
| -rw-r--r-- | node_modules/arg/package.json | 28 |
5 files changed, 605 insertions, 0 deletions
diff --git a/node_modules/arg/LICENSE.md b/node_modules/arg/LICENSE.md new file mode 100644 index 0000000..b708f87 --- /dev/null +++ b/node_modules/arg/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2021 Vercel, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/arg/README.md b/node_modules/arg/README.md new file mode 100644 index 0000000..6501df5 --- /dev/null +++ b/node_modules/arg/README.md @@ -0,0 +1,317 @@ +# Arg + +`arg` is an unopinionated, no-frills CLI argument parser. + +## Installation + +```bash +npm install arg +``` + +## Usage + +`arg()` takes either 1 or 2 arguments: + +1. Command line specification object (see below) +2. Parse options (_Optional_, defaults to `{permissive: false, argv: process.argv.slice(2), stopAtPositional: false}`) + +It returns an object with any values present on the command-line (missing options are thus +missing from the resulting object). Arg performs no validation/requirement checking - we +leave that up to the application. + +All parameters that aren't consumed by options (commonly referred to as "extra" parameters) +are added to `result._`, which is _always_ an array (even if no extra parameters are passed, +in which case an empty array is returned). + +```javascript +const arg = require('arg'); + +// `options` is an optional parameter +const args = arg( + spec, + (options = { permissive: false, argv: process.argv.slice(2) }) +); +``` + +For example: + +```console +$ node ./hello.js --verbose -vvv --port=1234 -n 'My name' foo bar --tag qux --tag=qix -- --foobar +``` + +```javascript +// hello.js +const arg = require('arg'); + +const args = arg({ + // Types + '--help': Boolean, + '--version': Boolean, + '--verbose': arg.COUNT, // Counts the number of times --verbose is passed + '--port': Number, // --port <number> or --port=<number> + '--name': String, // --name <string> or --name=<string> + '--tag': [String], // --tag <string> or --tag=<string> + + // Aliases + '-v': '--verbose', + '-n': '--name', // -n <string>; result is stored in --name + '--label': '--name' // --label <string> or --label=<string>; + // result is stored in --name +}); + +console.log(args); +/* +{ + _: ["foo", "bar", "--foobar"], + '--port': 1234, + '--verbose': 4, + '--name': "My name", + '--tag': ["qux", "qix"] +} +*/ +``` + +The values for each key=>value pair is either a type (function or [function]) or a string (indicating an alias). + +- In the case of a function, the string value of the argument's value is passed to it, + and the return value is used as the ultimate value. + +- In the case of an array, the only element _must_ be a type function. Array types indicate + that the argument may be passed multiple times, and as such the resulting value in the returned + object is an array with all of the values that were passed using the specified flag. + +- In the case of a string, an alias is established. If a flag is passed that matches the _key_, + then the _value_ is substituted in its place. + +Type functions are passed three arguments: + +1. The parameter value (always a string) +2. The parameter name (e.g. `--label`) +3. The previous value for the destination (useful for reduce-like operations or for supporting `-v` multiple times, etc.) + +This means the built-in `String`, `Number`, and `Boolean` type constructors "just work" as type functions. + +Note that `Boolean` and `[Boolean]` have special treatment - an option argument is _not_ consumed or passed, but instead `true` is +returned. These options are called "flags". + +For custom handlers that wish to behave as flags, you may pass the function through `arg.flag()`: + +```javascript +const arg = require('arg'); + +const argv = [ + '--foo', + 'bar', + '-ff', + 'baz', + '--foo', + '--foo', + 'qux', + '-fff', + 'qix' +]; + +function myHandler(value, argName, previousValue) { + /* `value` is always `true` */ + return 'na ' + (previousValue || 'batman!'); +} + +const args = arg( + { + '--foo': arg.flag(myHandler), + '-f': '--foo' + }, + { + argv + } +); + +console.log(args); +/* +{ + _: ['bar', 'baz', 'qux', 'qix'], + '--foo': 'na na na na na na na na batman!' +} +*/ +``` + +As well, `arg` supplies a helper argument handler called `arg.COUNT`, which equivalent to a `[Boolean]` argument's `.length` +property - effectively counting the number of times the boolean flag, denoted by the key, is passed on the command line.. +For example, this is how you could implement `ssh`'s multiple levels of verbosity (`-vvvv` being the most verbose). + +```javascript +const arg = require('arg'); + +const argv = ['-AAAA', '-BBBB']; + +const args = arg( + { + '-A': arg.COUNT, + '-B': [Boolean] + }, + { + argv + } +); + +console.log(args); +/* +{ + _: [], + '-A': 4, + '-B': [true, true, true, true] +} +*/ +``` + +### Options + +If a second parameter is specified and is an object, it specifies parsing options to modify the behavior of `arg()`. + +#### `argv` + +If you have already sliced or generated a number of raw arguments to be parsed (as opposed to letting `arg` +slice them from `process.argv`) you may specify them in the `argv` option. + +For example: + +```javascript +const args = arg( + { + '--foo': String + }, + { + argv: ['hello', '--foo', 'world'] + } +); +``` + +results in: + +```javascript +const args = { + _: ['hello'], + '--foo': 'world' +}; +``` + +#### `permissive` + +When `permissive` set to `true`, `arg` will push any unknown arguments +onto the "extra" argument array (`result._`) instead of throwing an error about +an unknown flag. + +For example: + +```javascript +const arg = require('arg'); + +const argv = [ + '--foo', + 'hello', + '--qux', + 'qix', + '--bar', + '12345', + 'hello again' +]; + +const args = arg( + { + '--foo': String, + '--bar': Number + }, + { + argv, + permissive: true + } +); +``` + +results in: + +```javascript +const args = { + _: ['--qux', 'qix', 'hello again'], + '--foo': 'hello', + '--bar': 12345 +}; +``` + +#### `stopAtPositional` + +When `stopAtPositional` is set to `true`, `arg` will halt parsing at the first +positional argument. + +For example: + +```javascript +const arg = require('arg'); + +const argv = ['--foo', 'hello', '--bar']; + +const args = arg( + { + '--foo': Boolean, + '--bar': Boolean + }, + { + argv, + stopAtPositional: true + } +); +``` + +results in: + +```javascript +const args = { + _: ['hello', '--bar'], + '--foo': true +}; +``` + +### Errors + +Some errors that `arg` throws provide a `.code` property in order to aid in recovering from user error, or to +differentiate between user error and developer error (bug). + +##### ARG_UNKNOWN_OPTION + +If an unknown option (not defined in the spec object) is passed, an error with code `ARG_UNKNOWN_OPTION` will be thrown: + +```js +// cli.js +try { + require('arg')({ '--hi': String }); +} catch (err) { + if (err.code === 'ARG_UNKNOWN_OPTION') { + console.log(err.message); + } else { + throw err; + } +} +``` + +```shell +node cli.js --extraneous true +Unknown or unexpected option: --extraneous +``` + +# FAQ + +A few questions and answers that have been asked before: + +### How do I require an argument with `arg`? + +Do the assertion yourself, such as: + +```javascript +const args = arg({ '--name': String }); + +if (!args['--name']) throw new Error('missing required argument: --name'); +``` + +# License + +Released under the [MIT License](LICENSE.md). diff --git a/node_modules/arg/index.d.ts b/node_modules/arg/index.d.ts new file mode 100644 index 0000000..44f9f35 --- /dev/null +++ b/node_modules/arg/index.d.ts @@ -0,0 +1,44 @@ +declare function arg<T extends arg.Spec>( + spec: T, + options?: arg.Options +): arg.Result<T>; + +declare namespace arg { + export const flagSymbol: unique symbol; + + export function flag<T>(fn: T): T & { [arg.flagSymbol]: true }; + + export const COUNT: Handler<number> & { [arg.flagSymbol]: true }; + + export type Handler<T = any> = ( + value: string, + name: string, + previousValue?: T + ) => T; + + export class ArgError extends Error { + constructor(message: string, code: string); + + code: string; + } + + export interface Spec { + [key: string]: string | Handler | [Handler]; + } + + export type Result<T extends Spec> = { _: string[] } & { + [K in keyof T]?: T[K] extends Handler + ? ReturnType<T[K]> + : T[K] extends [Handler] + ? Array<ReturnType<T[K][0]>> + : never; + }; + + export interface Options { + argv?: string[]; + permissive?: boolean; + stopAtPositional?: boolean; + } +} + +export = arg; diff --git a/node_modules/arg/index.js b/node_modules/arg/index.js new file mode 100644 index 0000000..3f60f4c --- /dev/null +++ b/node_modules/arg/index.js @@ -0,0 +1,195 @@ +const flagSymbol = Symbol('arg flag'); + +class ArgError extends Error { + constructor(msg, code) { + super(msg); + this.name = 'ArgError'; + this.code = code; + + Object.setPrototypeOf(this, ArgError.prototype); + } +} + +function arg( + opts, + { + argv = process.argv.slice(2), + permissive = false, + stopAtPositional = false + } = {} +) { + if (!opts) { + throw new ArgError( + 'argument specification object is required', + 'ARG_CONFIG_NO_SPEC' + ); + } + + const result = { _: [] }; + + const aliases = {}; + const handlers = {}; + + for (const key of Object.keys(opts)) { + if (!key) { + throw new ArgError( + 'argument key cannot be an empty string', + 'ARG_CONFIG_EMPTY_KEY' + ); + } + + if (key[0] !== '-') { + throw new ArgError( + `argument key must start with '-' but found: '${key}'`, + 'ARG_CONFIG_NONOPT_KEY' + ); + } + + if (key.length === 1) { + throw new ArgError( + `argument key must have a name; singular '-' keys are not allowed: ${key}`, + 'ARG_CONFIG_NONAME_KEY' + ); + } + + if (typeof opts[key] === 'string') { + aliases[key] = opts[key]; + continue; + } + + let type = opts[key]; + let isFlag = false; + + if ( + Array.isArray(type) && + type.length === 1 && + typeof type[0] === 'function' + ) { + const [fn] = type; + type = (value, name, prev = []) => { + prev.push(fn(value, name, prev[prev.length - 1])); + return prev; + }; + isFlag = fn === Boolean || fn[flagSymbol] === true; + } else if (typeof type === 'function') { + isFlag = type === Boolean || type[flagSymbol] === true; + } else { + throw new ArgError( + `type missing or not a function or valid array type: ${key}`, + 'ARG_CONFIG_VAD_TYPE' + ); + } + + if (key[1] !== '-' && key.length > 2) { + throw new ArgError( + `short argument keys (with a single hyphen) must have only one character: ${key}`, + 'ARG_CONFIG_SHORTOPT_TOOLONG' + ); + } + + handlers[key] = [type, isFlag]; + } + + for (let i = 0, len = argv.length; i < len; i++) { + const wholeArg = argv[i]; + + if (stopAtPositional && result._.length > 0) { + result._ = result._.concat(argv.slice(i)); + break; + } + + if (wholeArg === '--') { + result._ = result._.concat(argv.slice(i + 1)); + break; + } + + if (wholeArg.length > 1 && wholeArg[0] === '-') { + /* eslint-disable operator-linebreak */ + const separatedArguments = + wholeArg[1] === '-' || wholeArg.length === 2 + ? [wholeArg] + : wholeArg + .slice(1) + .split('') + .map((a) => `-${a}`); + /* eslint-enable operator-linebreak */ + + for (let j = 0; j < separatedArguments.length; j++) { + const arg = separatedArguments[j]; + const [originalArgName, argStr] = + arg[1] === '-' ? arg.split(/=(.*)/, 2) : [arg, undefined]; + + let argName = originalArgName; + while (argName in aliases) { + argName = aliases[argName]; + } + + if (!(argName in handlers)) { + if (permissive) { + result._.push(arg); + continue; + } else { + throw new ArgError( + `unknown or unexpected option: ${originalArgName}`, + 'ARG_UNKNOWN_OPTION' + ); + } + } + + const [type, isFlag] = handlers[argName]; + + if (!isFlag && j + 1 < separatedArguments.length) { + throw new ArgError( + `option requires argument (but was followed by another short argument): ${originalArgName}`, + 'ARG_MISSING_REQUIRED_SHORTARG' + ); + } + + if (isFlag) { + result[argName] = type(true, argName, result[argName]); + } else if (argStr === undefined) { + if ( + argv.length < i + 2 || + (argv[i + 1].length > 1 && + argv[i + 1][0] === '-' && + !( + argv[i + 1].match(/^-?\d*(\.(?=\d))?\d*$/) && + (type === Number || + // eslint-disable-next-line no-undef + (typeof BigInt !== 'undefined' && type === BigInt)) + )) + ) { + const extended = + originalArgName === argName ? '' : ` (alias for ${argName})`; + throw new ArgError( + `option requires argument: ${originalArgName}${extended}`, + 'ARG_MISSING_REQUIRED_LONGARG' + ); + } + + result[argName] = type(argv[i + 1], argName, result[argName]); + ++i; + } else { + result[argName] = type(argStr, argName, result[argName]); + } + } + } else { + result._.push(wholeArg); + } + } + + return result; +} + +arg.flag = (fn) => { + fn[flagSymbol] = true; + return fn; +}; + +// Utility types +arg.COUNT = arg.flag((v, name, existingCount) => (existingCount || 0) + 1); + +// Expose error class +arg.ArgError = ArgError; + +module.exports = arg; diff --git a/node_modules/arg/package.json b/node_modules/arg/package.json new file mode 100644 index 0000000..47368d7 --- /dev/null +++ b/node_modules/arg/package.json @@ -0,0 +1,28 @@ +{ + "name": "arg", + "version": "5.0.2", + "description": "Unopinionated, no-frills CLI argument parser", + "main": "index.js", + "types": "index.d.ts", + "repository": "vercel/arg", + "author": "Josh Junon <junon@wavetilt.com>", + "license": "MIT", + "files": [ + "index.js", + "index.d.ts" + ], + "scripts": { + "test": "WARN_EXIT=1 jest --coverage -w 2" + }, + "devDependencies": { + "chai": "^4.1.1", + "jest": "^27.0.6", + "prettier": "^2.3.2" + }, + "prettier": { + "arrowParens": "always", + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "none" + } +} |