From 64956bcf3c6d5850cb31f2b2a3e12107da398b7b Mon Sep 17 00:00:00 2001 From: zxfan Date: Wed, 4 Dec 2024 20:40:13 +0800 Subject: [PATCH] Support fallback syntax in .npmrc file --- .../rush-lib/src/utilities/npmrcUtilities.ts | 77 ++++++++++++------- .../src/utilities/test/npmrcUtilities.test.ts | 19 +++++ 2 files changed, 70 insertions(+), 26 deletions(-) create mode 100644 libraries/rush-lib/src/utilities/test/npmrcUtilities.test.ts diff --git a/libraries/rush-lib/src/utilities/npmrcUtilities.ts b/libraries/rush-lib/src/utilities/npmrcUtilities.ts index e3bd9026e21..32915ae44a3 100644 --- a/libraries/rush-lib/src/utilities/npmrcUtilities.ts +++ b/libraries/rush-lib/src/utilities/npmrcUtilities.ts @@ -22,27 +22,7 @@ export interface ILogger { // create a global _combinedNpmrc for cache purpose const _combinedNpmrcMap: Map = new Map(); -function _trimNpmrcFile(options: { - sourceNpmrcPath: string; - linesToPrepend?: string[]; - linesToAppend?: string[]; -}): string { - const { sourceNpmrcPath, linesToPrepend, linesToAppend } = options; - const combinedNpmrcFromCache: string | undefined = _combinedNpmrcMap.get(sourceNpmrcPath); - if (combinedNpmrcFromCache !== undefined) { - return combinedNpmrcFromCache; - } - let npmrcFileLines: string[] = []; - if (linesToPrepend) { - npmrcFileLines.push(...linesToPrepend); - } - if (fs.existsSync(sourceNpmrcPath)) { - npmrcFileLines.push(...fs.readFileSync(sourceNpmrcPath).toString().split('\n')); - } - if (linesToAppend) { - npmrcFileLines.push(...linesToAppend); - } - npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim()); +export function trimNpmrcFileLines(npmrcFileLines: string[], env: NodeJS.ProcessEnv): string[] { const resultLines: string[] = []; // This finds environment variable tokens that look like "${VAR_NAME}" @@ -66,11 +46,30 @@ function _trimNpmrcFile(options: { const environmentVariables: string[] | null = line.match(expansionRegExp); if (environmentVariables) { for (const token of environmentVariables) { - // Remove the leading "${" and the trailing "}" from the token - const environmentVariableName: string = token.substring(2, token.length - 1); - - // Is the environment variable defined? - if (!process.env[environmentVariableName]) { + /** + * Remove the leading "${" and the trailing "}" from the token + * + * ${nameString} -> nameString + * ${nameString-fallbackString} -> name-fallbackString + * ${nameString:-fallbackString} -> name:-fallbackString + */ + const nameWithFallback: string = token.substring(2, token.length - 1); + + /** + * Get the environment variable name and fallback value. + * + * name fallback + * nameString -> nameString undefined + * nameString-fallbackString -> nameString fallbackString + * nameString:-fallbackString -> nameString fallbackString + */ + const matched: string[] | null = nameWithFallback.match(/([^:-]+)(:?)-(.+)/); + // matched: [originStr, variableName, colon, fallback] + const name: string = matched?.[1] ?? nameWithFallback; + const fallback: string | undefined = matched?.[3]; + + // Is the environment variable and fallback value defined. + if (!env[name] && !fallback) { // No, so trim this line lineShouldBeTrimmed = true; break; @@ -87,6 +86,32 @@ function _trimNpmrcFile(options: { resultLines.push(line); } } + return resultLines; +} + +function _trimNpmrcFile(options: { + sourceNpmrcPath: string; + linesToPrepend?: string[]; + linesToAppend?: string[]; +}): string { + const { sourceNpmrcPath, linesToPrepend, linesToAppend } = options; + const combinedNpmrcFromCache: string | undefined = _combinedNpmrcMap.get(sourceNpmrcPath); + if (combinedNpmrcFromCache !== undefined) { + return combinedNpmrcFromCache; + } + let npmrcFileLines: string[] = []; + if (linesToPrepend) { + npmrcFileLines.push(...linesToPrepend); + } + if (fs.existsSync(sourceNpmrcPath)) { + npmrcFileLines.push(...fs.readFileSync(sourceNpmrcPath).toString().split('\n')); + } + if (linesToAppend) { + npmrcFileLines.push(...linesToAppend); + } + npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim()); + + const resultLines: string[] = trimNpmrcFileLines(npmrcFileLines, process.env); const combinedNpmrc: string = resultLines.join('\n'); diff --git a/libraries/rush-lib/src/utilities/test/npmrcUtilities.test.ts b/libraries/rush-lib/src/utilities/test/npmrcUtilities.test.ts new file mode 100644 index 00000000000..e96dbf10efd --- /dev/null +++ b/libraries/rush-lib/src/utilities/test/npmrcUtilities.test.ts @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +import { trimNpmrcFileLines } from '../npmrcUtilities'; + +describe('npmrcUtilities', () => { + it(trimNpmrcFileLines.name, () => { + expect(trimNpmrcFileLines(['var1=${foo}'], {})).toEqual(['; MISSING ENVIRONMENT VARIABLE: var1=${foo}']); + expect(trimNpmrcFileLines(['var1=${foo}'], { foo: 'test' })).toEqual(['var1=${foo}']); + expect(trimNpmrcFileLines(['var1=${foo-fallback_value}'], {})).toEqual(['var1=${foo-fallback_value}']); + expect(trimNpmrcFileLines(['var1=${foo-fallback_value}'], { foo: 'test' })).toEqual([ + 'var1=${foo-fallback_value}' + ]); + expect(trimNpmrcFileLines(['var1=${foo:-fallback_value}'], {})).toEqual(['var1=${foo:-fallback_value}']); + expect(trimNpmrcFileLines(['var1=${foo:-fallback_value}'], { foo: 'test' })).toEqual([ + 'var1=${foo:-fallback_value}' + ]); + }); +});