@vltpkg/graph 1.0.0-rc.13 → 1.0.0-rc.15

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.
Files changed (72) hide show
  1. package/README.md +97 -22
  2. package/dist/actual/load.d.ts.map +1 -1
  3. package/dist/actual/load.js +3 -2
  4. package/dist/actual/load.js.map +1 -1
  5. package/dist/diff.d.ts +2 -0
  6. package/dist/diff.d.ts.map +1 -1
  7. package/dist/diff.js +5 -1
  8. package/dist/diff.js.map +1 -1
  9. package/dist/fixup-added-names.d.ts +4 -1
  10. package/dist/fixup-added-names.d.ts.map +1 -1
  11. package/dist/fixup-added-names.js +16 -0
  12. package/dist/fixup-added-names.js.map +1 -1
  13. package/dist/graph.d.ts +7 -0
  14. package/dist/graph.d.ts.map +1 -1
  15. package/dist/graph.js +17 -2
  16. package/dist/graph.js.map +1 -1
  17. package/dist/ideal/append-nodes.d.ts +14 -2
  18. package/dist/ideal/append-nodes.d.ts.map +1 -1
  19. package/dist/ideal/append-nodes.js +188 -57
  20. package/dist/ideal/append-nodes.js.map +1 -1
  21. package/dist/ideal/build.d.ts.map +1 -1
  22. package/dist/ideal/build.js +11 -1
  23. package/dist/ideal/build.js.map +1 -1
  24. package/dist/ideal/peers.d.ts +90 -6
  25. package/dist/ideal/peers.d.ts.map +1 -1
  26. package/dist/ideal/peers.js +387 -131
  27. package/dist/ideal/peers.js.map +1 -1
  28. package/dist/ideal/refresh-ideal-graph.d.ts +0 -4
  29. package/dist/ideal/refresh-ideal-graph.d.ts.map +1 -1
  30. package/dist/ideal/refresh-ideal-graph.js +8 -24
  31. package/dist/ideal/refresh-ideal-graph.js.map +1 -1
  32. package/dist/ideal/sorting.d.ts +46 -0
  33. package/dist/ideal/sorting.d.ts.map +1 -0
  34. package/dist/ideal/sorting.js +71 -0
  35. package/dist/ideal/sorting.js.map +1 -0
  36. package/dist/ideal/types.d.ts +2 -6
  37. package/dist/ideal/types.d.ts.map +1 -1
  38. package/dist/ideal/types.js.map +1 -1
  39. package/dist/install.d.ts.map +1 -1
  40. package/dist/install.js +12 -0
  41. package/dist/install.js.map +1 -1
  42. package/dist/lockfile/load.d.ts.map +1 -1
  43. package/dist/lockfile/load.js +21 -0
  44. package/dist/lockfile/load.js.map +1 -1
  45. package/dist/lockfile/save.d.ts.map +1 -1
  46. package/dist/lockfile/save.js +2 -2
  47. package/dist/lockfile/save.js.map +1 -1
  48. package/dist/lockfile/types.d.ts +7 -0
  49. package/dist/lockfile/types.d.ts.map +1 -1
  50. package/dist/lockfile/types.js +6 -0
  51. package/dist/lockfile/types.js.map +1 -1
  52. package/dist/node.d.ts +2 -0
  53. package/dist/node.d.ts.map +1 -1
  54. package/dist/node.js.map +1 -1
  55. package/dist/reify/extract-node.d.ts.map +1 -1
  56. package/dist/reify/extract-node.js.map +1 -1
  57. package/dist/reify/index.d.ts +1 -0
  58. package/dist/reify/index.d.ts.map +1 -1
  59. package/dist/reify/index.js +2 -1
  60. package/dist/reify/index.js.map +1 -1
  61. package/dist/update.d.ts.map +1 -1
  62. package/dist/update.js +1 -0
  63. package/dist/update.js.map +1 -1
  64. package/dist/visualization/mermaid-output.d.ts +2 -1
  65. package/dist/visualization/mermaid-output.d.ts.map +1 -1
  66. package/dist/visualization/mermaid-output.js +28 -16
  67. package/dist/visualization/mermaid-output.js.map +1 -1
  68. package/package.json +22 -22
  69. package/dist/ideal/get-ordered-dependencies.d.ts +0 -10
  70. package/dist/ideal/get-ordered-dependencies.d.ts.map +0 -1
  71. package/dist/ideal/get-ordered-dependencies.js +0 -42
  72. package/dist/ideal/get-ordered-dependencies.js.map +0 -1
package/dist/graph.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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","sourcesContent":["import { getId, joinDepIDTuple, splitExtra } from '@vltpkg/dep-id'\nimport type { DepID } from '@vltpkg/dep-id'\nimport { error } from '@vltpkg/error-cause'\nimport { satisfies } from '@vltpkg/satisfies'\nimport { getOptions, Spec } from '@vltpkg/spec'\nimport type { SpecOptions } from '@vltpkg/spec'\nimport type {\n GraphLike,\n NodeLike,\n NormalizedManifest,\n DependencySaveType,\n} from '@vltpkg/types'\nimport type { Monorepo } from '@vltpkg/workspaces'\nimport { inspect } from 'node:util'\nimport type { InspectOptions } from 'node:util'\nimport { lockfileData } from './lockfile/save.ts'\nimport { Edge } from './edge.ts'\nimport { Node } from './node.ts'\nimport type { NodeOptions } from './node.ts'\nimport { resolveSaveType } from './resolve-save-type.ts'\nimport type { PeerContext } from './ideal/types.ts'\n\nconst kCustomInspect = Symbol.for('nodejs.util.inspect.custom')\n\nconst cacheKeySeparator = '│'\n\n// this is always the same, but we don't hard code it as a string,\n// in case the DepID module needs to change its delimiter again ever.\nconst mainDepID = joinDepIDTuple(['file', '.'])\n\nexport type ManifestInventory = Map<DepID, NormalizedManifest>\n\nconst getMap = <T extends Map<any, any>>(m?: T) =>\n m ?? (new Map() as T)\n\n/**\n * Get a cache key for a resolution based on the\n * spec, location and query modifier.\n */\nconst getResolutionCacheKey = (\n spec: Spec,\n location: string,\n extra: string,\n): string => {\n const f = spec.final\n // if it's a file: dep, then the fromNode location matters\n const fromPrefix = f.type === 'file' ? location + ' : ' : ''\n // the unique key should also precise what is the type of the spec,\n // and in the case of a registry, what registry it is from.\n const typePrecisionKey =\n f.registry ?\n `${cacheKeySeparator}registry` +\n `${cacheKeySeparator}${f.registry}`\n : f.gitRemote ?\n `${cacheKeySeparator}git` + `${cacheKeySeparator}${f.gitRemote}`\n : `${cacheKeySeparator}${f.type}`\n const modifierSuffix = `${cacheKeySeparator}${extra}`\n return fromPrefix + String(f) + typePrecisionKey + modifierSuffix\n}\n\nexport type GraphOptions = SpecOptions & {\n /**\n * The main importer manifest info.\n */\n mainManifest: NormalizedManifest\n /**\n * An inventory of seen manifests.\n */\n manifests?: ManifestInventory\n /**\n * A {@link Monorepo} object, for managing workspaces\n */\n monorepo?: Monorepo\n /**\n * Root of the project this graph represents\n */\n projectRoot: string\n}\n\nexport class Graph implements GraphLike {\n get [Symbol.toStringTag]() {\n return '@vltpkg/graph.Graph'\n }\n\n #options: GraphOptions\n\n #nodeOptions: NodeOptions\n\n /**\n * A {@link Monorepo} instance, used for managing workspaces.\n */\n monorepo?: Monorepo\n\n /**\n * An inventory with all manifests related to an install.\n */\n manifests: ManifestInventory\n\n /**\n * A set of all edges in this graph.\n */\n edges = new Set<Edge>()\n\n /**\n * Map registered dep ids to the node that represent them in the graph.\n */\n nodes = new Map<DepID, Node>()\n\n /**\n * Map of nodes by their name\n */\n nodesByName = new Map<string, Set<Node>>()\n\n /**\n * Cached resolutions for spec lookups\n */\n resolutions = new Map<string, Node>()\n\n /**\n * Reverse map of resolutions\n */\n resolutionsReverse = new Map<Node, Set<string>>()\n\n /**\n * A set of importer nodes in this graph.\n */\n importers = new Set<Node>()\n\n /**\n * The {@link Node} that represents the project root `package.json`.\n */\n mainImporter: Node\n\n /**\n * A set of extraneous dependencies found when building the graph.\n */\n extraneousDependencies = new Set<Edge>()\n\n /**\n * The root of the project this graph represents\n */\n projectRoot: string\n\n /**\n * The peer context sets used to resolve peer dependencies within this graph.\n */\n peerContexts: PeerContext[]\n\n /**\n * Tracks the current peer context index.\n */\n currentPeerContextIndex = 0\n\n constructor(options: GraphOptions) {\n const { mainManifest, monorepo } = options\n this.#options = options\n // hydrate spec options to their full contents, including defaults\n const specOptions = getOptions({\n registry: options.registry,\n registries: options.registries,\n 'git-hosts': options['git-hosts'],\n 'git-host-archives': options['git-host-archives'],\n 'scope-registries': options['scope-registries'],\n 'jsr-registries': options['jsr-registries'],\n catalog: options.catalog,\n catalogs: options.catalogs,\n })\n this.manifests = getMap(options.manifests)\n this.projectRoot = options.projectRoot\n this.#nodeOptions = {\n ...this.#options,\n ...specOptions,\n graph: this,\n }\n\n // add the project root node\n const mainImporterLocation = '.'\n const mainImporterSpec = Spec.parse(\n mainManifest.name || '(root)',\n mainImporterLocation,\n )\n const mainImporter = this.addNode(\n mainDepID,\n mainManifest,\n mainImporterSpec,\n )\n mainImporter.setImporterLocation(mainImporterLocation)\n mainImporter.mainImporter = true\n this.mainImporter = mainImporter\n this.mainImporter.workspaces = new Map()\n this.importers.add(mainImporter)\n this.manifests.set(mainImporter.id, mainManifest)\n\n // uses the monorepo instance in order to retrieve info on\n // workspaces and create importer nodes for each of them\n this.monorepo = monorepo\n if (this.monorepo) {\n for (const ws of this.monorepo) {\n const wsNode = this.addNode(\n ws.id,\n ws.manifest,\n undefined,\n ws.name,\n )\n wsNode.setImporterLocation(`./${ws.path}`)\n if (wsNode.manifest) {\n this.manifests.set(wsNode.id, wsNode.manifest)\n }\n this.importers.add(wsNode)\n // creates a virtual edge to connect the workspaces to the root node\n const edge = new Edge(\n 'prod',\n Spec.parse(wsNode.name, 'workspace:*', this.#options),\n this.mainImporter,\n wsNode,\n )\n this.mainImporter.workspaces.set(wsNode.name, edge)\n }\n }\n\n // initializes the peer context set collection\n const initialPeerContext: PeerContext = new Map()\n initialPeerContext.index = this.currentPeerContextIndex\n this.peerContexts = [initialPeerContext]\n }\n\n /**\n * Get the next peer context index.\n */\n nextPeerContextIndex() {\n return ++this.currentPeerContextIndex\n }\n\n /**\n * Delete all nodes and edges that are unreachable from the importers.\n * The collection of deleted nodes is returned.\n *\n * NOTE: This can be extremely slow for large graphs, and is almost always\n * unnecessary! Only call when it is known that some unreachable nodes may\n * have been created, for example when deleting the unneeded subgraph when an\n * optional node fails to resolve/install.\n */\n gc() {\n const { nodes } = this\n this.edges.clear()\n this.nodes = new Map()\n const marked = new Set(this.importers)\n for (const imp of marked) {\n // don't delete the importer!\n nodes.delete(imp.id)\n this.nodes.set(imp.id, imp)\n for (const edge of imp.edgesOut.values()) {\n this.edges.add(edge)\n const { to } = edge\n if (!to || marked.has(to)) continue\n marked.add(to)\n nodes.delete(to.id)\n this.nodes.set(to.id, to)\n }\n }\n for (const node of nodes.values()) {\n this.removeNode(node)\n }\n return nodes\n }\n\n /**\n * Create a new edge between two nodes of the graph in case both exist,\n * in case the destination node does not exists, then a dangling edge,\n * pointing to nothing will be created to represent that missing dependency.\n */\n addEdge(\n type: DependencySaveType,\n spec: Spec,\n from: NodeLike,\n to?: NodeLike,\n ) {\n // fix any nameless spec\n if (spec.name === '(unknown)') {\n if (to) {\n spec.name = to.name /* c8 ignore next */ || '(unknown)'\n spec.spec = `${to.name}@${spec.bareSpec}`\n } else {\n throw error(\n 'Impossible to place a missing, nameless dependency',\n { spec },\n )\n }\n }\n const existing = from.edgesOut.get(spec.name)\n if (existing) {\n const edge = existing as Edge\n if (\n edge.type === type &&\n edge.spec.bareSpec === spec.bareSpec\n ) {\n if (to && to !== edge.to) {\n // removes this edge from its destination edgesIn ref\n edge.to?.edgesIn.delete(edge)\n // now swap the destination to the new one\n edge.to = to as Node\n edge.to.edgesIn.add(edge)\n }\n return edge\n }\n this.edges.delete(edge)\n }\n const f = from as Node\n const edgeOut = f.addEdgesTo(\n resolveSaveType(from, spec.name, type),\n spec,\n to as Node | undefined,\n )\n this.edges.add(edgeOut)\n return edgeOut\n }\n\n /**\n * Find an existing node to satisfy a dependency\n */\n findResolution(spec: Spec, fromNode: Node, extra = '') {\n const f = spec.final\n const sf = getResolutionCacheKey(f, fromNode.location, extra)\n const cached = this.resolutions.get(sf)\n if (cached) return cached\n const nbn = this.nodesByName.get(f.name)\n if (!nbn) return undefined\n for (const node of nbn) {\n if (\n satisfies(\n node.id,\n f,\n fromNode.location,\n this.projectRoot,\n this.monorepo,\n )\n ) {\n this.resolutions.set(sf, node)\n // always set by now, because the node was added at some point\n this.resolutionsReverse.get(node)?.add(sf)\n return node\n }\n }\n }\n\n /**\n * Create a new node in the graph.\n */\n addNode(\n id?: DepID,\n manifest?: NormalizedManifest,\n spec?: Spec,\n name?: string,\n version?: string,\n ) {\n const node = new Node(\n this.#nodeOptions,\n id,\n manifest,\n spec,\n name,\n version,\n )\n this.nodes.set(node.id, node)\n const nbn = this.nodesByName.get(node.name) ?? new Set()\n nbn.add(node)\n\n // ensure the nodes by name set is always sorted, this will help\n // keeping a deterministic graph resolution when reusing nodes\n const newByNameSet = new Set(\n [...nbn].sort((a, b) => a.id.localeCompare(b.id)),\n )\n this.nodesByName.set(node.name, newByNameSet)\n\n if (manifest) {\n this.manifests.set(node.id, manifest)\n }\n return node\n }\n\n /**\n * Place a new package into the graph representation, creating the new\n * edges and possibly new nodes that are to be expected when traversing\n * the graph in a top-down direction, e.g: from importers to leafs.\n *\n * For different uses that are not a direct top-down traversal of the graph\n * consider using `addNode()` and `addEdge()` instead.\n */\n placePackage(\n fromNode: Node,\n depType: DependencySaveType,\n spec: Spec,\n manifest?: NormalizedManifest,\n id?: DepID,\n extra?: string,\n ): Node | undefined {\n // if no manifest is available, then create an edge that has no\n // reference to any other node, representing a missing dependency\n if (!manifest && !id) {\n this.addEdge(depType, spec, fromNode)\n return\n }\n\n // flags set on the node we're about to create or find.\n const flags = {\n dev: fromNode.dev || depType === 'dev',\n optional:\n fromNode.optional ||\n depType === 'optional' ||\n depType === 'peerOptional',\n }\n\n const depId = id || (manifest && getId(spec, manifest, extra))\n\n /* c8 ignore start - should not be possible */\n if (!depId) {\n throw error('Could not find dep id when placing package', {\n spec,\n manifest,\n })\n }\n /* c8 ignore stop */\n\n // if a node for this package is already represented by a node\n // in the graph, then just creates a new edge to that node\n const toFoundNode = this.nodes.get(depId)\n if (toFoundNode) {\n this.addEdge(depType, spec, fromNode, toFoundNode)\n // the current only stays dev/optional if this dep lets it remain so\n // if it's not already, we don't make it dev or optional.\n toFoundNode.detached = false\n toFoundNode.dev &&= flags.dev\n toFoundNode.optional &&= flags.optional\n return toFoundNode\n }\n\n // creates a new node and edges to its parent\n const toNode = this.addNode(depId, manifest, spec)\n toNode.registry = spec.registry\n toNode.dev = flags.dev\n toNode.optional = flags.optional\n // split extra into modifier and peerSetHash\n if (extra) {\n const { modifier, peerSetHash } = splitExtra(extra)\n toNode.modifier = modifier\n toNode.peerSetHash = peerSetHash\n }\n\n // add extra manifest info if available\n if (manifest) {\n const { bin, engines, os, cpu } = manifest\n // add platform info if available\n if (engines || os || cpu) {\n const platform: NodeLike['platform'] = {}\n if (engines) platform.engines = engines\n if (os) platform.os = os\n if (cpu) platform.cpu = cpu\n toNode.platform = platform\n }\n // add bin info if available\n if (bin) {\n toNode.bins = bin\n }\n }\n toNode.maybeSetConfusedManifest(spec, manifest)\n\n this.addEdge(depType, spec, fromNode, toNode)\n\n // populate resolution cache if applicable\n const f = getResolutionCacheKey(\n spec.final,\n fromNode.location,\n extra || '',\n )\n this.resolutions.set(f, toNode)\n const rrev = this.resolutionsReverse.get(toNode) ?? new Set()\n rrev.add(f)\n this.resolutionsReverse.set(toNode, rrev)\n\n return toNode\n }\n\n /**\n * Removes a node and its relevant edges from the graph.\n *\n * Use the `keepEdges` option to keep the edges that were pointing to\n * this node and only removes their `to` property value.\n *\n * If a replacement is provided, then any edges that were previously\n * pointing to the removed node will be directed to the replacement,\n * if it is valid to do so.\n */\n removeNode(node: Node, replacement?: Node, keepEdges?: boolean) {\n this.nodes.delete(node.id)\n const nbn = this.nodesByName.get(node.name)\n // if it's the last one, just remove the set\n if (nbn?.size === 1) this.nodesByName.delete(node.name)\n else nbn?.delete(node)\n for (const r of this.resolutionsReverse.get(node) ?? new Set()) {\n this.resolutions.delete(r)\n }\n this.resolutionsReverse.delete(node)\n this.manifests.delete(node.id)\n for (const edge of node.edgesOut.values()) {\n this.edges.delete(edge)\n }\n for (const edge of node.edgesIn) {\n if (\n replacement &&\n satisfies(\n replacement.id,\n edge.spec,\n edge.from.location,\n this.projectRoot,\n this.monorepo,\n )\n ) {\n edge.to = replacement\n } else if (keepEdges) {\n edge.to = undefined\n } else {\n edge.from.edgesOut.delete(edge.spec.name)\n this.edges.delete(edge)\n }\n }\n }\n\n /**\n * Removes the resolved node of a given edge.\n */\n removeEdgeResolution(edge: Edge, extra = '') {\n const node = edge.to\n const resolutionKey = getResolutionCacheKey(\n edge.spec,\n edge.from.location,\n extra,\n )\n if (node) {\n edge.to = undefined\n this.resolutions.delete(resolutionKey)\n this.resolutionsReverse.get(node)?.delete(resolutionKey)\n this.nodesByName.delete(node.name)\n node.edgesIn.delete(edge)\n if (node.edgesIn.size === 0) {\n this.nodes.delete(node.id)\n }\n }\n }\n\n /**\n * Remove all edges from the graph while preserving nodes and resolution caches.\n * This allows the graph to be reconstructed efficiently using the existing nodes.\n */\n resetEdges() {\n // Clear the global edges set\n this.edges.clear()\n\n // Clear all node edge relationships\n for (const node of this.nodes.values()) {\n // marking nodes as detached needs to be restricted to only those\n // that had a manifest, otherwise we'd be skipping fetching manifest\n // for nodes we don't have a manifest during the ideal build phase\n if (node.manifest) node.detached = true\n\n // detaches all edges from this node\n node.edgesOut.clear()\n node.edgesIn.clear()\n }\n }\n\n toJSON() {\n return lockfileData({\n ...this.#options,\n graph: this,\n saveManifests: true,\n })\n }\n\n [kCustomInspect](_: number, options: InspectOptions) {\n const data = this.toJSON()\n return `${this[Symbol.toStringTag]} ${inspect(data, options)}`\n }\n}\n"]}
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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","sourcesContent":["import { getId, joinDepIDTuple, splitExtra } from '@vltpkg/dep-id'\nimport type { DepID } from '@vltpkg/dep-id'\nimport { error } from '@vltpkg/error-cause'\nimport { satisfies } from '@vltpkg/satisfies'\nimport { getOptions, Spec } from '@vltpkg/spec'\nimport type { SpecOptions } from '@vltpkg/spec'\nimport type {\n GraphLike,\n NodeLike,\n NormalizedManifest,\n DependencySaveType,\n} from '@vltpkg/types'\nimport type { Monorepo } from '@vltpkg/workspaces'\nimport { inspect } from 'node:util'\nimport type { InspectOptions } from 'node:util'\nimport { lockfileData } from './lockfile/save.ts'\nimport { Edge } from './edge.ts'\nimport { Node } from './node.ts'\nimport type { NodeOptions } from './node.ts'\nimport { resolveSaveType } from './resolve-save-type.ts'\nimport type { PeerContext } from './ideal/types.ts'\n\nconst kCustomInspect = Symbol.for('nodejs.util.inspect.custom')\n\nconst cacheKeySeparator = '│'\n\n// this is always the same, but we don't hard code it as a string,\n// in case the DepID module needs to change its delimiter again ever.\nconst mainDepID = joinDepIDTuple(['file', '.'])\n\nexport type ManifestInventory = Map<DepID, NormalizedManifest>\n\nconst getMap = <T extends Map<any, any>>(m?: T) =>\n m ?? (new Map() as T)\n\n/**\n * Get a cache key for a resolution based on the\n * spec, location and query modifier.\n */\nconst getResolutionCacheKey = (\n spec: Spec,\n location: string,\n extra: string,\n): string => {\n const f = spec.final\n // if it's a file: dep, then the fromNode location matters\n const fromPrefix = f.type === 'file' ? location + ' : ' : ''\n // the unique key should also precise what is the type of the spec,\n // and in the case of a registry, what registry it is from.\n const typePrecisionKey =\n f.registry ?\n `${cacheKeySeparator}registry` +\n `${cacheKeySeparator}${f.registry}`\n : f.gitRemote ?\n `${cacheKeySeparator}git` + `${cacheKeySeparator}${f.gitRemote}`\n : `${cacheKeySeparator}${f.type}`\n const modifierSuffix = `${cacheKeySeparator}${extra}`\n return fromPrefix + String(f) + typePrecisionKey + modifierSuffix\n}\n\nexport type GraphOptions = SpecOptions & {\n /**\n * The main importer manifest info.\n */\n mainManifest: NormalizedManifest\n /**\n * An inventory of seen manifests.\n */\n manifests?: ManifestInventory\n /**\n * A {@link Monorepo} object, for managing workspaces\n */\n monorepo?: Monorepo\n /**\n * Root of the project this graph represents\n */\n projectRoot: string\n}\n\nexport class Graph implements GraphLike {\n get [Symbol.toStringTag]() {\n return '@vltpkg/graph.Graph'\n }\n\n #options: GraphOptions\n\n #nodeOptions: NodeOptions\n\n /**\n * A {@link Monorepo} instance, used for managing workspaces.\n */\n monorepo?: Monorepo\n\n /**\n * An inventory with all manifests related to an install.\n */\n manifests: ManifestInventory\n\n /**\n * A set of all edges in this graph.\n */\n edges = new Set<Edge>()\n\n /**\n * Map registered dep ids to the node that represent them in the graph.\n */\n nodes = new Map<DepID, Node>()\n\n /**\n * Map of nodes by their name\n */\n nodesByName = new Map<string, Set<Node>>()\n\n /**\n * Cached resolutions for spec lookups\n */\n resolutions = new Map<string, Node>()\n\n /**\n * Reverse map of resolutions\n */\n resolutionsReverse = new Map<Node, Set<string>>()\n\n /**\n * A set of importer nodes in this graph.\n */\n importers = new Set<Node>()\n\n /**\n * The {@link Node} that represents the project root `package.json`.\n */\n mainImporter: Node\n\n /**\n * A set of extraneous dependencies found when building the graph.\n */\n extraneousDependencies = new Set<Edge>()\n\n /**\n * The root of the project this graph represents\n */\n projectRoot: string\n\n /**\n * The peer context sets used to resolve peer dependencies within this graph.\n */\n peerContexts: PeerContext[]\n\n /**\n * Cache of forked peer contexts so identical fork operations can reuse\n * previously created contexts instead of duplicating them.\n *\n * Key format is internal and constructed in `ideal/peers.ts`.\n */\n peerContextForkCache = new Map<string, PeerContext>()\n\n /**\n * Tracks the current peer context index.\n */\n currentPeerContextIndex = 0\n\n constructor(options: GraphOptions) {\n const { mainManifest, monorepo } = options\n this.#options = options\n // hydrate spec options to their full contents, including defaults\n const specOptions = getOptions({\n registry: options.registry,\n registries: options.registries,\n 'git-hosts': options['git-hosts'],\n 'git-host-archives': options['git-host-archives'],\n 'scope-registries': options['scope-registries'],\n 'jsr-registries': options['jsr-registries'],\n catalog: options.catalog,\n catalogs: options.catalogs,\n })\n this.manifests = getMap(options.manifests)\n this.projectRoot = options.projectRoot\n this.#nodeOptions = {\n ...this.#options,\n ...specOptions,\n graph: this,\n }\n\n // add the project root node\n const mainImporterLocation = '.'\n const mainImporterSpec = Spec.parse(\n mainManifest.name || '(root)',\n mainImporterLocation,\n )\n const mainImporter = this.addNode(\n mainDepID,\n mainManifest,\n mainImporterSpec,\n )\n mainImporter.setImporterLocation(mainImporterLocation)\n mainImporter.mainImporter = true\n this.mainImporter = mainImporter\n this.mainImporter.workspaces = new Map()\n this.importers.add(mainImporter)\n this.manifests.set(mainImporter.id, mainManifest)\n\n // uses the monorepo instance in order to retrieve info on\n // workspaces and create importer nodes for each of them\n this.monorepo = monorepo\n if (this.monorepo) {\n for (const ws of this.monorepo) {\n const wsNode = this.addNode(\n ws.id,\n ws.manifest,\n undefined,\n ws.name,\n )\n wsNode.setImporterLocation(`./${ws.path}`)\n if (wsNode.manifest) {\n this.manifests.set(wsNode.id, wsNode.manifest)\n // set bins for workspace nodes so they can be linked\n // when another importer depends on this workspace\n /* c8 ignore next 3 - tested by integration tests */\n if (wsNode.manifest.bin) {\n wsNode.bins = wsNode.manifest.bin\n }\n }\n this.importers.add(wsNode)\n // creates a virtual edge to connect the workspaces to the root node\n const edge = new Edge(\n 'prod',\n Spec.parse(wsNode.name, 'workspace:*', this.#options),\n this.mainImporter,\n wsNode,\n )\n this.mainImporter.workspaces.set(wsNode.name, edge)\n }\n }\n\n // initializes the peer context set collection\n const initialPeerContext: PeerContext = new Map()\n initialPeerContext.index = this.currentPeerContextIndex\n this.peerContexts = [initialPeerContext]\n }\n\n /**\n * Get the next peer context index.\n */\n nextPeerContextIndex() {\n return ++this.currentPeerContextIndex\n }\n\n /**\n * Delete all nodes and edges that are unreachable from the importers.\n * The collection of deleted nodes is returned.\n *\n * NOTE: This can be extremely slow for large graphs, and is almost always\n * unnecessary! Only call when it is known that some unreachable nodes may\n * have been created, for example when deleting the unneeded subgraph when an\n * optional node fails to resolve/install.\n */\n gc() {\n const { nodes } = this\n this.edges.clear()\n this.nodes = new Map()\n const marked = new Set(this.importers)\n for (const imp of marked) {\n // don't delete the importer!\n nodes.delete(imp.id)\n this.nodes.set(imp.id, imp)\n for (const edge of imp.edgesOut.values()) {\n this.edges.add(edge)\n const { to } = edge\n if (!to || marked.has(to)) continue\n marked.add(to)\n nodes.delete(to.id)\n this.nodes.set(to.id, to)\n }\n }\n for (const node of nodes.values()) {\n this.removeNode(node)\n }\n return nodes\n }\n\n /**\n * Create a new edge between two nodes of the graph in case both exist,\n * in case the destination node does not exists, then a dangling edge,\n * pointing to nothing will be created to represent that missing dependency.\n */\n addEdge(\n type: DependencySaveType,\n spec: Spec,\n from: NodeLike,\n to?: NodeLike,\n ) {\n // fix any nameless spec\n if (spec.name === '(unknown)') {\n if (to) {\n spec.name = to.name /* c8 ignore next */ || '(unknown)'\n spec.spec = `${to.name}@${spec.bareSpec}`\n } else {\n throw error(\n 'Impossible to place a missing, nameless dependency',\n { spec },\n )\n }\n }\n const existing = from.edgesOut.get(spec.name)\n if (existing) {\n const edge = existing as Edge\n if (\n edge.type === type &&\n edge.spec.bareSpec === spec.bareSpec\n ) {\n if (to && to !== edge.to) {\n // removes this edge from its destination edgesIn ref\n edge.to?.edgesIn.delete(edge)\n // now swap the destination to the new one\n edge.to = to as Node\n edge.to.edgesIn.add(edge)\n }\n return edge\n }\n this.edges.delete(edge)\n }\n const f = from as Node\n const edgeOut = f.addEdgesTo(\n resolveSaveType(from, spec.name, type),\n spec,\n to as Node | undefined,\n )\n this.edges.add(edgeOut)\n return edgeOut\n }\n\n /**\n * Find an existing node to satisfy a dependency\n */\n findResolution(spec: Spec, fromNode: Node, extra = '') {\n const f = spec.final\n const sf = getResolutionCacheKey(f, fromNode.location, extra)\n const cached = this.resolutions.get(sf)\n if (cached) return cached\n const nbn = this.nodesByName.get(f.name)\n if (!nbn) return undefined\n for (const node of nbn) {\n if (\n satisfies(\n node.id,\n f,\n fromNode.location,\n this.projectRoot,\n this.monorepo,\n )\n ) {\n this.resolutions.set(sf, node)\n // always set by now, because the node was added at some point\n this.resolutionsReverse.get(node)?.add(sf)\n return node\n }\n }\n }\n\n /**\n * Create a new node in the graph.\n */\n addNode(\n id?: DepID,\n manifest?: NormalizedManifest,\n spec?: Spec,\n name?: string,\n version?: string,\n ) {\n const node = new Node(\n this.#nodeOptions,\n id,\n manifest,\n spec,\n name,\n version,\n )\n this.nodes.set(node.id, node)\n const nbn = this.nodesByName.get(node.name) ?? new Set()\n nbn.add(node)\n\n // ensure the nodes by name set is always sorted, this will help\n // keeping a deterministic graph resolution when reusing nodes\n const newByNameSet = new Set(\n [...nbn].sort((a, b) => a.id.localeCompare(b.id)),\n )\n this.nodesByName.set(node.name, newByNameSet)\n\n if (manifest) {\n this.manifests.set(node.id, manifest)\n }\n return node\n }\n\n /**\n * Place a new package into the graph representation, creating the new\n * edges and possibly new nodes that are to be expected when traversing\n * the graph in a top-down direction, e.g: from importers to leafs.\n *\n * For different uses that are not a direct top-down traversal of the graph\n * consider using `addNode()` and `addEdge()` instead.\n */\n placePackage(\n fromNode: Node,\n depType: DependencySaveType,\n spec: Spec,\n manifest?: NormalizedManifest,\n id?: DepID,\n extra?: string,\n ): Node | undefined {\n // if no manifest is available, then create an edge that has no\n // reference to any other node, representing a missing dependency\n if (!manifest && !id) {\n this.addEdge(depType, spec, fromNode)\n return\n }\n\n // flags set on the node we're about to create or find.\n const flags = {\n dev: fromNode.dev || depType === 'dev',\n optional:\n fromNode.optional ||\n depType === 'optional' ||\n depType === 'peerOptional',\n }\n\n const depId = id || (manifest && getId(spec, manifest, extra))\n\n /* c8 ignore start - should not be possible */\n if (!depId) {\n throw error('Could not find dep id when placing package', {\n spec,\n manifest,\n })\n }\n /* c8 ignore stop */\n\n // if a node for this package is already represented by a node\n // in the graph, then just creates a new edge to that node\n const toFoundNode = this.nodes.get(depId)\n if (toFoundNode) {\n this.addEdge(depType, spec, fromNode, toFoundNode)\n // the current only stays dev/optional if this dep lets it remain so\n // if it's not already, we don't make it dev or optional.\n toFoundNode.detached = false\n toFoundNode.dev &&= flags.dev\n toFoundNode.optional &&= flags.optional\n return toFoundNode\n }\n\n // creates a new node and edges to its parent\n const toNode = this.addNode(depId, manifest, spec)\n toNode.registry = spec.registry\n toNode.dev = flags.dev\n toNode.optional = flags.optional\n // split extra into modifier and peerSetHash\n if (extra) {\n const { modifier, peerSetHash } = splitExtra(extra)\n toNode.modifier = modifier\n toNode.peerSetHash = peerSetHash\n }\n\n // add extra manifest info if available\n if (manifest) {\n const { bin, engines, os, cpu, libc } = manifest\n // add platform info if available\n if (engines || os || cpu || libc) {\n const platform: NodeLike['platform'] = {}\n if (engines) platform.engines = engines\n if (os) platform.os = os\n if (cpu) platform.cpu = cpu\n if (libc) platform.libc = libc\n toNode.platform = platform\n }\n // add bin info if available\n if (bin) {\n toNode.bins = bin\n }\n }\n toNode.maybeSetConfusedManifest(spec, manifest)\n\n this.addEdge(depType, spec, fromNode, toNode)\n\n // populate resolution cache if applicable\n const f = getResolutionCacheKey(\n spec.final,\n fromNode.location,\n extra || '',\n )\n this.resolutions.set(f, toNode)\n const rrev = this.resolutionsReverse.get(toNode) ?? new Set()\n rrev.add(f)\n this.resolutionsReverse.set(toNode, rrev)\n\n return toNode\n }\n\n /**\n * Removes a node and its relevant edges from the graph.\n *\n * Use the `keepEdges` option to keep the edges that were pointing to\n * this node and only removes their `to` property value.\n *\n * If a replacement is provided, then any edges that were previously\n * pointing to the removed node will be directed to the replacement,\n * if it is valid to do so.\n */\n removeNode(node: Node, replacement?: Node, keepEdges?: boolean) {\n this.nodes.delete(node.id)\n const nbn = this.nodesByName.get(node.name)\n // if it's the last one, just remove the set\n if (nbn?.size === 1) this.nodesByName.delete(node.name)\n else nbn?.delete(node)\n for (const r of this.resolutionsReverse.get(node) ?? new Set()) {\n this.resolutions.delete(r)\n }\n this.resolutionsReverse.delete(node)\n this.manifests.delete(node.id)\n for (const edge of node.edgesOut.values()) {\n this.edges.delete(edge)\n }\n for (const edge of node.edgesIn) {\n if (\n replacement &&\n satisfies(\n replacement.id,\n edge.spec,\n edge.from.location,\n this.projectRoot,\n this.monorepo,\n )\n ) {\n edge.to = replacement\n } else if (keepEdges) {\n edge.to = undefined\n } else {\n edge.from.edgesOut.delete(edge.spec.name)\n this.edges.delete(edge)\n }\n }\n }\n\n /**\n * Removes the resolved node of a given edge.\n */\n removeEdgeResolution(edge: Edge, extra = '') {\n const node = edge.to\n const resolutionKey = getResolutionCacheKey(\n edge.spec,\n edge.from.location,\n extra,\n )\n if (node) {\n edge.to = undefined\n this.resolutions.delete(resolutionKey)\n this.resolutionsReverse.get(node)?.delete(resolutionKey)\n this.nodesByName.delete(node.name)\n node.edgesIn.delete(edge)\n if (node.edgesIn.size === 0) {\n this.nodes.delete(node.id)\n }\n }\n }\n\n /**\n * Remove all edges from the graph while preserving nodes and resolution caches.\n * This allows the graph to be reconstructed efficiently using the existing nodes.\n */\n resetEdges() {\n // Clear the global edges set\n this.edges.clear()\n\n // Clear all node edge relationships\n for (const node of this.nodes.values()) {\n // marking nodes as detached needs to be restricted to only those\n // that had a manifest, otherwise we'd be skipping fetching manifest\n // for nodes we don't have a manifest during the ideal build phase\n if (node.manifest) node.detached = true\n\n // detaches all edges from this node\n node.edgesOut.clear()\n node.edgesIn.clear()\n }\n }\n\n toJSON() {\n return lockfileData({\n ...this.#options,\n graph: this,\n saveManifests: true,\n })\n }\n\n [kCustomInspect](_: number, options: InspectOptions) {\n const data = this.toJSON()\n return `${this[Symbol.toStringTag]} ${inspect(data, options)}`\n }\n}\n"]}
@@ -13,8 +13,20 @@ import type { TransientAddMap, TransientRemoveMap } from './types.ts';
13
13
  * Append new nodes in the given `graph` for dependencies specified at `add`
14
14
  * and missing dependencies from the `deps` parameter.
15
15
  *
16
- * It also applies any modifiers that applies to a given node as it processes
17
- * and builds the graph.
16
+ * Uses **breadth-first traversal** (BFS) with **deterministic ordering** to
17
+ * ensure reproducible builds. The algorithm:
18
+ *
19
+ * 1. Process all deps at the current level in parallel
20
+ * 2. After each level, run `postPlacementPeerCheck` to handle peer contexts
21
+ * 3. Collect child deps for the next level
22
+ * 4. Repeat until no more deps to process
23
+ *
24
+ * **Peer Context Isolation**: Each workspace importer gets its own peer context
25
+ * to prevent cross-workspace leakage. Without this, `react@^18` from workspace A
26
+ * could incorrectly satisfy `react@^19` peer deps in workspace B.
27
+ *
28
+ * **Early Extraction**: When `actual` graph is provided, nodes are extracted
29
+ * to the vlt store during graph construction (not after), improving performance.
18
30
  */
19
31
  export declare const appendNodes: (packageInfo: PackageInfoClient, graph: Graph, fromNode: Node, deps: Dependency[], scurry: PathScurry, options: SpecOptions, seen: Set<DepID>, add?: Map<string, Dependency>, modifiers?: GraphModifier, modifierRefs?: Map<string, ModifierActiveEntry>, extractPromises?: Promise<ExtractResult>[], actual?: Graph, seenExtracted?: Set<DepID>, remover?: RollbackRemove, transientAdd?: TransientAddMap, transientRemove?: TransientRemoveMap) => Promise<void>;
20
32
  //# sourceMappingURL=append-nodes.d.ts.map
@@ -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;AAO/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;AAM7D,OAAO,KAAK,EAIV,eAAe,EACf,kBAAkB,EACnB,MAAM,YAAY,CAAA;AA4enB;;;;;;GAMG;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,kBAyGrC,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;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,12 +1,14 @@
1
1
  import { joinDepIDTuple, joinExtra } from '@vltpkg/dep-id';
2
2
  import { error } from '@vltpkg/error-cause';
3
3
  import { Spec } from '@vltpkg/spec';
4
+ import { satisfies } from '@vltpkg/satisfies';
4
5
  import { longDependencyTypes, normalizeManifest } from '@vltpkg/types';
5
6
  import { fixupAddedNames } from "../fixup-added-names.js";
6
7
  import { shorten } from "../dependencies.js";
7
8
  import { removeOptionalSubgraph } from "../remove-optional-subgraph.js";
8
9
  import { extractNode } from "../reify/extract-node.js";
9
- import { endPeerPlacement, postPlacementPeerCheck, startPeerPlacement, } from "./peers.js";
10
+ import { checkPeerEdgesCompatible, endPeerPlacement, forkPeerContext, postPlacementPeerCheck, startPeerPlacement, } from "./peers.js";
11
+ import { compareByHasPeerDeps } from "./sorting.js";
10
12
  /**
11
13
  * Only install devDeps for git dependencies and importers
12
14
  * Everything else always gets installed
@@ -39,18 +41,67 @@ const getFileTypeInfo = (spec, fromNode, scurry) => {
39
41
  };
40
42
  };
41
43
  const isStringArray = (a) => Array.isArray(a) && !a.some(b => typeof b !== 'string');
44
+ /**
45
+ * Try to find a compatible resolution for a dependency, checking peer context.
46
+ * If the first resolution candidate is incompatible with the peer context,
47
+ * try other candidates.
48
+ */
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);
52
+ let peerCompatResult = existingNode ?
53
+ checkPeerEdgesCompatible(existingNode, fromNode, peerContext, graph)
54
+ : { compatible: true };
55
+ // 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;
73
+ }
74
+ }
75
+ }
76
+ return { existingNode, peerCompatResult };
77
+ };
42
78
  /**
43
79
  * Fetch manifests for dependencies and create placement tasks.
80
+ *
81
+ * This is Phase 1 of the breadth-first graph building process. For each
82
+ * dependency at the current level:
83
+ * 1. Apply any active modifiers (spec swapping)
84
+ * 2. Try to find an existing node to reuse (with peer compatibility check)
85
+ * 3. If no reusable node, start a manifest fetch (in parallel)
86
+ * 4. Create placement tasks for Phase 2
87
+ *
88
+ * The result is sorted to process non-peer-dependent packages first,
89
+ * ensuring peer dependencies can resolve to already-placed siblings.
90
+ *
91
+ * **Read-only**: This function no longer mutates the graph. It returns
92
+ * tasks that will be applied serially in the BFS loop for deterministic ordering.
44
93
  */
45
94
  const fetchManifestsForDeps = async (packageInfo, graph, fromNode, deps, scurry, peerContext, modifierRefs, depth = 0) => {
46
- // Create fetch tasks for all dependencies at this level
47
95
  const fetchTasks = [];
48
96
  const placementTasks = [];
97
+ const reuseTasks = [];
98
+ const forkRequests = [];
49
99
  for (const { spec: originalSpec, type } of deps) {
50
100
  let spec = originalSpec;
51
101
  const fileTypeInfo = getFileTypeInfo(spec, fromNode, scurry);
52
102
  const activeModifier = modifierRefs?.get(spec.name);
53
- // here is the place we swap specs if a edge modifier was defined
103
+ // MODIFIER HANDLING: Swap spec if an edge modifier is fully matched
104
+ // Example: `vlt install --override "react:^19"` changes react's spec
54
105
  const queryModifier = activeModifier?.modifier.query;
55
106
  const completeModifier = activeModifier &&
56
107
  activeModifier.interactiveBreadcrumb.current ===
@@ -59,28 +110,40 @@ const fetchManifestsForDeps = async (packageInfo, graph, fromNode, deps, scurry,
59
110
  completeModifier &&
60
111
  'spec' in activeModifier.modifier) {
61
112
  spec = activeModifier.modifier.spec;
113
+ // bareSpec of '-' means "remove this dependency"
62
114
  if (spec.bareSpec === '-') {
63
115
  continue;
64
116
  }
65
117
  }
66
118
  const peer = type === 'peer' || type === 'peerOptional';
67
- // skip reusing nodes for peer deps since their reusability
68
- // is handled ahead-of-time during its parent's placement
69
- const existingNode = graph.findResolution(spec, fromNode, queryModifier);
119
+ // NODE REUSE LOGIC with peer compatibility
120
+ const { existingNode, peerCompatResult } = findCompatibleResolution(spec, fromNode, graph, peerContext, queryModifier, peer);
121
+ // Accumulate fork request if incompatible peer edges detected (defer actual fork)
122
+ const effectivePeerContext = peerContext;
123
+ /* c8 ignore start */
124
+ if (!peerCompatResult.compatible && peerCompatResult.forkEntry) {
125
+ forkRequests.push(peerCompatResult.forkEntry);
126
+ // All fork entries from this fromNode will be applied together in Phase B
127
+ }
128
+ /* c8 ignore stop */
70
129
  // defines what nodes are eligible to be reused
71
130
  const validExistingNode = existingNode &&
72
131
  !existingNode.detached &&
73
- // Regular deps can always reuse
132
+ // Regular deps can always reuse.
133
+ // Peer deps can reuse as well if their peer edges are compatible.
74
134
  /* c8 ignore start */
75
- (!peer ||
76
- // otherwise reusing peer deps only in case of a peerSetHash matche
77
- existingNode.peerSetHash === fromNode.peerSetHash);
135
+ (!peer || peerCompatResult.compatible) &&
136
+ // Check if existing node's peer edges are compatible with new parent
137
+ peerCompatResult.compatible;
78
138
  /* c8 ignore stop */
79
139
  if (validExistingNode ||
80
- // importers are handled at the ./add-nodes.ts top-level
140
+ // importers are handled at the ./refresh-ideal-graph.ts top-level
81
141
  // so we should just skip whenever we find one
82
142
  existingNode?.importer) {
83
- graph.addEdge(type, spec, fromNode, existingNode);
143
+ // Defer edge creation to Phase B for deterministic ordering.
144
+ // Previously added immediately, but this caused race conditions when
145
+ // parallel fetches completed in different orders.
146
+ reuseTasks.push({ type, spec, fromNode, toNode: existingNode });
84
147
  continue;
85
148
  }
86
149
  // is the current edge pointint go an optional dependency?
@@ -114,7 +177,7 @@ const fetchManifestsForDeps = async (packageInfo, graph, fromNode, deps, scurry,
114
177
  edgeOptional,
115
178
  manifestPromise,
116
179
  depth,
117
- peerContext,
180
+ peerContext: effectivePeerContext,
118
181
  };
119
182
  fetchTasks.push(fetchTask);
120
183
  }
@@ -130,34 +193,30 @@ const fetchManifestsForDeps = async (packageInfo, graph, fromNode, deps, scurry,
130
193
  // so that peer dependencies can easily reuse already placed regular
131
194
  // dependencies as part of peer context set resolution also makes sure to
132
195
  // sort by the manifest name for deterministic order.
133
- placementTasks.sort((a, b) => {
134
- const aIsPeer = (a.manifest?.peerDependencies &&
135
- Object.keys(a.manifest.peerDependencies).length > 0) ?
136
- 1
137
- : 0;
138
- const bIsPeer = (b.manifest?.peerDependencies &&
139
- Object.keys(b.manifest.peerDependencies).length > 0) ?
140
- 1
141
- : 0;
142
- // regular dependencies first, peer dependencies last
143
- if (aIsPeer !== bIsPeer) {
144
- return aIsPeer - bIsPeer;
145
- }
146
- // if both are in the same group,
147
- // sort alphabetically by manifest name (fallback to spec.name)
148
- const aName = a.manifest?.name /* c8 ignore next */ || a.fetchTask.spec.name;
149
- const bName = b.manifest?.name || b.fetchTask.spec.name;
150
- return aName.localeCompare(bName, 'en');
151
- });
152
- return placementTasks;
196
+ placementTasks.sort(compareByHasPeerDeps);
197
+ return { placementTasks, reuseTasks, forkRequests };
153
198
  };
154
199
  /**
155
- * Process placement tasks and collect child dependencies, this is the
156
- * second step of the appendNodes operation after manifest fetching in
157
- * which the final graph data structure is actually built.
200
+ * Process placement tasks and collect child dependencies.
201
+ *
202
+ * This is Phase 2 of the breadth-first graph building process. For each
203
+ * resolved manifest:
204
+ * 1. Handle missing manifests (optional vs required deps)
205
+ * 2. Start peer placement process (collect sibling context)
206
+ * 3. Place the node in the graph with appropriate flags
207
+ * 4. Trigger early extraction if eligible (performance optimization)
208
+ * 5. Collect child dependencies for the next BFS level
209
+ * 6. End peer placement (setup context update functions)
210
+ *
211
+ * Early extraction: When `actual` graph is provided, nodes destined for the
212
+ * vlt store are extracted immediately (in parallel) instead of waiting for
213
+ * the full ideal graph to be built. This significantly improves install time.
158
214
  */
159
215
  const processPlacementTasks = async (graph, options, placementTasks, add, modifiers, scurry, packageInfo, extractPromises, actual, seenExtracted, remover, transientAdd, transientRemove) => {
160
216
  const childDepsToProcess = [];
217
+ // Note: placementTasks are already sorted by fetchManifestsForDeps
218
+ // using compareByHasPeerDeps to ensure non-peer deps are processed first.
219
+ // We don't sort again here to preserve that ordering.
161
220
  for (const placementTask of placementTasks) {
162
221
  const { fetchTask, manifest } = placementTask;
163
222
  let { activeModifier, edgeOptional, fileTypeInfo, fromNode, peerContext, queryModifier, spec, type, } = fetchTask;
@@ -326,22 +385,43 @@ const processPlacementTasks = async (graph, options, placementTasks, add, modifi
326
385
  * Append new nodes in the given `graph` for dependencies specified at `add`
327
386
  * and missing dependencies from the `deps` parameter.
328
387
  *
329
- * It also applies any modifiers that applies to a given node as it processes
330
- * and builds the graph.
388
+ * Uses **breadth-first traversal** (BFS) with **deterministic ordering** to
389
+ * ensure reproducible builds. The algorithm:
390
+ *
391
+ * 1. Process all deps at the current level in parallel
392
+ * 2. After each level, run `postPlacementPeerCheck` to handle peer contexts
393
+ * 3. Collect child deps for the next level
394
+ * 4. Repeat until no more deps to process
395
+ *
396
+ * **Peer Context Isolation**: Each workspace importer gets its own peer context
397
+ * to prevent cross-workspace leakage. Without this, `react@^18` from workspace A
398
+ * could incorrectly satisfy `react@^19` peer deps in workspace B.
399
+ *
400
+ * **Early Extraction**: When `actual` graph is provided, nodes are extracted
401
+ * to the vlt store during graph construction (not after), improving performance.
331
402
  */
332
403
  export const appendNodes = async (packageInfo, graph, fromNode, deps, scurry, options, seen, add, modifiers, modifierRefs, extractPromises, actual, seenExtracted, remover, transientAdd, transientRemove) => {
404
+ // Cycle detection: skip if already processed
333
405
  /* c8 ignore next */
334
406
  if (seen.has(fromNode.id))
335
407
  return;
336
408
  seen.add(fromNode.id);
337
- // Get the initial peer context from the graph
338
- const [initialPeerContext] = graph.peerContexts;
409
+ // PEER CONTEXT ISOLATION: Each workspace importer needs its own context
410
+ // to prevent peer targets from one workspace affecting another.
411
+ // The main importer (index 0) uses the initial context; others get fresh ones.
412
+ let initialPeerContext = graph.peerContexts[0];
339
413
  /* c8 ignore start - impossible */
340
- if (!initialPeerContext) {
414
+ if (!initialPeerContext)
341
415
  throw error('no initial peer context found in graph');
342
- }
343
416
  /* c8 ignore stop */
344
- // Use a queue for breadth-first processing
417
+ if (fromNode.importer && fromNode !== graph.mainImporter) {
418
+ // Create isolated peer context for this workspace importer
419
+ const nextPeerContext = new Map();
420
+ nextPeerContext.index = graph.nextPeerContextIndex();
421
+ graph.peerContexts[nextPeerContext.index] = nextPeerContext;
422
+ initialPeerContext = nextPeerContext;
423
+ }
424
+ // BFS queue: process deps level by level for deterministic builds
345
425
  let currentLevelDeps = [
346
426
  {
347
427
  node: fromNode,
@@ -357,27 +437,78 @@ export const appendNodes = async (packageInfo, graph, fromNode, deps, scurry, op
357
437
  /* c8 ignore stop */
358
438
  },
359
439
  ];
440
+ // BFS MAIN LOOP: Process level by level until no more deps
360
441
  while (currentLevelDeps.length > 0) {
361
442
  const nextLevelDeps = [];
362
- // Process all nodes at the current level in parallel
363
- const levelResults = await Promise.all(currentLevelDeps.map(async ({ node, deps: nodeDeps, modifierRefs: nodeModifierRefs, peerContext, depth, }) => {
364
- // Mark node as seen when we start processing its dependencies
443
+ // ============================================================
444
+ // PHASE A: PARALLEL FETCH (READ-ONLY)
445
+ // ============================================================
446
+ // Fetch all manifests at this level in parallel without mutating the graph.
447
+ // This phase is read-only to avoid race conditions from network timing.
448
+ const fetchResults = await Promise.all(currentLevelDeps.map(async ({ node, deps: nodeDeps, modifierRefs: nodeModifierRefs, peerContext, depth, }) => {
449
+ // Cycle prevention: mark as seen when starting to process
365
450
  seen.add(node.id);
366
- // Fetch manifests for this node's dependencies
367
- const placementTasks = await fetchManifestsForDeps(packageInfo, graph, node,
368
- // Sort dependencies by spec.name for deterministic ordering
451
+ // Fetch manifests and collect tasks (no graph mutations)
452
+ const result = await fetchManifestsForDeps(packageInfo, graph, node,
453
+ // Sort by name for deterministic ordering (reproducible builds)
369
454
  nodeDeps.sort((a, b) => a.spec.name.localeCompare(b.spec.name, 'en')), scurry, peerContext, nodeModifierRefs, depth);
370
- // Process the placement tasks and get child dependencies
371
- return await processPlacementTasks(graph, options, placementTasks, add, modifiers, scurry, packageInfo, extractPromises, actual, seenExtracted, remover, transientAdd, transientRemove);
455
+ return {
456
+ entry: {
457
+ node,
458
+ deps: nodeDeps,
459
+ modifierRefs: nodeModifierRefs,
460
+ peerContext,
461
+ depth,
462
+ },
463
+ result,
464
+ };
372
465
  }));
373
- // Traverse the queued up children dependencies, adding and tracking
374
- // dependencies on the peer context set, forking the context as needed
375
- // and resolving any peer dependency that is able to be resolved using
376
- // the current peer context set
466
+ // ============================================================
467
+ // PHASE B: SERIAL MUTATIONS (DETERMINISTIC ORDER)
468
+ // ============================================================
469
+ // Sort results by stable identifiers to ensure deterministic ordering
470
+ // regardless of which manifest fetch completed first
471
+ const sortedResults = fetchResults.sort((a, b) => {
472
+ // Sort by node ID (DepID-based, stable) and depth
473
+ const keyA = `${a.entry.node.id}::${a.entry.depth}`;
474
+ const keyB = `${b.entry.node.id}::${b.entry.depth}`;
475
+ return keyA.localeCompare(keyB, 'en');
476
+ });
477
+ // Apply all mutations serially in deterministic order
478
+ const levelResults = [];
479
+ for (const { entry, result } of sortedResults) {
480
+ // Apply accumulated fork requests if any (from Phase A deferred forks)
481
+ if (result.forkRequests.length > 0) {
482
+ const forkedContext = forkPeerContext(graph, entry.peerContext, result.forkRequests);
483
+ entry.peerContext = forkedContext;
484
+ // Update peer context in all placement tasks to use forked context
485
+ for (const task of result.placementTasks) {
486
+ task.fetchTask.peerContext = forkedContext;
487
+ }
488
+ }
489
+ // Apply reuse edges in deterministic order (before placement)
490
+ // Sort reuse tasks by spec name for stability
491
+ const sortedReuseTasks = result.reuseTasks.sort((a, b) => a.spec.name.localeCompare(b.spec.name, 'en'));
492
+ for (const { type, spec, fromNode, toNode, } of sortedReuseTasks) {
493
+ graph.addEdge(type, spec, fromNode, toNode);
494
+ }
495
+ // Place nodes and collect child deps
496
+ const placed = await processPlacementTasks(graph, options, result.placementTasks, add, modifiers, scurry, packageInfo, extractPromises, actual, seenExtracted, remover, transientAdd, transientRemove);
497
+ levelResults.push(placed);
498
+ }
499
+ // ============================================================
500
+ // PHASE C: POST-PLACEMENT PEER CHECK
501
+ // ============================================================
502
+ // After all nodes at this level are placed, update peer contexts,
503
+ // fork as needed, and resolve peer deps that can be satisfied.
504
+ // This must happen AFTER placement so sibling nodes are available.
377
505
  postPlacementPeerCheck(graph, levelResults);
378
- // Collect all child dependencies for the next level
506
+ // ============================================================
507
+ // STEP 3: COLLECT CHILD DEPS FOR NEXT LEVEL
508
+ // ============================================================
379
509
  for (const childDepsToProcess of levelResults) {
380
510
  for (const childDep of childDepsToProcess) {
511
+ // Skip already-seen nodes (cycle prevention)
381
512
  if (!seen.has(childDep.node.id)) {
382
513
  /* c8 ignore next */
383
514
  const currentDepth = currentLevelDeps[0]?.depth ?? 0;
@@ -388,7 +519,7 @@ export const appendNodes = async (packageInfo, graph, fromNode, deps, scurry, op
388
519
  }
389
520
  }
390
521
  }
391
- // Move to the next level
522
+ // Advance to next BFS level
392
523
  currentLevelDeps = nextLevelDeps;
393
524
  }
394
525
  };