mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-28 11:01:30 -04:00
feat: support resolving peers with npm aliases (#6220)
close #4301 Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
6
.changeset/wild-dolphins-work.md
Normal file
6
.changeset/wild-dolphins-work.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"@pnpm/resolve-dependencies": patch
|
||||||
|
"pnpm": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Aliased packages should be used to resolve peer dependencies too [#4301](https://github.com/pnpm/pnpm/issues/4301).
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
"@pnpm/constants": "workspace:*",
|
"@pnpm/constants": "workspace:*",
|
||||||
"@pnpm/lockfile-types": "workspace:*",
|
"@pnpm/lockfile-types": "workspace:*",
|
||||||
"@pnpm/modules-yaml": "workspace:*",
|
"@pnpm/modules-yaml": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@pnpm/types": "workspace:*",
|
"@pnpm/types": "workspace:*",
|
||||||
"is-windows": "^1.0.2",
|
"is-windows": "^1.0.2",
|
||||||
"isexe": "2.0.0",
|
"isexe": "2.0.0",
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@pnpm/cafs": "workspace:*",
|
"@pnpm/cafs": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"path-exists": "^4.0.0"
|
"path-exists": "^4.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
"@pnpm/filter-workspace-packages": "workspace:*",
|
"@pnpm/filter-workspace-packages": "workspace:*",
|
||||||
"@pnpm/plugin-commands-rebuild": "workspace:*",
|
"@pnpm/plugin-commands-rebuild": "workspace:*",
|
||||||
"@pnpm/prepare": "workspace:*",
|
"@pnpm/prepare": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@pnpm/test-fixtures": "workspace:*",
|
"@pnpm/test-fixtures": "workspace:*",
|
||||||
"@types/ramda": "0.28.20",
|
"@types/ramda": "0.28.20",
|
||||||
"@types/semver": "7.3.13",
|
"@types/semver": "7.3.13",
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
"@pnpm/filter-workspace-packages": "workspace:*",
|
"@pnpm/filter-workspace-packages": "workspace:*",
|
||||||
"@pnpm/plugin-commands-script-runners": "workspace:*",
|
"@pnpm/plugin-commands-script-runners": "workspace:*",
|
||||||
"@pnpm/prepare": "workspace:*",
|
"@pnpm/prepare": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@types/is-windows": "^1.0.0",
|
"@types/is-windows": "^1.0.0",
|
||||||
"@types/ramda": "0.28.20",
|
"@types/ramda": "0.28.20",
|
||||||
"is-windows": "^1.0.2",
|
"is-windows": "^1.0.2",
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
"@commitlint/prompt-cli": "^17.4.4",
|
"@commitlint/prompt-cli": "^17.4.4",
|
||||||
"@pnpm/eslint-config": "workspace:*",
|
"@pnpm/eslint-config": "workspace:*",
|
||||||
"@pnpm/meta-updater": "0.2.2",
|
"@pnpm/meta-updater": "0.2.2",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@pnpm/tsconfig": "workspace:*",
|
"@pnpm/tsconfig": "workspace:*",
|
||||||
"@types/jest": "^29.4.0",
|
"@types/jest": "^29.4.0",
|
||||||
"@types/node": "^14.18.37",
|
"@types/node": "^14.18.37",
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
"@pnpm/filter-workspace-packages": "workspace:*",
|
"@pnpm/filter-workspace-packages": "workspace:*",
|
||||||
"@pnpm/plugin-commands-patching": "workspace:*",
|
"@pnpm/plugin-commands-patching": "workspace:*",
|
||||||
"@pnpm/prepare": "workspace:*",
|
"@pnpm/prepare": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@pnpm/test-fixtures": "workspace:*",
|
"@pnpm/test-fixtures": "workspace:*",
|
||||||
"@types/normalize-path": "^3.0.0",
|
"@types/normalize-path": "^3.0.0",
|
||||||
"@types/ramda": "0.28.20",
|
"@types/ramda": "0.28.20",
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
"@pnpm/lockfile-types": "workspace:*",
|
"@pnpm/lockfile-types": "workspace:*",
|
||||||
"@pnpm/package-store": "workspace:*",
|
"@pnpm/package-store": "workspace:*",
|
||||||
"@pnpm/prepare": "workspace:*",
|
"@pnpm/prepare": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@pnpm/store-path": "workspace:*",
|
"@pnpm/store-path": "workspace:*",
|
||||||
"@pnpm/test-fixtures": "workspace:*",
|
"@pnpm/test-fixtures": "workspace:*",
|
||||||
"@types/fs-extra": "^9.0.13",
|
"@types/fs-extra": "^9.0.13",
|
||||||
|
|||||||
@@ -1388,3 +1388,66 @@ test('deduplicate packages that have peers, when adding new dependency in a work
|
|||||||
expect(depPaths).toContain(`/@pnpm.e2e/abc@1.0.0${createPeersFolderSuffix([{ 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@1.0.0${createPeersFolderSuffix([{ 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${createPeersFolderSuffix([{ name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
|
expect(depPaths).toContain(`/@pnpm.e2e/abc-parent-with-ab@1.0.0${createPeersFolderSuffix([{ 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 () => {
|
||||||
|
prepareEmpty()
|
||||||
|
await addDistTag({ package: '@pnpm.e2e/peer-a', version: '1.0.0', distTag: 'latest' })
|
||||||
|
await addDistTag({ package: '@pnpm.e2e/peer-c', version: '1.0.0', distTag: 'latest' })
|
||||||
|
|
||||||
|
await addDependenciesToPackage(
|
||||||
|
{},
|
||||||
|
['@pnpm.e2e/abc-parent-with-aliases'],
|
||||||
|
await testDefaults({ autoInstallPeers: false, strictPeerDependencies: false })
|
||||||
|
)
|
||||||
|
|
||||||
|
const lockfile = await readYamlFile<any>(path.resolve(WANTED_LOCKFILE)) // eslint-disable-line
|
||||||
|
expect(lockfile.packages['/@pnpm.e2e/abc@1.0.0(@pnpm.e2e/peer-a@1.0.0)(@pnpm.e2e/peer-b@1.0.0)(@pnpm.e2e/peer-c@1.0.0)']).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('resolve peer dependency from aliased direct dependency', async () => {
|
||||||
|
prepareEmpty()
|
||||||
|
|
||||||
|
const opts = await testDefaults({ autoInstallPeers: false, strictPeerDependencies: false })
|
||||||
|
const manifest = await addDependenciesToPackage({}, ['peer-a@npm:@pnpm.e2e/peer-a@1.0.0'], opts)
|
||||||
|
await addDependenciesToPackage(manifest, ['@pnpm.e2e/abc@1.0.0'], opts)
|
||||||
|
|
||||||
|
const lockfile = await readYamlFile<any>(path.resolve(WANTED_LOCKFILE)) // eslint-disable-line
|
||||||
|
expect(lockfile.packages['/@pnpm.e2e/abc@1.0.0(@pnpm.e2e/peer-a@1.0.0)']).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('resolve peer dependency using the alias that differs from the real name of the direct dependency', async () => {
|
||||||
|
prepareEmpty()
|
||||||
|
|
||||||
|
const opts = await testDefaults({ autoInstallPeers: false, strictPeerDependencies: false })
|
||||||
|
const manifest = await addDependenciesToPackage({}, ['@pnpm.e2e/peer-b@npm:@pnpm.e2e/peer-a@1.0.0'], opts)
|
||||||
|
await addDependenciesToPackage(manifest, ['@pnpm.e2e/abc@1.0.0'], opts)
|
||||||
|
|
||||||
|
const lockfile = await readYamlFile<any>(path.resolve(WANTED_LOCKFILE)) // eslint-disable-line
|
||||||
|
expect(lockfile.packages['/@pnpm.e2e/abc@1.0.0(@pnpm.e2e/peer-a@1.0.0)(@pnpm.e2e/peer-a@1.0.0)']).toBeTruthy()
|
||||||
|
expect(lockfile.packages['/@pnpm.e2e/abc@1.0.0(@pnpm.e2e/peer-a@1.0.0)(@pnpm.e2e/peer-a@1.0.0)']?.dependencies['@pnpm.e2e/peer-a']).toBe('1.0.0')
|
||||||
|
expect(lockfile.packages['/@pnpm.e2e/abc@1.0.0(@pnpm.e2e/peer-a@1.0.0)(@pnpm.e2e/peer-a@1.0.0)']?.dependencies['@pnpm.e2e/peer-b']).toBe('/@pnpm.e2e/peer-a@1.0.0')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('when there are several aliased dependencies of the same package, pick the one with the highest version to resolve peers', async () => {
|
||||||
|
prepareEmpty()
|
||||||
|
|
||||||
|
const opts = await testDefaults({ autoInstallPeers: false, strictPeerDependencies: false })
|
||||||
|
const manifest = await addDependenciesToPackage({}, [
|
||||||
|
'peer-c3@npm:@pnpm.e2e/peer-c@1.0.0',
|
||||||
|
'peer-c2@npm:@pnpm.e2e/peer-c@1.0.1',
|
||||||
|
'peer-c1@npm:@pnpm.e2e/peer-c@2.0.0',
|
||||||
|
], opts)
|
||||||
|
await addDependenciesToPackage(manifest, ['@pnpm.e2e/abc@1.0.0'], opts)
|
||||||
|
|
||||||
|
const lockfile = await readYamlFile<any>(path.resolve(WANTED_LOCKFILE)) // eslint-disable-line
|
||||||
|
expect(lockfile.packages['/@pnpm.e2e/abc@1.0.0(@pnpm.e2e/peer-c@2.0.0)']).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('in a subdependency, when there are several aliased dependencies of the same package, pick the one with the highest version to resolve peers', async () => {
|
||||||
|
prepareEmpty()
|
||||||
|
|
||||||
|
await addDependenciesToPackage({}, ['@pnpm.e2e/abc-parent-with-aliases-of-same-pkg@1.0.0'], await testDefaults({ autoInstallPeers: false, strictPeerDependencies: false }))
|
||||||
|
|
||||||
|
const lockfile = await readYamlFile<any>(path.resolve(WANTED_LOCKFILE)) // eslint-disable-line
|
||||||
|
expect(lockfile.packages['/@pnpm.e2e/abc@1.0.0(@pnpm.e2e/peer-c@2.0.0)']).toBeTruthy()
|
||||||
|
})
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
"@pnpm/package-store": "workspace:*",
|
"@pnpm/package-store": "workspace:*",
|
||||||
"@pnpm/prepare": "workspace:*",
|
"@pnpm/prepare": "workspace:*",
|
||||||
"@pnpm/read-projects-context": "workspace:*",
|
"@pnpm/read-projects-context": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@pnpm/store-path": "workspace:*",
|
"@pnpm/store-path": "workspace:*",
|
||||||
"@pnpm/test-fixtures": "workspace:*",
|
"@pnpm/test-fixtures": "workspace:*",
|
||||||
"@types/fs-extra": "^9.0.13",
|
"@types/fs-extra": "^9.0.13",
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
"@pnpm/client": "workspace:*",
|
"@pnpm/client": "workspace:*",
|
||||||
"@pnpm/create-cafs-store": "workspace:*",
|
"@pnpm/create-cafs-store": "workspace:*",
|
||||||
"@pnpm/package-requester": "workspace:*",
|
"@pnpm/package-requester": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@pnpm/test-fixtures": "workspace:*",
|
"@pnpm/test-fixtures": "workspace:*",
|
||||||
"@types/normalize-path": "^3.0.0",
|
"@types/normalize-path": "^3.0.0",
|
||||||
"@types/ramda": "0.28.20",
|
"@types/ramda": "0.28.20",
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
"@pnpm/modules-yaml": "workspace:*",
|
"@pnpm/modules-yaml": "workspace:*",
|
||||||
"@pnpm/plugin-commands-installation": "workspace:*",
|
"@pnpm/plugin-commands-installation": "workspace:*",
|
||||||
"@pnpm/prepare": "workspace:*",
|
"@pnpm/prepare": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@pnpm/test-fixtures": "workspace:*",
|
"@pnpm/test-fixtures": "workspace:*",
|
||||||
"@types/proxyquire": "^1.3.28",
|
"@types/proxyquire": "^1.3.28",
|
||||||
"@types/ramda": "0.28.20",
|
"@types/ramda": "0.28.20",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import {
|
|||||||
} from '@pnpm/types'
|
} from '@pnpm/types'
|
||||||
import promiseShare from 'promise-share'
|
import promiseShare from 'promise-share'
|
||||||
import difference from 'ramda/src/difference'
|
import difference from 'ramda/src/difference'
|
||||||
|
import zipWith from 'ramda/src/zipWith'
|
||||||
import { getWantedDependencies, type WantedDependency } from './getWantedDependencies'
|
import { getWantedDependencies, type WantedDependency } from './getWantedDependencies'
|
||||||
import { depPathToRef } from './depPathToRef'
|
import { depPathToRef } from './depPathToRef'
|
||||||
import { createNodeIdForLinkedLocalPkg, type UpdateMatchingFunction } from './resolveDependencies'
|
import { createNodeIdForLinkedLocalPkg, type UpdateMatchingFunction } from './resolveDependencies'
|
||||||
@@ -173,7 +174,7 @@ export async function resolveDependencies (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const topParents: Array<{ name: string, version: string, linkedDir?: string }> = project.manifest
|
const topParents: Array<{ name: string, version: string, alias?: string, linkedDir?: string }> = project.manifest
|
||||||
? await getTopParents(
|
? await getTopParents(
|
||||||
difference(
|
difference(
|
||||||
Object.keys(getAllDependenciesFromManifest(project.manifest)),
|
Object.keys(getAllDependenciesFromManifest(project.manifest)),
|
||||||
@@ -440,13 +441,17 @@ function getAliasToDependencyTypeMap (manifest: ProjectManifest): Record<string,
|
|||||||
return depTypesOfAliases
|
return depTypesOfAliases
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getTopParents (pkgNames: string[], modules: string) {
|
async function getTopParents (pkgAliases: string[], modulesDir: string) {
|
||||||
const pkgs = await Promise.all(
|
const pkgs = await Promise.all(
|
||||||
pkgNames.map((pkgName) => path.join(modules, pkgName)).map(safeReadPackageJsonFromDir)
|
pkgAliases.map((alias) => path.join(modulesDir, alias)).map(safeReadPackageJsonFromDir)
|
||||||
)
|
)
|
||||||
return (
|
return zipWith((manifest, alias) => {
|
||||||
pkgs
|
if (!manifest) return null
|
||||||
.filter(Boolean) as DependencyManifest[]
|
return {
|
||||||
)
|
alias,
|
||||||
.map(({ name, version }: DependencyManifest) => ({ name, version }))
|
name: manifest.name,
|
||||||
|
version: manifest.version,
|
||||||
|
}
|
||||||
|
}, pkgs, pkgAliases)
|
||||||
|
.filter(Boolean) as DependencyManifest[]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import filenamify from 'filenamify'
|
import filenamify from 'filenamify'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import semver from 'semver'
|
||||||
import { semverUtils } from '@yarnpkg/core'
|
import { semverUtils } from '@yarnpkg/core'
|
||||||
import {
|
import type {
|
||||||
type Dependencies,
|
Dependencies,
|
||||||
type PeerDependencyIssues,
|
PeerDependencyIssues,
|
||||||
type PeerDependencyIssuesByProjects,
|
PeerDependencyIssuesByProjects,
|
||||||
} from '@pnpm/types'
|
} from '@pnpm/types'
|
||||||
import { depPathToFilename, createPeersFolderSuffixNewFormat } from '@pnpm/dependency-path'
|
import { depPathToFilename, createPeersFolderSuffixNewFormat } from '@pnpm/dependency-path'
|
||||||
import { type KeyValuePair } from 'ramda'
|
|
||||||
import isEmpty from 'ramda/src/isEmpty'
|
import isEmpty from 'ramda/src/isEmpty'
|
||||||
import mapValues from 'ramda/src/map'
|
import mapValues from 'ramda/src/map'
|
||||||
import pick from 'ramda/src/pick'
|
import pick from 'ramda/src/pick'
|
||||||
@@ -51,7 +51,7 @@ export interface ProjectToResolve {
|
|||||||
directNodeIdsByAlias: { [alias: string]: string }
|
directNodeIdsByAlias: { [alias: string]: string }
|
||||||
// only the top dependencies that were already installed
|
// only the top dependencies that were already installed
|
||||||
// to avoid warnings about unresolved peer dependencies
|
// to avoid warnings about unresolved peer dependencies
|
||||||
topParents: Array<{ name: string, version: string }>
|
topParents: Array<{ name: string, version: string, alias?: string }>
|
||||||
rootDir: string // is only needed for logging
|
rootDir: string // is only needed for logging
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
@@ -182,30 +182,32 @@ function createPkgsByName<T extends PartialResolvedPackage> (
|
|||||||
dependenciesTree: DependenciesTree<T>,
|
dependenciesTree: DependenciesTree<T>,
|
||||||
{ directNodeIdsByAlias, topParents }: {
|
{ directNodeIdsByAlias, topParents }: {
|
||||||
directNodeIdsByAlias: { [alias: string]: string }
|
directNodeIdsByAlias: { [alias: string]: string }
|
||||||
topParents: Array<{ name: string, version: string, linkedDir?: string }>
|
topParents: Array<{ name: string, version: string, alias?: string, linkedDir?: string }>
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
return Object.assign(
|
const parentRefs = toPkgByName(
|
||||||
Object.fromEntries(
|
Object
|
||||||
topParents.map(({ name, version, linkedDir }): KeyValuePair<string, ParentRef> => [
|
.keys(directNodeIdsByAlias)
|
||||||
name,
|
.map((alias) => ({
|
||||||
{
|
alias,
|
||||||
depth: 0,
|
node: dependenciesTree[directNodeIdsByAlias[alias]],
|
||||||
version,
|
nodeId: directNodeIdsByAlias[alias],
|
||||||
nodeId: linkedDir,
|
}))
|
||||||
},
|
|
||||||
])
|
|
||||||
),
|
|
||||||
toPkgByName(
|
|
||||||
Object
|
|
||||||
.keys(directNodeIdsByAlias)
|
|
||||||
.map((alias) => ({
|
|
||||||
alias,
|
|
||||||
node: dependenciesTree[directNodeIdsByAlias[alias]],
|
|
||||||
nodeId: directNodeIdsByAlias[alias],
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
const _updateParentRefs = updateParentRefs.bind(null, parentRefs)
|
||||||
|
for (const { name, version, alias, linkedDir } of topParents) {
|
||||||
|
const pkg = {
|
||||||
|
alias,
|
||||||
|
depth: 0,
|
||||||
|
version,
|
||||||
|
nodeId: linkedDir,
|
||||||
|
}
|
||||||
|
_updateParentRefs(name, pkg)
|
||||||
|
if (alias && alias !== name) {
|
||||||
|
_updateParentRefs(alias, pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parentRefs
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PeersCacheItem {
|
interface PeersCacheItem {
|
||||||
@@ -272,10 +274,10 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
|||||||
.every(([name, cachedNodeId]) => {
|
.every(([name, cachedNodeId]) => {
|
||||||
const parentPkgNodeId = parentPkgs[name]?.nodeId
|
const parentPkgNodeId = parentPkgs[name]?.nodeId
|
||||||
if (!parentPkgNodeId || !cachedNodeId) return false
|
if (!parentPkgNodeId || !cachedNodeId) return false
|
||||||
if (parentPkgs[name].nodeId === cachedNodeId) return true
|
if (parentPkgNodeId === cachedNodeId) return true
|
||||||
if (
|
if (
|
||||||
ctx.pathsByNodeId[cachedNodeId] &&
|
ctx.pathsByNodeId[cachedNodeId] &&
|
||||||
ctx.pathsByNodeId[cachedNodeId] === ctx.pathsByNodeId[parentPkgs[name].nodeId!]
|
ctx.pathsByNodeId[cachedNodeId] === ctx.pathsByNodeId[parentPkgNodeId]
|
||||||
) return true
|
) return true
|
||||||
const parentDepPath = (ctx.dependenciesTree[parentPkgNodeId].resolvedPackage as T).depPath
|
const parentDepPath = (ctx.dependenciesTree[parentPkgNodeId].resolvedPackage as T).depPath
|
||||||
if (!ctx.purePkgs.has(parentDepPath)) return false
|
if (!ctx.purePkgs.has(parentDepPath)) return false
|
||||||
@@ -572,16 +574,34 @@ interface ParentRef {
|
|||||||
depth: number
|
depth: number
|
||||||
// this is null only for already installed top dependencies
|
// this is null only for already installed top dependencies
|
||||||
nodeId?: string
|
nodeId?: string
|
||||||
|
alias?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function toPkgByName<T extends PartialResolvedPackage> (nodes: Array<{ alias: string, nodeId: string, node: DependenciesTreeNode<T> }>): ParentRefs {
|
function toPkgByName<T extends PartialResolvedPackage> (nodes: Array<{ alias: string, nodeId: string, node: DependenciesTreeNode<T> }>): ParentRefs {
|
||||||
const pkgsByName: ParentRefs = {}
|
const pkgsByName: ParentRefs = {}
|
||||||
|
const _updateParentRefs = updateParentRefs.bind(null, pkgsByName)
|
||||||
for (const { alias, node, nodeId } of nodes) {
|
for (const { alias, node, nodeId } of nodes) {
|
||||||
pkgsByName[alias] = {
|
const pkg = {
|
||||||
|
alias,
|
||||||
depth: node.depth,
|
depth: node.depth,
|
||||||
nodeId,
|
nodeId,
|
||||||
version: node.resolvedPackage.version,
|
version: node.resolvedPackage.version,
|
||||||
}
|
}
|
||||||
|
_updateParentRefs(alias, pkg)
|
||||||
|
if (alias !== node.resolvedPackage.name) {
|
||||||
|
_updateParentRefs(node.resolvedPackage.name, pkg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return pkgsByName
|
return pkgsByName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateParentRefs (parentRefs: ParentRefs, newAlias: string, pkg: ParentRef) {
|
||||||
|
const existing = parentRefs[newAlias]
|
||||||
|
if (existing) {
|
||||||
|
const existingHasAlias = existing.alias != null || existing.alias !== newAlias
|
||||||
|
if (!existingHasAlias) return
|
||||||
|
const newHasAlias = pkg.alias != null || pkg.alias !== newAlias
|
||||||
|
if (newHasAlias && semver.gte(existing.version, pkg.version)) return
|
||||||
|
}
|
||||||
|
parentRefs[newAlias] = pkg
|
||||||
|
}
|
||||||
|
|||||||
@@ -516,3 +516,99 @@ describe('unmet peer dependency issue resolved from subdependency', () => {
|
|||||||
expect(peerDependencyIssuesByProjects.project.bad.dep[0].resolvedFrom).toStrictEqual([{ name: 'foo', version: '1.0.0' }])
|
expect(peerDependencyIssuesByProjects.project.bad.dep[0].resolvedFrom).toStrictEqual([{ name: 'foo', version: '1.0.0' }])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('resolve peer dependencies with npm aliases', () => {
|
||||||
|
const fooPkg = {
|
||||||
|
name: 'foo',
|
||||||
|
depPath: 'foo/1.0.0',
|
||||||
|
version: '1.0.0',
|
||||||
|
peerDependencies: {
|
||||||
|
bar: '1.0.0',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const fooAliasPkg = {
|
||||||
|
name: 'foo',
|
||||||
|
depPath: 'foo/2.0.0',
|
||||||
|
version: '2.0.0',
|
||||||
|
peerDependencies: {
|
||||||
|
bar: '2.0.0',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const barPkg = {
|
||||||
|
name: 'bar',
|
||||||
|
depPath: 'bar/1.0.0',
|
||||||
|
version: '1.0.0',
|
||||||
|
peerDependencies: {},
|
||||||
|
}
|
||||||
|
const barAliasPkg = {
|
||||||
|
name: 'bar',
|
||||||
|
depPath: 'bar/2.0.0',
|
||||||
|
version: '2.0.0',
|
||||||
|
peerDependencies: {},
|
||||||
|
}
|
||||||
|
const { dependenciesGraph } = resolvePeers({
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
directNodeIdsByAlias: {
|
||||||
|
foo: '>foo/1.0.0>',
|
||||||
|
bar: '>bar/1.0.0>',
|
||||||
|
'foo-next': '>foo/2.0.0>',
|
||||||
|
'bar-next': '>bar/2.0.0>',
|
||||||
|
},
|
||||||
|
topParents: [],
|
||||||
|
rootDir: '',
|
||||||
|
id: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
dependenciesTree: {
|
||||||
|
'>foo/1.0.0>': {
|
||||||
|
children: {
|
||||||
|
bar: '>foo/1.0.0>bar/1.0.0>',
|
||||||
|
},
|
||||||
|
installable: true,
|
||||||
|
resolvedPackage: fooPkg,
|
||||||
|
depth: 0,
|
||||||
|
},
|
||||||
|
'>foo/1.0.0>bar/1.0.0>': {
|
||||||
|
children: {},
|
||||||
|
installable: true,
|
||||||
|
resolvedPackage: barPkg,
|
||||||
|
depth: 1,
|
||||||
|
},
|
||||||
|
'>foo/2.0.0>': {
|
||||||
|
children: {
|
||||||
|
bar: '>foo/2.0.0>bar/2.0.0>',
|
||||||
|
},
|
||||||
|
installable: true,
|
||||||
|
resolvedPackage: fooAliasPkg,
|
||||||
|
depth: 0,
|
||||||
|
},
|
||||||
|
'>foo/2.0.0>bar/2.0.0>': {
|
||||||
|
children: {},
|
||||||
|
installable: true,
|
||||||
|
resolvedPackage: barAliasPkg,
|
||||||
|
depth: 1,
|
||||||
|
},
|
||||||
|
'>bar/1.0.0>': {
|
||||||
|
children: {},
|
||||||
|
installable: true,
|
||||||
|
resolvedPackage: barPkg,
|
||||||
|
depth: 0,
|
||||||
|
},
|
||||||
|
'>bar/2.0.0>': {
|
||||||
|
children: {},
|
||||||
|
installable: true,
|
||||||
|
resolvedPackage: barAliasPkg,
|
||||||
|
depth: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
virtualStoreDir: '',
|
||||||
|
lockfileDir: '',
|
||||||
|
})
|
||||||
|
expect(Object.keys(dependenciesGraph)).toStrictEqual([
|
||||||
|
'bar/1.0.0',
|
||||||
|
'foo/1.0.0(bar@1.0.0)',
|
||||||
|
'bar/2.0.0',
|
||||||
|
'foo/2.0.0(bar@2.0.0)',
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|||||||
627
pnpm-lock.yaml
generated
627
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -60,7 +60,7 @@
|
|||||||
"@pnpm/prepare": "workspace:*",
|
"@pnpm/prepare": "workspace:*",
|
||||||
"@pnpm/read-package-json": "workspace:*",
|
"@pnpm/read-package-json": "workspace:*",
|
||||||
"@pnpm/read-project-manifest": "workspace:*",
|
"@pnpm/read-project-manifest": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@pnpm/run-npm": "workspace:*",
|
"@pnpm/run-npm": "workspace:*",
|
||||||
"@pnpm/tabtab": "^0.1.2",
|
"@pnpm/tabtab": "^0.1.2",
|
||||||
"@pnpm/test-fixtures": "workspace:*",
|
"@pnpm/test-fixtures": "workspace:*",
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
"@pnpm/lockfile-types": "workspace:*",
|
"@pnpm/lockfile-types": "workspace:*",
|
||||||
"@pnpm/plugin-commands-deploy": "workspace:*",
|
"@pnpm/plugin-commands-deploy": "workspace:*",
|
||||||
"@pnpm/prepare": "workspace:*",
|
"@pnpm/prepare": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0"
|
"@pnpm/registry-mock": "3.7.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@pnpm/cli-utils": "workspace:*",
|
"@pnpm/cli-utils": "workspace:*",
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
"@pnpm/filter-workspace-packages": "workspace:*",
|
"@pnpm/filter-workspace-packages": "workspace:*",
|
||||||
"@pnpm/plugin-commands-publishing": "workspace:*",
|
"@pnpm/plugin-commands-publishing": "workspace:*",
|
||||||
"@pnpm/prepare": "workspace:*",
|
"@pnpm/prepare": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@types/cross-spawn": "^6.0.2",
|
"@types/cross-spawn": "^6.0.2",
|
||||||
"@types/is-windows": "^1.0.0",
|
"@types/is-windows": "^1.0.0",
|
||||||
"@types/npm-packlist": "^3.0.0",
|
"@types/npm-packlist": "^3.0.0",
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
"@pnpm/plugin-commands-installation": "workspace:*",
|
"@pnpm/plugin-commands-installation": "workspace:*",
|
||||||
"@pnpm/plugin-commands-licenses": "workspace:*",
|
"@pnpm/plugin-commands-licenses": "workspace:*",
|
||||||
"@pnpm/read-package-json": "workspace:*",
|
"@pnpm/read-package-json": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@types/ramda": "0.28.20",
|
"@types/ramda": "0.28.20",
|
||||||
"@types/wrap-ansi": "^8.0.1",
|
"@types/wrap-ansi": "^8.0.1",
|
||||||
"@types/zkochan__table": "npm:@types/table@6.0.0",
|
"@types/zkochan__table": "npm:@types/table@6.0.0",
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
"@pnpm/plugin-commands-installation": "workspace:*",
|
"@pnpm/plugin-commands-installation": "workspace:*",
|
||||||
"@pnpm/plugin-commands-listing": "workspace:*",
|
"@pnpm/plugin-commands-listing": "workspace:*",
|
||||||
"@pnpm/prepare": "workspace:*",
|
"@pnpm/prepare": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@types/ramda": "0.28.20",
|
"@types/ramda": "0.28.20",
|
||||||
"execa": "npm:safe-execa@0.1.2",
|
"execa": "npm:safe-execa@0.1.2",
|
||||||
"strip-ansi": "^6.0.1",
|
"strip-ansi": "^6.0.1",
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
"@pnpm/plugin-commands-installation": "workspace:*",
|
"@pnpm/plugin-commands-installation": "workspace:*",
|
||||||
"@pnpm/plugin-commands-outdated": "workspace:*",
|
"@pnpm/plugin-commands-outdated": "workspace:*",
|
||||||
"@pnpm/prepare": "workspace:*",
|
"@pnpm/prepare": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@pnpm/test-fixtures": "workspace:*",
|
"@pnpm/test-fixtures": "workspace:*",
|
||||||
"@types/ramda": "0.28.20",
|
"@types/ramda": "0.28.20",
|
||||||
"@types/wrap-ansi": "^8.0.1",
|
"@types/wrap-ansi": "^8.0.1",
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
"@pnpm/lockfile-file": "workspace:*",
|
"@pnpm/lockfile-file": "workspace:*",
|
||||||
"@pnpm/plugin-commands-store": "workspace:*",
|
"@pnpm/plugin-commands-store": "workspace:*",
|
||||||
"@pnpm/prepare": "workspace:*",
|
"@pnpm/prepare": "workspace:*",
|
||||||
"@pnpm/registry-mock": "3.5.0",
|
"@pnpm/registry-mock": "3.7.0",
|
||||||
"@types/archy": "0.0.32",
|
"@types/archy": "0.0.32",
|
||||||
"@types/ramda": "0.28.20",
|
"@types/ramda": "0.28.20",
|
||||||
"@types/ssri": "^7.1.1",
|
"@types/ssri": "^7.1.1",
|
||||||
|
|||||||
Reference in New Issue
Block a user