@vltpkg/graph 0.0.0-9 → 1.0.0-rc.10
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 +136 -1
- package/dist/esm/actual/load.d.ts +49 -3
- package/dist/esm/actual/load.d.ts.map +1 -1
- package/dist/esm/actual/load.js +146 -74
- package/dist/esm/actual/load.js.map +1 -1
- package/dist/esm/browser.d.ts +8 -4
- package/dist/esm/browser.d.ts.map +1 -1
- package/dist/esm/browser.js +6 -2
- package/dist/esm/browser.js.map +1 -1
- package/dist/esm/build.d.ts +29 -0
- package/dist/esm/build.d.ts.map +1 -0
- package/dist/esm/build.js +79 -0
- package/dist/esm/build.js.map +1 -0
- package/dist/esm/dependencies.d.ts +10 -3
- package/dist/esm/dependencies.d.ts.map +1 -1
- package/dist/esm/dependencies.js +63 -0
- package/dist/esm/dependencies.js.map +1 -1
- package/dist/esm/diff.d.ts +69 -0
- package/dist/esm/diff.d.ts.map +1 -1
- package/dist/esm/diff.js +25 -0
- package/dist/esm/diff.js.map +1 -1
- package/dist/esm/edge.d.ts +8 -2
- package/dist/esm/edge.d.ts.map +1 -1
- package/dist/esm/edge.js +12 -0
- package/dist/esm/edge.js.map +1 -1
- package/dist/esm/fixup-added-names.d.ts +16 -0
- package/dist/esm/fixup-added-names.d.ts.map +1 -0
- package/dist/esm/fixup-added-names.js +31 -0
- package/dist/esm/fixup-added-names.js.map +1 -0
- package/dist/esm/graph.d.ts +34 -10
- package/dist/esm/graph.d.ts.map +1 -1
- package/dist/esm/graph.js +150 -24
- package/dist/esm/graph.js.map +1 -1
- package/dist/esm/ideal/append-nodes.d.ts +12 -1
- package/dist/esm/ideal/append-nodes.d.ts.map +1 -1
- package/dist/esm/ideal/append-nodes.js +303 -53
- package/dist/esm/ideal/append-nodes.js.map +1 -1
- package/dist/esm/ideal/build-ideal-from-starting-graph.d.ts +4 -4
- package/dist/esm/ideal/build-ideal-from-starting-graph.d.ts.map +1 -1
- package/dist/esm/ideal/build-ideal-from-starting-graph.js +35 -16
- package/dist/esm/ideal/build-ideal-from-starting-graph.js.map +1 -1
- package/dist/esm/ideal/build.d.ts +9 -0
- package/dist/esm/ideal/build.d.ts.map +1 -1
- package/dist/esm/ideal/build.js +31 -1
- package/dist/esm/ideal/build.js.map +1 -1
- package/dist/esm/ideal/get-importer-specs.d.ts +11 -3
- package/dist/esm/ideal/get-importer-specs.d.ts.map +1 -1
- package/dist/esm/ideal/get-importer-specs.js +86 -9
- package/dist/esm/ideal/get-importer-specs.js.map +1 -1
- package/dist/esm/ideal/get-ordered-dependencies.d.ts +10 -0
- package/dist/esm/ideal/get-ordered-dependencies.d.ts.map +1 -0
- package/dist/esm/ideal/get-ordered-dependencies.js +42 -0
- package/dist/esm/ideal/get-ordered-dependencies.js.map +1 -0
- package/dist/esm/ideal/peers.d.ts +71 -0
- package/dist/esm/ideal/peers.d.ts.map +1 -0
- package/dist/esm/ideal/peers.js +318 -0
- package/dist/esm/ideal/peers.js.map +1 -0
- package/dist/esm/ideal/refresh-ideal-graph.d.ts +48 -0
- package/dist/esm/ideal/refresh-ideal-graph.d.ts.map +1 -0
- package/dist/esm/ideal/refresh-ideal-graph.js +79 -0
- package/dist/esm/ideal/refresh-ideal-graph.js.map +1 -0
- package/dist/esm/ideal/types.d.ts +78 -1
- package/dist/esm/ideal/types.d.ts.map +1 -1
- package/dist/esm/ideal/types.js.map +1 -1
- package/dist/esm/index.d.ts +9 -4
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +5 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/install.d.ts +10 -4
- package/dist/esm/install.d.ts.map +1 -1
- package/dist/esm/install.js +191 -20
- package/dist/esm/install.js.map +1 -1
- package/dist/esm/lockfile/load-edges.d.ts +8 -1
- package/dist/esm/lockfile/load-edges.d.ts.map +1 -1
- package/dist/esm/lockfile/load-edges.js +80 -15
- package/dist/esm/lockfile/load-edges.js.map +1 -1
- package/dist/esm/lockfile/load-nodes.d.ts +3 -2
- package/dist/esm/lockfile/load-nodes.d.ts.map +1 -1
- package/dist/esm/lockfile/load-nodes.js +85 -13
- package/dist/esm/lockfile/load-nodes.js.map +1 -1
- package/dist/esm/lockfile/load.d.ts +18 -5
- package/dist/esm/lockfile/load.d.ts.map +1 -1
- package/dist/esm/lockfile/load.js +28 -20
- package/dist/esm/lockfile/load.js.map +1 -1
- package/dist/esm/lockfile/save.d.ts +16 -3
- package/dist/esm/lockfile/save.d.ts.map +1 -1
- package/dist/esm/lockfile/save.js +64 -17
- package/dist/esm/lockfile/save.js.map +1 -1
- package/dist/esm/lockfile/types.d.ts +34 -4
- package/dist/esm/lockfile/types.d.ts.map +1 -1
- package/dist/esm/lockfile/types.js +31 -0
- package/dist/esm/lockfile/types.js.map +1 -1
- package/dist/esm/modifiers.d.ts +189 -0
- package/dist/esm/modifiers.d.ts.map +1 -0
- package/dist/esm/modifiers.js +330 -0
- package/dist/esm/modifiers.js.map +1 -0
- package/dist/esm/node.d.ts +91 -6
- package/dist/esm/node.d.ts.map +1 -1
- package/dist/esm/node.js +119 -5
- package/dist/esm/node.js.map +1 -1
- package/dist/esm/reify/add-edge.d.ts +1 -2
- package/dist/esm/reify/add-edge.d.ts.map +1 -1
- package/dist/esm/reify/add-edge.js +29 -18
- package/dist/esm/reify/add-edge.js.map +1 -1
- package/dist/esm/reify/add-edges.d.ts +1 -2
- package/dist/esm/reify/add-edges.d.ts.map +1 -1
- package/dist/esm/reify/add-edges.js +3 -3
- package/dist/esm/reify/add-edges.js.map +1 -1
- package/dist/esm/reify/add-nodes.d.ts.map +1 -1
- package/dist/esm/reify/add-nodes.js +4 -27
- package/dist/esm/reify/add-nodes.js.map +1 -1
- package/dist/esm/reify/bin-chmod.d.ts +11 -0
- package/dist/esm/reify/bin-chmod.d.ts.map +1 -0
- package/dist/esm/reify/bin-chmod.js +39 -0
- package/dist/esm/reify/bin-chmod.js.map +1 -0
- package/dist/esm/reify/build.d.ts +10 -1
- package/dist/esm/reify/build.d.ts.map +1 -1
- package/dist/esm/reify/build.js +36 -23
- package/dist/esm/reify/build.js.map +1 -1
- package/dist/esm/reify/calculate-save-value.d.ts +3 -0
- package/dist/esm/reify/calculate-save-value.d.ts.map +1 -0
- package/dist/esm/reify/calculate-save-value.js +45 -0
- package/dist/esm/reify/calculate-save-value.js.map +1 -0
- package/dist/esm/reify/check-needed-build.d.ts +25 -0
- package/dist/esm/reify/check-needed-build.d.ts.map +1 -0
- package/dist/esm/reify/check-needed-build.js +50 -0
- package/dist/esm/reify/check-needed-build.js.map +1 -0
- package/dist/esm/reify/delete-edge.d.ts.map +1 -1
- package/dist/esm/reify/delete-edge.js +3 -4
- package/dist/esm/reify/delete-edge.js.map +1 -1
- package/dist/esm/reify/extract-node.d.ts +24 -0
- package/dist/esm/reify/extract-node.d.ts.map +1 -0
- package/dist/esm/reify/extract-node.js +84 -0
- package/dist/esm/reify/extract-node.js.map +1 -0
- package/dist/esm/reify/index.d.ts +18 -1
- package/dist/esm/reify/index.d.ts.map +1 -1
- package/dist/esm/reify/index.js +85 -15
- package/dist/esm/reify/index.js.map +1 -1
- package/dist/esm/reify/internal-hoist.d.ts +9 -0
- package/dist/esm/reify/internal-hoist.d.ts.map +1 -0
- package/dist/esm/reify/internal-hoist.js +134 -0
- package/dist/esm/reify/internal-hoist.js.map +1 -0
- package/dist/esm/reify/update-importers-package-json.d.ts +1 -1
- package/dist/esm/reify/update-importers-package-json.d.ts.map +1 -1
- package/dist/esm/reify/update-importers-package-json.js +33 -24
- package/dist/esm/reify/update-importers-package-json.js.map +1 -1
- package/dist/esm/remove-optional-subgraph.js +1 -1
- package/dist/esm/remove-optional-subgraph.js.map +1 -1
- package/dist/esm/resolve-save-type.d.ts +1 -2
- package/dist/esm/resolve-save-type.d.ts.map +1 -1
- package/dist/esm/resolve-save-type.js.map +1 -1
- package/dist/esm/stringify-node.d.ts +1 -1
- package/dist/esm/stringify-node.d.ts.map +1 -1
- package/dist/esm/stringify-node.js +10 -1
- package/dist/esm/stringify-node.js.map +1 -1
- package/dist/esm/transfer-data/load.d.ts +44 -0
- package/dist/esm/transfer-data/load.d.ts.map +1 -0
- package/dist/esm/transfer-data/load.js +176 -0
- package/dist/esm/transfer-data/load.js.map +1 -0
- package/dist/esm/uninstall.d.ts +5 -4
- package/dist/esm/uninstall.d.ts.map +1 -1
- package/dist/esm/uninstall.js +61 -19
- package/dist/esm/uninstall.js.map +1 -1
- package/dist/esm/update.d.ts +13 -0
- package/dist/esm/update.d.ts.map +1 -0
- package/dist/esm/update.js +73 -0
- package/dist/esm/update.js.map +1 -0
- package/dist/esm/virtual-root.d.ts +16 -0
- package/dist/esm/virtual-root.d.ts.map +1 -0
- package/dist/esm/virtual-root.js +79 -0
- package/dist/esm/virtual-root.js.map +1 -0
- package/dist/esm/visualization/human-readable-output.d.ts +4 -5
- package/dist/esm/visualization/human-readable-output.d.ts.map +1 -1
- package/dist/esm/visualization/human-readable-output.js +47 -19
- package/dist/esm/visualization/human-readable-output.js.map +1 -1
- package/dist/esm/visualization/json-output.d.ts +7 -2
- package/dist/esm/visualization/json-output.d.ts.map +1 -1
- package/dist/esm/visualization/json-output.js +35 -12
- package/dist/esm/visualization/json-output.js.map +1 -1
- package/dist/esm/visualization/mermaid-output.d.ts +7 -1
- package/dist/esm/visualization/mermaid-output.d.ts.map +1 -1
- package/dist/esm/visualization/mermaid-output.js +110 -14
- package/dist/esm/visualization/mermaid-output.js.map +1 -1
- package/dist/esm/visualization/object-like-output.d.ts +1 -1
- package/dist/esm/visualization/object-like-output.d.ts.map +1 -1
- package/dist/esm/visualization/object-like-output.js.map +1 -1
- package/package.json +35 -29
- package/dist/esm/ideal/add-nodes.d.ts +0 -19
- package/dist/esm/ideal/add-nodes.d.ts.map +0 -1
- package/dist/esm/ideal/add-nodes.js +0 -32
- package/dist/esm/ideal/add-nodes.js.map +0 -1
- package/dist/esm/ideal/remove-nodes.d.ts +0 -7
- package/dist/esm/ideal/remove-nodes.d.ts.map +0 -1
- package/dist/esm/ideal/remove-nodes.js +0 -19
- package/dist/esm/ideal/remove-nodes.js.map +0 -1
- package/dist/esm/reify/bin-paths.d.ts +0 -4
- package/dist/esm/reify/bin-paths.d.ts.map +0 -1
- package/dist/esm/reify/bin-paths.js +0 -23
- package/dist/esm/reify/bin-paths.js.map +0 -1
- package/dist/esm/types.d.ts +0 -42
- package/dist/esm/types.d.ts.map +0 -1
- package/dist/esm/types.js +0 -2
- package/dist/esm/types.js.map +0 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Computes the ordered list of dependencies for an given node,
|
|
3
|
+
* taking into account additions and removals.
|
|
4
|
+
*/
|
|
5
|
+
export const getNodeOrderedDependencies = (fromNode, options) => {
|
|
6
|
+
// using a map here instead of an array helps us get simpler
|
|
7
|
+
// deduplication while iterating through all the items at hand:
|
|
8
|
+
// existing dependencies in the graph, dependencies to be added, etc.
|
|
9
|
+
const deps = new Map();
|
|
10
|
+
for (const [name, { spec, type }] of fromNode.edgesOut.entries()) {
|
|
11
|
+
deps.set(name, { spec, type });
|
|
12
|
+
}
|
|
13
|
+
// next iterate through the list of dependencies to be added
|
|
14
|
+
const addedDeps = options?.add.get(fromNode.id);
|
|
15
|
+
if (addedDeps) {
|
|
16
|
+
for (const [name, { spec, type }] of addedDeps.entries()) {
|
|
17
|
+
deps.set(name, { spec, type });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// finally iterate through the list of dependencies to be removed
|
|
21
|
+
const removedDeps = options?.remove.get(fromNode.id);
|
|
22
|
+
if (removedDeps) {
|
|
23
|
+
for (const name of removedDeps) {
|
|
24
|
+
deps.delete(name);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// now turn the map into a sorted array
|
|
28
|
+
return getOrderedDependencies([...deps.values()]);
|
|
29
|
+
};
|
|
30
|
+
export const getOrderedDependencies = (deps) => {
|
|
31
|
+
const orderedDeps = [...deps].sort(({ spec: aSpec, type: aType }, { spec: bSpec, type: bType }) => {
|
|
32
|
+
const aIsPeer = aType === 'peer' || aType === 'peerOptional' ? 1 : 0;
|
|
33
|
+
const bIsPeer = bType === 'peer' || bType === 'peerOptional' ? 1 : 0;
|
|
34
|
+
// regular dependencies first, peer dependencies last
|
|
35
|
+
if (aIsPeer !== bIsPeer) {
|
|
36
|
+
return aIsPeer - bIsPeer;
|
|
37
|
+
}
|
|
38
|
+
return aSpec.name.localeCompare(bSpec.name, 'en');
|
|
39
|
+
});
|
|
40
|
+
return orderedDeps;
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=get-ordered-dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-ordered-dependencies.js","sourceRoot":"","sources":["../../../src/ideal/get-ordered-dependencies.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CACxC,QAAc,EACd,OAAwD,EAC1C,EAAE;IAChB,4DAA4D;IAC5D,+DAA+D;IAC/D,qEAAqE;IACrE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAsB,CAAA;IAC1C,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;QACjE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IAChC,CAAC;IACD,4DAA4D;IAC5D,MAAM,SAAS,GAAG,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IAC/C,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;YACzD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAChC,CAAC;IACH,CAAC;IACD,iEAAiE;IACjE,MAAM,WAAW,GAAG,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IACpD,IAAI,WAAW,EAAE,CAAC;QAChB,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACnB,CAAC;IACH,CAAC;IAED,uCAAuC;IACvC,OAAO,sBAAsB,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;AACnD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,IAAkB,EACJ,EAAE;IAChB,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAChC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;QAC7D,MAAM,OAAO,GACX,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACtD,MAAM,OAAO,GACX,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAEtD,qDAAqD;QACrD,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YACxB,OAAO,OAAO,GAAG,OAAO,CAAA;QAC1B,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IACnD,CAAC,CACF,CAAA;IACD,OAAO,WAAW,CAAA;AACpB,CAAC,CAAA","sourcesContent":["import type { Node } from '../node.ts'\nimport type { Dependency } from '../dependencies.ts'\nimport type {\n BuildIdealAddOptions,\n BuildIdealRemoveOptions,\n} from './types.ts'\n\n/**\n * Computes the ordered list of dependencies for an given node,\n * taking into account additions and removals.\n */\nexport const getNodeOrderedDependencies = (\n fromNode: Node,\n options?: BuildIdealAddOptions & BuildIdealRemoveOptions,\n): Dependency[] => {\n // using a map here instead of an array helps us get simpler\n // deduplication while iterating through all the items at hand:\n // existing dependencies in the graph, dependencies to be added, etc.\n const deps = new Map<string, Dependency>()\n for (const [name, { spec, type }] of fromNode.edgesOut.entries()) {\n deps.set(name, { spec, type })\n }\n // next iterate through the list of dependencies to be added\n const addedDeps = options?.add.get(fromNode.id)\n if (addedDeps) {\n for (const [name, { spec, type }] of addedDeps.entries()) {\n deps.set(name, { spec, type })\n }\n }\n // finally iterate through the list of dependencies to be removed\n const removedDeps = options?.remove.get(fromNode.id)\n if (removedDeps) {\n for (const name of removedDeps) {\n deps.delete(name)\n }\n }\n\n // now turn the map into a sorted array\n return getOrderedDependencies([...deps.values()])\n}\n\nexport const getOrderedDependencies = (\n deps: Dependency[],\n): Dependency[] => {\n const orderedDeps = [...deps].sort(\n ({ spec: aSpec, type: aType }, { spec: bSpec, type: bType }) => {\n const aIsPeer =\n aType === 'peer' || aType === 'peerOptional' ? 1 : 0\n const bIsPeer =\n bType === 'peer' || bType === 'peerOptional' ? 1 : 0\n\n // regular dependencies first, peer dependencies last\n if (aIsPeer !== bIsPeer) {\n return aIsPeer - bIsPeer\n }\n\n return aSpec.name.localeCompare(bSpec.name, 'en')\n },\n )\n return orderedDeps\n}\n"]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Spec, SpecOptions } from '@vltpkg/spec';
|
|
2
|
+
import type { DependencySaveType, Manifest } from '@vltpkg/types';
|
|
3
|
+
import type { Monorepo } from '@vltpkg/workspaces';
|
|
4
|
+
import type { Dependency } from '../dependencies.ts';
|
|
5
|
+
import type { Graph } from '../graph.ts';
|
|
6
|
+
import type { Node } from '../node.ts';
|
|
7
|
+
import type { PeerContext, PeerContextEntry, PeerContextEntryInput, ProcessPlacementResult } from './types.ts';
|
|
8
|
+
/**
|
|
9
|
+
* Retrieve a unique hash value for a given peer context set.
|
|
10
|
+
*/
|
|
11
|
+
export declare const retrievePeerContextHash: (peerContext: PeerContext | undefined) => string | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Checks if a given spec is compatible with the specs already
|
|
14
|
+
* assigned to a peer context entry.
|
|
15
|
+
*
|
|
16
|
+
* Returns true if compatible, false otherwise.
|
|
17
|
+
*/
|
|
18
|
+
export declare const incompatibleSpecs: (spec: Spec, entry: PeerContextEntry) => boolean;
|
|
19
|
+
export declare const checkEntriesToPeerContext: (peerContext: PeerContext, entries: PeerContextEntryInput[]) => boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Add or update dependencies in a given peer context making sure to check
|
|
22
|
+
* for compatibility with existing dependencies already resolved by a given
|
|
23
|
+
* peer context set. Extra info such as a target or dependent nodes is
|
|
24
|
+
* optional.
|
|
25
|
+
*
|
|
26
|
+
* Returns true if forking is needed, false otherwise.
|
|
27
|
+
*/
|
|
28
|
+
export declare const addEntriesToPeerContext: (peerContext: PeerContext, entries: PeerContextEntryInput[], fromNode: Node, monorepo?: Monorepo) => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Create and returns a forked copy of a given peer context set.
|
|
31
|
+
*/
|
|
32
|
+
export declare const forkPeerContext: (graph: Graph, peerContext: PeerContext, entries: PeerContextEntryInput[]) => PeerContext;
|
|
33
|
+
/**
|
|
34
|
+
* Starts the peer dependency placement process
|
|
35
|
+
* for a given node being processed and placed.
|
|
36
|
+
*/
|
|
37
|
+
export declare const startPeerPlacement: (peerContext: PeerContext, manifest: Manifest, fromNode: Node, options: SpecOptions) => {
|
|
38
|
+
peerSetHash: string | undefined;
|
|
39
|
+
queuedEntries: PeerContextEntryInput[];
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Ends the peer dependency placement process, returning the functions that
|
|
43
|
+
* are going to be used to update the peer context set, forking when needed
|
|
44
|
+
* and resolving peer dependencies if possible.
|
|
45
|
+
*/
|
|
46
|
+
export declare const endPeerPlacement: (peerContext: PeerContext, nextDeps: Dependency[], nextPeerDeps: Map<string, Dependency> & {
|
|
47
|
+
id?: number;
|
|
48
|
+
}, graph: Graph, spec: Spec, fromNode: Node, node: Node, type: DependencySaveType, queuedEntries: PeerContextEntryInput[]) => {
|
|
49
|
+
/**
|
|
50
|
+
* Add the new entries to the current peer context set.
|
|
51
|
+
*/
|
|
52
|
+
putEntries: () => {
|
|
53
|
+
dependent: Node;
|
|
54
|
+
spec: import("@vltpkg/spec/browser").Spec;
|
|
55
|
+
type: DependencySaveType;
|
|
56
|
+
}[] | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Try to resolve peer dependencies using already seen target
|
|
59
|
+
* values from the current peer context set.
|
|
60
|
+
*/
|
|
61
|
+
resolvePeerDeps: () => void;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Given an array of processed results for the current level dependencies
|
|
65
|
+
* being placed in the currently building ideal graph, traverse its direct
|
|
66
|
+
* dependencies and track peer dependencies in their appropriate peer context
|
|
67
|
+
* sets, forking as needed and resolving peer dependencies using suitable
|
|
68
|
+
* nodes already present in the graph if possible.
|
|
69
|
+
*/
|
|
70
|
+
export declare const postPlacementPeerCheck: (graph: Graph, sortedLevelResults: ProcessPlacementResult[]) => void;
|
|
71
|
+
//# sourceMappingURL=peers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peers.d.ts","sourceRoot":"","sources":["../../../src/ideal/peers.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjE,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;AACtC,OAAO,KAAK,EACV,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EAEvB,MAAM,YAAY,CAAA;AAEnB;;GAEG;AACH,eAAO,MAAM,uBAAuB,gBACrB,WAAW,GAAG,SAAS,KACnC,MAAM,GAAG,SAKX,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,SACtB,IAAI,SACH,gBAAgB,KACtB,OAkBF,CAAA;AAQD,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,OAsEF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,UACnB,KAAK,eACC,WAAW,WACf,qBAAqB,EAAE,KAC/B,WAqCF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,gBAChB,WAAW,YACd,QAAQ,YACR,IAAI,WACL,WAAW;;;CAyCrB,CAAA;AAED;;;;GAIG;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;;OAEG;;;;;;IA2CH;;;OAGG;;CAsCH,CAAA;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,UAC1B,KAAK,sBACQ,sBAAsB,EAAE,SAsD7C,CAAA"}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
// helpers for managing peer dependency resolution
|
|
2
|
+
// during the ideal graph building process.
|
|
3
|
+
import { intersects } from '@vltpkg/semver';
|
|
4
|
+
import { satisfies } from '@vltpkg/satisfies';
|
|
5
|
+
import { getDependencies } from "../dependencies.js";
|
|
6
|
+
import { getOrderedDependencies } from "./get-ordered-dependencies.js";
|
|
7
|
+
/**
|
|
8
|
+
* Retrieve a unique hash value for a given peer context set.
|
|
9
|
+
*/
|
|
10
|
+
export const retrievePeerContextHash = (peerContext) => {
|
|
11
|
+
// skips creating the initial peer context ref
|
|
12
|
+
if (!peerContext?.index)
|
|
13
|
+
return undefined;
|
|
14
|
+
return `ṗ:${peerContext.index}`;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Checks if a given spec is compatible with the specs already
|
|
18
|
+
* assigned to a peer context entry.
|
|
19
|
+
*
|
|
20
|
+
* Returns true if compatible, false otherwise.
|
|
21
|
+
*/
|
|
22
|
+
export const incompatibleSpecs = (spec, entry) => {
|
|
23
|
+
if (entry.specs.size > 0) {
|
|
24
|
+
for (const s of entry.specs) {
|
|
25
|
+
if (
|
|
26
|
+
// only able to check range intersections for registry types
|
|
27
|
+
(spec.type === 'registry' &&
|
|
28
|
+
(!spec.range ||
|
|
29
|
+
!s.range ||
|
|
30
|
+
!intersects(spec.range, s.range))) ||
|
|
31
|
+
// also support types other than registry in case
|
|
32
|
+
// they use the very same bareSpec value
|
|
33
|
+
(spec.type !== 'registry' && spec.bareSpec !== s.bareSpec)) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
};
|
|
40
|
+
/*
|
|
41
|
+
* Checks if there are any conflicting versions for a given dependency
|
|
42
|
+
* to be added to a peer context set which will require forking.
|
|
43
|
+
*
|
|
44
|
+
* Returns true if forking is needed, false otherwise.
|
|
45
|
+
*/
|
|
46
|
+
export const checkEntriesToPeerContext = (peerContext, entries) => {
|
|
47
|
+
// check on compatibility of new entries
|
|
48
|
+
for (const { spec, target } of entries) {
|
|
49
|
+
const name = target?.name ?? spec.final.name;
|
|
50
|
+
// skip any inactive entry
|
|
51
|
+
const entry = peerContext.get(name);
|
|
52
|
+
if (!entry?.active)
|
|
53
|
+
continue;
|
|
54
|
+
// validate if the provided spec is compatible with existing specs
|
|
55
|
+
if (incompatibleSpecs(spec, entry)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Add or update dependencies in a given peer context making sure to check
|
|
63
|
+
* for compatibility with existing dependencies already resolved by a given
|
|
64
|
+
* peer context set. Extra info such as a target or dependent nodes is
|
|
65
|
+
* optional.
|
|
66
|
+
*
|
|
67
|
+
* Returns true if forking is needed, false otherwise.
|
|
68
|
+
*/
|
|
69
|
+
export const addEntriesToPeerContext = (peerContext, entries, fromNode, monorepo) => {
|
|
70
|
+
// pre check to see if any of the new entries to be added to the
|
|
71
|
+
// provided peer context set conflicts with existing ones
|
|
72
|
+
// if that's already the case we can skip processing them and
|
|
73
|
+
// will return that a fork is needed right away
|
|
74
|
+
if (checkEntriesToPeerContext(peerContext, entries))
|
|
75
|
+
return true;
|
|
76
|
+
// iterate on every entry to be added to the peer context set
|
|
77
|
+
for (const { dependent, spec, target, type } of entries) {
|
|
78
|
+
const name = target?.name ?? spec.final.name;
|
|
79
|
+
// if there's no existing entry, create one
|
|
80
|
+
let entry = peerContext.get(name);
|
|
81
|
+
if (!entry) {
|
|
82
|
+
entry = {
|
|
83
|
+
active: true,
|
|
84
|
+
specs: new Set([spec]),
|
|
85
|
+
target,
|
|
86
|
+
type,
|
|
87
|
+
contextDependents: new Set(),
|
|
88
|
+
};
|
|
89
|
+
peerContext.set(name, entry);
|
|
90
|
+
if (dependent)
|
|
91
|
+
entry.contextDependents.add(dependent);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
// perform an extra check that confirms the new spec does not
|
|
95
|
+
// conflicts with existing specs in this entry, this handles the
|
|
96
|
+
// case of adding sibling deps that conflicts with one another
|
|
97
|
+
if (incompatibleSpecs(spec, entry))
|
|
98
|
+
return true;
|
|
99
|
+
if (target &&
|
|
100
|
+
[...entry.specs].every(s => satisfies(target.id, s, fromNode.location, fromNode.projectRoot, monorepo))) {
|
|
101
|
+
if (target.id !== entry.target?.id &&
|
|
102
|
+
target.version !== entry.target?.version) {
|
|
103
|
+
// we have a compatible entry that has a new, compatible target
|
|
104
|
+
// so we need to update all dependents to point to the new target
|
|
105
|
+
for (const dependents of entry.contextDependents) {
|
|
106
|
+
const edge = dependents.edgesOut.get(name);
|
|
107
|
+
if (edge?.to && edge.to !== target) {
|
|
108
|
+
edge.to.edgesIn.delete(edge);
|
|
109
|
+
edge.to = target;
|
|
110
|
+
target.edgesIn.add(edge);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
entry.target = target;
|
|
114
|
+
}
|
|
115
|
+
// otherwise sets the value in case it was nullish
|
|
116
|
+
entry.target ??= target;
|
|
117
|
+
}
|
|
118
|
+
// update specs and dependents values
|
|
119
|
+
entry.specs.add(spec);
|
|
120
|
+
if (dependent)
|
|
121
|
+
entry.contextDependents.add(dependent);
|
|
122
|
+
}
|
|
123
|
+
return false;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Create and returns a forked copy of a given peer context set.
|
|
127
|
+
*/
|
|
128
|
+
export const forkPeerContext = (graph, peerContext, entries) => {
|
|
129
|
+
// create a new peer context set
|
|
130
|
+
const nextPeerContext = new Map();
|
|
131
|
+
nextPeerContext.index = graph.nextPeerContextIndex();
|
|
132
|
+
// register it in the graph
|
|
133
|
+
graph.peerContexts[nextPeerContext.index] = nextPeerContext;
|
|
134
|
+
// copy existing entries marking them as inactive, it's also important
|
|
135
|
+
// to note that specs and contextDependents are new objects so that changes
|
|
136
|
+
// to those in the new context do not affect the previous one
|
|
137
|
+
for (const [name, entry] of peerContext.entries()) {
|
|
138
|
+
nextPeerContext.set(name, {
|
|
139
|
+
active: false,
|
|
140
|
+
specs: new Set(entry.specs),
|
|
141
|
+
target: undefined,
|
|
142
|
+
type: entry.type,
|
|
143
|
+
contextDependents: new Set(entry.contextDependents),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
// add the new entries to this peer context set, marking them as active
|
|
147
|
+
// these are the entries that were incompatible with the previous context set
|
|
148
|
+
for (const entry of entries) {
|
|
149
|
+
const { dependent, spec, target, type } = entry;
|
|
150
|
+
const name = target?.name /* c8 ignore next */ ?? spec.final.name;
|
|
151
|
+
const newEntry = {
|
|
152
|
+
active: true,
|
|
153
|
+
specs: new Set([spec]),
|
|
154
|
+
target,
|
|
155
|
+
type,
|
|
156
|
+
contextDependents: dependent ? new Set([dependent]) : new Set(),
|
|
157
|
+
};
|
|
158
|
+
nextPeerContext.set(name, newEntry);
|
|
159
|
+
}
|
|
160
|
+
return nextPeerContext;
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Starts the peer dependency placement process
|
|
164
|
+
* for a given node being processed and placed.
|
|
165
|
+
*/
|
|
166
|
+
export const startPeerPlacement = (peerContext, manifest, fromNode, options) => {
|
|
167
|
+
// queue entries so that they can be added at the end of the placement
|
|
168
|
+
// process, use a map to ensure deduplication between read json dep
|
|
169
|
+
// values and the resolved edges in the graph
|
|
170
|
+
const queueMap = new Map();
|
|
171
|
+
let peerSetHash;
|
|
172
|
+
if (manifest.peerDependencies &&
|
|
173
|
+
Object.keys(manifest.peerDependencies).length > 0) {
|
|
174
|
+
// generates a peer context set hash for nodes that
|
|
175
|
+
// have peer dependencies to be resolved
|
|
176
|
+
peerSetHash = retrievePeerContextHash(peerContext);
|
|
177
|
+
// get any potential sibling dependency from the
|
|
178
|
+
// parent node that might have not been parsed yet
|
|
179
|
+
const siblingDeps = getDependencies(fromNode, {
|
|
180
|
+
...options,
|
|
181
|
+
registry: fromNode.registry,
|
|
182
|
+
});
|
|
183
|
+
for (const [depName, dep] of siblingDeps) {
|
|
184
|
+
queueMap.set(depName, dep);
|
|
185
|
+
}
|
|
186
|
+
// collect the already parsed nodes and add those to the
|
|
187
|
+
// list of entries to be added to the peer context set
|
|
188
|
+
for (const edge of fromNode.edgesOut.values()) {
|
|
189
|
+
queueMap.set(edge.name, {
|
|
190
|
+
spec: edge.spec,
|
|
191
|
+
target: edge.to,
|
|
192
|
+
type: edge.type,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
peerSetHash,
|
|
198
|
+
queuedEntries: [...queueMap.values()],
|
|
199
|
+
};
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* Ends the peer dependency placement process, returning the functions that
|
|
203
|
+
* are going to be used to update the peer context set, forking when needed
|
|
204
|
+
* and resolving peer dependencies if possible.
|
|
205
|
+
*/
|
|
206
|
+
export const endPeerPlacement = (peerContext, nextDeps, nextPeerDeps, graph, spec, fromNode, node, type, queuedEntries) => ({
|
|
207
|
+
/**
|
|
208
|
+
* Add the new entries to the current peer context set.
|
|
209
|
+
*/
|
|
210
|
+
putEntries: () => {
|
|
211
|
+
// keep track of whether we need to fork the current peer context set
|
|
212
|
+
let needsToForkPeerContext = false;
|
|
213
|
+
// add queued entries from this node parents along
|
|
214
|
+
// with a self-ref to the current peer context set
|
|
215
|
+
const prevEntries = [
|
|
216
|
+
...queuedEntries,
|
|
217
|
+
/* ref itself */ {
|
|
218
|
+
spec,
|
|
219
|
+
target: node,
|
|
220
|
+
type,
|
|
221
|
+
},
|
|
222
|
+
];
|
|
223
|
+
addEntriesToPeerContext(peerContext, prevEntries, fromNode, graph.monorepo);
|
|
224
|
+
// add this node's direct dependencies next
|
|
225
|
+
const nextEntries = [
|
|
226
|
+
...nextDeps.map(dep => ({ ...dep, dependent: node })),
|
|
227
|
+
...[...nextPeerDeps.values()].map(dep => ({
|
|
228
|
+
...dep,
|
|
229
|
+
dependent: node,
|
|
230
|
+
})),
|
|
231
|
+
];
|
|
232
|
+
if (nextEntries.length > 0) {
|
|
233
|
+
needsToForkPeerContext = addEntriesToPeerContext(peerContext, nextEntries, node, graph.monorepo);
|
|
234
|
+
}
|
|
235
|
+
// returns all entries that need to be added to a forked
|
|
236
|
+
// context or undefined if the current context was updated directly
|
|
237
|
+
return needsToForkPeerContext ? nextEntries : undefined;
|
|
238
|
+
},
|
|
239
|
+
/**
|
|
240
|
+
* Try to resolve peer dependencies using already seen target
|
|
241
|
+
* values from the current peer context set.
|
|
242
|
+
*/
|
|
243
|
+
resolvePeerDeps: () => {
|
|
244
|
+
// iterate on the set of peer dependencies of the current node
|
|
245
|
+
// and try to resolve them from the existing peer context set,
|
|
246
|
+
// when possible, add them as edges in the graph right away, if not,
|
|
247
|
+
// then we move them back to the `nextDeps` list for processing
|
|
248
|
+
// along with the rest of the regular dependencies
|
|
249
|
+
for (const nextDep of nextPeerDeps.values()) {
|
|
250
|
+
const { spec, type } = nextDep;
|
|
251
|
+
if (type === 'peer' || type === 'peerOptional') {
|
|
252
|
+
// try to retrieve an entry for that peer dep from
|
|
253
|
+
// the current peer context set
|
|
254
|
+
const entry = peerContext.get(spec.final.name);
|
|
255
|
+
if (!node.edgesOut.has(spec.final.name) &&
|
|
256
|
+
entry?.target &&
|
|
257
|
+
satisfies(entry.target.id, spec, fromNode.location, fromNode.projectRoot, graph.monorepo)) {
|
|
258
|
+
// entry satisfied, create edge in the graph
|
|
259
|
+
graph.addEdge(type, spec, node, entry.target);
|
|
260
|
+
entry.specs.add(spec.final);
|
|
261
|
+
}
|
|
262
|
+
else if (type === 'peerOptional') {
|
|
263
|
+
// skip unsatisfied peerOptional dependencies,
|
|
264
|
+
// just create a dangling edge
|
|
265
|
+
graph.addEdge(type, spec, node);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
// could not satisfy from peer context, add to next deps
|
|
269
|
+
nextDeps.push(nextDep);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
/**
|
|
276
|
+
* Given an array of processed results for the current level dependencies
|
|
277
|
+
* being placed in the currently building ideal graph, traverse its direct
|
|
278
|
+
* dependencies and track peer dependencies in their appropriate peer context
|
|
279
|
+
* sets, forking as needed and resolving peer dependencies using suitable
|
|
280
|
+
* nodes already present in the graph if possible.
|
|
281
|
+
*/
|
|
282
|
+
export const postPlacementPeerCheck = (graph, sortedLevelResults) => {
|
|
283
|
+
// Update peer contexts in a sorted manner after processing all nodes
|
|
284
|
+
// at a given level to ensure deterministic behavior when it comes to
|
|
285
|
+
// forking new peer contexts
|
|
286
|
+
for (const childDepsToProcess of sortedLevelResults) {
|
|
287
|
+
const needsForking = new Map();
|
|
288
|
+
// first iterate on all child deps, adding entries to the current
|
|
289
|
+
// context and collect the information on which ones need forking
|
|
290
|
+
for (const childDep of childDepsToProcess) {
|
|
291
|
+
const needsFork = childDep.updateContext.putEntries();
|
|
292
|
+
if (needsFork) {
|
|
293
|
+
needsForking.set(childDep, needsFork);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// then iterate again, forking contexts as needed but also try to
|
|
297
|
+
// reuse the context of the previous sibling if possible
|
|
298
|
+
let prevContext;
|
|
299
|
+
for (const [childDep, nextEntries] of needsForking.entries()) {
|
|
300
|
+
if (prevContext &&
|
|
301
|
+
!checkEntriesToPeerContext(prevContext, nextEntries)) {
|
|
302
|
+
// the context of the previous sibling can be reused
|
|
303
|
+
addEntriesToPeerContext(prevContext, nextEntries, childDep.node, graph.monorepo);
|
|
304
|
+
childDep.peerContext = prevContext;
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
childDep.peerContext = forkPeerContext(graph, childDep.peerContext, nextEntries);
|
|
308
|
+
prevContext = childDep.peerContext;
|
|
309
|
+
}
|
|
310
|
+
// try to resolve peer dependencies now that
|
|
311
|
+
// the context is fully set up
|
|
312
|
+
for (const childDep of childDepsToProcess) {
|
|
313
|
+
childDep.updateContext.resolvePeerDeps();
|
|
314
|
+
childDep.deps = getOrderedDependencies(childDep.deps);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
//# sourceMappingURL=peers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peers.js","sourceRoot":"","sources":["../../../src/ideal/peers.ts"],"names":[],"mappings":"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","sourcesContent":["// helpers for managing peer dependency resolution\n// during the ideal graph building process.\n\nimport { intersects } from '@vltpkg/semver'\nimport { satisfies } from '@vltpkg/satisfies'\nimport { getDependencies } from '../dependencies.ts'\nimport { getOrderedDependencies } from './get-ordered-dependencies.ts'\nimport type { Spec, SpecOptions } from '@vltpkg/spec'\nimport type { DependencySaveType, Manifest } 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'\nimport type {\n PeerContext,\n PeerContextEntry,\n PeerContextEntryInput,\n ProcessPlacementResult,\n ProcessPlacementResultEntry,\n} from './types.ts'\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 `ṗ:${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 compatible, false otherwise.\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 if (\n // only able to check range intersections for registry types\n (spec.type === 'registry' &&\n (!spec.range ||\n !s.range ||\n !intersects(spec.range, s.range))) ||\n // also support types other than registry in case\n // they use the very same bareSpec value\n (spec.type !== 'registry' && spec.bareSpec !== s.bareSpec)\n ) {\n return true\n }\n }\n }\n return false\n}\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, 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 to see if any of the new entries to be added to the\n // provided peer context set conflicts with existing ones\n // if that's already the case we can skip processing them and\n // will return that a fork is needed right away\n if (checkEntriesToPeerContext(peerContext, entries)) return true\n\n // iterate on every entry to be added to the peer context set\n for (const { dependent, spec, target, type } of entries) {\n const name = target?.name ?? spec.final.name\n\n // if there's no existing entry, create one\n let entry = peerContext.get(name)\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 // perform an extra check that confirms the new spec does not\n // conflicts with existing specs in this entry, this handles the\n // case of adding sibling deps that conflicts with one another\n if (incompatibleSpecs(spec, entry)) return true\n\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 // we have a compatible entry that has a new, compatible target\n // so we need to update all dependents to point to the new target\n for (const dependents of entry.contextDependents) {\n const edge = dependents.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\n // otherwise sets the value in case it was nullish\n entry.target ??= target\n }\n\n // update specs and dependents values\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 // 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\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 * 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 queuedEntries: [...queueMap.values()],\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 */\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 putEntries: () => {\n // keep track of whether we need to fork the current peer context set\n let needsToForkPeerContext = false\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 addEntriesToPeerContext(\n peerContext,\n prevEntries,\n fromNode,\n graph.monorepo,\n )\n\n // add this node's direct dependencies next\n const nextEntries = [\n ...nextDeps.map(dep => ({ ...dep, dependent: node })),\n ...[...nextPeerDeps.values()].map(dep => ({\n ...dep,\n dependent: node,\n })),\n ]\n if (nextEntries.length > 0) {\n needsToForkPeerContext = addEntriesToPeerContext(\n peerContext,\n nextEntries,\n node,\n graph.monorepo,\n )\n }\n\n // returns all entries that need to be added to a forked\n // context or undefined if the current context was updated directly\n return needsToForkPeerContext ? nextEntries : undefined\n },\n\n /**\n * Try to resolve peer dependencies using already seen target\n * values from the current peer context set.\n */\n resolvePeerDeps: () => {\n // iterate on the set of peer dependencies of the current node\n // and try to resolve them from the existing peer context set,\n // when possible, add them as edges in the graph right away, if not,\n // then we move them back to the `nextDeps` list for processing\n // along with the rest of the regular dependencies\n for (const nextDep of nextPeerDeps.values()) {\n const { spec, type } = nextDep\n if (type === 'peer' || type === 'peerOptional') {\n // try to retrieve an entry for that peer dep from\n // the current peer context set\n const entry = peerContext.get(spec.final.name)\n if (\n !node.edgesOut.has(spec.final.name) &&\n entry?.target &&\n satisfies(\n entry.target.id,\n spec,\n fromNode.location,\n fromNode.projectRoot,\n graph.monorepo,\n )\n ) {\n // entry satisfied, create edge in the graph\n graph.addEdge(type, spec, node, entry.target)\n entry.specs.add(spec.final)\n } else if (type === 'peerOptional') {\n // skip unsatisfied peerOptional dependencies,\n // just create a dangling edge\n graph.addEdge(type, spec, node)\n } else {\n // could not satisfy from peer context, add to next deps\n nextDeps.push(nextDep)\n }\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 */\nexport const postPlacementPeerCheck = (\n graph: Graph,\n sortedLevelResults: ProcessPlacementResult[],\n) => {\n // Update peer contexts in a sorted manner after processing all nodes\n // at a given level to ensure deterministic behavior when it comes to\n // forking new peer contexts\n for (const childDepsToProcess of sortedLevelResults) {\n const needsForking = new Map<\n ProcessPlacementResultEntry,\n {\n dependent: Node\n spec: Spec\n type: DependencySaveType\n }[]\n >()\n // first iterate on all child deps, adding entries to the current\n // context and collect the information on which ones need forking\n for (const childDep of childDepsToProcess) {\n const needsFork = childDep.updateContext.putEntries()\n if (needsFork) {\n needsForking.set(childDep, needsFork)\n }\n }\n // then iterate again, forking contexts as needed but also try to\n // reuse the context of the previous sibling if possible\n let prevContext\n for (const [childDep, nextEntries] of needsForking.entries()) {\n if (\n prevContext &&\n !checkEntriesToPeerContext(prevContext, nextEntries)\n ) {\n // the context of the previous sibling can be reused\n addEntriesToPeerContext(\n prevContext,\n nextEntries,\n childDep.node,\n graph.monorepo,\n )\n childDep.peerContext = prevContext\n continue\n }\n childDep.peerContext = forkPeerContext(\n graph,\n childDep.peerContext,\n nextEntries,\n )\n prevContext = childDep.peerContext\n }\n // try to resolve peer dependencies now that\n // the context is fully set up\n for (const childDep of childDepsToProcess) {\n childDep.updateContext.resolvePeerDeps()\n childDep.deps = getOrderedDependencies(childDep.deps)\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { PathScurry } from 'path-scurry';
|
|
2
|
+
import type { PackageInfoClient } from '@vltpkg/package-info';
|
|
3
|
+
import type { SpecOptions } from '@vltpkg/spec';
|
|
4
|
+
import type { RollbackRemove } from '@vltpkg/rollback-remove';
|
|
5
|
+
import type { BuildIdealAddOptions, BuildIdealFromGraphOptions, BuildIdealRemoveOptions, TransientAddMap, TransientRemoveMap } from './types.ts';
|
|
6
|
+
import type { GraphModifier } from '../modifiers.ts';
|
|
7
|
+
import type { Graph } from '../graph.ts';
|
|
8
|
+
export type RefreshIdealGraphOptions = BuildIdealAddOptions & BuildIdealRemoveOptions & BuildIdealFromGraphOptions & SpecOptions & {
|
|
9
|
+
/**
|
|
10
|
+
* The graph modifiers helper object.
|
|
11
|
+
*/
|
|
12
|
+
modifiers?: GraphModifier;
|
|
13
|
+
/**
|
|
14
|
+
* A {@link PathScurry} instance based on the `projectRoot` path
|
|
15
|
+
*/
|
|
16
|
+
scurry: PathScurry;
|
|
17
|
+
/**
|
|
18
|
+
* A {@link PackageInfoClient} instance to read manifest info from.
|
|
19
|
+
*/
|
|
20
|
+
packageInfo: PackageInfoClient;
|
|
21
|
+
/**
|
|
22
|
+
* The actual graph to compare against for early extraction
|
|
23
|
+
*/
|
|
24
|
+
actual?: Graph;
|
|
25
|
+
/**
|
|
26
|
+
* A {@link RollbackRemove} instance to handle extraction rollbacks
|
|
27
|
+
*/
|
|
28
|
+
remover: RollbackRemove;
|
|
29
|
+
/**
|
|
30
|
+
* Dependencies to be added to non-importer nodes when they are placed.
|
|
31
|
+
* Used for nested folder dependencies that are not importers.
|
|
32
|
+
*/
|
|
33
|
+
transientAdd?: TransientAddMap;
|
|
34
|
+
/**
|
|
35
|
+
* Dependencies to be removed from non-importer nodes when they are placed.
|
|
36
|
+
* Used for nested folder dependencies that are not importers.
|
|
37
|
+
*/
|
|
38
|
+
transientRemove?: TransientRemoveMap;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Rebuilds the provided ideal graph.
|
|
42
|
+
*/
|
|
43
|
+
export declare const refreshIdealGraph: ({ add, graph, modifiers, packageInfo, scurry, actual, remove, remover, transientAdd, transientRemove, ...specOptions }: RefreshIdealGraphOptions) => Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Retrieve the next unique index for a peer context set.
|
|
46
|
+
*/
|
|
47
|
+
export declare const nextPeerContextIndex: () => number;
|
|
48
|
+
//# sourceMappingURL=refresh-ideal-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-ideal-graph.d.ts","sourceRoot":"","sources":["../../../src/ideal/refresh-ideal-graph.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,KAAK,EACV,oBAAoB,EACpB,0BAA0B,EAC1B,uBAAuB,EACvB,eAAe,EACf,kBAAkB,EACnB,MAAM,YAAY,CAAA;AAEnB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAEpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAGxC,MAAM,MAAM,wBAAwB,GAAG,oBAAoB,GACzD,uBAAuB,GACvB,0BAA0B,GAC1B,WAAW,GAAG;IACZ;;OAEG;IACH,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB;;OAEG;IACH,MAAM,EAAE,UAAU,CAAA;IAElB;;OAEG;IACH,WAAW,EAAE,iBAAiB,CAAA;IAE9B;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,CAAA;IAEd;;OAEG;IACH,OAAO,EAAE,cAAc,CAAA;IAEvB;;;OAGG;IACH,YAAY,CAAC,EAAE,eAAe,CAAA;IAE9B;;;OAGG;IACH,eAAe,CAAC,EAAE,kBAAkB,CAAA;CACrC,CAAA;AAkCH;;GAEG;AACH,eAAO,MAAM,iBAAiB,2HAY3B,wBAAwB,kBAkE1B,CAAA;AAMD;;GAEG;AACH,eAAO,MAAM,oBAAoB,cAA2B,CAAA"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { appendNodes } from "./append-nodes.js";
|
|
2
|
+
import { getNodeOrderedDependencies } from "./get-ordered-dependencies.js";
|
|
3
|
+
/**
|
|
4
|
+
* Returns an ordered list of importer nodes.
|
|
5
|
+
*/
|
|
6
|
+
const getOrderedImporters = (graph) => {
|
|
7
|
+
const orderedImporters = [...graph.importers].sort((a, b) => {
|
|
8
|
+
// sorts importers first by usage of peer deps
|
|
9
|
+
const aIsPeer = (a.manifest?.peerDependencies &&
|
|
10
|
+
Object.keys(a.manifest.peerDependencies).length > 0) ?
|
|
11
|
+
1
|
|
12
|
+
: 0;
|
|
13
|
+
const bIsPeer = (b.manifest?.peerDependencies &&
|
|
14
|
+
Object.keys(b.manifest.peerDependencies).length > 0) ?
|
|
15
|
+
1
|
|
16
|
+
: 0;
|
|
17
|
+
// importers with regular deps only first, with peer deps last
|
|
18
|
+
if (aIsPeer !== bIsPeer) {
|
|
19
|
+
return aIsPeer - bIsPeer;
|
|
20
|
+
}
|
|
21
|
+
// if both are in the same group, sort alphabetically by manifest name
|
|
22
|
+
return a.name.localeCompare(b.name, 'en');
|
|
23
|
+
});
|
|
24
|
+
return orderedImporters;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Rebuilds the provided ideal graph.
|
|
28
|
+
*/
|
|
29
|
+
export const refreshIdealGraph = async ({ add, graph, modifiers, packageInfo, scurry, actual, remove, remover, transientAdd, transientRemove, ...specOptions }) => {
|
|
30
|
+
const seen = new Set();
|
|
31
|
+
const extractPromises = [];
|
|
32
|
+
const seenExtracted = new Set();
|
|
33
|
+
// gets an ordered list of importers to ensure deterministic processing
|
|
34
|
+
const orderedImporters = getOrderedImporters(graph);
|
|
35
|
+
const depsPerImporter = new Map();
|
|
36
|
+
for (const importer of orderedImporters) {
|
|
37
|
+
// gets an ordered list of dependencies for this importer
|
|
38
|
+
// while also taking into account additions and removals
|
|
39
|
+
const deps = getNodeOrderedDependencies(importer, { add, remove });
|
|
40
|
+
depsPerImporter.set(importer, deps);
|
|
41
|
+
}
|
|
42
|
+
// removes all edges to start recalculating the graph
|
|
43
|
+
if (add.modifiedDependencies || remove.modifiedDependencies) {
|
|
44
|
+
graph.resetEdges();
|
|
45
|
+
}
|
|
46
|
+
// iterates on the list of dependencies per importer updating
|
|
47
|
+
// the graph using metadata fetch from the registry manifest files
|
|
48
|
+
for (const importer of orderedImporters) {
|
|
49
|
+
modifiers?.tryImporter(importer);
|
|
50
|
+
// gets a ref to the map of dependencies being added to this importer
|
|
51
|
+
const addedDeps = add.get(importer.id);
|
|
52
|
+
const deps = depsPerImporter.get(importer);
|
|
53
|
+
/* c8 ignore next */
|
|
54
|
+
if (!deps)
|
|
55
|
+
continue;
|
|
56
|
+
// gets a ref to the list of modifier functions for this set of deps
|
|
57
|
+
const modifierRefs = modifiers?.tryDependencies(importer, deps);
|
|
58
|
+
// Add new nodes for packages defined in the dependencies list fetching
|
|
59
|
+
// metadata from the registry manifests and updating the graph
|
|
60
|
+
await appendNodes(packageInfo, graph, importer, deps, scurry, specOptions, seen, addedDeps, modifiers, modifierRefs, extractPromises, actual, seenExtracted, remover, transientAdd, transientRemove);
|
|
61
|
+
}
|
|
62
|
+
// set default node locations, if possible
|
|
63
|
+
for (const node of graph.nodes.values()) {
|
|
64
|
+
node.setDefaultLocation();
|
|
65
|
+
}
|
|
66
|
+
// Wait for all extraction promises to complete
|
|
67
|
+
if (extractPromises.length > 0) {
|
|
68
|
+
await Promise.all(extractPromises);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Global index to assign unique ids used to track peer context sets.
|
|
73
|
+
*/
|
|
74
|
+
let peerContextIndex = 0;
|
|
75
|
+
/**
|
|
76
|
+
* Retrieve the next unique index for a peer context set.
|
|
77
|
+
*/
|
|
78
|
+
export const nextPeerContextIndex = () => peerContextIndex++;
|
|
79
|
+
//# sourceMappingURL=refresh-ideal-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-ideal-graph.js","sourceRoot":"","sources":["../../../src/ideal/refresh-ideal-graph.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendNodes } from './append-nodes.ts'\nimport { getNodeOrderedDependencies } from './get-ordered-dependencies.ts'\nimport type { PathScurry } from 'path-scurry'\nimport type { DepID } from '@vltpkg/dep-id'\nimport type { PackageInfoClient } from '@vltpkg/package-info'\nimport type { SpecOptions } from '@vltpkg/spec'\nimport type { RollbackRemove } from '@vltpkg/rollback-remove'\nimport type {\n BuildIdealAddOptions,\n BuildIdealFromGraphOptions,\n BuildIdealRemoveOptions,\n TransientAddMap,\n TransientRemoveMap,\n} from './types.ts'\nimport type { Dependency } from '../dependencies.ts'\nimport type { GraphModifier } from '../modifiers.ts'\nimport type { ExtractResult } from '../reify/extract-node.ts'\nimport type { Graph } from '../graph.ts'\nimport type { Node } from '../node.ts'\n\nexport type RefreshIdealGraphOptions = BuildIdealAddOptions &\n BuildIdealRemoveOptions &\n BuildIdealFromGraphOptions &\n SpecOptions & {\n /**\n * The graph modifiers helper object.\n */\n modifiers?: GraphModifier\n /**\n * A {@link PathScurry} instance based on the `projectRoot` path\n */\n scurry: PathScurry\n\n /**\n * A {@link PackageInfoClient} instance to read manifest info from.\n */\n packageInfo: PackageInfoClient\n\n /**\n * The actual graph to compare against for early extraction\n */\n actual?: Graph\n\n /**\n * A {@link RollbackRemove} instance to handle extraction rollbacks\n */\n remover: RollbackRemove\n\n /**\n * Dependencies to be added to non-importer nodes when they are placed.\n * Used for nested folder dependencies that are not importers.\n */\n transientAdd?: TransientAddMap\n\n /**\n * Dependencies to be removed from non-importer nodes when they are placed.\n * Used for nested folder dependencies that are not importers.\n */\n transientRemove?: TransientRemoveMap\n }\n\n/**\n * Returns an ordered list of importer nodes.\n */\nconst getOrderedImporters = (graph: Graph): Node[] => {\n const orderedImporters = [...graph.importers].sort((a, b) => {\n // sorts importers first by usage of peer deps\n const aIsPeer =\n (\n a.manifest?.peerDependencies &&\n Object.keys(a.manifest.peerDependencies).length > 0\n ) ?\n 1\n : 0\n const bIsPeer =\n (\n b.manifest?.peerDependencies &&\n Object.keys(b.manifest.peerDependencies).length > 0\n ) ?\n 1\n : 0\n\n // importers with regular deps only first, with peer deps last\n if (aIsPeer !== bIsPeer) {\n return aIsPeer - bIsPeer\n }\n\n // if both are in the same group, sort alphabetically by manifest name\n return a.name.localeCompare(b.name, 'en')\n })\n return orderedImporters\n}\n\n/**\n * Rebuilds the provided ideal graph.\n */\nexport const refreshIdealGraph = async ({\n add,\n graph,\n modifiers,\n packageInfo,\n scurry,\n actual,\n remove,\n remover,\n transientAdd,\n transientRemove,\n ...specOptions\n}: RefreshIdealGraphOptions) => {\n const seen = new Set<DepID>()\n const extractPromises: Promise<ExtractResult>[] = []\n const seenExtracted = new Set<DepID>()\n\n // gets an ordered list of importers to ensure deterministic processing\n const orderedImporters = getOrderedImporters(graph)\n const depsPerImporter = new Map<Node, Dependency[]>()\n for (const importer of orderedImporters) {\n // gets an ordered list of dependencies for this importer\n // while also taking into account additions and removals\n const deps = getNodeOrderedDependencies(importer, { add, remove })\n depsPerImporter.set(importer, deps)\n }\n\n // removes all edges to start recalculating the graph\n if (add.modifiedDependencies || remove.modifiedDependencies) {\n graph.resetEdges()\n }\n\n // iterates on the list of dependencies per importer updating\n // the graph using metadata fetch from the registry manifest files\n for (const importer of orderedImporters) {\n modifiers?.tryImporter(importer)\n\n // gets a ref to the map of dependencies being added to this importer\n const addedDeps = add.get(importer.id)\n\n const deps = depsPerImporter.get(importer)\n /* c8 ignore next */\n if (!deps) continue\n\n // gets a ref to the list of modifier functions for this set of deps\n const modifierRefs = modifiers?.tryDependencies(importer, deps)\n\n // Add new nodes for packages defined in the dependencies list fetching\n // metadata from the registry manifests and updating the graph\n await appendNodes(\n packageInfo,\n graph,\n importer,\n deps,\n scurry,\n specOptions,\n seen,\n addedDeps,\n modifiers,\n modifierRefs,\n extractPromises,\n actual,\n seenExtracted,\n remover,\n transientAdd,\n transientRemove,\n )\n }\n\n // set default node locations, if possible\n for (const node of graph.nodes.values()) {\n node.setDefaultLocation()\n }\n\n // Wait for all extraction promises to complete\n if (extractPromises.length > 0) {\n await Promise.all(extractPromises)\n }\n}\n\n/**\n * Global index to assign unique ids used to track peer context sets.\n */\nlet peerContextIndex = 0\n/**\n * Retrieve the next unique index for a peer context set.\n */\nexport const nextPeerContextIndex = () => peerContextIndex++\n"]}
|