Skip to content

Commit

Permalink
feat: allow setting typeDefault on nopt and clean lib methods
Browse files Browse the repository at this point in the history
Setting this option allows bypassing the default handling of unknown
keys when cleaning data.
  • Loading branch information
lukekarrys committed Jun 14, 2023
1 parent 9122d7c commit 082bad3
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 11 deletions.
34 changes: 23 additions & 11 deletions lib/nopt-lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ var abbrev = require('abbrev')
const debug = require('./debug')
const defaultTypeDefs = require('./type-defs')

function nopt (args, { types, shorthands, typeDefs, invalidHandler }) {
function nopt (args, { types, shorthands, typeDefs, invalidHandler, typeDefault }) {
debug(types, shorthands, args, typeDefs)

var data = {}
Expand All @@ -15,7 +15,7 @@ function nopt (args, { types, shorthands, typeDefs, invalidHandler }) {
parse(args, data, argv.remain, { typeDefs, types, shorthands })

// now data is full
clean(data, { types, typeDefs, invalidHandler })
clean(data, { types, typeDefs, invalidHandler, typeDefault })
data.argv = argv

Object.defineProperty(data.argv, 'toString', {
Expand All @@ -28,23 +28,28 @@ function nopt (args, { types, shorthands, typeDefs, invalidHandler }) {
return data
}

function clean (data, { types, typeDefs, invalidHandler }) {
function clean (data, { types, typeDefs, 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

const hasTypeDefault = typeof typeDefault !== 'undefined'
if (!hasTypeDefault) {
typeDefault = [false, true, null, StringType, ArrayType]
}

var remove = {}
var typeDefault = [false, true, null, StringType, ArrayType]

Object.keys(data).forEach(function (k) {
if (k === 'argv') {
return
}
var val = data[k]
var isArray = Array.isArray(val)
var type = types[k]
let rawType = types[k]
var type = rawType
if (!isArray) {
val = [val]
}
Expand Down Expand Up @@ -82,7 +87,14 @@ function clean (data, { types, typeDefs, invalidHandler }) {
}

if (!Object.prototype.hasOwnProperty.call(types, k)) {
return v
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
}

// allow `--no-blah` to set 'blah' to null if null is allowed
Expand All @@ -93,16 +105,16 @@ function clean (data, { types, typeDefs, invalidHandler }) {

var 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
Expand Down
48 changes: 48 additions & 0 deletions test/type-default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const t = require('tap')
const nopt = require('../lib/nopt-lib.js')

t.test('use other type default', (t) => {
const NotAllowed = Symbol('NotAllowed')
const Invalid = Symbol('Invalid')

const clean = (data, opts) => {
const invalids = []
nopt.clean(data, {
types: {
str: nopt.typeDefs.String.type,
invalid: Invalid,
},
typeDefs: {
...nopt.typeDefs,
NotAllowed: { type: NotAllowed, validate: () => false },
Invalid: { type: Invalid, validate: () => false },
},
invalidHandler: (k, v, type) => invalids.push([k, v, type]),
...opts,
})
return {
keys: Object.keys(data),
invalids,
}
}

t.strictSame(clean({
str: 'aaa',
invalid: 'bad',
unknown: 'huh?',
}), {
keys: ['str', 'unknown'],
invalids: [['invalid', 'bad', Invalid]],
}, 'invalid data is removed with clean')

t.strictSame(clean({
str: 'aaa',
invalid: 'bad',
unknown: 'huh?',
}, { typeDefault: NotAllowed }), {
keys: ['str'],
invalids: [['invalid', 'bad', Invalid], ['unknown', 'huh?', NotAllowed]],
}, 'invalid and unknown data is removed with a custom typeDefault')

t.end()
})

0 comments on commit 082bad3

Please sign in to comment.