diff --git a/.changeset/breezy-geese-end.md b/.changeset/breezy-geese-end.md new file mode 100644 index 0000000000..3a5b162c8a --- /dev/null +++ b/.changeset/breezy-geese-end.md @@ -0,0 +1,6 @@ +--- +"@pnpm/lockfile-utils": patch +"pnpm": patch +--- + +pnpm should not consider a lockfile out-of-date if `auto-install-peers` is set to `true` and the peer dependency is in `devDependencies` or `optionalDependencies` [#5080](https://github.com/pnpm/pnpm/issues/5080). diff --git a/packages/lockfile-utils/src/satisfiesPackageManifest.ts b/packages/lockfile-utils/src/satisfiesPackageManifest.ts index 4da7ad6df1..1ad1ebc326 100644 --- a/packages/lockfile-utils/src/satisfiesPackageManifest.ts +++ b/packages/lockfile-utils/src/satisfiesPackageManifest.ts @@ -4,23 +4,24 @@ import { ProjectManifest, } from '@pnpm/types' import equals from 'ramda/src/equals.js' +import omit from 'ramda/src/omit.js' export default (lockfile: Lockfile, pkg: ProjectManifest, importerId: string, opts?: { autoInstallPeers?: boolean }) => { const importer = lockfile.importers[importerId] if (!importer) return false let existingDeps = { ...pkg.devDependencies, ...pkg.dependencies, ...pkg.optionalDependencies } if (opts?.autoInstallPeers) { - existingDeps = { - ...pkg.peerDependencies, - ...existingDeps, - } pkg = { ...pkg, dependencies: { - ...pkg.peerDependencies, + ...omit(Object.keys(existingDeps), pkg.peerDependencies), ...pkg.dependencies, }, } + existingDeps = { + ...pkg.peerDependencies, + ...existingDeps, + } } if ( !equals(existingDeps, importer.specifiers) || diff --git a/packages/lockfile-utils/test/satisfiesPackageManifest.ts b/packages/lockfile-utils/test/satisfiesPackageManifest.ts index 45cca67fba..59d365e488 100644 --- a/packages/lockfile-utils/test/satisfiesPackageManifest.ts +++ b/packages/lockfile-utils/test/satisfiesPackageManifest.ts @@ -284,6 +284,36 @@ test('satisfiesPackageManifest()', () => { }, }, '.', { autoInstallPeers: true })).toBe(true) + expect(satisfiesPackageManifest({ + ...DEFAULT_LOCKFILE_FIELDS, + importers: { + '.': { + optionalDependencies: { + bar: '1.0.0', + }, + devDependencies: { + foo: '1.0.0', + }, + specifiers: { + foo: '1.0.0', + bar: '1.0.0', + }, + }, + }, + }, { + ...DEFAULT_PKG_FIELDS, + optionalDependencies: { + bar: '1.0.0', + }, + devDependencies: { + foo: '1.0.0', + }, + peerDependencies: { + foo: '^1.0.0', + bar: '^1.0.0', + }, + }, '.', { autoInstallPeers: true })).toBe(true) + expect(satisfiesPackageManifest({ ...DEFAULT_LOCKFILE_FIELDS, importers: {