From 8cce4282f7bef11aeeb73cffd532b477b241985e Mon Sep 17 00:00:00 2001 From: Kenrick Date: Mon, 15 Mar 2021 16:09:29 +0800 Subject: [PATCH] fix(publish): handle case where multiple config list is present When not handled, when there are multiple entries in this.npm.config.list, it causes crash as described in #2834 The change here merge everything in this.npm.config.list, because as I observed, the default config is present only at the last entry. Fix: #2834 Co-authored-by: @wraithgar PR-URL: https://github.com/npm/cli/pull/2865 Credit: @kenrick95 Close: #2865 Reviewed-by: @isaacs, @wraithgar --- lib/publish.js | 2 +- test/lib/publish.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/lib/publish.js b/lib/publish.js index f46f70291bebc..bfea1e139dbfc 100644 --- a/lib/publish.js +++ b/lib/publish.js @@ -141,7 +141,7 @@ class Publish extends BaseCommand { publishConfigToOpts (publishConfig) { // create a new object that inherits from the config stack // then squash the css-case into camelCase opts, like we do - return flatten({...this.npm.config.list[0], ...publishConfig}) + return flatten({...flatten(this.npm.config.list[0]), ...publishConfig}) } } module.exports = Publish diff --git a/test/lib/publish.js b/test/lib/publish.js index bfc58a4c36a06..d1a1cd630c0e6 100644 --- a/test/lib/publish.js +++ b/test/lib/publish.js @@ -473,3 +473,48 @@ t.test('read registry only from publishConfig', t => { t.end() }) }) + +t.test('able to publish after if encountered multiple configs', t => { + t.plan(3) + + const registry = 'https://some.registry' + const tag = 'better-tag' + const publishConfig = { registry } + const testDir = t.testdir({ + 'package.json': JSON.stringify({ + name: 'my-cool-pkg', + version: '1.0.0', + publishConfig, + }, null, 2), + }) + + const configList = [ + { ...defaults, tag }, + { ...defaults, registry: `https://other.registry`, tag: 'some-tag' }, + defaults, + ] + + const Publish = requireInject('../../lib/publish.js', { + libnpmpublish: { + publish: (manifest, tarData, opts) => { + t.same(opts.defaultTag, tag, 'gets option for expected tag') + }, + }, + }) + const publish = new Publish({ + config: { + list: configList, + getCredentialsByURI: (uri) => { + t.same(uri, registry, 'gets credentials for expected registry') + return { token: 'some.registry.token' } + }, + }, + }) + + publish.exec([testDir], (er) => { + if (er) + throw er + t.pass('got to callback') + t.end() + }) +})