mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-24 23:58:07 -05:00
feat: dedupe packages that have peers when dedupe-peer-dependents is true (#6153)
This commit is contained in:
41
.changeset/popular-maps-sip.md
Normal file
41
.changeset/popular-maps-sip.md
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
"@pnpm/resolve-dependencies": minor
|
||||
"@pnpm/core": minor
|
||||
"@pnpm/config": minor
|
||||
"pnpm": minor
|
||||
---
|
||||
|
||||
A new setting is now supported: `dedupe-peer-dependents`.
|
||||
|
||||
When this setting is set to `true`, packages with peer dependencies will be deduplicated after peers resolution.
|
||||
|
||||
For instance, let's say we have a workspace with two projects and both of them have `webpack` in their dependencies. `webpack` has `esbuild` in its optional peer dependencies, and one of the projects has `esbuild` in its dependencies. In this case, pnpm will link two instances of `webpack` to the `node_modules/.pnpm` directory: one with `esbuild` and another one without it:
|
||||
|
||||
```
|
||||
node_modules
|
||||
.pnpm
|
||||
webpack@1.0.0_esbuild@1.0.0
|
||||
webpack@1.0.0
|
||||
project1
|
||||
node_modules
|
||||
webpack -> ../../node_modules/.pnpm/webpack@1.0.0/node_modules/webpack
|
||||
project2
|
||||
node_modules
|
||||
webpack -> ../../node_modules/.pnpm/webpack@1.0.0_esbuild@1.0.0/node_modules/webpack
|
||||
esbuild
|
||||
```
|
||||
|
||||
This makes sense because `webpack` is used in two projects, and one of the projects doesn't have `esbuild`, so the two projects cannot share the same instance of `webpack`. However, this is not what most developers expect, especially since in a hoisted `node_modules`, there would only be one instance of `webpack`. Therefore, you may now use the `dedupe-peer-dependents` setting to deduplicate `webpack` when it has no conflicting peer dependencies. In this case, if we set `dedupe-peer-dependents` to `true`, both projects will use the same `webpack` instance, which is the one that has `esbuild` resolved:
|
||||
|
||||
```
|
||||
node_modules
|
||||
.pnpm
|
||||
webpack@1.0.0_esbuild@1.0.0
|
||||
project1
|
||||
node_modules
|
||||
webpack -> ../../node_modules/.pnpm/webpack@1.0.0_esbuild@1.0.0/node_modules/webpack
|
||||
project2
|
||||
node_modules
|
||||
webpack -> ../../node_modules/.pnpm/webpack@1.0.0_esbuild@1.0.0/node_modules/webpack
|
||||
esbuild
|
||||
```
|
||||
@@ -44,7 +44,7 @@
|
||||
"@pnpm/constants": "workspace:*",
|
||||
"@pnpm/lockfile-types": "workspace:*",
|
||||
"@pnpm/modules-yaml": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@pnpm/types": "workspace:*",
|
||||
"is-windows": "^1.0.2",
|
||||
"isexe": "2.0.0",
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@pnpm/cafs": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"path-exists": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -156,6 +156,7 @@ export interface Config {
|
||||
gitShallowHosts?: string[]
|
||||
legacyDirFiltering?: boolean
|
||||
onlyBuiltDependencies?: string[]
|
||||
dedupePeerDependents?: boolean
|
||||
|
||||
registries: Registries
|
||||
ignoreWorkspaceRootCheck: boolean
|
||||
|
||||
@@ -39,6 +39,7 @@ export const types = Object.assign({
|
||||
'merge-git-branch-lockfiles-branch-pattern': Array,
|
||||
color: ['always', 'auto', 'never'],
|
||||
'config-dir': String,
|
||||
'dedupe-peer-dependents': Boolean,
|
||||
dev: [null, true],
|
||||
dir: String,
|
||||
'enable-modules-dir': Boolean,
|
||||
@@ -183,6 +184,7 @@ export async function getConfig (
|
||||
'auto-install-peers': false,
|
||||
bail: true,
|
||||
color: 'auto',
|
||||
'dedupe-peer-dependents': false,
|
||||
'enable-modules-dir': true,
|
||||
'extend-node-path': true,
|
||||
'fetch-retries': 2,
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"@pnpm/filter-workspace-packages": "workspace:*",
|
||||
"@pnpm/plugin-commands-rebuild": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@types/ramda": "0.28.20",
|
||||
"@types/semver": "7.3.13",
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"@pnpm/filter-workspace-packages": "workspace:*",
|
||||
"@pnpm/plugin-commands-script-runners": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@types/is-windows": "^1.0.0",
|
||||
"@types/ramda": "0.28.20",
|
||||
"is-windows": "^1.0.2",
|
||||
|
||||
@@ -33,10 +33,10 @@
|
||||
},
|
||||
"homepage": "https://github.com/pnpm/pnpm/blob/main/patching/plugin-commands-patching#readme",
|
||||
"devDependencies": {
|
||||
"@pnpm/plugin-commands-patching": "workspace:*",
|
||||
"@pnpm/filter-workspace-packages": "workspace:*",
|
||||
"@pnpm/plugin-commands-patching": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@types/ramda": "0.28.20",
|
||||
"write-yaml-file": "^4.2.0"
|
||||
},
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
"@pnpm/git-utils": "workspace:*",
|
||||
"@pnpm/package-store": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@pnpm/store-path": "workspace:*",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
|
||||
@@ -121,6 +121,7 @@ export interface StrictInstallOptions {
|
||||
allProjects: ProjectOptions[]
|
||||
resolveSymlinksInInjectedDirs: boolean
|
||||
dedupeDirectDeps: boolean
|
||||
dedupePeerDependents: boolean
|
||||
useLockfileV6?: boolean
|
||||
extendNodePath: boolean
|
||||
}
|
||||
@@ -208,6 +209,7 @@ const defaults = async (opts: InstallOptions) => {
|
||||
modulesCacheMaxAge: 7 * 24 * 60,
|
||||
resolveSymlinksInInjectedDirs: false,
|
||||
dedupeDirectDeps: false,
|
||||
dedupePeerDependents: false,
|
||||
resolvePeersFromWorkspaceRoot: false,
|
||||
extendNodePath: true,
|
||||
} as StrictInstallOptions
|
||||
|
||||
@@ -807,7 +807,8 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => {
|
||||
!opts.currentLockfileIsUpToDate ||
|
||||
opts.force ||
|
||||
opts.needsFullResolution ||
|
||||
ctx.lockfileHadConflicts
|
||||
ctx.lockfileHadConflicts ||
|
||||
opts.dedupePeerDependents
|
||||
|
||||
// Ignore some fields when fixing lockfile, so these fields can be regenerated
|
||||
// and make sure it's up to date
|
||||
@@ -853,6 +854,7 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => {
|
||||
autoInstallPeers: opts.autoInstallPeers,
|
||||
currentLockfile: ctx.currentLockfile,
|
||||
defaultUpdateDepth: (opts.update || (opts.updateMatching != null)) ? opts.depth : -1,
|
||||
dedupePeerDependents: opts.dedupePeerDependents,
|
||||
dryRun: opts.lockfileOnly,
|
||||
engineStrict: opts.engineStrict,
|
||||
force: opts.force,
|
||||
|
||||
@@ -1225,3 +1225,102 @@ test('peer dependency is grouped with dependency when peer is resolved not from
|
||||
const lockfile = await readYamlFile<Lockfile>(path.resolve(WANTED_LOCKFILE))
|
||||
expect(lockfile.packages?.['/ajv-keywords/1.5.0_ajv@ajv'].dependencies?.['ajv']).toBe('link:ajv')
|
||||
})
|
||||
|
||||
test('deduplicate packages that have optional and non-optional peers', async () => {
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-a', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-b', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-c', version: '1.0.0', distTag: 'latest' })
|
||||
prepareEmpty()
|
||||
await addDependenciesToPackage({},
|
||||
['@pnpm.e2e/abc-optional-peers', '@pnpm.e2e/abc-optional-peers-parent'],
|
||||
await testDefaults({ autoInstallPeers: false, dedupePeerDependents: true })
|
||||
)
|
||||
|
||||
const lockfile = await readYamlFile<Lockfile>(path.resolve(WANTED_LOCKFILE))
|
||||
const depPaths = Object.keys(lockfile.packages ?? {})
|
||||
expect(depPaths.length).toBe(5)
|
||||
expect(depPaths).toContain(`/@pnpm.e2e/abc-optional-peers/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' }])}`)
|
||||
})
|
||||
|
||||
test('deduplicate packages that have peers', async () => {
|
||||
await addDistTag({ package: '@pnpm.e2e/abc-parent-with-ab', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-a', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-b', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-c', version: '1.0.0', distTag: 'latest' })
|
||||
|
||||
prepareEmpty()
|
||||
await addDependenciesToPackage({},
|
||||
['@pnpm.e2e/abc-grand-parent-with-c@1.0.0', '@pnpm.e2e/abc-parent-with-ab@1.0.0', '@pnpm.e2e/abc@1.0.0'],
|
||||
await testDefaults({ autoInstallPeers: false, dedupePeerDependents: true })
|
||||
)
|
||||
|
||||
const lockfile = await readYamlFile<Lockfile>(path.resolve(WANTED_LOCKFILE))
|
||||
const depPaths = Object.keys(lockfile.packages ?? {})
|
||||
expect(depPaths.length).toBe(8)
|
||||
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' }])}`)
|
||||
})
|
||||
|
||||
test('deduplicate packages that have peers, when adding new dependency in a workspace', async () => {
|
||||
await addDistTag({ package: '@pnpm.e2e/abc-parent-with-ab', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-a', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-b', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-c', version: '1.0.0', distTag: 'latest' })
|
||||
|
||||
const manifest1 = {
|
||||
name: 'project-1',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/abc-grand-parent-with-c': '1.0.0',
|
||||
},
|
||||
}
|
||||
const manifest2 = {
|
||||
name: 'project-2',
|
||||
}
|
||||
preparePackages([
|
||||
{
|
||||
location: 'project-1',
|
||||
package: manifest1,
|
||||
},
|
||||
{
|
||||
location: 'project-2',
|
||||
package: manifest2,
|
||||
},
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: manifest1,
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: manifest2,
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
await mutateModules(importers, await testDefaults({ allProjects, autoInstallPeers: false, dedupePeerDependents: true }))
|
||||
importers[1] = {
|
||||
dependencySelectors: ['@pnpm.e2e/abc@1.0.0'],
|
||||
mutation: 'installSome',
|
||||
rootDir: path.resolve('project-2'),
|
||||
}
|
||||
await mutateModules(importers, await testDefaults({ allProjects, autoInstallPeers: false, dedupePeerDependents: true }))
|
||||
|
||||
const lockfile = await readYamlFile<Lockfile>(path.resolve(WANTED_LOCKFILE))
|
||||
const depPaths = Object.keys(lockfile.packages ?? {})
|
||||
expect(depPaths.length).toBe(8)
|
||||
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' }])}`)
|
||||
})
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"@pnpm/package-store": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/read-projects-context": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@pnpm/store-path": "workspace:*",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
"@pnpm/client": "workspace:*",
|
||||
"@pnpm/create-cafs-store": "workspace:*",
|
||||
"@pnpm/package-requester": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@types/normalize-path": "^3.0.0",
|
||||
"@types/ramda": "0.28.20",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"@pnpm/modules-yaml": "workspace:*",
|
||||
"@pnpm/plugin-commands-installation": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@types/proxyquire": "^1.3.28",
|
||||
"@types/ramda": "0.28.20",
|
||||
|
||||
@@ -89,6 +89,7 @@ export async function resolveDependencies (
|
||||
importers: ImporterToResolve[],
|
||||
opts: ResolveDependenciesOptions & {
|
||||
defaultUpdateDepth: number
|
||||
dedupePeerDependents?: boolean
|
||||
preserveWorkspaceProtocol: boolean
|
||||
saveWorkspaceProtocol: 'rolling' | boolean
|
||||
lockfileIncludeTarballUrl?: boolean
|
||||
@@ -209,6 +210,7 @@ export async function resolveDependencies (
|
||||
peerDependencyIssuesByProjects,
|
||||
} = resolvePeers({
|
||||
dependenciesTree,
|
||||
dedupePeerDependents: opts.dedupePeerDependents,
|
||||
lockfileDir: opts.lockfileDir,
|
||||
projects: projectsToLink,
|
||||
virtualStoreDir: opts.virtualStoreDir,
|
||||
|
||||
@@ -32,6 +32,7 @@ export interface GenericDependenciesGraphNode {
|
||||
installable: boolean
|
||||
isBuilt?: boolean
|
||||
isPure: boolean
|
||||
resolvedPeerNames: string[]
|
||||
}
|
||||
|
||||
export type PartialResolvedPackage = Pick<ResolvedPackage,
|
||||
@@ -63,6 +64,7 @@ export function resolvePeers<T extends PartialResolvedPackage> (
|
||||
lockfileDir: string
|
||||
resolvePeersFromWorkspaceRoot?: boolean
|
||||
useLockfileV6?: boolean
|
||||
dedupePeerDependents?: boolean
|
||||
}
|
||||
): {
|
||||
dependenciesGraph: GenericDependenciesGraph<T>
|
||||
@@ -71,6 +73,7 @@ export function resolvePeers<T extends PartialResolvedPackage> (
|
||||
} {
|
||||
const depGraph: GenericDependenciesGraph<T> = {}
|
||||
const pathsByNodeId: Record<string, string> = {}
|
||||
const depPathsByPkgId: Record<string, string[]> = {}
|
||||
const _createPkgsByName = createPkgsByName.bind(null, opts.dependenciesTree)
|
||||
const rootPkgsByName = opts.resolvePeersFromWorkspaceRoot ? getRootPkgsByName(opts.dependenciesTree, opts.projects) : {}
|
||||
const peerDependencyIssuesByProjects: PeerDependencyIssuesByProjects = {}
|
||||
@@ -87,6 +90,7 @@ export function resolvePeers<T extends PartialResolvedPackage> (
|
||||
depGraph,
|
||||
lockfileDir: opts.lockfileDir,
|
||||
pathsByNodeId,
|
||||
depPathsByPkgId,
|
||||
peersCache: new Map(),
|
||||
peerDependencyIssues,
|
||||
purePkgs: new Set(),
|
||||
@@ -110,6 +114,15 @@ export function resolvePeers<T extends PartialResolvedPackage> (
|
||||
for (const { directNodeIdsByAlias, id } of opts.projects) {
|
||||
dependenciesByProjectId[id] = mapValues((nodeId) => pathsByNodeId[nodeId], directNodeIdsByAlias)
|
||||
}
|
||||
if (opts.dedupePeerDependents) {
|
||||
const depPathsMap = deduplicateDepPaths(depPathsByPkgId, depGraph)
|
||||
Object.values(depGraph).forEach((node) => {
|
||||
node.children = mapValues((childDepPath) => depPathsMap[childDepPath] ?? childDepPath, node.children)
|
||||
})
|
||||
for (const { id } of opts.projects) {
|
||||
dependenciesByProjectId[id] = mapValues((depPath) => depPathsMap[depPath] ?? depPath, dependenciesByProjectId[id])
|
||||
}
|
||||
}
|
||||
return {
|
||||
dependenciesGraph: depGraph,
|
||||
dependenciesByProjectId,
|
||||
@@ -117,6 +130,51 @@ export function resolvePeers<T extends PartialResolvedPackage> (
|
||||
}
|
||||
}
|
||||
|
||||
function nodeDepsCount (node: GenericDependenciesGraphNode) {
|
||||
return Object.keys(node.children).length + node.resolvedPeerNames.length
|
||||
}
|
||||
|
||||
function deduplicateDepPaths<T extends PartialResolvedPackage> (
|
||||
depPathsByPkgId: Record<string, string[]>,
|
||||
depGraph: GenericDependenciesGraph<T>
|
||||
) {
|
||||
const depPathsMap: Record<string, string> = {}
|
||||
for (let depPaths of Object.values(depPathsByPkgId)) {
|
||||
if (depPaths.length === 1) continue
|
||||
depPaths = depPaths.sort((depPath1, depPath2) => nodeDepsCount(depGraph[depPath1]) - nodeDepsCount(depGraph[depPath2]))
|
||||
let currentDepPaths = depPaths
|
||||
while (currentDepPaths.length) {
|
||||
const depPath1 = currentDepPaths.pop()!
|
||||
const nextDepPaths = []
|
||||
while (currentDepPaths.length) {
|
||||
const depPath2 = currentDepPaths.pop()!
|
||||
if (isCompatibleAndHasMoreDeps(depGraph, depPath1, depPath2)) {
|
||||
depPathsMap[depPath2] = depPath1
|
||||
} else {
|
||||
nextDepPaths.push(depPath2)
|
||||
}
|
||||
}
|
||||
nextDepPaths.push(...currentDepPaths)
|
||||
currentDepPaths = nextDepPaths
|
||||
}
|
||||
}
|
||||
return depPathsMap
|
||||
}
|
||||
|
||||
function isCompatibleAndHasMoreDeps<T extends PartialResolvedPackage> (
|
||||
depGraph: GenericDependenciesGraph<T>,
|
||||
depPath1: string,
|
||||
depPath2: string
|
||||
) {
|
||||
const node1 = depGraph[depPath1]
|
||||
const node2 = depGraph[depPath2]
|
||||
const node1DepPaths = Object.keys(node1.children)
|
||||
const node2DepPaths = Object.keys(node2.children)
|
||||
return nodeDepsCount(node1) > nodeDepsCount(node2) &&
|
||||
node2DepPaths.every((depPath) => node1DepPaths.includes(depPath)) &&
|
||||
node2.resolvedPeerNames.every((depPath) => node1.resolvedPeerNames.includes(depPath))
|
||||
}
|
||||
|
||||
function getRootPkgsByName<T extends PartialResolvedPackage> (dependenciesTree: DependenciesTree<T>, projects: ProjectToResolve[]) {
|
||||
const rootProject = projects.length > 1 ? projects.find(({ id }) => id === '.') : null
|
||||
return rootProject == null ? {} : createPkgsByName(dependenciesTree, rootProject)
|
||||
@@ -165,12 +223,16 @@ interface PeersResolution {
|
||||
resolvedPeers: Record<string, string>
|
||||
}
|
||||
|
||||
interface ResolvePeersContext {
|
||||
pathsByNodeId: { [nodeId: string]: string }
|
||||
depPathsByPkgId?: Record<string, string[]>
|
||||
}
|
||||
|
||||
function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
nodeId: string,
|
||||
parentParentPkgs: ParentRefs,
|
||||
ctx: {
|
||||
ctx: ResolvePeersContext & {
|
||||
dependenciesTree: DependenciesTree<T>
|
||||
pathsByNodeId: { [nodeId: string]: string }
|
||||
depGraph: GenericDependenciesGraph<T>
|
||||
virtualStoreDir: string
|
||||
peerDependencyIssues: Pick<PeerDependencyIssues, 'bad' | 'missing'>
|
||||
@@ -294,6 +356,14 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
}
|
||||
|
||||
ctx.pathsByNodeId[nodeId] = depPath
|
||||
if (ctx.depPathsByPkgId != null) {
|
||||
if (!ctx.depPathsByPkgId[resolvedPackage.depPath]) {
|
||||
ctx.depPathsByPkgId[resolvedPackage.depPath] = []
|
||||
}
|
||||
if (!ctx.depPathsByPkgId[resolvedPackage.depPath].includes(depPath)) {
|
||||
ctx.depPathsByPkgId[resolvedPackage.depPath].push(depPath)
|
||||
}
|
||||
}
|
||||
const peerDependencies = { ...resolvedPackage.peerDependencies }
|
||||
if (!ctx.depGraph[depPath] || ctx.depGraph[depPath].depth > node.depth) {
|
||||
const dir = path.join(modules, resolvedPackage.name)
|
||||
@@ -325,6 +395,7 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
modules,
|
||||
peerDependencies,
|
||||
transitivePeerDependencies,
|
||||
resolvedPeerNames: Object.keys(allResolvedPeers),
|
||||
}
|
||||
}
|
||||
return { resolvedPeers: allResolvedPeers, missingPeers: allMissingPeers }
|
||||
@@ -365,8 +436,7 @@ function resolvePeersOfChildren<T extends PartialResolvedPackage> (
|
||||
[alias: string]: string
|
||||
},
|
||||
parentPkgs: ParentRefs,
|
||||
ctx: {
|
||||
pathsByNodeId: { [nodeId: string]: string }
|
||||
ctx: ResolvePeersContext & {
|
||||
peerDependencyIssues: Pick<PeerDependencyIssues, 'bad' | 'missing'>
|
||||
peersCache: PeersCache
|
||||
virtualStoreDir: string
|
||||
|
||||
100
pnpm-lock.yaml
generated
100
pnpm-lock.yaml
generated
@@ -174,8 +174,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../pkg-manager/modules-yaml
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@pnpm/types':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/types
|
||||
@@ -214,8 +214,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../store/cafs
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
path-exists:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0
|
||||
@@ -1099,8 +1099,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@pnpm/test-fixtures':
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/test-fixtures
|
||||
@@ -1208,8 +1208,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@types/is-windows':
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
@@ -2532,8 +2532,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@types/ramda':
|
||||
specifier: 0.28.20
|
||||
version: 0.28.20
|
||||
@@ -2768,8 +2768,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@pnpm/store-path':
|
||||
specifier: workspace:*
|
||||
version: link:../../store/store-path
|
||||
@@ -3032,8 +3032,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../read-projects-context
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@pnpm/store-path':
|
||||
specifier: workspace:*
|
||||
version: link:../../store/store-path
|
||||
@@ -3395,8 +3395,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: 'link:'
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@pnpm/test-fixtures':
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/test-fixtures
|
||||
@@ -3579,8 +3579,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@pnpm/test-fixtures':
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/test-fixtures
|
||||
@@ -4120,8 +4120,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../pkg-manifest/read-project-manifest
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@pnpm/run-npm':
|
||||
specifier: workspace:*
|
||||
version: link:../exec/run-npm
|
||||
@@ -4371,8 +4371,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
|
||||
releasing/plugin-commands-publishing:
|
||||
dependencies:
|
||||
@@ -4468,8 +4468,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@types/cross-spawn':
|
||||
specifier: ^6.0.2
|
||||
version: 6.0.2
|
||||
@@ -5016,8 +5016,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../pkg-manifest/read-package-json
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@types/ramda':
|
||||
specifier: 0.28.20
|
||||
version: 0.28.20
|
||||
@@ -5080,8 +5080,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@types/ramda':
|
||||
specifier: 0.28.20
|
||||
version: 0.28.20
|
||||
@@ -5177,8 +5177,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@pnpm/test-fixtures':
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/test-fixtures
|
||||
@@ -5524,8 +5524,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0(typanion@3.12.1)
|
||||
specifier: 3.5.0
|
||||
version: 3.5.0(typanion@3.12.1)
|
||||
'@types/archy':
|
||||
specifier: 0.0.32
|
||||
version: 0.0.32
|
||||
@@ -7993,7 +7993,7 @@ packages:
|
||||
'@pnpm/find-workspace-dir': 5.0.1
|
||||
'@pnpm/find-workspace-packages': 5.0.36(@pnpm/logger@5.0.0)(@yarnpkg/core@4.0.0-rc.14)(typanion@3.12.1)
|
||||
'@pnpm/logger': 5.0.0
|
||||
'@pnpm/types': 8.10.0
|
||||
'@pnpm/types': 8.9.0
|
||||
'@yarnpkg/core': 4.0.0-rc.14(typanion@3.12.1)
|
||||
load-json-file: 7.0.1
|
||||
meow: 10.1.5
|
||||
@@ -8381,24 +8381,6 @@ packages:
|
||||
- typanion
|
||||
dev: true
|
||||
|
||||
/@pnpm/registry-mock@3.4.0(typanion@3.12.1):
|
||||
resolution: {integrity: sha512-M61ULPZS0ByO0gokTFmJCLvlb6W/idHp7Z6lIDQjKBII2z8DpFjI5D895F2MsNVxYLu3ZfZ3c3GISNtIbSFuPA==}
|
||||
engines: {node: '>=10.13'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
anonymous-npm-registry-client: 0.2.0
|
||||
cpr: 3.0.1
|
||||
execa: 5.1.1
|
||||
read-yaml-file: 2.1.0
|
||||
rimraf: 3.0.2
|
||||
tempy: 1.0.1
|
||||
verdaccio: 5.21.2(typanion@3.12.1)
|
||||
write-yaml-file: 4.2.0
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
- typanion
|
||||
|
||||
/@pnpm/registry-mock@3.5.0(typanion@3.12.1):
|
||||
resolution: {integrity: sha512-llz2BE8GB3vc/hFAQmKJtSrFoVnI0E2Nx+TPeIdn7zXTia+J03UYI6K3TPJMWcB37895BSMaFxDZh5abGASDgQ==}
|
||||
engines: {node: '>=10.13'}
|
||||
@@ -8416,7 +8398,6 @@ packages:
|
||||
- encoding
|
||||
- supports-color
|
||||
- typanion
|
||||
dev: true
|
||||
|
||||
/@pnpm/remove-bins@4.0.5(@pnpm/logger@5.0.0):
|
||||
resolution: {integrity: sha512-XQLCrLW4C80CZfMsTUIQhD1t4D21SIB9R1+9sP4CMXbOMxakIzctl/XKBVyYZCkAgNLgiII6S7rdBISYtsqx3A==}
|
||||
@@ -8561,7 +8542,6 @@ packages:
|
||||
/@pnpm/types@8.9.0:
|
||||
resolution: {integrity: sha512-3MYHYm8epnciApn6w5Fzx6sepawmsNU7l6lvIq+ER22/DPSrr83YMhU/EQWnf4lORn2YyiXFj0FJSyJzEtIGmw==}
|
||||
engines: {node: '>=14.6'}
|
||||
dev: false
|
||||
|
||||
/@pnpm/util.lex-comparator@1.0.0:
|
||||
resolution: {integrity: sha512-3aBQPHntVgk5AweBWZn+1I/fqZ9krK/w01197aYVkAJQGftb+BVWgEepxY5GChjSW12j52XX+CmfynYZ/p0DFQ==}
|
||||
@@ -8694,7 +8674,7 @@ packages:
|
||||
/@types/byline@4.2.33:
|
||||
resolution: {integrity: sha512-LJYez7wrWcJQQDknqZtrZuExMGP0IXmPl1rOOGDqLbu+H7UNNRfKNuSxCBcQMLH1EfjeWidLedC/hCc5dDfBog==}
|
||||
dependencies:
|
||||
'@types/node': 18.14.3
|
||||
'@types/node': 14.18.37
|
||||
dev: true
|
||||
|
||||
/@types/cacheable-request@6.0.3:
|
||||
@@ -8702,7 +8682,7 @@ packages:
|
||||
dependencies:
|
||||
'@types/http-cache-semantics': 4.0.1
|
||||
'@types/keyv': 3.1.4
|
||||
'@types/node': 18.14.3
|
||||
'@types/node': 14.18.37
|
||||
'@types/responselike': 1.0.0
|
||||
|
||||
/@types/concat-stream@2.0.0:
|
||||
@@ -8730,7 +8710,7 @@ packages:
|
||||
resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==}
|
||||
dependencies:
|
||||
'@types/minimatch': 5.1.2
|
||||
'@types/node': 18.14.3
|
||||
'@types/node': 14.18.37
|
||||
dev: true
|
||||
|
||||
/@types/graceful-fs@4.1.6:
|
||||
@@ -8804,7 +8784,7 @@ packages:
|
||||
/@types/keyv@3.1.4:
|
||||
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
|
||||
dependencies:
|
||||
'@types/node': 18.14.3
|
||||
'@types/node': 14.18.37
|
||||
|
||||
/@types/lodash@4.14.181:
|
||||
resolution: {integrity: sha512-n3tyKthHJbkiWhDZs3DkhkCzt2MexYHXlX0td5iMplyfwketaOeKboEVBqzceH7juqvEg3q5oUoBFxSLu7zFag==}
|
||||
@@ -8847,7 +8827,6 @@ packages:
|
||||
|
||||
/@types/node@14.18.37:
|
||||
resolution: {integrity: sha512-7GgtHCs/QZrBrDzgIJnQtuSvhFSwhyYSI2uafSwZoNt1iOGhEN5fwNrQMjtONyHm9+/LoA4453jH0CMYcr06Pg==}
|
||||
dev: true
|
||||
|
||||
/@types/node@18.14.3:
|
||||
resolution: {integrity: sha512-1y36CC5iL5CMyKALzwX9cwwxcWIxvIBe3gzs4GrXWXEQ8klQnCZ2U/WDGiNrXHmQcUhnaun17XG9TEIDlGj2RA==}
|
||||
@@ -8884,7 +8863,7 @@ packages:
|
||||
/@types/responselike@1.0.0:
|
||||
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
|
||||
dependencies:
|
||||
'@types/node': 18.14.3
|
||||
'@types/node': 14.18.37
|
||||
|
||||
/@types/retry@0.12.2:
|
||||
resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==}
|
||||
@@ -17357,7 +17336,7 @@ packages:
|
||||
/wide-align@1.1.5:
|
||||
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
|
||||
dependencies:
|
||||
string-width: 1.0.2
|
||||
string-width: 4.2.3
|
||||
|
||||
/widest-line@3.1.0:
|
||||
resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==}
|
||||
@@ -17670,7 +17649,6 @@ time:
|
||||
/@pnpm/npm-package-arg@1.0.0: '2022-06-28T12:48:31.287Z'
|
||||
/@pnpm/os.env.path-extender@0.2.10: '2023-02-28T01:46:02.862Z'
|
||||
/@pnpm/ramda@0.28.1: '2022-08-03T13:56:59.597Z'
|
||||
/@pnpm/registry-mock@3.4.0: '2023-02-08T00:47:00.662Z'
|
||||
/@pnpm/registry-mock@3.5.0: '2023-03-02T17:51:20.657Z'
|
||||
/@pnpm/semver-diff@1.1.0: '2021-11-16T12:40:59.941Z'
|
||||
/@pnpm/tabtab@0.1.2: '2021-03-05T17:31:19.932Z'
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/read-package-json": "workspace:*",
|
||||
"@pnpm/read-project-manifest": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@pnpm/run-npm": "workspace:*",
|
||||
"@pnpm/tabtab": "^0.1.2",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"@pnpm/lockfile-types": "workspace:*",
|
||||
"@pnpm/plugin-commands-deploy": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0"
|
||||
"@pnpm/registry-mock": "3.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pnpm/cli-utils": "workspace:*",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"@pnpm/filter-workspace-packages": "workspace:*",
|
||||
"@pnpm/plugin-commands-publishing": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@types/cross-spawn": "^6.0.2",
|
||||
"@types/is-windows": "^1.0.0",
|
||||
"@types/npm-packlist": "^3.0.0",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"@pnpm/plugin-commands-installation": "workspace:*",
|
||||
"@pnpm/plugin-commands-licenses": "workspace:*",
|
||||
"@pnpm/read-package-json": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@types/ramda": "0.28.20",
|
||||
"@types/wrap-ansi": "^8.0.1",
|
||||
"@types/zkochan__table": "npm:@types/table@6.0.0",
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"@pnpm/plugin-commands-installation": "workspace:*",
|
||||
"@pnpm/plugin-commands-listing": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@types/ramda": "0.28.20",
|
||||
"execa": "npm:safe-execa@0.1.2",
|
||||
"strip-ansi": "^6.0.1",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"@pnpm/plugin-commands-installation": "workspace:*",
|
||||
"@pnpm/plugin-commands-outdated": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@types/ramda": "0.28.20",
|
||||
"@types/wrap-ansi": "^8.0.1",
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"@pnpm/lockfile-file": "workspace:*",
|
||||
"@pnpm/plugin-commands-store": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.4.0",
|
||||
"@pnpm/registry-mock": "3.5.0",
|
||||
"@types/archy": "0.0.32",
|
||||
"@types/ramda": "0.28.20",
|
||||
"@types/ssri": "^7.1.1",
|
||||
|
||||
Reference in New Issue
Block a user