node/deps/npm/lib/utils/flat-options.js
Ruy Adorno d3906ae294
deps: upgrade npm to 7.5.0
PR-URL: https://github.com/nodejs/node/pull/37117
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
2021-01-29 23:49:44 -05:00

255 lines
6.9 KiB
JavaScript

// return a flattened config object with canonical names suitable for
// passing to dependencies like arborist, pacote, npm-registry-fetch, etc.
const log = require('npmlog')
const crypto = require('crypto')
const querystring = require('querystring')
const npmSession = crypto.randomBytes(8).toString('hex')
log.verbose('npm-session', npmSession)
const { join } = require('path')
const buildOmitList = obj => {
const include = obj.include || []
const omit = new Set((obj.omit || [])
.filter(type => !include.includes(type)))
const only = obj.only
if (/^prod(uction)?$/.test(only) || obj.production)
omit.add('dev')
if (/dev/.test(obj.also))
omit.delete('dev')
if (obj.dev)
omit.delete('dev')
if (obj.optional === false)
omit.add('optional')
obj.omit = [...omit]
// it would perhaps make more sense to put this in @npmcli/config, but
// since we can set dev to be omitted in multiple various legacy ways,
// it's better to set it here once it's all resolved.
if (obj.omit.includes('dev'))
process.env.NODE_ENV = 'production'
return [...omit]
}
// turn an object with npm-config style keys into an options object
// with camelCase values. This doesn't account for the stuff that is
// not pulled from the config keys, that's all handled only for the
// main function which acts on the npm object itself. Used by the
// flatOptions generator, and by the publishConfig handling logic.
const flatten = obj => ({
includeStaged: obj['include-staged'],
preferDedupe: obj['prefer-dedupe'],
ignoreScripts: obj['ignore-scripts'],
nodeVersion: obj['node-version'],
cache: join(obj.cache, '_cacache'),
global: obj.global,
registry: obj.registry,
scope: obj.scope,
access: obj.access,
alwaysAuth: obj['always-auth'],
audit: obj.audit,
auditLevel: obj['audit-level'],
_auth: obj._auth,
authType: obj['auth-type'],
ssoType: obj['sso-type'],
ssoPollFrequency: obj['sso-poll-frequency'],
before: obj.before,
browser: obj.browser,
ca: obj.ca,
cafile: obj.cafile,
cert: obj.cert,
key: obj.key,
// token creation options
cidr: obj.cidr,
readOnly: obj['read-only'],
// npm version options
preid: obj.preid,
tagVersionPrefix: obj['tag-version-prefix'],
allowSameVersion: obj['allow-same-version'],
// npm version git options
message: obj.message,
commitHooks: obj['commit-hooks'],
gitTagVersion: obj['git-tag-version'],
signGitCommit: obj['sign-git-commit'],
signGitTag: obj['sign-git-tag'],
// only used for npm ls in v7, not update
depth: obj.depth,
all: obj.all,
// Output configs
unicode: obj.unicode,
json: obj.json,
long: obj.long,
parseable: obj.parseable,
// options for npm search
search: {
description: obj.description,
exclude: obj.searchexclude,
limit: obj.searchlimit || 20,
opts: querystring.parse(obj.searchopts),
staleness: obj.searchstaleness,
},
diff: obj.diff,
diffUnified: obj['diff-unified'],
diffIgnoreAllSpace: obj['diff-ignore-all-space'],
diffNameOnly: obj['diff-name-only'],
diffNoPrefix: obj['diff-no-prefix'],
diffSrcPrefix: obj['diff-src-prefix'],
diffDstPrefix: obj['diff-dst-prefix'],
diffText: obj['diff-text'],
dryRun: obj['dry-run'],
engineStrict: obj['engine-strict'],
retry: {
retries: obj['fetch-retries'],
factor: obj['fetch-retry-factor'],
maxTimeout: obj['fetch-retry-maxtimeout'],
minTimeout: obj['fetch-retry-mintimeout'],
},
timeout: obj['fetch-timeout'],
force: obj.force,
formatPackageLock: obj['format-package-lock'],
fund: obj.fund,
// binary locators
git: obj.git,
viewer: obj.viewer,
editor: obj.editor,
// configs that affect how we build trees
binLinks: obj['bin-links'],
rebuildBundle: obj['rebuild-bundle'],
// --no-shrinkwrap is the same as --no-package-lock
packageLock: !(obj['package-lock'] === false ||
obj.shrinkwrap === false),
packageLockOnly: obj['package-lock-only'],
globalStyle: obj['global-style'],
legacyBundling: obj['legacy-bundling'],
foregroundScripts: !!obj['foreground-scripts'],
scriptShell: obj['script-shell'] || undefined,
shell: obj.shell,
omit: buildOmitList(obj),
legacyPeerDeps: obj['legacy-peer-deps'],
strictPeerDeps: obj['strict-peer-deps'],
// npx stuff
call: obj.call,
package: obj.package,
// used to build up the appropriate {add:{...}} options to Arborist.reify
save: obj.save,
saveBundle: obj['save-bundle'] && !obj['save-peer'],
saveType: obj['save-optional'] && obj['save-peer']
? 'peerOptional'
: obj['save-optional'] ? 'optional'
: obj['save-dev'] ? 'dev'
: obj['save-peer'] ? 'peer'
: obj['save-prod'] ? 'prod'
: null,
savePrefix: obj['save-exact'] ? ''
: obj['save-prefix'],
// configs for npm-registry-fetch
otp: obj.otp,
offline: obj.offline,
preferOffline: getPreferOffline(obj),
preferOnline: getPreferOnline(obj),
strictSSL: obj['strict-ssl'],
defaultTag: obj.tag,
userAgent: obj['user-agent'],
// yes, it's fine, just do it, jeez, stop asking
yes: obj.yes,
...getScopesAndAuths(obj),
// npm fund exclusive option to select an item from a funding list
which: obj.which,
// socks proxy can be configured in https-proxy or proxy field
// note that the various (HTTPS_|HTTP_|]PROXY environs will be
// respected if this is not set.
proxy: obj['https-proxy'] || obj.proxy,
noProxy: obj.noproxy,
})
const flatOptions = npm => npm.flatOptions || Object.freeze({
// flatten the config object
...flatten(npm.config.list[0]),
// Note that many of these do not come from configs or cli flags
// per se, though they may be implied or defined by them.
log,
npmSession,
dmode: npm.modes.exec,
fmode: npm.modes.file,
umask: npm.modes.umask,
hashAlgorithm: 'sha1', // XXX should this be sha512?
color: !!npm.color,
projectScope: npm.projectScope,
npmVersion: npm.version,
// npm.command is not set until AFTER flatOptions are defined
// so we need to make this a getter.
get npmCommand () {
return npm.command
},
tmp: npm.tmp,
prefix: npm.prefix,
globalPrefix: npm.globalPrefix,
localPrefix: npm.localPrefix,
npmBin: require.main && require.main.filename,
nodeBin: process.env.NODE || process.execPath,
get tag () {
return npm.config.get('tag')
},
})
const getPreferOnline = obj => {
const po = obj['prefer-online']
if (po !== undefined)
return po
return obj['cache-max'] <= 0
}
const getPreferOffline = obj => {
const po = obj['prefer-offline']
if (po !== undefined)
return po
return obj['cache-min'] >= 9999
}
// pull out all the @scope:<key> and //host:key config fields
// these are used by npm-registry-fetch for authing against registries
const getScopesAndAuths = obj => {
const scopesAndAuths = {}
// pull out all the @scope:... configs into a flat object.
for (const key in obj) {
if (/@.*:registry$/i.test(key) || /^\/\//.test(key))
scopesAndAuths[key] = obj[key]
}
return scopesAndAuths
}
module.exports = Object.assign(flatOptions, { flatten })