Socket
Socket
Sign inDemoInstall

nopt

Package Overview
Dependencies
1
Maintainers
6
Versions
34
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 7.1.0 to 7.2.0

41

bin/nopt.js
#!/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))

6

lib/debug.js
/* 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
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc