From 5fcfbd211f2efc19ad7e62ba90e193be974711f2 Mon Sep 17 00:00:00 2001 From: nlf Date: Sat, 26 Jun 2021 08:55:17 -0700 Subject: [PATCH] feat: introduce 'location' parameter for npm config command --- docs/content/commands/npm-config.md | 8 ++++++ docs/content/using-npm/config.md | 9 +++++++ lib/config.js | 8 +++--- lib/utils/config/definitions.js | 25 ++++++++++++++++++ tap-snapshots/test/lib/config.js.test.cjs | 10 +++---- .../test/lib/load-all-commands.js.test.cjs | 3 ++- .../lib/utils/config/definitions.js.test.cjs | 11 ++++++++ .../lib/utils/config/describe-all.js.test.cjs | 8 ++++++ .../test/lib/utils/config/index.js.test.cjs | 3 +++ .../test/lib/utils/npm-usage.js.test.cjs | 3 ++- test/lib/config.js | 26 +++++++++---------- test/lib/utils/config/definitions.js | 23 ++++++++++++++++ 12 files changed, 113 insertions(+), 24 deletions(-) diff --git a/docs/content/commands/npm-config.md b/docs/content/commands/npm-config.md index f2868cb8909a..ac79e85c1658 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 1036895101fc..6d458c71403c 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 d1585f414dca..a56dd92ffbde 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 d540b0fc67e8..1bbad60fd4f8 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 84418ec2e816..b5acbb0af94c 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 3575783a644b..90dc07f84815 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 12df9ec89f6f..26d2065462cc 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 daa071b642e9..c6173e7fe1c5 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 1e5ca232452e..f1cba9264ee2 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 3987f6a732da..50bfeedfb602 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 6c04293137af..8a1e7d85e09a 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 8724f0e3bd3e..24ff888e2b17 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() +})