From fdd89a6fe2fb77c6d056ec5ecef40ceff7f1494e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Fri, 28 Jun 2024 13:48:39 +0200 Subject: [PATCH] fix(core): handle packageManager property with createPackageJson (#26726) This PR was originally authored by @stephenwade. It adds the `packageManager` property to the `createPackageJson` function that ensures the generated `package.json` uses the same package manager that was used when generating it. ## Current Behavior ## Expected Behavior ## Related Issue(s) Fixes # --------- Co-authored-by: Stephen Wade Co-authored-by: Stephen Wade --- .../package-json/create-package-json.spec.ts | 94 ++++++++++++++++++- .../js/package-json/create-package-json.ts | 19 +++- 2 files changed, 111 insertions(+), 2 deletions(-) diff --git a/packages/nx/src/plugins/js/package-json/create-package-json.spec.ts b/packages/nx/src/plugins/js/package-json/create-package-json.spec.ts index 8be7865752..fdd4514045 100644 --- a/packages/nx/src/plugins/js/package-json/create-package-json.spec.ts +++ b/packages/nx/src/plugins/js/package-json/create-package-json.spec.ts @@ -397,7 +397,7 @@ describe('createPackageJson', () => { }); }); - describe('parsing "package.json" versions', () => { + describe('parsing "package.json"', () => { const appDependencies = [ { source: 'app1', target: 'npm:@nx/devkit', type: 'static' }, { source: 'app1', target: 'npm:typescript', type: 'static' }, @@ -654,6 +654,98 @@ describe('createPackageJson', () => { }, }); }); + + it('should add packageManager if missing', () => { + spies.push( + jest.spyOn(fs, 'existsSync').mockImplementation((path) => { + if (path === 'libs/lib1/package.json') { + return true; + } + if (path === 'package.json') { + return true; + } + }) + ); + spies.push( + jest + .spyOn(fileutilsModule, 'readJsonFile') + .mockImplementation((path) => { + if (path === 'package.json') { + return { + ...rootPackageJson(), + packageManager: 'yarn', + }; + } + if (path === 'libs/lib1/package.json') { + return projectPackageJson(); + } + }) + ); + + expect( + createPackageJson('lib1', graph, { + root: '', + }) + ).toEqual({ + dependencies: { + random: '1.0.0', + typescript: '^4.8.4', + }, + name: 'other-name', + packageManager: 'yarn', + version: '1.2.3', + }); + }); + + it('should replace packageManager if not in sync with root and show warning', () => { + spies.push( + jest.spyOn(fs, 'existsSync').mockImplementation((path) => { + if (path === 'libs/lib1/package.json') { + return true; + } + if (path === 'package.json') { + return true; + } + }) + ); + const consoleWarnSpy = jest.spyOn(process.stdout, 'write'); + spies.push(consoleWarnSpy); + spies.push( + jest + .spyOn(fileutilsModule, 'readJsonFile') + .mockImplementation((path) => { + if (path === 'package.json') { + return { + ...rootPackageJson(), + packageManager: 'yarn@1.2', + }; + } + if (path === 'libs/lib1/package.json') { + return { + ...projectPackageJson(), + packageManager: 'yarn@4.3', + }; + } + }) + ); + + expect( + createPackageJson('lib1', graph, { + root: '', + }) + ).toEqual({ + dependencies: { + random: '1.0.0', + typescript: '^4.8.4', + }, + name: 'other-name', + packageManager: 'yarn@1.2', + version: '1.2.3', + }); + expect(JSON.stringify(consoleWarnSpy.mock.calls)).toMatch( + /Package Manager Mismatch/ + ); + }); }); }); diff --git a/packages/nx/src/plugins/js/package-json/create-package-json.ts b/packages/nx/src/plugins/js/package-json/create-package-json.ts index 297f673b46..78d40fe206 100644 --- a/packages/nx/src/plugins/js/package-json/create-package-json.ts +++ b/packages/nx/src/plugins/js/package-json/create-package-json.ts @@ -16,6 +16,7 @@ import { filterUsingGlobPatterns, getTargetInputs, } from '../../../hasher/task-hasher'; +import { output } from '../../../utils/output'; interface NpmDeps { readonly dependencies: Record; @@ -43,7 +44,7 @@ export function createPackageJson( const projectNode = graph.nodes[projectName]; const isLibrary = projectNode.type === 'lib'; - const rootPackageJson = readJsonFile( + const rootPackageJson: PackageJson = readJsonFile( join(options.root ?? workspaceRoot, 'package.json') ); @@ -180,6 +181,22 @@ export function createPackageJson( packageJson.peerDependenciesMeta ); + if (rootPackageJson.packageManager) { + if ( + packageJson.packageManager && + packageJson.packageManager !== rootPackageJson.packageManager + ) { + output.warn({ + title: 'Package Manager Mismatch', + bodyLines: [ + `The project ${projectName} has explicitly specified "packageManager" config of "${packageJson.packageManager}" but the workspace is using "${rootPackageJson.packageManager}".`, + `Please remove the project level "packageManager" config or align it with the workspace root package.json.`, + ], + }); + } + packageJson.packageManager = rootPackageJson.packageManager; + } + return packageJson; }