@vltpkg/graph
Advanced tools
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"append-nodes.d.ts","sourceRoot":"","sources":["../../src/ideal/append-nodes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAE3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAE7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAQ/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAG7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EACpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAE7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAS7D,OAAO,KAAK,EAKV,eAAe,EACf,kBAAkB,EACnB,MAAM,YAAY,CAAA;AAylBnB;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,WAAW,gBACT,iBAAiB,SACvB,KAAK,YACF,IAAI,QACR,UAAU,EAAE,UACV,UAAU,WACT,WAAW,QACd,GAAG,CAAC,KAAK,CAAC,QACV,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,cACjB,aAAa,iBACV,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,oBAC7B,OAAO,CAAC,aAAa,CAAC,EAAE,WACjC,KAAK,kBACE,GAAG,CAAC,KAAK,CAAC,YAChB,cAAc,iBACT,eAAe,oBACZ,kBAAkB,kBAqLrC,CAAA"} | ||
| {"version":3,"file":"append-nodes.d.ts","sourceRoot":"","sources":["../../src/ideal/append-nodes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAE3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAE7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAQ/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAG7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EACpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAE7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAS7D,OAAO,KAAK,EAKV,eAAe,EACf,kBAAkB,EACnB,MAAM,YAAY,CAAA;AA+mBnB;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,WAAW,gBACT,iBAAiB,SACvB,KAAK,YACF,IAAI,QACR,UAAU,EAAE,UACV,UAAU,WACT,WAAW,QACd,GAAG,CAAC,KAAK,CAAC,QACV,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,cACjB,aAAa,iBACV,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,oBAC7B,OAAO,CAAC,aAAa,CAAC,EAAE,WACjC,KAAK,kBACE,GAAG,CAAC,KAAK,CAAC,YAChB,cAAc,iBACT,eAAe,oBACZ,kBAAkB,kBAqLrC,CAAA"} |
@@ -50,4 +50,33 @@ import { joinDepIDTuple, joinExtra } from '@vltpkg/dep-id'; | ||
| const findCompatibleResolution = (spec, fromNode, graph, peerContext, queryModifier, _peer) => { | ||
| const candidates = graph.nodesByName.get(spec.final.name); | ||
| let existingNode = graph.findResolution(spec, fromNode, queryModifier); | ||
| // Hoist invariants once | ||
| const fromLoc = fromNode.location; | ||
| const projectRoot = graph.projectRoot; | ||
| const monorepo = graph.monorepo; | ||
| const final = spec.final; | ||
| // Memoize satisfies() results per-node within this resolution attempt | ||
| const satisfiesCache = new Map(); | ||
| const satisfiesFinal = (n) => { | ||
| const key = n.id; | ||
| const cached = satisfiesCache.get(key); | ||
| /* c8 ignore next 3 - optimization: cache hit when same node checked multiple times */ | ||
| if (cached !== undefined) { | ||
| return cached; | ||
| } | ||
| const result = satisfies(key, final, fromLoc, projectRoot, monorepo); | ||
| satisfiesCache.set(key, result); | ||
| return result; | ||
| }; | ||
| // Prefer existing edge target if it satisfies the spec. | ||
| // This ensures lockfile resolutions are preserved when still valid, | ||
| // rather than potentially picking a different satisfying version. | ||
| const existingEdge = fromNode.edgesOut.get(spec.name); | ||
| let existingNode; | ||
| if (existingEdge?.to && | ||
| !existingEdge.to.detached && | ||
| satisfiesFinal(existingEdge.to)) { | ||
| existingNode = existingEdge.to; | ||
| } | ||
| else { | ||
| existingNode = graph.findResolution(spec, fromNode, queryModifier); | ||
| } | ||
| let peerCompatResult = existingNode ? | ||
@@ -57,20 +86,20 @@ checkPeerEdgesCompatible(existingNode, fromNode, peerContext, graph) | ||
| // CANDIDATE FALLBACK: If first candidate is peer-incompatible, try others | ||
| if (existingNode && | ||
| !peerCompatResult.compatible && | ||
| candidates && | ||
| candidates.size > 1) { | ||
| for (const candidate of candidates) { | ||
| if (candidate === existingNode) | ||
| continue; | ||
| if (candidate.detached) | ||
| continue; | ||
| if (!satisfies(candidate.id, spec.final, fromNode.location, graph.projectRoot, graph.monorepo)) { | ||
| continue; | ||
| // Lazy-load candidates only when fallback needed | ||
| if (existingNode && !peerCompatResult.compatible) { | ||
| const candidates = graph.nodesByName.get(final.name); | ||
| if (candidates && candidates.size > 1) { | ||
| for (const candidate of candidates) { | ||
| if (candidate === existingNode) | ||
| continue; | ||
| if (candidate.detached) | ||
| continue; | ||
| if (!satisfiesFinal(candidate)) | ||
| continue; | ||
| const compat = checkPeerEdgesCompatible(candidate, fromNode, peerContext, graph); | ||
| if (compat.compatible) { | ||
| existingNode = candidate; | ||
| peerCompatResult = compat; | ||
| break; | ||
| } | ||
| } | ||
| const compat = checkPeerEdgesCompatible(candidate, fromNode, peerContext, graph); | ||
| if (compat.compatible) { | ||
| existingNode = candidate; | ||
| peerCompatResult = compat; | ||
| break; | ||
| } | ||
| } | ||
@@ -77,0 +106,0 @@ } |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"append-nodes.js","sourceRoot":"","sources":["../../src/ideal/append-nodes.ts"],"names":[],"mappings":"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","sourcesContent":["import { joinDepIDTuple, joinExtra } from '@vltpkg/dep-id'\nimport type { DepID } from '@vltpkg/dep-id'\nimport { error } from '@vltpkg/error-cause'\nimport type { PackageInfoClient } from '@vltpkg/package-info'\nimport { Spec } from '@vltpkg/spec'\nimport type { SpecOptions } from '@vltpkg/spec'\nimport { satisfies } from '@vltpkg/satisfies'\nimport { longDependencyTypes, normalizeManifest } from '@vltpkg/types'\nimport type {\n DependencyTypeLong,\n DependencySaveType,\n Manifest,\n} from '@vltpkg/types'\nimport type { PathScurry } from 'path-scurry'\nimport { fixupAddedNames } from '../fixup-added-names.ts'\nimport { shorten } from '../dependencies.ts'\nimport type { Dependency } from '../dependencies.ts'\nimport type { Graph } from '../graph.ts'\nimport type { Node } from '../node.ts'\nimport { removeOptionalSubgraph } from '../remove-optional-subgraph.ts'\nimport type {\n GraphModifier,\n ModifierActiveEntry,\n} from '../modifiers.ts'\nimport type { ExtractResult } from '../reify/extract-node.ts'\nimport { extractNode } from '../reify/extract-node.ts'\nimport type { RollbackRemove } from '@vltpkg/rollback-remove'\nimport {\n checkPeerEdgesCompatible,\n endPeerPlacement,\n forkPeerContext,\n postPlacementPeerCheck,\n startPeerPlacement,\n} from './peers.ts'\nimport { compareByHasPeerDeps } from './sorting.ts'\nimport type {\n PeerContext,\n PeerContextEntryInput,\n AppendNodeEntry,\n ProcessPlacementResult,\n TransientAddMap,\n TransientRemoveMap,\n} from './types.ts'\n\ntype FileTypeInfo = {\n id: DepID\n path: string\n isDirectory: boolean\n}\n\n/**\n * Task for reusing an existing node (deferred edge creation).\n */\ntype ReuseTask = {\n type: DependencySaveType\n spec: Spec\n fromNode: Node\n toNode: Node\n}\n\n/**\n * Result of fetching manifests for dependencies.\n */\ntype FetchResult = {\n placementTasks: NodePlacementTask[]\n reuseTasks: ReuseTask[]\n forkRequests: PeerContextEntryInput[]\n}\n\n/**\n * Only install devDeps for git dependencies and importers\n * Everything else always gets installed\n */\nconst shouldInstallDepType = (\n node: Node,\n depType: DependencyTypeLong,\n) =>\n depType !== 'devDependencies' ||\n node.importer ||\n node.id.startsWith('git')\n\n/**\n * Retrieve the {@link DepID} and location for a `file:` type {@link Node}.\n */\nconst getFileTypeInfo = (\n spec: Spec,\n fromNode: Node,\n scurry: PathScurry,\n): FileTypeInfo | undefined => {\n const f = spec.final\n if (f.type !== 'file') return\n\n /* c8 ignore start - should be impossible */\n if (!f.file) {\n throw error('no path on file specifier', { spec })\n }\n /* c8 ignore stop */\n\n // Given that both linked folders and local tarballs (both defined with\n // usage of the `file:` spec prefix) location needs to be relative to their\n // parents, build the expected path and use it for both location and id\n const target = scurry.cwd.resolve(fromNode.location).resolve(f.file)\n const path = target.relativePosix()\n const id = joinDepIDTuple(['file', path])\n\n return {\n path,\n id,\n isDirectory: !!target.lstatSync()?.isDirectory(),\n }\n}\n\nconst isStringArray = (a: unknown): a is string[] =>\n Array.isArray(a) && !a.some(b => typeof b !== 'string')\n\n/**\n * Represents a manifest fetch operation with all the context needed.\n */\ntype ManifestFetchTask = {\n spec: Spec\n type: DependencySaveType\n fromNode: Node\n fileTypeInfo?: FileTypeInfo\n activeModifier?: ModifierActiveEntry\n queryModifier?: string\n edgeOptional: boolean\n manifestPromise: Promise<Manifest | undefined>\n depth: number\n peerContext: PeerContext\n}\n\n/**\n * Represents a node placement operation that depends on a resolved manifest.\n */\ntype NodePlacementTask = {\n fetchTask: ManifestFetchTask\n manifest: Manifest | undefined\n node?: Node\n childDeps?: Dependency[]\n childModifierRefs?: Map<string, ModifierActiveEntry>\n childPeerContext?: PeerContext\n}\n\n/**\n * Try to find a compatible resolution for a dependency, checking peer context.\n * If the first resolution candidate is incompatible with the peer context,\n * try other candidates.\n */\nconst findCompatibleResolution = (\n spec: Spec,\n fromNode: Node,\n graph: Graph,\n peerContext: PeerContext,\n queryModifier?: string,\n _peer?: boolean,\n) => {\n const candidates = graph.nodesByName.get(spec.final.name)\n let existingNode = graph.findResolution(\n spec,\n fromNode,\n queryModifier,\n )\n\n let peerCompatResult =\n existingNode ?\n checkPeerEdgesCompatible(\n existingNode,\n fromNode,\n peerContext,\n graph,\n )\n : { compatible: true }\n\n // CANDIDATE FALLBACK: If first candidate is peer-incompatible, try others\n if (\n existingNode &&\n !peerCompatResult.compatible &&\n candidates &&\n candidates.size > 1\n ) {\n for (const candidate of candidates) {\n if (candidate === existingNode) continue\n if (candidate.detached) continue\n if (\n !satisfies(\n candidate.id,\n spec.final,\n fromNode.location,\n graph.projectRoot,\n graph.monorepo,\n )\n ) {\n continue\n }\n\n const compat = checkPeerEdgesCompatible(\n candidate,\n fromNode,\n peerContext,\n graph,\n )\n if (compat.compatible) {\n existingNode = candidate\n peerCompatResult = compat\n break\n }\n }\n }\n\n return { existingNode, peerCompatResult }\n}\n\n/**\n * Fetch manifests for dependencies and create placement tasks.\n *\n * This is Phase 1 of the breadth-first graph building process. For each\n * dependency at the current level:\n * 1. Apply any active modifiers (spec swapping)\n * 2. Try to find an existing node to reuse (with peer compatibility check)\n * 3. If no reusable node, start a manifest fetch (in parallel)\n * 4. Create placement tasks for Phase 2\n *\n * The result is sorted to process non-peer-dependent packages first,\n * ensuring peer dependencies can resolve to already-placed siblings.\n *\n * **Read-only**: This function no longer mutates the graph. It returns\n * tasks that will be applied serially in the BFS loop for deterministic ordering.\n */\nconst fetchManifestsForDeps = async (\n packageInfo: PackageInfoClient,\n graph: Graph,\n fromNode: Node,\n deps: Dependency[],\n scurry: PathScurry,\n peerContext: PeerContext,\n modifierRefs?: Map<string, ModifierActiveEntry>,\n depth = 0,\n): Promise<FetchResult> => {\n const fetchTasks: ManifestFetchTask[] = []\n const placementTasks: NodePlacementTask[] = []\n const reuseTasks: ReuseTask[] = []\n const forkRequests: PeerContextEntryInput[] = []\n\n for (const { spec: originalSpec, type } of deps) {\n let spec = originalSpec\n const fileTypeInfo = getFileTypeInfo(spec, fromNode, scurry)\n const activeModifier = modifierRefs?.get(spec.name)\n\n // MODIFIER HANDLING: Swap spec if an edge modifier is fully matched\n // Example: `vlt install --override \"react:^19\"` changes react's spec\n const queryModifier = activeModifier?.modifier.query\n const completeModifier =\n activeModifier &&\n activeModifier.interactiveBreadcrumb.current ===\n activeModifier.modifier.breadcrumb.last\n if (\n queryModifier &&\n completeModifier &&\n 'spec' in activeModifier.modifier\n ) {\n spec = activeModifier.modifier.spec\n // bareSpec of '-' means \"remove this dependency\"\n if (spec.bareSpec === '-') {\n continue\n }\n }\n\n const peer = type === 'peer' || type === 'peerOptional'\n\n // NODE REUSE LOGIC with peer compatibility\n const { existingNode, peerCompatResult } =\n findCompatibleResolution(\n spec,\n fromNode,\n graph,\n peerContext,\n queryModifier,\n peer,\n )\n\n // Accumulate fork request if incompatible peer edges detected (defer actual fork)\n const effectivePeerContext = peerContext\n /* c8 ignore start */\n if (!peerCompatResult.compatible && peerCompatResult.forkEntry) {\n forkRequests.push(peerCompatResult.forkEntry)\n // All fork entries from this fromNode will be applied together in Phase B\n }\n /* c8 ignore stop */\n\n // defines what nodes are eligible to be reused\n const validExistingNode =\n existingNode &&\n !existingNode.detached &&\n // Regular deps can always reuse.\n // Peer deps can reuse as well if their peer edges are compatible.\n /* c8 ignore start */\n (!peer || peerCompatResult.compatible) &&\n // Check if existing node's peer edges are compatible with new parent\n peerCompatResult.compatible\n /* c8 ignore stop */\n\n if (\n validExistingNode ||\n // importers are handled at the ./refresh-ideal-graph.ts top-level\n // so we should just skip whenever we find one\n existingNode?.importer\n ) {\n // Defer edge creation to Phase B for deterministic ordering.\n // Previously added immediately, but this caused race conditions when\n // parallel fetches completed in different orders.\n reuseTasks.push({ type, spec, fromNode, toNode: existingNode })\n continue\n }\n\n // is the current edge pointint go an optional dependency?\n const edgeOptional =\n type === 'optional' || type === 'peerOptional'\n\n // Start manifest fetch immediately for parallel processing\n const manifestPromise =\n // the \"detached\" node state means that it has already been load as\n // part of a graph (either lockfile or actual) and it has valid manifest\n // data so we shortcut the package info manifest fetch here\n existingNode?.detached ?\n Promise.resolve(existingNode.manifest as Manifest | undefined)\n // this is the entry point to fetch calls to retrieve manifests\n // from the build ideal graph point of view\n : packageInfo\n .manifest(spec, { from: scurry.resolve(fromNode.location) })\n .then(manifest => manifest as Manifest | undefined)\n .catch((er: unknown) => {\n // optional deps ignored if inaccessible\n if (edgeOptional || fromNode.optional) {\n return undefined\n }\n throw er\n })\n\n const fetchTask: ManifestFetchTask = {\n spec,\n type,\n fromNode,\n fileTypeInfo,\n activeModifier,\n queryModifier,\n edgeOptional,\n manifestPromise,\n depth,\n peerContext: effectivePeerContext,\n }\n\n fetchTasks.push(fetchTask)\n }\n\n // Create placement tasks from fetch tasks\n for (const fetchTask of fetchTasks) {\n const manifest = await fetchTask.manifestPromise\n\n placementTasks.push({\n fetchTask,\n manifest,\n })\n }\n\n // sort placement tasks: non-peer dependencies first, then peer dependencies\n // so that peer dependencies can easily reuse already placed regular\n // dependencies as part of peer context set resolution also makes sure to\n // sort by the manifest name for deterministic order.\n placementTasks.sort(compareByHasPeerDeps)\n\n return { placementTasks, reuseTasks, forkRequests }\n}\n\n/**\n * Process placement tasks and collect child dependencies.\n *\n * This is Phase 2 of the breadth-first graph building process. For each\n * resolved manifest:\n * 1. Handle missing manifests (optional vs required deps)\n * 2. Start peer placement process (collect sibling context)\n * 3. Place the node in the graph with appropriate flags\n * 4. Trigger early extraction if eligible (performance optimization)\n * 5. Collect child dependencies for the next BFS level\n * 6. End peer placement (setup context update functions)\n *\n * Early extraction: When `actual` graph is provided, nodes destined for the\n * vlt store are extracted immediately (in parallel) instead of waiting for\n * the full ideal graph to be built. This significantly improves install time.\n */\nconst processPlacementTasks = async (\n graph: Graph,\n options: SpecOptions,\n placementTasks: NodePlacementTask[],\n add?: Map<string, Dependency>,\n modifiers?: GraphModifier,\n scurry?: PathScurry,\n packageInfo?: PackageInfoClient,\n extractPromises?: Promise<ExtractResult>[],\n actual?: Graph,\n seenExtracted?: Set<DepID>,\n remover?: RollbackRemove,\n transientAdd?: TransientAddMap,\n transientRemove?: TransientRemoveMap,\n): Promise<ProcessPlacementResult> => {\n const childDepsToProcess: ProcessPlacementResult = []\n\n // Note: placementTasks are already sorted by fetchManifestsForDeps\n // using compareByHasPeerDeps to ensure non-peer deps are processed first.\n // We don't sort again here to preserve that ordering.\n\n for (const placementTask of placementTasks) {\n const { fetchTask, manifest } = placementTask\n let {\n activeModifier,\n edgeOptional,\n fileTypeInfo,\n fromNode,\n peerContext,\n queryModifier,\n spec,\n type,\n } = fetchTask\n\n // fix the name in the `add` map when needed. This allows the upcoming\n // reify step to properly update the package.json file dependencies\n // using the correct names retrieved from the manifest data\n const additiveMap =\n fromNode.importer ? add : transientAdd?.get(fromNode.id)\n spec = fixupAddedNames(additiveMap, manifest, options, spec)\n\n // handles missing manifest resolution\n if (!manifest) {\n if (!edgeOptional && fromNode.isOptional()) {\n // failed resolution of a non-optional dep of an optional node\n // have to clean up the dependents\n removeOptionalSubgraph(graph, fromNode)\n continue\n } else if (edgeOptional) {\n // failed resolution of an optional dep, just ignore it,\n // nothing to prune because we never added it in the first place.\n continue\n } else {\n throw error('failed to resolve dependency', {\n spec,\n from: fromNode.location,\n })\n }\n }\n\n // start peer deps placement process, populating the peer context with\n // dependency data; adding the parent node deps and this manifest's\n // peer deps references to the current peer context set\n const peerPlacement = startPeerPlacement(\n peerContext,\n manifest,\n fromNode,\n options,\n )\n const peerSetHash = peerPlacement.peerSetHash\n const queuedEntries = peerPlacement.queuedEntries\n\n // places a new node in the graph representing a newly seen dependency\n const node = graph.placePackage(\n fromNode,\n type,\n spec,\n normalizeManifest(manifest),\n fileTypeInfo?.id,\n joinExtra({ peerSetHash, modifier: queryModifier }),\n )\n\n /* c8 ignore start - not possible, already ensured manifest */\n if (!node) {\n throw error('failed to place package', {\n from: fromNode.location,\n spec,\n })\n }\n /* c8 ignore stop */\n\n // update the node modifier tracker\n if (activeModifier) {\n modifiers?.updateActiveEntry(node, activeModifier)\n }\n\n const eligibleForExtraction =\n type !== 'peer' &&\n type !== 'peerOptional' &&\n remover &&\n extractPromises &&\n actual &&\n scurry &&\n packageInfo &&\n node.inVltStore() &&\n !node.isOptional() &&\n // this fixes an issue with installing `file:pathname` specs\n /* c8 ignore next */ !fileTypeInfo?.isDirectory &&\n !node.importer\n\n // extract the node if it meets the criteria for early extraction\n if (eligibleForExtraction) {\n /* c8 ignore start */\n if (seenExtracted?.has(node.id)) {\n continue\n }\n /* c8 ignore stop */\n seenExtracted?.add(node.id)\n const actualNode = actual.nodes.get(node.id)\n if (!actualNode?.equals(node)) {\n // extract the node without awaiting - push the promise to the array\n const extractPromise = extractNode(\n node,\n scurry,\n remover,\n options,\n packageInfo,\n )\n extractPromises.push(extractPromise)\n }\n }\n\n // updates graph node information\n if (fileTypeInfo?.path && fileTypeInfo.isDirectory) {\n node.location = fileTypeInfo.path\n }\n node.setResolved()\n\n // collect child dependencies for processing in the next level\n const nextPeerDeps = new Map<string, Dependency>()\n\n // compute deps normally\n const bundleDeps = manifest.bundleDependencies\n const bundled = new Set<string>(\n (\n node.id.startsWith('git') ||\n node.importer ||\n !isStringArray(bundleDeps)\n ) ?\n []\n : bundleDeps,\n )\n\n // setup next level to process all child dependencies in the manifest\n const nextDeps: Dependency[] = []\n\n // traverse actual dependency declarations in the manifest\n // creating dependency entries for them\n for (const depTypeName of longDependencyTypes) {\n const depRecord: Record<string, string> | undefined =\n manifest[depTypeName]\n\n if (depRecord && shouldInstallDepType(node, depTypeName)) {\n // Sort Object.entries for deterministic iteration\n const sortedEntries = Object.entries(depRecord).sort(\n ([a], [b]) => a.localeCompare(b, 'en'),\n )\n for (const [name, bareSpec] of sortedEntries) {\n // might need to skip already placed peer deps here\n if (bundled.has(name)) continue\n const dep = {\n type: shorten(depTypeName, name, manifest),\n spec: Spec.parse(name, bareSpec, {\n ...options,\n registry: spec.registry,\n }),\n }\n if (depTypeName === 'peerDependencies') {\n nextPeerDeps.set(name, dep)\n } else {\n nextDeps.push(dep)\n }\n }\n }\n }\n\n // Inject transient dependencies for non-importer nodes (nested folders)\n // These are deps that were added from a nested folder context using\n // relative file: specs that should resolve relative to that folder\n const transientDeps = transientAdd?.get(node.id)\n if (transientDeps) {\n for (const [, dep] of transientDeps) {\n if (dep.type === 'peer' || dep.type === 'peerOptional') {\n nextPeerDeps.set(dep.spec.name, dep)\n continue\n }\n\n // remove the dependency from nextDeps if it already exists\n const index = nextDeps.findIndex(\n d => d.spec.name === dep.spec.name,\n )\n if (index !== -1) {\n nextDeps.splice(index, 1)\n }\n\n nextDeps.push(dep)\n }\n }\n\n // Remove transient removals when needed\n const transientRemovals = transientRemove?.get(node.id)\n if (transientRemovals) {\n for (const depName of transientRemovals) {\n const index = nextDeps.findIndex(\n dep => dep.spec.name === depName,\n )\n if (index !== -1) {\n nextDeps.splice(index, 1)\n continue\n }\n\n if (nextPeerDeps.has(depName)) {\n nextPeerDeps.delete(depName)\n }\n }\n }\n\n // finish peer placement for this node, resolving satisfied peers\n // to seen nodes from the peer context and adding unsatisfied peers\n // to `nextDeps` so they get processed along regular dependencies\n const updateContext = endPeerPlacement(\n peerContext,\n nextDeps,\n nextPeerDeps,\n graph,\n spec,\n fromNode,\n node,\n type,\n queuedEntries,\n )\n\n childDepsToProcess.push({\n node,\n deps: nextDeps,\n modifierRefs: modifiers?.tryDependencies(node, nextDeps),\n peerContext,\n updateContext,\n })\n }\n\n return childDepsToProcess\n}\n\n/**\n * Append new nodes in the given `graph` for dependencies specified at `add`\n * and missing dependencies from the `deps` parameter.\n *\n * Uses **breadth-first traversal** (BFS) with **deterministic ordering** to\n * ensure reproducible builds. The algorithm:\n *\n * 1. Process all deps at the current level in parallel\n * 2. After each level, run `postPlacementPeerCheck` to handle peer contexts\n * 3. Collect child deps for the next level\n * 4. Repeat until no more deps to process\n *\n * **Peer Context Isolation**: Each workspace importer gets its own peer context\n * to prevent cross-workspace leakage. Without this, `react@^18` from workspace A\n * could incorrectly satisfy `react@^19` peer deps in workspace B.\n *\n * **Early Extraction**: When `actual` graph is provided, nodes are extracted\n * to the vlt store during graph construction (not after), improving performance.\n */\nexport const appendNodes = async (\n packageInfo: PackageInfoClient,\n graph: Graph,\n fromNode: Node,\n deps: Dependency[],\n scurry: PathScurry,\n options: SpecOptions,\n seen: Set<DepID>,\n add?: Map<string, Dependency>,\n modifiers?: GraphModifier,\n modifierRefs?: Map<string, ModifierActiveEntry>,\n extractPromises?: Promise<ExtractResult>[],\n actual?: Graph,\n seenExtracted?: Set<DepID>,\n remover?: RollbackRemove,\n transientAdd?: TransientAddMap,\n transientRemove?: TransientRemoveMap,\n) => {\n // Cycle detection: skip if already processed\n /* c8 ignore next */\n if (seen.has(fromNode.id)) return\n seen.add(fromNode.id)\n\n // PEER CONTEXT ISOLATION: Each workspace importer needs its own context\n // to prevent peer targets from one workspace affecting another.\n // The main importer (index 0) uses the initial context; others get fresh ones.\n let initialPeerContext = graph.peerContexts[0]\n /* c8 ignore start - impossible */\n if (!initialPeerContext)\n throw error('no initial peer context found in graph')\n /* c8 ignore stop */\n if (fromNode.importer && fromNode !== graph.mainImporter) {\n // Create isolated peer context for this workspace importer\n const nextPeerContext: PeerContext = new Map()\n nextPeerContext.index = graph.nextPeerContextIndex()\n graph.peerContexts[nextPeerContext.index] = nextPeerContext\n initialPeerContext = nextPeerContext\n }\n\n // BFS queue: process deps level by level for deterministic builds\n let currentLevelDeps: AppendNodeEntry[] = [\n {\n node: fromNode,\n deps,\n modifierRefs,\n depth: 0,\n peerContext: initialPeerContext,\n /* c8 ignore start */\n updateContext: {\n putEntries: () => undefined,\n resolvePeerDeps: () => {},\n },\n /* c8 ignore stop */\n },\n ]\n\n // BFS MAIN LOOP: Process level by level until no more deps\n while (currentLevelDeps.length > 0) {\n const nextLevelDeps: AppendNodeEntry[] = []\n\n // ============================================================\n // PHASE A: PARALLEL FETCH (READ-ONLY)\n // ============================================================\n // Fetch all manifests at this level in parallel without mutating the graph.\n // This phase is read-only to avoid race conditions from network timing.\n const fetchResults = await Promise.all(\n currentLevelDeps.map(\n async ({\n node,\n deps: nodeDeps,\n modifierRefs: nodeModifierRefs,\n peerContext,\n depth,\n }: AppendNodeEntry) => {\n // Cycle prevention: mark as seen when starting to process\n seen.add(node.id)\n\n // Fetch manifests and collect tasks (no graph mutations)\n const result = await fetchManifestsForDeps(\n packageInfo,\n graph,\n node,\n // Sort by name for deterministic ordering (reproducible builds)\n nodeDeps.sort((a, b) =>\n a.spec.name.localeCompare(b.spec.name, 'en'),\n ),\n scurry,\n peerContext,\n nodeModifierRefs,\n depth,\n )\n\n return {\n entry: {\n node,\n deps: nodeDeps,\n modifierRefs: nodeModifierRefs,\n peerContext,\n depth,\n },\n result,\n }\n },\n ),\n )\n\n // ============================================================\n // PHASE B: SERIAL MUTATIONS (DETERMINISTIC ORDER)\n // ============================================================\n // Sort results by stable identifiers to ensure deterministic ordering\n // regardless of which manifest fetch completed first\n const sortedResults = fetchResults.sort((a, b) => {\n // Sort by node ID (DepID-based, stable) and depth\n const keyA = `${a.entry.node.id}::${a.entry.depth}`\n const keyB = `${b.entry.node.id}::${b.entry.depth}`\n return keyA.localeCompare(keyB, 'en')\n })\n\n // Apply all mutations serially in deterministic order\n const levelResults: ProcessPlacementResult[] = []\n for (const { entry, result } of sortedResults) {\n // Apply accumulated fork requests if any (from Phase A deferred forks)\n if (result.forkRequests.length > 0) {\n const forkedContext = forkPeerContext(\n graph,\n entry.peerContext,\n result.forkRequests,\n )\n entry.peerContext = forkedContext\n // Update peer context in all placement tasks to use forked context\n for (const task of result.placementTasks) {\n task.fetchTask.peerContext = forkedContext\n }\n }\n\n // Apply reuse edges in deterministic order (before placement)\n // Sort reuse tasks by spec name for stability\n const sortedReuseTasks = result.reuseTasks.sort((a, b) =>\n a.spec.name.localeCompare(b.spec.name, 'en'),\n )\n for (const {\n type,\n spec,\n fromNode,\n toNode,\n } of sortedReuseTasks) {\n graph.addEdge(type, spec, fromNode, toNode)\n }\n\n // Place nodes and collect child deps\n const placed = await processPlacementTasks(\n graph,\n options,\n result.placementTasks,\n add,\n modifiers,\n scurry,\n packageInfo,\n extractPromises,\n actual,\n seenExtracted,\n remover,\n transientAdd,\n transientRemove,\n )\n\n levelResults.push(placed)\n }\n\n // ============================================================\n // PHASE C: POST-PLACEMENT PEER CHECK\n // ============================================================\n // After all nodes at this level are placed, update peer contexts,\n // fork as needed, and resolve peer deps that can be satisfied.\n // This must happen AFTER placement so sibling nodes are available.\n postPlacementPeerCheck(graph, levelResults)\n\n // ============================================================\n // STEP 3: COLLECT CHILD DEPS FOR NEXT LEVEL\n // ============================================================\n for (const childDepsToProcess of levelResults) {\n for (const childDep of childDepsToProcess) {\n // Skip already-seen nodes (cycle prevention)\n if (!seen.has(childDep.node.id)) {\n /* c8 ignore next */\n const currentDepth = currentLevelDeps[0]?.depth ?? 0\n nextLevelDeps.push({\n ...childDep,\n depth: currentDepth + 1,\n })\n }\n }\n }\n\n // Advance to next BFS level\n currentLevelDeps = nextLevelDeps\n }\n}\n"]} | ||
| {"version":3,"file":"append-nodes.js","sourceRoot":"","sources":["../../src/ideal/append-nodes.ts"],"names":[],"mappings":"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","sourcesContent":["import { joinDepIDTuple, joinExtra } from '@vltpkg/dep-id'\nimport type { DepID } from '@vltpkg/dep-id'\nimport { error } from '@vltpkg/error-cause'\nimport type { PackageInfoClient } from '@vltpkg/package-info'\nimport { Spec } from '@vltpkg/spec'\nimport type { SpecOptions } from '@vltpkg/spec'\nimport { satisfies } from '@vltpkg/satisfies'\nimport { longDependencyTypes, normalizeManifest } from '@vltpkg/types'\nimport type {\n DependencyTypeLong,\n DependencySaveType,\n Manifest,\n} from '@vltpkg/types'\nimport type { PathScurry } from 'path-scurry'\nimport { fixupAddedNames } from '../fixup-added-names.ts'\nimport { shorten } from '../dependencies.ts'\nimport type { Dependency } from '../dependencies.ts'\nimport type { Graph } from '../graph.ts'\nimport type { Node } from '../node.ts'\nimport { removeOptionalSubgraph } from '../remove-optional-subgraph.ts'\nimport type {\n GraphModifier,\n ModifierActiveEntry,\n} from '../modifiers.ts'\nimport type { ExtractResult } from '../reify/extract-node.ts'\nimport { extractNode } from '../reify/extract-node.ts'\nimport type { RollbackRemove } from '@vltpkg/rollback-remove'\nimport {\n checkPeerEdgesCompatible,\n endPeerPlacement,\n forkPeerContext,\n postPlacementPeerCheck,\n startPeerPlacement,\n} from './peers.ts'\nimport { compareByHasPeerDeps } from './sorting.ts'\nimport type {\n PeerContext,\n PeerContextEntryInput,\n AppendNodeEntry,\n ProcessPlacementResult,\n TransientAddMap,\n TransientRemoveMap,\n} from './types.ts'\n\ntype FileTypeInfo = {\n id: DepID\n path: string\n isDirectory: boolean\n}\n\n/**\n * Task for reusing an existing node (deferred edge creation).\n */\ntype ReuseTask = {\n type: DependencySaveType\n spec: Spec\n fromNode: Node\n toNode: Node\n}\n\n/**\n * Result of fetching manifests for dependencies.\n */\ntype FetchResult = {\n placementTasks: NodePlacementTask[]\n reuseTasks: ReuseTask[]\n forkRequests: PeerContextEntryInput[]\n}\n\n/**\n * Only install devDeps for git dependencies and importers\n * Everything else always gets installed\n */\nconst shouldInstallDepType = (\n node: Node,\n depType: DependencyTypeLong,\n) =>\n depType !== 'devDependencies' ||\n node.importer ||\n node.id.startsWith('git')\n\n/**\n * Retrieve the {@link DepID} and location for a `file:` type {@link Node}.\n */\nconst getFileTypeInfo = (\n spec: Spec,\n fromNode: Node,\n scurry: PathScurry,\n): FileTypeInfo | undefined => {\n const f = spec.final\n if (f.type !== 'file') return\n\n /* c8 ignore start - should be impossible */\n if (!f.file) {\n throw error('no path on file specifier', { spec })\n }\n /* c8 ignore stop */\n\n // Given that both linked folders and local tarballs (both defined with\n // usage of the `file:` spec prefix) location needs to be relative to their\n // parents, build the expected path and use it for both location and id\n const target = scurry.cwd.resolve(fromNode.location).resolve(f.file)\n const path = target.relativePosix()\n const id = joinDepIDTuple(['file', path])\n\n return {\n path,\n id,\n isDirectory: !!target.lstatSync()?.isDirectory(),\n }\n}\n\nconst isStringArray = (a: unknown): a is string[] =>\n Array.isArray(a) && !a.some(b => typeof b !== 'string')\n\n/**\n * Represents a manifest fetch operation with all the context needed.\n */\ntype ManifestFetchTask = {\n spec: Spec\n type: DependencySaveType\n fromNode: Node\n fileTypeInfo?: FileTypeInfo\n activeModifier?: ModifierActiveEntry\n queryModifier?: string\n edgeOptional: boolean\n manifestPromise: Promise<Manifest | undefined>\n depth: number\n peerContext: PeerContext\n}\n\n/**\n * Represents a node placement operation that depends on a resolved manifest.\n */\ntype NodePlacementTask = {\n fetchTask: ManifestFetchTask\n manifest: Manifest | undefined\n node?: Node\n childDeps?: Dependency[]\n childModifierRefs?: Map<string, ModifierActiveEntry>\n childPeerContext?: PeerContext\n}\n\n/**\n * Try to find a compatible resolution for a dependency, checking peer context.\n * If the first resolution candidate is incompatible with the peer context,\n * try other candidates.\n */\nconst findCompatibleResolution = (\n spec: Spec,\n fromNode: Node,\n graph: Graph,\n peerContext: PeerContext,\n queryModifier?: string,\n _peer?: boolean,\n) => {\n // Hoist invariants once\n const fromLoc = fromNode.location\n const projectRoot = graph.projectRoot\n const monorepo = graph.monorepo\n const final = spec.final\n // Memoize satisfies() results per-node within this resolution attempt\n const satisfiesCache = new Map<string, boolean>()\n const satisfiesFinal = (n: Node) => {\n const key = n.id\n const cached = satisfiesCache.get(key)\n /* c8 ignore next 3 - optimization: cache hit when same node checked multiple times */\n if (cached !== undefined) {\n return cached\n }\n const result = satisfies(\n key,\n final,\n fromLoc,\n projectRoot,\n monorepo,\n )\n satisfiesCache.set(key, result)\n return result\n }\n\n // Prefer existing edge target if it satisfies the spec.\n // This ensures lockfile resolutions are preserved when still valid,\n // rather than potentially picking a different satisfying version.\n const existingEdge = fromNode.edgesOut.get(spec.name)\n let existingNode: Node | undefined\n if (\n existingEdge?.to &&\n !existingEdge.to.detached &&\n satisfiesFinal(existingEdge.to)\n ) {\n existingNode = existingEdge.to\n } else {\n existingNode = graph.findResolution(spec, fromNode, queryModifier)\n }\n\n let peerCompatResult =\n existingNode ?\n checkPeerEdgesCompatible(\n existingNode,\n fromNode,\n peerContext,\n graph,\n )\n : { compatible: true }\n\n // CANDIDATE FALLBACK: If first candidate is peer-incompatible, try others\n // Lazy-load candidates only when fallback needed\n if (existingNode && !peerCompatResult.compatible) {\n const candidates = graph.nodesByName.get(final.name)\n if (candidates && candidates.size > 1) {\n for (const candidate of candidates) {\n if (candidate === existingNode) continue\n if (candidate.detached) continue\n if (!satisfiesFinal(candidate)) continue\n\n const compat = checkPeerEdgesCompatible(\n candidate,\n fromNode,\n peerContext,\n graph,\n )\n if (compat.compatible) {\n existingNode = candidate\n peerCompatResult = compat\n break\n }\n }\n }\n }\n\n return { existingNode, peerCompatResult }\n}\n\n/**\n * Fetch manifests for dependencies and create placement tasks.\n *\n * This is Phase 1 of the breadth-first graph building process. For each\n * dependency at the current level:\n * 1. Apply any active modifiers (spec swapping)\n * 2. Try to find an existing node to reuse (with peer compatibility check)\n * 3. If no reusable node, start a manifest fetch (in parallel)\n * 4. Create placement tasks for Phase 2\n *\n * The result is sorted to process non-peer-dependent packages first,\n * ensuring peer dependencies can resolve to already-placed siblings.\n *\n * **Read-only**: This function no longer mutates the graph. It returns\n * tasks that will be applied serially in the BFS loop for deterministic ordering.\n */\nconst fetchManifestsForDeps = async (\n packageInfo: PackageInfoClient,\n graph: Graph,\n fromNode: Node,\n deps: Dependency[],\n scurry: PathScurry,\n peerContext: PeerContext,\n modifierRefs?: Map<string, ModifierActiveEntry>,\n depth = 0,\n): Promise<FetchResult> => {\n const fetchTasks: ManifestFetchTask[] = []\n const placementTasks: NodePlacementTask[] = []\n const reuseTasks: ReuseTask[] = []\n const forkRequests: PeerContextEntryInput[] = []\n\n for (const { spec: originalSpec, type } of deps) {\n let spec = originalSpec\n const fileTypeInfo = getFileTypeInfo(spec, fromNode, scurry)\n const activeModifier = modifierRefs?.get(spec.name)\n\n // MODIFIER HANDLING: Swap spec if an edge modifier is fully matched\n // Example: `vlt install --override \"react:^19\"` changes react's spec\n const queryModifier = activeModifier?.modifier.query\n const completeModifier =\n activeModifier &&\n activeModifier.interactiveBreadcrumb.current ===\n activeModifier.modifier.breadcrumb.last\n if (\n queryModifier &&\n completeModifier &&\n 'spec' in activeModifier.modifier\n ) {\n spec = activeModifier.modifier.spec\n // bareSpec of '-' means \"remove this dependency\"\n if (spec.bareSpec === '-') {\n continue\n }\n }\n\n const peer = type === 'peer' || type === 'peerOptional'\n\n // NODE REUSE LOGIC with peer compatibility\n const { existingNode, peerCompatResult } =\n findCompatibleResolution(\n spec,\n fromNode,\n graph,\n peerContext,\n queryModifier,\n peer,\n )\n\n // Accumulate fork request if incompatible peer edges detected (defer actual fork)\n const effectivePeerContext = peerContext\n /* c8 ignore start */\n if (!peerCompatResult.compatible && peerCompatResult.forkEntry) {\n forkRequests.push(peerCompatResult.forkEntry)\n // All fork entries from this fromNode will be applied together in Phase B\n }\n /* c8 ignore stop */\n\n // defines what nodes are eligible to be reused\n const validExistingNode =\n existingNode &&\n !existingNode.detached &&\n // Regular deps can always reuse.\n // Peer deps can reuse as well if their peer edges are compatible.\n /* c8 ignore start */\n (!peer || peerCompatResult.compatible) &&\n // Check if existing node's peer edges are compatible with new parent\n peerCompatResult.compatible\n /* c8 ignore stop */\n\n if (\n validExistingNode ||\n // importers are handled at the ./refresh-ideal-graph.ts top-level\n // so we should just skip whenever we find one\n existingNode?.importer\n ) {\n // Defer edge creation to Phase B for deterministic ordering.\n // Previously added immediately, but this caused race conditions when\n // parallel fetches completed in different orders.\n reuseTasks.push({ type, spec, fromNode, toNode: existingNode })\n continue\n }\n\n // is the current edge pointint go an optional dependency?\n const edgeOptional =\n type === 'optional' || type === 'peerOptional'\n\n // Start manifest fetch immediately for parallel processing\n const manifestPromise =\n // the \"detached\" node state means that it has already been load as\n // part of a graph (either lockfile or actual) and it has valid manifest\n // data so we shortcut the package info manifest fetch here\n existingNode?.detached ?\n Promise.resolve(existingNode.manifest as Manifest | undefined)\n // this is the entry point to fetch calls to retrieve manifests\n // from the build ideal graph point of view\n : packageInfo\n .manifest(spec, { from: scurry.resolve(fromNode.location) })\n .then(manifest => manifest as Manifest | undefined)\n .catch((er: unknown) => {\n // optional deps ignored if inaccessible\n if (edgeOptional || fromNode.optional) {\n return undefined\n }\n throw er\n })\n\n const fetchTask: ManifestFetchTask = {\n spec,\n type,\n fromNode,\n fileTypeInfo,\n activeModifier,\n queryModifier,\n edgeOptional,\n manifestPromise,\n depth,\n peerContext: effectivePeerContext,\n }\n\n fetchTasks.push(fetchTask)\n }\n\n // Create placement tasks from fetch tasks\n for (const fetchTask of fetchTasks) {\n const manifest = await fetchTask.manifestPromise\n\n placementTasks.push({\n fetchTask,\n manifest,\n })\n }\n\n // sort placement tasks: non-peer dependencies first, then peer dependencies\n // so that peer dependencies can easily reuse already placed regular\n // dependencies as part of peer context set resolution also makes sure to\n // sort by the manifest name for deterministic order.\n placementTasks.sort(compareByHasPeerDeps)\n\n return { placementTasks, reuseTasks, forkRequests }\n}\n\n/**\n * Process placement tasks and collect child dependencies.\n *\n * This is Phase 2 of the breadth-first graph building process. For each\n * resolved manifest:\n * 1. Handle missing manifests (optional vs required deps)\n * 2. Start peer placement process (collect sibling context)\n * 3. Place the node in the graph with appropriate flags\n * 4. Trigger early extraction if eligible (performance optimization)\n * 5. Collect child dependencies for the next BFS level\n * 6. End peer placement (setup context update functions)\n *\n * Early extraction: When `actual` graph is provided, nodes destined for the\n * vlt store are extracted immediately (in parallel) instead of waiting for\n * the full ideal graph to be built. This significantly improves install time.\n */\nconst processPlacementTasks = async (\n graph: Graph,\n options: SpecOptions,\n placementTasks: NodePlacementTask[],\n add?: Map<string, Dependency>,\n modifiers?: GraphModifier,\n scurry?: PathScurry,\n packageInfo?: PackageInfoClient,\n extractPromises?: Promise<ExtractResult>[],\n actual?: Graph,\n seenExtracted?: Set<DepID>,\n remover?: RollbackRemove,\n transientAdd?: TransientAddMap,\n transientRemove?: TransientRemoveMap,\n): Promise<ProcessPlacementResult> => {\n const childDepsToProcess: ProcessPlacementResult = []\n\n // Note: placementTasks are already sorted by fetchManifestsForDeps\n // using compareByHasPeerDeps to ensure non-peer deps are processed first.\n // We don't sort again here to preserve that ordering.\n\n for (const placementTask of placementTasks) {\n const { fetchTask, manifest } = placementTask\n let {\n activeModifier,\n edgeOptional,\n fileTypeInfo,\n fromNode,\n peerContext,\n queryModifier,\n spec,\n type,\n } = fetchTask\n\n // fix the name in the `add` map when needed. This allows the upcoming\n // reify step to properly update the package.json file dependencies\n // using the correct names retrieved from the manifest data\n const additiveMap =\n fromNode.importer ? add : transientAdd?.get(fromNode.id)\n spec = fixupAddedNames(additiveMap, manifest, options, spec)\n\n // handles missing manifest resolution\n if (!manifest) {\n if (!edgeOptional && fromNode.isOptional()) {\n // failed resolution of a non-optional dep of an optional node\n // have to clean up the dependents\n removeOptionalSubgraph(graph, fromNode)\n continue\n } else if (edgeOptional) {\n // failed resolution of an optional dep, just ignore it,\n // nothing to prune because we never added it in the first place.\n continue\n } else {\n throw error('failed to resolve dependency', {\n spec,\n from: fromNode.location,\n })\n }\n }\n\n // start peer deps placement process, populating the peer context with\n // dependency data; adding the parent node deps and this manifest's\n // peer deps references to the current peer context set\n const peerPlacement = startPeerPlacement(\n peerContext,\n manifest,\n fromNode,\n options,\n )\n const peerSetHash = peerPlacement.peerSetHash\n const queuedEntries = peerPlacement.queuedEntries\n\n // places a new node in the graph representing a newly seen dependency\n const node = graph.placePackage(\n fromNode,\n type,\n spec,\n normalizeManifest(manifest),\n fileTypeInfo?.id,\n joinExtra({ peerSetHash, modifier: queryModifier }),\n )\n\n /* c8 ignore start - not possible, already ensured manifest */\n if (!node) {\n throw error('failed to place package', {\n from: fromNode.location,\n spec,\n })\n }\n /* c8 ignore stop */\n\n // update the node modifier tracker\n if (activeModifier) {\n modifiers?.updateActiveEntry(node, activeModifier)\n }\n\n const eligibleForExtraction =\n type !== 'peer' &&\n type !== 'peerOptional' &&\n remover &&\n extractPromises &&\n actual &&\n scurry &&\n packageInfo &&\n node.inVltStore() &&\n !node.isOptional() &&\n // this fixes an issue with installing `file:pathname` specs\n /* c8 ignore next */ !fileTypeInfo?.isDirectory &&\n !node.importer\n\n // extract the node if it meets the criteria for early extraction\n if (eligibleForExtraction) {\n /* c8 ignore start */\n if (seenExtracted?.has(node.id)) {\n continue\n }\n /* c8 ignore stop */\n seenExtracted?.add(node.id)\n const actualNode = actual.nodes.get(node.id)\n if (!actualNode?.equals(node)) {\n // extract the node without awaiting - push the promise to the array\n const extractPromise = extractNode(\n node,\n scurry,\n remover,\n options,\n packageInfo,\n )\n extractPromises.push(extractPromise)\n }\n }\n\n // updates graph node information\n if (fileTypeInfo?.path && fileTypeInfo.isDirectory) {\n node.location = fileTypeInfo.path\n }\n node.setResolved()\n\n // collect child dependencies for processing in the next level\n const nextPeerDeps = new Map<string, Dependency>()\n\n // compute deps normally\n const bundleDeps = manifest.bundleDependencies\n const bundled = new Set<string>(\n (\n node.id.startsWith('git') ||\n node.importer ||\n !isStringArray(bundleDeps)\n ) ?\n []\n : bundleDeps,\n )\n\n // setup next level to process all child dependencies in the manifest\n const nextDeps: Dependency[] = []\n\n // traverse actual dependency declarations in the manifest\n // creating dependency entries for them\n for (const depTypeName of longDependencyTypes) {\n const depRecord: Record<string, string> | undefined =\n manifest[depTypeName]\n\n if (depRecord && shouldInstallDepType(node, depTypeName)) {\n // Sort Object.entries for deterministic iteration\n const sortedEntries = Object.entries(depRecord).sort(\n ([a], [b]) => a.localeCompare(b, 'en'),\n )\n for (const [name, bareSpec] of sortedEntries) {\n // might need to skip already placed peer deps here\n if (bundled.has(name)) continue\n const dep = {\n type: shorten(depTypeName, name, manifest),\n spec: Spec.parse(name, bareSpec, {\n ...options,\n registry: spec.registry,\n }),\n }\n if (depTypeName === 'peerDependencies') {\n nextPeerDeps.set(name, dep)\n } else {\n nextDeps.push(dep)\n }\n }\n }\n }\n\n // Inject transient dependencies for non-importer nodes (nested folders)\n // These are deps that were added from a nested folder context using\n // relative file: specs that should resolve relative to that folder\n const transientDeps = transientAdd?.get(node.id)\n if (transientDeps) {\n for (const [, dep] of transientDeps) {\n if (dep.type === 'peer' || dep.type === 'peerOptional') {\n nextPeerDeps.set(dep.spec.name, dep)\n continue\n }\n\n // remove the dependency from nextDeps if it already exists\n const index = nextDeps.findIndex(\n d => d.spec.name === dep.spec.name,\n )\n if (index !== -1) {\n nextDeps.splice(index, 1)\n }\n\n nextDeps.push(dep)\n }\n }\n\n // Remove transient removals when needed\n const transientRemovals = transientRemove?.get(node.id)\n if (transientRemovals) {\n for (const depName of transientRemovals) {\n const index = nextDeps.findIndex(\n dep => dep.spec.name === depName,\n )\n if (index !== -1) {\n nextDeps.splice(index, 1)\n continue\n }\n\n if (nextPeerDeps.has(depName)) {\n nextPeerDeps.delete(depName)\n }\n }\n }\n\n // finish peer placement for this node, resolving satisfied peers\n // to seen nodes from the peer context and adding unsatisfied peers\n // to `nextDeps` so they get processed along regular dependencies\n const updateContext = endPeerPlacement(\n peerContext,\n nextDeps,\n nextPeerDeps,\n graph,\n spec,\n fromNode,\n node,\n type,\n queuedEntries,\n )\n\n childDepsToProcess.push({\n node,\n deps: nextDeps,\n modifierRefs: modifiers?.tryDependencies(node, nextDeps),\n peerContext,\n updateContext,\n })\n }\n\n return childDepsToProcess\n}\n\n/**\n * Append new nodes in the given `graph` for dependencies specified at `add`\n * and missing dependencies from the `deps` parameter.\n *\n * Uses **breadth-first traversal** (BFS) with **deterministic ordering** to\n * ensure reproducible builds. The algorithm:\n *\n * 1. Process all deps at the current level in parallel\n * 2. After each level, run `postPlacementPeerCheck` to handle peer contexts\n * 3. Collect child deps for the next level\n * 4. Repeat until no more deps to process\n *\n * **Peer Context Isolation**: Each workspace importer gets its own peer context\n * to prevent cross-workspace leakage. Without this, `react@^18` from workspace A\n * could incorrectly satisfy `react@^19` peer deps in workspace B.\n *\n * **Early Extraction**: When `actual` graph is provided, nodes are extracted\n * to the vlt store during graph construction (not after), improving performance.\n */\nexport const appendNodes = async (\n packageInfo: PackageInfoClient,\n graph: Graph,\n fromNode: Node,\n deps: Dependency[],\n scurry: PathScurry,\n options: SpecOptions,\n seen: Set<DepID>,\n add?: Map<string, Dependency>,\n modifiers?: GraphModifier,\n modifierRefs?: Map<string, ModifierActiveEntry>,\n extractPromises?: Promise<ExtractResult>[],\n actual?: Graph,\n seenExtracted?: Set<DepID>,\n remover?: RollbackRemove,\n transientAdd?: TransientAddMap,\n transientRemove?: TransientRemoveMap,\n) => {\n // Cycle detection: skip if already processed\n /* c8 ignore next */\n if (seen.has(fromNode.id)) return\n seen.add(fromNode.id)\n\n // PEER CONTEXT ISOLATION: Each workspace importer needs its own context\n // to prevent peer targets from one workspace affecting another.\n // The main importer (index 0) uses the initial context; others get fresh ones.\n let initialPeerContext = graph.peerContexts[0]\n /* c8 ignore start - impossible */\n if (!initialPeerContext)\n throw error('no initial peer context found in graph')\n /* c8 ignore stop */\n if (fromNode.importer && fromNode !== graph.mainImporter) {\n // Create isolated peer context for this workspace importer\n const nextPeerContext: PeerContext = new Map()\n nextPeerContext.index = graph.nextPeerContextIndex()\n graph.peerContexts[nextPeerContext.index] = nextPeerContext\n initialPeerContext = nextPeerContext\n }\n\n // BFS queue: process deps level by level for deterministic builds\n let currentLevelDeps: AppendNodeEntry[] = [\n {\n node: fromNode,\n deps,\n modifierRefs,\n depth: 0,\n peerContext: initialPeerContext,\n /* c8 ignore start */\n updateContext: {\n putEntries: () => undefined,\n resolvePeerDeps: () => {},\n },\n /* c8 ignore stop */\n },\n ]\n\n // BFS MAIN LOOP: Process level by level until no more deps\n while (currentLevelDeps.length > 0) {\n const nextLevelDeps: AppendNodeEntry[] = []\n\n // ============================================================\n // PHASE A: PARALLEL FETCH (READ-ONLY)\n // ============================================================\n // Fetch all manifests at this level in parallel without mutating the graph.\n // This phase is read-only to avoid race conditions from network timing.\n const fetchResults = await Promise.all(\n currentLevelDeps.map(\n async ({\n node,\n deps: nodeDeps,\n modifierRefs: nodeModifierRefs,\n peerContext,\n depth,\n }: AppendNodeEntry) => {\n // Cycle prevention: mark as seen when starting to process\n seen.add(node.id)\n\n // Fetch manifests and collect tasks (no graph mutations)\n const result = await fetchManifestsForDeps(\n packageInfo,\n graph,\n node,\n // Sort by name for deterministic ordering (reproducible builds)\n nodeDeps.sort((a, b) =>\n a.spec.name.localeCompare(b.spec.name, 'en'),\n ),\n scurry,\n peerContext,\n nodeModifierRefs,\n depth,\n )\n\n return {\n entry: {\n node,\n deps: nodeDeps,\n modifierRefs: nodeModifierRefs,\n peerContext,\n depth,\n },\n result,\n }\n },\n ),\n )\n\n // ============================================================\n // PHASE B: SERIAL MUTATIONS (DETERMINISTIC ORDER)\n // ============================================================\n // Sort results by stable identifiers to ensure deterministic ordering\n // regardless of which manifest fetch completed first\n const sortedResults = fetchResults.sort((a, b) => {\n // Sort by node ID (DepID-based, stable) and depth\n const keyA = `${a.entry.node.id}::${a.entry.depth}`\n const keyB = `${b.entry.node.id}::${b.entry.depth}`\n return keyA.localeCompare(keyB, 'en')\n })\n\n // Apply all mutations serially in deterministic order\n const levelResults: ProcessPlacementResult[] = []\n for (const { entry, result } of sortedResults) {\n // Apply accumulated fork requests if any (from Phase A deferred forks)\n if (result.forkRequests.length > 0) {\n const forkedContext = forkPeerContext(\n graph,\n entry.peerContext,\n result.forkRequests,\n )\n entry.peerContext = forkedContext\n // Update peer context in all placement tasks to use forked context\n for (const task of result.placementTasks) {\n task.fetchTask.peerContext = forkedContext\n }\n }\n\n // Apply reuse edges in deterministic order (before placement)\n // Sort reuse tasks by spec name for stability\n const sortedReuseTasks = result.reuseTasks.sort((a, b) =>\n a.spec.name.localeCompare(b.spec.name, 'en'),\n )\n for (const {\n type,\n spec,\n fromNode,\n toNode,\n } of sortedReuseTasks) {\n graph.addEdge(type, spec, fromNode, toNode)\n }\n\n // Place nodes and collect child deps\n const placed = await processPlacementTasks(\n graph,\n options,\n result.placementTasks,\n add,\n modifiers,\n scurry,\n packageInfo,\n extractPromises,\n actual,\n seenExtracted,\n remover,\n transientAdd,\n transientRemove,\n )\n\n levelResults.push(placed)\n }\n\n // ============================================================\n // PHASE C: POST-PLACEMENT PEER CHECK\n // ============================================================\n // After all nodes at this level are placed, update peer contexts,\n // fork as needed, and resolve peer deps that can be satisfied.\n // This must happen AFTER placement so sibling nodes are available.\n postPlacementPeerCheck(graph, levelResults)\n\n // ============================================================\n // STEP 3: COLLECT CHILD DEPS FOR NEXT LEVEL\n // ============================================================\n for (const childDepsToProcess of levelResults) {\n for (const childDep of childDepsToProcess) {\n // Skip already-seen nodes (cycle prevention)\n if (!seen.has(childDep.node.id)) {\n /* c8 ignore next */\n const currentDepth = currentLevelDeps[0]?.depth ?? 0\n nextLevelDeps.push({\n ...childDep,\n depth: currentDepth + 1,\n })\n }\n }\n }\n\n // Advance to next BFS level\n currentLevelDeps = nextLevelDeps\n }\n}\n"]} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"peers.d.ts","sourceRoot":"","sources":["../../src/ideal/peers.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAGnC,OAAO,KAAK,EAEV,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,OAAO,KAAK,EACV,kBAAkB,EAElB,QAAQ,EACT,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC;;;;GAIG;AACH,KAAK,oBAAoB,GAAG;IAC1B,UAAU,EAAE,OAAO,CAAA;IACnB,gFAAgF;IAChF,SAAS,CAAC,EAAE,qBAAqB,GAAG;QAAE,MAAM,EAAE,IAAI,CAAA;KAAE,CAAA;CACrD,CAAA;AA6ID;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,wBAAwB,iBACrB,IAAI,YACR,IAAI,eACD,WAAW,SACjB,KAAK,KACX,oBAuHF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,gBACrB,WAAW,GAAG,SAAS,KACnC,MAAM,GAAG,SAKX,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,SACtB,IAAI,SACH,gBAAgB,KACtB,OAkBF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,YAC9B,qBAAqB,EAAE,KAC/B,qBAAqB,EAAsC,CAAA;AAQ9D,eAAO,MAAM,yBAAyB,gBACvB,WAAW,WACf,qBAAqB,EAAE,KAC/B,OAgBF,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,gBACrB,WAAW,WACf,qBAAqB,EAAE,YACtB,IAAI,aACH,QAAQ,KAClB,OA6DF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,UACnB,KAAK,eACC,WAAW,WACf,qBAAqB,EAAE,KAC/B,WA4CF,CAAA;AA0DD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,gBAChB,WAAW,YACd,QAAQ,YACR,IAAI,WACL,WAAW;;;CA4CrB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,gBACd,WAAW,YACd,UAAU,EAAE,gBACR,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,SAChD,KAAK,QACN,IAAI,YACA,IAAI,QACR,IAAI,QACJ,kBAAkB,iBACT,qBAAqB,EAAE;IAEtC;;;;;;;;;;;OAWG;;;;;;;;;;IAsDH;;;;;;;;;OASG;;CA4EH,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,sBAAsB,UAC1B,KAAK,sBACQ,sBAAsB,EAAE,SA6D7C,CAAA"} | ||
| {"version":3,"file":"peers.d.ts","sourceRoot":"","sources":["../../src/ideal/peers.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAGnC,OAAO,KAAK,EAEV,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,OAAO,KAAK,EACV,kBAAkB,EAElB,QAAQ,EACT,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC;;;;GAIG;AACH,KAAK,oBAAoB,GAAG;IAC1B,UAAU,EAAE,OAAO,CAAA;IACnB,gFAAgF;IAChF,SAAS,CAAC,EAAE,qBAAqB,GAAG;QAAE,MAAM,EAAE,IAAI,CAAA;KAAE,CAAA;CACrD,CAAA;AA6ID;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,wBAAwB,iBACrB,IAAI,YACR,IAAI,eACD,WAAW,SACjB,KAAK,KACX,oBAmLF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,gBACrB,WAAW,GAAG,SAAS,KACnC,MAAM,GAAG,SAKX,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,SACtB,IAAI,SACH,gBAAgB,KACtB,OAkBF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,YAC9B,qBAAqB,EAAE,KAC/B,qBAAqB,EAAsC,CAAA;AAQ9D,eAAO,MAAM,yBAAyB,gBACvB,WAAW,WACf,qBAAqB,EAAE,KAC/B,OAgBF,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,gBACrB,WAAW,WACf,qBAAqB,EAAE,YACtB,IAAI,aACH,QAAQ,KAClB,OA6DF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,UACnB,KAAK,eACC,WAAW,WACf,qBAAqB,EAAE,KAC/B,WA4CF,CAAA;AA0DD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,gBAChB,WAAW,YACd,QAAQ,YACR,IAAI,WACL,WAAW;;;CA4CrB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,gBACd,WAAW,YACd,UAAU,EAAE,gBACR,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,SAChD,KAAK,QACN,IAAI,YACA,IAAI,QACR,IAAI,QACJ,kBAAkB,iBACT,qBAAqB,EAAE;IAEtC;;;;;;;;;;;OAWG;;;;;;;;;;IAsDH;;;;;;;;;OASG;;CA4EH,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,sBAAsB,UAC1B,KAAK,sBACQ,sBAAsB,EAAE,SA6D7C,CAAA"} |
+73
-16
@@ -127,3 +127,32 @@ // helpers for managing peer dependency resolution | ||
| } | ||
| for (const [peerName, peerBareSpec] of Object.entries(peerDeps)) { | ||
| // Per-call memoization: avoid repeated satisfies() calls with identical args | ||
| const parseOpts = { | ||
| ...graph.mainImporter.options, | ||
| registry: fromNode.registry, | ||
| }; | ||
| const fromLocation = fromNode.location; | ||
| const projectRoot = fromNode.projectRoot; | ||
| const monorepo = graph.monorepo; | ||
| const satisfiesMemo = new Map(); | ||
| const satisfiesNodeSpec = (node, spec) => { | ||
| const key = `${node.id}\0${spec.type}\0${spec.bareSpec}\0${String(spec.final)}`; | ||
| let result = satisfiesMemo.get(key); | ||
| if (result === undefined) { | ||
| result = satisfies(node.id, spec, fromLocation, projectRoot, monorepo); | ||
| satisfiesMemo.set(key, result); | ||
| } | ||
| return result; | ||
| }; | ||
| const nodeSatisfiesAll = (node, specs) => { | ||
| for (const s of specs) { | ||
| if (!satisfiesNodeSpec(node, s)) | ||
| return false; | ||
| } | ||
| return true; | ||
| }; | ||
| for (const peerName in peerDeps) { | ||
| const peerBareSpec = peerDeps[peerName]; | ||
| /* c8 ignore next - peerDeps[peerName] is always defined when iterating */ | ||
| if (!peerBareSpec) | ||
| continue; | ||
| const existingEdge = existingNode.edgesOut.get(peerName); | ||
@@ -141,3 +170,3 @@ // CHECK 0: Reject reuse if peer edge doesn't exist yet (node unprocessed). | ||
| continue; | ||
| const peerSpec = parseSpec(peerName, peerBareSpec, fromNode, graph); | ||
| const peerSpec = Spec.parse(peerName, peerBareSpec, parseOpts); | ||
| // CHECK 1: Does peer context have a different target for this peer? | ||
@@ -148,2 +177,12 @@ const contextEntry = peerContext.get(peerName); | ||
| !shouldIgnoreContextMismatch(peerName, contextEntry.target, fromNode, graph)) { | ||
| // If existing edge target still satisfies the peer spec, no real conflict. | ||
| // The existing resolution is still valid even if context has a different target. | ||
| // This ensures idempotency when loading from lockfile where peer contexts | ||
| // are rebuilt fresh but existing nodes have valid peer resolutions. | ||
| const existingTarget = existingEdge.to; | ||
| const existingTargetSatisfiesPeer = satisfiesNodeSpec(existingTarget, peerSpec); | ||
| if (existingTargetSatisfiesPeer && | ||
| nodeSatisfiesAll(existingTarget, contextEntry.specs)) { | ||
| continue; // Truly no conflict | ||
| } | ||
| const result = buildIncompatibleResult(contextEntry.target, peerSpec, contextEntry.type, fromNode, graph); | ||
@@ -156,2 +195,10 @@ if (result) | ||
| if (siblingEdge?.to && siblingEdge.to.id !== existingEdge.to.id) { | ||
| // If existing edge target still satisfies the peer spec, no real conflict. | ||
| // Both sibling and existing targets may be valid - prefer keeping existing. | ||
| const existingTarget = existingEdge.to; | ||
| const existingTargetSatisfiesPeer = satisfiesNodeSpec(existingTarget, peerSpec); | ||
| if (existingTargetSatisfiesPeer && | ||
| satisfiesNodeSpec(existingTarget, siblingEdge.spec)) { | ||
| continue; // Truly no conflict | ||
| } | ||
| const result = buildIncompatibleResult(siblingEdge.to, peerSpec, siblingEdge.type, fromNode, graph); | ||
@@ -180,17 +227,27 @@ if (result) | ||
| if (declared && declaredType) { | ||
| const parentSpec = parseSpec(peerName, declared, fromNode, graph); | ||
| for (const candidateNode of graph.nodes.values()) { | ||
| if (candidateNode.name === peerName && | ||
| candidateNode.id !== existingEdge.to.id && | ||
| nodeSatisfiesSpec(candidateNode, parentSpec, fromNode, graph) && | ||
| nodeSatisfiesSpec(candidateNode, peerSpec, fromNode, graph)) { | ||
| return { | ||
| compatible: false, | ||
| forkEntry: { | ||
| spec: peerSpec, | ||
| target: candidateNode, | ||
| type: shorten(declaredType), | ||
| }, | ||
| }; | ||
| const parentSpec = Spec.parse(peerName, declared, parseOpts); | ||
| // If existing edge target already satisfies parent's declared spec, | ||
| // there's no conflict - the parent can use the same node as the existing | ||
| // peer edge. Only search for alternatives if existing target is incompatible. | ||
| if (satisfiesNodeSpec(existingEdge.to, parentSpec)) { | ||
| continue; // Existing target works for parent too, no conflict | ||
| } | ||
| // Use nodesByName (deterministic DepID order) instead of full graph scan | ||
| const candidates = graph.nodesByName.get(peerName); | ||
| if (candidates) { | ||
| for (const candidateNode of candidates) { | ||
| if (candidateNode.id !== existingEdge.to.id && | ||
| satisfiesNodeSpec(candidateNode, parentSpec) && | ||
| satisfiesNodeSpec(candidateNode, peerSpec)) { | ||
| return { | ||
| compatible: false, | ||
| forkEntry: { | ||
| spec: peerSpec, | ||
| target: candidateNode, | ||
| type: shorten(declaredType), | ||
| }, | ||
| }; | ||
| } | ||
| } | ||
| /* c8 ignore next */ | ||
| } | ||
@@ -197,0 +254,0 @@ } |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"peers.js","sourceRoot":"","sources":["../../src/ideal/peers.ts"],"names":[],"mappings":"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","sourcesContent":["// helpers for managing peer dependency resolution\n// during the ideal graph building process.\n\nimport { intersects } from '@vltpkg/semver'\nimport { satisfies } from '@vltpkg/satisfies'\nimport { Spec } from '@vltpkg/spec'\nimport { getDependencies, shorten } from '../dependencies.ts'\nimport { compareByType, getOrderedDependencies } from './sorting.ts'\nimport type {\n ProcessPlacementResultEntry,\n PeerContext,\n PeerContextEntry,\n PeerContextEntryInput,\n ProcessPlacementResult,\n} from './types.ts'\nimport type { SpecOptions } from '@vltpkg/spec'\nimport { longDependencyTypes } from '@vltpkg/types'\nimport type {\n DependencySaveType,\n DependencyTypeLong,\n Manifest,\n} from '@vltpkg/types'\nimport type { Monorepo } from '@vltpkg/workspaces'\nimport type { Dependency } from '../dependencies.ts'\nimport type { Graph } from '../graph.ts'\nimport type { Node } from '../node.ts'\n\n/**\n * Result of checking if an existing node's peer edges are compatible\n * with a new parent's context. The `forkEntry` property is optional\n * and will only be present if the node's peer edges are incompatible.\n */\ntype PeerEdgeCompatResult = {\n compatible: boolean\n /** When incompatible, entry to add to forked context (target always present) */\n forkEntry?: PeerContextEntryInput & { target: Node }\n}\n\n/**\n * Check if a node satisfies a spec within a given context.\n *\n * Wraps the common `satisfies()` call pattern used throughout peer dependency\n * resolution. The satisfaction check requires:\n * - `node.id`: The DepID of the candidate node\n * - `spec`: The spec to satisfy (e.g., `^18.0.0`)\n * - `fromNode.location`: Where the dependency is declared (affects file: specs)\n * - `projectRoot`: For resolving workspace specs\n * - `monorepo`: For workspace-aware resolution\n */\nconst nodeSatisfiesSpec = (\n node: Node,\n spec: Spec,\n fromNode: Node,\n graph: Graph,\n): boolean =>\n satisfies(\n node.id,\n spec,\n fromNode.location,\n fromNode.projectRoot,\n graph.monorepo,\n )\n\n/**\n * Parse a spec with registry options from a parent node context.\n *\n * Inherits registry configuration from `graph.mainImporter.options` to ensure\n * consistent scope-registry and custom registry mappings. The `fromNode.registry`\n * override allows scoped packages to use their configured registry.\n */\nconst parseSpec = (\n name: string,\n bareSpec: string,\n fromNode: Node,\n graph: Graph,\n): Spec =>\n Spec.parse(name, bareSpec, {\n ...graph.mainImporter.options,\n registry: fromNode.registry,\n })\n\n/**\n * Generate a unique cache key for a peer context fork operation.\n *\n * Format: `{baseIndex}::{sortedEntrySignatures}`\n * - `baseIndex`: The parent context's index (0 for initial context)\n * - Entry signature: `{name}|{type}|{targetId}|{spec}` sorted alphabetically\n *\n * This enables caching identical fork operations to avoid creating duplicate\n * peer contexts when the same entries would be added to the same base context.\n */\nconst getForkKey = (\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n) => {\n const base = peerContext.index ?? 0\n const sig = entries\n .map(\n e =>\n `${e.spec.final.name}|${e.type}|${e.target?.id ?? '∅'}|${e.spec}`,\n )\n .sort()\n .join(';')\n return `${base}::${sig}`\n}\n\n/**\n * Check if parent declares a dep for peerName that the context target doesn't satisfy.\n * If so, the context entry isn't applicable - return true to ignore the mismatch.\n *\n * This prevents cross-importer peer context leakage. Example scenario:\n * - Root importer has `react@^18` in peer context\n * - Workspace A declares `react@^19` as a dependency\n * - When checking compatibility for Workspace A's deps, the `react@^18` context\n * entry shouldn't force a fork because Workspace A will resolve its own react\n *\n * The logic: if parent declares peerName and the context target doesn't satisfy\n * parent's declared spec, the context entry won't be used anyway, so ignore it.\n */\nconst shouldIgnoreContextMismatch = (\n peerName: string,\n contextTarget: Node,\n fromNode: Node,\n graph: Graph,\n): boolean => {\n const parentManifest = fromNode.manifest\n /* c8 ignore next - edge case: fromNode always has manifest in practice */\n if (!parentManifest) return false\n\n // Search all dependency types for a declaration of peerName\n for (const depType of longDependencyTypes) {\n const declared = parentManifest[depType]?.[peerName]\n if (!declared) continue\n\n // Parent declares this package - check if context target satisfies it\n const parentSpec = parseSpec(peerName, declared, fromNode, graph)\n // If context target doesn't satisfy parent's spec, ignore the mismatch\n // because parent will resolve its own version anyway\n return !nodeSatisfiesSpec(\n contextTarget,\n parentSpec,\n fromNode,\n graph,\n )\n }\n return false\n}\n\n/**\n * Build incompatible result if target satisfies the peer spec.\n *\n * Returns an incompatible result only when the target node actually satisfies\n * the peer spec. This matters because:\n * - If target satisfies the spec, it's a valid alternative that conflicts with\n * the existing node's peer edge target\n * - If target doesn't satisfy the spec, it's not a valid peer resolution, so\n * there's no conflict to report\n *\n * The returned `forkEntry` contains the conflicting spec and target, which will\n * be used to create a forked peer context with the alternative resolution.\n */\nconst buildIncompatibleResult = (\n target: Node,\n peerSpec: Spec,\n type: DependencySaveType,\n fromNode: Node,\n graph: Graph,\n): PeerEdgeCompatResult | undefined => {\n if (nodeSatisfiesSpec(target, peerSpec, fromNode, graph)) {\n return {\n compatible: false,\n forkEntry: { spec: peerSpec, target, type },\n }\n }\n return undefined\n}\n\n/**\n * Check if an existing node's peer edges would still resolve to the same\n * targets from a new parent's context. Returns incompatible info if any\n * peer would resolve differently, meaning the node should NOT be reused.\n *\n * This is crucial for avoiding incorrect node reuse that would break peer\n * dependency contracts. Three sources of conflict are checked:\n *\n * 1. **Peer context entries**: The global peer context may have resolved a\n * different version of a peer dependency than what the existing node expects.\n *\n * 2. **Already-placed siblings**: The parent node may already have an edge to\n * a different version of the peer dependency.\n *\n * 3. **Not-yet-placed siblings**: The parent's manifest declares a dependency\n * on the same package, and there's a graph node that would satisfy it but\n * differs from what the existing node expects.\n */\nexport const checkPeerEdgesCompatible = (\n existingNode: Node,\n fromNode: Node,\n peerContext: PeerContext,\n graph: Graph,\n): PeerEdgeCompatResult => {\n const peerDeps = existingNode.manifest?.peerDependencies\n // No peer deps = always compatible\n if (!peerDeps || Object.keys(peerDeps).length === 0) {\n return { compatible: true }\n }\n\n for (const [peerName, peerBareSpec] of Object.entries(peerDeps)) {\n const existingEdge = existingNode.edgesOut.get(peerName)\n\n // CHECK 0: Reject reuse if peer edge doesn't exist yet (node unprocessed).\n // Cannot verify compatibility since peer resolution depends on original\n // placement context, which may differ from current parent's context.\n // Note: Dangling edges (edge exists, no target) are handled separately below.\n // This conservative check prevents incorrect reuse when placement order varies.\n if (existingEdge === undefined) {\n return { compatible: false }\n }\n\n // Dangling peer edge (edge exists but unresolved) - skip, nothing to conflict with\n if (!existingEdge.to) continue\n\n const peerSpec = parseSpec(\n peerName,\n peerBareSpec,\n fromNode,\n graph,\n )\n\n // CHECK 1: Does peer context have a different target for this peer?\n const contextEntry = peerContext.get(peerName)\n if (\n contextEntry?.target &&\n contextEntry.target.id !== existingEdge.to.id &&\n !shouldIgnoreContextMismatch(\n peerName,\n contextEntry.target,\n fromNode,\n graph,\n )\n ) {\n const result = buildIncompatibleResult(\n contextEntry.target,\n peerSpec,\n contextEntry.type,\n fromNode,\n graph,\n )\n if (result) return result\n }\n\n // CHECK 2: Does parent already have an edge to a different version?\n const siblingEdge = fromNode.edgesOut.get(peerName)\n if (siblingEdge?.to && siblingEdge.to.id !== existingEdge.to.id) {\n const result = buildIncompatibleResult(\n siblingEdge.to,\n peerSpec,\n siblingEdge.type,\n fromNode,\n graph,\n )\n if (result) return result\n }\n\n // CHECK 3: Does parent's manifest declare this peer, with a different\n // satisfying node already in the graph?\n const manifest = fromNode.manifest\n let declared: string | undefined\n let declaredType: DependencyTypeLong | undefined\n\n if (manifest) {\n for (const depType of longDependencyTypes) {\n const deps = manifest[depType]\n if (\n deps &&\n typeof deps === 'object' &&\n !Array.isArray(deps) &&\n peerName in deps\n ) {\n declared = deps[peerName]\n declaredType = depType\n break\n }\n }\n }\n\n if (declared && declaredType) {\n const parentSpec = parseSpec(\n peerName,\n declared,\n fromNode,\n graph,\n )\n for (const candidateNode of graph.nodes.values()) {\n if (\n candidateNode.name === peerName &&\n candidateNode.id !== existingEdge.to.id &&\n nodeSatisfiesSpec(\n candidateNode,\n parentSpec,\n fromNode,\n graph,\n ) &&\n nodeSatisfiesSpec(candidateNode, peerSpec, fromNode, graph)\n ) {\n return {\n compatible: false,\n forkEntry: {\n spec: peerSpec,\n target: candidateNode,\n type: shorten(declaredType),\n },\n }\n }\n }\n }\n }\n\n return { compatible: true }\n}\n\n/**\n * Retrieve a unique hash value for a given peer context set.\n */\nexport const retrievePeerContextHash = (\n peerContext: PeerContext | undefined,\n): string | undefined => {\n // skips creating the initial peer context ref\n if (!peerContext?.index) return undefined\n\n return `peer.${peerContext.index}`\n}\n\n/**\n * Checks if a given spec is compatible with the specs already\n * assigned to a peer context entry.\n *\n * Returns true if INCOMPATIBLE, false if compatible.\n *\n * Compatibility rules:\n * - **Registry specs**: Uses semver range intersection. `^18.0.0` and `^18.2.0`\n * intersect (compatible), but `^18.0.0` and `^19.0.0` don't (incompatible).\n * - **Non-registry specs** (git, file, etc.): Requires exact bareSpec match.\n * `github:foo/bar#v1` only matches itself.\n *\n * This is used to determine when peer context forking is needed - if specs\n * are incompatible, a new peer context must be created.\n */\nexport const incompatibleSpecs = (\n spec: Spec,\n entry: PeerContextEntry,\n): boolean => {\n if (entry.specs.size > 0) {\n for (const s_ of entry.specs) {\n const s = s_.final\n if (\n // Registry types: check semver range intersection\n (spec.type === 'registry' &&\n (!spec.range ||\n !s.range ||\n !intersects(spec.range, s.range))) ||\n // Non-registry types: require exact bareSpec match\n (spec.type !== 'registry' && spec.bareSpec !== s.bareSpec)\n ) {\n return true\n }\n }\n }\n return false\n}\n\n/**\n * Sort peer context entry inputs for deterministic processing.\n * Orders: non-peer dependencies first, then peer dependencies, alphabetically by name.\n */\nexport const getOrderedPeerContextEntries = (\n entries: PeerContextEntryInput[],\n): PeerContextEntryInput[] => [...entries].sort(compareByType)\n\n/*\n * Checks if there are any conflicting versions for a given dependency\n * to be added to a peer context set which will require forking.\n *\n * Returns true if forking is needed, false otherwise.\n */\nexport const checkEntriesToPeerContext = (\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n): boolean => {\n // check on compatibility of new entries\n for (const { spec, target } of entries) {\n const name = target?.name ?? spec.final.name\n\n // skip any inactive entry\n const entry = peerContext.get(name)\n if (!entry?.active) continue\n\n // validate if the provided spec is compatible with existing specs\n if (incompatibleSpecs(spec.final, entry)) {\n return true\n }\n }\n\n return false\n}\n\n/**\n * Add or update dependencies in a given peer context making sure to check\n * for compatibility with existing dependencies already resolved by a given\n * peer context set. Extra info such as a target or dependent nodes is\n * optional.\n *\n * Returns true if forking is needed, false otherwise.\n */\nexport const addEntriesToPeerContext = (\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n fromNode: Node,\n monorepo?: Monorepo,\n): boolean => {\n // pre check for conflicts before processing\n if (checkEntriesToPeerContext(peerContext, entries)) return true\n\n for (const { dependent, spec, target, type } of entries) {\n const name = target?.name ?? spec.final.name\n let entry = peerContext.get(name)\n\n // create new entry if none exists\n if (!entry) {\n entry = {\n active: true,\n specs: new Set([spec]),\n target,\n type,\n contextDependents: new Set(),\n }\n peerContext.set(name, entry)\n if (dependent) entry.contextDependents.add(dependent)\n continue\n }\n\n // check for sibling dep conflicts\n if (incompatibleSpecs(spec.final, entry)) return true\n\n // update target if compatible with all specs\n if (\n target &&\n [...entry.specs].every(s =>\n satisfies(\n target.id,\n s,\n fromNode.location,\n fromNode.projectRoot,\n monorepo,\n ),\n )\n ) {\n if (\n target.id !== entry.target?.id &&\n target.version !== entry.target?.version\n ) {\n // update dependents to point to new target\n for (const dep of entry.contextDependents) {\n const edge = dep.edgesOut.get(name)\n if (edge?.to && edge.to !== target) {\n edge.to.edgesIn.delete(edge)\n edge.to = target\n target.edgesIn.add(edge)\n }\n }\n entry.target = target\n }\n entry.target ??= target\n }\n\n entry.specs.add(spec)\n if (dependent) entry.contextDependents.add(dependent)\n }\n\n return false\n}\n\n/**\n * Create and returns a forked copy of a given peer context set.\n */\nexport const forkPeerContext = (\n graph: Graph,\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n): PeerContext => {\n const forkKey = getForkKey(peerContext, entries)\n const cached = graph.peerContextForkCache.get(forkKey)\n if (cached) {\n return cached\n }\n\n // create a new peer context set\n const nextPeerContext: PeerContext = new Map()\n nextPeerContext.index = graph.nextPeerContextIndex()\n // register it in the graph\n graph.peerContexts[nextPeerContext.index] = nextPeerContext\n graph.peerContextForkCache.set(forkKey, nextPeerContext)\n\n // copy existing entries marking them as inactive, it's also important\n // to note that specs and contextDependents are new objects so that changes\n // to those in the new context do not affect the previous one\n for (const [name, entry] of peerContext.entries()) {\n nextPeerContext.set(name, {\n active: false,\n specs: new Set(entry.specs),\n target: undefined,\n type: entry.type,\n contextDependents: new Set(entry.contextDependents),\n })\n }\n\n // add the new entries to this peer context set, marking them as active\n // these are the entries that were incompatible with the previous context set\n for (const entry of entries) {\n const { dependent, spec, target, type } = entry\n const name = target?.name /* c8 ignore next */ ?? spec.final.name\n const newEntry = {\n active: true,\n specs: new Set([spec]),\n target,\n type,\n contextDependents:\n dependent ? new Set([dependent]) : new Set<Node>(),\n }\n nextPeerContext.set(name, newEntry)\n }\n\n return nextPeerContext\n}\n\n/**\n * Find a peer from queued entries' peer edge closure using BFS.\n *\n * This handles peer dependency cycles like `@isaacs/peer-dep-cycle-a/b/c` where:\n * - A depends on B (peer)\n * - B depends on C (peer)\n * - C depends on A (peer)\n *\n * The BFS explores:\n * 1. Start nodes: All resolved targets from `queuedEntries` (sibling deps)\n * 2. For each node, check if it has an edge to `name` that satisfies `peerSpec`\n * 3. If not found, follow peer edges to explore their peer edges (up to depth 3)\n *\n * Prefers \"local\" providers (found via sibling's peer edges) over global context.\n */\nconst findFromPeerClosure = (\n name: string,\n peerSpec: Spec,\n queuedEntries: PeerContextEntryInput[],\n fromNode: Node,\n graph: Graph,\n): Node | undefined => {\n // Start BFS from all resolved sibling targets\n const start = queuedEntries\n .map(e => e.target)\n .filter((n): n is Node => !!n)\n const seen = new Set<string>()\n const q: { n: Node; depth: number }[] = start.map(n => ({\n n,\n depth: 0,\n }))\n\n while (q.length) {\n const cur = q.shift()\n if (!cur || seen.has(cur.n.id)) continue\n seen.add(cur.n.id)\n\n // Check if this node has an edge to the peer we're looking for\n const edge = cur.n.edgesOut.get(name)\n if (\n edge?.to &&\n nodeSatisfiesSpec(edge.to, peerSpec, fromNode, graph)\n ) {\n return edge.to\n }\n\n // Follow peer edges only (not regular deps) to stay in peer closure\n for (const e of cur.n.edgesOut.values()) {\n if ((e.type === 'peer' || e.type === 'peerOptional') && e.to) {\n q.push({ n: e.to, depth: cur.depth + 1 })\n }\n }\n }\n return undefined\n}\n\n/**\n * Starts the peer dependency placement process\n * for a given node being processed and placed.\n */\nexport const startPeerPlacement = (\n peerContext: PeerContext,\n manifest: Manifest,\n fromNode: Node,\n options: SpecOptions,\n) => {\n // queue entries so that they can be added at the end of the placement\n // process, use a map to ensure deduplication between read json dep\n // values and the resolved edges in the graph\n const queueMap = new Map<string, PeerContextEntryInput>()\n let peerSetHash: string | undefined\n\n if (\n manifest.peerDependencies &&\n Object.keys(manifest.peerDependencies).length > 0\n ) {\n // generates a peer context set hash for nodes that\n // have peer dependencies to be resolved\n peerSetHash = retrievePeerContextHash(peerContext)\n\n // get any potential sibling dependency from the\n // parent node that might have not been parsed yet\n const siblingDeps = getDependencies(fromNode, {\n ...options,\n registry: fromNode.registry,\n })\n for (const [depName, dep] of siblingDeps) {\n queueMap.set(depName, dep)\n }\n\n // collect the already parsed nodes and add those to the\n // list of entries to be added to the peer context set\n for (const edge of fromNode.edgesOut.values()) {\n queueMap.set(edge.name, {\n spec: edge.spec,\n target: edge.to,\n type: edge.type,\n })\n }\n }\n\n return {\n peerSetHash,\n // Sort queuedEntries for deterministic order\n queuedEntries: getOrderedPeerContextEntries([\n ...queueMap.values(),\n ]),\n }\n}\n\n/**\n * Ends the peer dependency placement process, returning the functions that\n * are going to be used to update the peer context set, forking when needed\n * and resolving peer dependencies if possible.\n *\n * Returns two deferred functions:\n * - `putEntries()`: Adds entries to peer context; returns fork entries if conflict\n * - `resolvePeerDeps()`: Resolves peer deps from context/siblings or adds to nextDeps\n *\n * These are deferred (not executed immediately) so that all siblings at a level\n * can be processed before peer context updates, enabling context reuse optimization.\n */\nexport const endPeerPlacement = (\n peerContext: PeerContext,\n nextDeps: Dependency[],\n nextPeerDeps: Map<string, Dependency> & { id?: number },\n graph: Graph,\n spec: Spec,\n fromNode: Node,\n node: Node,\n type: DependencySaveType,\n queuedEntries: PeerContextEntryInput[],\n) => ({\n /**\n * Add the new entries to the current peer context set.\n *\n * Two sets of entries are checked:\n * - `prevEntries`: Parent's queued entries + self-reference\n * - `nextEntries`: This node's deps + peer deps (with node as dependent)\n *\n * If either conflicts with the current context, returns ALL entries to be\n * added to a forked context (prevEntries last for priority).\n *\n * Returns `undefined` if no fork needed (entries added directly to context).\n */\n putEntries: () => {\n // add queued entries from this node parents along\n // with a self-ref to the current peer context set\n const prevEntries = [\n ...queuedEntries,\n /* ref itself */ {\n spec,\n target: node,\n type,\n },\n ]\n\n const nextEntries = [\n ...nextDeps.map(dep => ({ ...dep, dependent: node })),\n ...[...nextPeerDeps.values()].map(dep => ({\n ...dep,\n dependent: node,\n })),\n ]\n\n const conflictPrev = checkEntriesToPeerContext(\n peerContext,\n prevEntries,\n )\n const conflictNext =\n nextEntries.length > 0 &&\n checkEntriesToPeerContext(peerContext, nextEntries)\n\n if (conflictPrev || conflictNext) {\n // returns all entries that need to be added to a forked context\n // giving priority to parent entries (prevEntries) by placing them last\n return [...nextEntries, ...prevEntries]\n }\n\n addEntriesToPeerContext(\n peerContext,\n prevEntries,\n fromNode,\n graph.monorepo,\n )\n\n if (nextEntries.length > 0) {\n addEntriesToPeerContext(\n peerContext,\n nextEntries,\n node,\n graph.monorepo,\n )\n }\n\n return undefined\n },\n\n /**\n * Try to resolve peer dependencies using already seen target\n * values from the current peer context set.\n *\n * Resolution priority (highest to lowest):\n * 1. Sibling deps from parent (workspace direct deps take priority)\n * 2. Peer-edge closure of sibling targets (handles peer cycles)\n * 3. Global peer context set entries\n * 4. Add to nextDeps for normal resolution (or create dangling edge for optional)\n */\n resolvePeerDeps: () => {\n for (const nextDep of nextPeerDeps.values()) {\n const { spec, type } = nextDep\n /* c8 ignore next - only peer types reach here by design */\n if (type !== 'peer' && type !== 'peerOptional') continue\n\n const name = spec.final.name\n\n // PRIORITY 1: Sibling deps from parent\n // These take priority because workspace's direct deps should win over\n // versions from other workspaces that may be in the peer context\n const siblingEntry = queuedEntries.find(\n e => (e.target?.name ?? e.spec.final.name) === name,\n )\n const siblingTarget =\n siblingEntry?.target ?? fromNode.edgesOut.get(name)?.to\n\n if (\n siblingTarget &&\n nodeSatisfiesSpec(siblingTarget, spec, fromNode, graph)\n ) {\n // Override existing edge if pointing elsewhere (sibling must win)\n const existingEdge = node.edgesOut.get(name)\n if (existingEdge?.to && existingEdge.to !== siblingTarget) {\n existingEdge.to.edgesIn.delete(existingEdge)\n existingEdge.to = siblingTarget\n siblingTarget.edgesIn.add(existingEdge)\n } else if (!existingEdge) {\n graph.addEdge(type, spec, node, siblingTarget)\n }\n continue\n }\n\n // PRIORITY 2: Peer-edge closure of sibling targets\n // Handles cycles like A->B(peer)->C(peer)->A(peer)\n const localPeer = findFromPeerClosure(\n name,\n spec,\n queuedEntries,\n fromNode,\n graph,\n )\n if (localPeer && !node.edgesOut.has(name)) {\n graph.addEdge(type, spec, node, localPeer)\n continue\n }\n\n // PRIORITY 3: Global peer context set\n const entry = peerContext.get(name)\n if (\n !node.edgesOut.has(name) &&\n entry?.target &&\n nodeSatisfiesSpec(entry.target, spec, fromNode, graph)\n ) {\n graph.addEdge(type, spec, node, entry.target)\n entry.specs.add(spec.final)\n continue\n }\n\n // PRIORITY 4: Fallback - add to nextDeps or create dangling edge\n if (type === 'peerOptional') {\n // Optional peers that can't be resolved get a dangling edge\n graph.addEdge(type, spec, node)\n } else if (\n siblingEntry &&\n siblingEntry.spec.bareSpec !== spec.bareSpec\n ) {\n // Sibling has a more specific spec - use it for resolution\n nextDeps.push({ ...nextDep, spec: siblingEntry.spec })\n } else {\n // Add to next deps for normal resolution in upcoming levels\n nextDeps.push(nextDep)\n }\n }\n },\n})\n\n/**\n * Given an array of processed results for the current level dependencies\n * being placed in the currently building ideal graph, traverse its direct\n * dependencies and track peer dependencies in their appropriate peer context\n * sets, forking as needed and resolving peer dependencies using suitable\n * nodes already present in the graph if possible.\n *\n * This is the core peer context management algorithm, executed after each\n * BFS level. It runs in three phases:\n *\n * **Phase 1: Collect fork requirements**\n * Call `putEntries()` on each child dep to add entries to peer context.\n * Collect which children need forked contexts (due to conflicts).\n *\n * **Phase 2: Fork or reuse contexts**\n * For children needing forks, try to reuse a sibling's forked context if\n * compatible. This optimization reduces the number of peer contexts created.\n *\n * **Phase 3: Resolve peer deps**\n * With contexts finalized, call `resolvePeerDeps()` to create edges for\n * peers that can be satisfied from context/siblings, or add them to nextDeps.\n *\n * All operations are sorted by `node.id` for deterministic, reproducible builds.\n */\nexport const postPlacementPeerCheck = (\n graph: Graph,\n sortedLevelResults: ProcessPlacementResult[],\n) => {\n for (const childDepsToProcess of sortedLevelResults) {\n // Sort by node.id for deterministic processing order\n const sortedChildDeps = [...childDepsToProcess].sort((a, b) =>\n a.node.id.localeCompare(b.node.id, 'en'),\n )\n\n // PHASE 1: Collect which children need forked contexts\n const needsForking = new Map<\n ProcessPlacementResultEntry,\n PeerContextEntryInput[]\n >()\n for (const childDep of sortedChildDeps) {\n const needsFork = childDep.updateContext.putEntries()\n if (needsFork) {\n needsForking.set(childDep, needsFork)\n }\n }\n\n // Sort forking entries for deterministic fork order\n const sortedNeedsForkingEntries = [\n ...needsForking.entries(),\n ].sort(([a], [b]) => a.node.id.localeCompare(b.node.id, 'en'))\n\n // PHASE 2: Fork or reuse sibling contexts\n // Track previous context for potential reuse by next sibling\n let prevContext\n for (const [childDep, nextEntries] of sortedNeedsForkingEntries) {\n // Optimization: try to reuse previous sibling's forked context\n // if its entries are compatible with this child's entries\n if (\n prevContext &&\n !checkEntriesToPeerContext(prevContext, nextEntries)\n ) {\n addEntriesToPeerContext(\n prevContext,\n nextEntries,\n childDep.node,\n graph.monorepo,\n )\n childDep.peerContext = prevContext\n continue\n }\n\n // Can't reuse - create a new forked context\n childDep.peerContext = forkPeerContext(\n graph,\n childDep.peerContext,\n nextEntries,\n )\n prevContext = childDep.peerContext\n }\n\n // PHASE 3: Resolve peer deps with finalized contexts\n for (const childDep of sortedChildDeps) {\n childDep.updateContext.resolvePeerDeps()\n // Re-order deps for deterministic next-level processing\n childDep.deps = getOrderedDependencies(childDep.deps)\n }\n }\n}\n"]} | ||
| {"version":3,"file":"peers.js","sourceRoot":"","sources":["../../src/ideal/peers.ts"],"names":[],"mappings":"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","sourcesContent":["// helpers for managing peer dependency resolution\n// during the ideal graph building process.\n\nimport { intersects } from '@vltpkg/semver'\nimport { satisfies } from '@vltpkg/satisfies'\nimport { Spec } from '@vltpkg/spec'\nimport { getDependencies, shorten } from '../dependencies.ts'\nimport { compareByType, getOrderedDependencies } from './sorting.ts'\nimport type {\n ProcessPlacementResultEntry,\n PeerContext,\n PeerContextEntry,\n PeerContextEntryInput,\n ProcessPlacementResult,\n} from './types.ts'\nimport type { SpecOptions } from '@vltpkg/spec'\nimport { longDependencyTypes } from '@vltpkg/types'\nimport type {\n DependencySaveType,\n DependencyTypeLong,\n Manifest,\n} from '@vltpkg/types'\nimport type { Monorepo } from '@vltpkg/workspaces'\nimport type { Dependency } from '../dependencies.ts'\nimport type { Graph } from '../graph.ts'\nimport type { Node } from '../node.ts'\n\n/**\n * Result of checking if an existing node's peer edges are compatible\n * with a new parent's context. The `forkEntry` property is optional\n * and will only be present if the node's peer edges are incompatible.\n */\ntype PeerEdgeCompatResult = {\n compatible: boolean\n /** When incompatible, entry to add to forked context (target always present) */\n forkEntry?: PeerContextEntryInput & { target: Node }\n}\n\n/**\n * Check if a node satisfies a spec within a given context.\n *\n * Wraps the common `satisfies()` call pattern used throughout peer dependency\n * resolution. The satisfaction check requires:\n * - `node.id`: The DepID of the candidate node\n * - `spec`: The spec to satisfy (e.g., `^18.0.0`)\n * - `fromNode.location`: Where the dependency is declared (affects file: specs)\n * - `projectRoot`: For resolving workspace specs\n * - `monorepo`: For workspace-aware resolution\n */\nconst nodeSatisfiesSpec = (\n node: Node,\n spec: Spec,\n fromNode: Node,\n graph: Graph,\n): boolean =>\n satisfies(\n node.id,\n spec,\n fromNode.location,\n fromNode.projectRoot,\n graph.monorepo,\n )\n\n/**\n * Parse a spec with registry options from a parent node context.\n *\n * Inherits registry configuration from `graph.mainImporter.options` to ensure\n * consistent scope-registry and custom registry mappings. The `fromNode.registry`\n * override allows scoped packages to use their configured registry.\n */\nconst parseSpec = (\n name: string,\n bareSpec: string,\n fromNode: Node,\n graph: Graph,\n): Spec =>\n Spec.parse(name, bareSpec, {\n ...graph.mainImporter.options,\n registry: fromNode.registry,\n })\n\n/**\n * Generate a unique cache key for a peer context fork operation.\n *\n * Format: `{baseIndex}::{sortedEntrySignatures}`\n * - `baseIndex`: The parent context's index (0 for initial context)\n * - Entry signature: `{name}|{type}|{targetId}|{spec}` sorted alphabetically\n *\n * This enables caching identical fork operations to avoid creating duplicate\n * peer contexts when the same entries would be added to the same base context.\n */\nconst getForkKey = (\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n) => {\n const base = peerContext.index ?? 0\n const sig = entries\n .map(\n e =>\n `${e.spec.final.name}|${e.type}|${e.target?.id ?? '∅'}|${e.spec}`,\n )\n .sort()\n .join(';')\n return `${base}::${sig}`\n}\n\n/**\n * Check if parent declares a dep for peerName that the context target doesn't satisfy.\n * If so, the context entry isn't applicable - return true to ignore the mismatch.\n *\n * This prevents cross-importer peer context leakage. Example scenario:\n * - Root importer has `react@^18` in peer context\n * - Workspace A declares `react@^19` as a dependency\n * - When checking compatibility for Workspace A's deps, the `react@^18` context\n * entry shouldn't force a fork because Workspace A will resolve its own react\n *\n * The logic: if parent declares peerName and the context target doesn't satisfy\n * parent's declared spec, the context entry won't be used anyway, so ignore it.\n */\nconst shouldIgnoreContextMismatch = (\n peerName: string,\n contextTarget: Node,\n fromNode: Node,\n graph: Graph,\n): boolean => {\n const parentManifest = fromNode.manifest\n /* c8 ignore next - edge case: fromNode always has manifest in practice */\n if (!parentManifest) return false\n\n // Search all dependency types for a declaration of peerName\n for (const depType of longDependencyTypes) {\n const declared = parentManifest[depType]?.[peerName]\n if (!declared) continue\n\n // Parent declares this package - check if context target satisfies it\n const parentSpec = parseSpec(peerName, declared, fromNode, graph)\n // If context target doesn't satisfy parent's spec, ignore the mismatch\n // because parent will resolve its own version anyway\n return !nodeSatisfiesSpec(\n contextTarget,\n parentSpec,\n fromNode,\n graph,\n )\n }\n return false\n}\n\n/**\n * Build incompatible result if target satisfies the peer spec.\n *\n * Returns an incompatible result only when the target node actually satisfies\n * the peer spec. This matters because:\n * - If target satisfies the spec, it's a valid alternative that conflicts with\n * the existing node's peer edge target\n * - If target doesn't satisfy the spec, it's not a valid peer resolution, so\n * there's no conflict to report\n *\n * The returned `forkEntry` contains the conflicting spec and target, which will\n * be used to create a forked peer context with the alternative resolution.\n */\nconst buildIncompatibleResult = (\n target: Node,\n peerSpec: Spec,\n type: DependencySaveType,\n fromNode: Node,\n graph: Graph,\n): PeerEdgeCompatResult | undefined => {\n if (nodeSatisfiesSpec(target, peerSpec, fromNode, graph)) {\n return {\n compatible: false,\n forkEntry: { spec: peerSpec, target, type },\n }\n }\n return undefined\n}\n\n/**\n * Check if an existing node's peer edges would still resolve to the same\n * targets from a new parent's context. Returns incompatible info if any\n * peer would resolve differently, meaning the node should NOT be reused.\n *\n * This is crucial for avoiding incorrect node reuse that would break peer\n * dependency contracts. Three sources of conflict are checked:\n *\n * 1. **Peer context entries**: The global peer context may have resolved a\n * different version of a peer dependency than what the existing node expects.\n *\n * 2. **Already-placed siblings**: The parent node may already have an edge to\n * a different version of the peer dependency.\n *\n * 3. **Not-yet-placed siblings**: The parent's manifest declares a dependency\n * on the same package, and there's a graph node that would satisfy it but\n * differs from what the existing node expects.\n */\nexport const checkPeerEdgesCompatible = (\n existingNode: Node,\n fromNode: Node,\n peerContext: PeerContext,\n graph: Graph,\n): PeerEdgeCompatResult => {\n const peerDeps = existingNode.manifest?.peerDependencies\n // No peer deps = always compatible\n if (!peerDeps || Object.keys(peerDeps).length === 0) {\n return { compatible: true }\n }\n\n // Per-call memoization: avoid repeated satisfies() calls with identical args\n const parseOpts = {\n ...graph.mainImporter.options,\n registry: fromNode.registry,\n }\n const fromLocation = fromNode.location\n const projectRoot = fromNode.projectRoot\n const monorepo = graph.monorepo\n const satisfiesMemo = new Map<string, boolean>()\n const satisfiesNodeSpec = (node: Node, spec: Spec): boolean => {\n const key = `${node.id}\\0${spec.type}\\0${spec.bareSpec}\\0${String(spec.final)}`\n let result = satisfiesMemo.get(key)\n if (result === undefined) {\n result = satisfies(\n node.id,\n spec,\n fromLocation,\n projectRoot,\n monorepo,\n )\n satisfiesMemo.set(key, result)\n }\n return result\n }\n const nodeSatisfiesAll = (\n node: Node,\n specs: Iterable<Spec>,\n ): boolean => {\n for (const s of specs) {\n if (!satisfiesNodeSpec(node, s)) return false\n }\n return true\n }\n\n for (const peerName in peerDeps) {\n const peerBareSpec = peerDeps[peerName]\n /* c8 ignore next - peerDeps[peerName] is always defined when iterating */\n if (!peerBareSpec) continue\n const existingEdge = existingNode.edgesOut.get(peerName)\n\n // CHECK 0: Reject reuse if peer edge doesn't exist yet (node unprocessed).\n // Cannot verify compatibility since peer resolution depends on original\n // placement context, which may differ from current parent's context.\n // Note: Dangling edges (edge exists, no target) are handled separately below.\n // This conservative check prevents incorrect reuse when placement order varies.\n if (existingEdge === undefined) {\n return { compatible: false }\n }\n\n // Dangling peer edge (edge exists but unresolved) - skip, nothing to conflict with\n if (!existingEdge.to) continue\n\n const peerSpec = Spec.parse(peerName, peerBareSpec, parseOpts)\n\n // CHECK 1: Does peer context have a different target for this peer?\n const contextEntry = peerContext.get(peerName)\n if (\n contextEntry?.target &&\n contextEntry.target.id !== existingEdge.to.id &&\n !shouldIgnoreContextMismatch(\n peerName,\n contextEntry.target,\n fromNode,\n graph,\n )\n ) {\n // If existing edge target still satisfies the peer spec, no real conflict.\n // The existing resolution is still valid even if context has a different target.\n // This ensures idempotency when loading from lockfile where peer contexts\n // are rebuilt fresh but existing nodes have valid peer resolutions.\n const existingTarget = existingEdge.to\n const existingTargetSatisfiesPeer = satisfiesNodeSpec(\n existingTarget,\n peerSpec,\n )\n if (\n existingTargetSatisfiesPeer &&\n nodeSatisfiesAll(existingTarget, contextEntry.specs)\n ) {\n continue // Truly no conflict\n }\n const result = buildIncompatibleResult(\n contextEntry.target,\n peerSpec,\n contextEntry.type,\n fromNode,\n graph,\n )\n if (result) return result\n }\n\n // CHECK 2: Does parent already have an edge to a different version?\n const siblingEdge = fromNode.edgesOut.get(peerName)\n if (siblingEdge?.to && siblingEdge.to.id !== existingEdge.to.id) {\n // If existing edge target still satisfies the peer spec, no real conflict.\n // Both sibling and existing targets may be valid - prefer keeping existing.\n const existingTarget = existingEdge.to\n const existingTargetSatisfiesPeer = satisfiesNodeSpec(\n existingTarget,\n peerSpec,\n )\n if (\n existingTargetSatisfiesPeer &&\n satisfiesNodeSpec(existingTarget, siblingEdge.spec)\n ) {\n continue // Truly no conflict\n }\n const result = buildIncompatibleResult(\n siblingEdge.to,\n peerSpec,\n siblingEdge.type,\n fromNode,\n graph,\n )\n if (result) return result\n }\n\n // CHECK 3: Does parent's manifest declare this peer, with a different\n // satisfying node already in the graph?\n const manifest = fromNode.manifest\n let declared: string | undefined\n let declaredType: DependencyTypeLong | undefined\n\n if (manifest) {\n for (const depType of longDependencyTypes) {\n const deps = manifest[depType]\n if (\n deps &&\n typeof deps === 'object' &&\n !Array.isArray(deps) &&\n peerName in deps\n ) {\n declared = deps[peerName]\n declaredType = depType\n break\n }\n }\n }\n\n if (declared && declaredType) {\n const parentSpec = Spec.parse(peerName, declared, parseOpts)\n // If existing edge target already satisfies parent's declared spec,\n // there's no conflict - the parent can use the same node as the existing\n // peer edge. Only search for alternatives if existing target is incompatible.\n if (satisfiesNodeSpec(existingEdge.to, parentSpec)) {\n continue // Existing target works for parent too, no conflict\n }\n // Use nodesByName (deterministic DepID order) instead of full graph scan\n const candidates = graph.nodesByName.get(peerName)\n if (candidates) {\n for (const candidateNode of candidates) {\n if (\n candidateNode.id !== existingEdge.to.id &&\n satisfiesNodeSpec(candidateNode, parentSpec) &&\n satisfiesNodeSpec(candidateNode, peerSpec)\n ) {\n return {\n compatible: false,\n forkEntry: {\n spec: peerSpec,\n target: candidateNode,\n type: shorten(declaredType),\n },\n }\n }\n }\n /* c8 ignore next */\n }\n }\n }\n\n return { compatible: true }\n}\n\n/**\n * Retrieve a unique hash value for a given peer context set.\n */\nexport const retrievePeerContextHash = (\n peerContext: PeerContext | undefined,\n): string | undefined => {\n // skips creating the initial peer context ref\n if (!peerContext?.index) return undefined\n\n return `peer.${peerContext.index}`\n}\n\n/**\n * Checks if a given spec is compatible with the specs already\n * assigned to a peer context entry.\n *\n * Returns true if INCOMPATIBLE, false if compatible.\n *\n * Compatibility rules:\n * - **Registry specs**: Uses semver range intersection. `^18.0.0` and `^18.2.0`\n * intersect (compatible), but `^18.0.0` and `^19.0.0` don't (incompatible).\n * - **Non-registry specs** (git, file, etc.): Requires exact bareSpec match.\n * `github:foo/bar#v1` only matches itself.\n *\n * This is used to determine when peer context forking is needed - if specs\n * are incompatible, a new peer context must be created.\n */\nexport const incompatibleSpecs = (\n spec: Spec,\n entry: PeerContextEntry,\n): boolean => {\n if (entry.specs.size > 0) {\n for (const s_ of entry.specs) {\n const s = s_.final\n if (\n // Registry types: check semver range intersection\n (spec.type === 'registry' &&\n (!spec.range ||\n !s.range ||\n !intersects(spec.range, s.range))) ||\n // Non-registry types: require exact bareSpec match\n (spec.type !== 'registry' && spec.bareSpec !== s.bareSpec)\n ) {\n return true\n }\n }\n }\n return false\n}\n\n/**\n * Sort peer context entry inputs for deterministic processing.\n * Orders: non-peer dependencies first, then peer dependencies, alphabetically by name.\n */\nexport const getOrderedPeerContextEntries = (\n entries: PeerContextEntryInput[],\n): PeerContextEntryInput[] => [...entries].sort(compareByType)\n\n/*\n * Checks if there are any conflicting versions for a given dependency\n * to be added to a peer context set which will require forking.\n *\n * Returns true if forking is needed, false otherwise.\n */\nexport const checkEntriesToPeerContext = (\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n): boolean => {\n // check on compatibility of new entries\n for (const { spec, target } of entries) {\n const name = target?.name ?? spec.final.name\n\n // skip any inactive entry\n const entry = peerContext.get(name)\n if (!entry?.active) continue\n\n // validate if the provided spec is compatible with existing specs\n if (incompatibleSpecs(spec.final, entry)) {\n return true\n }\n }\n\n return false\n}\n\n/**\n * Add or update dependencies in a given peer context making sure to check\n * for compatibility with existing dependencies already resolved by a given\n * peer context set. Extra info such as a target or dependent nodes is\n * optional.\n *\n * Returns true if forking is needed, false otherwise.\n */\nexport const addEntriesToPeerContext = (\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n fromNode: Node,\n monorepo?: Monorepo,\n): boolean => {\n // pre check for conflicts before processing\n if (checkEntriesToPeerContext(peerContext, entries)) return true\n\n for (const { dependent, spec, target, type } of entries) {\n const name = target?.name ?? spec.final.name\n let entry = peerContext.get(name)\n\n // create new entry if none exists\n if (!entry) {\n entry = {\n active: true,\n specs: new Set([spec]),\n target,\n type,\n contextDependents: new Set(),\n }\n peerContext.set(name, entry)\n if (dependent) entry.contextDependents.add(dependent)\n continue\n }\n\n // check for sibling dep conflicts\n if (incompatibleSpecs(spec.final, entry)) return true\n\n // update target if compatible with all specs\n if (\n target &&\n [...entry.specs].every(s =>\n satisfies(\n target.id,\n s,\n fromNode.location,\n fromNode.projectRoot,\n monorepo,\n ),\n )\n ) {\n if (\n target.id !== entry.target?.id &&\n target.version !== entry.target?.version\n ) {\n // update dependents to point to new target\n for (const dep of entry.contextDependents) {\n const edge = dep.edgesOut.get(name)\n if (edge?.to && edge.to !== target) {\n edge.to.edgesIn.delete(edge)\n edge.to = target\n target.edgesIn.add(edge)\n }\n }\n entry.target = target\n }\n entry.target ??= target\n }\n\n entry.specs.add(spec)\n if (dependent) entry.contextDependents.add(dependent)\n }\n\n return false\n}\n\n/**\n * Create and returns a forked copy of a given peer context set.\n */\nexport const forkPeerContext = (\n graph: Graph,\n peerContext: PeerContext,\n entries: PeerContextEntryInput[],\n): PeerContext => {\n const forkKey = getForkKey(peerContext, entries)\n const cached = graph.peerContextForkCache.get(forkKey)\n if (cached) {\n return cached\n }\n\n // create a new peer context set\n const nextPeerContext: PeerContext = new Map()\n nextPeerContext.index = graph.nextPeerContextIndex()\n // register it in the graph\n graph.peerContexts[nextPeerContext.index] = nextPeerContext\n graph.peerContextForkCache.set(forkKey, nextPeerContext)\n\n // copy existing entries marking them as inactive, it's also important\n // to note that specs and contextDependents are new objects so that changes\n // to those in the new context do not affect the previous one\n for (const [name, entry] of peerContext.entries()) {\n nextPeerContext.set(name, {\n active: false,\n specs: new Set(entry.specs),\n target: undefined,\n type: entry.type,\n contextDependents: new Set(entry.contextDependents),\n })\n }\n\n // add the new entries to this peer context set, marking them as active\n // these are the entries that were incompatible with the previous context set\n for (const entry of entries) {\n const { dependent, spec, target, type } = entry\n const name = target?.name /* c8 ignore next */ ?? spec.final.name\n const newEntry = {\n active: true,\n specs: new Set([spec]),\n target,\n type,\n contextDependents:\n dependent ? new Set([dependent]) : new Set<Node>(),\n }\n nextPeerContext.set(name, newEntry)\n }\n\n return nextPeerContext\n}\n\n/**\n * Find a peer from queued entries' peer edge closure using BFS.\n *\n * This handles peer dependency cycles like `@isaacs/peer-dep-cycle-a/b/c` where:\n * - A depends on B (peer)\n * - B depends on C (peer)\n * - C depends on A (peer)\n *\n * The BFS explores:\n * 1. Start nodes: All resolved targets from `queuedEntries` (sibling deps)\n * 2. For each node, check if it has an edge to `name` that satisfies `peerSpec`\n * 3. If not found, follow peer edges to explore their peer edges (up to depth 3)\n *\n * Prefers \"local\" providers (found via sibling's peer edges) over global context.\n */\nconst findFromPeerClosure = (\n name: string,\n peerSpec: Spec,\n queuedEntries: PeerContextEntryInput[],\n fromNode: Node,\n graph: Graph,\n): Node | undefined => {\n // Start BFS from all resolved sibling targets\n const start = queuedEntries\n .map(e => e.target)\n .filter((n): n is Node => !!n)\n const seen = new Set<string>()\n const q: { n: Node; depth: number }[] = start.map(n => ({\n n,\n depth: 0,\n }))\n\n while (q.length) {\n const cur = q.shift()\n if (!cur || seen.has(cur.n.id)) continue\n seen.add(cur.n.id)\n\n // Check if this node has an edge to the peer we're looking for\n const edge = cur.n.edgesOut.get(name)\n if (\n edge?.to &&\n nodeSatisfiesSpec(edge.to, peerSpec, fromNode, graph)\n ) {\n return edge.to\n }\n\n // Follow peer edges only (not regular deps) to stay in peer closure\n for (const e of cur.n.edgesOut.values()) {\n if ((e.type === 'peer' || e.type === 'peerOptional') && e.to) {\n q.push({ n: e.to, depth: cur.depth + 1 })\n }\n }\n }\n return undefined\n}\n\n/**\n * Starts the peer dependency placement process\n * for a given node being processed and placed.\n */\nexport const startPeerPlacement = (\n peerContext: PeerContext,\n manifest: Manifest,\n fromNode: Node,\n options: SpecOptions,\n) => {\n // queue entries so that they can be added at the end of the placement\n // process, use a map to ensure deduplication between read json dep\n // values and the resolved edges in the graph\n const queueMap = new Map<string, PeerContextEntryInput>()\n let peerSetHash: string | undefined\n\n if (\n manifest.peerDependencies &&\n Object.keys(manifest.peerDependencies).length > 0\n ) {\n // generates a peer context set hash for nodes that\n // have peer dependencies to be resolved\n peerSetHash = retrievePeerContextHash(peerContext)\n\n // get any potential sibling dependency from the\n // parent node that might have not been parsed yet\n const siblingDeps = getDependencies(fromNode, {\n ...options,\n registry: fromNode.registry,\n })\n for (const [depName, dep] of siblingDeps) {\n queueMap.set(depName, dep)\n }\n\n // collect the already parsed nodes and add those to the\n // list of entries to be added to the peer context set\n for (const edge of fromNode.edgesOut.values()) {\n queueMap.set(edge.name, {\n spec: edge.spec,\n target: edge.to,\n type: edge.type,\n })\n }\n }\n\n return {\n peerSetHash,\n // Sort queuedEntries for deterministic order\n queuedEntries: getOrderedPeerContextEntries([\n ...queueMap.values(),\n ]),\n }\n}\n\n/**\n * Ends the peer dependency placement process, returning the functions that\n * are going to be used to update the peer context set, forking when needed\n * and resolving peer dependencies if possible.\n *\n * Returns two deferred functions:\n * - `putEntries()`: Adds entries to peer context; returns fork entries if conflict\n * - `resolvePeerDeps()`: Resolves peer deps from context/siblings or adds to nextDeps\n *\n * These are deferred (not executed immediately) so that all siblings at a level\n * can be processed before peer context updates, enabling context reuse optimization.\n */\nexport const endPeerPlacement = (\n peerContext: PeerContext,\n nextDeps: Dependency[],\n nextPeerDeps: Map<string, Dependency> & { id?: number },\n graph: Graph,\n spec: Spec,\n fromNode: Node,\n node: Node,\n type: DependencySaveType,\n queuedEntries: PeerContextEntryInput[],\n) => ({\n /**\n * Add the new entries to the current peer context set.\n *\n * Two sets of entries are checked:\n * - `prevEntries`: Parent's queued entries + self-reference\n * - `nextEntries`: This node's deps + peer deps (with node as dependent)\n *\n * If either conflicts with the current context, returns ALL entries to be\n * added to a forked context (prevEntries last for priority).\n *\n * Returns `undefined` if no fork needed (entries added directly to context).\n */\n putEntries: () => {\n // add queued entries from this node parents along\n // with a self-ref to the current peer context set\n const prevEntries = [\n ...queuedEntries,\n /* ref itself */ {\n spec,\n target: node,\n type,\n },\n ]\n\n const nextEntries = [\n ...nextDeps.map(dep => ({ ...dep, dependent: node })),\n ...[...nextPeerDeps.values()].map(dep => ({\n ...dep,\n dependent: node,\n })),\n ]\n\n const conflictPrev = checkEntriesToPeerContext(\n peerContext,\n prevEntries,\n )\n const conflictNext =\n nextEntries.length > 0 &&\n checkEntriesToPeerContext(peerContext, nextEntries)\n\n if (conflictPrev || conflictNext) {\n // returns all entries that need to be added to a forked context\n // giving priority to parent entries (prevEntries) by placing them last\n return [...nextEntries, ...prevEntries]\n }\n\n addEntriesToPeerContext(\n peerContext,\n prevEntries,\n fromNode,\n graph.monorepo,\n )\n\n if (nextEntries.length > 0) {\n addEntriesToPeerContext(\n peerContext,\n nextEntries,\n node,\n graph.monorepo,\n )\n }\n\n return undefined\n },\n\n /**\n * Try to resolve peer dependencies using already seen target\n * values from the current peer context set.\n *\n * Resolution priority (highest to lowest):\n * 1. Sibling deps from parent (workspace direct deps take priority)\n * 2. Peer-edge closure of sibling targets (handles peer cycles)\n * 3. Global peer context set entries\n * 4. Add to nextDeps for normal resolution (or create dangling edge for optional)\n */\n resolvePeerDeps: () => {\n for (const nextDep of nextPeerDeps.values()) {\n const { spec, type } = nextDep\n /* c8 ignore next - only peer types reach here by design */\n if (type !== 'peer' && type !== 'peerOptional') continue\n\n const name = spec.final.name\n\n // PRIORITY 1: Sibling deps from parent\n // These take priority because workspace's direct deps should win over\n // versions from other workspaces that may be in the peer context\n const siblingEntry = queuedEntries.find(\n e => (e.target?.name ?? e.spec.final.name) === name,\n )\n const siblingTarget =\n siblingEntry?.target ?? fromNode.edgesOut.get(name)?.to\n\n if (\n siblingTarget &&\n nodeSatisfiesSpec(siblingTarget, spec, fromNode, graph)\n ) {\n // Override existing edge if pointing elsewhere (sibling must win)\n const existingEdge = node.edgesOut.get(name)\n if (existingEdge?.to && existingEdge.to !== siblingTarget) {\n existingEdge.to.edgesIn.delete(existingEdge)\n existingEdge.to = siblingTarget\n siblingTarget.edgesIn.add(existingEdge)\n } else if (!existingEdge) {\n graph.addEdge(type, spec, node, siblingTarget)\n }\n continue\n }\n\n // PRIORITY 2: Peer-edge closure of sibling targets\n // Handles cycles like A->B(peer)->C(peer)->A(peer)\n const localPeer = findFromPeerClosure(\n name,\n spec,\n queuedEntries,\n fromNode,\n graph,\n )\n if (localPeer && !node.edgesOut.has(name)) {\n graph.addEdge(type, spec, node, localPeer)\n continue\n }\n\n // PRIORITY 3: Global peer context set\n const entry = peerContext.get(name)\n if (\n !node.edgesOut.has(name) &&\n entry?.target &&\n nodeSatisfiesSpec(entry.target, spec, fromNode, graph)\n ) {\n graph.addEdge(type, spec, node, entry.target)\n entry.specs.add(spec.final)\n continue\n }\n\n // PRIORITY 4: Fallback - add to nextDeps or create dangling edge\n if (type === 'peerOptional') {\n // Optional peers that can't be resolved get a dangling edge\n graph.addEdge(type, spec, node)\n } else if (\n siblingEntry &&\n siblingEntry.spec.bareSpec !== spec.bareSpec\n ) {\n // Sibling has a more specific spec - use it for resolution\n nextDeps.push({ ...nextDep, spec: siblingEntry.spec })\n } else {\n // Add to next deps for normal resolution in upcoming levels\n nextDeps.push(nextDep)\n }\n }\n },\n})\n\n/**\n * Given an array of processed results for the current level dependencies\n * being placed in the currently building ideal graph, traverse its direct\n * dependencies and track peer dependencies in their appropriate peer context\n * sets, forking as needed and resolving peer dependencies using suitable\n * nodes already present in the graph if possible.\n *\n * This is the core peer context management algorithm, executed after each\n * BFS level. It runs in three phases:\n *\n * **Phase 1: Collect fork requirements**\n * Call `putEntries()` on each child dep to add entries to peer context.\n * Collect which children need forked contexts (due to conflicts).\n *\n * **Phase 2: Fork or reuse contexts**\n * For children needing forks, try to reuse a sibling's forked context if\n * compatible. This optimization reduces the number of peer contexts created.\n *\n * **Phase 3: Resolve peer deps**\n * With contexts finalized, call `resolvePeerDeps()` to create edges for\n * peers that can be satisfied from context/siblings, or add them to nextDeps.\n *\n * All operations are sorted by `node.id` for deterministic, reproducible builds.\n */\nexport const postPlacementPeerCheck = (\n graph: Graph,\n sortedLevelResults: ProcessPlacementResult[],\n) => {\n for (const childDepsToProcess of sortedLevelResults) {\n // Sort by node.id for deterministic processing order\n const sortedChildDeps = [...childDepsToProcess].sort((a, b) =>\n a.node.id.localeCompare(b.node.id, 'en'),\n )\n\n // PHASE 1: Collect which children need forked contexts\n const needsForking = new Map<\n ProcessPlacementResultEntry,\n PeerContextEntryInput[]\n >()\n for (const childDep of sortedChildDeps) {\n const needsFork = childDep.updateContext.putEntries()\n if (needsFork) {\n needsForking.set(childDep, needsFork)\n }\n }\n\n // Sort forking entries for deterministic fork order\n const sortedNeedsForkingEntries = [\n ...needsForking.entries(),\n ].sort(([a], [b]) => a.node.id.localeCompare(b.node.id, 'en'))\n\n // PHASE 2: Fork or reuse sibling contexts\n // Track previous context for potential reuse by next sibling\n let prevContext\n for (const [childDep, nextEntries] of sortedNeedsForkingEntries) {\n // Optimization: try to reuse previous sibling's forked context\n // if its entries are compatible with this child's entries\n if (\n prevContext &&\n !checkEntriesToPeerContext(prevContext, nextEntries)\n ) {\n addEntriesToPeerContext(\n prevContext,\n nextEntries,\n childDep.node,\n graph.monorepo,\n )\n childDep.peerContext = prevContext\n continue\n }\n\n // Can't reuse - create a new forked context\n childDep.peerContext = forkPeerContext(\n graph,\n childDep.peerContext,\n nextEntries,\n )\n prevContext = childDep.peerContext\n }\n\n // PHASE 3: Resolve peer deps with finalized contexts\n for (const childDep of sortedChildDeps) {\n childDep.updateContext.resolvePeerDeps()\n // Re-order deps for deterministic next-level processing\n childDep.deps = getOrderedDependencies(childDep.deps)\n }\n }\n}\n"]} |
+22
-22
| { | ||
| "name": "@vltpkg/graph", | ||
| "description": "A library that helps understanding & expressing what happens on an install", | ||
| "version": "1.0.0-rc.16", | ||
| "version": "1.0.0-rc.17", | ||
| "repository": { | ||
@@ -14,22 +14,22 @@ "type": "git", | ||
| "promise-call-limit": "^3.0.2", | ||
| "@vltpkg/cmd-shim": "1.0.0-rc.16", | ||
| "@vltpkg/dep-id": "1.0.0-rc.16", | ||
| "@vltpkg/dss-breadcrumb": "1.0.0-rc.16", | ||
| "@vltpkg/error-cause": "1.0.0-rc.16", | ||
| "@vltpkg/fast-split": "1.0.0-rc.16", | ||
| "@vltpkg/graph-run": "1.0.0-rc.16", | ||
| "@vltpkg/init": "1.0.0-rc.16", | ||
| "@vltpkg/output": "1.0.0-rc.16", | ||
| "@vltpkg/package-info": "1.0.0-rc.16", | ||
| "@vltpkg/package-json": "1.0.0-rc.16", | ||
| "@vltpkg/pick-manifest": "1.0.0-rc.16", | ||
| "@vltpkg/query": "1.0.0-rc.16", | ||
| "@vltpkg/run": "1.0.0-rc.16", | ||
| "@vltpkg/rollback-remove": "1.0.0-rc.16", | ||
| "@vltpkg/satisfies": "1.0.0-rc.16", | ||
| "@vltpkg/security-archive": "1.0.0-rc.16", | ||
| "@vltpkg/spec": "1.0.0-rc.16", | ||
| "@vltpkg/types": "1.0.0-rc.16", | ||
| "@vltpkg/vlt-json": "1.0.0-rc.16", | ||
| "@vltpkg/workspaces": "1.0.0-rc.16" | ||
| "@vltpkg/cmd-shim": "1.0.0-rc.17", | ||
| "@vltpkg/dss-breadcrumb": "1.0.0-rc.17", | ||
| "@vltpkg/dep-id": "1.0.0-rc.17", | ||
| "@vltpkg/error-cause": "1.0.0-rc.17", | ||
| "@vltpkg/fast-split": "1.0.0-rc.17", | ||
| "@vltpkg/graph-run": "1.0.0-rc.17", | ||
| "@vltpkg/init": "1.0.0-rc.17", | ||
| "@vltpkg/output": "1.0.0-rc.17", | ||
| "@vltpkg/package-info": "1.0.0-rc.17", | ||
| "@vltpkg/package-json": "1.0.0-rc.17", | ||
| "@vltpkg/pick-manifest": "1.0.0-rc.17", | ||
| "@vltpkg/query": "1.0.0-rc.17", | ||
| "@vltpkg/rollback-remove": "1.0.0-rc.17", | ||
| "@vltpkg/run": "1.0.0-rc.17", | ||
| "@vltpkg/satisfies": "1.0.0-rc.17", | ||
| "@vltpkg/security-archive": "1.0.0-rc.17", | ||
| "@vltpkg/spec": "1.0.0-rc.17", | ||
| "@vltpkg/types": "1.0.0-rc.17", | ||
| "@vltpkg/vlt-json": "1.0.0-rc.17", | ||
| "@vltpkg/workspaces": "1.0.0-rc.17" | ||
| }, | ||
@@ -46,3 +46,3 @@ "devDependencies": { | ||
| "typescript-eslint": "^8.49.0", | ||
| "@vltpkg/vlt-json": "1.0.0-rc.16" | ||
| "@vltpkg/vlt-json": "1.0.0-rc.17" | ||
| }, | ||
@@ -49,0 +49,0 @@ "license": "BSD-2-Clause-Patent", |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
895000
1.16%8419
1.03%24
4.35%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated
Updated
Updated
Updated
Updated
Updated
Updated
Updated