Skip to content

Commit

Permalink
fix(core): prevent duplication of peerDependencyRules in the lockfile (
Browse files Browse the repository at this point in the history
…#4576)

If a workspace has a global peerDependencyRule that is applied by more
than one package, the lockfile could contain duplicate copies
of the patched range. For example react-dom might have
`peerDependencies: 17.0.2 | 17 | 17 | 17 | 17` in the lockfile.

This causes merge conflicts as package updates seem to regularly change
the number of duplicates, causing lockfile conflicts.

The fix checks if the same widened range has already been appended,
and ignores subsequent duplicates if they exist.
  • Loading branch information
kamsar committed Apr 15, 2022
1 parent b2d0031 commit 88289a4
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/mighty-papayas-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@pnpm/core": patch
---

peerDependencyRules will no longer cause duplicated peer dependency rules in the lockfile when used in workspaces
15 changes: 14 additions & 1 deletion packages/core/src/install/createPeerDependencyPatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,23 @@ export default function (
if (peerDependencyRules.allowedVersions[peerName] === '*') {
pkg.peerDependencies![peerName] = '*'
} else {
pkg.peerDependencies![peerName] += ` || ${peerDependencyRules.allowedVersions[peerName]}`
const allowedVersions = parseVersions(peerDependencyRules.allowedVersions[peerName])
const currentVersions = parseVersions(pkg.peerDependencies![peerName])

allowedVersions.forEach(allowedVersion => {
if (!currentVersions.includes(allowedVersion)) {
currentVersions.push(allowedVersion)
}
})

pkg.peerDependencies![peerName] = currentVersions.join(' || ')
}
}
}
return pkg
}) as ReadPackageHook
}

function parseVersions (versions: string) {
return versions.split('||').map(v => v.trim())
}
36 changes: 36 additions & 0 deletions packages/core/test/install/createPeerDependencyPatcher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,39 @@ test('createPeerDependencyPatcher() extends peer ranges', () => {
baz: '*',
})
})

test('createPeerDependencyPatcher() does not create duplicate extended ranges', async () => {
const patcher = createPeerDependencyPatcher({
allowedVersions: {
foo: '1',
same: '12',
multi: '16',
mix: '1 || 2 || 3',
partialmatch: '1',
nopadding: '^17.0.1||18.x',
},
})
const patchedPkg = patcher({
peerDependencies: {
foo: '0',
same: '12',
multi: '16 || 17',
mix: '1 || 4',
partialmatch: '16 || 1.2.1',
nopadding: '15.0.1||16',
},
})
// double apply the same patch to the same package
// this can occur in a monorepo when several packages
// all try to apply the same patch
const patchedAgainPkg = patcher(await patchedPkg)
expect(patchedAgainPkg['peerDependencies']).toStrictEqual({
// the patch is applied only once (not 0 || 1 || 1)
foo: '0 || 1',
same: '12',
multi: '16 || 17',
mix: '1 || 4 || 2 || 3',
partialmatch: '16 || 1.2.1 || 1',
nopadding: '15.0.1 || 16 || ^17.0.1 || 18.x',
})
})

0 comments on commit 88289a4

Please sign in to comment.