@vltpkg/graph 1.0.0-rc.16 → 1.0.0-rc.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ ---
2
+ title: '@vltpkg/graph'
3
+ ---
4
+
1
5
  ![graph](https://github.com/user-attachments/assets/dfbed9e0-8ef0-4a43-993d-d3e5d1e5ae1d)
2
6
 
3
7
  # @vltpkg/graph
@@ -1 +1 @@
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"}
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;AAqnBnB;;;;;;;;;;;;;;;;;;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"}
@@ -47,29 +47,58 @@ const isStringArray = (a) => Array.isArray(a) && !a.some(b => typeof b !== 'stri
47
47
  * try other candidates.
48
48
  */
49
49
  const findCompatibleResolution = (spec, fromNode, graph, peerContext, queryModifier, _peer) => {
50
- const candidates = graph.nodesByName.get(spec.final.name);
51
- let existingNode = graph.findResolution(spec, fromNode, queryModifier);
50
+ // Hoist invariants once
51
+ const fromLoc = fromNode.location;
52
+ const projectRoot = graph.projectRoot;
53
+ const monorepo = graph.monorepo;
54
+ const final = spec.final;
55
+ // Memoize satisfies() results per-node within this resolution attempt
56
+ const satisfiesCache = new Map();
57
+ const satisfiesFinal = (n) => {
58
+ const key = n.id;
59
+ const cached = satisfiesCache.get(key);
60
+ /* c8 ignore next 3 - optimization: cache hit when same node checked multiple times */
61
+ if (cached !== undefined) {
62
+ return cached;
63
+ }
64
+ const result = satisfies(key, final, fromLoc, projectRoot, monorepo);
65
+ satisfiesCache.set(key, result);
66
+ return result;
67
+ };
68
+ // Prefer existing edge target if it satisfies the spec.
69
+ // This ensures lockfile resolutions are preserved when still valid,
70
+ // rather than potentially picking a different satisfying version.
71
+ const existingEdge = fromNode.edgesOut.get(spec.name);
72
+ let existingNode;
73
+ if (existingEdge?.to &&
74
+ !existingEdge.to.detached &&
75
+ satisfiesFinal(existingEdge.to)) {
76
+ existingNode = existingEdge.to;
77
+ }
78
+ else {
79
+ existingNode = graph.findResolution(spec, fromNode, queryModifier);
80
+ }
52
81
  let peerCompatResult = existingNode ?
53
82
  checkPeerEdgesCompatible(existingNode, fromNode, peerContext, graph)
54
83
  : { compatible: true };
55
84
  // CANDIDATE FALLBACK: If first candidate is peer-incompatible, try others
56
- if (existingNode &&
57
- !peerCompatResult.compatible &&
58
- candidates &&
59
- candidates.size > 1) {
60
- for (const candidate of candidates) {
61
- if (candidate === existingNode)
62
- continue;
63
- if (candidate.detached)
64
- continue;
65
- if (!satisfies(candidate.id, spec.final, fromNode.location, graph.projectRoot, graph.monorepo)) {
66
- continue;
67
- }
68
- const compat = checkPeerEdgesCompatible(candidate, fromNode, peerContext, graph);
69
- if (compat.compatible) {
70
- existingNode = candidate;
71
- peerCompatResult = compat;
72
- break;
85
+ // Lazy-load candidates only when fallback needed
86
+ if (existingNode && !peerCompatResult.compatible) {
87
+ const candidates = graph.nodesByName.get(final.name);
88
+ if (candidates && candidates.size > 1) {
89
+ for (const candidate of candidates) {
90
+ if (candidate === existingNode)
91
+ continue;
92
+ if (candidate.detached)
93
+ continue;
94
+ if (!satisfiesFinal(candidate))
95
+ continue;
96
+ const compat = checkPeerEdgesCompatible(candidate, fromNode, peerContext, graph);
97
+ if (compat.compatible) {
98
+ existingNode = candidate;
99
+ peerCompatResult = compat;
100
+ break;
101
+ }
73
102
  }
74
103
  }
75
104
  }
@@ -296,7 +325,13 @@ const processPlacementTasks = async (graph, options, placementTasks, add, modifi
296
325
  if (fileTypeInfo?.path && fileTypeInfo.isDirectory) {
297
326
  node.location = fileTypeInfo.path;
298
327
  }
299
- node.setResolved();
328
+ // Do not clobber lockfile-provided resolved values.
329
+ // `setResolved()` cannot infer a tarball without a manifest,
330
+ // which can cause `resolved` to become undefined and the
331
+ // main lockfile to mutate across installs.
332
+ if (!node.resolved) {
333
+ node.setResolved();
334
+ }
300
335
  // collect child dependencies for processing in the next level
301
336
  const nextPeerDeps = new Map();
302
337
  // compute deps normally
@@ -1 +1 @@
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"]}
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 // 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 // Do not clobber lockfile-provided resolved values.\n // `setResolved()` cannot infer a tarball without a manifest,\n // which can cause `resolved` to become undefined and the\n // main lockfile to mutate across installs.\n if (!node.resolved) {\n node.setResolved()\n }\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 @@
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"}
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,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"}
@@ -124,7 +124,36 @@ export const checkPeerEdgesCompatible = (existingNode, fromNode, peerContext, gr
124
124
  if (!peerDeps || Object.keys(peerDeps).length === 0) {
125
125
  return { compatible: true };
126
126
  }
127
- for (const [peerName, peerBareSpec] of Object.entries(peerDeps)) {
127
+ // Per-call memoization: avoid repeated satisfies() calls with identical args
128
+ const parseOpts = {
129
+ ...graph.mainImporter.options,
130
+ registry: fromNode.registry,
131
+ };
132
+ const fromLocation = fromNode.location;
133
+ const projectRoot = fromNode.projectRoot;
134
+ const monorepo = graph.monorepo;
135
+ const satisfiesMemo = new Map();
136
+ const satisfiesNodeSpec = (node, spec) => {
137
+ const key = `${node.id}\0${spec.type}\0${spec.bareSpec}\0${String(spec.final)}`;
138
+ let result = satisfiesMemo.get(key);
139
+ if (result === undefined) {
140
+ result = satisfies(node.id, spec, fromLocation, projectRoot, monorepo);
141
+ satisfiesMemo.set(key, result);
142
+ }
143
+ return result;
144
+ };
145
+ const nodeSatisfiesAll = (node, specs) => {
146
+ for (const s of specs) {
147
+ if (!satisfiesNodeSpec(node, s))
148
+ return false;
149
+ }
150
+ return true;
151
+ };
152
+ for (const peerName in peerDeps) {
153
+ const peerBareSpec = peerDeps[peerName];
154
+ /* c8 ignore next - peerDeps[peerName] is always defined when iterating */
155
+ if (!peerBareSpec)
156
+ continue;
128
157
  const existingEdge = existingNode.edgesOut.get(peerName);
129
158
  // CHECK 0: Reject reuse if peer edge doesn't exist yet (node unprocessed).
130
159
  // Cannot verify compatibility since peer resolution depends on original
@@ -137,12 +166,22 @@ export const checkPeerEdgesCompatible = (existingNode, fromNode, peerContext, gr
137
166
  // Dangling peer edge (edge exists but unresolved) - skip, nothing to conflict with
138
167
  if (!existingEdge.to)
139
168
  continue;
140
- const peerSpec = parseSpec(peerName, peerBareSpec, fromNode, graph);
169
+ const peerSpec = Spec.parse(peerName, peerBareSpec, parseOpts);
141
170
  // CHECK 1: Does peer context have a different target for this peer?
142
171
  const contextEntry = peerContext.get(peerName);
143
172
  if (contextEntry?.target &&
144
173
  contextEntry.target.id !== existingEdge.to.id &&
145
174
  !shouldIgnoreContextMismatch(peerName, contextEntry.target, fromNode, graph)) {
175
+ // If existing edge target still satisfies the peer spec, no real conflict.
176
+ // The existing resolution is still valid even if context has a different target.
177
+ // This ensures idempotency when loading from lockfile where peer contexts
178
+ // are rebuilt fresh but existing nodes have valid peer resolutions.
179
+ const existingTarget = existingEdge.to;
180
+ const existingTargetSatisfiesPeer = satisfiesNodeSpec(existingTarget, peerSpec);
181
+ if (existingTargetSatisfiesPeer &&
182
+ nodeSatisfiesAll(existingTarget, contextEntry.specs)) {
183
+ continue; // Truly no conflict
184
+ }
146
185
  const result = buildIncompatibleResult(contextEntry.target, peerSpec, contextEntry.type, fromNode, graph);
147
186
  if (result)
148
187
  return result;
@@ -150,6 +189,14 @@ export const checkPeerEdgesCompatible = (existingNode, fromNode, peerContext, gr
150
189
  // CHECK 2: Does parent already have an edge to a different version?
151
190
  const siblingEdge = fromNode.edgesOut.get(peerName);
152
191
  if (siblingEdge?.to && siblingEdge.to.id !== existingEdge.to.id) {
192
+ // If existing edge target still satisfies the peer spec, no real conflict.
193
+ // Both sibling and existing targets may be valid - prefer keeping existing.
194
+ const existingTarget = existingEdge.to;
195
+ const existingTargetSatisfiesPeer = satisfiesNodeSpec(existingTarget, peerSpec);
196
+ if (existingTargetSatisfiesPeer &&
197
+ satisfiesNodeSpec(existingTarget, siblingEdge.spec)) {
198
+ continue; // Truly no conflict
199
+ }
153
200
  const result = buildIncompatibleResult(siblingEdge.to, peerSpec, siblingEdge.type, fromNode, graph);
154
201
  if (result)
155
202
  return result;
@@ -173,21 +220,31 @@ export const checkPeerEdgesCompatible = (existingNode, fromNode, peerContext, gr
173
220
  }
174
221
  }
175
222
  if (declared && declaredType) {
176
- const parentSpec = parseSpec(peerName, declared, fromNode, graph);
177
- for (const candidateNode of graph.nodes.values()) {
178
- if (candidateNode.name === peerName &&
179
- candidateNode.id !== existingEdge.to.id &&
180
- nodeSatisfiesSpec(candidateNode, parentSpec, fromNode, graph) &&
181
- nodeSatisfiesSpec(candidateNode, peerSpec, fromNode, graph)) {
182
- return {
183
- compatible: false,
184
- forkEntry: {
185
- spec: peerSpec,
186
- target: candidateNode,
187
- type: shorten(declaredType),
188
- },
189
- };
223
+ const parentSpec = Spec.parse(peerName, declared, parseOpts);
224
+ // If existing edge target already satisfies parent's declared spec,
225
+ // there's no conflict - the parent can use the same node as the existing
226
+ // peer edge. Only search for alternatives if existing target is incompatible.
227
+ if (satisfiesNodeSpec(existingEdge.to, parentSpec)) {
228
+ continue; // Existing target works for parent too, no conflict
229
+ }
230
+ // Use nodesByName (deterministic DepID order) instead of full graph scan
231
+ const candidates = graph.nodesByName.get(peerName);
232
+ if (candidates) {
233
+ for (const candidateNode of candidates) {
234
+ if (candidateNode.id !== existingEdge.to.id &&
235
+ satisfiesNodeSpec(candidateNode, parentSpec) &&
236
+ satisfiesNodeSpec(candidateNode, peerSpec)) {
237
+ return {
238
+ compatible: false,
239
+ forkEntry: {
240
+ spec: peerSpec,
241
+ target: candidateNode,
242
+ type: shorten(declaredType),
243
+ },
244
+ };
245
+ }
190
246
  }
247
+ /* c8 ignore next */
191
248
  }
192
249
  }
193
250
  }
@@ -1 +1 @@
1
- {"version":3,"file":"peers.js","sourceRoot":"","sources":["../../src/ideal/peers.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,2CAA2C;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AASpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAsBnD;;;;;;;;;;GAUG;AACH,MAAM,iBAAiB,GAAG,CACxB,IAAU,EACV,IAAU,EACV,QAAc,EACd,KAAY,EACH,EAAE,CACX,SAAS,CACP,IAAI,CAAC,EAAE,EACP,IAAI,EACJ,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,WAAW,EACpB,KAAK,CAAC,QAAQ,CACf,CAAA;AAEH;;;;;;GAMG;AACH,MAAM,SAAS,GAAG,CAChB,IAAY,EACZ,QAAgB,EAChB,QAAc,EACd,KAAY,EACN,EAAE,CACR,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE;IACzB,GAAG,KAAK,CAAC,YAAY,CAAC,OAAO;IAC7B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;CAC5B,CAAC,CAAA;AAEJ;;;;;;;;;GASG;AACH,MAAM,UAAU,GAAG,CACjB,WAAwB,EACxB,OAAgC,EAChC,EAAE;IACF,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,IAAI,CAAC,CAAA;IACnC,MAAM,GAAG,GAAG,OAAO;SAChB,GAAG,CACF,CAAC,CAAC,EAAE,CACF,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CACpE;SACA,IAAI,EAAE;SACN,IAAI,CAAC,GAAG,CAAC,CAAA;IACZ,OAAO,GAAG,IAAI,KAAK,GAAG,EAAE,CAAA;AAC1B,CAAC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,2BAA2B,GAAG,CAClC,QAAgB,EAChB,aAAmB,EACnB,QAAc,EACd,KAAY,EACH,EAAE;IACX,MAAM,cAAc,GAAG,QAAQ,CAAC,QAAQ,CAAA;IACxC,0EAA0E;IAC1E,IAAI,CAAC,cAAc;QAAE,OAAO,KAAK,CAAA;IAEjC,4DAA4D;IAC5D,KAAK,MAAM,OAAO,IAAI,mBAAmB,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAA;QACpD,IAAI,CAAC,QAAQ;YAAE,SAAQ;QAEvB,sEAAsE;QACtE,MAAM,UAAU,GAAG,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;QACjE,uEAAuE;QACvE,qDAAqD;QACrD,OAAO,CAAC,iBAAiB,CACvB,aAAa,EACb,UAAU,EACV,QAAQ,EACR,KAAK,CACN,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,uBAAuB,GAAG,CAC9B,MAAY,EACZ,QAAc,EACd,IAAwB,EACxB,QAAc,EACd,KAAY,EACsB,EAAE;IACpC,IAAI,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;QACzD,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;SAC5C,CAAA;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,YAAkB,EAClB,QAAc,EACd,WAAwB,EACxB,KAAY,EACU,EAAE;IACxB,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,gBAAgB,CAAA;IACxD,mCAAmC;IACnC,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;IAC7B,CAAC;IAED,KAAK,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChE,MAAM,YAAY,GAAG,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAExD,2EAA2E;QAC3E,wEAAwE;QACxE,qEAAqE;QACrE,8EAA8E;QAC9E,gFAAgF;QAChF,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;QAC9B,CAAC;QAED,mFAAmF;QACnF,IAAI,CAAC,YAAY,CAAC,EAAE;YAAE,SAAQ;QAE9B,MAAM,QAAQ,GAAG,SAAS,CACxB,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,KAAK,CACN,CAAA;QAED,oEAAoE;QACpE,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC9C,IACE,YAAY,EAAE,MAAM;YACpB,YAAY,CAAC,MAAM,CAAC,EAAE,KAAK,YAAY,CAAC,EAAE,CAAC,EAAE;YAC7C,CAAC,2BAA2B,CAC1B,QAAQ,EACR,YAAY,CAAC,MAAM,EACnB,QAAQ,EACR,KAAK,CACN,EACD,CAAC;YACD,MAAM,MAAM,GAAG,uBAAuB,CACpC,YAAY,CAAC,MAAM,EACnB,QAAQ,EACR,YAAY,CAAC,IAAI,EACjB,QAAQ,EACR,KAAK,CACN,CAAA;YACD,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAA;QAC3B,CAAC;QAED,oEAAoE;QACpE,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACnD,IAAI,WAAW,EAAE,EAAE,IAAI,WAAW,CAAC,EAAE,CAAC,EAAE,KAAK,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAChE,MAAM,MAAM,GAAG,uBAAuB,CACpC,WAAW,CAAC,EAAE,EACd,QAAQ,EACR,WAAW,CAAC,IAAI,EAChB,QAAQ,EACR,KAAK,CACN,CAAA;YACD,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAA;QAC3B,CAAC;QAED,sEAAsE;QACtE,wCAAwC;QACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAA;QAClC,IAAI,QAA4B,CAAA;QAChC,IAAI,YAA4C,CAAA;QAEhD,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,MAAM,OAAO,IAAI,mBAAmB,EAAE,CAAC;gBAC1C,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;gBAC9B,IACE,IAAI;oBACJ,OAAO,IAAI,KAAK,QAAQ;oBACxB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;oBACpB,QAAQ,IAAI,IAAI,EAChB,CAAC;oBACD,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAA;oBACzB,YAAY,GAAG,OAAO,CAAA;oBACtB,MAAK;gBACP,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,IAAI,YAAY,EAAE,CAAC;YAC7B,MAAM,UAAU,GAAG,SAAS,CAC1B,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,KAAK,CACN,CAAA;YACD,KAAK,MAAM,aAAa,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBACjD,IACE,aAAa,CAAC,IAAI,KAAK,QAAQ;oBAC/B,aAAa,CAAC,EAAE,KAAK,YAAY,CAAC,EAAE,CAAC,EAAE;oBACvC,iBAAiB,CACf,aAAa,EACb,UAAU,EACV,QAAQ,EACR,KAAK,CACN;oBACD,iBAAiB,CAAC,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EAC3D,CAAC;oBACD,OAAO;wBACL,UAAU,EAAE,KAAK;wBACjB,SAAS,EAAE;4BACT,IAAI,EAAE,QAAQ;4BACd,MAAM,EAAE,aAAa;4BACrB,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC;yBAC5B;qBACF,CAAA;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;AAC7B,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,WAAoC,EAChB,EAAE;IACtB,8CAA8C;IAC9C,IAAI,CAAC,WAAW,EAAE,KAAK;QAAE,OAAO,SAAS,CAAA;IAEzC,OAAO,QAAQ,WAAW,CAAC,KAAK,EAAE,CAAA;AACpC,CAAC,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,IAAU,EACV,KAAuB,EACd,EAAE;IACX,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAA;YAClB;YACE,kDAAkD;YAClD,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU;gBACvB,CAAC,CAAC,IAAI,CAAC,KAAK;oBACV,CAAC,CAAC,CAAC,KAAK;oBACR,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtC,mDAAmD;gBACnD,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,CAAC,EAC1D,CAAC;gBACD,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAC1C,OAAgC,EACP,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;AAE9D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,WAAwB,EACxB,OAAgC,EACvB,EAAE;IACX,wCAAwC;IACxC,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA;QAE5C,0BAA0B;QAC1B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACnC,IAAI,CAAC,KAAK,EAAE,MAAM;YAAE,SAAQ;QAE5B,kEAAkE;QAClE,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,WAAwB,EACxB,OAAgC,EAChC,QAAc,EACd,QAAmB,EACV,EAAE;IACX,4CAA4C;IAC5C,IAAI,yBAAyB,CAAC,WAAW,EAAE,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IAEhE,KAAK,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;QACxD,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA;QAC5C,IAAI,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAEjC,kCAAkC;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG;gBACN,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;gBACtB,MAAM;gBACN,IAAI;gBACJ,iBAAiB,EAAE,IAAI,GAAG,EAAE;aAC7B,CAAA;YACD,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;YAC5B,IAAI,SAAS;gBAAE,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;YACrD,SAAQ;QACV,CAAC;QAED,kCAAkC;QAClC,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;QAErD,6CAA6C;QAC7C,IACE,MAAM;YACN,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CACzB,SAAS,CACP,MAAM,CAAC,EAAE,EACT,CAAC,EACD,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,WAAW,EACpB,QAAQ,CACT,CACF,EACD,CAAC;YACD,IACE,MAAM,CAAC,EAAE,KAAK,KAAK,CAAC,MAAM,EAAE,EAAE;gBAC9B,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,EACxC,CAAC;gBACD,2CAA2C;gBAC3C,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;oBAC1C,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;oBACnC,IAAI,IAAI,EAAE,EAAE,IAAI,IAAI,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;wBACnC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;wBAC5B,IAAI,CAAC,EAAE,GAAG,MAAM,CAAA;wBAChB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;oBAC1B,CAAC;gBACH,CAAC;gBACD,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;YACvB,CAAC;YACD,KAAK,CAAC,MAAM,KAAK,MAAM,CAAA;QACzB,CAAC;QAED,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACrB,IAAI,SAAS;YAAE,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACvD,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,KAAY,EACZ,WAAwB,EACxB,OAAgC,EACnB,EAAE;IACf,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IAChD,MAAM,MAAM,GAAG,KAAK,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACtD,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAA;IACf,CAAC;IAED,gCAAgC;IAChC,MAAM,eAAe,GAAgB,IAAI,GAAG,EAAE,CAAA;IAC9C,eAAe,CAAC,KAAK,GAAG,KAAK,CAAC,oBAAoB,EAAE,CAAA;IACpD,2BAA2B;IAC3B,KAAK,CAAC,YAAY,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,eAAe,CAAA;IAC3D,KAAK,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;IAExD,sEAAsE;IACtE,2EAA2E;IAC3E,6DAA6D;IAC7D,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;QAClD,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE;YACxB,MAAM,EAAE,KAAK;YACb,KAAK,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;YAC3B,MAAM,EAAE,SAAS;YACjB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,iBAAiB,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC;SACpD,CAAC,CAAA;IACJ,CAAC;IAED,uEAAuE;IACvE,6EAA6E;IAC7E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAA;QAC/C,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA;QACjE,MAAM,QAAQ,GAAG;YACf,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;YACtB,MAAM;YACN,IAAI;YACJ,iBAAiB,EACf,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAQ;SACrD,CAAA;QACD,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACrC,CAAC;IAED,OAAO,eAAe,CAAA;AACxB,CAAC,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,mBAAmB,GAAG,CAC1B,IAAY,EACZ,QAAc,EACd,aAAsC,EACtC,QAAc,EACd,KAAY,EACM,EAAE;IACpB,8CAA8C;IAC9C,MAAM,KAAK,GAAG,aAAa;SACxB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;SAClB,MAAM,CAAC,CAAC,CAAC,EAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,MAAM,CAAC,GAAiC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,KAAK,EAAE,CAAC;KACT,CAAC,CAAC,CAAA;IAEH,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAA;QACrB,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,SAAQ;QACxC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAElB,+DAA+D;QAC/D,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACrC,IACE,IAAI,EAAE,EAAE;YACR,iBAAiB,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EACrD,CAAC;YACD,OAAO,IAAI,CAAC,EAAE,CAAA;QAChB,CAAC;QAED,oEAAoE;QACpE,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACxC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC7D,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAA;YAC3C,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,WAAwB,EACxB,QAAkB,EAClB,QAAc,EACd,OAAoB,EACpB,EAAE;IACF,sEAAsE;IACtE,mEAAmE;IACnE,6CAA6C;IAC7C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAiC,CAAA;IACzD,IAAI,WAA+B,CAAA;IAEnC,IACE,QAAQ,CAAC,gBAAgB;QACzB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,MAAM,GAAG,CAAC,EACjD,CAAC;QACD,mDAAmD;QACnD,wCAAwC;QACxC,WAAW,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAA;QAElD,gDAAgD;QAChD,kDAAkD;QAClD,MAAM,WAAW,GAAG,eAAe,CAAC,QAAQ,EAAE;YAC5C,GAAG,OAAO;YACV,QAAQ,EAAE,QAAQ,CAAC,QAAQ;SAC5B,CAAC,CAAA;QACF,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;YACzC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;QAC5B,CAAC;QAED,wDAAwD;QACxD,sDAAsD;QACtD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9C,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;gBACtB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,WAAW;QACX,6CAA6C;QAC7C,aAAa,EAAE,4BAA4B,CAAC;YAC1C,GAAG,QAAQ,CAAC,MAAM,EAAE;SACrB,CAAC;KACH,CAAA;AACH,CAAC,CAAA;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,WAAwB,EACxB,QAAsB,EACtB,YAAuD,EACvD,KAAY,EACZ,IAAU,EACV,QAAc,EACd,IAAU,EACV,IAAwB,EACxB,aAAsC,EACtC,EAAE,CAAC,CAAC;IACJ;;;;;;;;;;;OAWG;IACH,UAAU,EAAE,GAAG,EAAE;QACf,kDAAkD;QAClD,kDAAkD;QAClD,MAAM,WAAW,GAAG;YAClB,GAAG,aAAa;YAChB,gBAAgB,CAAC;gBACf,IAAI;gBACJ,MAAM,EAAE,IAAI;gBACZ,IAAI;aACL;SACF,CAAA;QAED,MAAM,WAAW,GAAG;YAClB,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,GAAG,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACxC,GAAG,GAAG;gBACN,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC;SACJ,CAAA;QAED,MAAM,YAAY,GAAG,yBAAyB,CAC5C,WAAW,EACX,WAAW,CACZ,CAAA;QACD,MAAM,YAAY,GAChB,WAAW,CAAC,MAAM,GAAG,CAAC;YACtB,yBAAyB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;QAErD,IAAI,YAAY,IAAI,YAAY,EAAE,CAAC;YACjC,gEAAgE;YAChE,uEAAuE;YACvE,OAAO,CAAC,GAAG,WAAW,EAAE,GAAG,WAAW,CAAC,CAAA;QACzC,CAAC;QAED,uBAAuB,CACrB,WAAW,EACX,WAAW,EACX,QAAQ,EACR,KAAK,CAAC,QAAQ,CACf,CAAA;QAED,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,uBAAuB,CACrB,WAAW,EACX,WAAW,EACX,IAAI,EACJ,KAAK,CAAC,QAAQ,CACf,CAAA;QACH,CAAC;QAED,OAAO,SAAS,CAAA;IAClB,CAAC;IAED;;;;;;;;;OASG;IACH,eAAe,EAAE,GAAG,EAAE;QACpB,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5C,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;YAC9B,2DAA2D;YAC3D,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,cAAc;gBAAE,SAAQ;YAExD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA;YAE5B,uCAAuC;YACvC,sEAAsE;YACtE,iEAAiE;YACjE,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CACrC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CACpD,CAAA;YACD,MAAM,aAAa,GACjB,YAAY,EAAE,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,CAAA;YAEzD,IACE,aAAa;gBACb,iBAAiB,CAAC,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,EACvD,CAAC;gBACD,kEAAkE;gBAClE,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBAC5C,IAAI,YAAY,EAAE,EAAE,IAAI,YAAY,CAAC,EAAE,KAAK,aAAa,EAAE,CAAC;oBAC1D,YAAY,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;oBAC5C,YAAY,CAAC,EAAE,GAAG,aAAa,CAAA;oBAC/B,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;gBACzC,CAAC;qBAAM,IAAI,CAAC,YAAY,EAAE,CAAC;oBACzB,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,CAAA;gBAChD,CAAC;gBACD,SAAQ;YACV,CAAC;YAED,mDAAmD;YACnD,mDAAmD;YACnD,MAAM,SAAS,GAAG,mBAAmB,CACnC,IAAI,EACJ,IAAI,EACJ,aAAa,EACb,QAAQ,EACR,KAAK,CACN,CAAA;YACD,IAAI,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1C,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;gBAC1C,SAAQ;YACV,CAAC;YAED,sCAAsC;YACtC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACnC,IACE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBACxB,KAAK,EAAE,MAAM;gBACb,iBAAiB,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,EACtD,CAAC;gBACD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;gBAC7C,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC3B,SAAQ;YACV,CAAC;YAED,iEAAiE;YACjE,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;gBAC5B,4DAA4D;gBAC5D,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;YACjC,CAAC;iBAAM,IACL,YAAY;gBACZ,YAAY,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,EAC5C,CAAC;gBACD,2DAA2D;gBAC3D,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,CAAA;YACxD,CAAC;iBAAM,CAAC;gBACN,4DAA4D;gBAC5D,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACxB,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,KAAY,EACZ,kBAA4C,EAC5C,EAAE;IACF,KAAK,MAAM,kBAAkB,IAAI,kBAAkB,EAAE,CAAC;QACpD,qDAAqD;QACrD,MAAM,eAAe,GAAG,CAAC,GAAG,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC5D,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CACzC,CAAA;QAED,uDAAuD;QACvD,MAAM,YAAY,GAAG,IAAI,GAAG,EAGzB,CAAA;QACH,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;YACvC,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,EAAE,CAAA;YACrD,IAAI,SAAS,EAAE,CAAC;gBACd,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;YACvC,CAAC;QACH,CAAC;QAED,oDAAoD;QACpD,MAAM,yBAAyB,GAAG;YAChC,GAAG,YAAY,CAAC,OAAO,EAAE;SAC1B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAA;QAE9D,0CAA0C;QAC1C,6DAA6D;QAC7D,IAAI,WAAW,CAAA;QACf,KAAK,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,IAAI,yBAAyB,EAAE,CAAC;YAChE,+DAA+D;YAC/D,0DAA0D;YAC1D,IACE,WAAW;gBACX,CAAC,yBAAyB,CAAC,WAAW,EAAE,WAAW,CAAC,EACpD,CAAC;gBACD,uBAAuB,CACrB,WAAW,EACX,WAAW,EACX,QAAQ,CAAC,IAAI,EACb,KAAK,CAAC,QAAQ,CACf,CAAA;gBACD,QAAQ,CAAC,WAAW,GAAG,WAAW,CAAA;gBAClC,SAAQ;YACV,CAAC;YAED,4CAA4C;YAC5C,QAAQ,CAAC,WAAW,GAAG,eAAe,CACpC,KAAK,EACL,QAAQ,CAAC,WAAW,EACpB,WAAW,CACZ,CAAA;YACD,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAA;QACpC,CAAC;QAED,qDAAqD;QACrD,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;YACvC,QAAQ,CAAC,aAAa,CAAC,eAAe,EAAE,CAAA;YACxC,wDAAwD;YACxD,QAAQ,CAAC,IAAI,GAAG,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACvD,CAAC;IACH,CAAC;AACH,CAAC,CAAA","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"]}
1
+ {"version":3,"file":"peers.js","sourceRoot":"","sources":["../../src/ideal/peers.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,2CAA2C;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AASpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAsBnD;;;;;;;;;;GAUG;AACH,MAAM,iBAAiB,GAAG,CACxB,IAAU,EACV,IAAU,EACV,QAAc,EACd,KAAY,EACH,EAAE,CACX,SAAS,CACP,IAAI,CAAC,EAAE,EACP,IAAI,EACJ,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,WAAW,EACpB,KAAK,CAAC,QAAQ,CACf,CAAA;AAEH;;;;;;GAMG;AACH,MAAM,SAAS,GAAG,CAChB,IAAY,EACZ,QAAgB,EAChB,QAAc,EACd,KAAY,EACN,EAAE,CACR,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE;IACzB,GAAG,KAAK,CAAC,YAAY,CAAC,OAAO;IAC7B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;CAC5B,CAAC,CAAA;AAEJ;;;;;;;;;GASG;AACH,MAAM,UAAU,GAAG,CACjB,WAAwB,EACxB,OAAgC,EAChC,EAAE;IACF,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,IAAI,CAAC,CAAA;IACnC,MAAM,GAAG,GAAG,OAAO;SAChB,GAAG,CACF,CAAC,CAAC,EAAE,CACF,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CACpE;SACA,IAAI,EAAE;SACN,IAAI,CAAC,GAAG,CAAC,CAAA;IACZ,OAAO,GAAG,IAAI,KAAK,GAAG,EAAE,CAAA;AAC1B,CAAC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,2BAA2B,GAAG,CAClC,QAAgB,EAChB,aAAmB,EACnB,QAAc,EACd,KAAY,EACH,EAAE;IACX,MAAM,cAAc,GAAG,QAAQ,CAAC,QAAQ,CAAA;IACxC,0EAA0E;IAC1E,IAAI,CAAC,cAAc;QAAE,OAAO,KAAK,CAAA;IAEjC,4DAA4D;IAC5D,KAAK,MAAM,OAAO,IAAI,mBAAmB,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAA;QACpD,IAAI,CAAC,QAAQ;YAAE,SAAQ;QAEvB,sEAAsE;QACtE,MAAM,UAAU,GAAG,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;QACjE,uEAAuE;QACvE,qDAAqD;QACrD,OAAO,CAAC,iBAAiB,CACvB,aAAa,EACb,UAAU,EACV,QAAQ,EACR,KAAK,CACN,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,uBAAuB,GAAG,CAC9B,MAAY,EACZ,QAAc,EACd,IAAwB,EACxB,QAAc,EACd,KAAY,EACsB,EAAE;IACpC,IAAI,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;QACzD,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;SAC5C,CAAA;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,YAAkB,EAClB,QAAc,EACd,WAAwB,EACxB,KAAY,EACU,EAAE;IACxB,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,gBAAgB,CAAA;IACxD,mCAAmC;IACnC,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;IAC7B,CAAC;IAED,6EAA6E;IAC7E,MAAM,SAAS,GAAG;QAChB,GAAG,KAAK,CAAC,YAAY,CAAC,OAAO;QAC7B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;KAC5B,CAAA;IACD,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAA;IACtC,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAA;IACxC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;IAC/B,MAAM,aAAa,GAAG,IAAI,GAAG,EAAmB,CAAA;IAChD,MAAM,iBAAiB,GAAG,CAAC,IAAU,EAAE,IAAU,EAAW,EAAE;QAC5D,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAA;QAC/E,IAAI,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACnC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,GAAG,SAAS,CAChB,IAAI,CAAC,EAAE,EACP,IAAI,EACJ,YAAY,EACZ,WAAW,EACX,QAAQ,CACT,CAAA;YACD,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QAChC,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;IACD,MAAM,gBAAgB,GAAG,CACvB,IAAU,EACV,KAAqB,EACZ,EAAE;QACX,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAA;QAC/C,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;IAED,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAChC,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAA;QACvC,0EAA0E;QAC1E,IAAI,CAAC,YAAY;YAAE,SAAQ;QAC3B,MAAM,YAAY,GAAG,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAExD,2EAA2E;QAC3E,wEAAwE;QACxE,qEAAqE;QACrE,8EAA8E;QAC9E,gFAAgF;QAChF,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;QAC9B,CAAC;QAED,mFAAmF;QACnF,IAAI,CAAC,YAAY,CAAC,EAAE;YAAE,SAAQ;QAE9B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,SAAS,CAAC,CAAA;QAE9D,oEAAoE;QACpE,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC9C,IACE,YAAY,EAAE,MAAM;YACpB,YAAY,CAAC,MAAM,CAAC,EAAE,KAAK,YAAY,CAAC,EAAE,CAAC,EAAE;YAC7C,CAAC,2BAA2B,CAC1B,QAAQ,EACR,YAAY,CAAC,MAAM,EACnB,QAAQ,EACR,KAAK,CACN,EACD,CAAC;YACD,2EAA2E;YAC3E,iFAAiF;YACjF,0EAA0E;YAC1E,oEAAoE;YACpE,MAAM,cAAc,GAAG,YAAY,CAAC,EAAE,CAAA;YACtC,MAAM,2BAA2B,GAAG,iBAAiB,CACnD,cAAc,EACd,QAAQ,CACT,CAAA;YACD,IACE,2BAA2B;gBAC3B,gBAAgB,CAAC,cAAc,EAAE,YAAY,CAAC,KAAK,CAAC,EACpD,CAAC;gBACD,SAAQ,CAAC,oBAAoB;YAC/B,CAAC;YACD,MAAM,MAAM,GAAG,uBAAuB,CACpC,YAAY,CAAC,MAAM,EACnB,QAAQ,EACR,YAAY,CAAC,IAAI,EACjB,QAAQ,EACR,KAAK,CACN,CAAA;YACD,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAA;QAC3B,CAAC;QAED,oEAAoE;QACpE,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACnD,IAAI,WAAW,EAAE,EAAE,IAAI,WAAW,CAAC,EAAE,CAAC,EAAE,KAAK,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAChE,2EAA2E;YAC3E,4EAA4E;YAC5E,MAAM,cAAc,GAAG,YAAY,CAAC,EAAE,CAAA;YACtC,MAAM,2BAA2B,GAAG,iBAAiB,CACnD,cAAc,EACd,QAAQ,CACT,CAAA;YACD,IACE,2BAA2B;gBAC3B,iBAAiB,CAAC,cAAc,EAAE,WAAW,CAAC,IAAI,CAAC,EACnD,CAAC;gBACD,SAAQ,CAAC,oBAAoB;YAC/B,CAAC;YACD,MAAM,MAAM,GAAG,uBAAuB,CACpC,WAAW,CAAC,EAAE,EACd,QAAQ,EACR,WAAW,CAAC,IAAI,EAChB,QAAQ,EACR,KAAK,CACN,CAAA;YACD,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAA;QAC3B,CAAC;QAED,sEAAsE;QACtE,wCAAwC;QACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAA;QAClC,IAAI,QAA4B,CAAA;QAChC,IAAI,YAA4C,CAAA;QAEhD,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,MAAM,OAAO,IAAI,mBAAmB,EAAE,CAAC;gBAC1C,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;gBAC9B,IACE,IAAI;oBACJ,OAAO,IAAI,KAAK,QAAQ;oBACxB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;oBACpB,QAAQ,IAAI,IAAI,EAChB,CAAC;oBACD,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAA;oBACzB,YAAY,GAAG,OAAO,CAAA;oBACtB,MAAK;gBACP,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,IAAI,YAAY,EAAE,CAAC;YAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAA;YAC5D,oEAAoE;YACpE,yEAAyE;YACzE,8EAA8E;YAC9E,IAAI,iBAAiB,CAAC,YAAY,CAAC,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC;gBACnD,SAAQ,CAAC,oDAAoD;YAC/D,CAAC;YACD,yEAAyE;YACzE,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YAClD,IAAI,UAAU,EAAE,CAAC;gBACf,KAAK,MAAM,aAAa,IAAI,UAAU,EAAE,CAAC;oBACvC,IACE,aAAa,CAAC,EAAE,KAAK,YAAY,CAAC,EAAE,CAAC,EAAE;wBACvC,iBAAiB,CAAC,aAAa,EAAE,UAAU,CAAC;wBAC5C,iBAAiB,CAAC,aAAa,EAAE,QAAQ,CAAC,EAC1C,CAAC;wBACD,OAAO;4BACL,UAAU,EAAE,KAAK;4BACjB,SAAS,EAAE;gCACT,IAAI,EAAE,QAAQ;gCACd,MAAM,EAAE,aAAa;gCACrB,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC;6BAC5B;yBACF,CAAA;oBACH,CAAC;gBACH,CAAC;gBACD,oBAAoB;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;AAC7B,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,WAAoC,EAChB,EAAE;IACtB,8CAA8C;IAC9C,IAAI,CAAC,WAAW,EAAE,KAAK;QAAE,OAAO,SAAS,CAAA;IAEzC,OAAO,QAAQ,WAAW,CAAC,KAAK,EAAE,CAAA;AACpC,CAAC,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,IAAU,EACV,KAAuB,EACd,EAAE;IACX,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAA;YAClB;YACE,kDAAkD;YAClD,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU;gBACvB,CAAC,CAAC,IAAI,CAAC,KAAK;oBACV,CAAC,CAAC,CAAC,KAAK;oBACR,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtC,mDAAmD;gBACnD,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,CAAC,EAC1D,CAAC;gBACD,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAC1C,OAAgC,EACP,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;AAE9D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,WAAwB,EACxB,OAAgC,EACvB,EAAE;IACX,wCAAwC;IACxC,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA;QAE5C,0BAA0B;QAC1B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACnC,IAAI,CAAC,KAAK,EAAE,MAAM;YAAE,SAAQ;QAE5B,kEAAkE;QAClE,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,WAAwB,EACxB,OAAgC,EAChC,QAAc,EACd,QAAmB,EACV,EAAE;IACX,4CAA4C;IAC5C,IAAI,yBAAyB,CAAC,WAAW,EAAE,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IAEhE,KAAK,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;QACxD,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA;QAC5C,IAAI,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAEjC,kCAAkC;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG;gBACN,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;gBACtB,MAAM;gBACN,IAAI;gBACJ,iBAAiB,EAAE,IAAI,GAAG,EAAE;aAC7B,CAAA;YACD,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;YAC5B,IAAI,SAAS;gBAAE,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;YACrD,SAAQ;QACV,CAAC;QAED,kCAAkC;QAClC,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;QAErD,6CAA6C;QAC7C,IACE,MAAM;YACN,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CACzB,SAAS,CACP,MAAM,CAAC,EAAE,EACT,CAAC,EACD,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,WAAW,EACpB,QAAQ,CACT,CACF,EACD,CAAC;YACD,IACE,MAAM,CAAC,EAAE,KAAK,KAAK,CAAC,MAAM,EAAE,EAAE;gBAC9B,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,EACxC,CAAC;gBACD,2CAA2C;gBAC3C,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;oBAC1C,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;oBACnC,IAAI,IAAI,EAAE,EAAE,IAAI,IAAI,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;wBACnC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;wBAC5B,IAAI,CAAC,EAAE,GAAG,MAAM,CAAA;wBAChB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;oBAC1B,CAAC;gBACH,CAAC;gBACD,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;YACvB,CAAC;YACD,KAAK,CAAC,MAAM,KAAK,MAAM,CAAA;QACzB,CAAC;QAED,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACrB,IAAI,SAAS;YAAE,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACvD,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,KAAY,EACZ,WAAwB,EACxB,OAAgC,EACnB,EAAE;IACf,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IAChD,MAAM,MAAM,GAAG,KAAK,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACtD,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAA;IACf,CAAC;IAED,gCAAgC;IAChC,MAAM,eAAe,GAAgB,IAAI,GAAG,EAAE,CAAA;IAC9C,eAAe,CAAC,KAAK,GAAG,KAAK,CAAC,oBAAoB,EAAE,CAAA;IACpD,2BAA2B;IAC3B,KAAK,CAAC,YAAY,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,eAAe,CAAA;IAC3D,KAAK,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;IAExD,sEAAsE;IACtE,2EAA2E;IAC3E,6DAA6D;IAC7D,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;QAClD,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE;YACxB,MAAM,EAAE,KAAK;YACb,KAAK,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;YAC3B,MAAM,EAAE,SAAS;YACjB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,iBAAiB,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC;SACpD,CAAC,CAAA;IACJ,CAAC;IAED,uEAAuE;IACvE,6EAA6E;IAC7E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAA;QAC/C,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA;QACjE,MAAM,QAAQ,GAAG;YACf,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;YACtB,MAAM;YACN,IAAI;YACJ,iBAAiB,EACf,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAQ;SACrD,CAAA;QACD,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACrC,CAAC;IAED,OAAO,eAAe,CAAA;AACxB,CAAC,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,mBAAmB,GAAG,CAC1B,IAAY,EACZ,QAAc,EACd,aAAsC,EACtC,QAAc,EACd,KAAY,EACM,EAAE;IACpB,8CAA8C;IAC9C,MAAM,KAAK,GAAG,aAAa;SACxB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;SAClB,MAAM,CAAC,CAAC,CAAC,EAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,MAAM,CAAC,GAAiC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,KAAK,EAAE,CAAC;KACT,CAAC,CAAC,CAAA;IAEH,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAA;QACrB,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,SAAQ;QACxC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAElB,+DAA+D;QAC/D,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACrC,IACE,IAAI,EAAE,EAAE;YACR,iBAAiB,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EACrD,CAAC;YACD,OAAO,IAAI,CAAC,EAAE,CAAA;QAChB,CAAC;QAED,oEAAoE;QACpE,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACxC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC7D,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAA;YAC3C,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,WAAwB,EACxB,QAAkB,EAClB,QAAc,EACd,OAAoB,EACpB,EAAE;IACF,sEAAsE;IACtE,mEAAmE;IACnE,6CAA6C;IAC7C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAiC,CAAA;IACzD,IAAI,WAA+B,CAAA;IAEnC,IACE,QAAQ,CAAC,gBAAgB;QACzB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,MAAM,GAAG,CAAC,EACjD,CAAC;QACD,mDAAmD;QACnD,wCAAwC;QACxC,WAAW,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAA;QAElD,gDAAgD;QAChD,kDAAkD;QAClD,MAAM,WAAW,GAAG,eAAe,CAAC,QAAQ,EAAE;YAC5C,GAAG,OAAO;YACV,QAAQ,EAAE,QAAQ,CAAC,QAAQ;SAC5B,CAAC,CAAA;QACF,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;YACzC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;QAC5B,CAAC;QAED,wDAAwD;QACxD,sDAAsD;QACtD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9C,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;gBACtB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,WAAW;QACX,6CAA6C;QAC7C,aAAa,EAAE,4BAA4B,CAAC;YAC1C,GAAG,QAAQ,CAAC,MAAM,EAAE;SACrB,CAAC;KACH,CAAA;AACH,CAAC,CAAA;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,WAAwB,EACxB,QAAsB,EACtB,YAAuD,EACvD,KAAY,EACZ,IAAU,EACV,QAAc,EACd,IAAU,EACV,IAAwB,EACxB,aAAsC,EACtC,EAAE,CAAC,CAAC;IACJ;;;;;;;;;;;OAWG;IACH,UAAU,EAAE,GAAG,EAAE;QACf,kDAAkD;QAClD,kDAAkD;QAClD,MAAM,WAAW,GAAG;YAClB,GAAG,aAAa;YAChB,gBAAgB,CAAC;gBACf,IAAI;gBACJ,MAAM,EAAE,IAAI;gBACZ,IAAI;aACL;SACF,CAAA;QAED,MAAM,WAAW,GAAG;YAClB,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,GAAG,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACxC,GAAG,GAAG;gBACN,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC;SACJ,CAAA;QAED,MAAM,YAAY,GAAG,yBAAyB,CAC5C,WAAW,EACX,WAAW,CACZ,CAAA;QACD,MAAM,YAAY,GAChB,WAAW,CAAC,MAAM,GAAG,CAAC;YACtB,yBAAyB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;QAErD,IAAI,YAAY,IAAI,YAAY,EAAE,CAAC;YACjC,gEAAgE;YAChE,uEAAuE;YACvE,OAAO,CAAC,GAAG,WAAW,EAAE,GAAG,WAAW,CAAC,CAAA;QACzC,CAAC;QAED,uBAAuB,CACrB,WAAW,EACX,WAAW,EACX,QAAQ,EACR,KAAK,CAAC,QAAQ,CACf,CAAA;QAED,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,uBAAuB,CACrB,WAAW,EACX,WAAW,EACX,IAAI,EACJ,KAAK,CAAC,QAAQ,CACf,CAAA;QACH,CAAC;QAED,OAAO,SAAS,CAAA;IAClB,CAAC;IAED;;;;;;;;;OASG;IACH,eAAe,EAAE,GAAG,EAAE;QACpB,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5C,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;YAC9B,2DAA2D;YAC3D,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,cAAc;gBAAE,SAAQ;YAExD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA;YAE5B,uCAAuC;YACvC,sEAAsE;YACtE,iEAAiE;YACjE,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CACrC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CACpD,CAAA;YACD,MAAM,aAAa,GACjB,YAAY,EAAE,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,CAAA;YAEzD,IACE,aAAa;gBACb,iBAAiB,CAAC,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,EACvD,CAAC;gBACD,kEAAkE;gBAClE,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBAC5C,IAAI,YAAY,EAAE,EAAE,IAAI,YAAY,CAAC,EAAE,KAAK,aAAa,EAAE,CAAC;oBAC1D,YAAY,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;oBAC5C,YAAY,CAAC,EAAE,GAAG,aAAa,CAAA;oBAC/B,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;gBACzC,CAAC;qBAAM,IAAI,CAAC,YAAY,EAAE,CAAC;oBACzB,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,CAAA;gBAChD,CAAC;gBACD,SAAQ;YACV,CAAC;YAED,mDAAmD;YACnD,mDAAmD;YACnD,MAAM,SAAS,GAAG,mBAAmB,CACnC,IAAI,EACJ,IAAI,EACJ,aAAa,EACb,QAAQ,EACR,KAAK,CACN,CAAA;YACD,IAAI,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1C,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;gBAC1C,SAAQ;YACV,CAAC;YAED,sCAAsC;YACtC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACnC,IACE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBACxB,KAAK,EAAE,MAAM;gBACb,iBAAiB,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,EACtD,CAAC;gBACD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;gBAC7C,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC3B,SAAQ;YACV,CAAC;YAED,iEAAiE;YACjE,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;gBAC5B,4DAA4D;gBAC5D,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;YACjC,CAAC;iBAAM,IACL,YAAY;gBACZ,YAAY,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,EAC5C,CAAC;gBACD,2DAA2D;gBAC3D,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,CAAA;YACxD,CAAC;iBAAM,CAAC;gBACN,4DAA4D;gBAC5D,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACxB,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,KAAY,EACZ,kBAA4C,EAC5C,EAAE;IACF,KAAK,MAAM,kBAAkB,IAAI,kBAAkB,EAAE,CAAC;QACpD,qDAAqD;QACrD,MAAM,eAAe,GAAG,CAAC,GAAG,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC5D,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CACzC,CAAA;QAED,uDAAuD;QACvD,MAAM,YAAY,GAAG,IAAI,GAAG,EAGzB,CAAA;QACH,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;YACvC,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,EAAE,CAAA;YACrD,IAAI,SAAS,EAAE,CAAC;gBACd,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;YACvC,CAAC;QACH,CAAC;QAED,oDAAoD;QACpD,MAAM,yBAAyB,GAAG;YAChC,GAAG,YAAY,CAAC,OAAO,EAAE;SAC1B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAA;QAE9D,0CAA0C;QAC1C,6DAA6D;QAC7D,IAAI,WAAW,CAAA;QACf,KAAK,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,IAAI,yBAAyB,EAAE,CAAC;YAChE,+DAA+D;YAC/D,0DAA0D;YAC1D,IACE,WAAW;gBACX,CAAC,yBAAyB,CAAC,WAAW,EAAE,WAAW,CAAC,EACpD,CAAC;gBACD,uBAAuB,CACrB,WAAW,EACX,WAAW,EACX,QAAQ,CAAC,IAAI,EACb,KAAK,CAAC,QAAQ,CACf,CAAA;gBACD,QAAQ,CAAC,WAAW,GAAG,WAAW,CAAA;gBAClC,SAAQ;YACV,CAAC;YAED,4CAA4C;YAC5C,QAAQ,CAAC,WAAW,GAAG,eAAe,CACpC,KAAK,EACL,QAAQ,CAAC,WAAW,EACpB,WAAW,CACZ,CAAA;YACD,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAA;QACpC,CAAC;QAED,qDAAqD;QACrD,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;YACvC,QAAQ,CAAC,aAAa,CAAC,eAAe,EAAE,CAAA;YACxC,wDAAwD;YACxD,QAAQ,CAAC,IAAI,GAAG,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACvD,CAAC;IACH,CAAC;AACH,CAAC,CAAA","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"]}
@@ -119,7 +119,7 @@ export const lockfileData = ({ graph, catalog, catalogs, 'git-hosts': gitHosts,
119
119
  ...(registry !== undefined && registry !== defaultRegistry ?
120
120
  { registry }
121
121
  : undefined),
122
- ...(hasItems(registries) ?
122
+ ...(hasItems(cleanRegistries) ?
123
123
  { registries: cleanRegistries }
124
124
  : undefined),
125
125
  ...(hasItems(cleanGitHosts) ?
@@ -1 +1 @@
1
- {"version":3,"file":"save.js","sourceRoot":"","sources":["../../src/lockfile/save.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n expandNormalizedManifestSymbols,\n isRecordStringString,\n} from '@vltpkg/types'\nimport {\n defaultGitHostArchives,\n defaultGitHosts,\n defaultJsrRegistries,\n defaultRegistries,\n defaultRegistry,\n defaultScopeRegistries,\n} from '@vltpkg/spec'\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport {\n getFlagNumFromNode,\n getBuildStateFromNode,\n LOCKFILE_VERSION,\n} from './types.ts'\nimport type { DepID } from '@vltpkg/dep-id'\nimport type { SpecOptions } from '@vltpkg/spec'\nimport type { Edge } from '../edge.ts'\nimport type { Graph } from '../graph.ts'\nimport type { Node } from '../node.ts'\nimport type {\n LockfileData,\n LockfileEdgeKey,\n LockfileEdges,\n LockfileEdgeValue,\n LockfileNode,\n LockfilePlatform,\n} from './types.ts'\nimport type { GraphModifier } from '../modifiers.ts'\nimport { error } from '@vltpkg/error-cause'\n\nexport type SaveOptions = SpecOptions & {\n /**\n * The graph to be stored in the lockfile.\n */\n graph: Graph\n /**\n * The graph modifiers helper object.\n */\n modifiers?: GraphModifier\n /**\n * Should it save manifest data in the lockfile?\n */\n saveManifests?: boolean\n /**\n * Should it save build state data in the lockfile?\n */\n saveBuildData?: boolean\n /**\n * Should it throw an error if a manifest is missing?\n */\n throwOnMissingManifest?: boolean\n}\n\nconst formatNodes = (\n nodes: Iterable<Node>,\n saveManifests?: boolean,\n saveBuildData?: boolean,\n registry?: string,\n throwOnMissingManifest?: boolean,\n) => {\n // we do not store importers in the lockfile, though we do store\n // their edges. when we load, we always read workspaces/main fresh.\n const arr: Node[] = [...nodes].filter(node => !node.importer)\n // nodes are sorted in order to have a deterministic result\n const orderedNodes: Node[] = arr.sort((a, b) =>\n a.id.localeCompare(b.id, 'en'),\n )\n\n const res: Record<DepID, LockfileNode> = {}\n for (const node of orderedNodes) {\n const customRegistry =\n node.resolved && registry && !node.resolved.startsWith(registry)\n const resolved = customRegistry ? node.resolved : undefined\n // if it's in a location other than the default, stash that\n const location =\n node.id.startsWith('file') || node.inVltStore() ?\n undefined\n : node.location\n\n const flags = getFlagNumFromNode(node)\n const lockfileNode: LockfileNode = [flags, node.name]\n\n if (node.integrity) {\n lockfileNode[2] = node.integrity\n }\n\n // skip resolved for remote nodes since\n // these are already part of the dep id\n if (resolved && !node.id.startsWith('remote')) {\n lockfileNode[3] = resolved\n }\n\n if (location) {\n lockfileNode[4] = location\n }\n\n if (saveManifests && node.manifest) {\n lockfileNode[5] = expandNormalizedManifestSymbols(node.manifest)\n\n if (node.confused && node.rawManifest) {\n lockfileNode[6] = expandNormalizedManifestSymbols(\n node.rawManifest,\n )\n }\n }\n\n // Throw an error if a manifest is missing and the option is enabled\n if (throwOnMissingManifest && !node.manifest) {\n throw error(`Missing manifest for node ${node.id}.`)\n }\n\n // Always save platform data for optional dependencies if available\n if (node.optional && node.platform) {\n lockfileNode[7] = node.platform as LockfilePlatform\n }\n\n // Save bin data if available\n if (node.bins && Object.keys(node.bins).length) {\n lockfileNode[8] = node.bins\n }\n\n // Save build state data if requested\n if (saveBuildData) {\n const buildState = getBuildStateFromNode(node)\n if (buildState !== undefined) {\n lockfileNode[9] = buildState\n }\n }\n\n res[node.id] = lockfileNode\n }\n return res\n}\n\nconst formatEdges = (edges: Set<Edge>): LockfileEdges =>\n Object.fromEntries(\n [...edges]\n .sort(\n (a, b) =>\n /* c8 ignore start - nondeterminstic and annoying to test */\n // sort importers to the top, then alphabetically by\n // id, type, target\n Number(b.from.importer) - Number(a.from.importer) ||\n a.from.id.localeCompare(b.from.id, 'en') ||\n a.type.localeCompare(b.type, 'en') ||\n (a.to?.id ?? '').localeCompare(b.to?.id ?? ''),\n /* c8 ignore stop */\n )\n .map((edge): [LockfileEdgeKey, LockfileEdgeValue] => [\n `${edge.from.id} ${edge.spec.name}`,\n `${edge.type} ${edge.spec.bareSpec || '*'} ${edge.to?.id ?? 'MISSING'}`,\n ]),\n )\n\nconst removeDefaultItems = (\n defaultItems: Record<string, string>,\n items: Record<string, string>,\n) => {\n const res: Record<string, string> = {}\n for (const [key, value] of Object.entries(items)) {\n if (!defaultItems[key] || defaultItems[key] !== value) {\n res[key] = value\n }\n }\n return res\n}\n\nexport const lockfileData = ({\n graph,\n catalog,\n catalogs,\n 'git-hosts': gitHosts,\n 'git-host-archives': gitHostArchives,\n modifiers,\n registry,\n registries,\n saveManifests,\n saveBuildData,\n 'scope-registries': scopeRegistries,\n 'jsr-registries': jsrRegistries,\n throwOnMissingManifest,\n}: SaveOptions): LockfileData => {\n const cleanGitHosts =\n isRecordStringString(gitHosts) ?\n removeDefaultItems(defaultGitHosts, gitHosts)\n : undefined\n const cleanGitHostArchives =\n isRecordStringString(gitHostArchives) ?\n removeDefaultItems(defaultGitHostArchives, gitHostArchives)\n : undefined\n const cleanModifiers =\n modifiers && isRecordStringString(modifiers.config) ?\n modifiers.config\n : undefined\n const cleanRegistries =\n isRecordStringString(registries) ?\n removeDefaultItems(defaultRegistries, registries)\n : undefined\n const cleanScopeRegistries =\n isRecordStringString(scopeRegistries) ?\n removeDefaultItems(defaultScopeRegistries, scopeRegistries)\n : undefined\n const cleanJsrRegistries =\n isRecordStringString(jsrRegistries) ?\n removeDefaultItems(defaultJsrRegistries, jsrRegistries)\n : undefined\n const hasItems = (clean: Record<string, unknown> | undefined) =>\n clean && Object.keys(clean).length\n return {\n lockfileVersion: LOCKFILE_VERSION,\n options: {\n ...(hasItems(cleanModifiers) ?\n { modifiers: cleanModifiers }\n : {}),\n ...(hasItems(catalog) ? { catalog } : {}),\n ...(hasItems(catalogs) ? { catalogs } : {}),\n ...(hasItems(cleanScopeRegistries) ?\n { 'scope-registries': cleanScopeRegistries }\n : undefined),\n ...(hasItems(cleanJsrRegistries) ?\n { 'jsr-registries': cleanJsrRegistries }\n : undefined),\n ...(registry !== undefined && registry !== defaultRegistry ?\n { registry }\n : undefined),\n ...(hasItems(registries) ?\n { registries: cleanRegistries }\n : undefined),\n ...(hasItems(cleanGitHosts) ?\n { 'git-hosts': cleanGitHosts }\n : undefined),\n ...(hasItems(cleanGitHostArchives) ?\n { 'git-host-archives': cleanGitHostArchives }\n : undefined),\n },\n nodes: formatNodes(\n graph.nodes.values(),\n saveManifests,\n saveBuildData,\n registry,\n throwOnMissingManifest,\n ),\n edges: formatEdges(graph.edges),\n }\n}\n\n// renders each node / edge as a single line entry\nconst extraFormat = (jsonString: string) => {\n const str = `${jsonString}\\n`\n const [init, ...parts] = str.split(' \"nodes\": {')\n const res = [init]\n for (const part of parts) {\n res.push(\n part.replaceAll('\\n ', '').replaceAll('\\n ]', ']'),\n )\n }\n return res.join(' \"nodes\": {')\n}\n\nexport const saveData = (\n data: LockfileData,\n fileName: string,\n saveManifests = false,\n): void => {\n const json = JSON.stringify(data, null, 2)\n const content = saveManifests ? json : extraFormat(json)\n writeFileSync(fileName, content)\n}\n\nexport const save = (\n options: Omit<SaveOptions, 'saveManifests'>,\n): void => {\n const { graph } = options\n const data = lockfileData({ ...options, saveManifests: false })\n const fileName = resolve(graph.projectRoot, 'vlt-lock.json')\n saveData(data, fileName, false)\n}\n\nexport const saveHidden = (\n options: Omit<SaveOptions, 'saveManifests' | 'saveBuildData'>,\n): void => {\n const { graph } = options\n let data: LockfileData | undefined\n\n try {\n data = lockfileData({\n ...options,\n saveManifests: true,\n saveBuildData: true,\n throwOnMissingManifest: true,\n })\n } catch {}\n\n if (!data) return\n\n const fileName = resolve(\n graph.projectRoot,\n 'node_modules/.vlt-lock.json',\n )\n mkdirSync(dirname(fileName), { recursive: true })\n saveData(data, fileName, true)\n}\n"]}
1
+ {"version":3,"file":"save.js","sourceRoot":"","sources":["../../src/lockfile/save.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n expandNormalizedManifestSymbols,\n isRecordStringString,\n} from '@vltpkg/types'\nimport {\n defaultGitHostArchives,\n defaultGitHosts,\n defaultJsrRegistries,\n defaultRegistries,\n defaultRegistry,\n defaultScopeRegistries,\n} from '@vltpkg/spec'\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport {\n getFlagNumFromNode,\n getBuildStateFromNode,\n LOCKFILE_VERSION,\n} from './types.ts'\nimport type { DepID } from '@vltpkg/dep-id'\nimport type { SpecOptions } from '@vltpkg/spec'\nimport type { Edge } from '../edge.ts'\nimport type { Graph } from '../graph.ts'\nimport type { Node } from '../node.ts'\nimport type {\n LockfileData,\n LockfileEdgeKey,\n LockfileEdges,\n LockfileEdgeValue,\n LockfileNode,\n LockfilePlatform,\n} from './types.ts'\nimport type { GraphModifier } from '../modifiers.ts'\nimport { error } from '@vltpkg/error-cause'\n\nexport type SaveOptions = SpecOptions & {\n /**\n * The graph to be stored in the lockfile.\n */\n graph: Graph\n /**\n * The graph modifiers helper object.\n */\n modifiers?: GraphModifier\n /**\n * Should it save manifest data in the lockfile?\n */\n saveManifests?: boolean\n /**\n * Should it save build state data in the lockfile?\n */\n saveBuildData?: boolean\n /**\n * Should it throw an error if a manifest is missing?\n */\n throwOnMissingManifest?: boolean\n}\n\nconst formatNodes = (\n nodes: Iterable<Node>,\n saveManifests?: boolean,\n saveBuildData?: boolean,\n registry?: string,\n throwOnMissingManifest?: boolean,\n) => {\n // we do not store importers in the lockfile, though we do store\n // their edges. when we load, we always read workspaces/main fresh.\n const arr: Node[] = [...nodes].filter(node => !node.importer)\n // nodes are sorted in order to have a deterministic result\n const orderedNodes: Node[] = arr.sort((a, b) =>\n a.id.localeCompare(b.id, 'en'),\n )\n\n const res: Record<DepID, LockfileNode> = {}\n for (const node of orderedNodes) {\n const customRegistry =\n node.resolved && registry && !node.resolved.startsWith(registry)\n const resolved = customRegistry ? node.resolved : undefined\n // if it's in a location other than the default, stash that\n const location =\n node.id.startsWith('file') || node.inVltStore() ?\n undefined\n : node.location\n\n const flags = getFlagNumFromNode(node)\n const lockfileNode: LockfileNode = [flags, node.name]\n\n if (node.integrity) {\n lockfileNode[2] = node.integrity\n }\n\n // skip resolved for remote nodes since\n // these are already part of the dep id\n if (resolved && !node.id.startsWith('remote')) {\n lockfileNode[3] = resolved\n }\n\n if (location) {\n lockfileNode[4] = location\n }\n\n if (saveManifests && node.manifest) {\n lockfileNode[5] = expandNormalizedManifestSymbols(node.manifest)\n\n if (node.confused && node.rawManifest) {\n lockfileNode[6] = expandNormalizedManifestSymbols(\n node.rawManifest,\n )\n }\n }\n\n // Throw an error if a manifest is missing and the option is enabled\n if (throwOnMissingManifest && !node.manifest) {\n throw error(`Missing manifest for node ${node.id}.`)\n }\n\n // Always save platform data for optional dependencies if available\n if (node.optional && node.platform) {\n lockfileNode[7] = node.platform as LockfilePlatform\n }\n\n // Save bin data if available\n if (node.bins && Object.keys(node.bins).length) {\n lockfileNode[8] = node.bins\n }\n\n // Save build state data if requested\n if (saveBuildData) {\n const buildState = getBuildStateFromNode(node)\n if (buildState !== undefined) {\n lockfileNode[9] = buildState\n }\n }\n\n res[node.id] = lockfileNode\n }\n return res\n}\n\nconst formatEdges = (edges: Set<Edge>): LockfileEdges =>\n Object.fromEntries(\n [...edges]\n .sort(\n (a, b) =>\n /* c8 ignore start - nondeterminstic and annoying to test */\n // sort importers to the top, then alphabetically by\n // id, type, target\n Number(b.from.importer) - Number(a.from.importer) ||\n a.from.id.localeCompare(b.from.id, 'en') ||\n a.type.localeCompare(b.type, 'en') ||\n (a.to?.id ?? '').localeCompare(b.to?.id ?? ''),\n /* c8 ignore stop */\n )\n .map((edge): [LockfileEdgeKey, LockfileEdgeValue] => [\n `${edge.from.id} ${edge.spec.name}`,\n `${edge.type} ${edge.spec.bareSpec || '*'} ${edge.to?.id ?? 'MISSING'}`,\n ]),\n )\n\nconst removeDefaultItems = (\n defaultItems: Record<string, string>,\n items: Record<string, string>,\n) => {\n const res: Record<string, string> = {}\n for (const [key, value] of Object.entries(items)) {\n if (!defaultItems[key] || defaultItems[key] !== value) {\n res[key] = value\n }\n }\n return res\n}\n\nexport const lockfileData = ({\n graph,\n catalog,\n catalogs,\n 'git-hosts': gitHosts,\n 'git-host-archives': gitHostArchives,\n modifiers,\n registry,\n registries,\n saveManifests,\n saveBuildData,\n 'scope-registries': scopeRegistries,\n 'jsr-registries': jsrRegistries,\n throwOnMissingManifest,\n}: SaveOptions): LockfileData => {\n const cleanGitHosts =\n isRecordStringString(gitHosts) ?\n removeDefaultItems(defaultGitHosts, gitHosts)\n : undefined\n const cleanGitHostArchives =\n isRecordStringString(gitHostArchives) ?\n removeDefaultItems(defaultGitHostArchives, gitHostArchives)\n : undefined\n const cleanModifiers =\n modifiers && isRecordStringString(modifiers.config) ?\n modifiers.config\n : undefined\n const cleanRegistries =\n isRecordStringString(registries) ?\n removeDefaultItems(defaultRegistries, registries)\n : undefined\n const cleanScopeRegistries =\n isRecordStringString(scopeRegistries) ?\n removeDefaultItems(defaultScopeRegistries, scopeRegistries)\n : undefined\n const cleanJsrRegistries =\n isRecordStringString(jsrRegistries) ?\n removeDefaultItems(defaultJsrRegistries, jsrRegistries)\n : undefined\n const hasItems = (clean: Record<string, unknown> | undefined) =>\n clean && Object.keys(clean).length\n return {\n lockfileVersion: LOCKFILE_VERSION,\n options: {\n ...(hasItems(cleanModifiers) ?\n { modifiers: cleanModifiers }\n : {}),\n ...(hasItems(catalog) ? { catalog } : {}),\n ...(hasItems(catalogs) ? { catalogs } : {}),\n ...(hasItems(cleanScopeRegistries) ?\n { 'scope-registries': cleanScopeRegistries }\n : undefined),\n ...(hasItems(cleanJsrRegistries) ?\n { 'jsr-registries': cleanJsrRegistries }\n : undefined),\n ...(registry !== undefined && registry !== defaultRegistry ?\n { registry }\n : undefined),\n ...(hasItems(cleanRegistries) ?\n { registries: cleanRegistries }\n : undefined),\n ...(hasItems(cleanGitHosts) ?\n { 'git-hosts': cleanGitHosts }\n : undefined),\n ...(hasItems(cleanGitHostArchives) ?\n { 'git-host-archives': cleanGitHostArchives }\n : undefined),\n },\n nodes: formatNodes(\n graph.nodes.values(),\n saveManifests,\n saveBuildData,\n registry,\n throwOnMissingManifest,\n ),\n edges: formatEdges(graph.edges),\n }\n}\n\n// renders each node / edge as a single line entry\nconst extraFormat = (jsonString: string) => {\n const str = `${jsonString}\\n`\n const [init, ...parts] = str.split(' \"nodes\": {')\n const res = [init]\n for (const part of parts) {\n res.push(\n part.replaceAll('\\n ', '').replaceAll('\\n ]', ']'),\n )\n }\n return res.join(' \"nodes\": {')\n}\n\nexport const saveData = (\n data: LockfileData,\n fileName: string,\n saveManifests = false,\n): void => {\n const json = JSON.stringify(data, null, 2)\n const content = saveManifests ? json : extraFormat(json)\n writeFileSync(fileName, content)\n}\n\nexport const save = (\n options: Omit<SaveOptions, 'saveManifests'>,\n): void => {\n const { graph } = options\n const data = lockfileData({ ...options, saveManifests: false })\n const fileName = resolve(graph.projectRoot, 'vlt-lock.json')\n saveData(data, fileName, false)\n}\n\nexport const saveHidden = (\n options: Omit<SaveOptions, 'saveManifests' | 'saveBuildData'>,\n): void => {\n const { graph } = options\n let data: LockfileData | undefined\n\n try {\n data = lockfileData({\n ...options,\n saveManifests: true,\n saveBuildData: true,\n throwOnMissingManifest: true,\n })\n } catch {}\n\n if (!data) return\n\n const fileName = resolve(\n graph.projectRoot,\n 'node_modules/.vlt-lock.json',\n )\n mkdirSync(dirname(fileName), { recursive: true })\n saveData(data, fileName, true)\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vltpkg/graph",
3
3
  "description": "A library that helps understanding & expressing what happens on an install",
4
- "version": "1.0.0-rc.16",
4
+ "version": "1.0.0-rc.18",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/vltpkg/vltpkg.git",
@@ -11,26 +11,26 @@
11
11
  "dependencies": {
12
12
  "path-scurry": "^2.0.1",
13
13
  "promise-call-limit": "^3.0.2",
14
- "@vltpkg/cmd-shim": "1.0.0-rc.16",
15
- "@vltpkg/dep-id": "1.0.0-rc.16",
16
- "@vltpkg/dss-breadcrumb": "1.0.0-rc.16",
17
- "@vltpkg/error-cause": "1.0.0-rc.16",
18
- "@vltpkg/fast-split": "1.0.0-rc.16",
19
- "@vltpkg/graph-run": "1.0.0-rc.16",
20
- "@vltpkg/init": "1.0.0-rc.16",
21
- "@vltpkg/output": "1.0.0-rc.16",
22
- "@vltpkg/package-info": "1.0.0-rc.16",
23
- "@vltpkg/package-json": "1.0.0-rc.16",
24
- "@vltpkg/pick-manifest": "1.0.0-rc.16",
25
- "@vltpkg/query": "1.0.0-rc.16",
26
- "@vltpkg/run": "1.0.0-rc.16",
27
- "@vltpkg/rollback-remove": "1.0.0-rc.16",
28
- "@vltpkg/satisfies": "1.0.0-rc.16",
29
- "@vltpkg/security-archive": "1.0.0-rc.16",
30
- "@vltpkg/spec": "1.0.0-rc.16",
31
- "@vltpkg/types": "1.0.0-rc.16",
32
- "@vltpkg/vlt-json": "1.0.0-rc.16",
33
- "@vltpkg/workspaces": "1.0.0-rc.16"
14
+ "@vltpkg/dep-id": "1.0.0-rc.18",
15
+ "@vltpkg/dss-breadcrumb": "1.0.0-rc.18",
16
+ "@vltpkg/cmd-shim": "1.0.0-rc.18",
17
+ "@vltpkg/fast-split": "1.0.0-rc.18",
18
+ "@vltpkg/error-cause": "1.0.0-rc.18",
19
+ "@vltpkg/graph-run": "1.0.0-rc.18",
20
+ "@vltpkg/init": "1.0.0-rc.18",
21
+ "@vltpkg/output": "1.0.0-rc.18",
22
+ "@vltpkg/package-info": "1.0.0-rc.18",
23
+ "@vltpkg/package-json": "1.0.0-rc.18",
24
+ "@vltpkg/pick-manifest": "1.0.0-rc.18",
25
+ "@vltpkg/query": "1.0.0-rc.18",
26
+ "@vltpkg/rollback-remove": "1.0.0-rc.18",
27
+ "@vltpkg/run": "1.0.0-rc.18",
28
+ "@vltpkg/satisfies": "1.0.0-rc.18",
29
+ "@vltpkg/security-archive": "1.0.0-rc.18",
30
+ "@vltpkg/spec": "1.0.0-rc.18",
31
+ "@vltpkg/types": "1.0.0-rc.18",
32
+ "@vltpkg/vlt-json": "1.0.0-rc.18",
33
+ "@vltpkg/workspaces": "1.0.0-rc.18"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@eslint/js": "^9.39.1",
@@ -42,7 +42,7 @@
42
42
  "typedoc": "~0.27.9",
43
43
  "typescript": "5.7.3",
44
44
  "typescript-eslint": "^8.49.0",
45
- "@vltpkg/vlt-json": "1.0.0-rc.16"
45
+ "@vltpkg/vlt-json": "1.0.0-rc.18"
46
46
  },
47
47
  "license": "BSD-2-Clause-Patent",
48
48
  "engines": {