refactor: rename peersSuffix to peerDepGraphHash (#9656)

This commit is contained in:
Zoltan Kochan
2025-06-17 02:27:58 +02:00
committed by GitHub
parent 61e7b0391a
commit 540986f326
16 changed files with 80 additions and 73 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/dependency-path": major
"@pnpm/lockfile.utils": major
---
Peers suffix renamed to peerDepGraphHash.

View File

@@ -118,8 +118,8 @@ function pruneTimeInLockfile (time: Record<string, string>, importers: Record<st
for (const depType of DEPENDENCIES_FIELDS) {
for (const [depName, ref] of Object.entries(importer[depType] ?? {})) {
const suffixStart = ref.version.indexOf('(')
const refWithoutPeerSuffix = suffixStart === -1 ? ref.version : ref.version.slice(0, suffixStart)
const depPath = refToRelative(refWithoutPeerSuffix, depName)
const refWithoutPeerDepGraphHash = suffixStart === -1 ? ref.version : ref.version.slice(0, suffixStart)
const depPath = refToRelative(refWithoutPeerDepGraphHash, depName)
if (!depPath) continue
rootDepPaths.add(depPath)
}

View File

@@ -77,8 +77,8 @@ export function lockfileToPackageRegistry (
}
}
for (const [relDepPath, pkgSnapshot] of Object.entries(lockfile.packages ?? {})) {
const { name, version, peersSuffix } = nameVerFromPkgSnapshot(relDepPath, pkgSnapshot)
const pnpVersion = toPnPVersion(version, peersSuffix)
const { name, version, peerDepGraphHash } = nameVerFromPkgSnapshot(relDepPath, pkgSnapshot)
const pnpVersion = toPnPVersion(version, peerDepGraphHash)
let packageStore = packageRegistry.get(name)
if (!packageStore) {
packageStore = new Map()
@@ -121,8 +121,8 @@ function toPackageDependenciesMap (
}
const relDepPath = refToRelative(ref, depAlias)
if (!relDepPath) return [depAlias, ref]
const { name, version, peersSuffix } = nameVerFromPkgSnapshot(relDepPath, lockfile.packages![relDepPath])
const pnpVersion = toPnPVersion(version, peersSuffix)
const { name, version, peerDepGraphHash } = nameVerFromPkgSnapshot(relDepPath, lockfile.packages![relDepPath])
const pnpVersion = toPnPVersion(version, peerDepGraphHash)
if (depAlias === name) {
return [depAlias, pnpVersion]
}
@@ -130,8 +130,8 @@ function toPackageDependenciesMap (
})
}
function toPnPVersion (version: string, peersSuffix: string | undefined) {
return peersSuffix
? `virtual:${version}${peersSuffix}#${version}`
function toPnPVersion (version: string, peerDepGraphHash: string | undefined) {
return peerDepGraphHash
? `virtual:${version}${peerDepGraphHash}#${version}`
: version
}

View File

@@ -4,7 +4,7 @@ import { type PkgResolutionId } from '@pnpm/types'
export interface NameVer {
name: string
peersSuffix: string | undefined
peerDepGraphHash: string | undefined
version: string
nonSemverVersion?: PkgResolutionId
}
@@ -16,7 +16,7 @@ export function nameVerFromPkgSnapshot (
const pkgInfo = dp.parse(depPath)
return {
name: pkgInfo.name as string,
peersSuffix: pkgInfo.peersSuffix,
peerDepGraphHash: pkgInfo.peerDepGraphHash,
version: pkgSnapshot.version ?? pkgInfo.version as string,
nonSemverVersion: pkgInfo.nonSemverVersion,
}

View File

@@ -9,7 +9,7 @@ test('nameVerFromPkgSnapshot()', () => {
},
})).toEqual({
name: 'foo',
peersSuffix: undefined,
peerDepGraphHash: undefined,
version: '1.0.0',
nonSemverVersion: 'some-weird-path',
})
@@ -20,7 +20,7 @@ test('nameVerFromPkgSnapshot()', () => {
},
})).toEqual({
name: 'foo',
peersSuffix: undefined,
peerDepGraphHash: undefined,
version: '1.0.0',
})
@@ -30,7 +30,7 @@ test('nameVerFromPkgSnapshot()', () => {
},
})).toEqual({
name: 'foo',
peersSuffix: '(bar@2.0.0)',
peerDepGraphHash: '(bar@2.0.0)',
version: '1.0.0',
})
})

View File

@@ -6,7 +6,7 @@ export function isAbsolute (dependencyPath: string): boolean {
return dependencyPath[0] !== '/'
}
export function indexOfPeersSuffix (depPath: string): { peersIndex: number, patchHashIndex: number } {
export function indexOfDepPathSuffix (depPath: string): { peersIndex: number, patchHashIndex: number } {
if (!depPath.endsWith(')')) return { peersIndex: -1, patchHashIndex: -1 }
let open = 1
for (let i = depPath.length - 2; i >= 0; i--) {
@@ -32,25 +32,25 @@ export function indexOfPeersSuffix (depPath: string): { peersIndex: number, patc
export interface ParsedDepPath {
id: string
peersSuffix: string
peerDepGraphHash: string
}
export function parseDepPath (relDepPath: string): ParsedDepPath {
const { peersIndex } = indexOfPeersSuffix(relDepPath)
const { peersIndex } = indexOfDepPathSuffix(relDepPath)
if (peersIndex !== -1) {
return {
id: relDepPath.substring(0, peersIndex),
peersSuffix: relDepPath.substring(peersIndex),
peerDepGraphHash: relDepPath.substring(peersIndex),
}
}
return {
id: relDepPath,
peersSuffix: '',
peerDepGraphHash: '',
}
}
export function removeSuffix (relDepPath: string): string {
const { peersIndex, patchHashIndex } = indexOfPeersSuffix(relDepPath)
const { peersIndex, patchHashIndex } = indexOfDepPathSuffix(relDepPath)
if (patchHashIndex !== -1) {
return relDepPath.substring(0, patchHashIndex)
}
@@ -62,7 +62,7 @@ export function removeSuffix (relDepPath: string): string {
export function getPkgIdWithPatchHash (depPath: DepPath): PkgIdWithPatchHash {
let pkgId: string = depPath
const { peersIndex: sepIndex } = indexOfPeersSuffix(pkgId)
const { peersIndex: sepIndex } = indexOfDepPathSuffix(pkgId)
if (sepIndex !== -1) {
pkgId = pkgId.substring(0, sepIndex)
}
@@ -74,7 +74,7 @@ export function getPkgIdWithPatchHash (depPath: DepPath): PkgIdWithPatchHash {
export function tryGetPackageId (relDepPath: DepPath): PkgId {
let pkgId: string = relDepPath
const { peersIndex, patchHashIndex } = indexOfPeersSuffix(pkgId)
const { peersIndex, patchHashIndex } = indexOfDepPathSuffix(pkgId)
const sepIndex = patchHashIndex === -1 ? peersIndex : patchHashIndex
if (sepIndex !== -1) {
pkgId = pkgId.substring(0, sepIndex)
@@ -109,7 +109,7 @@ export function refToRelative (
export interface DependencyPath {
name?: string
peersSuffix?: string
peerDepGraphHash?: string
version?: string
nonSemverVersion?: PkgResolutionId
patchHash?: string
@@ -130,26 +130,26 @@ export function parse (dependencyPath: string): DependencyPath {
const name = dependencyPath.substring(0, sepIndex)
let version = dependencyPath.substring(sepIndex + 1)
if (version) {
let peersSuffix: string | undefined
let peerDepGraphHash: string | undefined
let patchHash: string | undefined
const { peersIndex, patchHashIndex } = indexOfPeersSuffix(version)
const { peersIndex, patchHashIndex } = indexOfDepPathSuffix(version)
if (peersIndex !== -1 || patchHashIndex !== -1) {
if (peersIndex === -1) {
patchHash = version.substring(patchHashIndex)
version = version.substring(0, patchHashIndex)
} else if (patchHashIndex === -1) {
peersSuffix = version.substring(peersIndex)
peerDepGraphHash = version.substring(peersIndex)
version = version.substring(0, peersIndex)
} else {
patchHash = version.substring(patchHashIndex, peersIndex)
peersSuffix = version.substring(peersIndex)
peerDepGraphHash = version.substring(peersIndex)
version = version.substring(0, patchHashIndex)
}
}
if (semver.valid(version)) {
return {
name,
peersSuffix,
peerDepGraphHash,
version,
patchHash,
}
@@ -157,7 +157,7 @@ export function parse (dependencyPath: string): DependencyPath {
return {
name,
nonSemverVersion: version as PkgResolutionId,
peersSuffix,
peerDepGraphHash,
patchHash,
}
}
@@ -189,9 +189,10 @@ function depPathToFilenameUnescaped (depPath: string): string {
return depPath.replace(':', '+')
}
// Peer ID or stringified peer dependency graph
export type PeerId = { name: string, version: string } | string
export function createPeersDirSuffix (peerIds: PeerId[], maxLength: number = 1000): string {
export function createPeerDepGraphHash (peerIds: PeerId[], maxLength: number = 1000): string {
let dirName = peerIds.map(
(peerId) => {
if (typeof peerId !== 'string') {

View File

@@ -21,35 +21,35 @@ test('parse()', () => {
/* eslint-enable @typescript-eslint/no-explicit-any */
expect(parse('foo@1.0.0')).toStrictEqual({
name: 'foo',
peersSuffix: undefined,
peerDepGraphHash: undefined,
version: '1.0.0',
patchHash: undefined,
})
expect(parse('@foo/bar@1.0.0')).toStrictEqual({
name: '@foo/bar',
peersSuffix: undefined,
peerDepGraphHash: undefined,
version: '1.0.0',
patchHash: undefined,
})
expect(parse('foo@1.0.0(@types/babel__core@7.1.14)')).toStrictEqual({
name: 'foo',
peersSuffix: '(@types/babel__core@7.1.14)',
peerDepGraphHash: '(@types/babel__core@7.1.14)',
version: '1.0.0',
patchHash: undefined,
})
expect(parse('foo@1.0.0(@types/babel__core@7.1.14)(foo@1.0.0)')).toStrictEqual({
name: 'foo',
peersSuffix: '(@types/babel__core@7.1.14)(foo@1.0.0)',
peerDepGraphHash: '(@types/babel__core@7.1.14)(foo@1.0.0)',
version: '1.0.0',
patchHash: undefined,
})
expect(parse('@(-.-)/foo@1.0.0(@types/babel__core@7.1.14)(foo@1.0.0)')).toStrictEqual({
name: '@(-.-)/foo',
peersSuffix: '(@types/babel__core@7.1.14)(foo@1.0.0)',
peerDepGraphHash: '(@types/babel__core@7.1.14)(foo@1.0.0)',
version: '1.0.0',
patchHash: undefined,
})
@@ -57,13 +57,13 @@ test('parse()', () => {
expect(parse('tar-pkg@file:../tar-pkg-1.0.0.tgz')).toStrictEqual({
name: 'tar-pkg',
nonSemverVersion: 'file:../tar-pkg-1.0.0.tgz',
peersSuffix: undefined,
peerDepGraphHash: undefined,
patchHash: undefined,
})
expect(parse('foo@1.0.0(patch_hash=0000)(@types/babel__core@7.1.14)')).toStrictEqual({
name: 'foo',
peersSuffix: '(@types/babel__core@7.1.14)',
peerDepGraphHash: '(@types/babel__core@7.1.14)',
version: '1.0.0',
patchHash: '(patch_hash=0000)',
})

View File

@@ -69,7 +69,7 @@ export async function getPatchedDependency (rawDependency: string, opts: GetPatc
export interface LockfileVersion {
gitTarballUrl?: string
name: string
peersSuffix?: string
peerDepGraphHash?: string
version: string
}

View File

@@ -1,4 +1,4 @@
import { createPeersDirSuffix } from '@pnpm/dependency-path'
import { createPeerDepGraphHash } from '@pnpm/dependency-path'
import { type ProjectRootDir, type ProjectId, type ProjectManifest } from '@pnpm/types'
import { prepareEmpty } from '@pnpm/prepare'
import { addDistTag } from '@pnpm/registry-mock'
@@ -159,12 +159,12 @@ test('importer with different peers uses correct peer', async () => {
const lockfile = readLockfile()
expect(lockfile.importers['project1' as ProjectId]?.dependencies?.['@pnpm.e2e/has-foo100-peer']).toEqual({
specifier: 'catalog:',
version: `1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/foo', version: '100.0.0' }])}`,
version: `1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/foo', version: '100.0.0' }])}`,
})
expect(lockfile.importers['project2' as ProjectId]?.dependencies?.['@pnpm.e2e/has-foo100-peer']).toEqual({
specifier: 'catalog:',
// This version is intentionally different from the one above ꜜ
version: `1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/foo', version: '100.1.0' }])}`,
version: `1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/foo', version: '100.1.0' }])}`,
})
})

View File

@@ -5,7 +5,7 @@ import { prepareEmpty, preparePackages } from '@pnpm/prepare'
import { addDistTag, REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
import { type ProjectRootDir } from '@pnpm/types'
import { sync as rimraf } from '@zkochan/rimraf'
import { createPeersDirSuffix } from '@pnpm/dependency-path'
import { createPeerDepGraphHash } from '@pnpm/dependency-path'
import { testDefaults } from '../utils'
test('auto install non-optional peer dependencies', async () => {
@@ -87,7 +87,7 @@ test('hoist a peer dependency in order to reuse it by other dependencies, when i
const project = prepareEmpty()
await addDependenciesToPackage({}, ['@pnpm/xyz-parent-parent-parent-parent', '@pnpm/xyz-parent-parent-with-xyz'], testDefaults({ autoInstallPeers: true }))
const lockfile = project.readLockfile()
const suffix = createPeersDirSuffix([{ name: '@pnpm/x', version: '1.0.0' }, { name: '@pnpm/y', version: '1.0.0' }, { name: '@pnpm/z', version: '1.0.0' }])
const suffix = createPeerDepGraphHash([{ name: '@pnpm/x', version: '1.0.0' }, { name: '@pnpm/y', version: '1.0.0' }, { name: '@pnpm/z', version: '1.0.0' }])
expect(Object.keys(lockfile.snapshots).sort()).toStrictEqual([
'@pnpm/x@1.0.0',
'@pnpm/xyz-parent-parent-with-xyz@1.0.0',
@@ -110,8 +110,8 @@ test('don\'t hoist a peer dependency when there is a root dependency by that nam
`http://localhost:${REGISTRY_MOCK_PORT}/@pnpm/y/-/y-2.0.0.tgz`,
], testDefaults({ autoInstallPeers: true }))
const lockfile = project.readLockfile()
const suffix1 = createPeersDirSuffix([{ name: '@pnpm/y', version: '2.0.0' }, { name: '@pnpm/z', version: '1.0.0' }, { name: '@pnpm.e2e/peer-a', version: '1.0.0' }])
const suffix2 = createPeersDirSuffix([{ name: '@pnpm/x', version: '1.0.0' }, { name: '@pnpm/y', version: '1.0.0' }, { name: '@pnpm/z', version: '1.0.0' }])
const suffix1 = createPeerDepGraphHash([{ name: '@pnpm/y', version: '2.0.0' }, { name: '@pnpm/z', version: '1.0.0' }, { name: '@pnpm.e2e/peer-a', version: '1.0.0' }])
const suffix2 = createPeerDepGraphHash([{ name: '@pnpm/x', version: '1.0.0' }, { name: '@pnpm/y', version: '1.0.0' }, { name: '@pnpm/z', version: '1.0.0' }])
expect(Object.keys(lockfile.snapshots).sort()).toStrictEqual([
'@pnpm.e2e/peer-a@1.0.0',
'@pnpm/x@1.0.0',
@@ -137,7 +137,7 @@ test('don\'t auto-install a peer dependency, when that dependency is in the root
`http://localhost:${REGISTRY_MOCK_PORT}/@pnpm/y/-/y-2.0.0.tgz`,
], testDefaults({ autoInstallPeers: true }))
const lockfile = project.readLockfile()
const suffix = createPeersDirSuffix([{ name: '@pnpm/y', version: '2.0.0' }, { name: '@pnpm/z', version: '1.0.0' }, { name: '@pnpm.e2e/peer-a', version: '1.0.0' }])
const suffix = createPeerDepGraphHash([{ name: '@pnpm/y', version: '2.0.0' }, { name: '@pnpm/z', version: '1.0.0' }, { name: '@pnpm.e2e/peer-a', version: '1.0.0' }])
expect(Object.keys(lockfile.snapshots).sort()).toStrictEqual([
`@pnpm/xyz-parent-parent-parent-parent@1.0.0${suffix}`,
`@pnpm/xyz-parent-parent-parent@1.0.0${suffix}`,

View File

@@ -4,7 +4,7 @@ import { prepareEmpty } from '@pnpm/prepare'
import { addDistTag } from '@pnpm/registry-mock'
import { addDependenciesToPackage } from '@pnpm/core'
import deepRequireCwd from 'deep-require-cwd'
import { createPeersDirSuffix } from '@pnpm/dependency-path'
import { createPeerDepGraphHash } from '@pnpm/dependency-path'
import { testDefaults } from '../utils'
test('package with default peer dependency, when auto install peers is on', async () => {
@@ -26,7 +26,7 @@ test('don\'t install the default peer dependency when it may be resolved from pa
const lockfile = project.readLockfile()
expect(Object.keys(lockfile.snapshots).sort()).toStrictEqual([
'@pnpm.e2e/dep-of-pkg-with-1-dep@101.0.0',
`@pnpm.e2e/has-default-peer@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/dep-of-pkg-with-1-dep', version: '101.0.0' }])}`,
`@pnpm.e2e/has-default-peer@1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/dep-of-pkg-with-1-dep', version: '101.0.0' }])}`,
].sort())
})

View File

@@ -13,7 +13,7 @@ import {
mutateModulesInSingleProject,
} from '@pnpm/core'
import { sync as rimraf } from '@zkochan/rimraf'
import { createPeersDirSuffix } from '@pnpm/dependency-path'
import { createPeerDepGraphHash } from '@pnpm/dependency-path'
import loadJsonFile from 'load-json-file'
import { sync as readYamlFile } from 'read-yaml-file'
import sinon from 'sinon'
@@ -1539,8 +1539,8 @@ test('resolve a subdependency from the workspace and use it as a peer', async ()
const project = assertProject(process.cwd())
const wantedLockfile = project.readLockfile()
const suffix1 = createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '@pnpm.e2e+peer-a' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }])
const suffix2 = createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '@pnpm.e2e+peer-a' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.1' }])
const suffix1 = createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-a', version: '@pnpm.e2e+peer-a' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }])
const suffix2 = createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-a', version: '@pnpm.e2e+peer-a' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.1' }])
expect(Object.keys(wantedLockfile.snapshots).sort()).toStrictEqual(
[
'@pnpm.e2e/abc-grand-parent-with-c@1.0.0',

View File

@@ -19,7 +19,7 @@ import {
import { sync as rimraf } from '@zkochan/rimraf'
import sinon from 'sinon'
import deepRequireCwd from 'deep-require-cwd'
import { createPeersDirSuffix, depPathToFilename } from '@pnpm/dependency-path'
import { createPeerDepGraphHash, depPathToFilename } from '@pnpm/dependency-path'
import { testDefaults } from '../utils'
const f = fixtures(__dirname)
@@ -551,7 +551,7 @@ test('peer dependencies are linked when running one named installation', async (
const pkgVariation1 = path.join(
'node_modules/.pnpm',
depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`, 120),
depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`, 120),
'node_modules'
)
await okFile(path.join(pkgVariation1, '@pnpm.e2e/abc'))
@@ -562,7 +562,7 @@ test('peer dependencies are linked when running one named installation', async (
const pkgVariation2 = path.join(
'node_modules/.pnpm',
depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`, 120),
depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`, 120),
'node_modules'
)
await okFile(path.join(pkgVariation2, '@pnpm.e2e/abc'))
@@ -590,7 +590,7 @@ test('peer dependencies are linked when running two separate named installations
const pkgVariation1 = path.join(
'node_modules/.pnpm',
depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`, 120),
depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`, 120),
'node_modules'
)
await okFile(path.join(pkgVariation1, '@pnpm.e2e/abc'))
@@ -601,7 +601,7 @@ test('peer dependencies are linked when running two separate named installations
const pkgVariation2 = path.join(
'node_modules/.pnpm',
depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '2.0.0' }])}`, 120),
depPathToFilename(`@pnpm.e2e/abc@1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '2.0.0' }])}`, 120),
'node_modules'
)
await okFile(path.join(pkgVariation2, '@pnpm.e2e/abc'))
@@ -661,7 +661,7 @@ test('peer bins are linked', async () => {
await addDependenciesToPackage({}, ['@pnpm.e2e/for-testing-peers-having-bins'], testDefaults({ fastUnpack: false }))
const suffix = createPeersDirSuffix([{ name: '@pnpm.e2e/peer-with-bin', version: '1.0.0' }])
const suffix = createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-with-bin', version: '1.0.0' }])
const pkgVariation = path.join('.pnpm', depPathToFilename(`@pnpm.e2e/pkg-with-peer-having-bin@1.0.0${suffix}`, 120), 'node_modules')
project.isExecutable(path.join(pkgVariation, '@pnpm.e2e/pkg-with-peer-having-bin/node_modules/.bin', 'peer-with-bin'))
@@ -1299,7 +1299,7 @@ test('deduplicate packages that have optional and non-optional peers', async ()
const lockfile = readYamlFile<LockfileFile>(path.resolve(WANTED_LOCKFILE))
const depPaths = Object.keys(lockfile.snapshots ?? {})
expect(depPaths.length).toBe(5)
expect(depPaths).toContain(`@pnpm.e2e/abc-optional-peers@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
expect(depPaths).toContain(`@pnpm.e2e/abc-optional-peers@1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
})
test('deduplicate packages that have peers', async () => {
@@ -1317,8 +1317,8 @@ test('deduplicate packages that have peers', async () => {
const lockfile = readYamlFile<LockfileFile>(path.resolve(WANTED_LOCKFILE))
const depPaths = Object.keys(lockfile.snapshots ?? {})
expect(depPaths.length).toBe(8)
expect(depPaths).toContain(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
expect(depPaths).toContain(`@pnpm.e2e/abc-parent-with-ab@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
expect(depPaths).toContain(`@pnpm.e2e/abc@1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
expect(depPaths).toContain(`@pnpm.e2e/abc-parent-with-ab@1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
})
test('deduplicate packages that have peers, when adding new dependency in a workspace', async () => {
@@ -1381,8 +1381,8 @@ test('deduplicate packages that have peers, when adding new dependency in a work
const lockfile = readYamlFile<LockfileFile>(path.resolve(WANTED_LOCKFILE))
const depPaths = Object.keys(lockfile.snapshots ?? {})
expect(depPaths.length).toBe(8)
expect(depPaths).toContain(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
expect(depPaths).toContain(`@pnpm.e2e/abc-parent-with-ab@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
expect(depPaths).toContain(`@pnpm.e2e/abc@1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
expect(depPaths).toContain(`@pnpm.e2e/abc-parent-with-ab@1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
})
test('resolve peer dependencies from aliased subdependencies if they are dependencies of a parent package', async () => {

View File

@@ -12,7 +12,7 @@ import {
type PkgIdWithPatchHash,
type ProjectRootDir,
} from '@pnpm/types'
import { depPathToFilename, createPeersDirSuffix, type PeerId } from '@pnpm/dependency-path'
import { depPathToFilename, createPeerDepGraphHash, type PeerId } from '@pnpm/dependency-path'
import partition from 'ramda/src/partition'
import pick from 'ramda/src/pick'
import { type NodeId } from './nextNodeId'
@@ -538,8 +538,8 @@ async function resolvePeersOfNode<T extends PartialResolvedPackage> (
pendingPeers.push({ alias, nodeId: peerNodeId })
}
if (pendingPeers.length === 0) {
const peersDirSuffix = createPeersDirSuffix(peerIds, ctx.peersSuffixMaxLength)
addDepPathToGraph(`${resolvedPackage.pkgIdWithPatchHash}${peersDirSuffix}` as DepPath)
const peerDepGraphHash = createPeerDepGraphHash(peerIds, ctx.peersSuffixMaxLength)
addDepPathToGraph(`${resolvedPackage.pkgIdWithPatchHash}${peerDepGraphHash}` as DepPath)
} else {
calculateDepPathIfNeeded = calculateDepPath.bind(null, peerIds, pendingPeers)
}
@@ -565,7 +565,7 @@ async function resolvePeersOfNode<T extends PartialResolvedPackage> (
}
}
}
const peersDirSuffix = createPeersDirSuffix([
const peerDepGraphHash = createPeerDepGraphHash([
...peerIds,
...await Promise.all(pendingPeerNodes
.map(async (pendingPeer) => {
@@ -579,7 +579,7 @@ async function resolvePeersOfNode<T extends PartialResolvedPackage> (
})
),
], ctx.peersSuffixMaxLength)
addDepPathToGraph(`${resolvedPackage.pkgIdWithPatchHash}${peersDirSuffix}` as DepPath)
addDepPathToGraph(`${resolvedPackage.pkgIdWithPatchHash}${peerDepGraphHash}` as DepPath)
}
function addDepPathToGraph (depPath: DepPath): void {

View File

@@ -4,7 +4,7 @@ import { type LockfileFile } from '@pnpm/lockfile.types'
import { preparePackages } from '@pnpm/prepare'
import { addDistTag } from '@pnpm/registry-mock'
import { sync as readYamlFile } from 'read-yaml-file'
import { createPeersDirSuffix } from '@pnpm/dependency-path'
import { createPeerDepGraphHash } from '@pnpm/dependency-path'
import { sync as loadJsonFile } from 'load-json-file'
import { sync as writeYamlFile } from 'write-yaml-file'
import { execPnpm } from '../utils'
@@ -45,8 +45,8 @@ test('deduplicate packages that have peers, when adding new dependency in a work
const lockfile = readYamlFile<LockfileFile>(path.resolve(WANTED_LOCKFILE))
const depPaths = Object.keys(lockfile.snapshots ?? {})
expect(depPaths.length).toBe(8)
expect(depPaths).toContain(`@pnpm.e2e/abc@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
expect(depPaths).toContain(`@pnpm.e2e/abc-parent-with-ab@1.0.0${createPeersDirSuffix([{ name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
expect(depPaths).toContain(`@pnpm.e2e/abc@1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
expect(depPaths).toContain(`@pnpm.e2e/abc-parent-with-ab@1.0.0${createPeerDepGraphHash([{ name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
})
test('partial update in a workspace should work with dedupe-peer-dependents is true', async () => {

View File

@@ -254,7 +254,7 @@ function resolveLinkOrFile (pkgVer: string, opts: Pick<ConvertOptions, 'lockfile
function resolveScheme (scheme: ResolveLinkOrFileResult['scheme'], base: string): ResolveLinkOrFileResult | undefined {
if (!pkgVer.startsWith(scheme)) return undefined
const { id, peersSuffix: suffix } = dp.parseDepPath(pkgVer.slice(scheme.length))
const { id, peerDepGraphHash: suffix } = dp.parseDepPath(pkgVer.slice(scheme.length))
const resolvedPath = path.resolve(base, id)
return { scheme, resolvedPath, suffix }
}
@@ -262,7 +262,7 @@ function resolveLinkOrFile (pkgVer: string, opts: Pick<ConvertOptions, 'lockfile
const resolveSchemeResult = resolveScheme('file:', lockfileDir) ?? resolveScheme('link:', projectRootDirRealPath)
if (resolveSchemeResult) return resolveSchemeResult
const { nonSemverVersion, patchHash, peersSuffix, version } = dp.parse(pkgVer)
const { nonSemverVersion, patchHash, peerDepGraphHash, version } = dp.parse(pkgVer)
if (!nonSemverVersion) return undefined
if (version) {
@@ -276,7 +276,7 @@ function resolveLinkOrFile (pkgVer: string, opts: Pick<ConvertOptions, 'lockfile
throw new Error(`Something goes wrong, suffix should be undefined but isn't: ${parseResult.suffix}`)
}
parseResult.suffix = `${patchHash ?? ''}${peersSuffix ?? ''}`
parseResult.suffix = `${patchHash ?? ''}${peerDepGraphHash ?? ''}`
return parseResult
}