Skip to content

Commit

Permalink
fix(core): consistent pnpm lockfile v6 version parsing (#17135)
Browse files Browse the repository at this point in the history
Co-authored-by: Miroslav Jonaš <[email protected]>
  • Loading branch information
halfbakedsneed and meeroslav authored May 24, 2023
1 parent fc38dc1 commit 60dda1a
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 13 deletions.
4 changes: 2 additions & 2 deletions packages/nx/src/plugins/js/lock-file/pnpm-parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
});
Expand Down
32 changes: 21 additions & 11 deletions packages/nx/src/plugins/js/lock-file/pnpm-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, ProjectGraphExternalNode>();
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<string, ProjectGraphExternalNode>
keyMap: Map<string, ProjectGraphExternalNode>,
isV6: boolean
) {
const nodes: Map<string, Map<string, ProjectGraphExternalNode>> = 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);
Expand Down Expand Up @@ -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) {
Expand All @@ -98,7 +99,8 @@ function addNodes(

function getHoistedVersion(
hoistedDependencies: Record<string, any>,
packageName: string
packageName: string,
isV6: boolean
): string {
let version = getHoistedPackageVersion(packageName);

Expand All @@ -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
Expand All @@ -121,15 +123,19 @@ function getHoistedVersion(
function addDependencies(
data: Lockfile,
builder: ProjectGraphBuilder,
keyMap: Map<string, ProjectGraphExternalNode>
keyMap: Map<string, ProjectGraphExternalNode>,
isV6: boolean
) {
Object.entries(data.packages).forEach(([key, snapshot]) => {
const node = keyMap.get(key);
[snapshot.dependencies, snapshot.optionalDependencies].forEach(
(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}`];
Expand All @@ -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,
Expand Down

0 comments on commit 60dda1a

Please sign in to comment.