Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/node_modules/@npmcli/config/lib/index.js')
-rw-r--r--deps/npm/node_modules/@npmcli/config/lib/index.js206
1 files changed, 148 insertions, 58 deletions
diff --git a/deps/npm/node_modules/@npmcli/config/lib/index.js b/deps/npm/node_modules/@npmcli/config/lib/index.js
index 293fad2ec56..dc839a5389c 100644
--- a/deps/npm/node_modules/@npmcli/config/lib/index.js
+++ b/deps/npm/node_modules/@npmcli/config/lib/index.js
@@ -3,6 +3,8 @@ const walkUp = require('walk-up-path')
const ini = require('ini')
const nopt = require('nopt')
const mkdirp = require('mkdirp-infer-owner')
+const mapWorkspaces = require('@npmcli/map-workspaces')
+const rpj = require('read-package-json-fast')
/* istanbul ignore next */
const myUid = process.getuid && process.getuid()
@@ -91,7 +93,6 @@ class Config {
execPath = process.execPath,
cwd = process.cwd(),
}) {
-
// turn the definitions into nopt's weirdo syntax
this.definitions = definitions
const types = {}
@@ -100,8 +101,9 @@ class Config {
for (const [key, def] of Object.entries(definitions)) {
defaults[key] = def.default
types[key] = def.type
- if (def.deprecated)
+ if (def.deprecated) {
this.deprecated[key] = def.deprecated.trim().replace(/\n +/, '\n')
+ }
}
// populated the first time we flatten the object
@@ -162,41 +164,48 @@ class Config {
// return the location where key is found.
find (key) {
- if (!this.loaded)
+ if (!this.loaded) {
throw new Error('call config.load() before reading values')
+ }
return this[_find](key)
}
+
[_find] (key) {
// have to look in reverse order
const entries = [...this.data.entries()]
for (let i = entries.length - 1; i > -1; i--) {
const [where, { data }] = entries[i]
- if (hasOwnProperty(data, key))
+ if (hasOwnProperty(data, key)) {
return where
+ }
}
return null
}
get (key, where) {
- if (!this.loaded)
+ if (!this.loaded) {
throw new Error('call config.load() before reading values')
+ }
return this[_get](key, where)
}
+
// we need to get values sometimes, so use this internal one to do so
// while in the process of loading.
[_get] (key, where = null) {
if (where !== null && !confTypes.has(where)) {
throw new Error('invalid config location param: ' + where)
}
- const { data, source } = this.data.get(where || 'cli')
+ const { data } = this.data.get(where || 'cli')
return where === null || hasOwnProperty(data, key) ? data[key] : undefined
}
set (key, val, where = 'cli') {
- if (!this.loaded)
+ if (!this.loaded) {
throw new Error('call config.load() before setting values')
- if (!confTypes.has(where))
+ }
+ if (!confTypes.has(where)) {
throw new Error('invalid config location param: ' + where)
+ }
this[_checkDeprecated](key)
const { data } = this.data.get(where)
data[key] = val
@@ -209,8 +218,9 @@ class Config {
}
get flat () {
- if (this[_flatOptions])
+ if (this[_flatOptions]) {
return this[_flatOptions]
+ }
// create the object for flat options passed to deps
process.emit('time', 'config:load:flatten')
@@ -225,16 +235,19 @@ class Config {
}
delete (key, where = 'cli') {
- if (!this.loaded)
+ if (!this.loaded) {
throw new Error('call config.load() before deleting values')
- if (!confTypes.has(where))
+ }
+ if (!confTypes.has(where)) {
throw new Error('invalid config location param: ' + where)
+ }
delete this.data.get(where).data[key]
}
async load () {
- if (this.loaded)
+ if (this.loaded) {
throw new Error('attempting to load npm config multiple times')
+ }
process.emit('time', 'config:load')
// first load the defaults, which sets the global prefix
@@ -282,7 +295,9 @@ class Config {
const creds = this.getCredentialsByURI(reg)
// ignore this error because a failed set will strip out anything that
// might be a security hazard, which was the intention.
- try { this.setCredentialsByURI(reg, creds) } catch (_) {}
+ try {
+ this.setCredentialsByURI(reg, creds)
+ } catch (_) {}
process.emit('timeEnd', 'config:load:credentials')
// set proper globalPrefix now that everything is loaded
@@ -319,14 +334,16 @@ class Config {
}
loadHome () {
- if (this.env.HOME)
+ if (this.env.HOME) {
return this.home = this.env.HOME
+ }
this.home = homedir()
}
loadGlobalPrefix () {
- if (this.globalPrefix)
+ if (this.globalPrefix) {
throw new Error('cannot load default global prefix more than once')
+ }
if (this.env.PREFIX) {
this.globalPrefix = this.env.PREFIX
@@ -338,17 +355,18 @@ class Config {
this.globalPrefix = dirname(dirname(this.execPath))
// destdir only is respected on Unix
- if (this.env.DESTDIR)
+ if (this.env.DESTDIR) {
this.globalPrefix = join(this.env.DESTDIR, this.globalPrefix)
+ }
}
}
loadEnv () {
- const prefix = 'npm_config_'
const conf = Object.create(null)
for (const [envKey, envVal] of Object.entries(this.env)) {
- if (!/^npm_config_/i.test(envKey) || envVal === '')
+ if (!/^npm_config_/i.test(envKey) || envVal === '') {
continue
+ }
const key = envKey.substr('npm_config_'.length)
.replace(/(?!^)_/g, '-') // don't replace _ at the start of the key
.toLowerCase()
@@ -368,9 +386,10 @@ class Config {
}
get valid () {
- for (const [where, {valid}] of this.data.entries()) {
- if (valid === false || valid === null && !this.validate(where))
+ for (const [where, { valid }] of this.data.entries()) {
+ if (valid === false || valid === null && !this.validate(where)) {
return false
+ }
}
return true
}
@@ -378,11 +397,12 @@ class Config {
validate (where) {
if (!where) {
let valid = true
- for (const [where, obj] of this.data.entries()) {
+ for (const [where] of this.data.entries()) {
// no need to validate our defaults, we know they're fine
// cli was already validated when parsed the first time
- if (where === 'default' || where === 'builtin' || where === 'cli')
+ if (where === 'default' || where === 'builtin' || where === 'cli') {
continue
+ }
const ret = this.validate(where)
valid = valid && ret
}
@@ -424,14 +444,15 @@ class Config {
this.data.get(where)[_valid] = false
if (Array.isArray(type)) {
- if (type.includes(typeDefs.url.type))
+ if (type.includes(typeDefs.url.type)) {
type = typeDefs.url.type
- else {
+ } else {
/* istanbul ignore if - no actual configs matching this, but
* path types SHOULD be handled this way, like URLs, for the
* same reason */
- if (type.includes(typeDefs.path.type))
+ if (type.includes(typeDefs.path.type)) {
type = typeDefs.path.type
+ }
}
}
@@ -469,15 +490,17 @@ class Config {
this.sources.set(source, where)
if (er) {
conf.loadError = er
- if (er.code !== 'ENOENT')
+ if (er.code !== 'ENOENT') {
this.log.verbose('config', `error loading ${where} config`, er)
+ }
} else {
conf.raw = obj
for (const [key, value] of Object.entries(obj)) {
const k = envReplace(key, this.env)
const v = this.parseField(value, k)
- if (where !== 'default')
+ if (where !== 'default') {
this[_checkDeprecated](k, where, obj, [key, value])
+ }
conf.data[k] = v
}
}
@@ -528,9 +551,9 @@ class Config {
// up loading the "project" config where the "userconfig" will be,
// which causes some calamaties. So, we only load project config if
// it doesn't match what the userconfig will be.
- if (projectFile !== this[_get]('userconfig'))
+ if (projectFile !== this[_get]('userconfig')) {
return this[_loadFile](projectFile, 'project')
- else {
+ } else {
this.data.get('project').source = '(same as "user" config, ignored)'
this.sources.set(this.data.get('project').source, 'project')
}
@@ -543,23 +566,65 @@ class Config {
return
}
+ const cliWorkspaces = this[_get]('workspaces', 'cli')
+
for (const p of walkUp(this.cwd)) {
- // walk up until we have a nm dir or a pj file
- const hasAny = (await Promise.all([
- stat(resolve(p, 'node_modules'))
- .then(st => st.isDirectory())
- .catch(() => false),
- stat(resolve(p, 'package.json'))
- .then(st => st.isFile())
- .catch(() => false),
- ])).some(is => is)
- if (hasAny) {
+ const hasNodeModules = await stat(resolve(p, 'node_modules'))
+ .then((st) => st.isDirectory())
+ .catch(() => false)
+
+ const hasPackageJson = await stat(resolve(p, 'package.json'))
+ .then((st) => st.isFile())
+ .catch(() => false)
+
+ if (!this.localPrefix && (hasNodeModules || hasPackageJson)) {
this.localPrefix = p
- return
+
+ // if workspaces are disabled, return now
+ if (cliWorkspaces === false) {
+ return
+ }
+
+ // otherwise, continue the loop
+ continue
+ }
+
+ if (this.localPrefix && hasPackageJson) {
+ // if we already set localPrefix but this dir has a package.json
+ // then we need to see if `p` is a workspace root by reading its package.json
+ // however, if reading it fails then we should just move on
+ const pkg = await rpj(resolve(p, 'package.json')).catch(() => false)
+ if (!pkg) {
+ continue
+ }
+
+ const workspaces = await mapWorkspaces({ cwd: p, pkg })
+ for (const w of workspaces.values()) {
+ if (w === this.localPrefix) {
+ // see if there's a .npmrc file in the workspace, if so log a warning
+ const hasNpmrc = await stat(resolve(this.localPrefix, '.npmrc'))
+ .then((st) => st.isFile())
+ .catch(() => false)
+
+ if (hasNpmrc) {
+ this.log.warn(`ignoring workspace config at ${this.localPrefix}/.npmrc`)
+ }
+
+ // set the workspace in the default layer, which allows it to be overridden easily
+ const { data } = this.data.get('default')
+ data.workspace = [this.localPrefix]
+ this.localPrefix = p
+ this.log.info(`found workspace root at ${this.localPrefix}`)
+ // we found a root, so we return now
+ return
+ }
+ }
}
}
- this.localPrefix = this.cwd
+ if (!this.localPrefix) {
+ this.localPrefix = this.cwd
+ }
}
loadUserConfig () {
@@ -571,10 +636,12 @@ class Config {
}
async save (where) {
- if (!this.loaded)
+ if (!this.loaded) {
throw new Error('call config.load() before saving')
- if (!confFileTypes.has(where))
+ }
+ if (!confFileTypes.has(where)) {
throw new Error('invalid config location param: ' + where)
+ }
const conf = this.data.get(where)
conf[_raw] = { ...conf.data }
conf[_loadError] = null
@@ -586,7 +653,9 @@ class Config {
// we ignore this error because the failed set already removed
// anything that might be a security hazard, and it won't be
// saved back to the .npmrc file, so we're good.
- try { this.setCredentialsByURI(reg, creds) } catch (_) {}
+ try {
+ this.setCredentialsByURI(reg, creds)
+ } catch (_) {}
}
const iniData = ini.stringify(conf.data).trim() + '\n'
@@ -602,8 +671,9 @@ class Config {
/* istanbul ignore if - this is best-effort and a pita to test */
if (myUid === 0) {
const st = await stat(dir).catch(() => null)
- if (st && (st.uid !== myUid || st.gid !== myGid))
+ if (st && (st.uid !== myUid || st.gid !== myGid)) {
await chown(conf.source, st.uid, st.gid).catch(() => {})
+ }
}
const mode = where === 'user' ? 0o600 : 0o666
await chmod(conf.source, mode)
@@ -651,8 +721,9 @@ class Config {
email = email ||
this.get('email', 'user') ||
this.get(`${nerfed}:email`, 'user')
- if (email)
+ if (email) {
this.set('email', email, 'user')
+ }
}
// field that hasn't been used as documented for a LONG time,
@@ -668,10 +739,12 @@ class Config {
this.delete(`${nerfed}:_password`, 'user')
this.delete(`${nerfed}:username`, 'user')
} else if (username || password) {
- if (!username)
+ if (!username) {
throw new Error('must include username')
- if (!password)
+ }
+ if (!password) {
throw new Error('must include password')
+ }
this.delete(`${nerfed}:_authToken`, 'user')
this.set(`${nerfed}:username`, username, 'user')
// note: not encrypted, no idea why we bothered to do this, but oh well
@@ -689,8 +762,9 @@ class Config {
const creds = {}
const email = this.get(`${nerfed}:email`) || this.get('email')
- if (email)
+ if (email) {
creds.email = email
+ }
const tokenReg = this.get(`${nerfed}:_authToken`) ||
this.get(`${nerfed}:_authtoken`) ||
@@ -725,8 +799,9 @@ class Config {
// at this point, we can only use the values if the URI is the
// default registry.
const defaultNerf = nerfDart(this.get('registry'))
- if (nerfed !== defaultNerf)
+ if (nerfed !== defaultNerf) {
return creds
+ }
const userDef = this.get('username')
const passDef = this.get('_password')
@@ -741,8 +816,9 @@ class Config {
// Handle the old-style _auth=<base64> style for the default
// registry, if set.
const auth = this.get('_auth')
- if (!auth)
+ if (!auth) {
return creds
+ }
const authDecode = Buffer.from(auth, 'base64').toString('utf8')
const authSplit = authDecode.split(':')
@@ -755,7 +831,9 @@ class Config {
// set up the environment object we have with npm_config_* environs
// for all configs that are different from their default values, and
// set EDITOR and HOME.
- setEnvs () { setEnvs(this) }
+ setEnvs () {
+ setEnvs(this)
+ }
}
const _data = Symbol('data')
@@ -781,25 +859,37 @@ class ConfigData {
}
set source (s) {
- if (this[_source])
+ if (this[_source]) {
throw new Error('cannot set ConfigData source more than once')
+ }
this[_source] = s
}
- get source () { return this[_source] }
+
+ get source () {
+ return this[_source]
+ }
set loadError (e) {
- if (this[_loadError] || this[_raw])
+ if (this[_loadError] || this[_raw]) {
throw new Error('cannot set ConfigData loadError after load')
+ }
this[_loadError] = e
}
- get loadError () { return this[_loadError] }
+
+ get loadError () {
+ return this[_loadError]
+ }
set raw (r) {
- if (this[_raw] || this[_loadError])
+ if (this[_raw] || this[_loadError]) {
throw new Error('cannot set ConfigData raw after load')
+ }
this[_raw] = r
}
- get raw () { return this[_raw] }
+
+ get raw () {
+ return this[_raw]
+ }
}
module.exports = Config