@npmcli/config
Advanced tools
+68
-69
| // TODO: set the scope config from package.json or explicit cli config | ||
| const walkUp = require('walk-up-path') | ||
| const { walkUp } = require('walk-up-path') | ||
| const ini = require('ini') | ||
@@ -75,12 +75,8 @@ const nopt = require('nopt') | ||
| const _loaded = Symbol('loaded') | ||
| const _get = Symbol('get') | ||
| const _find = Symbol('find') | ||
| const _loadObject = Symbol('loadObject') | ||
| const _loadFile = Symbol('loadFile') | ||
| const _checkDeprecated = Symbol('checkDeprecated') | ||
| const _flatten = Symbol('flatten') | ||
| const _flatOptions = Symbol('flatOptions') | ||
| class Config { | ||
| #loaded = false | ||
| #flatten | ||
| // populated the first time we flatten the object | ||
| #flatOptions = null | ||
| class Config { | ||
| static get typeDefs () { | ||
@@ -117,5 +113,3 @@ return typeDefs | ||
| // populated the first time we flatten the object | ||
| this[_flatOptions] = null | ||
| this[_flatten] = flatten | ||
| this.#flatten = flatten | ||
| this.types = types | ||
@@ -164,11 +158,11 @@ this.shorthands = shorthands | ||
| this[_loaded] = false | ||
| this.#loaded = false | ||
| } | ||
| get loaded () { | ||
| return this[_loaded] | ||
| return this.#loaded | ||
| } | ||
| get prefix () { | ||
| return this[_get]('global') ? this.globalPrefix : this.localPrefix | ||
| return this.#get('global') ? this.globalPrefix : this.localPrefix | ||
| } | ||
@@ -181,6 +175,3 @@ | ||
| } | ||
| return this[_find](key) | ||
| } | ||
| [_find] (key) { | ||
| // have to look in reverse order | ||
@@ -201,3 +192,3 @@ const entries = [...this.data.entries()] | ||
| } | ||
| return this[_get](key, where) | ||
| return this.#get(key, where) | ||
| } | ||
@@ -207,3 +198,3 @@ | ||
| // while in the process of loading. | ||
| [_get] (key, where = null) { | ||
| #get (key, where = null) { | ||
| if (where !== null && !confTypes.has(where)) { | ||
@@ -223,5 +214,8 @@ throw new Error('invalid config location param: ' + where) | ||
| } | ||
| this[_checkDeprecated](key) | ||
| const { data } = this.data.get(where) | ||
| this.#checkDeprecated(key) | ||
| const { data, raw } = this.data.get(where) | ||
| data[key] = val | ||
| if (['global', 'user', 'project'].includes(where)) { | ||
| raw[key] = val | ||
| } | ||
@@ -232,8 +226,8 @@ // this is now dirty, the next call to this.valid will have to check it | ||
| // the flat options are invalidated, regenerate next time they're needed | ||
| this[_flatOptions] = null | ||
| this.#flatOptions = null | ||
| } | ||
| get flat () { | ||
| if (this[_flatOptions]) { | ||
| return this[_flatOptions] | ||
| if (this.#flatOptions) { | ||
| return this.#flatOptions | ||
| } | ||
@@ -243,10 +237,10 @@ | ||
| process.emit('time', 'config:load:flatten') | ||
| this[_flatOptions] = {} | ||
| this.#flatOptions = {} | ||
| // walk from least priority to highest | ||
| for (const { data } of this.data.values()) { | ||
| this[_flatten](data, this[_flatOptions]) | ||
| this.#flatten(data, this.#flatOptions) | ||
| } | ||
| process.emit('timeEnd', 'config:load:flatten') | ||
| return this[_flatOptions] | ||
| return this.#flatOptions | ||
| } | ||
@@ -261,3 +255,7 @@ | ||
| } | ||
| delete this.data.get(where).data[key] | ||
| const { data, raw } = this.data.get(where) | ||
| delete data[key] | ||
| if (['global', 'user', 'project'].includes(where)) { | ||
| delete raw[key] | ||
| } | ||
| } | ||
@@ -303,4 +301,4 @@ | ||
| // set this before calling setEnvs, so that we don't have to share | ||
| // symbols, as that module also does a bunch of get operations | ||
| this[_loaded] = true | ||
| // private attributes, as that module also does a bunch of get operations | ||
| this.#loaded = true | ||
@@ -321,3 +319,3 @@ // set proper globalPrefix now that everything is loaded | ||
| this[_loadObject]({ | ||
| this.#loadObject({ | ||
| ...this.defaults, | ||
@@ -331,3 +329,3 @@ prefix: this.globalPrefix, | ||
| // the registry, unless overridden somewhere else. | ||
| settableGetter(data, 'metrics-registry', () => this[_get]('registry')) | ||
| settableGetter(data, 'metrics-registry', () => this.#get('registry')) | ||
@@ -338,3 +336,3 @@ // if the prefix is set on cli, env, or userconfig, then we need to | ||
| // returns `/foo/etc/npmrc`, but better to not change it at this point. | ||
| settableGetter(data, 'globalconfig', () => resolve(this[_get]('prefix'), 'etc/npmrc')) | ||
| settableGetter(data, 'globalconfig', () => resolve(this.#get('prefix'), 'etc/npmrc')) | ||
| } | ||
@@ -380,3 +378,3 @@ | ||
| } | ||
| this[_loadObject](conf, 'env', 'environment') | ||
| this.#loadObject(conf, 'env', 'environment') | ||
| } | ||
@@ -391,3 +389,3 @@ | ||
| delete conf.argv | ||
| this[_loadObject](conf, 'cli', 'command line options') | ||
| this.#loadObject(conf, 'cli', 'command line options') | ||
| } | ||
@@ -560,3 +558,4 @@ | ||
| [_loadObject] (obj, where, source, er = null) { | ||
| #loadObject (obj, where, source, er = null) { | ||
| // obj is the raw data read from the file | ||
| const conf = this.data.get(where) | ||
@@ -588,3 +587,3 @@ if (conf.source) { | ||
| if (where !== 'default') { | ||
| this[_checkDeprecated](k, where, obj, [key, value]) | ||
| this.#checkDeprecated(k, where, obj, [key, value]) | ||
| } | ||
@@ -596,3 +595,3 @@ conf.data[k] = v | ||
| [_checkDeprecated] (key, where, obj, kv) { | ||
| #checkDeprecated (key, where, obj, kv) { | ||
| // XXX(npm9+) make this throw an error | ||
@@ -609,8 +608,8 @@ if (this.deprecated[key]) { | ||
| async [_loadFile] (file, type) { | ||
| async #loadFile (file, type) { | ||
| process.emit('time', 'config:load:file:' + file) | ||
| // only catch the error from readFile, not from the loadObject call | ||
| await readFile(file, 'utf8').then( | ||
| data => this[_loadObject](ini.parse(data), type, file), | ||
| er => this[_loadObject](null, type, file, er) | ||
| data => this.#loadObject(ini.parse(data), type, file), | ||
| er => this.#loadObject(null, type, file, er) | ||
| ) | ||
@@ -621,3 +620,3 @@ process.emit('timeEnd', 'config:load:file:' + file) | ||
| loadBuiltinConfig () { | ||
| return this[_loadFile](resolve(this.npmPath, 'npmrc'), 'builtin') | ||
| return this.#loadFile(resolve(this.npmPath, 'npmrc'), 'builtin') | ||
| } | ||
@@ -637,3 +636,3 @@ | ||
| if (this[_get]('global') === true || this[_get]('location') === 'global') { | ||
| if (this.#get('global') === true || this.#get('location') === 'global') { | ||
| this.data.get('project').source = '(global mode enabled, ignored)' | ||
@@ -650,4 +649,4 @@ this.sources.set(this.data.get('project').source, 'project') | ||
| // it doesn't match what the userconfig will be. | ||
| if (projectFile !== this[_get]('userconfig')) { | ||
| return this[_loadFile](projectFile, 'project') | ||
| if (projectFile !== this.#get('userconfig')) { | ||
| return this.#loadFile(projectFile, 'project') | ||
| } else { | ||
@@ -660,3 +659,3 @@ this.data.get('project').source = '(same as "user" config, ignored)' | ||
| async loadLocalPrefix () { | ||
| const cliPrefix = this[_get]('prefix', 'cli') | ||
| const cliPrefix = this.#get('prefix', 'cli') | ||
| if (cliPrefix) { | ||
@@ -667,4 +666,4 @@ this.localPrefix = cliPrefix | ||
| const cliWorkspaces = this[_get]('workspaces', 'cli') | ||
| const isGlobal = this[_get]('global') || this[_get]('location') === 'global' | ||
| const cliWorkspaces = this.#get('workspaces', 'cli') | ||
| const isGlobal = this.#get('global') || this.#get('location') === 'global' | ||
@@ -729,7 +728,7 @@ for (const p of walkUp(this.cwd)) { | ||
| loadUserConfig () { | ||
| return this[_loadFile](this[_get]('userconfig'), 'user') | ||
| return this.#loadFile(this.#get('userconfig'), 'user') | ||
| } | ||
| loadGlobalConfig () { | ||
| return this[_loadFile](this[_get]('globalconfig'), 'global') | ||
| return this.#loadFile(this.#get('globalconfig'), 'global') | ||
| } | ||
@@ -746,3 +745,2 @@ | ||
| const conf = this.data.get(where) | ||
| conf[_raw] = { ...conf.data } | ||
| conf[_loadError] = null | ||
@@ -760,3 +758,5 @@ | ||
| const iniData = ini.stringify(conf.data).trim() + '\n' | ||
| // We need the actual raw data before we called parseField so that we are | ||
| // saving the same content back to the file | ||
| const iniData = ini.stringify(conf.raw).trim() + '\n' | ||
| if (!iniData.trim()) { | ||
@@ -901,13 +901,12 @@ // ignore the unlink error (eg, if file doesn't exist) | ||
| const _data = Symbol('data') | ||
| const _raw = Symbol('raw') | ||
| const _loadError = Symbol('loadError') | ||
| const _source = Symbol('source') | ||
| const _valid = Symbol('valid') | ||
| class ConfigData { | ||
| #data | ||
| #source = null | ||
| #raw = null | ||
| constructor (parent) { | ||
| this[_data] = Object.create(parent && parent.data) | ||
| this[_source] = null | ||
| this[_loadError] = null | ||
| this[_raw] = null | ||
| this.#data = Object.create(parent && parent.data) | ||
| this.#raw = {} | ||
| this[_valid] = true | ||
@@ -917,3 +916,3 @@ } | ||
| get data () { | ||
| return this[_data] | ||
| return this.#data | ||
| } | ||
@@ -926,14 +925,14 @@ | ||
| set source (s) { | ||
| if (this[_source]) { | ||
| if (this.#source) { | ||
| throw new Error('cannot set ConfigData source more than once') | ||
| } | ||
| this[_source] = s | ||
| this.#source = s | ||
| } | ||
| get source () { | ||
| return this[_source] | ||
| return this.#source | ||
| } | ||
| set loadError (e) { | ||
| if (this[_loadError] || this[_raw]) { | ||
| if (this[_loadError] || (Object.keys(this.#raw).length)) { | ||
| throw new Error('cannot set ConfigData loadError after load') | ||
@@ -949,10 +948,10 @@ } | ||
| set raw (r) { | ||
| if (this[_raw] || this[_loadError]) { | ||
| if (Object.keys(this.#raw).length || this[_loadError]) { | ||
| throw new Error('cannot set ConfigData raw after load') | ||
| } | ||
| this[_raw] = r | ||
| this.#raw = r | ||
| } | ||
| get raw () { | ||
| return this[_raw] | ||
| return this.#raw | ||
| } | ||
@@ -959,0 +958,0 @@ } |
+3
-3
| { | ||
| "name": "@npmcli/config", | ||
| "version": "6.1.5", | ||
| "version": "6.1.6", | ||
| "files": [ | ||
@@ -41,3 +41,3 @@ "bin/", | ||
| "@npmcli/map-workspaces": "^3.0.2", | ||
| "ini": "^3.0.0", | ||
| "ini": "^4.1.0", | ||
| "nopt": "^7.0.0", | ||
@@ -47,3 +47,3 @@ "proc-log": "^3.0.0", | ||
| "semver": "^7.3.5", | ||
| "walk-up-path": "^1.0.0" | ||
| "walk-up-path": "^3.0.1" | ||
| }, | ||
@@ -50,0 +50,0 @@ "engines": { |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
50707
-0.18%1117
-0.18%+ Added
+ Added
- Removed
- Removed
Updated
Updated