fix: resolving peer deps with prerelease versions (#7981)

close #7977
This commit is contained in:
Zoltan Kochan
2024-04-21 14:31:58 +02:00
committed by GitHub
parent e9530a8ff7
commit abaf12e8cf
4 changed files with 51 additions and 17 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/resolve-dependencies": patch
"pnpm": patch
---
Resolve peer dependencies correctly, when they have prerelease versions [#7977](https://github.com/pnpm/pnpm/issues/7977).

View File

@@ -0,0 +1,29 @@
import { type PreferredVersions } from '@pnpm/resolver-base'
import semver from 'semver'
export function hoistPeers (
missingRequiredPeers: Array<[string, { range: string }]>,
opts: {
autoInstallPeers: boolean
allPreferredVersions?: PreferredVersions
}
): Record<string, string> {
const dependencies: Record<string, string> = {}
for (const [peerName, { range }] of missingRequiredPeers) {
if (opts.allPreferredVersions![peerName]) {
const versions: string[] = []
const nonVersions: string[] = []
for (const [spec, specType] of Object.entries(opts.allPreferredVersions![peerName])) {
if (specType === 'version') {
versions.push(spec)
} else {
nonVersions.push(spec)
}
}
dependencies[peerName] = [semver.maxSatisfying(versions, '*', { includePrerelease: true }), ...nonVersions].join(' || ')
} else if (opts.autoInstallPeers) {
dependencies[peerName] = range
}
}
return dependencies
}

View File

@@ -57,6 +57,7 @@ import {
nodeIdContains,
splitNodeId,
} from './nodeIdUtils'
import { hoistPeers } from './hoistPeers'
import { wantedDepIsLocallyAvailable } from './wantedDepIsLocallyAvailable'
import { replaceVersionInPref } from './replaceVersionInPref'
@@ -329,23 +330,7 @@ export async function resolveRootDependencies (
)
)
if (!missingRequiredPeers.length && !missingOptionalPeerNames.length) break
const dependencies: Record<string, string> = {}
for (const [peerName, { range }] of missingRequiredPeers) {
if (ctx.allPreferredVersions![peerName]) {
const versions: string[] = []
const nonVersions: string[] = []
for (const [spec, specType] of Object.entries(ctx.allPreferredVersions![peerName])) {
if (specType === 'version') {
versions.push(spec)
} else {
nonVersions.push(spec)
}
}
dependencies[peerName] = [semver.maxSatisfying(versions, '*'), ...nonVersions].join(' || ')
} else if (ctx.autoInstallPeers) {
dependencies[peerName] = range
}
}
const dependencies = hoistPeers(missingRequiredPeers, ctx)
const nextMissingOptionalPeers: string[] = []
const optionalDependencies: Record<string, string> = {}
for (const missingOptionalPeerName of missingOptionalPeerNames) {

View File

@@ -0,0 +1,14 @@
import { hoistPeers } from '../lib/hoistPeers'
test('hoistPeers picks an already available prerelease version', () => {
expect(hoistPeers([['foo', { range: '*' }]], {
autoInstallPeers: false,
allPreferredVersions: {
foo: {
'1.0.0-beta.0': 'version',
},
},
})).toStrictEqual({
foo: '1.0.0-beta.0',
})
})