diff --git a/packages/devkit/nx.ts b/packages/devkit/nx.ts index 1eccb0723ea19e..9507d850769438 100644 --- a/packages/devkit/nx.ts +++ b/packages/devkit/nx.ts @@ -1,7 +1,20 @@ -export function requireNx(): typeof import('nx/src/devkit-exports') { +// After Nx v18, this can be removed and replaced with either: +// - import {} from 'nx/src/devkit-exports' +// - import {} from 'nx/src/devkit-internals' +export function requireNx(): typeof import('nx/src/devkit-exports') & + Partial { try { - return require('nx/src/devkit-exports'); + let result = { ...require('nx/src/devkit-exports') }; + try { + result = { + ...result, + // Remove in Nx v18, devkit should not support Nx v16.0.2 at that point. + ...require('nx/src/devkit-internals'), + }; + } catch {} + return result; } catch { + // Remove in Nx V17, devkit should not support Nx < 16 at that point. return require('./nx-reexports-pre16'); } } diff --git a/packages/devkit/src/utils/package-json.ts b/packages/devkit/src/utils/package-json.ts index b2726a34f96092..0c3f5880dd5d20 100644 --- a/packages/devkit/src/utils/package-json.ts +++ b/packages/devkit/src/utils/package-json.ts @@ -17,6 +17,7 @@ const { getPackageManagerCommand, workspaceRoot, detectPackageManager, + createTempNpmDirectory, } = requireNx(); const UNIDENTIFIED_VERSION = 'UNIDENTIFIED_VERSION'; @@ -450,7 +451,9 @@ export function ensurePackage( ); } - const tempDir = dirSync().name; + const { dir: tempDir } = createTempNpmDirectory?.() ?? { + dir: dirSync().name, + }; console.log(`Fetching ${pkg}...`); const packageManager = detectPackageManager(); diff --git a/packages/nx/src/devkit-internals.ts b/packages/nx/src/devkit-internals.ts new file mode 100644 index 00000000000000..fca393f59c319e --- /dev/null +++ b/packages/nx/src/devkit-internals.ts @@ -0,0 +1,6 @@ +/** + * Note to developers: STOP! These exports are available via requireNx in @nx/devkit. + * + * These may not be available in certain version of Nx, so be sure to check them first. + */ +export { createTempNpmDirectory } from './utils/package-manager'; diff --git a/packages/nx/src/utils/package-manager.ts b/packages/nx/src/utils/package-manager.ts index e613806e492021..a0e9c76a49fc40 100644 --- a/packages/nx/src/utils/package-manager.ts +++ b/packages/nx/src/utils/package-manager.ts @@ -7,6 +7,7 @@ import { promisify } from 'util'; import { writeJsonFile } from './fileutils'; import { readModulePackageJson } from './package-json'; import { gte, lt } from 'semver'; +import { workspaceRoot } from './workspace-root'; const execAsync = promisify(exec); @@ -118,16 +119,30 @@ export function getPackageManagerVersion( * Checks for a project level npmrc file by crawling up the file tree until * hitting a package.json file, as this is how npm finds them as well. */ -export function checkForNPMRC( +export function findFileInPackageJsonDirectory( + file: string, directory: string = process.cwd() ): string | null { while (!existsSync(join(directory, 'package.json'))) { directory = dirname(directory); } - const path = join(directory, '.npmrc'); + const path = join(directory, file); return existsSync(path) ? path : null; } +export function copyPackageManagerConfigurationFiles( + root: string, + destination: string +) { + for (const packageManagerConfigFile of ['.npmrc', '.yarnrc', '.yarnrc.yml']) { + const f = findFileInPackageJsonDirectory(packageManagerConfigFile, root); + if (f) { + // Copy config file if it exists, so that the package manager still follows it. + copyFileSync(f, `${destination}/.npmrc`); + } + } +} + /** * Creates a temporary directory where you can run package manager commands safely. * @@ -140,11 +155,7 @@ export function createTempNpmDirectory() { // A package.json is needed for pnpm pack and for .npmrc to resolve writeJsonFile(`${dir}/package.json`, {}); - const npmrc = checkForNPMRC(); - if (npmrc) { - // Copy npmrc if it exists, so that npm still follows it. - copyFileSync(npmrc, `${dir}/.npmrc`); - } + copyPackageManagerConfigurationFiles(workspaceRoot, dir); const cleanup = async () => { try {