mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-28 02:53:15 -04:00
refactor(resolve-dependencies): use Maps and Sets instead of objects (#6749)
This commit is contained in:
5
.changeset/fair-apples-mix.md
Normal file
5
.changeset/fair-apples-mix.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/resolve-dependencies": patch
|
||||
---
|
||||
|
||||
Refactor resolve-dependencies to use maps and sets instead of objects
|
||||
@@ -89,12 +89,13 @@ export type DependenciesTreeNode<T> = {
|
||||
depth: -1
|
||||
})
|
||||
|
||||
export interface DependenciesTree<T> {
|
||||
// a node ID is the join of the package's keypath with a colon
|
||||
// E.g., a subdeps node ID which parent is `foo` will be
|
||||
// registry.npmjs.org/foo/1.0.0:registry.npmjs.org/bar/1.0.0
|
||||
[nodeId: string]: DependenciesTreeNode<T>
|
||||
}
|
||||
export type DependenciesTree<T> = Map<
|
||||
// a node ID is the join of the package's keypath with a colon
|
||||
// E.g., a subdeps node ID which parent is `foo` will be
|
||||
// registry.npmjs.org/foo/1.0.0:registry.npmjs.org/bar/1.0.0
|
||||
string,
|
||||
DependenciesTreeNode<T>
|
||||
>
|
||||
|
||||
export type ResolvedPackagesByDepPath = Record<string, ResolvedPackage>
|
||||
|
||||
@@ -680,7 +681,7 @@ async function resolveDependenciesOfDependency (
|
||||
|
||||
if (resolveDependencyResult == null) return { resolveDependencyResult: null }
|
||||
if (resolveDependencyResult.isLinkedDependency) {
|
||||
ctx.dependenciesTree[createNodeIdForLinkedLocalPkg(ctx.lockfileDir, resolveDependencyResult.resolution.directory)] = {
|
||||
ctx.dependenciesTree.set(createNodeIdForLinkedLocalPkg(ctx.lockfileDir, resolveDependencyResult.resolution.directory), {
|
||||
children: {},
|
||||
depth: -1,
|
||||
installable: true,
|
||||
@@ -688,7 +689,7 @@ async function resolveDependenciesOfDependency (
|
||||
name: resolveDependencyResult.name,
|
||||
version: resolveDependencyResult.version,
|
||||
},
|
||||
}
|
||||
})
|
||||
return { resolveDependencyResult }
|
||||
}
|
||||
if (!resolveDependencyResult.isNew) {
|
||||
@@ -815,7 +816,7 @@ async function resolveChildren (
|
||||
alias: child.alias,
|
||||
depPath: child.depPath,
|
||||
}))
|
||||
ctx.dependenciesTree[parentPkg.nodeId] = {
|
||||
ctx.dependenciesTree.set(parentPkg.nodeId, {
|
||||
children: pkgAddresses.reduce((chn, child) => {
|
||||
chn[child.alias] = (child as PkgAddress).nodeId ?? child.pkgId
|
||||
return chn
|
||||
@@ -823,7 +824,7 @@ async function resolveChildren (
|
||||
depth: parentDepth,
|
||||
installable: parentPkg.installable,
|
||||
resolvedPackage: ctx.resolvedPackagesByDepPath[parentPkg.depPath],
|
||||
}
|
||||
})
|
||||
return resolvingPeers
|
||||
}
|
||||
|
||||
@@ -1304,8 +1305,8 @@ async function resolveDependency (
|
||||
ctx.resolvedPackagesByDepPath[depPath].fetchingBundledManifest = pkgResponse.bundledManifest!
|
||||
}
|
||||
|
||||
if (ctx.dependenciesTree[nodeId]) {
|
||||
ctx.dependenciesTree[nodeId].depth = Math.min(ctx.dependenciesTree[nodeId].depth, options.currentDepth)
|
||||
if (ctx.dependenciesTree.has(nodeId)) {
|
||||
ctx.dependenciesTree.get(nodeId)!.depth = Math.min(ctx.dependenciesTree.get(nodeId)!.depth, options.currentDepth)
|
||||
} else {
|
||||
ctx.pendingNodes.push({
|
||||
alias: wantedDependency.alias || pkg.name,
|
||||
|
||||
@@ -101,7 +101,7 @@ export async function resolveDependencyTree<T> (
|
||||
childrenByParentDepPath: {} as ChildrenByParentDepPath,
|
||||
currentLockfile: opts.currentLockfile,
|
||||
defaultTag: opts.tag,
|
||||
dependenciesTree: {} as DependenciesTree<ResolvedPackage>,
|
||||
dependenciesTree: new Map() as DependenciesTree<ResolvedPackage>,
|
||||
dryRun: opts.dryRun,
|
||||
engineStrict: opts.engineStrict,
|
||||
force: opts.force,
|
||||
@@ -168,13 +168,13 @@ export async function resolveDependencyTree<T> (
|
||||
const directDepsByImporterId = zipObj(importers.map(({ id }) => id), pkgAddressesByImporters)
|
||||
|
||||
ctx.pendingNodes.forEach((pendingNode) => {
|
||||
ctx.dependenciesTree[pendingNode.nodeId] = {
|
||||
ctx.dependenciesTree.set(pendingNode.nodeId, {
|
||||
children: () => buildTree(ctx, pendingNode.nodeId, pendingNode.resolvedPackage.id,
|
||||
ctx.childrenByParentDepPath[pendingNode.resolvedPackage.depPath], pendingNode.depth + 1, pendingNode.installable),
|
||||
depth: pendingNode.depth,
|
||||
installable: pendingNode.installable,
|
||||
resolvedPackage: pendingNode.resolvedPackage,
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const resolvedImporters = {} as {
|
||||
@@ -197,7 +197,7 @@ export async function resolveDependencyTree<T> (
|
||||
if (dep.isLinkedDependency === true) {
|
||||
return dep
|
||||
}
|
||||
const resolvedPackage = ctx.dependenciesTree[dep.nodeId].resolvedPackage as ResolvedPackage
|
||||
const resolvedPackage = ctx.dependenciesTree.get(dep.nodeId)!.resolvedPackage as ResolvedPackage
|
||||
return {
|
||||
alias: dep.alias,
|
||||
dev: resolvedPackage.dev,
|
||||
@@ -254,7 +254,7 @@ function buildTree (
|
||||
const childNodeId = createNodeId(parentNodeId, child.depPath)
|
||||
childrenNodeIds[child.alias] = childNodeId
|
||||
installable = installable && !ctx.skipped.has(child.depPath)
|
||||
ctx.dependenciesTree[childNodeId] = {
|
||||
ctx.dependenciesTree.set(childNodeId, {
|
||||
children: () => buildTree(ctx,
|
||||
childNodeId,
|
||||
child.depPath,
|
||||
@@ -265,7 +265,7 @@ function buildTree (
|
||||
depth,
|
||||
installable,
|
||||
resolvedPackage: ctx.resolvedPackagesByDepPath[child.depPath],
|
||||
}
|
||||
})
|
||||
}
|
||||
return childrenNodeIds
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import type {
|
||||
import { depPathToFilename, createPeersFolderSuffix } from '@pnpm/dependency-path'
|
||||
import mapValues from 'ramda/src/map'
|
||||
import pick from 'ramda/src/pick'
|
||||
import pickBy from 'ramda/src/pickBy'
|
||||
import scan from 'ramda/src/scan'
|
||||
import {
|
||||
type DependenciesTree,
|
||||
@@ -31,7 +30,7 @@ export interface GenericDependenciesGraphNode {
|
||||
installable: boolean
|
||||
isBuilt?: boolean
|
||||
isPure: boolean
|
||||
resolvedPeerNames: string[]
|
||||
resolvedPeerNames: Set<string>
|
||||
}
|
||||
|
||||
export type PartialResolvedPackage = Pick<ResolvedPackage,
|
||||
@@ -70,8 +69,8 @@ export function resolvePeers<T extends PartialResolvedPackage> (
|
||||
peerDependencyIssuesByProjects: PeerDependencyIssuesByProjects
|
||||
} {
|
||||
const depGraph: GenericDependenciesGraph<T> = {}
|
||||
const pathsByNodeId: Record<string, string> = {}
|
||||
const depPathsByPkgId: Record<string, string[]> = {}
|
||||
const pathsByNodeId = new Map<string, string>()
|
||||
const depPathsByPkgId = new Map<string, Set<string>>()
|
||||
const _createPkgsByName = createPkgsByName.bind(null, opts.dependenciesTree)
|
||||
const rootPkgsByName = opts.resolvePeersFromWorkspaceRoot ? getRootPkgsByName(opts.dependenciesTree, opts.projects) : {}
|
||||
const peerDependencyIssuesByProjects: PeerDependencyIssuesByProjects = {}
|
||||
@@ -104,15 +103,15 @@ export function resolvePeers<T extends PartialResolvedPackage> (
|
||||
}
|
||||
|
||||
Object.values(depGraph).forEach((node) => {
|
||||
node.children = mapValues((childNodeId) => pathsByNodeId[childNodeId] ?? childNodeId, node.children)
|
||||
node.children = mapValues((childNodeId) => pathsByNodeId.get(childNodeId) ?? childNodeId, node.children)
|
||||
})
|
||||
|
||||
const dependenciesByProjectId: { [id: string]: Record<string, string> } = {}
|
||||
for (const { directNodeIdsByAlias, id } of opts.projects) {
|
||||
dependenciesByProjectId[id] = mapValues((nodeId) => pathsByNodeId[nodeId], directNodeIdsByAlias)
|
||||
dependenciesByProjectId[id] = mapValues((nodeId) => pathsByNodeId.get(nodeId)!, directNodeIdsByAlias)
|
||||
}
|
||||
if (opts.dedupePeerDependents) {
|
||||
const duplicates = Object.values(depPathsByPkgId).filter((item) => item.length > 1)
|
||||
const duplicates = Array.from(depPathsByPkgId.values()).filter((item) => item.size > 1)
|
||||
const allDepPathsMap = deduplicateAll(depGraph, duplicates)
|
||||
for (const { id } of opts.projects) {
|
||||
dependenciesByProjectId[id] = mapValues((depPath) => allDepPathsMap[depPath] ?? depPath, dependenciesByProjectId[id])
|
||||
@@ -126,12 +125,12 @@ export function resolvePeers<T extends PartialResolvedPackage> (
|
||||
}
|
||||
|
||||
function nodeDepsCount (node: GenericDependenciesGraphNode) {
|
||||
return Object.keys(node.children).length + node.resolvedPeerNames.length
|
||||
return Object.keys(node.children).length + node.resolvedPeerNames.size
|
||||
}
|
||||
|
||||
function deduplicateAll<T extends PartialResolvedPackage> (
|
||||
depGraph: GenericDependenciesGraph<T>,
|
||||
duplicates: string[][]
|
||||
duplicates: Array<Set<string>>
|
||||
): Record<string, string> {
|
||||
const { depPathsMap, remainingDuplicates } = deduplicateDepPaths(duplicates, depGraph)
|
||||
if (remainingDuplicates.length === duplicates.length) {
|
||||
@@ -150,16 +149,16 @@ function deduplicateAll<T extends PartialResolvedPackage> (
|
||||
}
|
||||
|
||||
function deduplicateDepPaths<T extends PartialResolvedPackage> (
|
||||
duplicates: string[][],
|
||||
duplicates: Array<Set<string>>,
|
||||
depGraph: GenericDependenciesGraph<T>
|
||||
) {
|
||||
const depCountSorter = (depPath1: string, depPath2: string) => nodeDepsCount(depGraph[depPath1]) - nodeDepsCount(depGraph[depPath2])
|
||||
const depPathsMap: Record<string, string> = {}
|
||||
const remainingDuplicates: string[][] = []
|
||||
const remainingDuplicates: Array<Set<string>> = []
|
||||
|
||||
for (const depPaths of duplicates) {
|
||||
const unresolvedDepPaths = new Set(depPaths)
|
||||
let currentDepPaths = depPaths.sort(depCountSorter)
|
||||
const unresolvedDepPaths = new Set(depPaths.values())
|
||||
let currentDepPaths = [...depPaths].sort(depCountSorter)
|
||||
|
||||
while (currentDepPaths.length) {
|
||||
const depPath1 = currentDepPaths.pop()!
|
||||
@@ -179,7 +178,7 @@ function deduplicateDepPaths<T extends PartialResolvedPackage> (
|
||||
}
|
||||
|
||||
if (unresolvedDepPaths.size) {
|
||||
remainingDuplicates.push([...unresolvedDepPaths])
|
||||
remainingDuplicates.push(unresolvedDepPaths)
|
||||
}
|
||||
}
|
||||
return {
|
||||
@@ -195,11 +194,16 @@ function isCompatibleAndHasMoreDeps<T extends PartialResolvedPackage> (
|
||||
) {
|
||||
const node1 = depGraph[depPath1]
|
||||
const node2 = depGraph[depPath2]
|
||||
const node1DepPaths = Object.values(node1.children)
|
||||
if (nodeDepsCount(node1) < nodeDepsCount(node2)) return false
|
||||
|
||||
const node1DepPathsSet = new Set(Object.values(node1.children))
|
||||
const node2DepPaths = Object.values(node2.children)
|
||||
return nodeDepsCount(node1) > nodeDepsCount(node2) &&
|
||||
node2DepPaths.every((depPath) => node1DepPaths.includes(depPath)) &&
|
||||
node2.resolvedPeerNames.every((depPath) => node1.resolvedPeerNames.includes(depPath))
|
||||
if (!node2DepPaths.every((depPath) => node1DepPathsSet.has(depPath))) return false
|
||||
|
||||
for (const depPath of node2.resolvedPeerNames) {
|
||||
if (!node1.resolvedPeerNames.has(depPath)) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function getRootPkgsByName<T extends PartialResolvedPackage> (dependenciesTree: DependenciesTree<T>, projects: ProjectToResolve[]) {
|
||||
@@ -219,7 +223,7 @@ function createPkgsByName<T extends PartialResolvedPackage> (
|
||||
.keys(directNodeIdsByAlias)
|
||||
.map((alias) => ({
|
||||
alias,
|
||||
node: dependenciesTree[directNodeIdsByAlias[alias]],
|
||||
node: dependenciesTree.get(directNodeIdsByAlias[alias])!,
|
||||
nodeId: directNodeIdsByAlias[alias],
|
||||
}))
|
||||
)
|
||||
@@ -241,20 +245,20 @@ function createPkgsByName<T extends PartialResolvedPackage> (
|
||||
|
||||
interface PeersCacheItem {
|
||||
depPath: string
|
||||
resolvedPeers: Array<[string, string]>
|
||||
missingPeers: string[]
|
||||
resolvedPeers: Map<string, string>
|
||||
missingPeers: Set<string>
|
||||
}
|
||||
|
||||
type PeersCache = Map<string, PeersCacheItem[]>
|
||||
|
||||
interface PeersResolution {
|
||||
missingPeers: string[]
|
||||
resolvedPeers: Record<string, string>
|
||||
missingPeers: Set<string>
|
||||
resolvedPeers: Map<string, string>
|
||||
}
|
||||
|
||||
interface ResolvePeersContext {
|
||||
pathsByNodeId: { [nodeId: string]: string }
|
||||
depPathsByPkgId?: Record<string, string[]>
|
||||
pathsByNodeId: Map<string, string>
|
||||
depPathsByPkgId?: Map<string, Set<string>>
|
||||
}
|
||||
|
||||
function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
@@ -271,16 +275,16 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
lockfileDir: string
|
||||
}
|
||||
): PeersResolution {
|
||||
const node = ctx.dependenciesTree[nodeId]
|
||||
if (node.depth === -1) return { resolvedPeers: {}, missingPeers: [] }
|
||||
const node = ctx.dependenciesTree.get(nodeId)!
|
||||
if (node.depth === -1) return { resolvedPeers: new Map<string, string>(), missingPeers: new Set<string>() }
|
||||
const resolvedPackage = node.resolvedPackage as T
|
||||
if (
|
||||
ctx.purePkgs.has(resolvedPackage.depPath) &&
|
||||
ctx.depGraph[resolvedPackage.depPath].depth <= node.depth &&
|
||||
Object.keys(resolvedPackage.peerDependencies).length === 0
|
||||
) {
|
||||
ctx.pathsByNodeId[nodeId] = resolvedPackage.depPath
|
||||
return { resolvedPeers: {}, missingPeers: [] }
|
||||
ctx.pathsByNodeId.set(nodeId, resolvedPackage.depPath)
|
||||
return { resolvedPeers: new Map<string, string>(), missingPeers: new Set<string>() }
|
||||
}
|
||||
if (typeof node.children === 'function') {
|
||||
node.children = node.children()
|
||||
@@ -293,36 +297,39 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
toPkgByName(
|
||||
Object.entries(children).map(([alias, nodeId]) => ({
|
||||
alias,
|
||||
node: ctx.dependenciesTree[nodeId],
|
||||
node: ctx.dependenciesTree.get(nodeId)!,
|
||||
nodeId,
|
||||
}))
|
||||
)
|
||||
)
|
||||
const hit = ctx.peersCache.get(resolvedPackage.depPath)?.find((cache) =>
|
||||
cache.resolvedPeers
|
||||
.every(([name, cachedNodeId]) => {
|
||||
const parentPkgNodeId = parentPkgs[name]?.nodeId
|
||||
if (!parentPkgNodeId || !cachedNodeId) return false
|
||||
if (parentPkgNodeId === cachedNodeId) return true
|
||||
if (
|
||||
ctx.pathsByNodeId[cachedNodeId] &&
|
||||
ctx.pathsByNodeId[cachedNodeId] === ctx.pathsByNodeId[parentPkgNodeId]
|
||||
) return true
|
||||
if (!ctx.dependenciesTree[parentPkgNodeId] && parentPkgNodeId.startsWith('link:')) {
|
||||
return false
|
||||
}
|
||||
const parentDepPath = (ctx.dependenciesTree[parentPkgNodeId].resolvedPackage as T).depPath
|
||||
if (!ctx.purePkgs.has(parentDepPath)) return false
|
||||
const cachedDepPath = (ctx.dependenciesTree[cachedNodeId].resolvedPackage as T).depPath
|
||||
return parentDepPath === cachedDepPath
|
||||
}) && cache.missingPeers.every((missingPeer) => !parentPkgs[missingPeer])
|
||||
)
|
||||
const hit = ctx.peersCache.get(resolvedPackage.depPath)?.find((cache) => {
|
||||
for (const [name, cachedNodeId] of cache.resolvedPeers) {
|
||||
const parentPkgNodeId = parentPkgs[name]?.nodeId
|
||||
if (!parentPkgNodeId || !cachedNodeId) return false
|
||||
if (parentPkgNodeId === cachedNodeId) continue
|
||||
if (
|
||||
ctx.pathsByNodeId.has(cachedNodeId) &&
|
||||
ctx.pathsByNodeId.get(cachedNodeId) === ctx.pathsByNodeId.get(parentPkgNodeId)
|
||||
) continue
|
||||
if (!ctx.dependenciesTree.has(parentPkgNodeId) && parentPkgNodeId.startsWith('link:')) {
|
||||
return false
|
||||
}
|
||||
const parentDepPath = (ctx.dependenciesTree.get(parentPkgNodeId)!.resolvedPackage as T).depPath
|
||||
if (!ctx.purePkgs.has(parentDepPath)) return false
|
||||
const cachedDepPath = (ctx.dependenciesTree.get(cachedNodeId)!.resolvedPackage as T).depPath
|
||||
if (parentDepPath !== cachedDepPath) return false
|
||||
}
|
||||
for (const missingPeer of cache.missingPeers) {
|
||||
if (parentPkgs[missingPeer]) return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
if (hit != null) {
|
||||
ctx.pathsByNodeId[nodeId] = hit.depPath
|
||||
ctx.pathsByNodeId.set(nodeId, hit.depPath)
|
||||
ctx.depGraph[hit.depPath].depth = Math.min(ctx.depGraph[hit.depPath].depth, node.depth)
|
||||
return {
|
||||
missingPeers: hit.missingPeers,
|
||||
resolvedPeers: Object.fromEntries(hit.resolvedPeers),
|
||||
resolvedPeers: hit.resolvedPeers,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +339,7 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
} = resolvePeersOfChildren(children, parentPkgs, ctx)
|
||||
|
||||
const { resolvedPeers, missingPeers } = Object.keys(resolvedPackage.peerDependencies).length === 0
|
||||
? { resolvedPeers: {}, missingPeers: [] }
|
||||
? { resolvedPeers: new Map<string, string>(), missingPeers: new Set<string>() }
|
||||
: _resolvePeers({
|
||||
currentDepth: node.depth,
|
||||
dependenciesTree: ctx.dependenciesTree,
|
||||
@@ -344,16 +351,26 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
rootDir: ctx.rootDir,
|
||||
})
|
||||
|
||||
const allResolvedPeers = Object.assign(unknownResolvedPeersOfChildren, resolvedPeers)
|
||||
delete allResolvedPeers[node.resolvedPackage.name]
|
||||
const allMissingPeers = Array.from(new Set([...missingPeersOfChildren, ...missingPeers]))
|
||||
const allResolvedPeers = unknownResolvedPeersOfChildren
|
||||
for (const [k, v] of resolvedPeers) {
|
||||
allResolvedPeers.set(k, v)
|
||||
}
|
||||
allResolvedPeers.delete(node.resolvedPackage.name)
|
||||
|
||||
const allMissingPeers = new Set<string>()
|
||||
for (const peer of missingPeersOfChildren) {
|
||||
allMissingPeers.add(peer)
|
||||
}
|
||||
for (const peer of missingPeers) {
|
||||
allMissingPeers.add(peer)
|
||||
}
|
||||
|
||||
let depPath: string
|
||||
if (Object.keys(allResolvedPeers).length === 0) {
|
||||
if (allResolvedPeers.size === 0) {
|
||||
depPath = resolvedPackage.depPath
|
||||
} else {
|
||||
const peersFolderSuffix = createPeersFolderSuffix(
|
||||
Object.entries(allResolvedPeers)
|
||||
[...allResolvedPeers.entries()]
|
||||
.map(([alias, nodeId]) => {
|
||||
if (nodeId.startsWith('link:')) {
|
||||
const linkedDir = nodeId.slice(5)
|
||||
@@ -362,7 +379,7 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
version: filenamify(linkedDir, { replacement: '+' }),
|
||||
}
|
||||
}
|
||||
const { name, version } = ctx.dependenciesTree[nodeId].resolvedPackage
|
||||
const { name, version } = ctx.dependenciesTree.get(nodeId)!.resolvedPackage
|
||||
return { name, version }
|
||||
})
|
||||
)
|
||||
@@ -370,14 +387,14 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
}
|
||||
const localLocation = path.join(ctx.virtualStoreDir, depPathToFilename(depPath))
|
||||
const modules = path.join(localLocation, 'node_modules')
|
||||
const isPure = Object.keys(allResolvedPeers).length === 0 && allMissingPeers.length === 0
|
||||
const isPure = allResolvedPeers.size === 0 && allMissingPeers.size === 0
|
||||
if (isPure) {
|
||||
ctx.purePkgs.add(resolvedPackage.depPath)
|
||||
} else {
|
||||
const cache = {
|
||||
missingPeers: allMissingPeers,
|
||||
depPath,
|
||||
resolvedPeers: Object.entries(allResolvedPeers),
|
||||
resolvedPeers: allResolvedPeers,
|
||||
}
|
||||
if (ctx.peersCache.has(resolvedPackage.depPath)) {
|
||||
ctx.peersCache.get(resolvedPackage.depPath)!.push(cache)
|
||||
@@ -386,13 +403,13 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
}
|
||||
}
|
||||
|
||||
ctx.pathsByNodeId[nodeId] = depPath
|
||||
ctx.pathsByNodeId.set(nodeId, depPath)
|
||||
if (ctx.depPathsByPkgId != null) {
|
||||
if (!ctx.depPathsByPkgId[resolvedPackage.depPath]) {
|
||||
ctx.depPathsByPkgId[resolvedPackage.depPath] = []
|
||||
if (!ctx.depPathsByPkgId.has(resolvedPackage.depPath)) {
|
||||
ctx.depPathsByPkgId.set(resolvedPackage.depPath, new Set())
|
||||
}
|
||||
if (!ctx.depPathsByPkgId[resolvedPackage.depPath].includes(depPath)) {
|
||||
ctx.depPathsByPkgId[resolvedPackage.depPath].push(depPath)
|
||||
if (!ctx.depPathsByPkgId.get(resolvedPackage.depPath)!.has(depPath)) {
|
||||
ctx.depPathsByPkgId.get(resolvedPackage.depPath)!.add(depPath)
|
||||
}
|
||||
}
|
||||
const peerDependencies = { ...resolvedPackage.peerDependencies }
|
||||
@@ -400,15 +417,14 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
const dir = path.join(modules, resolvedPackage.name)
|
||||
|
||||
const transitivePeerDependencies = new Set<string>()
|
||||
const unknownPeers = [
|
||||
...Object.keys(unknownResolvedPeersOfChildren),
|
||||
...missingPeersOfChildren,
|
||||
]
|
||||
if (unknownPeers.length > 0) {
|
||||
for (const unknownPeer of unknownPeers) {
|
||||
if (!peerDependencies[unknownPeer]) {
|
||||
transitivePeerDependencies.add(unknownPeer)
|
||||
}
|
||||
for (const unknownPeer of unknownResolvedPeersOfChildren.keys()) {
|
||||
if (!peerDependencies[unknownPeer]) {
|
||||
transitivePeerDependencies.add(unknownPeer)
|
||||
}
|
||||
}
|
||||
for (const unknownPeer of missingPeersOfChildren) {
|
||||
if (!peerDependencies[unknownPeer]) {
|
||||
transitivePeerDependencies.add(unknownPeer)
|
||||
}
|
||||
}
|
||||
ctx.depGraph[depPath] = {
|
||||
@@ -416,7 +432,7 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
children: Object.assign(
|
||||
getPreviouslyResolvedChildren(nodeId, ctx.dependenciesTree),
|
||||
children,
|
||||
resolvedPeers
|
||||
Object.fromEntries(resolvedPeers.entries())
|
||||
),
|
||||
depPath,
|
||||
depth: node.depth,
|
||||
@@ -426,7 +442,7 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
modules,
|
||||
peerDependencies,
|
||||
transitivePeerDependencies,
|
||||
resolvedPeerNames: Object.keys(allResolvedPeers),
|
||||
resolvedPeerNames: new Set(allResolvedPeers.keys()),
|
||||
}
|
||||
}
|
||||
return { resolvedPeers: allResolvedPeers, missingPeers: allMissingPeers }
|
||||
@@ -449,7 +465,7 @@ function getPreviouslyResolvedChildren<T extends PartialResolvedPackage> (nodeId
|
||||
nodeIdChunks.pop()
|
||||
nodeIdChunks.reduce((accNodeId, part) => {
|
||||
accNodeId += `>${part}>${ownId}`
|
||||
const parentNode = dependenciesTree[`${accNodeId}>`]
|
||||
const parentNode = dependenciesTree.get(`${accNodeId}>`)!
|
||||
if (typeof parentNode.children === 'function') {
|
||||
parentNode.children = parentNode.children()
|
||||
}
|
||||
@@ -478,18 +494,27 @@ function resolvePeersOfChildren<T extends PartialResolvedPackage> (
|
||||
lockfileDir: string
|
||||
}
|
||||
): PeersResolution {
|
||||
const allResolvedPeers: Record<string, string> = {}
|
||||
const allResolvedPeers = new Map<string, string>()
|
||||
const allMissingPeers = new Set<string>()
|
||||
|
||||
for (const childNodeId of Object.values(children)) {
|
||||
const { resolvedPeers, missingPeers } = resolvePeersOfNode(childNodeId, parentPkgs, ctx)
|
||||
Object.assign(allResolvedPeers, resolvedPeers)
|
||||
missingPeers.forEach((missingPeer) => allMissingPeers.add(missingPeer))
|
||||
for (const [k, v] of resolvedPeers) {
|
||||
allResolvedPeers.set(k, v)
|
||||
}
|
||||
for (const missingPeer of missingPeers) {
|
||||
allMissingPeers.add(missingPeer)
|
||||
}
|
||||
}
|
||||
|
||||
const unknownResolvedPeersOfChildren: Record<string, string> = pickBy((_, alias) => !children[alias], allResolvedPeers)
|
||||
const unknownResolvedPeersOfChildren = new Map<string, string>()
|
||||
for (const [alias, v] of allResolvedPeers) {
|
||||
if (!children[alias]) {
|
||||
unknownResolvedPeersOfChildren.set(alias, v)
|
||||
}
|
||||
}
|
||||
|
||||
return { resolvedPeers: unknownResolvedPeersOfChildren, missingPeers: Array.from(allMissingPeers) }
|
||||
return { resolvedPeers: unknownResolvedPeersOfChildren, missingPeers: allMissingPeers }
|
||||
}
|
||||
|
||||
function _resolvePeers<T extends PartialResolvedPackage> (
|
||||
@@ -504,8 +529,8 @@ function _resolvePeers<T extends PartialResolvedPackage> (
|
||||
peerDependencyIssues: Pick<PeerDependencyIssues, 'bad' | 'missing'>
|
||||
}
|
||||
): PeersResolution {
|
||||
const resolvedPeers: { [alias: string]: string } = {}
|
||||
const missingPeers = []
|
||||
const resolvedPeers = new Map<string, string>()
|
||||
const missingPeers = new Set<string>()
|
||||
for (const peerName in ctx.resolvedPackage.peerDependencies) { // eslint-disable-line:forin
|
||||
const peerVersionRange = ctx.resolvedPackage.peerDependencies[peerName].replace(/^workspace:/, '')
|
||||
|
||||
@@ -513,7 +538,7 @@ function _resolvePeers<T extends PartialResolvedPackage> (
|
||||
const optionalPeer = ctx.resolvedPackage.peerDependenciesMeta?.[peerName]?.optional === true
|
||||
|
||||
if (!resolved) {
|
||||
missingPeers.push(peerName)
|
||||
missingPeers.add(peerName)
|
||||
const location = getLocationFromNodeIdAndPkg({
|
||||
dependenciesTree: ctx.dependenciesTree,
|
||||
nodeId: ctx.nodeId,
|
||||
@@ -554,7 +579,7 @@ function _resolvePeers<T extends PartialResolvedPackage> (
|
||||
})
|
||||
}
|
||||
|
||||
if (resolved?.nodeId) resolvedPeers[peerName] = resolved.nodeId
|
||||
if (resolved?.nodeId) resolvedPeers.set(peerName, resolved.nodeId)
|
||||
}
|
||||
return { resolvedPeers, missingPeers }
|
||||
}
|
||||
@@ -590,7 +615,8 @@ function getLocationFromNodeId<T> (
|
||||
const parts = splitNodeId(nodeId).slice(0, -1)
|
||||
const parents = scan((prevNodeId, pkgId) => createNodeId(prevNodeId, pkgId), '>', parts)
|
||||
.slice(2)
|
||||
.map((nid) => pick(['name', 'version'], dependenciesTree[nid].resolvedPackage as ResolvedPackage))
|
||||
|
||||
.map((nid) => pick(['name', 'version'], dependenciesTree.get(nid)!.resolvedPackage as ResolvedPackage))
|
||||
return {
|
||||
projectId: parts[0],
|
||||
parents,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { resolvePeers } from '../lib/resolvePeers'
|
||||
import { type PartialResolvedPackage, resolvePeers } from '../lib/resolvePeers'
|
||||
import { type DependenciesTreeNode } from '../lib/resolveDependencies'
|
||||
|
||||
test('packages are not deduplicated when versions do not match', () => {
|
||||
const fooPkg = {
|
||||
const fooPkg: PartialResolvedPackage = {
|
||||
name: 'foo',
|
||||
version: '1.0.0',
|
||||
depPath: 'foo/1.0.0',
|
||||
@@ -16,7 +17,7 @@ test('packages are not deduplicated when versions do not match', () => {
|
||||
},
|
||||
}
|
||||
|
||||
const peers = Object.fromEntries(
|
||||
const peers: Record<string, PartialResolvedPackage> = Object.fromEntries(
|
||||
[
|
||||
['bar', '1.0.0'],
|
||||
['bar', '2.0.0'],
|
||||
@@ -29,7 +30,7 @@ test('packages are not deduplicated when versions do not match', () => {
|
||||
version,
|
||||
depPath: `${name}/${version}`,
|
||||
peerDependencies: {},
|
||||
},
|
||||
} satisfies PartialResolvedPackage,
|
||||
])
|
||||
)
|
||||
|
||||
@@ -74,7 +75,7 @@ test('packages are not deduplicated when versions do not match', () => {
|
||||
id: 'project4',
|
||||
},
|
||||
],
|
||||
dependenciesTree: Object.fromEntries([
|
||||
dependenciesTree: new Map<string, DependenciesTreeNode<PartialResolvedPackage>>(([
|
||||
['>project1>foo/1.0.0>', fooPkg],
|
||||
['>project1>bar/1.0.0>', peers.bar_1_0_0],
|
||||
|
||||
@@ -89,12 +90,12 @@ test('packages are not deduplicated when versions do not match', () => {
|
||||
['>project4>bar/2.0.0>', peers.bar_2_0_0],
|
||||
['>project4>baz/2.0.0>', peers.baz_2_0_0],
|
||||
|
||||
].map(([path, resolvedPackage]) => [path, {
|
||||
] satisfies Array<[string, PartialResolvedPackage]>).map(([path, resolvedPackage]) => [path, {
|
||||
children: {},
|
||||
installable: {},
|
||||
resolvedPackage,
|
||||
depth: 0,
|
||||
}])),
|
||||
} as DependenciesTreeNode<PartialResolvedPackage>])),
|
||||
dedupePeerDependents: true,
|
||||
virtualStoreDir: '',
|
||||
lockfileDir: '',
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/// <reference path="../../../__typings__/index.d.ts" />
|
||||
import { resolvePeers } from '../lib/resolvePeers'
|
||||
import { type PartialResolvedPackage, resolvePeers } from '../lib/resolvePeers'
|
||||
import { type DependenciesTreeNode } from '../lib/resolveDependencies'
|
||||
|
||||
test('resolve peer dependencies of cyclic dependencies', () => {
|
||||
const fooPkg = {
|
||||
@@ -31,24 +32,24 @@ test('resolve peer dependencies of cyclic dependencies', () => {
|
||||
id: '',
|
||||
},
|
||||
],
|
||||
dependenciesTree: {
|
||||
'>foo/1.0.0>': {
|
||||
dependenciesTree: new Map<string, DependenciesTreeNode<PartialResolvedPackage>>([
|
||||
['>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>': {
|
||||
}],
|
||||
['>foo/1.0.0>bar/1.0.0>', {
|
||||
children: {
|
||||
qar: '>foo/1.0.0>bar/1.0.0>qar/1.0.0>',
|
||||
},
|
||||
installable: true,
|
||||
resolvedPackage: barPkg,
|
||||
depth: 1,
|
||||
},
|
||||
'>foo/1.0.0>bar/1.0.0>qar/1.0.0>': {
|
||||
}],
|
||||
['>foo/1.0.0>bar/1.0.0>qar/1.0.0>', {
|
||||
children: {
|
||||
zoo: '>foo/1.0.0>bar/1.0.0>qar/1.0.0>zoo/1.0.0>',
|
||||
},
|
||||
@@ -63,8 +64,8 @@ test('resolve peer dependencies of cyclic dependencies', () => {
|
||||
},
|
||||
},
|
||||
depth: 2,
|
||||
},
|
||||
'>foo/1.0.0>bar/1.0.0>qar/1.0.0>zoo/1.0.0>': {
|
||||
}],
|
||||
['>foo/1.0.0>bar/1.0.0>qar/1.0.0>zoo/1.0.0>', {
|
||||
children: {
|
||||
foo: '>foo/1.0.0>bar/1.0.0>qar/1.0.0>zoo/1.0.0>foo/1.0.0>',
|
||||
bar: '>foo/1.0.0>bar/1.0.0>qar/1.0.0>zoo/1.0.0>bar/1.0.0>',
|
||||
@@ -79,20 +80,20 @@ test('resolve peer dependencies of cyclic dependencies', () => {
|
||||
},
|
||||
},
|
||||
depth: 3,
|
||||
},
|
||||
'>foo/1.0.0>bar/1.0.0>qar/1.0.0>zoo/1.0.0>foo/1.0.0>': {
|
||||
}],
|
||||
['>foo/1.0.0>bar/1.0.0>qar/1.0.0>zoo/1.0.0>foo/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: fooPkg,
|
||||
depth: 4,
|
||||
},
|
||||
'>foo/1.0.0>bar/1.0.0>qar/1.0.0>zoo/1.0.0>bar/1.0.0>': {
|
||||
}],
|
||||
['>foo/1.0.0>bar/1.0.0>qar/1.0.0>zoo/1.0.0>bar/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: barPkg,
|
||||
depth: 4,
|
||||
},
|
||||
},
|
||||
}],
|
||||
]),
|
||||
virtualStoreDir: '',
|
||||
lockfileDir: '',
|
||||
})
|
||||
@@ -139,22 +140,22 @@ test('when a package is referenced twice in the dependencies graph and one of th
|
||||
id: '',
|
||||
},
|
||||
],
|
||||
dependenciesTree: {
|
||||
'>zoo/1.0.0>': {
|
||||
dependenciesTree: new Map<string, DependenciesTreeNode<PartialResolvedPackage>>([
|
||||
['>zoo/1.0.0>', {
|
||||
children: {
|
||||
foo: '>zoo/1.0.0>foo/1.0.0>',
|
||||
},
|
||||
installable: true,
|
||||
resolvedPackage: zooPkg,
|
||||
depth: 0,
|
||||
},
|
||||
'>zoo/1.0.0>foo/1.0.0>': {
|
||||
}],
|
||||
['>zoo/1.0.0>foo/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: fooPkg,
|
||||
depth: 1,
|
||||
},
|
||||
'>bar/1.0.0>': {
|
||||
}],
|
||||
['>bar/1.0.0>', {
|
||||
children: {
|
||||
zoo: '>bar/1.0.0>zoo/1.0.0>',
|
||||
qar: '>bar/1.0.0>qar/1.0.0>',
|
||||
@@ -162,22 +163,22 @@ test('when a package is referenced twice in the dependencies graph and one of th
|
||||
installable: true,
|
||||
resolvedPackage: barPkg,
|
||||
depth: 0,
|
||||
},
|
||||
'>bar/1.0.0>zoo/1.0.0>': {
|
||||
}],
|
||||
['>bar/1.0.0>zoo/1.0.0>', {
|
||||
children: {
|
||||
foo: '>bar/1.0.0>zoo/1.0.0>foo/1.0.0>',
|
||||
},
|
||||
installable: true,
|
||||
resolvedPackage: zooPkg,
|
||||
depth: 1,
|
||||
},
|
||||
'>bar/1.0.0>zoo/1.0.0>foo/1.0.0>': {
|
||||
}],
|
||||
['>bar/1.0.0>zoo/1.0.0>foo/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: fooPkg,
|
||||
depth: 2,
|
||||
},
|
||||
'>bar/1.0.0>qar/1.0.0>': {
|
||||
}],
|
||||
['>bar/1.0.0>qar/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: {
|
||||
@@ -187,8 +188,8 @@ test('when a package is referenced twice in the dependencies graph and one of th
|
||||
peerDependencies: {},
|
||||
},
|
||||
depth: 1,
|
||||
},
|
||||
},
|
||||
}],
|
||||
]),
|
||||
virtualStoreDir: '',
|
||||
lockfileDir: '',
|
||||
})
|
||||
@@ -308,68 +309,68 @@ describe('peer dependency issues', () => {
|
||||
id: 'project6',
|
||||
},
|
||||
],
|
||||
dependenciesTree: {
|
||||
'>project1>foo/1.0.0>': {
|
||||
dependenciesTree: new Map<string, DependenciesTreeNode<PartialResolvedPackage>>([
|
||||
['>project1>foo/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: fooPkg,
|
||||
depth: 0,
|
||||
},
|
||||
'>project2>bar/1.0.0>': {
|
||||
}],
|
||||
['>project2>bar/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: barPkg,
|
||||
depth: 0,
|
||||
},
|
||||
'>project3>foo/1.0.0>': {
|
||||
}],
|
||||
['>project3>foo/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: fooPkg,
|
||||
depth: 0,
|
||||
},
|
||||
'>project3>bar/1.0.0>': {
|
||||
}],
|
||||
['>project3>bar/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: barPkg,
|
||||
depth: 0,
|
||||
},
|
||||
'>project4>bar/1.0.0>': {
|
||||
}],
|
||||
['>project4>bar/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: barPkg,
|
||||
depth: 0,
|
||||
},
|
||||
'>project4>qar/1.0.0>': {
|
||||
}],
|
||||
['>project4>qar/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: qarPkg,
|
||||
depth: 0,
|
||||
},
|
||||
'>project5>foo/1.0.0>': {
|
||||
}],
|
||||
['>project5>foo/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: fooPkg,
|
||||
depth: 0,
|
||||
},
|
||||
'>project5>bar/2.0.0>': {
|
||||
}],
|
||||
['>project5>bar/2.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: barWithOptionalPeer,
|
||||
depth: 0,
|
||||
},
|
||||
'>project6>foo/2.0.0>': {
|
||||
}],
|
||||
['>project6>foo/2.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: fooWithOptionalPeer,
|
||||
depth: 0,
|
||||
},
|
||||
'>project6>bar/2.0.0>': {
|
||||
}],
|
||||
['>project6>bar/2.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: barWithOptionalPeer,
|
||||
depth: 0,
|
||||
},
|
||||
},
|
||||
}],
|
||||
]),
|
||||
virtualStoreDir: '',
|
||||
lockfileDir: '',
|
||||
})
|
||||
@@ -408,8 +409,8 @@ describe('unmet peer dependency issues', () => {
|
||||
id: 'project1',
|
||||
},
|
||||
],
|
||||
dependenciesTree: {
|
||||
'>project1>foo/1.0.0>': {
|
||||
dependenciesTree: new Map<string, DependenciesTreeNode<PartialResolvedPackage>>([
|
||||
['>project1>foo/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: {
|
||||
@@ -422,8 +423,8 @@ describe('unmet peer dependency issues', () => {
|
||||
},
|
||||
},
|
||||
depth: 0,
|
||||
},
|
||||
'>project1>peer1/1.0.0-rc.0>': {
|
||||
}],
|
||||
['>project1>peer1/1.0.0-rc.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: {
|
||||
@@ -433,8 +434,8 @@ describe('unmet peer dependency issues', () => {
|
||||
peerDependencies: {},
|
||||
},
|
||||
depth: 0,
|
||||
},
|
||||
'>project1>peer2/1.1.0-rc.0>': {
|
||||
}],
|
||||
['>project1>peer2/1.1.0-rc.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: {
|
||||
@@ -444,8 +445,8 @@ describe('unmet peer dependency issues', () => {
|
||||
peerDependencies: {},
|
||||
},
|
||||
depth: 0,
|
||||
},
|
||||
},
|
||||
}],
|
||||
]),
|
||||
virtualStoreDir: '',
|
||||
lockfileDir: '',
|
||||
})
|
||||
@@ -469,8 +470,8 @@ describe('unmet peer dependency issue resolved from subdependency', () => {
|
||||
id: 'project',
|
||||
},
|
||||
],
|
||||
dependenciesTree: {
|
||||
'>project>foo/1.0.0>': {
|
||||
dependenciesTree: new Map<string, DependenciesTreeNode<PartialResolvedPackage>>([
|
||||
['>project>foo/1.0.0>', {
|
||||
children: {
|
||||
dep: '>project>foo/1.0.0>dep/1.0.0>',
|
||||
bar: '>project>foo/1.0.0>bar/1.0.0>',
|
||||
@@ -483,8 +484,8 @@ describe('unmet peer dependency issue resolved from subdependency', () => {
|
||||
peerDependencies: {},
|
||||
},
|
||||
depth: 0,
|
||||
},
|
||||
'>project>foo/1.0.0>dep/1.0.0>': {
|
||||
}],
|
||||
['>project>foo/1.0.0>dep/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: {
|
||||
@@ -494,8 +495,8 @@ describe('unmet peer dependency issue resolved from subdependency', () => {
|
||||
peerDependencies: {},
|
||||
},
|
||||
depth: 1,
|
||||
},
|
||||
'>project>foo/1.0.0>bar/1.0.0>': {
|
||||
}],
|
||||
['>project>foo/1.0.0>bar/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: {
|
||||
@@ -507,8 +508,8 @@ describe('unmet peer dependency issue resolved from subdependency', () => {
|
||||
},
|
||||
},
|
||||
depth: 1,
|
||||
},
|
||||
},
|
||||
}],
|
||||
]),
|
||||
virtualStoreDir: '',
|
||||
lockfileDir: '',
|
||||
})
|
||||
@@ -560,48 +561,48 @@ test('resolve peer dependencies with npm aliases', () => {
|
||||
id: '',
|
||||
},
|
||||
],
|
||||
dependenciesTree: {
|
||||
'>foo/1.0.0>': {
|
||||
dependenciesTree: new Map<string, DependenciesTreeNode<PartialResolvedPackage>>([
|
||||
['>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>': {
|
||||
}],
|
||||
['>foo/1.0.0>bar/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: barPkg,
|
||||
depth: 1,
|
||||
},
|
||||
'>foo/2.0.0>': {
|
||||
}],
|
||||
['>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>': {
|
||||
}],
|
||||
['>foo/2.0.0>bar/2.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: barAliasPkg,
|
||||
depth: 1,
|
||||
},
|
||||
'>bar/1.0.0>': {
|
||||
}],
|
||||
['>bar/1.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: barPkg,
|
||||
depth: 0,
|
||||
},
|
||||
'>bar/2.0.0>': {
|
||||
}],
|
||||
['>bar/2.0.0>', {
|
||||
children: {},
|
||||
installable: true,
|
||||
resolvedPackage: barAliasPkg,
|
||||
depth: 0,
|
||||
},
|
||||
},
|
||||
}],
|
||||
]),
|
||||
virtualStoreDir: '',
|
||||
lockfileDir: '',
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user