diff --git a/packages/angular/cli/src/commands/update/schematic/npm.ts b/packages/angular/cli/src/commands/update/schematic/npm.ts index 1eb084c90a1b..b5ff584e0bd8 100644 --- a/packages/angular/cli/src/commands/update/schematic/npm.ts +++ b/packages/angular/cli/src/commands/update/schematic/npm.ts @@ -16,7 +16,9 @@ const lockfile = require('@yarnpkg/lockfile'); const ini = require('ini'); const pacote = require('pacote'); -type PackageManagerOptions = Record; +interface PackageManagerOptions extends Record { + forceAuth?: Record; +} const npmPackageJsonCache = new Map>>(); let npmrc: PackageManagerOptions; @@ -41,8 +43,8 @@ function readOptions( } const defaultConfigLocations = [ - path.join(globalPrefix, 'etc', baseFilename), - path.join(homedir(), dotFilename), + (!yarn && process.env.NPM_CONFIG_GLOBALCONFIG) || path.join(globalPrefix, 'etc', baseFilename), + (!yarn && process.env.NPM_CONFIG_USERCONFIG) || path.join(homedir(), dotFilename), ]; const projectConfigLocations: string[] = [path.join(cwd, dotFilename)]; @@ -67,47 +69,57 @@ function readOptions( // See: https://github.com/npm/npm-registry-fetch/blob/ebddbe78a5f67118c1f7af2e02c8a22bcaf9e850/index.js#L99-L126 const rcConfig: PackageManagerOptions = yarn ? lockfile.parse(data) : ini.parse(data); for (const [key, value] of Object.entries(rcConfig)) { + let substitutedValue = value; + + // Substitute any environment variable references. + if (typeof value === 'string') { + substitutedValue = value.replace(/\$\{([^\}]+)\}/, (_, name) => process.env[name] || ''); + } + switch (key) { + // Unless auth options are scope with the registry url it appears that npm-registry-fetch ignores them, + // even though they are documented. + // https://github.com/npm/npm-registry-fetch/blob/8954f61d8d703e5eb7f3d93c9b40488f8b1b62ac/README.md + // https://github.com/npm/npm-registry-fetch/blob/8954f61d8d703e5eb7f3d93c9b40488f8b1b62ac/auth.js#L45-L91 + case '_authToken': + case 'token': + case 'username': + case 'password': + case '_auth': + case 'auth': + options['forceAuth'] ??= {}; + options['forceAuth'][key] = substitutedValue; + break; case 'noproxy': case 'no-proxy': - options['noProxy'] = value; + options['noProxy'] = substitutedValue; break; case 'maxsockets': - options['maxSockets'] = value; + options['maxSockets'] = substitutedValue; break; case 'https-proxy': case 'proxy': - options['proxy'] = value; + options['proxy'] = substitutedValue; break; case 'strict-ssl': - options['strictSSL'] = value; + options['strictSSL'] = substitutedValue; break; case 'local-address': - options['localAddress'] = value; + options['localAddress'] = substitutedValue; break; case 'cafile': - if (typeof value === 'string') { - const cafile = path.resolve(path.dirname(location), value); + if (typeof substitutedValue === 'string') { + const cafile = path.resolve(path.dirname(location), substitutedValue); try { options['ca'] = readFileSync(cafile, 'utf8').replace(/\r?\n/g, '\n'); } catch {} } break; default: - options[key] = value; + options[key] = substitutedValue; break; } } - } else if (showPotentials) { - logger.info(`Trying '${location}'...not found.`); - } - } - - // Substitute any environment variable references - for (const key in options) { - const value = options[key]; - if (typeof value === 'string') { - options[key] = value.replace(/\$\{([^\}]+)\}/, (_, name) => process.env[name] || ''); } } diff --git a/packages/angular/cli/utilities/package-metadata.ts b/packages/angular/cli/utilities/package-metadata.ts index 129cca59d6db..7eb303e1c52e 100644 --- a/packages/angular/cli/utilities/package-metadata.ts +++ b/packages/angular/cli/utilities/package-metadata.ts @@ -58,7 +58,9 @@ export interface PackageMetadata { 'dist-tags'?: unknown; } -type PackageManagerOptions = Record; +interface PackageManagerOptions extends Record { + forceAuth?: Record; +} let npmrc: PackageManagerOptions; @@ -122,47 +124,57 @@ function readOptions( // See: https://github.com/npm/npm-registry-fetch/blob/ebddbe78a5f67118c1f7af2e02c8a22bcaf9e850/index.js#L99-L126 const rcConfig: PackageManagerOptions = yarn ? lockfile.parse(data) : ini.parse(data); for (const [key, value] of Object.entries(rcConfig)) { + let substitutedValue = value; + + // Substitute any environment variable references. + if (typeof value === 'string') { + substitutedValue = value.replace(/\$\{([^\}]+)\}/, (_, name) => process.env[name] || ''); + } + switch (key) { + // Unless auth options are scope with the registry url it appears that npm-registry-fetch ignores them, + // even though they are documented. + // https://github.com/npm/npm-registry-fetch/blob/8954f61d8d703e5eb7f3d93c9b40488f8b1b62ac/README.md + // https://github.com/npm/npm-registry-fetch/blob/8954f61d8d703e5eb7f3d93c9b40488f8b1b62ac/auth.js#L45-L91 + case '_authToken': + case 'token': + case 'username': + case 'password': + case '_auth': + case 'auth': + options['forceAuth'] ??= {}; + options['forceAuth'][key] = substitutedValue; + break; case 'noproxy': case 'no-proxy': - options['noProxy'] = value; + options['noProxy'] = substitutedValue; break; case 'maxsockets': - options['maxSockets'] = value; + options['maxSockets'] = substitutedValue; break; case 'https-proxy': case 'proxy': - options['proxy'] = value; + options['proxy'] = substitutedValue; break; case 'strict-ssl': - options['strictSSL'] = value; + options['strictSSL'] = substitutedValue; break; case 'local-address': - options['localAddress'] = value; + options['localAddress'] = substitutedValue; break; case 'cafile': - if (typeof value === 'string') { - const cafile = path.resolve(path.dirname(location), value); + if (typeof substitutedValue === 'string') { + const cafile = path.resolve(path.dirname(location), substitutedValue); try { options['ca'] = readFileSync(cafile, 'utf8').replace(/\r?\n/g, '\n'); } catch {} } break; default: - options[key] = value; + options[key] = substitutedValue; break; } } - } else if (showPotentials) { - logger.info(`Trying '${location}'...not found.`); - } - } - - // Substitute any environment variable references - for (const key in options) { - const value = options[key]; - if (typeof value === 'string') { - options[key] = value.replace(/\$\{([^\}]+)\}/, (_, name) => process.env[name] || ''); } }