change approach again

This commit is contained in:
2018-05-09 14:31:22 +02:00
parent 54a933c83a
commit 0686e02b75
2252 changed files with 864743 additions and 270 deletions

96
node_modules/command-line-args/lib/argv.js generated vendored Normal file
View File

@ -0,0 +1,96 @@
'use strict'
const arrayify = require('array-back')
const option = require('./option')
/**
* Handles parsing different argv notations
*
* @module argv
* @private
*/
class Argv extends Array {
load (argv) {
if (argv) {
argv = arrayify(argv)
} else {
/* if no argv supplied, assume we are parsing process.argv */
argv = process.argv.slice(0)
argv.splice(0, 2)
}
argv.forEach(arg => this.push(String(arg)))
}
clear () {
this.length = 0
}
/**
* expand --option=value style args. The value is clearly marked to indicate it is definitely a value (which would otherwise be unclear if the value is `--value`, which would be parsed as an option). The special marker is removed in parsing phase.
*/
expandOptionEqualsNotation () {
const optEquals = option.optEquals
if (this.some(optEquals.test.bind(optEquals))) {
const expandedArgs = []
this.forEach(arg => {
const matches = arg.match(optEquals)
if (matches) {
expandedArgs.push(matches[1], option.VALUE_MARKER + matches[2])
} else {
expandedArgs.push(arg)
}
})
this.clear()
this.load(expandedArgs)
}
}
/**
* expand getopt-style combined options
*/
expandGetoptNotation () {
const findReplace = require('find-replace')
const combinedArg = option.combined
const hasGetopt = this.some(combinedArg.test.bind(combinedArg))
if (hasGetopt) {
findReplace(this, combinedArg, arg => {
arg = arg.slice(1)
return arg.split('').map(letter => '-' + letter)
})
}
}
/**
* Inspect the user-supplied options for validation issues.
* @throws `UNKNOWN_OPTION`
*/
validate (definitions, options) {
options = options || {}
let invalidOption
if (!options.partial) {
const optionWithoutDefinition = this
.filter(arg => option.isOption(arg))
.some(arg => {
if (definitions.get(arg) === undefined) {
invalidOption = arg
return true
}
})
if (optionWithoutDefinition) {
halt(
'UNKNOWN_OPTION',
'Unknown option: ' + invalidOption
)
}
}
}
}
function halt (name, message) {
const err = new Error(message)
err.name = name
throw err
}
module.exports = Argv

View File

@ -0,0 +1,58 @@
'use strict'
/**
* @module command-line-args
*/
module.exports = commandLineArgs
/**
* Returns an object containing all options set on the command line. By default it parses the global [`process.argv`](https://nodejs.org/api/process.html#process_process_argv) array.
*
* By default, an exception is thrown if the user sets an unknown option (one without a valid [definition](#exp_module_definition--OptionDefinition)). To enable __partial parsing__, invoke `commandLineArgs` with the `partial` option - all unknown arguments will be returned in the `_unknown` property.
*
*
* @param {module:definition[]} - An array of [OptionDefinition](#exp_module_definition--OptionDefinition) objects
* @param [options] {object} - Options.
* @param [options.argv] {string[]} - An array of strings, which if passed will be parsed instead of `process.argv`.
* @param [options.partial] {boolean} - If `true`, an array of unknown arguments is returned in the `_unknown` property of the output.
* @returns {object}
* @throws `UNKNOWN_OPTION` if `options.partial` is false and the user set an undefined option
* @throws `NAME_MISSING` if an option definition is missing the required `name` property
* @throws `INVALID_TYPE` if an option definition has a `type` value that's not a function
* @throws `INVALID_ALIAS` if an alias is numeric, a hyphen or a length other than 1
* @throws `DUPLICATE_NAME` if an option definition name was used more than once
* @throws `DUPLICATE_ALIAS` if an option definition alias was used more than once
* @throws `DUPLICATE_DEFAULT_OPTION` if more than one option definition has `defaultOption: true`
* @alias module:command-line-args
*/
function commandLineArgs (optionDefinitions, options) {
options = options || {}
const Definitions = require('./definitions')
const Argv = require('./argv')
const definitions = new Definitions()
definitions.load(optionDefinitions)
const argv = new Argv()
argv.load(options.argv)
argv.expandOptionEqualsNotation()
argv.expandGetoptNotation()
argv.validate(definitions, options)
const OutputClass = definitions.isGrouped() ? require('./grouped-output') : require('./output')
const output = new OutputClass(definitions, options)
let optionName
const option = require('./option')
for (const arg of argv) {
if (option.isOption(arg)) {
optionName = output.setFlag(arg) ? undefined : arg
} else {
if (optionName) {
optionName = output.setOptionValue(optionName, arg) ? undefined : optionName
} else {
optionName = output.setValue(arg) ? undefined : optionName
}
}
}
return output.toObject()
}

236
node_modules/command-line-args/lib/definition.js generated vendored Normal file
View File

@ -0,0 +1,236 @@
'use strict'
const t = require('typical')
/**
* @module definition
*/
/**
* Describes a command-line option. Additionally, you can add `description` and `typeLabel` properties and make use of [command-line-usage](https://github.com/75lb/command-line-usage).
* @alias module:definition
* @typicalname option
*/
class OptionDefinition {
constructor (definition) {
/**
* The only required definition property is `name`, so the simplest working example is
* ```js
* [
* { name: "file" },
* { name: "verbose" },
* { name: "depth"}
* ]
* ```
*
* In this case, the value of each option will be either a Boolean or string.
*
* | # | Command line args | .parse() output |
* | --- | -------------------- | ------------ |
* | 1 | `--file` | `{ file: true }` |
* | 2 | `--file lib.js --verbose` | `{ file: "lib.js", verbose: true }` |
* | 3 | `--verbose very` | `{ verbose: "very" }` |
* | 4 | `--depth 2` | `{ depth: "2" }` |
*
* Unicode option names and aliases are valid, for example:
* ```js
* [
* { name: 'один' },
* { name: '两' },
* { name: 'три', alias: 'т' }
* ]
* ```
* @type {string}
*/
this.name = definition.name
/**
* The `type` value is a setter function (you receive the output from this), enabling you to be specific about the type and value received.
*
* You can use a class, if you like:
*
* ```js
* const fs = require('fs')
*
* function FileDetails(filename){
* if (!(this instanceof FileDetails)) return new FileDetails(filename)
* this.filename = filename
* this.exists = fs.existsSync(filename)
* }
*
* const cli = commandLineArgs([
* { name: 'file', type: FileDetails },
* { name: 'depth', type: Number }
* ])
* ```
*
* | # | Command line args| .parse() output |
* | --- | ----------------- | ------------ |
* | 1 | `--file asdf.txt` | `{ file: { filename: 'asdf.txt', exists: false } }` |
*
* The `--depth` option expects a `Number`. If no value was set, you will receive `null`.
*
* | # | Command line args | .parse() output |
* | --- | ----------------- | ------------ |
* | 2 | `--depth` | `{ depth: null }` |
* | 3 | `--depth 2` | `{ depth: 2 }` |
*
* @type {function}
* @default String
*/
this.type = definition.type || String
/**
* getopt-style short option names. Can be any single character (unicode included) except a digit or hypen.
*
* ```js
* [
* { name: "hot", alias: "h", type: Boolean },
* { name: "discount", alias: "d", type: Boolean },
* { name: "courses", alias: "c" , type: Number }
* ]
* ```
*
* | # | Command line | .parse() output |
* | --- | ------------ | ------------ |
* | 1 | `-hcd` | `{ hot: true, courses: null, discount: true }` |
* | 2 | `-hdc 3` | `{ hot: true, discount: true, courses: 3 }` |
*
* @type {string}
*/
this.alias = definition.alias
/**
* Set this flag if the option takes a list of values. You will receive an array of values, each passed through the `type` function (if specified).
*
* ```js
* [
* { name: "files", type: String, multiple: true }
* ]
* ```
*
* | # | Command line | .parse() output |
* | --- | ------------ | ------------ |
* | 1 | `--files one.js two.js` | `{ files: [ 'one.js', 'two.js' ] }` |
* | 2 | `--files one.js --files two.js` | `{ files: [ 'one.js', 'two.js' ] }` |
* | 3 | `--files *` | `{ files: [ 'one.js', 'two.js' ] }` |
*
* @type {boolean}
*/
this.multiple = definition.multiple
/**
* Any unclaimed command-line args will be set on this option. This flag is typically set on the most commonly-used option to make for more concise usage (i.e. `$ myapp *.js` instead of `$ myapp --files *.js`).
*
* ```js
* [
* { name: "files", type: String, multiple: true, defaultOption: true }
* ]
* ```
*
* | # | Command line | .parse() output |
* | --- | ------------ | ------------ |
* | 1 | `--files one.js two.js` | `{ files: [ 'one.js', 'two.js' ] }` |
* | 2 | `one.js two.js` | `{ files: [ 'one.js', 'two.js' ] }` |
* | 3 | `*` | `{ files: [ 'one.js', 'two.js' ] }` |
*
* @type {boolean}
*/
this.defaultOption = definition.defaultOption
/**
* An initial value for the option.
*
* ```js
* [
* { name: "files", type: String, multiple: true, defaultValue: [ "one.js" ] },
* { name: "max", type: Number, defaultValue: 3 }
* ]
* ```
*
* | # | Command line | .parse() output |
* | --- | ------------ | ------------ |
* | 1 | | `{ files: [ 'one.js' ], max: 3 }` |
* | 2 | `--files two.js` | `{ files: [ 'two.js' ], max: 3 }` |
* | 3 | `--max 4` | `{ files: [ 'one.js' ], max: 4 }` |
*
* @type {*}
*/
this.defaultValue = definition.defaultValue
/**
* When your app has a large amount of options it makes sense to organise them in groups.
*
* There are two automatic groups: `_all` (contains all options) and `_none` (contains options without a `group` specified in their definition).
*
* ```js
* [
* { name: "verbose", group: "standard" },
* { name: "help", group: [ "standard", "main" ] },
* { name: "compress", group: [ "server", "main" ] },
* { name: "static", group: "server" },
* { name: "debug" }
* ]
* ```
*
*<table>
* <tr>
* <th>#</th><th>Command Line</th><th>.parse() output</th>
* </tr>
* <tr>
* <td>1</td><td><code>--verbose</code></td><td><pre><code>
*{
* _all: { verbose: true },
* standard: { verbose: true }
*}
*</code></pre></td>
* </tr>
* <tr>
* <td>2</td><td><code>--debug</code></td><td><pre><code>
*{
* _all: { debug: true },
* _none: { debug: true }
*}
*</code></pre></td>
* </tr>
* <tr>
* <td>3</td><td><code>--verbose --debug --compress</code></td><td><pre><code>
*{
* _all: {
* verbose: true,
* debug: true,
* compress: true
* },
* standard: { verbose: true },
* server: { compress: true },
* main: { compress: true },
* _none: { debug: true }
*}
*</code></pre></td>
* </tr>
* <tr>
* <td>4</td><td><code>--compress</code></td><td><pre><code>
*{
* _all: { compress: true },
* server: { compress: true },
* main: { compress: true }
*}
*</code></pre></td>
* </tr>
*</table>
*
* @type {string|string[]}
*/
this.group = definition.group
/* pick up any remaining properties */
for (let prop in definition) {
if (!this[prop]) this[prop] = definition[prop]
}
}
isBoolean (value) {
return this.type === Boolean || (t.isFunction(this.type) && this.type.name === 'Boolean')
}
}
module.exports = OptionDefinition

155
node_modules/command-line-args/lib/definitions.js generated vendored Normal file
View File

@ -0,0 +1,155 @@
'use strict'
const arrayify = require('array-back')
const option = require('./option')
const Definition = require('./definition')
const t = require('typical')
/**
* @module definitions
* @private
*/
/**
* @alias module:definitions
*/
class Definitions extends Array {
load (definitions) {
this.clear()
arrayify(definitions).forEach(def => this.push(new Definition(def)))
this.validate()
}
clear () {
this.length = 0
}
/**
* validate option definitions
* @returns {string}
*/
validate (argv) {
const someHaveNoName = this.some(def => !def.name)
if (someHaveNoName) {
halt(
'NAME_MISSING',
'Invalid option definitions: the `name` property is required on each definition'
)
}
const someDontHaveFunctionType = this.some(def => def.type && typeof def.type !== 'function')
if (someDontHaveFunctionType) {
halt(
'INVALID_TYPE',
'Invalid option definitions: the `type` property must be a setter fuction (default: `Boolean`)'
)
}
let invalidOption
const numericAlias = this.some(def => {
invalidOption = def
return t.isDefined(def.alias) && t.isNumber(def.alias)
})
if (numericAlias) {
halt(
'INVALID_ALIAS',
'Invalid option definition: to avoid ambiguity an alias cannot be numeric [--' + invalidOption.name + ' alias is -' + invalidOption.alias + ']'
)
}
const multiCharacterAlias = this.some(def => {
invalidOption = def
return t.isDefined(def.alias) && def.alias.length !== 1
})
if (multiCharacterAlias) {
halt(
'INVALID_ALIAS',
'Invalid option definition: an alias must be a single character'
)
}
const hypenAlias = this.some(def => {
invalidOption = def
return def.alias === '-'
})
if (hypenAlias) {
halt(
'INVALID_ALIAS',
'Invalid option definition: an alias cannot be "-"'
)
}
const duplicateName = hasDuplicates(this.map(def => def.name))
if (duplicateName) {
halt(
'DUPLICATE_NAME',
'Two or more option definitions have the same name'
)
}
const duplicateAlias = hasDuplicates(this.map(def => def.alias))
if (duplicateAlias) {
halt(
'DUPLICATE_ALIAS',
'Two or more option definitions have the same alias'
)
}
const duplicateDefaultOption = hasDuplicates(this.map(def => def.defaultOption))
if (duplicateDefaultOption) {
halt(
'DUPLICATE_DEFAULT_OPTION',
'Only one option definition can be the defaultOption'
)
}
}
/**
* @param {string}
* @returns {Definition}
*/
get (arg) {
return option.short.test(arg)
? this.find(def => def.alias === option.short.name(arg))
: this.find(def => def.name === option.long.name(arg))
}
getDefault () {
return this.find(def => def.defaultOption === true)
}
isGrouped () {
return this.some(def => def.group)
}
whereGrouped () {
return this.filter(containsValidGroup)
}
whereNotGrouped () {
return this.filter(def => !containsValidGroup(def))
}
}
function halt (name, message) {
const err = new Error(message)
err.name = name
throw err
}
function containsValidGroup (def) {
return arrayify(def.group).some(group => group)
}
function hasDuplicates (array) {
const items = {}
for (let i = 0; i < array.length; i++) {
const value = array[i]
if (items[value]) {
return true
} else {
if (t.isDefined(value)) items[value] = true
}
}
}
module.exports = Definitions

35
node_modules/command-line-args/lib/grouped-output.js generated vendored Normal file
View File

@ -0,0 +1,35 @@
'use strict'
const arrayify = require('array-back')
const Output = require('./output')
class GroupedOutput extends Output {
toObject () {
const superOutput = super.toObject()
delete superOutput._unknown
const grouped = {
_all: superOutput
}
if (this.unknown.length) grouped._unknown = this.unknown
this.definitions.whereGrouped().forEach(def => {
const outputValue = this.output[def.name]
for (const groupName of arrayify(def.group)) {
grouped[groupName] = grouped[groupName] || {}
if (outputValue && outputValue.isDefined()) {
grouped[groupName][def.name] = outputValue.value
}
}
})
this.definitions.whereNotGrouped().forEach(def => {
const outputValue = this.output[def.name]
if (outputValue && outputValue.isDefined()) {
if (!grouped._none) grouped._none = {}
grouped._none[def.name] = outputValue.value
}
})
return grouped
}
}
module.exports = GroupedOutput

14
node_modules/command-line-args/lib/option.js generated vendored Normal file
View File

@ -0,0 +1,14 @@
'use strict'
class ArgRegExp extends RegExp {
name (arg) {
return arg.match(this)[1]
}
}
exports.short = new ArgRegExp('^-([^\\d-])$')
exports.long = new ArgRegExp('^--(\\S+)')
exports.combined = new ArgRegExp('^-([^\\d-]{2,})$')
exports.isOption = arg => exports.short.test(arg) || exports.long.test(arg)
exports.optEquals = new ArgRegExp('^(--\\S+?)=(.*)')
exports.VALUE_MARKER = '552f3a31-14cd-4ced-bd67-656a659e9efb' // must be unique

152
node_modules/command-line-args/lib/output.js generated vendored Normal file
View File

@ -0,0 +1,152 @@
'use strict'
const t = require('typical')
const arrayify = require('array-back')
class OutputValue {
constructor (value) {
this.value = value
this.hasDefaultArrayValue = false
this.valueSource = 'unknown'
}
isDefined () {
return t.isDefined(this.value)
}
}
class Output {
constructor (definitions, options) {
this.options = options || {}
this.output = {}
this.unknown = []
this.definitions = definitions
this._assignDefaultValues()
}
_assignDefaultValues () {
this.definitions.forEach(def => {
if (t.isDefined(def.defaultValue)) {
if (def.multiple) {
this.output[def.name] = new OutputValue(arrayify(def.defaultValue))
this.output[def.name].hasDefaultArrayValue = true
} else {
this.output[def.name] = new OutputValue(def.defaultValue)
}
this.output[def.name].valueSource = 'default'
}
})
}
setFlag (optionArg) {
const def = this.definitions.get(optionArg)
if (def) {
this.output[def.name] = this.output[def.name] || new OutputValue()
const outputValue = this.output[def.name]
if (def.multiple) outputValue.value = outputValue.value || []
/* for boolean types, set value to `true`. For all other types run value through setter function. */
if (def.isBoolean()) {
if (Array.isArray(outputValue.value)) {
outputValue.value.push(true)
} else {
outputValue.value = true
}
return true
} else {
if (!Array.isArray(outputValue.value) && outputValue.valueSource === 'unknown') outputValue.value = null
return false
}
} else {
this.unknown.push(optionArg)
return true
}
}
setOptionValue (optionArg, value) {
const ValueArg = require('./value-arg')
const valueArg = new ValueArg(value)
const def = this.definitions.get(optionArg)
this.output[def.name] = this.output[def.name] || new OutputValue()
const outputValue = this.output[def.name]
if (def.multiple) outputValue.value = outputValue.value || []
/* run value through setter function. */
valueArg.value = def.type(valueArg.value)
outputValue.valueSource = 'argv'
if (Array.isArray(outputValue.value)) {
if (outputValue.hasDefaultArrayValue) {
outputValue.value = [ valueArg.value ]
outputValue.hasDefaultArrayValue = false
} else {
outputValue.value.push(valueArg.value)
}
return false
} else {
outputValue.value = valueArg.value
return true
}
}
/**
* Return `true` when an option value was set and is not a multiple. Return `false` if option was a multiple or if a value was not yet set.
*/
setValue (value) {
const ValueArg = require('./value-arg')
const valueArg = new ValueArg(value)
/* use the defaultOption */
const def = this.definitions.getDefault()
/* handle unknown values in the case a value was already set on a defaultOption */
if (def) {
const currentValue = this.output[def.name]
if (valueArg.isDefined() && currentValue && t.isDefined(currentValue.value)) {
if (def.multiple) {
/* in the case we're setting an --option=value value on a multiple defaultOption, tag the value onto the previous unknown */
if (valueArg.isOptionValueNotationValue && this.unknown.length) {
this.unknown[this.unknown.length - 1] += `=${valueArg.value}`
return true
}
} else {
/* currentValue has already been set by argv,log this value as unknown and move on */
if (currentValue.valueSource === 'argv') {
this.unknown.push(valueArg.value)
return true
}
}
}
return this.setOptionValue(`--${def.name}`, value)
} else {
if (valueArg.isOptionValueNotationValue) {
this.unknown[this.unknown.length - 1] += `=${valueArg.value}`
} else {
this.unknown.push(valueArg.value)
}
return true
}
}
get (name) {
return this.output[name] && this.output[name].value
}
toObject () {
let output = Object.assign({}, this.output)
if (this.options.partial && this.unknown.length) {
output._unknown = this.unknown
}
for (const prop in output) {
if (prop !== '_unknown') {
output[prop] = output[prop].value
}
}
return output
}
}
module.exports = Output

36
node_modules/command-line-args/lib/output2.js generated vendored Normal file
View File

@ -0,0 +1,36 @@
class FlagOption {}
class SingleValueOption {
constructor (definition) {
this.definition = definition
}
set value (val) {
this._val = this.definition.type(val)
}
get value () {
return this._val
}
}
class MultipleValueOption {}
class Output extends Map {
constructor (definitions) {
this.definitions = definitions
}
set (key, value) {
const def = this.definitions.get(key)
}
}
const optionDefinitions = [
{ name: 'one' }
]
const output = new Output(optionDefinitions)
output.set('one', 'something')
console.log(output)
output.set('one', 'something2')
console.log(output)

18
node_modules/command-line-args/lib/value-arg.js generated vendored Normal file
View File

@ -0,0 +1,18 @@
'use strict'
const t = require('typical')
const option = require('./option')
const reBeginsWithValueMarker = new RegExp('^' + option.VALUE_MARKER)
class ValueArg {
constructor (value) {
this.isOptionValueNotationValue = reBeginsWithValueMarker.test(value)
/* if the value marker is present at the value beginning, strip it */
this.value = value ? value.replace(reBeginsWithValueMarker, '') : value
}
isDefined () {
return t.isDefined(this.value)
}
}
module.exports = ValueArg