mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-10 18:18:56 -04:00
fix(core): prevent duplication of peerDependencyRules in the lockfile (#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.
This commit is contained in:
5
.changeset/mighty-papayas-itch.md
Normal file
5
.changeset/mighty-papayas-itch.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/core": patch
|
||||
---
|
||||
|
||||
peerDependencyRules will no longer cause duplicated peer dependency rules in the lockfile when used in workspaces
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user