Comparing version 7.1.0 to 7.2.0
#!/usr/bin/env node | ||
var nopt = require('../lib/nopt') | ||
var path = require('path') | ||
var types = { num: Number, | ||
const nopt = require('../lib/nopt') | ||
const path = require('path') | ||
console.log('parsed', nopt({ | ||
num: Number, | ||
bool: Boolean, | ||
@@ -16,4 +17,4 @@ help: Boolean, | ||
file: path, | ||
} | ||
var shorthands = { s: ['--str', 'astring'], | ||
}, { | ||
s: ['--str', 'astring'], | ||
b: ['--bool'], | ||
@@ -29,30 +30,2 @@ nb: ['--no-bool'], | ||
f: ['--file'], | ||
} | ||
var parsed = nopt(types | ||
, shorthands | ||
, process.argv | ||
, 2) | ||
console.log('parsed', parsed) | ||
if (parsed.help) { | ||
console.log('') | ||
console.log('nopt cli tester') | ||
console.log('') | ||
console.log('types') | ||
console.log(Object.keys(types).map(function M (t) { | ||
var type = types[t] | ||
if (Array.isArray(type)) { | ||
return [t, type.map(function (mappedType) { | ||
return mappedType.name | ||
})] | ||
} | ||
return [t, type && type.name] | ||
}).reduce(function (s, i) { | ||
s[i[0]] = i[1] | ||
return s | ||
}, {})) | ||
console.log('') | ||
console.log('shorthands') | ||
console.log(shorthands) | ||
} | ||
}, process.argv, 2)) |
/* istanbul ignore next */ | ||
module.exports = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG | ||
? function () { | ||
console.error.apply(console, arguments) | ||
} | ||
: function () {} | ||
? (...a) => console.error(...a) | ||
: () => {} |
@@ -1,10 +0,36 @@ | ||
var abbrev = require('abbrev') | ||
const abbrev = require('abbrev') | ||
const debug = require('./debug') | ||
const defaultTypeDefs = require('./type-defs') | ||
function nopt (args, { types, shorthands, typeDefs, invalidHandler }) { | ||
const hasOwn = (o, k) => Object.prototype.hasOwnProperty.call(o, k) | ||
const getType = (k, { types, dynamicTypes }) => { | ||
let hasType = hasOwn(types, k) | ||
let type = types[k] | ||
if (!hasType && typeof dynamicTypes === 'function') { | ||
const matchedType = dynamicTypes(k) | ||
if (matchedType !== undefined) { | ||
type = matchedType | ||
hasType = true | ||
} | ||
} | ||
return [hasType, type] | ||
} | ||
const isTypeDef = (type, def) => def && type === def | ||
const hasTypeDef = (type, def) => def && type.indexOf(def) !== -1 | ||
const doesNotHaveTypeDef = (type, def) => def && !hasTypeDef(type, def) | ||
function nopt (args, { | ||
types, | ||
shorthands, | ||
typeDefs, | ||
invalidHandler, | ||
typeDefault, | ||
dynamicTypes, | ||
} = {}) { | ||
debug(types, shorthands, args, typeDefs) | ||
var data = {} | ||
var argv = { | ||
const data = {} | ||
const argv = { | ||
remain: [], | ||
@@ -15,6 +41,6 @@ cooked: args, | ||
parse(args, data, argv.remain, { typeDefs, types, shorthands }) | ||
parse(args, data, argv.remain, { typeDefs, types, dynamicTypes, shorthands }) | ||
// now data is full | ||
clean(data, { types, typeDefs, invalidHandler }) | ||
clean(data, { types, dynamicTypes, typeDefs, invalidHandler, typeDefault }) | ||
data.argv = argv | ||
@@ -32,19 +58,37 @@ | ||
function clean (data, { types, typeDefs, invalidHandler }) { | ||
const StringType = typeDefs.String.type | ||
const NumberType = typeDefs.Number.type | ||
const ArrayType = typeDefs.Array.type | ||
const BooleanType = typeDefs.Boolean.type | ||
const DateType = typeDefs.Date.type | ||
function clean (data, { | ||
types = {}, | ||
typeDefs = {}, | ||
dynamicTypes, | ||
invalidHandler, | ||
typeDefault, | ||
} = {}) { | ||
const StringType = typeDefs.String?.type | ||
const NumberType = typeDefs.Number?.type | ||
const ArrayType = typeDefs.Array?.type | ||
const BooleanType = typeDefs.Boolean?.type | ||
const DateType = typeDefs.Date?.type | ||
var remove = {} | ||
var typeDefault = [false, true, null, StringType, ArrayType] | ||
const hasTypeDefault = typeof typeDefault !== 'undefined' | ||
if (!hasTypeDefault) { | ||
typeDefault = [false, true, null] | ||
if (StringType) { | ||
typeDefault.push(StringType) | ||
} | ||
if (ArrayType) { | ||
typeDefault.push(ArrayType) | ||
} | ||
} | ||
Object.keys(data).forEach(function (k) { | ||
const remove = {} | ||
Object.keys(data).forEach((k) => { | ||
if (k === 'argv') { | ||
return | ||
} | ||
var val = data[k] | ||
var isArray = Array.isArray(val) | ||
var type = types[k] | ||
let val = data[k] | ||
debug('val=%j', val) | ||
const isArray = Array.isArray(val) | ||
let [hasType, rawType] = getType(k, { types, dynamicTypes }) | ||
let type = rawType | ||
if (!isArray) { | ||
@@ -56,3 +100,3 @@ val = [val] | ||
} | ||
if (type === ArrayType) { | ||
if (isTypeDef(type, ArrayType)) { | ||
type = typeDefault.concat(ArrayType) | ||
@@ -66,3 +110,3 @@ } | ||
debug('types=', type) | ||
val = val.map(function (v) { | ||
val = val.map((v) => { | ||
// if it's an unknown value, then parse false/true/null/numbers/dates | ||
@@ -74,11 +118,11 @@ if (typeof v === 'string') { | ||
|| (v === 'true' && | ||
(~type.indexOf(true) || ~type.indexOf(BooleanType))) | ||
(~type.indexOf(true) || hasTypeDef(type, BooleanType))) | ||
|| (v === 'false' && | ||
(~type.indexOf(false) || ~type.indexOf(BooleanType)))) { | ||
(~type.indexOf(false) || hasTypeDef(type, BooleanType)))) { | ||
v = JSON.parse(v) | ||
debug('jsonable %j', v) | ||
} else if (~type.indexOf(NumberType) && !isNaN(v)) { | ||
} else if (hasTypeDef(type, NumberType) && !isNaN(v)) { | ||
debug('convert to number', v) | ||
v = +v | ||
} else if (~type.indexOf(DateType) && !isNaN(Date.parse(v))) { | ||
} else if (hasTypeDef(type, DateType) && !isNaN(Date.parse(v))) { | ||
debug('convert to date', v) | ||
@@ -89,4 +133,11 @@ v = new Date(v) | ||
if (!Object.prototype.hasOwnProperty.call(types, k)) { | ||
return v | ||
if (!hasType) { | ||
if (!hasTypeDefault) { | ||
return v | ||
} | ||
// if the default type has been passed in then we want to validate the | ||
// unknown data key instead of bailing out earlier. we also set the raw | ||
// type which is passed to the invalid handler so that it can be | ||
// determined if during validation if it is unknown vs invalid | ||
rawType = typeDefault | ||
} | ||
@@ -96,26 +147,24 @@ | ||
if (v === false && ~type.indexOf(null) && | ||
!(~type.indexOf(false) || ~type.indexOf(BooleanType))) { | ||
!(~type.indexOf(false) || hasTypeDef(type, BooleanType))) { | ||
v = null | ||
} | ||
var d = {} | ||
const d = {} | ||
d[k] = v | ||
debug('prevalidated val', d, v, types[k]) | ||
if (!validate(d, k, v, types[k], { typeDefs })) { | ||
debug('prevalidated val', d, v, rawType) | ||
if (!validate(d, k, v, rawType, { typeDefs })) { | ||
if (invalidHandler) { | ||
invalidHandler(k, v, types[k], data) | ||
invalidHandler(k, v, rawType, data) | ||
} else if (invalidHandler !== false) { | ||
debug('invalid: ' + k + '=' + v, types[k]) | ||
debug('invalid: ' + k + '=' + v, rawType) | ||
} | ||
return remove | ||
} | ||
debug('validated v', d, v, types[k]) | ||
debug('validated v', d, v, rawType) | ||
return d[k] | ||
}).filter(function (v) { | ||
return v !== remove | ||
}) | ||
}).filter((v) => v !== remove) | ||
// if we allow Array specifically, then an empty array is how we | ||
// express 'no value here', not null. Allow it. | ||
if (!val.length && type.indexOf(ArrayType) === -1) { | ||
if (!val.length && doesNotHaveTypeDef(type, ArrayType)) { | ||
debug('VAL HAS NO LENGTH, DELETE IT', val, k, type.indexOf(ArrayType)) | ||
@@ -134,8 +183,8 @@ delete data[k] | ||
function validate (data, k, val, type, { typeDefs }) { | ||
const ArrayType = typeDefs.Array.type | ||
function validate (data, k, val, type, { typeDefs } = {}) { | ||
const ArrayType = typeDefs?.Array?.type | ||
// arrays are lists of types. | ||
if (Array.isArray(type)) { | ||
for (let i = 0, l = type.length; i < l; i++) { | ||
if (type[i] === ArrayType) { | ||
if (isTypeDef(type[i], ArrayType)) { | ||
continue | ||
@@ -152,3 +201,3 @@ } | ||
// an array of anything? | ||
if (type === ArrayType) { | ||
if (isTypeDef(type, ArrayType)) { | ||
return true | ||
@@ -178,7 +227,7 @@ } | ||
// now go through the list of typeDefs, validate against each one. | ||
var ok = false | ||
var types = Object.keys(typeDefs) | ||
let ok = false | ||
const types = Object.keys(typeDefs) | ||
for (let i = 0, l = types.length; i < l; i++) { | ||
debug('test type %j %j %j', k, val, types[i]) | ||
var t = typeDefs[types[i]] | ||
const t = typeDefs[types[i]] | ||
if (t && ( | ||
@@ -189,3 +238,3 @@ (type && type.name && t.type && t.type.name) ? | ||
)) { | ||
var d = {} | ||
const d = {} | ||
ok = t.validate(d, k, val) !== false | ||
@@ -207,15 +256,21 @@ val = d[k] | ||
function parse (args, data, remain, { typeDefs, types, shorthands }) { | ||
const StringType = typeDefs.String.type | ||
const NumberType = typeDefs.String.type | ||
const ArrayType = typeDefs.Array.type | ||
const BooleanType = typeDefs.Boolean.type | ||
function parse (args, data, remain, { | ||
types = {}, | ||
typeDefs = {}, | ||
shorthands = {}, | ||
dynamicTypes, | ||
} = {}) { | ||
const StringType = typeDefs.String?.type | ||
const NumberType = typeDefs.Number?.type | ||
const ArrayType = typeDefs.Array?.type | ||
const BooleanType = typeDefs.Boolean?.type | ||
debug('parse', args, data, remain) | ||
var abbrevs = abbrev(Object.keys(types)) | ||
var shortAbbr = abbrev(Object.keys(shorthands)) | ||
const abbrevs = abbrev(Object.keys(types)) | ||
debug('abbrevs=%j', abbrevs) | ||
const shortAbbr = abbrev(Object.keys(shorthands)) | ||
for (var i = 0; i < args.length; i++) { | ||
var arg = args[i] | ||
for (let i = 0; i < args.length; i++) { | ||
let arg = args[i] | ||
debug('arg', arg) | ||
@@ -230,8 +285,8 @@ | ||
} | ||
var hadEq = false | ||
let hadEq = false | ||
if (arg.charAt(0) === '-' && arg.length > 1) { | ||
var at = arg.indexOf('=') | ||
const at = arg.indexOf('=') | ||
if (at > -1) { | ||
hadEq = true | ||
var v = arg.slice(at + 1) | ||
const v = arg.slice(at + 1) | ||
arg = arg.slice(0, at) | ||
@@ -243,6 +298,5 @@ args.splice(i, 1, arg, v) | ||
// if so, splice and back up to re-parse it. | ||
var shRes = resolveShort(arg, shortAbbr, abbrevs, { shorthands }) | ||
const shRes = resolveShort(arg, shortAbbr, abbrevs, { shorthands }) | ||
debug('arg=%j shRes=%j', arg, shRes) | ||
if (shRes) { | ||
debug(arg, shRes) | ||
args.splice.apply(args, [i, 1].concat(shRes)) | ||
@@ -255,3 +309,3 @@ if (arg !== shRes[0]) { | ||
arg = arg.replace(/^-+/, '') | ||
var no = null | ||
let no = null | ||
while (arg.toLowerCase().indexOf('no-') === 0) { | ||
@@ -266,4 +320,4 @@ no = !no | ||
var argType = types[arg] | ||
var isTypeArray = Array.isArray(argType) | ||
let [hasType, argType] = getType(arg, { types, dynamicTypes }) | ||
let isTypeArray = Array.isArray(argType) | ||
if (isTypeArray && argType.length === 1) { | ||
@@ -274,10 +328,7 @@ isTypeArray = false | ||
var isArray = argType === ArrayType || | ||
isTypeArray && argType.indexOf(ArrayType) !== -1 | ||
let isArray = isTypeDef(argType, ArrayType) || | ||
isTypeArray && hasTypeDef(argType, ArrayType) | ||
// allow unknown things to be arrays if specified multiple times. | ||
if ( | ||
!Object.prototype.hasOwnProperty.call(types, arg) && | ||
Object.prototype.hasOwnProperty.call(data, arg) | ||
) { | ||
if (!hasType && hasOwn(data, arg)) { | ||
if (!Array.isArray(data[arg])) { | ||
@@ -289,8 +340,8 @@ data[arg] = [data[arg]] | ||
var val | ||
var la = args[i + 1] | ||
let val | ||
let la = args[i + 1] | ||
var isBool = typeof no === 'boolean' || | ||
argType === BooleanType || | ||
isTypeArray && argType.indexOf(BooleanType) !== -1 || | ||
const isBool = typeof no === 'boolean' || | ||
isTypeDef(argType, BooleanType) || | ||
isTypeArray && hasTypeDef(argType, BooleanType) || | ||
(typeof argType === 'undefined' && !hadEq) || | ||
@@ -326,7 +377,7 @@ (la === 'false' && | ||
!isNaN(la) && | ||
~argType.indexOf(NumberType)) { | ||
hasTypeDef(argType, NumberType)) { | ||
// number | ||
val = +la | ||
i++ | ||
} else if (!la.match(/^-[^-]/) && ~argType.indexOf(StringType)) { | ||
} else if (!la.match(/^-[^-]/) && hasTypeDef(argType, StringType)) { | ||
// string | ||
@@ -347,3 +398,3 @@ val = la | ||
if (argType === StringType) { | ||
if (isTypeDef(argType, StringType)) { | ||
if (la === undefined) { | ||
@@ -376,3 +427,22 @@ la = '' | ||
function resolveShort (arg, shortAbbr, abbrevs, { shorthands }) { | ||
const SINGLES = Symbol('singles') | ||
const singleCharacters = (arg, shorthands) => { | ||
let singles = shorthands[SINGLES] | ||
if (!singles) { | ||
singles = Object.keys(shorthands).filter((s) => s.length === 1).reduce((l, r) => { | ||
l[r] = true | ||
return l | ||
}, {}) | ||
shorthands[SINGLES] = singles | ||
debug('shorthand singles', singles) | ||
} | ||
const chrs = arg.split('').filter((c) => singles[c]) | ||
return chrs.join('') === arg ? chrs : null | ||
} | ||
function resolveShort (arg, ...rest) { | ||
const { types = {}, shorthands = {} } = rest.length ? rest.pop() : {} | ||
const shortAbbr = rest[0] ?? abbrev(Object.keys(shorthands)) | ||
const abbrevs = rest[1] ?? abbrev(Object.keys(types)) | ||
// handle single-char shorthands glommed together, like | ||
@@ -400,26 +470,7 @@ // npm ls -glp, but only if there is one dash, and only if | ||
// first check to see if this arg is a set of single-char shorthands | ||
var singles = shorthands.___singles | ||
if (!singles) { | ||
singles = Object.keys(shorthands).filter(function (s) { | ||
return s.length === 1 | ||
}).reduce(function (l, r) { | ||
l[r] = true | ||
return l | ||
}, {}) | ||
shorthands.___singles = singles | ||
debug('shorthand singles', singles) | ||
const chrs = singleCharacters(arg, shorthands) | ||
if (chrs) { | ||
return chrs.map((c) => shorthands[c]).reduce((l, r) => l.concat(r), []) | ||
} | ||
var chrs = arg.split('').filter(function (c) { | ||
return singles[c] | ||
}) | ||
if (chrs.join('') === arg) { | ||
return chrs.map(function (c) { | ||
return shorthands[c] | ||
}).reduce(function (l, r) { | ||
return l.concat(r) | ||
}, []) | ||
} | ||
// if it's an arg abbrev, and not a literal shorthand, then prefer the arg | ||
@@ -426,0 +477,0 @@ if (abbrevs[arg] && !shorthands[arg]) { |
@@ -15,5 +15,5 @@ const lib = require('./nopt-lib') | ||
function nopt (types = {}, shorthands = {}, args = process.argv, slice = 2) { | ||
function nopt (types, shorthands, args = process.argv, slice = 2) { | ||
return lib.nopt(args.slice(slice), { | ||
types, | ||
types: types || {}, | ||
shorthands: shorthands || {}, | ||
@@ -27,3 +27,3 @@ typeDefs: exports.typeDefs, | ||
return lib.clean(data, { | ||
types, | ||
types: types || {}, | ||
typeDefs, | ||
@@ -30,0 +30,0 @@ invalidHandler: exports.invalidHandler, |
@@ -1,5 +0,5 @@ | ||
var url = require('url') | ||
var path = require('path') | ||
var Stream = require('stream').Stream | ||
var os = require('os') | ||
const url = require('url') | ||
const path = require('path') | ||
const Stream = require('stream').Stream | ||
const os = require('os') | ||
const debug = require('./debug') | ||
@@ -21,5 +21,5 @@ | ||
var isWin = process.platform === 'win32' | ||
var homePattern = isWin ? /^~(\/|\\)/ : /^~\// | ||
var home = os.homedir() | ||
const isWin = process.platform === 'win32' | ||
const homePattern = isWin ? /^~(\/|\\)/ : /^~\// | ||
const home = os.homedir() | ||
@@ -43,3 +43,3 @@ if (home && val.match(homePattern)) { | ||
function validateDate (data, k, val) { | ||
var s = Date.parse(val) | ||
const s = Date.parse(val) | ||
debug('validate Date %j %j %j', k, val, s) | ||
@@ -46,0 +46,0 @@ if (isNaN(s)) { |
{ | ||
"name": "nopt", | ||
"version": "7.1.0", | ||
"version": "7.2.0", | ||
"description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", | ||
@@ -29,9 +29,6 @@ "author": "GitHub Inc.", | ||
"@npmcli/eslint-config": "^4.0.0", | ||
"@npmcli/template-oss": "4.12.0", | ||
"@npmcli/template-oss": "4.15.1", | ||
"tap": "^16.3.0" | ||
}, | ||
"tap": { | ||
"lines": 91, | ||
"branches": 87, | ||
"statements": 91, | ||
"nyc-arg": [ | ||
@@ -52,4 +49,5 @@ "--exclude", | ||
"windowsCI": false, | ||
"version": "4.12.0" | ||
"version": "4.15.1", | ||
"publish": true | ||
} | ||
} |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
26137
561