From 60dda1af51c9e8c611f268d929f885215d9f023b Mon Sep 17 00:00:00 2001 From: Jayden Park Date: Thu, 25 May 2023 01:30:45 +1000 Subject: [PATCH] fix(core): consistent pnpm lockfile v6 version parsing (#17135) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Miroslav Jonaš --- .../plugins/js/lock-file/pnpm-parser.spec.ts | 4 +-- .../src/plugins/js/lock-file/pnpm-parser.ts | 32 ++++++++++++------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/nx/src/plugins/js/lock-file/pnpm-parser.spec.ts b/packages/nx/src/plugins/js/lock-file/pnpm-parser.spec.ts index 258bd81de7af1..bce5b30b7dcd8 100644 --- a/packages/nx/src/plugins/js/lock-file/pnpm-parser.spec.ts +++ b/packages/nx/src/plugins/js/lock-file/pnpm-parser.spec.ts @@ -183,12 +183,12 @@ describe('pnpm LockFile utility', () => { // this is our pruned lock file structure const prunedGraph = pruneProjectGraph(graph, appPackageJson); expect(Object.keys(prunedGraph.externalNodes).length).toEqual( - 864 + 117 // peer cypress adds additional 117 deps + 864 + 119 // peer cypress adds additional 119 deps ); // this should not fail expect(() => - stringifyPnpmLockfile(prunedGraph, lockFile, appPackageJson) + stringifyPnpmLockfile(prunedGraph, appLockFile, appPackageJson) ).not.toThrow(); }); }); diff --git a/packages/nx/src/plugins/js/lock-file/pnpm-parser.ts b/packages/nx/src/plugins/js/lock-file/pnpm-parser.ts index d12cac03aa159..d2928f7a7aaeb 100644 --- a/packages/nx/src/plugins/js/lock-file/pnpm-parser.ts +++ b/packages/nx/src/plugins/js/lock-file/pnpm-parser.ts @@ -25,26 +25,27 @@ export function parsePnpmLockfile( builder: ProjectGraphBuilder ): void { const data = parseAndNormalizePnpmLockfile(lockFileContent); + const isV6 = isV6Lockfile(data); // we use key => node map to avoid duplicate work when parsing keys const keyMap = new Map(); - addNodes(data, builder, keyMap); - addDependencies(data, builder, keyMap); + + addNodes(data, builder, keyMap, isV6); + addDependencies(data, builder, keyMap, isV6); } function addNodes( data: Lockfile, builder: ProjectGraphBuilder, - keyMap: Map + keyMap: Map, + isV6: boolean ) { const nodes: Map> = new Map(); Object.entries(data.packages).forEach(([key, snapshot]) => { const packageName = findPackageName(key, snapshot, data); const rawVersion = findVersion(key, packageName); - const version = isV6Lockfile(data) - ? rawVersion.split('(')[0] - : rawVersion.split('_')[0]; + const version = parseBaseVersion(rawVersion, isV6); // we don't need to keep duplicates, we can just track the keys const existingNode = nodes.get(packageName)?.get(version); @@ -83,7 +84,7 @@ function addNodes( if (versionMap.size === 1) { hoistedNode = versionMap.values().next().value; } else { - const hoistedVersion = getHoistedVersion(hoistedDeps, packageName); + const hoistedVersion = getHoistedVersion(hoistedDeps, packageName, isV6); hoistedNode = versionMap.get(hoistedVersion); } if (hoistedNode) { @@ -98,7 +99,8 @@ function addNodes( function getHoistedVersion( hoistedDependencies: Record, - packageName: string + packageName: string, + isV6: boolean ): string { let version = getHoistedPackageVersion(packageName); @@ -107,7 +109,7 @@ function getHoistedVersion( k.startsWith(`/${packageName}/`) ); if (key) { - version = getVersion(key, packageName).split('_')[0]; + version = parseBaseVersion(getVersion(key, packageName), isV6); } else { // pnpm might not hoist every package // similarly those packages will not be available to be used via import @@ -121,7 +123,8 @@ function getHoistedVersion( function addDependencies( data: Lockfile, builder: ProjectGraphBuilder, - keyMap: Map + keyMap: Map, + isV6: boolean ) { Object.entries(data.packages).forEach(([key, snapshot]) => { const node = keyMap.get(key); @@ -129,7 +132,10 @@ function addDependencies( (section) => { if (section) { Object.entries(section).forEach(([name, versionRange]) => { - const version = findVersion(versionRange, name).split('_')[0]; + const version = parseBaseVersion( + findVersion(versionRange, name), + isV6 + ); const target = builder.graph.externalNodes[`npm:${name}@${version}`] || builder.graph.externalNodes[`npm:${name}`]; @@ -143,6 +149,10 @@ function addDependencies( }); } +function parseBaseVersion(rawVersion: string, isV6: boolean): string { + return isV6 ? rawVersion.split('(')[0] : rawVersion.split('_')[0]; +} + export function stringifyPnpmLockfile( graph: ProjectGraph, rootLockFileContent: string,