From 4261c900087ecd615af9ae1f80a46dba3f13e687 Mon Sep 17 00:00:00 2001 From: Bodo Graumann Date: Mon, 21 Sep 2020 16:16:20 +0200 Subject: [PATCH] fix: respect scope when resolving package metadata This should fix the remaining issue reported in #5411. In particular, if the user configured a dedicated npm registry for a specific scope, this setting was previously disregarded by vue-cli. Thus it was impossible to use vue upgrade if the packages were not also published to the official npm registry. --- .../cli/lib/util/ProjectPackageManager.js | 48 ++++++++++++++----- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/packages/@vue/cli/lib/util/ProjectPackageManager.js b/packages/@vue/cli/lib/util/ProjectPackageManager.js index 2ab3877bf5..168065b994 100644 --- a/packages/@vue/cli/lib/util/ProjectPackageManager.js +++ b/packages/@vue/cli/lib/util/ProjectPackageManager.js @@ -85,9 +85,23 @@ function stripVersion (packageName) { return result[1] } +// extract the package scope from the full package name +// the result includes the initial @ character +function extractPackageScope (packageName) { + const scopedNameRegExp = /^(@[^\/]+)\/.*$/ + const result = packageName.match(scopedNameRegExp) + + if (!result) { + return undefined + } + + return result[1] +} + class PackageManager { constructor ({ context, forcePackageManager } = {}) { this.context = context || process.cwd() + this._registries = {} if (forcePackageManager) { this.bin = forcePackageManager @@ -146,9 +160,10 @@ class PackageManager { // Any command that implemented registry-related feature should support // `-r` / `--registry` option - async getRegistry () { - if (this._registry) { - return this._registry + async getRegistry (scope) { + const cacheKey = scope || '' + if (this._registries[cacheKey]) { + return this._registries[cacheKey] } const args = minimist(process.argv, { @@ -157,24 +172,30 @@ class PackageManager { } }) + let registry if (args.registry) { - this._registry = args.registry + registry = args.registry } else if (!process.env.VUE_CLI_TEST && await shouldUseTaobao(this.bin)) { - this._registry = registries.taobao + registry = registries.taobao } else { try { - this._registry = (await execa(this.bin, ['config', 'get', 'registry'])).stdout + if (scope) { + registry = (await execa(this.bin, ['config', 'get', scope + ':registry'])).stdout + } + if (!registry || registry === 'undefined') { + registry = (await execa(this.bin, ['config', 'get', 'registry'])).stdout + } } catch (e) { // Yarn 2 uses `npmRegistryServer` instead of `registry` - this._registry = (await execa(this.bin, ['config', 'get', 'npmRegistryServer'])).stdout + registry = (await execa(this.bin, ['config', 'get', 'npmRegistryServer'])).stdout } } - this._registry = stripAnsi(this._registry).trim() - return this._registry + this._registries[cacheKey] = stripAnsi(registry).trim() + return this._registries[cacheKey] } - async getAuthToken () { + async getAuthToken (scope) { // get npmrc (https://docs.npmjs.com/configuring-npm/npmrc.html#files) const possibleRcPaths = [ path.resolve(this.context, '.npmrc'), @@ -197,7 +218,7 @@ class PackageManager { } } - const registry = await this.getRegistry() + const registry = await this.getRegistry(scope) const registryWithoutProtocol = registry .replace(/https?:/, '') // remove leading protocol .replace(/([^/])$/, '$1/') // ensure ending with slash @@ -255,8 +276,9 @@ class PackageManager { // https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md async getMetadata (packageName, { full = false } = {}) { - const registry = await this.getRegistry() - const authToken = await this.getAuthToken() + const scope = extractPackageScope(packageName) + const registry = await this.getRegistry(scope) + const authToken = await this.getAuthToken(scope) const metadataKey = `${this.bin}-${registry}-${packageName}` let metadata = metadataCache.get(metadataKey)