Comparing version 5.0.0 to 6.0.0
#!/usr/bin/env node | ||
var nopt = require("../lib/nopt") | ||
, path = require("path") | ||
, types = { num: Number | ||
, bool: Boolean | ||
, help: Boolean | ||
, list: Array | ||
, "num-list": [Number, Array] | ||
, "str-list": [String, Array] | ||
, "bool-list": [Boolean, Array] | ||
, str: String | ||
, clear: Boolean | ||
, config: Boolean | ||
, length: Number | ||
, file: path | ||
} | ||
, shorthands = { s: [ "--str", "astring" ] | ||
, b: [ "--bool" ] | ||
, nb: [ "--no-bool" ] | ||
, tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] | ||
, "?": ["--help"] | ||
, h: ["--help"] | ||
, H: ["--help"] | ||
, n: [ "--num", "125" ] | ||
, c: ["--config"] | ||
, l: ["--length"] | ||
, f: ["--file"] | ||
} | ||
, parsed = nopt( types | ||
, shorthands | ||
, process.argv | ||
, 2 ) | ||
var nopt = require('../lib/nopt') | ||
var path = require('path') | ||
var types = { num: Number, | ||
bool: Boolean, | ||
help: Boolean, | ||
list: Array, | ||
'num-list': [Number, Array], | ||
'str-list': [String, Array], | ||
'bool-list': [Boolean, Array], | ||
str: String, | ||
clear: Boolean, | ||
config: Boolean, | ||
length: Number, | ||
file: path, | ||
} | ||
var shorthands = { s: ['--str', 'astring'], | ||
b: ['--bool'], | ||
nb: ['--no-bool'], | ||
tft: ['--bool-list', '--no-bool-list', '--bool-list', 'true'], | ||
'?': ['--help'], | ||
h: ['--help'], | ||
H: ['--help'], | ||
n: ['--num', '125'], | ||
c: ['--config'], | ||
l: ['--length'], | ||
f: ['--file'], | ||
} | ||
var parsed = nopt(types | ||
, shorthands | ||
, process.argv | ||
, 2) | ||
console.log("parsed", parsed) | ||
console.log('parsed', parsed) | ||
if (parsed.help) { | ||
console.log("") | ||
console.log("nopt cli tester") | ||
console.log("") | ||
console.log("types") | ||
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 (type) { return type.name })] | ||
return [t, type.map(function (mappedType) { | ||
return mappedType.name | ||
})] | ||
} | ||
@@ -51,5 +53,5 @@ return [t, type && type.name] | ||
}, {})) | ||
console.log("") | ||
console.log("shorthands") | ||
console.log('') | ||
console.log('shorthands') | ||
console.log(shorthands) | ||
} |
368
lib/nopt.js
// info about each config option. | ||
var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG | ||
? function () { console.error.apply(console, arguments) } | ||
? function () { | ||
console.error.apply(console, arguments) | ||
} | ||
: function () {} | ||
var url = require("url") | ||
, path = require("path") | ||
, Stream = require("stream").Stream | ||
, abbrev = require("abbrev") | ||
, os = require("os") | ||
var url = require('url') | ||
var path = require('path') | ||
var Stream = require('stream').Stream | ||
var abbrev = require('abbrev') | ||
var os = require('os') | ||
@@ -17,9 +19,9 @@ module.exports = exports = nopt | ||
exports.typeDefs = | ||
{ String : { type: String, validate: validateString } | ||
, Boolean : { type: Boolean, validate: validateBoolean } | ||
, url : { type: url, validate: validateUrl } | ||
, Number : { type: Number, validate: validateNumber } | ||
, path : { type: path, validate: validatePath } | ||
, Stream : { type: Stream, validate: validateStream } | ||
, Date : { type: Date, validate: validateDate } | ||
{ String: { type: String, validate: validateString }, | ||
Boolean: { type: Boolean, validate: validateBoolean }, | ||
url: { type: url, validate: validateUrl }, | ||
Number: { type: Number, validate: validateNumber }, | ||
path: { type: path, validate: validatePath }, | ||
Stream: { type: Stream, validate: validateStream }, | ||
Date: { type: Date, validate: validateDate }, | ||
} | ||
@@ -31,3 +33,5 @@ | ||
shorthands = shorthands || {} | ||
if (typeof slice !== "number") slice = 2 | ||
if (typeof slice !== 'number') { | ||
slice = 2 | ||
} | ||
@@ -38,8 +42,7 @@ debug(types, shorthands, args, slice) | ||
var data = {} | ||
, key | ||
, argv = { | ||
remain: [], | ||
cooked: args, | ||
original: args.slice(0) | ||
} | ||
var argv = { | ||
remain: [], | ||
cooked: args, | ||
original: args.slice(0), | ||
} | ||
@@ -51,4 +54,5 @@ parse(args, data, argv.remain, types, shorthands) | ||
Object.defineProperty(data.argv, 'toString', { value: function () { | ||
return this.original.map(JSON.stringify).join(" ") | ||
}, enumerable: false }) | ||
return this.original.map(JSON.stringify).join(' ') | ||
}, | ||
enumerable: false }) | ||
return data | ||
@@ -60,61 +64,73 @@ } | ||
var remove = {} | ||
, typeDefault = [false, true, null, String, Array] | ||
var typeDefault = [false, true, null, String, Array] | ||
Object.keys(data).forEach(function (k) { | ||
if (k === "argv") return | ||
if (k === 'argv') { | ||
return | ||
} | ||
var val = data[k] | ||
, isArray = Array.isArray(val) | ||
, type = types[k] | ||
if (!isArray) val = [val] | ||
if (!type) type = typeDefault | ||
if (type === Array) type = typeDefault.concat(Array) | ||
if (!Array.isArray(type)) type = [type] | ||
var isArray = Array.isArray(val) | ||
var type = types[k] | ||
if (!isArray) { | ||
val = [val] | ||
} | ||
if (!type) { | ||
type = typeDefault | ||
} | ||
if (type === Array) { | ||
type = typeDefault.concat(Array) | ||
} | ||
if (!Array.isArray(type)) { | ||
type = [type] | ||
} | ||
debug("val=%j", val) | ||
debug("types=", type) | ||
val = val.map(function (val) { | ||
debug('val=%j', val) | ||
debug('types=', type) | ||
val = val.map(function (v) { | ||
// if it's an unknown value, then parse false/true/null/numbers/dates | ||
if (typeof val === "string") { | ||
debug("string %j", val) | ||
val = val.trim() | ||
if ((val === "null" && ~type.indexOf(null)) | ||
|| (val === "true" && | ||
if (typeof v === 'string') { | ||
debug('string %j', v) | ||
v = v.trim() | ||
if ((v === 'null' && ~type.indexOf(null)) | ||
|| (v === 'true' && | ||
(~type.indexOf(true) || ~type.indexOf(Boolean))) | ||
|| (val === "false" && | ||
|| (v === 'false' && | ||
(~type.indexOf(false) || ~type.indexOf(Boolean)))) { | ||
val = JSON.parse(val) | ||
debug("jsonable %j", val) | ||
} else if (~type.indexOf(Number) && !isNaN(val)) { | ||
debug("convert to number", val) | ||
val = +val | ||
} else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { | ||
debug("convert to date", val) | ||
val = new Date(val) | ||
v = JSON.parse(v) | ||
debug('jsonable %j', v) | ||
} else if (~type.indexOf(Number) && !isNaN(v)) { | ||
debug('convert to number', v) | ||
v = +v | ||
} else if (~type.indexOf(Date) && !isNaN(Date.parse(v))) { | ||
debug('convert to date', v) | ||
v = new Date(v) | ||
} | ||
} | ||
if (!types.hasOwnProperty(k)) { | ||
return val | ||
if (!Object.prototype.hasOwnProperty.call(types, k)) { | ||
return v | ||
} | ||
// allow `--no-blah` to set 'blah' to null if null is allowed | ||
if (val === false && ~type.indexOf(null) && | ||
if (v === false && ~type.indexOf(null) && | ||
!(~type.indexOf(false) || ~type.indexOf(Boolean))) { | ||
val = null | ||
v = null | ||
} | ||
var d = {} | ||
d[k] = val | ||
debug("prevalidated val", d, val, types[k]) | ||
if (!validate(d, k, val, types[k], typeDefs)) { | ||
d[k] = v | ||
debug('prevalidated val', d, v, types[k]) | ||
if (!validate(d, k, v, types[k], typeDefs)) { | ||
if (exports.invalidHandler) { | ||
exports.invalidHandler(k, val, types[k], data) | ||
exports.invalidHandler(k, v, types[k], data) | ||
} else if (exports.invalidHandler !== false) { | ||
debug("invalid: "+k+"="+val, types[k]) | ||
debug('invalid: ' + k + '=' + v, types[k]) | ||
} | ||
return remove | ||
} | ||
debug("validated val", d, val, types[k]) | ||
debug('validated v', d, v, types[k]) | ||
return d[k] | ||
}).filter(function (val) { return val !== remove }) | ||
}).filter(function (v) { | ||
return v !== remove | ||
}) | ||
@@ -126,9 +142,10 @@ // if we allow Array specifically, then an empty array is how we | ||
delete data[k] | ||
} | ||
else if (isArray) { | ||
} else if (isArray) { | ||
debug(isArray, data[k], val) | ||
data[k] = val | ||
} else data[k] = val[0] | ||
} else { | ||
data[k] = val[0] | ||
} | ||
debug("k=%s val=%j", k, val, data[k]) | ||
debug('k=%s val=%j', k, val, data[k]) | ||
}) | ||
@@ -142,13 +159,17 @@ } | ||
function validatePath (data, k, val) { | ||
if (val === true) return false | ||
if (val === null) return true | ||
if (val === true) { | ||
return false | ||
} | ||
if (val === null) { | ||
return true | ||
} | ||
val = String(val) | ||
var isWin = process.platform === 'win32' | ||
, homePattern = isWin ? /^~(\/|\\)/ : /^~\// | ||
, home = os.homedir() | ||
var isWin = process.platform === 'win32' | ||
var homePattern = isWin ? /^~(\/|\\)/ : /^~\// | ||
var home = os.homedir() | ||
if (home && val.match(homePattern)) { | ||
data[k] = path.resolve(home, val.substr(2)) | ||
data[k] = path.resolve(home, val.slice(2)) | ||
} else { | ||
@@ -161,4 +182,6 @@ data[k] = path.resolve(val) | ||
function validateNumber (data, k, val) { | ||
debug("validate Number %j %j %j", k, val, isNaN(val)) | ||
if (isNaN(val)) return false | ||
debug('validate Number %j %j %j', k, val, isNaN(val)) | ||
if (isNaN(val)) { | ||
return false | ||
} | ||
data[k] = +val | ||
@@ -169,4 +192,6 @@ } | ||
var s = Date.parse(val) | ||
debug("validate Date %j %j %j", k, val, s) | ||
if (isNaN(s)) return false | ||
debug('validate Date %j %j %j', k, val, s) | ||
if (isNaN(s)) { | ||
return false | ||
} | ||
data[k] = new Date(val) | ||
@@ -176,8 +201,15 @@ } | ||
function validateBoolean (data, k, val) { | ||
if (val instanceof Boolean) val = val.valueOf() | ||
else if (typeof val === "string") { | ||
if (!isNaN(val)) val = !!(+val) | ||
else if (val === "null" || val === "false") val = false | ||
else val = true | ||
} else val = !!val | ||
if (val instanceof Boolean) { | ||
val = val.valueOf() | ||
} else if (typeof val === 'string') { | ||
if (!isNaN(val)) { | ||
val = !!(+val) | ||
} else if (val === 'null' || val === 'false') { | ||
val = false | ||
} else { | ||
val = true | ||
} | ||
} else { | ||
val = !!val | ||
} | ||
data[k] = val | ||
@@ -187,4 +219,8 @@ } | ||
function validateUrl (data, k, val) { | ||
// Changing this would be a breaking change in the npm cli | ||
/* eslint-disable-next-line node/no-deprecated-api */ | ||
val = url.parse(String(val)) | ||
if (!val.host) return false | ||
if (!val.host) { | ||
return false | ||
} | ||
data[k] = val.href | ||
@@ -194,3 +230,5 @@ } | ||
function validateStream (data, k, val) { | ||
if (!(val instanceof Stream)) return false | ||
if (!(val instanceof Stream)) { | ||
return false | ||
} | ||
data[k] = val | ||
@@ -202,5 +240,9 @@ } | ||
if (Array.isArray(type)) { | ||
for (var i = 0, l = type.length; i < l; i ++) { | ||
if (type[i] === Array) continue | ||
if (validate(data, k, val, type[i], typeDefs)) return true | ||
for (let i = 0, l = type.length; i < l; i++) { | ||
if (type[i] === Array) { | ||
continue | ||
} | ||
if (validate(data, k, val, type[i], typeDefs)) { | ||
return true | ||
} | ||
} | ||
@@ -212,7 +254,15 @@ delete data[k] | ||
// an array of anything? | ||
if (type === Array) return true | ||
if (type === Array) { | ||
return true | ||
} | ||
// Original comment: | ||
// NaN is poisonous. Means that something is not allowed. | ||
// New comment: Changing this to an isNaN check breaks a lot of tests. | ||
// Something is being assumed here that is not actually what happens in | ||
// practice. Fixing it is outside the scope of getting linting to pass in | ||
// this repo. Leaving as-is for now. | ||
/* eslint-disable-next-line no-self-compare */ | ||
if (type !== type) { | ||
debug("Poison NaN", k, val, type) | ||
debug('Poison NaN', k, val, type) | ||
delete data[k] | ||
@@ -224,3 +274,3 @@ return false | ||
if (val === type) { | ||
debug("Explicitly allowed %j", val) | ||
debug('Explicitly allowed %j', val) | ||
// if (isArray) (data[k] = data[k] || []).push(val) | ||
@@ -234,10 +284,13 @@ // else data[k] = val | ||
var ok = false | ||
, types = Object.keys(typeDefs) | ||
for (var i = 0, l = types.length; i < l; i ++) { | ||
debug("test type %j %j %j", k, val, types[i]) | ||
var 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]] | ||
if (t && | ||
((type && type.name && t.type && t.type.name) ? (type.name === t.type.name) : (type === t.type))) { | ||
if (t && ( | ||
(type && type.name && t.type && t.type.name) ? | ||
(type.name === t.type.name) : | ||
(type === t.type) | ||
)) { | ||
var d = {} | ||
ok = false !== t.validate(d, k, val) | ||
ok = t.validate(d, k, val) !== false | ||
val = d[k] | ||
@@ -252,5 +305,7 @@ if (ok) { | ||
} | ||
debug("OK? %j (%j %j %j)", ok, k, val, types[i]) | ||
debug('OK? %j (%j %j %j)', ok, k, val, types[types.length - 1]) | ||
if (!ok) delete data[k] | ||
if (!ok) { | ||
delete data[k] | ||
} | ||
return ok | ||
@@ -260,11 +315,10 @@ } | ||
function parse (args, data, remain, types, shorthands) { | ||
debug("parse", args, data, remain) | ||
debug('parse', args, data, remain) | ||
var key = null | ||
, abbrevs = abbrev(Object.keys(types)) | ||
, shortAbbr = abbrev(Object.keys(shorthands)) | ||
var abbrevs = abbrev(Object.keys(types)) | ||
var shortAbbr = abbrev(Object.keys(shorthands)) | ||
for (var i = 0; i < args.length; i ++) { | ||
for (var i = 0; i < args.length; i++) { | ||
var arg = args[i] | ||
debug("arg", arg) | ||
debug('arg', arg) | ||
@@ -275,12 +329,12 @@ if (arg.match(/^-{2,}$/)) { | ||
remain.push.apply(remain, args.slice(i + 1)) | ||
args[i] = "--" | ||
args[i] = '--' | ||
break | ||
} | ||
var hadEq = false | ||
if (arg.charAt(0) === "-" && arg.length > 1) { | ||
if (arg.charAt(0) === '-' && arg.length > 1) { | ||
var at = arg.indexOf('=') | ||
if (at > -1) { | ||
hadEq = true | ||
var v = arg.substr(at + 1) | ||
arg = arg.substr(0, at) | ||
var v = arg.slice(at + 1) | ||
arg = arg.slice(0, at) | ||
args.splice(i, 1, arg, v) | ||
@@ -292,3 +346,3 @@ } | ||
var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) | ||
debug("arg=%j shRes=%j", arg, shRes) | ||
debug('arg=%j shRes=%j', arg, shRes) | ||
if (shRes) { | ||
@@ -298,14 +352,16 @@ debug(arg, shRes) | ||
if (arg !== shRes[0]) { | ||
i -- | ||
i-- | ||
continue | ||
} | ||
} | ||
arg = arg.replace(/^-+/, "") | ||
arg = arg.replace(/^-+/, '') | ||
var no = null | ||
while (arg.toLowerCase().indexOf("no-") === 0) { | ||
while (arg.toLowerCase().indexOf('no-') === 0) { | ||
no = !no | ||
arg = arg.substr(3) | ||
arg = arg.slice(3) | ||
} | ||
if (abbrevs[arg]) arg = abbrevs[arg] | ||
if (abbrevs[arg]) { | ||
arg = abbrevs[arg] | ||
} | ||
@@ -323,5 +379,9 @@ var argType = types[arg] | ||
// allow unknown things to be arrays if specified multiple times. | ||
if (!types.hasOwnProperty(arg) && data.hasOwnProperty(arg)) { | ||
if (!Array.isArray(data[arg])) | ||
if ( | ||
!Object.prototype.hasOwnProperty.call(types, arg) && | ||
Object.prototype.hasOwnProperty.call(data, arg) | ||
) { | ||
if (!Array.isArray(data[arg])) { | ||
data[arg] = [data[arg]] | ||
} | ||
isArray = true | ||
@@ -331,3 +391,3 @@ } | ||
var val | ||
, la = args[i + 1] | ||
var la = args[i + 1] | ||
@@ -338,3 +398,3 @@ var isBool = typeof no === 'boolean' || | ||
(typeof argType === 'undefined' && !hadEq) || | ||
(la === "false" && | ||
(la === 'false' && | ||
(argType === null || | ||
@@ -347,7 +407,9 @@ isTypeArray && ~argType.indexOf(null))) | ||
// however, also support --bool true or --bool false | ||
if (la === "true" || la === "false") { | ||
if (la === 'true' || la === 'false') { | ||
val = JSON.parse(la) | ||
la = null | ||
if (no) val = !val | ||
i ++ | ||
if (no) { | ||
val = !val | ||
} | ||
i++ | ||
} | ||
@@ -360,22 +422,25 @@ | ||
val = la | ||
i ++ | ||
} else if ( la === "null" && ~argType.indexOf(null) ) { | ||
i++ | ||
} else if (la === 'null' && ~argType.indexOf(null)) { | ||
// null allowed | ||
val = null | ||
i ++ | ||
} else if ( !la.match(/^-{2,}[^-]/) && | ||
i++ | ||
} else if (!la.match(/^-{2,}[^-]/) && | ||
!isNaN(la) && | ||
~argType.indexOf(Number) ) { | ||
~argType.indexOf(Number)) { | ||
// number | ||
val = +la | ||
i ++ | ||
} else if ( !la.match(/^-[^-]/) && ~argType.indexOf(String) ) { | ||
i++ | ||
} else if (!la.match(/^-[^-]/) && ~argType.indexOf(String)) { | ||
// string | ||
val = la | ||
i ++ | ||
i++ | ||
} | ||
} | ||
if (isArray) (data[arg] = data[arg] || []).push(val) | ||
else data[arg] = val | ||
if (isArray) { | ||
(data[arg] = data[arg] || []).push(val) | ||
} else { | ||
data[arg] = val | ||
} | ||
@@ -387,6 +452,6 @@ continue | ||
if (la === undefined) { | ||
la = "" | ||
la = '' | ||
} else if (la.match(/^-{1,2}[^-]+/)) { | ||
la = "" | ||
i -- | ||
la = '' | ||
i-- | ||
} | ||
@@ -397,10 +462,13 @@ } | ||
la = undefined | ||
i -- | ||
i-- | ||
} | ||
val = la === undefined ? true : la | ||
if (isArray) (data[arg] = data[arg] || []).push(val) | ||
else data[arg] = val | ||
if (isArray) { | ||
(data[arg] = data[arg] || []).push(val) | ||
} else { | ||
data[arg] = val | ||
} | ||
i ++ | ||
i++ | ||
continue | ||
@@ -420,4 +488,5 @@ } | ||
// if it's an exact known option, then don't go any further | ||
if (abbrevs[arg] === arg) | ||
if (abbrevs[arg] === arg) { | ||
return null | ||
} | ||
@@ -427,4 +496,5 @@ // if it's an exact known shortopt, same deal | ||
// make it an array, if it's a list of words | ||
if (shorthands[arg] && !Array.isArray(shorthands[arg])) | ||
if (shorthands[arg] && !Array.isArray(shorthands[arg])) { | ||
shorthands[arg] = shorthands[arg].split(/\s+/) | ||
} | ||
@@ -439,3 +509,3 @@ return shorthands[arg] | ||
return s.length === 1 | ||
}).reduce(function (l,r) { | ||
}).reduce(function (l, r) { | ||
l[r] = true | ||
@@ -448,26 +518,30 @@ return l | ||
var chrs = arg.split("").filter(function (c) { | ||
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 (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 | ||
if (abbrevs[arg] && !shorthands[arg]) | ||
if (abbrevs[arg] && !shorthands[arg]) { | ||
return null | ||
} | ||
// if it's an abbr for a shorthand, then use that | ||
if (shortAbbr[arg]) | ||
if (shortAbbr[arg]) { | ||
arg = shortAbbr[arg] | ||
} | ||
// make it an array, if it's a list of words | ||
if (shorthands[arg] && !Array.isArray(shorthands[arg])) | ||
if (shorthands[arg] && !Array.isArray(shorthands[arg])) { | ||
shorthands[arg] = shorthands[arg].split(/\s+/) | ||
} | ||
return shorthands[arg] | ||
} |
{ | ||
"name": "nopt", | ||
"version": "5.0.0", | ||
"version": "6.0.0", | ||
"description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", | ||
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)", | ||
"author": "GitHub Inc.", | ||
"main": "lib/nopt.js", | ||
@@ -11,3 +11,9 @@ "scripts": { | ||
"prepublishOnly": "git push origin --follow-tags", | ||
"test": "tap test/*.js" | ||
"test": "tap", | ||
"lint": "eslint \"**/*.js\"", | ||
"postlint": "template-oss-check", | ||
"template-oss-apply": "template-oss-apply --force", | ||
"lintfix": "npm run lint -- --fix", | ||
"snap": "tap", | ||
"posttest": "npm run lint" | ||
}, | ||
@@ -23,14 +29,27 @@ "repository": { | ||
"dependencies": { | ||
"abbrev": "1" | ||
"abbrev": "^1.0.0" | ||
}, | ||
"devDependencies": { | ||
"tap": "^14.10.6" | ||
"@npmcli/eslint-config": "^3.0.1", | ||
"@npmcli/template-oss": "3.5.0", | ||
"tap": "^16.3.0" | ||
}, | ||
"tap": { | ||
"lines": 87, | ||
"functions": 91, | ||
"branches": 81, | ||
"statements": 87 | ||
}, | ||
"files": [ | ||
"bin", | ||
"lib" | ||
"bin/", | ||
"lib/" | ||
], | ||
"engines": { | ||
"node": ">=6" | ||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0" | ||
}, | ||
"templateOSS": { | ||
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", | ||
"windowsCI": false, | ||
"version": "3.5.0" | ||
} | ||
} |
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
507
23946
3
5
1
Updatedabbrev@^1.0.0