diff --git a/lib/config/clear-credentials-by-uri.js b/lib/config/clear-credentials-by-uri.js deleted file mode 100644 index 13c356605f021..0000000000000 --- a/lib/config/clear-credentials-by-uri.js +++ /dev/null @@ -1,16 +0,0 @@ -var assert = require('assert') - -var toNerfDart = require('./nerf-dart.js') - -module.exports = clearCredentialsByURI - -function clearCredentialsByURI (uri) { - assert(uri && typeof uri === 'string', 'registry URL is required') - - var nerfed = toNerfDart(uri) - - this.del(nerfed + ':_authToken', 'user') - this.del(nerfed + ':_password', 'user') - this.del(nerfed + ':username', 'user') - this.del(nerfed + ':email', 'user') -} diff --git a/lib/config/core.js b/lib/config/core.js deleted file mode 100644 index 13dabc4a11ef6..0000000000000 --- a/lib/config/core.js +++ /dev/null @@ -1,378 +0,0 @@ -const CC = require('config-chain').ConfigChain -const inherits = require('inherits') -const configDefs = require('./defaults.js') -const types = configDefs.types -const fs = require('fs') -const path = require('path') -const nopt = require('nopt') -const ini = require('ini') -const Umask = configDefs.Umask -const mkdirp = require('mkdirp-infer-owner') -const umask = require('../utils/umask') -const isWindows = require('../utils/is-windows.js') - -const myUid = process.getuid && process.getuid() -const myGid = process.getgid && process.getgid() - -const { promisify } = require('util') -const load = async (cli, builtin) => { - // clone the cli object that's passed in, so we don't mutate it - cli = { ...cli } - - // check for a builtin if provided. - exports.usingBuiltin = !!builtin - const rc = exports.rootConf = new Conf() - if (builtin) { - rc.addFile(builtin, 'builtin') - } else { - rc.add({}, 'builtin') - } - - return load_(builtin, rc, cli) -} - -// XXX promisify this the rest of the way, and all the Conf class methods -const load_ = promisify(function load_ (builtin, rc, cli, cb) { - const defaults = configDefs.defaults - const conf = new Conf(rc) - - conf.usingBuiltin = !!builtin - conf.add(cli, 'cli') - conf.addEnv() - - conf.loadPrefix(er => { - if (er) return cb(er) - - // If you're doing `npm --userconfig=~/foo.npmrc` then you'd expect - // that ~/.npmrc won't override the stuff in ~/foo.npmrc (or, indeed - // be used at all). - // - // However, if the cwd is ~, then ~/.npmrc is the home for the project - // config, and will override the userconfig. - // - // If you're not setting the userconfig explicitly, then it will be loaded - // twice, which is harmless but excessive. If you *are* setting the - // userconfig explicitly then it will override your explicit intent, and - // that IS harmful and unexpected. - // - // Solution: Do not load project config file that is the same as either - // the default or resolved userconfig value. npm will log a "verbose" - // message about this when it happens, but it is a rare enough edge case - // that we don't have to be super concerned about it. - const projectConf = path.resolve(conf.localPrefix, '.npmrc') - const defaultUserConfig = rc.get('userconfig') - const resolvedUserConfig = conf.get('userconfig') - if (!conf.get('global') && - projectConf !== defaultUserConfig && - projectConf !== resolvedUserConfig) { - conf.addFile(projectConf, 'project') - conf.once('load', afterPrefix) - } else { - conf.add({}, 'project') - afterPrefix() - } - }) - - function afterPrefix () { - conf.addFile(conf.get('userconfig'), 'user') - conf.once('error', cb) - conf.once('load', afterUser) - } - - function afterUser () { - // globalconfig and globalignorefile defaults - // need to respond to the 'prefix' setting up to this point. - // Eg, `npm config get globalconfig --prefix ~/local` should - // return `~/local/etc/npmrc` - // annoying humans and their expectations! - if (conf.get('prefix')) { - const etc = path.resolve(conf.get('prefix'), 'etc') - defaults.globalconfig = path.resolve(etc, 'npmrc') - defaults.globalignorefile = path.resolve(etc, 'npmignore') - } - - conf.addFile(conf.get('globalconfig'), 'global') - - // move the builtin into the conf stack now. - conf.root = defaults - conf.add(rc.shift(), 'builtin') - conf.once('load', function () { - conf.loadExtras(afterExtras) - }) - } - - function afterExtras (er) { - if (er) return cb(er) - - // warn about invalid bits. - validate(conf) - - const cafile = conf.get('cafile') - - if (cafile) { - return conf.loadCAFile(cafile, finalize) - } - - finalize() - } - - function finalize (er) { - if (er) { - return cb(er) - } - - exports.loaded = conf - cb(er, conf) - } -}) - -// Basically the same as CC, but: -// 1. Always ini -// 2. Parses environment variable names in field values -// 3. Field values that start with ~/ are replaced with process.env.HOME -// 4. Can inherit from another Conf object, using it as the base. -inherits(Conf, CC) -function Conf (base) { - if (!(this instanceof Conf)) return new Conf(base) - - CC.call(this) - - if (base) { - if (base instanceof Conf) { - this.root = base.list[0] || base.root - } else { - this.root = base - } - } else { - this.root = configDefs.defaults - } -} - -Conf.prototype.loadPrefix = require('./load-prefix.js') -Conf.prototype.loadCAFile = require('./load-cafile.js') -Conf.prototype.setUser = require('./set-user.js') -Conf.prototype.getCredentialsByURI = require('./get-credentials-by-uri.js') -Conf.prototype.setCredentialsByURI = require('./set-credentials-by-uri.js') -Conf.prototype.clearCredentialsByURI = require('./clear-credentials-by-uri.js') - -Conf.prototype.loadExtras = function (cb) { - this.setUser(function (er) { - if (er) return cb(er) - // Without prefix, nothing will ever work - mkdirp(this.prefix).then(() => cb()).catch(cb) - }.bind(this)) -} - -Conf.prototype.save = function (where, cb) { - const target = this.sources[where] - if (!target || !(target.path || target.source) || !target.data) { - let er - if (where !== 'builtin') er = new Error('bad save target: ' + where) - if (cb) { - process.nextTick(() => cb(er)) - return this - } - return this.emit('error', er) - } - - if (target.source) { - const pref = target.prefix || '' - Object.keys(target.data).forEach(function (k) { - target.source[pref + k] = target.data[k] - }) - if (cb) process.nextTick(cb) - return this - } - - const data = ini.stringify(target.data) - - const then = er => { - if (er) return done(er) - fs.chmod(target.path, mode, done) - } - - const done = er => { - if (er) { - if (cb) return cb(er) - else return this.emit('error', er) - } - this._saving-- - if (this._saving === 0) { - if (cb) cb() - this.emit('save') - } - } - - this._saving++ - - const mode = where === 'user' ? 0o600 : 0o666 - if (!data.trim()) { - // ignore the possible error (e.g. the file doesn't exist) - fs.unlink(target.path, () => done()) - } else { - const dir = path.dirname(target.path) - mkdirp(dir).catch(then).then(() => { - fs.stat(dir, (er, st) => { - if (er) return then(er) - fs.writeFile(target.path, data, 'utf8', function (er) { - if (er) return then(er) - if (myUid === 0 && (myUid !== st.uid || myGid !== st.gid)) { - fs.chown(target.path, st.uid, st.gid, then) - } else { - then() - } - }) - }) - }) - } - - return this -} - -Conf.prototype.addFile = function (file, name) { - name = name || file - var marker = { __source__: name } - this.sources[name] = { path: file, type: 'ini' } - this.push(marker) - this._await() - fs.readFile(file, 'utf8', function (er, data) { - // just ignore missing files. - if (er) return this.add({}, marker) - - this.addString(data, file, 'ini', marker) - }.bind(this)) - return this -} - -// always ini files. -Conf.prototype.parse = function (content, file) { - return CC.prototype.parse.call(this, content, file, 'ini') -} - -Conf.prototype.add = function (data, marker) { - try { - Object.keys(data).forEach(function (k) { - const newKey = envReplace(k) - const newField = parseField(data[k], newKey) - delete data[k] - data[newKey] = newField - }) - } catch (e) { - this.emit('error', e) - return this - } - return CC.prototype.add.call(this, data, marker) -} - -Conf.prototype.addEnv = function (env) { - env = env || process.env - var conf = {} - Object.keys(env) - .filter(function (k) { return k.match(/^npm_config_/i) }) - .forEach(function (k) { - if (!env[k]) return - - // leave first char untouched, even if - // it is a '_' - convert all other to '-' - var p = k.toLowerCase() - .replace(/^npm_config_/, '') - .replace(/(?!^)_/g, '-') - conf[p] = env[k] - }) - return CC.prototype.addEnv.call(this, '', conf, 'env') -} - -function parseField (f, k, listElement = false) { - if (typeof f !== 'string' && !(f instanceof String)) return f - - // type can be an array or single thing. - 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() - - // 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 - - switch (f) { - case 'true': return true - case 'false': return false - case 'null': return null - case 'undefined': return undefined - } - - f = envReplace(f) - - if (isPath) { - var homePattern = isWindows ? /^~(\/|\\)/ : /^~\// - if (f.match(homePattern) && process.env.HOME) { - f = path.resolve(process.env.HOME, f.substr(2)) - } - f = path.resolve(f) - } - - if (isUmask) f = umask.fromString(f) - - if (isNumber && !isNaN(f)) f = +f - - return f -} - -function envReplace (f) { - if (typeof f !== 'string' || !f) return f - - // replace any ${ENV} values with the appropriate environ. - var envExpr = /(\\*)\$\{([^}]+)\}/g - return f.replace(envExpr, function (orig, esc, name) { - esc = esc.length && esc.length % 2 - if (esc) return orig - if (undefined === process.env[name]) { - throw new Error('Failed to replace env in config: ' + orig) - } - - return process.env[name] - }) -} - -function validate (cl) { - // warn about invalid configs at every level. - cl.list.forEach(function (conf) { - nopt.clean(conf, configDefs.types) - }) - - nopt.clean(cl.root, configDefs.types) -} - -exports.load = load -exports.Conf = Conf -exports.loaded = false -exports.rootConf = null -exports.usingBuiltin = false -exports.defs = configDefs - -Object.defineProperty(exports, 'defaults', { - get: function () { - return configDefs.defaults - }, - enumerable: true -}) - -Object.defineProperty(exports, 'types', { - get: function () { - return configDefs.types - }, - enumerable: true -}) - -exports.validate = validate diff --git a/lib/config/defaults.js b/lib/config/defaults.js deleted file mode 100644 index 13e3c0c11c666..0000000000000 --- a/lib/config/defaults.js +++ /dev/null @@ -1,453 +0,0 @@ -// defaults, types, and shorthands. - -var path = require('path') -var url = require('url') -var Stream = require('stream').Stream -var semver = require('semver') -var nopt = require('nopt') -var os = require('os') -var osenv = require('osenv') -var umask = require('../utils/umask') -var hasUnicode = require('has-unicode') - -var log -try { - log = require('npmlog') -} catch (er) { - var util = require('util') - log = { - warn: function (m) { - console.warn(m + ' ' + util.format.apply(util, [].slice.call(arguments, 1))) - } - } -} - -exports.Umask = Umask -function Umask () {} -function validateUmask (data, k, val) { - return umask.validate(data, k, val) -} - -function validateSemver (data, k, val) { - if (!semver.valid(val)) return false - data[k] = semver.valid(val) -} - -function validateStream (data, k, val) { - if (!(val instanceof Stream)) return false - data[k] = val -} - -nopt.typeDefs.semver = { type: semver, validate: validateSemver } -nopt.typeDefs.Stream = { type: Stream, validate: validateStream } -nopt.typeDefs.Umask = { type: Umask, validate: validateUmask } - -nopt.invalidHandler = function (k, val, type) { - log.warn('invalid config', k + '=' + JSON.stringify(val)) - - if (Array.isArray(type)) { - if (type.indexOf(url) !== -1) type = url - else if (type.indexOf(path) !== -1) type = path - } - - switch (type) { - case Umask: - log.warn('invalid config', 'Must be umask, octal number in range 0000..0777') - break - case url: - log.warn('invalid config', "Must be a full url with 'http://'") - break - case path: - log.warn('invalid config', 'Must be a valid filesystem path') - break - case Number: - log.warn('invalid config', 'Must be a numeric value') - break - case Stream: - log.warn('invalid config', 'Must be an instance of the Stream class') - break - } -} - -var defaults - -var temp = osenv.tmpdir() -var home = osenv.home() - -var uidOrPid = process.getuid ? process.getuid() : process.pid - -if (home) process.env.HOME = home -else home = path.resolve(temp, 'npm-' + uidOrPid) - -var cacheExtra = process.platform === 'win32' ? 'npm-cache' : '.npm' -var cacheRoot = (process.platform === 'win32' && process.env.APPDATA) || home -var cache = path.resolve(cacheRoot, cacheExtra) - -var globalPrefix -Object.defineProperty(exports, 'defaults', { - get: function () { - if (defaults) return defaults - - if (process.env.PREFIX) { - globalPrefix = process.env.PREFIX - } else if (process.platform === 'win32') { - // c:\node\node.exe --> prefix=c:\node\ - globalPrefix = path.dirname(process.execPath) - } else { - // /usr/local/bin/node --> prefix=/usr/local - globalPrefix = path.dirname(path.dirname(process.execPath)) - - // destdir only is respected on Unix - if (process.env.DESTDIR) { - globalPrefix = path.join(process.env.DESTDIR, globalPrefix) - } - } - - defaults = { - access: null, - all: false, - 'allow-same-version': false, - 'always-auth': false, - also: null, - audit: true, - 'audit-level': null, - 'auth-type': 'legacy', - - before: null, - 'bin-links': true, - browser: null, - - ca: null, - cafile: null, - - cache: cache, - - 'cache-lock-stale': 60000, - 'cache-lock-retries': 10, - 'cache-lock-wait': 10000, - - 'cache-max': Infinity, - 'cache-min': 10, - - cert: null, - - cidr: null, - - color: process.env.NO_COLOR == null, - call: '', - depth: 0, - description: true, - dev: false, - 'dry-run': false, - editor: osenv.editor(), - 'engine-strict': false, - force: false, - 'format-package-lock': true, - - fund: true, - - 'fetch-retries': 2, - 'fetch-retry-factor': 10, - 'fetch-retry-mintimeout': 10000, - 'fetch-retry-maxtimeout': 60000, - - git: 'git', - 'git-tag-version': true, - 'commit-hooks': true, - - global: false, - globalconfig: path.resolve(globalPrefix, 'etc', 'npmrc'), - 'global-style': false, - group: process.platform === 'win32' ? 0 - : process.env.SUDO_GID || (process.getgid && process.getgid()), - 'ham-it-up': false, - heading: 'npm', - 'if-present': false, - include: [], - 'include-staged': false, - 'ignore-prepublish': false, - 'ignore-scripts': false, - 'init-module': path.resolve(home, '.npm-init.js'), - 'init-author-name': '', - 'init-author-email': '', - 'init-author-url': '', - 'init-version': '1.0.0', - 'init-license': 'ISC', - json: false, - key: null, - 'legacy-bundling': false, - 'legacy-peer-deps': false, - link: false, - 'local-address': undefined, - loglevel: 'notice', - 'logs-max': 10, - long: false, - maxsockets: 50, - message: '%s', - 'metrics-registry': null, - 'node-options': null, - 'node-version': process.version, - offline: false, - omit: [], - only: null, - optional: true, - otp: null, - package: [], - 'package-lock': true, - 'package-lock-only': false, - parseable: false, - 'prefer-offline': false, - 'prefer-online': false, - prefix: globalPrefix, - preid: '', - production: process.env.NODE_ENV === 'production', - progress: !process.env.TRAVIS && !process.env.CI, - proxy: null, - 'https-proxy': null, - noproxy: null, - 'user-agent': 'npm/{npm-version} ' + - 'node/{node-version} ' + - '{platform} ' + - '{arch} ' + - '{ci}', - 'read-only': false, - 'rebuild-bundle': true, - registry: 'https://registry.npmjs.org/', - rollback: true, - save: true, - 'save-bundle': false, - 'save-dev': false, - 'save-exact': false, - 'save-optional': false, - 'save-prefix': '^', - 'save-prod': false, - scope: '', - 'script-shell': null, - 'scripts-prepend-node-path': 'warn-only', - searchopts: '', - searchexclude: null, - searchlimit: 20, - searchstaleness: 15 * 60, - 'send-metrics': false, - shell: osenv.shell(), - shrinkwrap: true, - 'sign-git-commit': false, - 'sign-git-tag': false, - 'sso-poll-frequency': 500, - 'sso-type': 'oauth', - 'strict-ssl': true, - tag: 'latest', - 'tag-version-prefix': 'v', - timing: false, - tmp: temp, - unicode: hasUnicode(), - 'unsafe-perm': process.platform === 'win32' || - process.platform === 'cygwin' || - !(process.getuid && process.setuid && - process.getgid && process.setgid) || - process.getuid() !== 0, - 'update-notifier': true, - usage: false, - user: (process.platform === 'win32' || os.type() === 'OS400') ? 0 : 'nobody', - userconfig: path.resolve(home, '.npmrc'), - umask: process.umask ? process.umask() : umask.fromString('022'), - version: false, - versions: false, - viewer: process.platform === 'win32' ? 'browser' : 'man', - - _exit: true - } - - return defaults - } -}) - -exports.types = { - access: [null, 'restricted', 'public'], - all: Boolean, - 'allow-same-version': Boolean, - 'always-auth': Boolean, - also: [null, 'dev', 'development'], - audit: Boolean, - 'audit-level': ['low', 'moderate', 'high', 'critical', 'none', null], - 'auth-type': ['legacy', 'sso', 'saml', 'oauth'], - before: [null, Date], - 'bin-links': Boolean, - browser: [null, Boolean, String], - ca: [null, String, Array], - cafile: path, - cache: path, - 'cache-lock-stale': Number, - 'cache-lock-retries': Number, - 'cache-lock-wait': Number, - 'cache-max': Number, - 'cache-min': Number, - cert: [null, String], - cidr: [null, String, Array], - color: ['always', Boolean], - call: String, - depth: Number, - description: Boolean, - dev: Boolean, - 'dry-run': Boolean, - editor: String, - 'engine-strict': Boolean, - force: Boolean, - fund: Boolean, - 'format-package-lock': Boolean, - 'fetch-retries': Number, - 'fetch-retry-factor': Number, - 'fetch-retry-mintimeout': Number, - 'fetch-retry-maxtimeout': Number, - git: String, - 'git-tag-version': Boolean, - 'commit-hooks': Boolean, - global: Boolean, - globalconfig: path, - 'global-style': Boolean, - group: [Number, String], - 'https-proxy': [null, url], - 'user-agent': String, - 'ham-it-up': Boolean, - heading: String, - 'if-present': Boolean, - include: [Array, 'prod', 'dev', 'optional', 'peer'], - 'include-staged': Boolean, - 'ignore-prepublish': Boolean, - 'ignore-scripts': Boolean, - 'init-module': path, - 'init-author-name': String, - 'init-author-email': String, - 'init-author-url': ['', url], - 'init-license': String, - 'init-version': semver, - json: Boolean, - key: [null, String], - 'legacy-bundling': Boolean, - 'legacy-peer-deps': Boolean, - link: Boolean, - 'local-address': getLocalAddresses(), - loglevel: ['silent', 'error', 'warn', 'notice', 'http', 'timing', 'info', 'verbose', 'silly'], - 'logs-max': Number, - long: Boolean, - maxsockets: Number, - message: String, - 'metrics-registry': [null, String], - 'node-options': [null, String], - 'node-version': [null, semver], - noproxy: [null, String, Array], - offline: Boolean, - omit: [Array, 'dev', 'optional', 'peer'], - only: [null, 'dev', 'development', 'prod', 'production'], - optional: Boolean, - otp: [null, String], - package: [String, Array], - 'package-lock': Boolean, - 'package-lock-only': Boolean, - parseable: Boolean, - 'prefer-offline': Boolean, - 'prefer-online': Boolean, - prefix: path, - preid: String, - production: Boolean, - progress: Boolean, - proxy: [null, false, url], // allow proxy to be disabled explicitly - 'read-only': Boolean, - 'rebuild-bundle': Boolean, - registry: [null, url], - rollback: Boolean, - save: Boolean, - 'save-bundle': Boolean, - 'save-dev': Boolean, - 'save-exact': Boolean, - 'save-optional': Boolean, - 'save-prefix': String, - 'save-prod': Boolean, - scope: String, - 'script-shell': [null, String], - 'scripts-prepend-node-path': [Boolean, 'auto', 'warn-only'], - searchopts: String, - searchexclude: [null, String], - searchlimit: Number, - searchstaleness: Number, - 'send-metrics': Boolean, - shell: String, - shrinkwrap: Boolean, - 'sign-git-commit': Boolean, - 'sign-git-tag': Boolean, - 'sso-poll-frequency': Number, - 'sso-type': [null, 'oauth', 'saml'], - 'strict-ssl': Boolean, - tag: String, - timing: Boolean, - tmp: path, - unicode: Boolean, - 'unsafe-perm': Boolean, - 'update-notifier': Boolean, - usage: Boolean, - user: [Number, String], - userconfig: path, - umask: Umask, - version: Boolean, - 'tag-version-prefix': String, - versions: Boolean, - viewer: String, - _exit: Boolean -} - -function getLocalAddresses () { - var interfaces - // #8094: some environments require elevated permissions to enumerate - // interfaces, and synchronously throw EPERM when run without - // elevated privileges - try { - interfaces = os.networkInterfaces() - } catch (e) { - interfaces = {} - } - - return Object.keys(interfaces).map( - nic => interfaces[nic].map(({ address }) => address) - ).reduce((curr, next) => curr.concat(next), []).concat(undefined) -} - -exports.shorthands = { - 'enjoy-by': ['--before'], - c: ['--call'], - s: ['--loglevel', 'silent'], - d: ['--loglevel', 'info'], - dd: ['--loglevel', 'verbose'], - ddd: ['--loglevel', 'silly'], - noreg: ['--no-registry'], - N: ['--no-registry'], - reg: ['--registry'], - 'no-reg': ['--no-registry'], - silent: ['--loglevel', 'silent'], - verbose: ['--loglevel', 'verbose'], - quiet: ['--loglevel', 'warn'], - q: ['--loglevel', 'warn'], - h: ['--usage'], - H: ['--usage'], - '?': ['--usage'], - help: ['--usage'], - v: ['--version'], - f: ['--force'], - desc: ['--description'], - 'no-desc': ['--no-description'], - local: ['--no-global'], - l: ['--long'], - m: ['--message'], - p: ['--parseable'], - porcelain: ['--parseable'], - readonly: ['--read-only'], - g: ['--global'], - S: ['--save'], - D: ['--save-dev'], - E: ['--save-exact'], - O: ['--save-optional'], - P: ['--save-prod'], - y: ['--yes'], - n: ['--no-yes'], - B: ['--save-bundle'], - C: ['--prefix'] -} diff --git a/lib/config/get-credentials-by-uri.js b/lib/config/get-credentials-by-uri.js deleted file mode 100644 index 21926c6865993..0000000000000 --- a/lib/config/get-credentials-by-uri.js +++ /dev/null @@ -1,78 +0,0 @@ -var assert = require('assert') - -var toNerfDart = require('./nerf-dart.js') - -module.exports = getCredentialsByURI - -function getCredentialsByURI (uri) { - assert(uri && typeof uri === 'string', 'registry URL is required') - var nerfed = toNerfDart(uri) - var defnerf = toNerfDart(this.get('registry')) - - // hidden class micro-optimization - var c = { - scope: nerfed, - token: undefined, - password: undefined, - username: undefined, - email: undefined, - auth: undefined, - alwaysAuth: undefined - } - - // used to override scope matching for tokens as well as legacy auth - if (this.get(nerfed + ':always-auth') !== undefined) { - var val = this.get(nerfed + ':always-auth') - c.alwaysAuth = val === 'false' ? false : !!val - } else if (this.get('always-auth') !== undefined) { - c.alwaysAuth = this.get('always-auth') - } - - if (this.get(nerfed + ':_authToken')) { - c.token = this.get(nerfed + ':_authToken') - // the bearer token is enough, don't confuse things - return c - } - - if (this.get(nerfed + ':-authtoken')) { - c.token = this.get(nerfed + ':-authtoken') - // the bearer token is enough, don't confuse things - return c - } - - // Handle the old-style _auth= style for the default - // registry, if set. - var authDef = this.get('_auth') - var userDef = this.get('username') - var passDef = this.get('_password') - if (authDef && !(userDef && passDef)) { - authDef = Buffer.from(authDef, 'base64').toString() - authDef = authDef.split(':') - userDef = authDef.shift() - passDef = authDef.join(':') - } - - if (this.get(nerfed + ':_password')) { - c.password = Buffer.from(this.get(nerfed + ':_password'), 'base64').toString('utf8') - } else if (nerfed === defnerf && passDef) { - c.password = passDef - } - - if (this.get(nerfed + ':username')) { - c.username = this.get(nerfed + ':username') - } else if (nerfed === defnerf && userDef) { - c.username = userDef - } - - if (this.get(nerfed + ':email')) { - c.email = this.get(nerfed + ':email') - } else if (this.get('email')) { - c.email = this.get('email') - } - - if (c.username && c.password) { - c.auth = Buffer.from(c.username + ':' + c.password).toString('base64') - } - - return c -} diff --git a/lib/config/load-cafile.js b/lib/config/load-cafile.js deleted file mode 100644 index de8f61625a6b1..0000000000000 --- a/lib/config/load-cafile.js +++ /dev/null @@ -1,32 +0,0 @@ -module.exports = loadCAFile - -var fs = require('fs') - -function loadCAFile (cafilePath, cb) { - if (!cafilePath) return process.nextTick(cb) - - fs.readFile(cafilePath, 'utf8', afterCARead.bind(this)) - - function afterCARead (er, cadata) { - if (er) { - // previous cafile no longer exists, so just continue on gracefully - if (er.code === 'ENOENT') return cb() - return cb(er) - } - - var delim = '-----END CERTIFICATE-----' - var output - - output = cadata - .split(delim) - .filter(function (xs) { - return !!xs.trim() - }) - .map(function (xs) { - return xs.trimLeft() + delim - }) - - this.set('ca', output) - cb(null) - } -} diff --git a/lib/config/load-prefix.js b/lib/config/load-prefix.js deleted file mode 100644 index fd80e76345159..0000000000000 --- a/lib/config/load-prefix.js +++ /dev/null @@ -1,53 +0,0 @@ -module.exports = loadPrefix - -var findPrefix = require('find-npm-prefix') -var path = require('path') - -function loadPrefix (cb) { - var cli = this.list[0] - - Object.defineProperty(this, 'prefix', - { - set: function (prefix) { - var g = this.get('global') - this[g ? 'globalPrefix' : 'localPrefix'] = prefix - }.bind(this), - get: function () { - var g = this.get('global') - return g ? this.globalPrefix : this.localPrefix - }.bind(this), - enumerable: true - }) - - Object.defineProperty(this, 'globalPrefix', - { - set: function (prefix) { - this.set('prefix', prefix) - }.bind(this), - get: function () { - return path.resolve(this.get('prefix')) - }.bind(this), - enumerable: true - }) - - var p - Object.defineProperty(this, 'localPrefix', - { - set: function (prefix) { p = prefix }, - get: function () { return p }, - enumerable: true - }) - - // try to guess at a good node_modules location. - // If we are *explicitly* given a prefix on the cli, then - // always use that. otherwise, infer local prefix from cwd. - if (Object.prototype.hasOwnProperty.call(cli, 'prefix')) { - p = path.resolve(cli.prefix) - process.nextTick(cb) - } else { - findPrefix(process.cwd()).then((found) => { - p = found - cb() - }, cb) - } -} diff --git a/lib/config/nerf-dart.js b/lib/config/nerf-dart.js deleted file mode 100644 index d6ae4aa2aa7e2..0000000000000 --- a/lib/config/nerf-dart.js +++ /dev/null @@ -1,18 +0,0 @@ -const { URL } = require('url') - -/** - * Maps a URL to an identifier. - * - * Name courtesy schiffertronix media LLC, a New Jersey corporation - * - * @param {String} uri The URL to be nerfed. - * - * @returns {String} A nerfed URL. - */ -module.exports = (url) => { - const parsed = new URL(url) - const from = `${parsed.protocol}//${parsed.host}${parsed.pathname}` - const rel = new URL('.', from) - const res = `//${rel.host}${rel.pathname}` - return res -} diff --git a/lib/config/set-credentials-by-uri.js b/lib/config/set-credentials-by-uri.js deleted file mode 100644 index 4723d561a8af6..0000000000000 --- a/lib/config/set-credentials-by-uri.js +++ /dev/null @@ -1,39 +0,0 @@ -var assert = require('assert') - -var toNerfDart = require('./nerf-dart.js') - -module.exports = setCredentialsByURI - -function setCredentialsByURI (uri, c) { - assert(uri && typeof uri === 'string', 'registry URL is required') - assert(c && typeof c === 'object', 'credentials are required') - - var nerfed = toNerfDart(uri) - - if (c.token) { - this.set(nerfed + ':_authToken', c.token, 'user') - this.del(nerfed + ':_password', 'user') - this.del(nerfed + ':username', 'user') - this.del(nerfed + ':email', 'user') - this.del(nerfed + ':always-auth', 'user') - } else if (c.username || c.password || c.email) { - assert(c.username, 'must include username') - assert(c.password, 'must include password') - assert(c.email, 'must include email address') - - this.del(nerfed + ':_authToken', 'user') - - var encoded = Buffer.from(c.password, 'utf8').toString('base64') - this.set(nerfed + ':_password', encoded, 'user') - this.set(nerfed + ':username', c.username, 'user') - this.set(nerfed + ':email', c.email, 'user') - - if (c.alwaysAuth !== undefined) { - this.set(nerfed + ':always-auth', c.alwaysAuth, 'user') - } else { - this.del(nerfed + ':always-auth', 'user') - } - } else { - throw new Error('No credentials to set.') - } -} diff --git a/lib/config/set-envs.js b/lib/config/set-envs.js deleted file mode 100644 index 2a513fc908887..0000000000000 --- a/lib/config/set-envs.js +++ /dev/null @@ -1,92 +0,0 @@ -// 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 - -// Return the env key if this is a thing that belongs in the env. -// Ie, if the key isn't a @scope, //nerf.dart, or _private, -// and the value is a string or array. Otherwise return false. -const envKey = (key, val) => { - return !/^[/@_]/.test(key) && - (typeof envVal(val) === 'string') && - `npm_config_${key.replace(/-/g, '_').toLowerCase()}` -} - -const envVal = val => Array.isArray(val) ? val.map(v => envVal(v)).join('\n\n') - : val === null || val === undefined || val === false ? '' - : typeof val === 'object' ? null - : String(val) - -const sameConfigValue = (def, val) => - !Array.isArray(val) || !Array.isArray(def) ? def === val - : sameArrayValue(def, val) - -const sameArrayValue = (def, val) => { - if (def.length !== val.length) { - return false - } - for (let i = 0; i < def.length; i++) { - /* istanbul ignore next - there are no array configs where the default - * is not an empty array, so this loop is a no-op, but it's the correct - * thing to do if we ever DO add a config like that. */ - if (def[i] !== val[i]) { - return false - } - } - return true -} - -const setEnv = (env, rawKey, rawVal) => { - const val = envVal(rawVal) - const key = envKey(rawKey, val) - if (key && val !== null) { - env[key] = val - } -} - -const setEnvs = (npm, env = process.env) => { - // This ensures that all npm config values that are not the defaults are - // shared appropriately with child processes, without false positives. - // - // if the key is the default value, - // if the environ is NOT the default value, - // set the environ - // else skip it, it's fine - // if the key is NOT the default value, - // if the env is setting it, then leave it (already set) - // otherwise, set the env - const { config: { list: [cliConf, envConf] } } = npm - const cliSet = new Set(Object.keys(cliConf)) - const envSet = new Set(Object.keys(envConf)) - const { defaults } = require('./defaults.js') - // the configs form a prototype chain, so we can for/in over cli to - // see all the current values, and hasOwnProperty to see if it's - // set therre. - for (const key in cliConf) { - if (sameConfigValue(defaults[key], cliConf[key])) { - if (!sameConfigValue(defaults[key], envConf[key])) { - // getting set back to the default in the cli config - setEnv(env, key, cliConf[key]) - } - } else { - // config is not the default - if (!(envSet.has(key) && !cliSet.has(key))) { - // was not set in the env, so we have to put it there - setEnv(env, key, cliConf[key]) - } - } - } - - // also set some other common ones. - env.npm_execpath = require.main.filename - env.npm_node_execpath = process.execPath - 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 (cliConf['node-options']) { - env.NODE_OPTIONS = cliConf['node-options'] - } -} - -module.exports = setEnvs diff --git a/lib/config/set-user.js b/lib/config/set-user.js deleted file mode 100644 index 8579a88634ee7..0000000000000 --- a/lib/config/set-user.js +++ /dev/null @@ -1,28 +0,0 @@ -module.exports = setUser - -const assert = require('assert') -const path = require('path') -const fs = require('fs') -const mkdirp = require('mkdirp-infer-owner') - -function setUser (cb) { - var defaultConf = this.root - assert(defaultConf !== Object.prototype) - - // If global, leave it as-is. - // If not global, then set the user to the owner of the prefix folder. - // Just set the default, so it can be overridden. - if (this.get('global')) return cb() - if (process.env.SUDO_UID) { - defaultConf.user = +(process.env.SUDO_UID) - return cb() - } - - const prefix = path.resolve(this.get('prefix')) - mkdirp(prefix).catch(cb).then(() => { - fs.stat(prefix, function (er, st) { - defaultConf.user = st && st.uid - return cb(er) - }) - }) -} diff --git a/test/lib/config/set-envs.js b/test/lib/config/set-envs.js deleted file mode 100644 index 869622c0f1686..0000000000000 --- a/test/lib/config/set-envs.js +++ /dev/null @@ -1,165 +0,0 @@ -const t = require('tap') -const setEnvs = require('../../../lib/config/set-envs.js') -const { defaults } = require('../../../lib/config/defaults.js') - -t.test('set envs that are not defaults and not already in env', t => { - const envConf = Object.create(defaults) - const cliConf = Object.create(envConf) - const npm = { - config: { - list: [cliConf, envConf] - } - } - const extras = { - npm_execpath: require.main.filename, - npm_node_execpath: process.execPath, - npm_command: undefined - } - const env = {} - setEnvs(npm, env) - t.strictSame(env, { ...extras }, 'no new environment vars to create') - envConf.call = 'me, maybe' - setEnvs(npm, env) - t.strictSame(env, { ...extras }, 'no new environment vars to create, already in env') - delete envConf.call - cliConf.call = 'me, maybe' - setEnvs(npm, env) - t.strictSame(env, { - ...extras, - npm_config_call: 'me, maybe' - }, 'set in env, because changed from default in cli') - envConf.call = 'me, maybe' - cliConf.call = '' - cliConf['node-options'] = 'some options for node' - setEnvs(npm, env) - t.strictSame(env, { - ...extras, - npm_config_call: '', - npm_config_node_options: 'some options for node', - NODE_OPTIONS: 'some options for node' - }, 'set in env, because changed from default in env, back to default in cli') - t.end() -}) - -t.test('set envs that are not defaults and not already in env, array style', t => { - const envConf = Object.create(defaults) - const cliConf = Object.create(envConf) - const npm = { - config: { - list: [cliConf, envConf] - } - } - const extras = { - npm_execpath: require.main.filename, - npm_node_execpath: process.execPath, - npm_command: undefined - } - const env = {} - setEnvs(npm, env) - t.strictSame(env, { ...extras }, 'no new environment vars to create') - envConf.omit = ['dev'] - setEnvs(npm, env) - t.strictSame(env, { ...extras }, 'no new environment vars to create, already in env') - delete envConf.omit - cliConf.omit = ['dev', 'optional'] - setEnvs(npm, env) - t.strictSame(env, { - ...extras, - npm_config_omit: 'dev\n\noptional' - }, 'set in env, because changed from default in cli') - envConf.omit = ['optional', 'peer'] - cliConf.omit = [] - setEnvs(npm, env) - t.strictSame(env, { - ...extras, - npm_config_omit: '' - }, 'set in env, because changed from default in env, back to default in cli') - t.end() -}) - -t.test('set envs that are not defaults and not already in env, boolean edition', t => { - const envConf = Object.create(defaults) - const cliConf = Object.create(envConf) - const npm = { - config: { - list: [cliConf, envConf] - } - } - const extras = { - npm_execpath: require.main.filename, - npm_node_execpath: process.execPath, - npm_command: undefined - } - const env = {} - setEnvs(npm, env) - t.strictSame(env, { ...extras }, 'no new environment vars to create') - envConf.audit = false - setEnvs(npm, env) - t.strictSame(env, { ...extras }, 'no new environment vars to create, already in env') - delete envConf.audit - cliConf.audit = false - cliConf.ignoreObjects = { - some: { object: 12345 } - } - setEnvs(npm, env) - t.strictSame(env, { - ...extras, - npm_config_audit: '' - }, 'set in env, because changed from default in cli') - envConf.audit = false - cliConf.audit = true - setEnvs(npm, env) - t.strictSame(env, { - ...extras, - npm_config_audit: 'true' - }, 'set in env, because changed from default in env, back to default in cli') - t.end() -}) - -t.test('default to process.env', t => { - const envConf = Object.create(defaults) - const cliConf = Object.create(envConf) - const npm = { - config: { - list: [cliConf, envConf] - } - } - const extras = { - npm_execpath: require.main.filename, - npm_node_execpath: process.execPath, - npm_command: undefined - } - const env = {} - const envDescriptor = Object.getOwnPropertyDescriptor(process, 'env') - Object.defineProperty(process, 'env', { - value: env, - configurable: true, - enumerable: true, - writable: true - }) - t.teardown(() => Object.defineProperty(process, env, envDescriptor)) - - setEnvs(npm) - t.strictSame(env, { ...extras }, 'no new environment vars to create') - envConf.audit = false - setEnvs(npm) - t.strictSame(env, { ...extras }, 'no new environment vars to create, already in env') - delete envConf.audit - cliConf.audit = false - cliConf.ignoreObjects = { - some: { object: 12345 } - } - setEnvs(npm) - t.strictSame(env, { - ...extras, - npm_config_audit: '' - }, 'set in env, because changed from default in cli') - envConf.audit = false - cliConf.audit = true - setEnvs(npm) - t.strictSame(env, { - ...extras, - npm_config_audit: 'true' - }, 'set in env, because changed from default in env, back to default in cli') - t.end() -})