From 70753712c9d66a07133980ef798e4bff7e1cf277 Mon Sep 17 00:00:00 2001 From: Michael Peto <16761176+petomi@users.noreply.github.com> Date: Fri, 12 Jan 2024 10:56:56 -0500 Subject: [PATCH] fix(@angular/cli): fixes Yarn v2 support for registry configuration Adds support for yarnrc.yml files so that users of Yarn v2+ who attempt to run `ng add` or `ng update` do not experience a bug where the incorrect registry file extension (.yarnrc) is selected. Fixes #23448 --- packages/angular/cli/src/commands/add/cli.ts | 7 ++- .../angular/cli/src/commands/update/cli.ts | 11 ++++- .../cli/src/utilities/package-metadata.ts | 49 +++++++++++++++---- 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/packages/angular/cli/src/commands/add/cli.ts b/packages/angular/cli/src/commands/add/cli.ts index dc3de137a0d5..9134041da2f4 100644 --- a/packages/angular/cli/src/commands/add/cli.ts +++ b/packages/angular/cli/src/commands/add/cli.ts @@ -141,7 +141,10 @@ export default class AddCommandModule spinner.start('Determining package manager...'); const usingYarn = packageManager.name === PackageManager.Yarn; - spinner.info(`Using package manager: ${colors.grey(packageManager.name)}`); + const packageManagerVersion = packageManager.version; + spinner.info( + `Using package manager: ${colors.grey(packageManager.name)} ${packageManagerVersion}`, + ); if ( packageIdentifier.name && @@ -155,6 +158,7 @@ export default class AddCommandModule let packageMetadata; try { packageMetadata = await fetchPackageMetadata(packageIdentifier.name, logger, { + packageManagerVersion, registry, usingYarn, verbose, @@ -241,6 +245,7 @@ export default class AddCommandModule try { spinner.start('Loading package information from registry...'); const manifest = await fetchPackageManifest(packageIdentifier.toString(), logger, { + packageManagerVersion, registry, verbose, usingYarn, diff --git a/packages/angular/cli/src/commands/update/cli.ts b/packages/angular/cli/src/commands/update/cli.ts index fe262dbf968d..82c83ea3b4f2 100644 --- a/packages/angular/cli/src/commands/update/cli.ts +++ b/packages/angular/cli/src/commands/update/cli.ts @@ -601,7 +601,8 @@ export default class UpdateCommandModule extends CommandModule, packages: PackageIdentifier[], ): Promise { - const { logger } = this.context; + const { logger, packageManager } = this.context; + packageManager.ensureCompatibility(); const logVerbose = (message: string) => { if (options.verbose) { @@ -609,6 +610,12 @@ export default class UpdateCommandModule extends CommandModule; @@ -58,7 +59,12 @@ interface PackageManagerOptions extends Record { let npmrc: PackageManagerOptions; const npmPackageJsonCache = new Map>>(); -function ensureNpmrc(logger: logging.LoggerApi, usingYarn: boolean, verbose: boolean): void { +function ensureNpmrc( + logger: logging.LoggerApi, + usingYarn: boolean, + verbose: boolean, + packageManagerVersion?: string, +): void { if (!npmrc) { try { npmrc = readOptions(logger, false, verbose); @@ -66,7 +72,7 @@ function ensureNpmrc(logger: logging.LoggerApi, usingYarn: boolean, verbose: boo if (usingYarn) { try { - npmrc = { ...npmrc, ...readOptions(logger, true, verbose) }; + npmrc = { ...npmrc, ...readOptions(logger, true, verbose, packageManagerVersion) }; } catch {} } } @@ -76,9 +82,20 @@ function readOptions( logger: logging.LoggerApi, yarn = false, showPotentials = false, + packageManagerVersion?: string, ): PackageManagerOptions { const cwd = process.cwd(); - const baseFilename = yarn ? 'yarnrc' : 'npmrc'; + let baseFilename: string; + if (yarn) { + // adds support for the yarnrc.yml format used by yarn v2+ + if (packageManagerVersion != null && semver.gt(packageManagerVersion, '2.0.0')) { + baseFilename = 'yarnrc.yml'; + } else { + baseFilename = 'yarnrc'; + } + } else { + baseFilename = 'npmrc'; + } const dotFilename = '.' + baseFilename; let globalPrefix: string; @@ -229,19 +246,21 @@ export async function fetchPackageMetadata( name: string, logger: logging.LoggerApi, options?: { + packageManagerVersion?: string; registry?: string; usingYarn?: boolean; verbose?: boolean; }, ): Promise { - const { usingYarn, verbose, registry } = { + const { packageManagerVersion, usingYarn, verbose, registry } = { + packageManagerVersion: undefined, registry: undefined, usingYarn: false, verbose: false, ...options, }; - ensureNpmrc(logger, usingYarn, verbose); + ensureNpmrc(logger, usingYarn, verbose, packageManagerVersion); const { packument } = await import('pacote'); const response = await packument(name, { fullMetadata: true, @@ -278,13 +297,19 @@ export async function fetchPackageManifest( name: string, logger: logging.LoggerApi, options: { + packageManagerVersion?: string; registry?: string; usingYarn?: boolean; verbose?: boolean; } = {}, ): Promise { - const { usingYarn = false, verbose = false, registry } = options; - ensureNpmrc(logger, usingYarn, verbose); + const { + packageManagerVersion = undefined, + usingYarn = false, + verbose = false, + registry, + } = options; + ensureNpmrc(logger, usingYarn, verbose, packageManagerVersion); const { manifest } = await import('pacote'); const response = await manifest(name, { @@ -300,6 +325,7 @@ export async function getNpmPackageJson( packageName: string, logger: logging.LoggerApi, options: { + packageManagerVersion?: string; registry?: string; usingYarn?: boolean; verbose?: boolean; @@ -310,8 +336,13 @@ export async function getNpmPackageJson( return cachedResponse; } - const { usingYarn = false, verbose = false, registry } = options; - ensureNpmrc(logger, usingYarn, verbose); + const { + packageManagerVersion = undefined, + usingYarn = false, + verbose = false, + registry, + } = options; + ensureNpmrc(logger, usingYarn, verbose, packageManagerVersion); const { packument } = await import('pacote'); const response = packument(packageName, { fullMetadata: true,