fix: resolve peers from linked in dependencies (#4541)

This commit is contained in:
Zoltan Kochan
2022-04-09 15:59:52 +03:00
committed by GitHub
parent 9d35b88c1e
commit aecd4acdd6
7 changed files with 110 additions and 10 deletions

View File

@@ -0,0 +1,7 @@
---
"@pnpm/core": patch
"@pnpm/resolve-dependencies": patch
"pnpm": patch
---
Linked in dependencies should be considered when resolving peer dependencies [#4541](https://github.com/pnpm/pnpm/pull/4541).

View File

@@ -1163,8 +1163,8 @@ test('resolve a subdependency from the workspace and use it as a peer', async ()
'/abc-grand-parent-with-c/1.0.0',
'/abc-parent-with-ab/1.0.0',
'/abc-parent-with-ab/1.0.0_peer-c@1.0.1',
'/abc/1.0.0_20890f3ae006d9839e924c7177030952',
'/abc/1.0.0_peer-a@1.0.1+peer-b@1.0.0',
'/abc/1.0.0_2ff3f699e79762943311edf90e6e1302',
'/abc/1.0.0_peer-a@peer-a+peer-b@1.0.0',
'/dep-of-pkg-with-1-dep/100.0.0',
'/is-positive/1.0.0',
'/peer-b/1.0.0',
@@ -1172,7 +1172,7 @@ test('resolve a subdependency from the workspace and use it as a peer', async ()
]
)
expect(wantedLockfile.packages['/abc-parent-with-ab/1.0.0'].dependencies?.['peer-a']).toBe('link:peer-a')
expect(wantedLockfile.packages['/abc/1.0.0_peer-a@1.0.1+peer-b@1.0.0'].dependencies?.['peer-a']).toBe('link:peer-a')
expect(wantedLockfile.packages['/abc/1.0.0_peer-a@peer-a+peer-b@1.0.0'].dependencies?.['peer-a']).toBe('link:peer-a')
})
test('resolve a subdependency from the workspace, when it uses the workspace protocol', async () => {

View File

@@ -1127,3 +1127,46 @@ test('peer dependency that is resolved by a dev dependency', async () => {
await project.has('@typegoose/typegoose')
await project.hasNot('@types/mongoose')
})
test('peer dependency is grouped with dependency when peer is resolved not from a top dependency', async () => {
const project1Manifest = {
name: 'project-1',
version: '1.0.0',
dependencies: {
'ajv-keywords': '1.5.0',
ajv: 'link:../ajv',
},
}
const project2Manifest = {
name: 'ajv',
version: '4.10.4',
}
preparePackages([
{
location: 'project-1',
package: project1Manifest,
},
{
location: 'ajv',
package: project2Manifest,
},
])
const importers: MutatedProject[] = [
{
buildIndex: 0,
manifest: project1Manifest,
mutation: 'install',
rootDir: path.resolve('project-1'),
},
{
buildIndex: 0,
manifest: project2Manifest,
mutation: 'install',
rootDir: path.resolve('ajv'),
},
]
await mutateModules(importers, await testDefaults({}))
const lockfile = await readYamlFile<Lockfile>(path.resolve(WANTED_LOCKFILE))
expect(lockfile.packages?.['/ajv-keywords/1.5.0_ajv@ajv'].dependencies?.['ajv']).toBe('link:ajv')
})

View File

@@ -46,6 +46,7 @@
"@yarnpkg/core": "3.2.0",
"dependency-path": "workspace:9.0.0",
"encode-registry": "^3.0.0",
"filenamify": "^4.3.0",
"get-npm-tarball-url": "^2.0.3",
"is-inner-link": "^4.0.0",
"is-subdir": "^1.1.1",

View File

@@ -131,7 +131,7 @@ export default async function (
)
}
const topParents = project.manifest
const topParents: Array<{ name: string, version: string, linkedDir?: string }> = project.manifest
? await getTopParents(
difference(
Object.keys(getAllDependenciesFromManifest(project.manifest)),
@@ -142,6 +142,13 @@ export default async function (
project.modulesDir
)
: []
resolvedImporter.linkedDependencies.forEach((linkedDependency) => {
topParents.push({
name: linkedDependency.alias,
version: linkedDependency.version,
linkedDir: `link:${path.relative(opts.lockfileDir, linkedDependency.resolution.directory)}`,
})
})
const manifest = updatedOriginalManifest ?? project.originalManifest ?? project.manifest
importers[index].manifest = manifest

View File

@@ -1,4 +1,5 @@
import crypto from 'crypto'
import filenamify from 'filenamify'
import path from 'path'
import { satisfiesWithPrereleases } from '@yarnpkg/core/lib/semverUtils'
import {
@@ -117,16 +118,17 @@ function createPkgsByName<T extends PartialResolvedPackage> (
dependenciesTree: DependenciesTree<T>,
{ directNodeIdsByAlias, topParents }: {
directNodeIdsByAlias: {[alias: string]: string}
topParents: Array<{name: string, version: string}>
topParents: Array<{name: string, version: string, linkedDir?: string}>
}
) {
return Object.assign(
fromPairs(
topParents.map(({ name, version }): KeyValuePair<string, ParentRef> => [
topParents.map(({ name, version, linkedDir }): KeyValuePair<string, ParentRef> => [
name,
{
depth: 0,
version,
nodeId: linkedDir,
},
])
),
@@ -249,9 +251,19 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
depPath = resolvedPackage.depPath
} else {
const peersFolderSuffix = createPeersFolderSuffix(
Object.keys(allResolvedPeers)
.map((alias) => ctx.dependenciesTree[allResolvedPeers[alias]].resolvedPackage)
.map(({ name, version }) => ({ name, version })))
Object.entries(allResolvedPeers)
.map(([alias, nodeId]) => {
if (nodeId.startsWith('link:')) {
const linkedDir = nodeId.slice(5)
return {
name: alias,
version: filenamify(linkedDir, { replacement: '+' }),
}
}
const { name, version } = ctx.dependenciesTree[nodeId].resolvedPackage
return { name, version }
})
)
depPath = `${resolvedPackage.depPath}${peersFolderSuffix}`
}
const localLocation = path.join(ctx.virtualStoreDir, depPathToFilename(depPath))

32
pnpm-lock.yaml generated
View File

@@ -3178,6 +3178,7 @@ importers:
'@yarnpkg/core': 3.2.0
dependency-path: workspace:9.0.0
encode-registry: ^3.0.0
filenamify: ^4.3.0
get-npm-tarball-url: ^2.0.3
is-inner-link: ^4.0.0
is-subdir: ^1.1.1
@@ -3205,6 +3206,7 @@ importers:
'@yarnpkg/core': 3.2.0
dependency-path: link:../dependency-path
encode-registry: 3.0.0
filenamify: 4.3.0
get-npm-tarball-url: 2.0.3
is-inner-link: 4.0.0
is-subdir: 1.2.0
@@ -8257,7 +8259,7 @@ packages:
/eslint-config-standard-with-typescript/21.0.1_716c3012ce9c6cb0db5ff56082353a72:
resolution: {integrity: sha512-FeiMHljEJ346Y0I/HpAymNKdrgKEpHpcg/D93FvPHWfCzbT4QyUJba/0FwntZeGLXfUiWDSeKmdJD597d9wwiw==}
peerDependencies:
'@typescript-eslint/eslint-plugin': ^4.0.1 || ^5.6.0 || ^5.6.0
'@typescript-eslint/eslint-plugin': ^4.0.1 || ^5.6.0
eslint: '*'
eslint-plugin-import: ^2.22.1
eslint-plugin-node: ^11.1.0
@@ -8769,6 +8771,20 @@ packages:
dependencies:
flat-cache: 3.0.4
/filename-reserved-regex/2.0.0:
resolution: {integrity: sha1-q/c9+rc10EVECr/qLZHzieu/oik=}
engines: {node: '>=4'}
dev: false
/filenamify/4.3.0:
resolution: {integrity: sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==}
engines: {node: '>=8'}
dependencies:
filename-reserved-regex: 2.0.0
strip-outer: 1.0.1
trim-repeated: 1.0.0
dev: false
/fill-keys/1.0.2:
resolution: {integrity: sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=}
engines: {node: '>=0.10.0'}
@@ -13883,6 +13899,13 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
/strip-outer/1.0.1:
resolution: {integrity: sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==}
engines: {node: '>=0.10.0'}
dependencies:
escape-string-regexp: 1.0.5
dev: false
/supports-color/5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
@@ -14216,6 +14239,13 @@ packages:
engines: {node: '>=12'}
dev: true
/trim-repeated/1.0.0:
resolution: {integrity: sha1-42RqLqTokTEr9+rObPsFOAvAHCE=}
engines: {node: '>=0.10.0'}
dependencies:
escape-string-regexp: 1.0.5
dev: false
/trim-trailing-lines/1.1.4:
resolution: {integrity: sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==}
dev: false