@vltpkg/graph 1.0.2 → 1.0.3
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/dist/actual/load.d.ts +10 -0
- package/dist/browser.d.ts +1 -1
- package/dist/ideal/peers.d.ts +11 -0
- package/dist/ideal/peers.js +27 -8
- package/dist/ideal/types.d.ts +6 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/install.js +8 -1
- package/dist/lockfile/load-edges.d.ts +6 -2
- package/dist/lockfile/load-edges.js +15 -2
- package/dist/lockfile/load-nodes.js +1 -0
- package/dist/lockfile/load.d.ts +10 -1
- package/dist/lockfile/load.js +11 -2
- package/dist/lockfile/types.d.ts +6 -0
- package/dist/node.d.ts +5 -0
- package/dist/node.js +5 -0
- package/dist/reify/extract-node.js +8 -10
- package/package.json +21 -21
package/dist/actual/load.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { DepID } from '@vltpkg/dep-id';
|
|
|
4
4
|
import type { PackageJson } from '@vltpkg/package-json';
|
|
5
5
|
import type { SpecOptions } from '@vltpkg/spec';
|
|
6
6
|
import type { NormalizedManifest } from '@vltpkg/types';
|
|
7
|
+
import type { LockfileData, SpecCache } from '../lockfile/types.ts';
|
|
7
8
|
import type { Monorepo } from '@vltpkg/workspaces';
|
|
8
9
|
import type { Path, PathScurry } from 'path-scurry';
|
|
9
10
|
import type { GraphModifier } from '../modifiers.ts';
|
|
@@ -65,6 +66,15 @@ export type LoadOptions = SpecOptions & {
|
|
|
65
66
|
* operations. Skips package extraction, filesystem operations, and hidden lockfile saves.
|
|
66
67
|
*/
|
|
67
68
|
lockfileOnly?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Shared intern cache for parsed lockfile specs.
|
|
71
|
+
*/
|
|
72
|
+
specCache?: SpecCache;
|
|
73
|
+
/**
|
|
74
|
+
* Already-parsed main lockfile data. When set, ideal build skips
|
|
75
|
+
* re-reading `vlt-lock.json`.
|
|
76
|
+
*/
|
|
77
|
+
lockfileData?: LockfileData;
|
|
68
78
|
};
|
|
69
79
|
export type ReadEntry = {
|
|
70
80
|
alias: string;
|
package/dist/browser.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { stringifyNode } from './stringify-node.ts';
|
|
|
5
5
|
export type { LoadResult, TransferData, } from './transfer-data/load.ts';
|
|
6
6
|
export * from './virtual-root.ts';
|
|
7
7
|
declare const lockfile: {
|
|
8
|
-
loadEdges: (graph: import("@vltpkg/types").GraphLike, edges: import("./lockfile/types.ts").LockfileData["edges"], options: import("@vltpkg/spec").SpecOptions) => void;
|
|
8
|
+
loadEdges: (graph: import("@vltpkg/types").GraphLike, edges: import("./lockfile/types.ts").LockfileData["edges"], options: import("@vltpkg/spec").SpecOptions, cache?: import("./lockfile/load-edges.ts").LoadEdgesCache) => void;
|
|
9
9
|
loadNodes: (graph: import("@vltpkg/types").GraphLike, nodes: import("./lockfile/types.ts").LockfileData["nodes"], options: import("@vltpkg/spec").SpecOptions, actual?: import("@vltpkg/types").GraphLike, throwOnMissingManifest?: boolean) => void;
|
|
10
10
|
};
|
|
11
11
|
declare const transfer: {
|
package/dist/ideal/peers.d.ts
CHANGED
|
@@ -41,6 +41,17 @@ export declare const checkPeerEdgesCompatible: (existingNode: Node, fromNode: No
|
|
|
41
41
|
* Retrieve a unique hash value for a given peer context set.
|
|
42
42
|
*/
|
|
43
43
|
export declare const retrievePeerContextHash: (peerContext: PeerContext | undefined) => string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Generate a dedupe key for a spec stored in a peer context entry's
|
|
46
|
+
* `specs` map. Two specs with the same key are interchangeable for the
|
|
47
|
+
* purposes of `incompatibleSpecs()`/`satisfies()` checks, so only one
|
|
48
|
+
* needs to be retained regardless of how many dependents contribute it.
|
|
49
|
+
*
|
|
50
|
+
* Keyed on type + textual spec (name@bareSpec) + registry, since specs
|
|
51
|
+
* that are textually identical but resolve against different registries
|
|
52
|
+
* are not interchangeable.
|
|
53
|
+
*/
|
|
54
|
+
export declare const peerSpecKey: (spec: Spec) => string;
|
|
44
55
|
/**
|
|
45
56
|
* Checks if a given spec is compatible with the specs already
|
|
46
57
|
* assigned to a peer context entry.
|
package/dist/ideal/peers.js
CHANGED
|
@@ -179,7 +179,7 @@ export const checkPeerEdgesCompatible = (existingNode, fromNode, peerContext, gr
|
|
|
179
179
|
const existingTarget = existingEdge.to;
|
|
180
180
|
const existingTargetSatisfiesPeer = satisfiesNodeSpec(existingTarget, peerSpec);
|
|
181
181
|
if (existingTargetSatisfiesPeer &&
|
|
182
|
-
nodeSatisfiesAll(existingTarget, contextEntry.specs)) {
|
|
182
|
+
nodeSatisfiesAll(existingTarget, contextEntry.specs.values())) {
|
|
183
183
|
continue; // Truly no conflict
|
|
184
184
|
}
|
|
185
185
|
const result = buildIncompatibleResult(contextEntry.target, peerSpec, contextEntry.type, fromNode, graph);
|
|
@@ -259,6 +259,20 @@ export const retrievePeerContextHash = (peerContext) => {
|
|
|
259
259
|
return undefined;
|
|
260
260
|
return `peer.${peerContext.index}`;
|
|
261
261
|
};
|
|
262
|
+
/**
|
|
263
|
+
* Generate a dedupe key for a spec stored in a peer context entry's
|
|
264
|
+
* `specs` map. Two specs with the same key are interchangeable for the
|
|
265
|
+
* purposes of `incompatibleSpecs()`/`satisfies()` checks, so only one
|
|
266
|
+
* needs to be retained regardless of how many dependents contribute it.
|
|
267
|
+
*
|
|
268
|
+
* Keyed on type + textual spec (name@bareSpec) + registry, since specs
|
|
269
|
+
* that are textually identical but resolve against different registries
|
|
270
|
+
* are not interchangeable.
|
|
271
|
+
*/
|
|
272
|
+
export const peerSpecKey = (spec) => {
|
|
273
|
+
const f = spec.final;
|
|
274
|
+
return `${f.type}\0${String(f)}\0${f.registry ?? ''}`;
|
|
275
|
+
};
|
|
262
276
|
/**
|
|
263
277
|
* Checks if a given spec is compatible with the specs already
|
|
264
278
|
* assigned to a peer context entry.
|
|
@@ -276,7 +290,7 @@ export const retrievePeerContextHash = (peerContext) => {
|
|
|
276
290
|
*/
|
|
277
291
|
export const incompatibleSpecs = (spec, entry) => {
|
|
278
292
|
if (entry.specs.size > 0) {
|
|
279
|
-
for (const s_ of entry.specs) {
|
|
293
|
+
for (const s_ of entry.specs.values()) {
|
|
280
294
|
const s = s_.final;
|
|
281
295
|
if (
|
|
282
296
|
// Registry types: check semver range intersection
|
|
@@ -337,7 +351,7 @@ export const addEntriesToPeerContext = (peerContext, entries, fromNode, monorepo
|
|
|
337
351
|
if (!entry) {
|
|
338
352
|
entry = {
|
|
339
353
|
active: true,
|
|
340
|
-
specs: new
|
|
354
|
+
specs: new Map([[peerSpecKey(spec), spec]]),
|
|
341
355
|
target,
|
|
342
356
|
type,
|
|
343
357
|
contextDependents: new Set(),
|
|
@@ -352,7 +366,7 @@ export const addEntriesToPeerContext = (peerContext, entries, fromNode, monorepo
|
|
|
352
366
|
return true;
|
|
353
367
|
// update target if compatible with all specs
|
|
354
368
|
if (target &&
|
|
355
|
-
[...entry.specs].every(s => satisfies(target.id, s, fromNode.location, fromNode.projectRoot, monorepo))) {
|
|
369
|
+
[...entry.specs.values()].every(s => satisfies(target.id, s, fromNode.location, fromNode.projectRoot, monorepo))) {
|
|
356
370
|
if (target.id !== entry.target?.id &&
|
|
357
371
|
target.version !== entry.target?.version) {
|
|
358
372
|
// update dependents to point to new target
|
|
@@ -368,7 +382,9 @@ export const addEntriesToPeerContext = (peerContext, entries, fromNode, monorepo
|
|
|
368
382
|
}
|
|
369
383
|
entry.target ??= target;
|
|
370
384
|
}
|
|
371
|
-
|
|
385
|
+
const specKey = peerSpecKey(spec);
|
|
386
|
+
if (!entry.specs.has(specKey))
|
|
387
|
+
entry.specs.set(specKey, spec);
|
|
372
388
|
if (dependent)
|
|
373
389
|
entry.contextDependents.add(dependent);
|
|
374
390
|
}
|
|
@@ -395,7 +411,7 @@ export const forkPeerContext = (graph, peerContext, entries) => {
|
|
|
395
411
|
for (const [name, entry] of peerContext.entries()) {
|
|
396
412
|
nextPeerContext.set(name, {
|
|
397
413
|
active: false,
|
|
398
|
-
specs: new
|
|
414
|
+
specs: new Map(entry.specs),
|
|
399
415
|
target: undefined,
|
|
400
416
|
type: entry.type,
|
|
401
417
|
contextDependents: new Set(entry.contextDependents),
|
|
@@ -408,7 +424,7 @@ export const forkPeerContext = (graph, peerContext, entries) => {
|
|
|
408
424
|
const name = target?.name /* c8 ignore next */ ?? spec.final.name;
|
|
409
425
|
const newEntry = {
|
|
410
426
|
active: true,
|
|
411
|
-
specs: new
|
|
427
|
+
specs: new Map([[peerSpecKey(spec), spec]]),
|
|
412
428
|
target,
|
|
413
429
|
type,
|
|
414
430
|
contextDependents: dependent ? new Set([dependent]) : new Set(),
|
|
@@ -610,7 +626,10 @@ export const endPeerPlacement = (peerContext, nextDeps, nextPeerDeps, graph, spe
|
|
|
610
626
|
entry?.target &&
|
|
611
627
|
nodeSatisfiesSpec(entry.target, spec, fromNode, graph)) {
|
|
612
628
|
graph.addEdge(type, spec, node, entry.target);
|
|
613
|
-
|
|
629
|
+
const finalKey = peerSpecKey(spec.final);
|
|
630
|
+
if (!entry.specs.has(finalKey)) {
|
|
631
|
+
entry.specs.set(finalKey, spec.final);
|
|
632
|
+
}
|
|
614
633
|
continue;
|
|
615
634
|
}
|
|
616
635
|
// PRIORITY 4: Fallback - add to nextDeps or create dangling edge
|
package/dist/ideal/types.d.ts
CHANGED
|
@@ -81,8 +81,12 @@ export type PeerContextEntry = {
|
|
|
81
81
|
* peer context set and should not be considered for resolution.
|
|
82
82
|
*/
|
|
83
83
|
active: boolean;
|
|
84
|
-
/**
|
|
85
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Full Spec objects that are part of this peer context entry, keyed by
|
|
86
|
+
* `peerSpecKey()` so textually identical specs collapse into one entry
|
|
87
|
+
* instead of piling up per dependent.
|
|
88
|
+
*/
|
|
89
|
+
specs: Map<string, Spec>;
|
|
86
90
|
/** The target Node that satisfies all specs for this peer context entry */
|
|
87
91
|
target: Node | undefined;
|
|
88
92
|
/** The type of dependency this entry represents */
|
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,8 @@ export declare const actual: {
|
|
|
22
22
|
import type { LoadOptions as LockfileLoadOptions } from './lockfile/load.ts';
|
|
23
23
|
export declare const lockfile: {
|
|
24
24
|
load: (options: LockfileLoadOptions) => import("./graph.ts").Graph;
|
|
25
|
-
|
|
25
|
+
loadData: (projectRoot: string, lockfilePath?: string) => import("./lockfile/types.ts").LockfileData;
|
|
26
|
+
loadEdges: (graph: import("@vltpkg/types").GraphLike, edges: import("./lockfile/types.ts").LockfileData["edges"], options: import("@vltpkg/spec").SpecOptions, cache?: import("./lockfile/load-edges.ts").LoadEdgesCache) => void;
|
|
26
27
|
loadNodes: (graph: import("@vltpkg/types").GraphLike, nodes: import("./lockfile/types.ts").LockfileData["nodes"], options: import("@vltpkg/spec").SpecOptions, actual?: import("@vltpkg/types").GraphLike, throwOnMissingManifest?: boolean) => void;
|
|
27
28
|
save: (options: Omit<import("./lockfile/save.ts").SaveOptions, "saveManifests">) => void;
|
|
28
29
|
};
|
package/dist/index.js
CHANGED
|
@@ -17,12 +17,13 @@ export * from "./modifiers.js";
|
|
|
17
17
|
export * from "./virtual-root.js";
|
|
18
18
|
import { load as actualLoad } from "./actual/load.js";
|
|
19
19
|
export const actual = { load: actualLoad };
|
|
20
|
-
import { load as lockfileLoad } from "./lockfile/load.js";
|
|
20
|
+
import { load as lockfileLoad, loadData as lockfileLoadData, } from "./lockfile/load.js";
|
|
21
21
|
import { loadEdges } from "./lockfile/load-edges.js";
|
|
22
22
|
import { loadNodes } from "./lockfile/load-nodes.js";
|
|
23
23
|
import { save } from "./lockfile/save.js";
|
|
24
24
|
export const lockfile = {
|
|
25
25
|
load: lockfileLoad,
|
|
26
|
+
loadData: lockfileLoadData,
|
|
26
27
|
loadEdges,
|
|
27
28
|
loadNodes,
|
|
28
29
|
save,
|
package/dist/install.js
CHANGED
|
@@ -9,7 +9,7 @@ import { getDependencies } from "./dependencies.js";
|
|
|
9
9
|
import { RollbackRemove } from '@vltpkg/rollback-remove';
|
|
10
10
|
import { existsSync, rmSync } from 'node:fs';
|
|
11
11
|
import { resolve } from 'node:path';
|
|
12
|
-
import { load as loadVirtual } from "./lockfile/load.js";
|
|
12
|
+
import { load as loadVirtual, loadData } from "./lockfile/load.js";
|
|
13
13
|
import { getImporterSpecs } from "./ideal/get-importer-specs.js";
|
|
14
14
|
import { lockfile } from "./index.js";
|
|
15
15
|
import { updatePackageJson } from "./reify/update-importers-package-json.js";
|
|
@@ -50,6 +50,8 @@ export const install = async (options, add) => {
|
|
|
50
50
|
packageJson: options.packageJson,
|
|
51
51
|
scurry: options.scurry,
|
|
52
52
|
});
|
|
53
|
+
const specCache = new Map();
|
|
54
|
+
const lockfileData = options.frozenLockfile ? loadData(options.projectRoot) : undefined;
|
|
53
55
|
if (options.frozenLockfile) {
|
|
54
56
|
// validates no add/remove operations are requested
|
|
55
57
|
if (add?.modifiedDependencies) {
|
|
@@ -65,6 +67,8 @@ export const install = async (options, add) => {
|
|
|
65
67
|
...options,
|
|
66
68
|
mainManifest,
|
|
67
69
|
monorepo: fullMonorepo,
|
|
70
|
+
specCache,
|
|
71
|
+
lockfileData,
|
|
68
72
|
});
|
|
69
73
|
const emptyAdd = Object.assign(new Map(), { modifiedDependencies: false });
|
|
70
74
|
const emptyRemove = Object.assign(new Map(), {
|
|
@@ -149,6 +153,7 @@ export const install = async (options, add) => {
|
|
|
149
153
|
loadManifests: true,
|
|
150
154
|
modifiers: undefined, // modifiers should not be used here
|
|
151
155
|
monorepo: fullMonorepo,
|
|
156
|
+
specCache,
|
|
152
157
|
});
|
|
153
158
|
// if the actual graph has no dependencies, it's simpler to ignore it
|
|
154
159
|
// this allows us to check for its availability later on for properly
|
|
@@ -166,6 +171,8 @@ export const install = async (options, add) => {
|
|
|
166
171
|
remove,
|
|
167
172
|
remover,
|
|
168
173
|
monorepo: fullMonorepo,
|
|
174
|
+
specCache,
|
|
175
|
+
lockfileData,
|
|
169
176
|
});
|
|
170
177
|
// If lockfileOnly is enabled, skip reify and only save the lockfile
|
|
171
178
|
if (options.lockfileOnly) {
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { Spec } from '@vltpkg/spec/browser';
|
|
2
2
|
import type { SpecOptions } from '@vltpkg/spec/browser';
|
|
3
3
|
import type { DependencyTypeShort, GraphLike, NodeLike } from '@vltpkg/types';
|
|
4
|
-
import type { LockfileData } from './types.ts';
|
|
4
|
+
import type { LockfileData, SpecCache } from './types.ts';
|
|
5
|
+
export type LoadEdgesCache = {
|
|
6
|
+
specCache: SpecCache;
|
|
7
|
+
prefix: string;
|
|
8
|
+
};
|
|
5
9
|
export type ProcessingEdge = {
|
|
6
10
|
fromNode: NodeLike;
|
|
7
11
|
toNode: NodeLike | undefined;
|
|
8
12
|
depType: DependencyTypeShort;
|
|
9
13
|
spec: Spec;
|
|
10
14
|
};
|
|
11
|
-
export declare const loadEdges: (graph: GraphLike, edges: LockfileData["edges"], options: SpecOptions) => void;
|
|
15
|
+
export declare const loadEdges: (graph: GraphLike, edges: LockfileData["edges"], options: SpecOptions, cache?: LoadEdgesCache) => void;
|
|
@@ -26,7 +26,20 @@ const retrieveNodeFromGraph = (key, value, graph, fromId, seenNodes) => {
|
|
|
26
26
|
}
|
|
27
27
|
return foundNode;
|
|
28
28
|
};
|
|
29
|
-
|
|
29
|
+
const parseEdgeSpec = (specName, bareSpec, options, cache) => {
|
|
30
|
+
// graph.addEdge mutates name/spec on '(unknown)' instances
|
|
31
|
+
if (!cache || specName === '(unknown)') {
|
|
32
|
+
return Spec.parse(specName, bareSpec, options);
|
|
33
|
+
}
|
|
34
|
+
const key = `${cache.prefix}\0${specName}\0${bareSpec}`;
|
|
35
|
+
const cached = cache.specCache.get(key);
|
|
36
|
+
if (cached)
|
|
37
|
+
return cached;
|
|
38
|
+
const spec = Spec.parse(specName, bareSpec, options);
|
|
39
|
+
cache.specCache.set(key, spec);
|
|
40
|
+
return spec;
|
|
41
|
+
};
|
|
42
|
+
export const loadEdges = (graph, edges, options, cache) => {
|
|
30
43
|
const entries = Object.entries(edges);
|
|
31
44
|
const edgeCount = entries.length;
|
|
32
45
|
// Only use optimizations for non-trivial graphs
|
|
@@ -93,7 +106,7 @@ export const loadEdges = (graph, edges, options) => {
|
|
|
93
106
|
// loaded), so overriding here would always inject `undefined`
|
|
94
107
|
// and silently revert to the default npm registry.
|
|
95
108
|
// See vltpkg/vltpkg#1580.
|
|
96
|
-
const spec =
|
|
109
|
+
const spec = parseEdgeSpec(specName, valRest.substring(0, vrSplit), options, cache);
|
|
97
110
|
if (useOptimizations) {
|
|
98
111
|
edgeProcessingQueue.push({
|
|
99
112
|
fromNode,
|
|
@@ -73,6 +73,7 @@ export const loadNodes = (graph, nodes, options, actual, throwOnMissingManifest)
|
|
|
73
73
|
node.integrity = integrity ?? referenceNode?.integrity;
|
|
74
74
|
node.resolved =
|
|
75
75
|
type === 'remote' ? filepath : ((resolved ?? referenceNode?.resolved));
|
|
76
|
+
node.resolvedFromLockfile = !!(node.integrity && node.resolved);
|
|
76
77
|
node.projectRoot = graph.projectRoot;
|
|
77
78
|
if (!node.resolved)
|
|
78
79
|
node.setResolved();
|
package/dist/lockfile/load.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { Graph } from '../graph.ts';
|
|
|
4
4
|
import type { PathScurry } from 'path-scurry';
|
|
5
5
|
import type { NormalizedManifest } from '@vltpkg/types';
|
|
6
6
|
import type { SpecOptions } from '@vltpkg/spec';
|
|
7
|
-
import type { LockfileData } from './types.ts';
|
|
7
|
+
import type { LockfileData, SpecCache } from './types.ts';
|
|
8
8
|
import type { GraphModifier } from '../modifiers.ts';
|
|
9
9
|
export type LoadOptions = SpecOptions & {
|
|
10
10
|
/**
|
|
@@ -39,7 +39,16 @@ export type LoadOptions = SpecOptions & {
|
|
|
39
39
|
* Whether to throw an error if a manifest is missing when loading nodes.
|
|
40
40
|
*/
|
|
41
41
|
throwOnMissingManifest?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Shared intern cache for parsed lockfile specs.
|
|
44
|
+
*/
|
|
45
|
+
specCache?: SpecCache;
|
|
46
|
+
/**
|
|
47
|
+
* Already-parsed lockfile data. When set, skips the filesystem read.
|
|
48
|
+
*/
|
|
49
|
+
lockfileData?: LockfileData;
|
|
42
50
|
};
|
|
51
|
+
export declare const loadData: (projectRoot: string, lockfilePath?: string) => LockfileData;
|
|
43
52
|
export declare const load: (options: LoadOptions) => Graph;
|
|
44
53
|
export declare const loadHidden: (options: LoadOptions) => Graph;
|
|
45
54
|
export declare const loadObject: (options: LoadOptions, lockfileData: Omit<LockfileData, "options" | "lockfileVersion"> & Partial<Pick<LockfileData, "options" | "lockfileVersion">>) => Graph;
|
package/dist/lockfile/load.js
CHANGED
|
@@ -12,9 +12,11 @@ import { LOCKFILE_VERSION } from "./types.js";
|
|
|
12
12
|
const loadLockfile = (projectRoot, lockfilePath) => JSON.parse(readFileSync(resolve(projectRoot, lockfilePath), {
|
|
13
13
|
encoding: 'utf8',
|
|
14
14
|
}));
|
|
15
|
+
export const loadData = (projectRoot, lockfilePath = 'vlt-lock.json') => loadLockfile(projectRoot, lockfilePath);
|
|
15
16
|
export const load = (options) => {
|
|
16
17
|
const { projectRoot } = options;
|
|
17
|
-
return loadObject(options,
|
|
18
|
+
return loadObject(options, options.lockfileData ??
|
|
19
|
+
loadLockfile(projectRoot, 'vlt-lock.json'));
|
|
18
20
|
};
|
|
19
21
|
export const loadHidden = (options) => {
|
|
20
22
|
const { projectRoot } = options;
|
|
@@ -159,7 +161,14 @@ export const loadObject = (options, lockfileData) => {
|
|
|
159
161
|
});
|
|
160
162
|
graph.optionsChanged = optionsChanged;
|
|
161
163
|
loadNodes(graph, lockfileData.nodes, mergedOptions, options.actual, options.throwOnMissingManifest);
|
|
162
|
-
|
|
164
|
+
// Skip interning when modifiers are active — they mutate Spec.overridden
|
|
165
|
+
const specCache = options.modifiers || !options.specCache ?
|
|
166
|
+
undefined
|
|
167
|
+
: {
|
|
168
|
+
specCache: options.specCache,
|
|
169
|
+
prefix: JSON.stringify(lockfileOptions),
|
|
170
|
+
};
|
|
171
|
+
loadEdges(graph, lockfileData.edges, mergedOptions, specCache);
|
|
163
172
|
// hydrate missing node-level registry data
|
|
164
173
|
for (const node of graph.nodes.values()) {
|
|
165
174
|
const [firstEdge] = node.edgesIn;
|
package/dist/lockfile/types.d.ts
CHANGED
|
@@ -25,6 +25,12 @@ export type LockfileData = {
|
|
|
25
25
|
nodes: Record<DepID, LockfileNode>;
|
|
26
26
|
edges: LockfileEdges;
|
|
27
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* Per-install intern cache for parsed lockfile specs. Shared across
|
|
30
|
+
* hidden + main lockfile loads so identical (name, bareSpec) pairs
|
|
31
|
+
* reuse one Spec instance.
|
|
32
|
+
*/
|
|
33
|
+
export type SpecCache = Map<string, Spec>;
|
|
28
34
|
/**
|
|
29
35
|
* Current lockfile format version.
|
|
30
36
|
* Only lockfiles with matching version are considered valid.
|
package/dist/node.d.ts
CHANGED
|
@@ -76,6 +76,11 @@ export declare class Node implements NodeLike {
|
|
|
76
76
|
* The manifest integrity value.
|
|
77
77
|
*/
|
|
78
78
|
integrity?: Integrity;
|
|
79
|
+
/**
|
|
80
|
+
* True when `integrity` and `resolved` came from a lockfile, i.e. they were
|
|
81
|
+
* verified by the install that wrote them.
|
|
82
|
+
*/
|
|
83
|
+
resolvedFromLockfile: boolean;
|
|
79
84
|
/**
|
|
80
85
|
* The manifest this node represents in the graph.
|
|
81
86
|
*/
|
package/dist/node.js
CHANGED
|
@@ -101,6 +101,11 @@ export class Node {
|
|
|
101
101
|
* The manifest integrity value.
|
|
102
102
|
*/
|
|
103
103
|
integrity;
|
|
104
|
+
/**
|
|
105
|
+
* True when `integrity` and `resolved` came from a lockfile, i.e. they were
|
|
106
|
+
* verified by the install that wrote them.
|
|
107
|
+
*/
|
|
108
|
+
resolvedFromLockfile = false;
|
|
104
109
|
/**
|
|
105
110
|
* The manifest this node represents in the graph.
|
|
106
111
|
*/
|
|
@@ -38,15 +38,17 @@ export const extractNode = async (node, scurry, remover, options, packageInfo, d
|
|
|
38
38
|
error: new Error('Platform check failed or package deprecated'),
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
+
const extractOptions = {
|
|
42
|
+
from,
|
|
43
|
+
integrity,
|
|
44
|
+
resolved,
|
|
45
|
+
fromLockfile: node.resolvedFromLockfile,
|
|
46
|
+
};
|
|
41
47
|
try {
|
|
42
48
|
await remover.rm(target);
|
|
43
49
|
if (removeOptionalFailedNode) {
|
|
44
50
|
try {
|
|
45
|
-
const result = await packageInfo.extract(spec, target,
|
|
46
|
-
from,
|
|
47
|
-
integrity,
|
|
48
|
-
resolved,
|
|
49
|
-
});
|
|
51
|
+
const result = await packageInfo.extract(spec, target, extractOptions);
|
|
50
52
|
// Store computed integrity for git/remote deps
|
|
51
53
|
if (result.integrity && !node.integrity) {
|
|
52
54
|
node.integrity = result.integrity;
|
|
@@ -59,11 +61,7 @@ export const extractNode = async (node, scurry, remover, options, packageInfo, d
|
|
|
59
61
|
}
|
|
60
62
|
}
|
|
61
63
|
else {
|
|
62
|
-
const result = await packageInfo.extract(spec, target,
|
|
63
|
-
from,
|
|
64
|
-
integrity,
|
|
65
|
-
resolved,
|
|
66
|
-
});
|
|
64
|
+
const result = await packageInfo.extract(spec, target, extractOptions);
|
|
67
65
|
// Store computed integrity for git/remote deps
|
|
68
66
|
if (result.integrity && !node.integrity) {
|
|
69
67
|
node.integrity = result.integrity;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vltpkg/graph",
|
|
3
3
|
"description": "A library that helps understanding & expressing what happens on an install",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.3",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/vltpkg/vltpkg.git",
|
|
@@ -13,26 +13,26 @@
|
|
|
13
13
|
"url": "http://vlt.sh"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@vltpkg/cmd-shim": "1.0.
|
|
17
|
-
"@vltpkg/dep-id": "1.0.
|
|
18
|
-
"@vltpkg/dss-breadcrumb": "1.0.
|
|
19
|
-
"@vltpkg/error-cause": "1.0.
|
|
20
|
-
"@vltpkg/fast-split": "1.0.
|
|
21
|
-
"@vltpkg/graph-run": "1.0.
|
|
22
|
-
"@vltpkg/init": "1.0.
|
|
23
|
-
"@vltpkg/output": "1.0.
|
|
24
|
-
"@vltpkg/package-info": "1.0.
|
|
25
|
-
"@vltpkg/package-json": "1.0.
|
|
26
|
-
"@vltpkg/pick-manifest": "1.0.
|
|
27
|
-
"@vltpkg/query": "1.0.
|
|
28
|
-
"@vltpkg/rollback-remove": "1.0.
|
|
29
|
-
"@vltpkg/run": "1.0.
|
|
30
|
-
"@vltpkg/satisfies": "1.0.
|
|
31
|
-
"@vltpkg/security-archive": "1.0.
|
|
32
|
-
"@vltpkg/spec": "1.0.
|
|
33
|
-
"@vltpkg/types": "1.0.
|
|
34
|
-
"@vltpkg/vlt-json": "1.0.
|
|
35
|
-
"@vltpkg/workspaces": "1.0.
|
|
16
|
+
"@vltpkg/cmd-shim": "1.0.3",
|
|
17
|
+
"@vltpkg/dep-id": "1.0.3",
|
|
18
|
+
"@vltpkg/dss-breadcrumb": "1.0.3",
|
|
19
|
+
"@vltpkg/error-cause": "1.0.3",
|
|
20
|
+
"@vltpkg/fast-split": "1.0.3",
|
|
21
|
+
"@vltpkg/graph-run": "1.0.3",
|
|
22
|
+
"@vltpkg/init": "1.0.3",
|
|
23
|
+
"@vltpkg/output": "1.0.3",
|
|
24
|
+
"@vltpkg/package-info": "1.0.3",
|
|
25
|
+
"@vltpkg/package-json": "1.0.3",
|
|
26
|
+
"@vltpkg/pick-manifest": "1.0.3",
|
|
27
|
+
"@vltpkg/query": "1.0.3",
|
|
28
|
+
"@vltpkg/rollback-remove": "1.0.3",
|
|
29
|
+
"@vltpkg/run": "1.0.3",
|
|
30
|
+
"@vltpkg/satisfies": "1.0.3",
|
|
31
|
+
"@vltpkg/security-archive": "1.0.3",
|
|
32
|
+
"@vltpkg/spec": "1.0.3",
|
|
33
|
+
"@vltpkg/types": "1.0.3",
|
|
34
|
+
"@vltpkg/vlt-json": "1.0.3",
|
|
35
|
+
"@vltpkg/workspaces": "1.0.3",
|
|
36
36
|
"path-scurry": "^2.0.1",
|
|
37
37
|
"promise-call-limit": "^3.0.2"
|
|
38
38
|
},
|