@vltpkg/graph 1.0.0-rc.22 → 1.0.0-rc.24

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 (109) hide show
  1. package/dist/actual/load.d.ts +107 -0
  2. package/dist/actual/load.js +336 -0
  3. package/dist/browser.d.ts +14 -0
  4. package/dist/browser.js +16 -0
  5. package/dist/build.d.ts +28 -0
  6. package/dist/build.js +78 -0
  7. package/dist/dependencies.d.ts +65 -0
  8. package/dist/dependencies.js +111 -0
  9. package/dist/diff.d.ts +119 -0
  10. package/dist/diff.js +151 -0
  11. package/dist/edge.d.ts +46 -0
  12. package/dist/edge.js +77 -0
  13. package/dist/fixup-added-names.d.ts +18 -0
  14. package/dist/fixup-added-names.js +46 -0
  15. package/dist/graph.d.ts +153 -0
  16. package/dist/graph.js +444 -0
  17. package/dist/ideal/append-nodes.d.ts +31 -0
  18. package/dist/ideal/append-nodes.js +560 -0
  19. package/dist/ideal/build-ideal-from-starting-graph.d.ts +14 -0
  20. package/dist/ideal/build-ideal-from-starting-graph.js +69 -0
  21. package/dist/ideal/build.d.ts +40 -0
  22. package/dist/ideal/build.js +84 -0
  23. package/dist/ideal/get-importer-specs.d.ts +20 -0
  24. package/dist/ideal/get-importer-specs.js +180 -0
  25. package/dist/ideal/peers.d.ts +160 -0
  26. package/dist/ideal/peers.js +696 -0
  27. package/dist/ideal/refresh-ideal-graph.d.ts +43 -0
  28. package/dist/ideal/refresh-ideal-graph.js +62 -0
  29. package/dist/ideal/remove-satisfied-specs.d.ts +7 -0
  30. package/dist/ideal/remove-satisfied-specs.js +34 -0
  31. package/dist/ideal/sorting.d.ts +45 -0
  32. package/dist/ideal/sorting.js +70 -0
  33. package/dist/ideal/types.d.ts +107 -0
  34. package/dist/ideal/types.js +1 -0
  35. package/dist/index.d.ts +38 -0
  36. package/dist/index.js +32 -0
  37. package/dist/install.d.ts +19 -0
  38. package/dist/install.js +208 -0
  39. package/dist/lockfile/load-edges.d.ts +11 -0
  40. package/dist/lockfile/load-edges.js +105 -0
  41. package/dist/lockfile/load-nodes.d.ts +4 -0
  42. package/dist/lockfile/load-nodes.js +101 -0
  43. package/dist/lockfile/load.d.ts +45 -0
  44. package/dist/lockfile/load.js +84 -0
  45. package/dist/lockfile/save.d.ts +30 -0
  46. package/dist/lockfile/save.js +174 -0
  47. package/dist/lockfile/types.d.ts +95 -0
  48. package/dist/lockfile/types.js +49 -0
  49. package/dist/modifiers.d.ts +188 -0
  50. package/dist/modifiers.js +329 -0
  51. package/dist/node.d.ts +234 -0
  52. package/dist/node.js +388 -0
  53. package/dist/non-empty-list.d.ts +2 -0
  54. package/dist/non-empty-list.js +2 -0
  55. package/dist/reify/add-edge.d.ts +9 -0
  56. package/dist/reify/add-edge.js +71 -0
  57. package/dist/reify/add-edges.d.ts +4 -0
  58. package/dist/reify/add-edges.js +12 -0
  59. package/dist/reify/add-nodes.d.ts +6 -0
  60. package/dist/reify/add-nodes.js +16 -0
  61. package/dist/reify/bin-chmod.d.ts +10 -0
  62. package/dist/reify/bin-chmod.js +38 -0
  63. package/dist/reify/build.d.ts +13 -0
  64. package/dist/reify/build.js +111 -0
  65. package/dist/reify/calculate-save-value.d.ts +2 -0
  66. package/dist/reify/calculate-save-value.js +50 -0
  67. package/dist/reify/check-needed-build.d.ts +34 -0
  68. package/dist/reify/check-needed-build.js +71 -0
  69. package/dist/reify/delete-edge.d.ts +4 -0
  70. package/dist/reify/delete-edge.js +27 -0
  71. package/dist/reify/delete-edges.d.ts +4 -0
  72. package/dist/reify/delete-edges.js +13 -0
  73. package/dist/reify/delete-nodes.d.ts +4 -0
  74. package/dist/reify/delete-nodes.js +15 -0
  75. package/dist/reify/extract-node.d.ts +23 -0
  76. package/dist/reify/extract-node.js +83 -0
  77. package/dist/reify/index.d.ts +34 -0
  78. package/dist/reify/index.js +161 -0
  79. package/dist/reify/internal-hoist.d.ts +8 -0
  80. package/dist/reify/internal-hoist.js +133 -0
  81. package/dist/reify/optional-fail.d.ts +15 -0
  82. package/dist/reify/optional-fail.js +15 -0
  83. package/dist/reify/rollback.d.ts +4 -0
  84. package/dist/reify/rollback.js +23 -0
  85. package/dist/reify/update-importers-package-json.d.ts +35 -0
  86. package/dist/reify/update-importers-package-json.js +122 -0
  87. package/dist/remove-optional-subgraph.d.ts +33 -0
  88. package/dist/remove-optional-subgraph.js +47 -0
  89. package/dist/resolve-save-type.d.ts +5 -0
  90. package/dist/resolve-save-type.js +4 -0
  91. package/dist/stringify-node.d.ts +2 -0
  92. package/dist/stringify-node.js +32 -0
  93. package/dist/transfer-data/load.d.ts +43 -0
  94. package/dist/transfer-data/load.js +175 -0
  95. package/dist/uninstall.d.ts +14 -0
  96. package/dist/uninstall.js +75 -0
  97. package/dist/update.d.ts +12 -0
  98. package/dist/update.js +73 -0
  99. package/dist/virtual-root.d.ts +15 -0
  100. package/dist/virtual-root.js +78 -0
  101. package/dist/visualization/human-readable-output.d.ts +26 -0
  102. package/dist/visualization/human-readable-output.js +163 -0
  103. package/dist/visualization/json-output.d.ts +41 -0
  104. package/dist/visualization/json-output.js +50 -0
  105. package/dist/visualization/mermaid-output.d.ts +17 -0
  106. package/dist/visualization/mermaid-output.js +170 -0
  107. package/dist/visualization/object-like-output.d.ts +2 -0
  108. package/dist/visualization/object-like-output.js +47 -0
  109. package/package.json +25 -25
@@ -0,0 +1,40 @@
1
+ import type { PackageInfoClient } from '@vltpkg/package-info';
2
+ import type { LoadOptions as LoadActualOptions } from '../actual/load.ts';
3
+ import type { AddImportersDependenciesMap, RemoveImportersDependenciesMap } from '../dependencies.ts';
4
+ import type { Graph } from '../graph.ts';
5
+ import type { RollbackRemove } from '@vltpkg/rollback-remove';
6
+ export type BuildIdealOptions = LoadActualOptions & {
7
+ /**
8
+ * An actual graph
9
+ */
10
+ actual?: Graph;
11
+ /**
12
+ * A `Map` in which keys are {@link DepID} linking to another `Map` in which
13
+ * keys are the dependency names and values are {@link Dependency}. This
14
+ * structure represents dependencies that need to be added to the importer
15
+ * represented by {@link DepID}.
16
+ */
17
+ add?: AddImportersDependenciesMap;
18
+ /**
19
+ * A `Map` object representing nodes to be removed from the ideal graph.
20
+ * Each {@link DepID} key represents an importer node and the `Set` of
21
+ * dependency names to be removed from its dependency list.
22
+ */
23
+ remove?: RemoveImportersDependenciesMap;
24
+ /**
25
+ * A {@link RollbackRemove} instance to handle extraction rollbacks
26
+ */
27
+ remover: RollbackRemove;
28
+ /**
29
+ * A {@link PackageInfoClient} instance to read manifest info from.
30
+ */
31
+ packageInfo: PackageInfoClient;
32
+ };
33
+ /**
34
+ * Builds an ideal {@link Graph} representing the dependencies that
35
+ * should be present in order to fulfill the requirements defined
36
+ * by the `package.json` and `vlt-lock.json` files using either the
37
+ * virtual or actual graph as a starting point. Also add / remove any
38
+ * dependencies listed in the `add` and `remove` properties.
39
+ */
40
+ export declare const build: (options: BuildIdealOptions) => Promise<Graph>;
@@ -0,0 +1,84 @@
1
+ import { error } from '@vltpkg/error-cause';
2
+ import { graphStep } from '@vltpkg/output';
3
+ import { load as loadActual } from "../actual/load.js";
4
+ import { load as loadVirtual } from "../lockfile/load.js";
5
+ import { buildIdealFromStartingGraph } from "./build-ideal-from-starting-graph.js";
6
+ import { splitDepID } from '@vltpkg/dep-id';
7
+ const getMap = (m) => m ?? new Map();
8
+ /**
9
+ * Validates that a file dependency node exists in the graph after
10
+ * a successful graph build. This helps providing an actionable error
11
+ * message in case the current working directory is a linked nested
12
+ * folder that hasn't yet been added as a dependency to an importer
13
+ * in the project.
14
+ */
15
+ const validateFileDepNode = (graph, id) => {
16
+ const [type, path] = splitDepID(id);
17
+ if (type === 'file' && !graph.nodes.get(id)) {
18
+ throw error('The current working dir is not a dependency of this project', { path });
19
+ }
20
+ };
21
+ /**
22
+ * Builds an ideal {@link Graph} representing the dependencies that
23
+ * should be present in order to fulfill the requirements defined
24
+ * by the `package.json` and `vlt-lock.json` files using either the
25
+ * virtual or actual graph as a starting point. Also add / remove any
26
+ * dependencies listed in the `add` and `remove` properties.
27
+ */
28
+ export const build = async (options) => {
29
+ const done = graphStep('build');
30
+ // Creates the shared instances that are going to be used
31
+ // in both the loader methods and the build graph
32
+ const { packageInfo, packageJson, scurry, monorepo } = options;
33
+ const mainManifest = options.mainManifest ?? packageJson.read(options.projectRoot);
34
+ let graph;
35
+ try {
36
+ graph = loadVirtual({
37
+ ...options,
38
+ mainManifest,
39
+ monorepo,
40
+ });
41
+ }
42
+ catch (err) {
43
+ // Check if this is a lockfile version mismatch
44
+ const cause = err.cause;
45
+ if (cause?.code === 'ELOCKFILEVERSION') {
46
+ // If lockfile is from a different vlt version, hard fail
47
+ if (typeof cause.found === 'number' &&
48
+ typeof cause.wanted === 'number') {
49
+ throw err;
50
+ }
51
+ // TODO: add warning to CLI layer via @vltpkg/output when available
52
+ }
53
+ graph = loadActual({
54
+ ...options,
55
+ mainManifest,
56
+ monorepo,
57
+ });
58
+ }
59
+ const res = await buildIdealFromStartingGraph({
60
+ ...options,
61
+ scurry,
62
+ add: getMap(options.add),
63
+ graph,
64
+ packageInfo,
65
+ remove: getMap(options.remove),
66
+ actual: options.actual,
67
+ });
68
+ done();
69
+ // when adding or removing a new dependency from a file dep,
70
+ // validate the receiver node was present in the graph
71
+ if (options.add) {
72
+ for (const [addKey, value] of options.add.entries()) {
73
+ if (value.size)
74
+ validateFileDepNode(res, addKey);
75
+ }
76
+ }
77
+ if (options.remove) {
78
+ for (const [removeKey, value] of options.remove.entries()) {
79
+ if (value.size)
80
+ validateFileDepNode(res, removeKey);
81
+ }
82
+ }
83
+ return res;
84
+ };
@@ -0,0 +1,20 @@
1
+ import type { AddImportersDependenciesMap, RemoveImportersDependenciesMap } from '../dependencies.ts';
2
+ import type { BuildIdealAddOptions, BuildIdealFromGraphOptions, BuildIdealRemoveOptions, TransientAddMap, TransientRemoveMap } from './types.ts';
3
+ import type { SpecOptions } from '@vltpkg/spec';
4
+ import type { PackageJson } from '@vltpkg/package-json';
5
+ import type { PathScurry } from 'path-scurry';
6
+ export type GetImporterSpecsOptions = BuildIdealAddOptions & BuildIdealFromGraphOptions & BuildIdealRemoveOptions & SpecOptions & {
7
+ scurry: PathScurry;
8
+ packageJson: PackageJson;
9
+ };
10
+ /**
11
+ * Given a {@link Graph} and a list of {@link Dependency}, merges the
12
+ * dependencies info found in the graph importers and returns the add & remove
13
+ * results as a Map in which keys are {@link DepID} of each importer node.
14
+ */
15
+ export declare const getImporterSpecs: (options: GetImporterSpecsOptions) => {
16
+ add: AddImportersDependenciesMap;
17
+ remove: RemoveImportersDependenciesMap;
18
+ transientAdd: TransientAddMap;
19
+ transientRemove: TransientRemoveMap;
20
+ };
@@ -0,0 +1,180 @@
1
+ import { longDependencyTypes } from '@vltpkg/types';
2
+ import { shorten, asDependency } from "../dependencies.js";
3
+ import { removeSatisfiedSpecs } from "./remove-satisfied-specs.js";
4
+ import { Spec } from '@vltpkg/spec';
5
+ const hasDepName = (importer, edge) => {
6
+ for (const depType of longDependencyTypes) {
7
+ const listedDeps = importer.manifest?.[depType];
8
+ if (listedDeps && Object.hasOwn(listedDeps, edge.name))
9
+ return true;
10
+ }
11
+ return false;
12
+ };
13
+ class AddImportersDependenciesMapImpl extends Map {
14
+ modifiedDependencies = false;
15
+ }
16
+ class RemoveImportersDependenciesMapImpl extends Map {
17
+ modifiedDependencies = false;
18
+ }
19
+ /**
20
+ * Given a {@link Graph} and a list of {@link Dependency}, merges the
21
+ * dependencies info found in the graph importers and returns the add & remove
22
+ * results as a Map in which keys are {@link DepID} of each importer node.
23
+ */
24
+ export const getImporterSpecs = (options) => {
25
+ const { add, graph, remove } = options;
26
+ const addResult = new AddImportersDependenciesMapImpl();
27
+ const removeResult = new RemoveImportersDependenciesMapImpl();
28
+ // traverse the list of importers in the starting graph
29
+ for (const importer of graph.importers) {
30
+ // uses a Map keying to the spec.name in order to easily make sure there's
31
+ // only a single dependency entry for a given dependency for each importer
32
+ const addDeps = new Map();
33
+ const removeDeps = new Set();
34
+ // if an edge from the graph is not listed in the manifest,
35
+ // add that edge to the list of dependencies to be removed
36
+ for (const edge of importer.edgesOut.values()) {
37
+ if (!hasDepName(importer, edge) &&
38
+ !add.get(importer.id)?.has(edge.name)) {
39
+ removeDeps.add(edge.name);
40
+ removeResult.modifiedDependencies = true;
41
+ }
42
+ }
43
+ // if a dependency is listed in the manifest but not in the graph,
44
+ // add that dependency to the list of dependencies to be added
45
+ for (const depType of longDependencyTypes) {
46
+ const deps = Object.entries(importer.manifest?.[depType] ?? {});
47
+ for (const [depName, depSpec] of deps) {
48
+ const edge = importer.edgesOut.get(depName);
49
+ // skip if the edge exists and already uses the same spec
50
+ if (edge?.to && depSpec === edge.spec.bareSpec)
51
+ continue;
52
+ const dependency = asDependency({
53
+ spec: Spec.parse(depName, depSpec, options),
54
+ type: shorten(depType, depName, importer.manifest),
55
+ });
56
+ addDeps.set(depName, dependency);
57
+ }
58
+ }
59
+ addResult.set(importer.id, addDeps);
60
+ removeResult.set(importer.id, removeDeps);
61
+ }
62
+ // Maps to store dependencies targeting non-importer nodes (e.g., nested folders)
63
+ // These will be injected when the target node is placed in the graph
64
+ const transientAdd = new Map();
65
+ const transientRemove = new Map();
66
+ // Traverse all nodes in the graph to find file type dependencies that are directories
67
+ // and populate transientAdd/transientRemove with their manifest dependencies
68
+ // Only process when scurry and packageJson are available
69
+ for (const node of graph.nodes.values()) {
70
+ // Skip importers as they're already handled above and also skip
71
+ // any non-file type dependencies
72
+ if (graph.importers.has(node) || !node.id.startsWith('file'))
73
+ continue;
74
+ // check if this is a file type dependency that is a directory
75
+ const nodePath = options.scurry.cwd.resolve(node.location);
76
+ const stat = nodePath.lstatSync();
77
+ if (stat?.isDirectory()) {
78
+ // load the manifest for this directory (throw if it does not exist)
79
+ const manifest = options.packageJson.read(nodePath.fullpath());
80
+ // should always set the manifest to the read manifest
81
+ node.manifest = manifest;
82
+ // create a map of dependencies from the manifest
83
+ const addDeps = new Map();
84
+ // check for edges not in manifest (should be removed)
85
+ const removeDeps = new Set();
86
+ for (const edge of node.edgesOut.values()) {
87
+ if (!hasDepName(node, edge) &&
88
+ !add.get(node.id)?.has(edge.name)) {
89
+ removeDeps.add(edge.name);
90
+ }
91
+ }
92
+ // iterate over manifest dependencies to add them if
93
+ // they're missing from the graph
94
+ for (const depType of longDependencyTypes) {
95
+ const deps = Object.entries(manifest[depType] ?? {});
96
+ for (const [depName, depSpec] of deps) {
97
+ const edge = node.edgesOut.get(depName);
98
+ // skip if the edge exists and already uses the same spec
99
+ if (edge?.to && depSpec === edge.spec.bareSpec)
100
+ continue;
101
+ // add the dependency to the addDeps map
102
+ const dependency = asDependency({
103
+ spec: Spec.parse(depName, depSpec, options),
104
+ type: shorten(depType, depName, manifest),
105
+ });
106
+ addDeps.set(depName, dependency);
107
+ }
108
+ }
109
+ // store in transientAdd if there are any dependencies
110
+ if (addDeps.size > 0) {
111
+ transientAdd.set(node.id, addDeps);
112
+ }
113
+ // store in transientRemove if there are any to remove
114
+ if (removeDeps.size > 0) {
115
+ transientRemove.set(node.id, removeDeps);
116
+ }
117
+ }
118
+ }
119
+ // merges any provided specs to add to the current found results
120
+ for (const [id, addDeps] of add.entries()) {
121
+ const deps = addResult.get(id);
122
+ if (!deps) {
123
+ // Not an importer - only store file-type deps for later injection
124
+ if (id.startsWith('file')) {
125
+ transientAdd.set(id, addDeps);
126
+ }
127
+ continue;
128
+ }
129
+ for (const [name, dep] of addDeps.entries()) {
130
+ deps.set(name, dep);
131
+ }
132
+ }
133
+ // Merges results from user-provided `remove` option with any remove
134
+ // results found from comparing the manifest with the loaded graph
135
+ for (const [key, removeSet] of remove) {
136
+ const importerRemoveItem = removeResult.get(key);
137
+ if (importerRemoveItem) {
138
+ for (const depName of removeSet) {
139
+ importerRemoveItem.add(depName);
140
+ }
141
+ }
142
+ else if (key.startsWith('file')) {
143
+ // Not an importer - only store file-type deps in transientRemove
144
+ const existing = transientRemove.get(key);
145
+ if (existing) {
146
+ for (const depName of removeSet) {
147
+ existing.add(depName);
148
+ }
149
+ }
150
+ else {
151
+ transientRemove.set(key, new Set(removeSet));
152
+ }
153
+ }
154
+ }
155
+ // Removes any references to an importer that no longer has specs
156
+ for (const [key, removeItem] of removeResult) {
157
+ if (removeItem.size === 0) {
158
+ removeResult.delete(key);
159
+ }
160
+ }
161
+ // removes already satisfied dependencies from the dependencies list
162
+ removeSatisfiedSpecs({
163
+ add: addResult,
164
+ graph,
165
+ });
166
+ // set the modifiedDependencies flag if any
167
+ // of the importers have modified dependencies
168
+ for (const addDeps of addResult.values()) {
169
+ if (addDeps.size > 0) {
170
+ addResult.modifiedDependencies = true;
171
+ break;
172
+ }
173
+ }
174
+ return {
175
+ add: addResult,
176
+ remove: removeResult,
177
+ transientAdd,
178
+ transientRemove,
179
+ };
180
+ };
@@ -0,0 +1,160 @@
1
+ import { Spec } from '@vltpkg/spec';
2
+ import type { PeerContext, PeerContextEntry, PeerContextEntryInput, ProcessPlacementResult } from './types.ts';
3
+ import type { SpecOptions } from '@vltpkg/spec';
4
+ import type { DependencySaveType, Manifest } from '@vltpkg/types';
5
+ import type { Monorepo } from '@vltpkg/workspaces';
6
+ import type { Dependency } from '../dependencies.ts';
7
+ import type { Graph } from '../graph.ts';
8
+ import type { Node } from '../node.ts';
9
+ /**
10
+ * Result of checking if an existing node's peer edges are compatible
11
+ * with a new parent's context. The `forkEntry` property is optional
12
+ * and will only be present if the node's peer edges are incompatible.
13
+ */
14
+ type PeerEdgeCompatResult = {
15
+ compatible: boolean;
16
+ /** When incompatible, entry to add to forked context (target always present) */
17
+ forkEntry?: PeerContextEntryInput & {
18
+ target: Node;
19
+ };
20
+ };
21
+ /**
22
+ * Check if an existing node's peer edges would still resolve to the same
23
+ * targets from a new parent's context. Returns incompatible info if any
24
+ * peer would resolve differently, meaning the node should NOT be reused.
25
+ *
26
+ * This is crucial for avoiding incorrect node reuse that would break peer
27
+ * dependency contracts. Three sources of conflict are checked:
28
+ *
29
+ * 1. **Peer context entries**: The global peer context may have resolved a
30
+ * different version of a peer dependency than what the existing node expects.
31
+ *
32
+ * 2. **Already-placed siblings**: The parent node may already have an edge to
33
+ * a different version of the peer dependency.
34
+ *
35
+ * 3. **Not-yet-placed siblings**: The parent's manifest declares a dependency
36
+ * on the same package, and there's a graph node that would satisfy it but
37
+ * differs from what the existing node expects.
38
+ */
39
+ export declare const checkPeerEdgesCompatible: (existingNode: Node, fromNode: Node, peerContext: PeerContext, graph: Graph) => PeerEdgeCompatResult;
40
+ /**
41
+ * Retrieve a unique hash value for a given peer context set.
42
+ */
43
+ export declare const retrievePeerContextHash: (peerContext: PeerContext | undefined) => string | undefined;
44
+ /**
45
+ * Checks if a given spec is compatible with the specs already
46
+ * assigned to a peer context entry.
47
+ *
48
+ * Returns true if INCOMPATIBLE, false if compatible.
49
+ *
50
+ * Compatibility rules:
51
+ * - **Registry specs**: Uses semver range intersection. `^18.0.0` and `^18.2.0`
52
+ * intersect (compatible), but `^18.0.0` and `^19.0.0` don't (incompatible).
53
+ * - **Non-registry specs** (git, file, etc.): Requires exact bareSpec match.
54
+ * `github:foo/bar#v1` only matches itself.
55
+ *
56
+ * This is used to determine when peer context forking is needed - if specs
57
+ * are incompatible, a new peer context must be created.
58
+ */
59
+ export declare const incompatibleSpecs: (spec: Spec, entry: PeerContextEntry) => boolean;
60
+ /**
61
+ * Sort peer context entry inputs for deterministic processing.
62
+ * Orders: non-peer dependencies first, then peer dependencies, alphabetically by name.
63
+ */
64
+ export declare const getOrderedPeerContextEntries: (entries: PeerContextEntryInput[]) => PeerContextEntryInput[];
65
+ export declare const checkEntriesToPeerContext: (peerContext: PeerContext, entries: PeerContextEntryInput[]) => boolean;
66
+ /**
67
+ * Add or update dependencies in a given peer context making sure to check
68
+ * for compatibility with existing dependencies already resolved by a given
69
+ * peer context set. Extra info such as a target or dependent nodes is
70
+ * optional.
71
+ *
72
+ * Returns true if forking is needed, false otherwise.
73
+ */
74
+ export declare const addEntriesToPeerContext: (peerContext: PeerContext, entries: PeerContextEntryInput[], fromNode: Node, monorepo?: Monorepo) => boolean;
75
+ /**
76
+ * Create and returns a forked copy of a given peer context set.
77
+ */
78
+ export declare const forkPeerContext: (graph: Graph, peerContext: PeerContext, entries: PeerContextEntryInput[]) => PeerContext;
79
+ /**
80
+ * Starts the peer dependency placement process
81
+ * for a given node being processed and placed.
82
+ */
83
+ export declare const startPeerPlacement: (peerContext: PeerContext, manifest: Manifest, fromNode: Node, options: SpecOptions) => {
84
+ peerSetHash: string | undefined;
85
+ queuedEntries: PeerContextEntryInput[];
86
+ };
87
+ /**
88
+ * Ends the peer dependency placement process, returning the functions that
89
+ * are going to be used to update the peer context set, forking when needed
90
+ * and resolving peer dependencies if possible.
91
+ *
92
+ * Returns two deferred functions:
93
+ * - `putEntries()`: Adds entries to peer context; returns fork entries if conflict
94
+ * - `resolvePeerDeps()`: Resolves peer deps from context/siblings or adds to nextDeps
95
+ *
96
+ * These are deferred (not executed immediately) so that all siblings at a level
97
+ * can be processed before peer context updates, enabling context reuse optimization.
98
+ */
99
+ export declare const endPeerPlacement: (peerContext: PeerContext, nextDeps: Dependency[], nextPeerDeps: Map<string, Dependency> & {
100
+ id?: number;
101
+ }, graph: Graph, spec: Spec, fromNode: Node, node: Node, type: DependencySaveType, queuedEntries: PeerContextEntryInput[]) => {
102
+ /**
103
+ * Add the new entries to the current peer context set.
104
+ *
105
+ * Two sets of entries are checked:
106
+ * - `prevEntries`: Parent's queued entries + self-reference
107
+ * - `nextEntries`: This node's deps + peer deps (with node as dependent)
108
+ *
109
+ * If either conflicts with the current context, returns ALL entries to be
110
+ * added to a forked context (prevEntries last for priority).
111
+ *
112
+ * Returns `undefined` if no fork needed (entries added directly to context).
113
+ */
114
+ putEntries: () => (PeerContextEntryInput | {
115
+ dependent: Node;
116
+ spec: import("@vltpkg/spec/browser").Spec;
117
+ type: DependencySaveType;
118
+ } | {
119
+ spec: Spec;
120
+ target: Node;
121
+ type: DependencySaveType;
122
+ })[] | undefined;
123
+ /**
124
+ * Try to resolve peer dependencies using already seen target
125
+ * values from the current peer context set.
126
+ *
127
+ * Resolution priority (highest to lowest):
128
+ * 1. Sibling deps from parent (workspace direct deps take priority)
129
+ * 2. Peer-edge closure of sibling targets (handles peer cycles)
130
+ * 3. Global peer context set entries
131
+ * 4. Add to nextDeps for normal resolution (or create dangling edge for optional)
132
+ */
133
+ resolvePeerDeps: () => void;
134
+ };
135
+ /**
136
+ * Given an array of processed results for the current level dependencies
137
+ * being placed in the currently building ideal graph, traverse its direct
138
+ * dependencies and track peer dependencies in their appropriate peer context
139
+ * sets, forking as needed and resolving peer dependencies using suitable
140
+ * nodes already present in the graph if possible.
141
+ *
142
+ * This is the core peer context management algorithm, executed after each
143
+ * BFS level. It runs in three phases:
144
+ *
145
+ * **Phase 1: Collect fork requirements**
146
+ * Call `putEntries()` on each child dep to add entries to peer context.
147
+ * Collect which children need forked contexts (due to conflicts).
148
+ *
149
+ * **Phase 2: Fork or reuse contexts**
150
+ * For children needing forks, try to reuse a sibling's forked context if
151
+ * compatible. This optimization reduces the number of peer contexts created.
152
+ *
153
+ * **Phase 3: Resolve peer deps**
154
+ * With contexts finalized, call `resolvePeerDeps()` to create edges for
155
+ * peers that can be satisfied from context/siblings, or add them to nextDeps.
156
+ *
157
+ * All operations are sorted by `node.id` for deterministic, reproducible builds.
158
+ */
159
+ export declare const postPlacementPeerCheck: (graph: Graph, sortedLevelResults: ProcessPlacementResult[]) => void;
160
+ export {};