diff options
author | isaacs <i@izs.me> | 2020-03-08 05:06:27 +0300 |
---|---|---|
committer | isaacs <i@izs.me> | 2020-05-08 04:12:27 +0300 |
commit | e3e8c681b28eddc43d4e12649ba23645b49cd9bd (patch) | |
tree | 29099d162c2427da0b3e6418fa9470363850e7ca /lib | |
parent | b7165476fa8fcefec7648453ad1ac91ead63f934 (diff) |
Set basic npm envs in main command function
This sets environment variables for npm_command, npm_execpath,
npm_node_execpath, NODE_OPTIONS, and any non-default configs that do not
start with @, /, or _ (as those are potentially sensitive, or at least
not useful).
This is in preparation for the move from npm-lifecycle to
@npmcli/run-script for running lifecycle scripts.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/config/core.js | 26 | ||||
-rw-r--r-- | lib/config/set-envs.js | 42 | ||||
-rw-r--r-- | lib/npm.js | 17 |
3 files changed, 64 insertions, 21 deletions
diff --git a/lib/config/core.js b/lib/config/core.js index 36420b345..a3110464e 100644 --- a/lib/config/core.js +++ b/lib/config/core.js @@ -356,25 +356,25 @@ Conf.prototype.addEnv = function (env) { return CC.prototype.addEnv.call(this, '', conf, 'env') } -function parseField (f, k) { +function parseField (f, k, listElement = false) { if (typeof f !== 'string' && !(f instanceof String)) return f // type can be an array or single thing. - var typeList = [].concat(types[k]) - var isPath = typeList.indexOf(path) !== -1 - var isBool = typeList.indexOf(Boolean) !== -1 - var isString = typeList.indexOf(String) !== -1 - var isUmask = typeList.indexOf(Umask) !== -1 - var isNumber = typeList.indexOf(Number) !== -1 + const typeList = [].concat(types[k]) + const isPath = typeList.includes(path) + const isBool = typeList.includes(Boolean) + const isString = typeList.includes(String) + const isUmask = typeList.includes(Umask) + const isNumber = typeList.includes(Number) + const isList = typeList.includes(Array) && !listElement f = ('' + f).trim() - if (f.match(/^".*"$/)) { - try { - f = JSON.parse(f) - } catch (e) { - throw new Error('Failed parsing JSON config key ' + k + ': ' + f) - } + // list types get put in the environment separated by double-\n + // usually a single \n would suffice, but ca/cert configs can contain + // line breaks and multiple entries. + if (isList) { + return f.split('\n').map(field => parseField(field, k, true)) } if (isBool && !isString && f === '') return true diff --git a/lib/config/set-envs.js b/lib/config/set-envs.js new file mode 100644 index 000000000..faa75b5f5 --- /dev/null +++ b/lib/config/set-envs.js @@ -0,0 +1,42 @@ +// Set environment variables for any non-default configs, +// so that they're already there when we run lifecycle scripts. +// +// See https://github.com/npm/rfcs/pull/90 + +const envName = name => `npm_config_${name.replace(/-/g, '_')}` + +const envKey = (key, val) => { + return !/^[\/@_]/.test(key) && + (typeof val === 'string' || Array.isArray(val)) && + `npm_config_${key.replace(/-/g, '_').toLowerCase()}` +} + +const envVal = val => Array.isArray(val) ? val.join('\n\n') : val + +const setEnvs = npm => { + // The objects in the config.list array are arranged in + // a prototype chain, so we can just for/in over the top + // of the stack and grab any that don't match the default + const { config: { list: [ configs ] } } = npm + const { defaults } = require('./defaults.js') + const set = {} + for (const key in configs) { + const val = configs[key] + const environ = envKey(key, val) + if (defaults[key] !== val && environ) { + process.env[environ] = envVal(val) + } + } + + process.env.npm_execpath = require.main.filename + process.env.npm_node_execpath = process.execPath + process.env.npm_command = npm.command + + // note: this doesn't afect the *current* node process, of course, since + // it's already started, but it does affect the options passed to scripts. + if (configs['node-options']) { + process.env.NODE_OPTIONS = configs['node-options'] + } +} + +module.exports = setEnvs diff --git a/lib/npm.js b/lib/npm.js index 03b333867..8567f5b37 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -111,19 +111,20 @@ 'See the README.md or bin/npm-cli.js for example usage.' ) } - var a = npm.deref(c) + var actualCommand = npm.deref(c) if (c === 'la' || c === 'll') { npm.config.set('long', true) } - npm.command = c - npm.config.set('command', c) + npm.command = actualCommand npm.flatOptions = require('./config/flat-options.js')(npm) - if (commandCache[a]) return commandCache[a] + require('./config/set-envs.js')(npm) - var cmd = require(path.join(__dirname, a + '.js')) + if (commandCache[actualCommand]) return commandCache[actualCommand] - commandCache[a] = function () { + var cmd = require(path.join(__dirname, actualCommand + '.js')) + + commandCache[actualCommand] = function () { var args = Array.prototype.slice.call(arguments, 0) if (typeof args[args.length - 1] !== 'function') { args.push(defaultCb) @@ -142,10 +143,10 @@ } Object.keys(cmd).forEach(function (k) { - commandCache[a][k] = cmd[k] + commandCache[actualCommand][k] = cmd[k] }) - return commandCache[a] + return commandCache[actualCommand] }, enumerable: fullList.indexOf(c) !== -1, configurable: true }) |