diff --git a/docs/content/commands/npm-config.md b/docs/content/commands/npm-config.md index f2868cb8909a9..ac79e85c1658b 100644 --- a/docs/content/commands/npm-config.md +++ b/docs/content/commands/npm-config.md @@ -128,6 +128,14 @@ folder instead of the current working directory. See The command to run for `npm edit` and `npm config edit`. +#### `location` + +* Default: "user" unless `--global` is passed, which will also set this value + to "global" +* Type: "global", "user", or "project" + +When passed to `npm config` this refers to which config file to use. + #### `long` * Default: false diff --git a/docs/content/using-npm/config.md b/docs/content/using-npm/config.md index 1036895101fcc..6d458c71403c1 100644 --- a/docs/content/using-npm/config.md +++ b/docs/content/using-npm/config.md @@ -67,6 +67,7 @@ The following shorthands are parsed on the command-line: * `--desc`: `--description` * `-f`: `--force` * `-g`: `--global` +* `-L`: `--location` * `-d`: `--loglevel info` * `-s`: `--loglevel silent` * `--silent`: `--loglevel silent` @@ -753,6 +754,14 @@ Used with `npm ls`, limiting output to only those packages that are linked. The IP address of the local interface to use when making connections to the npm registry. Must be IPv4 in versions of Node prior to 0.12. +#### `location` + +* Default: "user" unless `--global` is passed, which will also set this value + to "global" +* Type: "global", "user", or "project" + +When passed to `npm config` this refers to which config file to use. + #### `loglevel` * Default: "notice" diff --git a/lib/config.js b/lib/config.js index d1585f414dca8..a56dd92ffbde6 100644 --- a/lib/config.js +++ b/lib/config.js @@ -56,6 +56,7 @@ class Config extends BaseCommand { 'json', 'global', 'editor', + 'location', 'long', ] } @@ -137,7 +138,7 @@ class Config extends BaseCommand { if (!args.length) throw this.usageError() - const where = this.npm.config.get('global') ? 'global' : 'user' + const where = this.npm.config.get('location') for (const [key, val] of Object.entries(keyValues(args))) { this.npm.log.info('config', 'set %j %j', key, val) this.npm.config.set(key, val || '', where) @@ -167,16 +168,15 @@ class Config extends BaseCommand { if (!keys.length) throw this.usageError() - const where = this.npm.config.get('global') ? 'global' : 'user' + const where = this.npm.config.get('location') for (const key of keys) this.npm.config.delete(key, where) await this.npm.config.save(where) } async edit () { - const global = this.npm.config.get('global') const e = this.npm.config.get('editor') - const where = global ? 'global' : 'user' + const where = this.npm.config.get('location') const file = this.npm.config.data.get(where).source // save first, just to make sure it's synced up diff --git a/lib/utils/config/definitions.js b/lib/utils/config/definitions.js index d540b0fc67e82..1bbad60fd4f87 100644 --- a/lib/utils/config/definitions.js +++ b/lib/utils/config/definitions.js @@ -1103,6 +1103,31 @@ define('local-address', { flatten, }) +define('location', { + default: 'user', + short: 'L', + type: [ + 'global', + 'user', + 'project', + ], + defaultDescription: ` + "user" unless \`--global\` is passed, which will also set this value to "global" + `, + description: ` + When passed to \`npm config\` this refers to which config file to use. + `, + // NOTE: the flattener here deliberately does not alter the value of global + // for now, this is to avoid inadvertently causing any breakage. the value of + // global, however, does modify this flag. + flatten (key, obj, flatOptions) { + // if global is set, we override ourselves + if (obj.global) + obj.location = 'global' + flatOptions.location = obj.location + }, +}) + define('loglevel', { default: 'notice', type: [ diff --git a/tap-snapshots/test/lib/config.js.test.cjs b/tap-snapshots/test/lib/config.js.test.cjs index 84418ec2e816d..b5acbb0af94c5 100644 --- a/tap-snapshots/test/lib/config.js.test.cjs +++ b/tap-snapshots/test/lib/config.js.test.cjs @@ -5,7 +5,7 @@ * Make sure to inspect the output below. Do not ignore changes! */ 'use strict' -exports[`test/lib/config.js TAP config edit --global > should write global config file 1`] = ` +exports[`test/lib/config.js TAP config edit --location=global > should write global config file 1`] = ` ;;;; ; npm globalconfig file: /etc/npmrc ; this is a simple ini-formatted file @@ -92,8 +92,8 @@ cat = true chai = true dog = true editor = "vi" -global = false json = false +location = "user" long = false ; node bin location = /path/to/node @@ -116,8 +116,8 @@ cat = true chai = true dog = true editor = "vi" -global = false json = false +location = "user" long = true ` @@ -128,8 +128,8 @@ cat = true chai = true dog = true editor = "vi" -global = false json = false +location = "user" long = false ; node bin location = /path/to/node @@ -145,9 +145,9 @@ cat = true chai = true dog = true editor = "vi" -global = false init.author.name = "Bar" json = false +location = "user" long = false ; "user" config from ~/.npmrc diff --git a/tap-snapshots/test/lib/load-all-commands.js.test.cjs b/tap-snapshots/test/lib/load-all-commands.js.test.cjs index 3575783a644b2..90dc07f848155 100644 --- a/tap-snapshots/test/lib/load-all-commands.js.test.cjs +++ b/tap-snapshots/test/lib/load-all-commands.js.test.cjs @@ -151,7 +151,8 @@ npm config list [--json] npm config edit Options: -[--json] [-g|--global] [--editor ] [-l|--long] +[--json] [-g|--global] [--editor ] [-L|--location ] +[-l|--long] alias: c diff --git a/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs b/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs index 12df9ec89f6f7..26d2065462cc1 100644 --- a/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs +++ b/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs @@ -81,6 +81,7 @@ Array [ "legacy-peer-deps", "link", "local-address", + "location", "loglevel", "logs-max", "long", @@ -1019,6 +1020,16 @@ The IP address of the local interface to use when making connections to the npm registry. Must be IPv4 in versions of Node prior to 0.12. ` +exports[`test/lib/utils/config/definitions.js TAP > config description for location 1`] = ` +#### \`location\` + +* Default: "user" unless \`--global\` is passed, which will also set this value + to "global" +* Type: "global", "user", or "project" + +When passed to \`npm config\` this refers to which config file to use. +` + exports[`test/lib/utils/config/definitions.js TAP > config description for loglevel 1`] = ` #### \`loglevel\` diff --git a/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs b/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs index daa071b642e94..c6173e7fe1c55 100644 --- a/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs +++ b/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs @@ -632,6 +632,14 @@ Used with \`npm ls\`, limiting output to only those packages that are linked. The IP address of the local interface to use when making connections to the npm registry. Must be IPv4 in versions of Node prior to 0.12. +#### \`location\` + +* Default: "user" unless \`--global\` is passed, which will also set this value + to "global" +* Type: "global", "user", or "project" + +When passed to \`npm config\` this refers to which config file to use. + #### \`loglevel\` * Default: "notice" diff --git a/tap-snapshots/test/lib/utils/config/index.js.test.cjs b/tap-snapshots/test/lib/utils/config/index.js.test.cjs index 1e5ca232452e0..f1cba9264ee2f 100644 --- a/tap-snapshots/test/lib/utils/config/index.js.test.cjs +++ b/tap-snapshots/test/lib/utils/config/index.js.test.cjs @@ -64,6 +64,9 @@ Object { "l": Array [ "--long", ], + "L": Array [ + "--location", + ], "local": Array [ "--no-global", ], diff --git a/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs b/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs index 3987f6a732da5..50bfeedfb6021 100644 --- a/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs +++ b/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs @@ -294,7 +294,8 @@ All commands: npm config edit Options: - [--json] [-g|--global] [--editor ] [-l|--long] + [--json] [-g|--global] [--editor ] [-L|--location ] + [-l|--long] alias: c diff --git a/test/lib/config.js b/test/lib/config.js index 6c04293137af9..8a1e7d85e09aa 100644 --- a/test/lib/config.js +++ b/test/lib/config.js @@ -47,8 +47,8 @@ const defaults = { const cliConfig = { editor: 'vi', json: false, + location: 'user', long: false, - global: false, cat: true, chai: true, dog: true, @@ -198,8 +198,8 @@ t.test('config list --json', t => { { editor: 'vi', json: true, + location: 'user', long: false, - global: false, cat: true, chai: true, dog: true, @@ -265,7 +265,7 @@ t.test('config delete multiple key', t => { }) }) -t.test('config delete key --global', t => { +t.test('config delete key --location=global', t => { t.plan(4) npm.config.delete = (key, where) => { @@ -277,13 +277,13 @@ t.test('config delete key --global', t => { t.equal(where, 'global', 'should save global config post-delete') } - cliConfig.global = true + cliConfig.location = 'global' config.exec(['delete', 'foo'], (err) => { - t.error(err, 'npm config delete key --global') + t.error(err, 'npm config delete key --location=global') }) t.teardown(() => { - cliConfig.global = false + cliConfig.location = 'user' delete npm.config.delete delete npm.config.save }) @@ -419,7 +419,7 @@ t.test('config set invalid key', t => { }) }) -t.test('config set key --global', t => { +t.test('config set key --location=global', t => { t.plan(5) npm.config.set = (key, val, where) => { @@ -432,13 +432,13 @@ t.test('config set key --global', t => { t.equal(where, 'global', 'should save global config') } - cliConfig.global = true + cliConfig.location = 'global' config.exec(['set', 'foo', 'bar'], (err) => { - t.error(err, 'npm config set key --global') + t.error(err, 'npm config set key --location=global') }) t.teardown(() => { - cliConfig.global = false + cliConfig.location = 'user' delete npm.config.set delete npm.config.save }) @@ -583,10 +583,10 @@ sign-git-commit=true` }) }) -t.test('config edit --global', t => { +t.test('config edit --location=global', t => { t.plan(6) - cliConfig.global = true + cliConfig.location = 'global' const npmrc = 'init.author.name=Foo' npm.config.data.set('global', { source: '/etc/npmrc', @@ -626,7 +626,7 @@ t.test('config edit --global', t => { }) t.teardown(() => { - cliConfig.global = false + cliConfig.location = 'user' npm.config.data.delete('user') delete npm.config.save }) diff --git a/test/lib/utils/config/definitions.js b/test/lib/utils/config/definitions.js index 8724f0e3bd3eb..24ff888e2b17b 100644 --- a/test/lib/utils/config/definitions.js +++ b/test/lib/utils/config/definitions.js @@ -797,3 +797,26 @@ t.test('save-exact', t => { t.strictSame(flat, { savePrefix: '~1.2.3' }) t.end() }) + +t.test('location', t => { + const obj = { + global: true, + location: 'user', + } + const flat = {} + definitions.location.flatten('location', obj, flat) + // global = true sets location in both places to global + t.strictSame(flat, { location: 'global' }) + t.strictSame(obj, { global: true, location: 'global' }) + + obj.global = false + obj.location = 'user' + delete flat.global + delete flat.location + + definitions.location.flatten('location', obj, flat) + // global = false leaves location unaltered + t.strictSame(flat, { location: 'user' }) + t.strictSame(obj, { global: false, location: 'user' }) + t.end() +})