@vltpkg/graph 1.0.0-rc.23 → 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.
- package/dist/actual/load.d.ts +107 -0
- package/dist/actual/load.js +336 -0
- package/dist/browser.d.ts +14 -0
- package/dist/browser.js +16 -0
- package/dist/build.d.ts +28 -0
- package/dist/build.js +78 -0
- package/dist/dependencies.d.ts +65 -0
- package/dist/dependencies.js +111 -0
- package/dist/diff.d.ts +119 -0
- package/dist/diff.js +151 -0
- package/dist/edge.d.ts +46 -0
- package/dist/edge.js +77 -0
- package/dist/fixup-added-names.d.ts +18 -0
- package/dist/fixup-added-names.js +46 -0
- package/dist/graph.d.ts +153 -0
- package/dist/graph.js +444 -0
- package/dist/ideal/append-nodes.d.ts +31 -0
- package/dist/ideal/append-nodes.js +560 -0
- package/dist/ideal/build-ideal-from-starting-graph.d.ts +14 -0
- package/dist/ideal/build-ideal-from-starting-graph.js +69 -0
- package/dist/ideal/build.d.ts +40 -0
- package/dist/ideal/build.js +84 -0
- package/dist/ideal/get-importer-specs.d.ts +20 -0
- package/dist/ideal/get-importer-specs.js +180 -0
- package/dist/ideal/peers.d.ts +160 -0
- package/dist/ideal/peers.js +696 -0
- package/dist/ideal/refresh-ideal-graph.d.ts +43 -0
- package/dist/ideal/refresh-ideal-graph.js +62 -0
- package/dist/ideal/remove-satisfied-specs.d.ts +7 -0
- package/dist/ideal/remove-satisfied-specs.js +34 -0
- package/dist/ideal/sorting.d.ts +45 -0
- package/dist/ideal/sorting.js +70 -0
- package/dist/ideal/types.d.ts +107 -0
- package/dist/ideal/types.js +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +32 -0
- package/dist/install.d.ts +19 -0
- package/dist/install.js +208 -0
- package/dist/lockfile/load-edges.d.ts +11 -0
- package/dist/lockfile/load-edges.js +105 -0
- package/dist/lockfile/load-nodes.d.ts +4 -0
- package/dist/lockfile/load-nodes.js +101 -0
- package/dist/lockfile/load.d.ts +45 -0
- package/dist/lockfile/load.js +84 -0
- package/dist/lockfile/save.d.ts +30 -0
- package/dist/lockfile/save.js +174 -0
- package/dist/lockfile/types.d.ts +95 -0
- package/dist/lockfile/types.js +49 -0
- package/dist/modifiers.d.ts +188 -0
- package/dist/modifiers.js +329 -0
- package/dist/node.d.ts +234 -0
- package/dist/node.js +388 -0
- package/dist/non-empty-list.d.ts +2 -0
- package/dist/non-empty-list.js +2 -0
- package/dist/reify/add-edge.d.ts +9 -0
- package/dist/reify/add-edge.js +71 -0
- package/dist/reify/add-edges.d.ts +4 -0
- package/dist/reify/add-edges.js +12 -0
- package/dist/reify/add-nodes.d.ts +6 -0
- package/dist/reify/add-nodes.js +16 -0
- package/dist/reify/bin-chmod.d.ts +10 -0
- package/dist/reify/bin-chmod.js +38 -0
- package/dist/reify/build.d.ts +13 -0
- package/dist/reify/build.js +111 -0
- package/dist/reify/calculate-save-value.d.ts +2 -0
- package/dist/reify/calculate-save-value.js +50 -0
- package/dist/reify/check-needed-build.d.ts +34 -0
- package/dist/reify/check-needed-build.js +71 -0
- package/dist/reify/delete-edge.d.ts +4 -0
- package/dist/reify/delete-edge.js +27 -0
- package/dist/reify/delete-edges.d.ts +4 -0
- package/dist/reify/delete-edges.js +13 -0
- package/dist/reify/delete-nodes.d.ts +4 -0
- package/dist/reify/delete-nodes.js +15 -0
- package/dist/reify/extract-node.d.ts +23 -0
- package/dist/reify/extract-node.js +83 -0
- package/dist/reify/index.d.ts +34 -0
- package/dist/reify/index.js +161 -0
- package/dist/reify/internal-hoist.d.ts +8 -0
- package/dist/reify/internal-hoist.js +133 -0
- package/dist/reify/optional-fail.d.ts +15 -0
- package/dist/reify/optional-fail.js +15 -0
- package/dist/reify/rollback.d.ts +4 -0
- package/dist/reify/rollback.js +23 -0
- package/dist/reify/update-importers-package-json.d.ts +35 -0
- package/dist/reify/update-importers-package-json.js +122 -0
- package/dist/remove-optional-subgraph.d.ts +33 -0
- package/dist/remove-optional-subgraph.js +47 -0
- package/dist/resolve-save-type.d.ts +5 -0
- package/dist/resolve-save-type.js +4 -0
- package/dist/stringify-node.d.ts +2 -0
- package/dist/stringify-node.js +32 -0
- package/dist/transfer-data/load.d.ts +43 -0
- package/dist/transfer-data/load.js +175 -0
- package/dist/uninstall.d.ts +14 -0
- package/dist/uninstall.js +75 -0
- package/dist/update.d.ts +12 -0
- package/dist/update.js +73 -0
- package/dist/virtual-root.d.ts +15 -0
- package/dist/virtual-root.js +78 -0
- package/dist/visualization/human-readable-output.d.ts +26 -0
- package/dist/visualization/human-readable-output.js +163 -0
- package/dist/visualization/json-output.d.ts +41 -0
- package/dist/visualization/json-output.js +50 -0
- package/dist/visualization/mermaid-output.d.ts +17 -0
- package/dist/visualization/mermaid-output.js +170 -0
- package/dist/visualization/object-like-output.d.ts +2 -0
- package/dist/visualization/object-like-output.js +47 -0
- package/package.json +22 -22
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { error } from '@vltpkg/error-cause';
|
|
2
|
+
import { Spec } from '@vltpkg/spec/browser';
|
|
3
|
+
import { dependencyTypes, longDependencyTypes, shortDependencyTypes, } from '@vltpkg/types';
|
|
4
|
+
export const isDependencyTypeShort = (obj) => shortDependencyTypes.has(obj);
|
|
5
|
+
export const isDependencySaveType = (obj) => shortDependencyTypes.has(obj) ||
|
|
6
|
+
obj === 'implicit';
|
|
7
|
+
export const asDependencyTypeShort = (obj) => {
|
|
8
|
+
if (!isDependencyTypeShort(obj)) {
|
|
9
|
+
throw error('Invalid dependency type', {
|
|
10
|
+
found: obj,
|
|
11
|
+
validOptions: [...shortDependencyTypes],
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
return obj;
|
|
15
|
+
};
|
|
16
|
+
const isObj = (o) => !!o && typeof o === 'object';
|
|
17
|
+
// TODO: it would be nice to have a @vltpkg/spec.isSpec method
|
|
18
|
+
export const isDependency = (o) =>
|
|
19
|
+
// TODO: it would be nice to have a @vltpkg/spec.isSpec method
|
|
20
|
+
isObj(o) &&
|
|
21
|
+
isObj(o.spec) &&
|
|
22
|
+
!!o.spec.type &&
|
|
23
|
+
isDependencySaveType(o.type);
|
|
24
|
+
export const asDependency = (obj) => {
|
|
25
|
+
if (!isDependency(obj)) {
|
|
26
|
+
throw error('Invalid dependency', { found: obj });
|
|
27
|
+
}
|
|
28
|
+
return obj;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Get the {@link DependencyTypeShort} from a {@link DependencyTypeLong}.
|
|
32
|
+
*/
|
|
33
|
+
export const shorten = (typeLong, name, manifest) => {
|
|
34
|
+
const shortName = dependencyTypes.get(typeLong);
|
|
35
|
+
if (!shortName) {
|
|
36
|
+
throw error('Invalid dependency type name', {
|
|
37
|
+
found: typeLong,
|
|
38
|
+
validOptions: [...longDependencyTypes],
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (shortName !== 'peer') {
|
|
42
|
+
return shortName;
|
|
43
|
+
}
|
|
44
|
+
if (name &&
|
|
45
|
+
manifest?.peerDependenciesMeta?.[name]?.optional === true) {
|
|
46
|
+
return 'peerOptional';
|
|
47
|
+
}
|
|
48
|
+
return 'peer';
|
|
49
|
+
};
|
|
50
|
+
const isStringArray = (a) => Array.isArray(a) && !a.some(b => typeof b !== 'string');
|
|
51
|
+
/*
|
|
52
|
+
* Retrieves a map of all dependencies, of all types, that can be iterated
|
|
53
|
+
* on and consulted when parsing the directory contents of a given node.
|
|
54
|
+
*/
|
|
55
|
+
export const getRawDependencies = (node) => {
|
|
56
|
+
const dependencies = new Map();
|
|
57
|
+
const bundleDeps = node.manifest?.bundleDependencies ?? [];
|
|
58
|
+
// if it's an importer, bundleDeps are just normal. if it's a dep,
|
|
59
|
+
// then they're ignored entirely.
|
|
60
|
+
const bundled = (!node.importer &&
|
|
61
|
+
!node.id.startsWith('git') &&
|
|
62
|
+
isStringArray(bundleDeps)) ?
|
|
63
|
+
new Set(bundleDeps)
|
|
64
|
+
: new Set();
|
|
65
|
+
for (const depType of longDependencyTypes) {
|
|
66
|
+
const obj = node.manifest?.[depType];
|
|
67
|
+
// only care about devDeps for importers and git or symlink deps
|
|
68
|
+
// technically this will also include devDeps for tarball file: specs,
|
|
69
|
+
// but that is likely rare enough to not worry about too much.
|
|
70
|
+
if (depType === 'devDependencies' &&
|
|
71
|
+
!node.importer &&
|
|
72
|
+
!node.id.startsWith('git') &&
|
|
73
|
+
!node.id.startsWith('file')) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (obj) {
|
|
77
|
+
for (const [name, bareSpec] of Object.entries(obj)) {
|
|
78
|
+
// if it's a bundled dependency, we just ignore it entirely.
|
|
79
|
+
if (bundled.has(name))
|
|
80
|
+
continue;
|
|
81
|
+
dependencies.set(name, {
|
|
82
|
+
name,
|
|
83
|
+
type: depType,
|
|
84
|
+
bareSpec,
|
|
85
|
+
registry: node.registry,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return dependencies;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Retrieves a map of all dependencies, of all types, that can be inferred
|
|
94
|
+
* from a given node manifest, including missing dependencies.
|
|
95
|
+
*/
|
|
96
|
+
export const getDependencies = (node, options) => {
|
|
97
|
+
const res = new Map();
|
|
98
|
+
const dependencies = getRawDependencies(node);
|
|
99
|
+
for (const { name, type, bareSpec } of dependencies.values()) {
|
|
100
|
+
const depType = shorten(type, name, node.manifest);
|
|
101
|
+
const spec = Spec.parse(name, bareSpec, {
|
|
102
|
+
...options,
|
|
103
|
+
registry: node.registry,
|
|
104
|
+
});
|
|
105
|
+
res.set(name, {
|
|
106
|
+
spec,
|
|
107
|
+
type: depType,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return res;
|
|
111
|
+
};
|
package/dist/diff.d.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { InspectOptions } from 'node:util';
|
|
2
|
+
import type { Edge } from './edge.ts';
|
|
3
|
+
import type { Graph } from './graph.ts';
|
|
4
|
+
import type { Node } from './node.ts';
|
|
5
|
+
declare const kCustomInspect: unique symbol;
|
|
6
|
+
/**
|
|
7
|
+
* A Diff object is a representation of a set of changes from one
|
|
8
|
+
* graph to another, typically from the actual graph as it is reified
|
|
9
|
+
* on disk, to an intended ideal graph.
|
|
10
|
+
*
|
|
11
|
+
* The naming convention can get a bit confusing here, because it's a
|
|
12
|
+
* set of directed changes from one set of directed objects to another.
|
|
13
|
+
*
|
|
14
|
+
* Within the context the Diff object, `from` is the Graph we're coming from,
|
|
15
|
+
* and `to` is the Graph we're trying to create.
|
|
16
|
+
*/
|
|
17
|
+
export declare class Diff {
|
|
18
|
+
from: Graph;
|
|
19
|
+
to: Graph;
|
|
20
|
+
projectRoot: string;
|
|
21
|
+
/**
|
|
22
|
+
* If changes need to be made later for failures of optional nodes,
|
|
23
|
+
* set this flag so that we know to call graph.gc() at the appropriate time.
|
|
24
|
+
*/
|
|
25
|
+
hadOptionalFailures: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Collection of nodes to add and delete
|
|
28
|
+
*/
|
|
29
|
+
nodes: {
|
|
30
|
+
/** Nodes in the `to` graph that are not in the `from` graph */
|
|
31
|
+
add: Set<Node>;
|
|
32
|
+
/** Nodes in the `from` graph that are not in the `to` graph */
|
|
33
|
+
delete: Set<Node>;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Collection of nodes to add and delete
|
|
37
|
+
*/
|
|
38
|
+
edges: {
|
|
39
|
+
/** Edges in the `to` graph that are not found in the `from` graph */
|
|
40
|
+
add: Set<Edge>;
|
|
41
|
+
/** Edges in the `from` graph that are not found in the `to` graph */
|
|
42
|
+
delete: Set<Edge>;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* True if the diff only contains optional nodes (computed during construction)
|
|
46
|
+
*/
|
|
47
|
+
optionalOnly: boolean;
|
|
48
|
+
get [Symbol.toStringTag](): string;
|
|
49
|
+
constructor(from: Graph, to: Graph);
|
|
50
|
+
[kCustomInspect](_: number, options?: InspectOptions): string;
|
|
51
|
+
hasChanges(): boolean;
|
|
52
|
+
toJSON(): {
|
|
53
|
+
nodes: {
|
|
54
|
+
add: {
|
|
55
|
+
rawManifest?: import("@vltpkg/types").Override<import("@vltpkg/types").Manifest, import("@vltpkg/types").NormalizedFields> | undefined;
|
|
56
|
+
peerSetHash?: string | undefined;
|
|
57
|
+
id: import("@vltpkg/dep-id").DepID;
|
|
58
|
+
name: string;
|
|
59
|
+
version: string | undefined;
|
|
60
|
+
location: string;
|
|
61
|
+
importer: boolean;
|
|
62
|
+
manifest: import("@vltpkg/types").Override<import("@vltpkg/types").Manifest, import("@vltpkg/types").NormalizedFields> | undefined;
|
|
63
|
+
projectRoot: string;
|
|
64
|
+
integrity: `sha512-${string}` | undefined;
|
|
65
|
+
resolved: string | undefined;
|
|
66
|
+
dev: boolean;
|
|
67
|
+
optional: boolean;
|
|
68
|
+
confused: boolean;
|
|
69
|
+
modifier: string | undefined;
|
|
70
|
+
platform: {
|
|
71
|
+
engines?: Record<string, string>;
|
|
72
|
+
os?: string[] | string;
|
|
73
|
+
cpu?: string[] | string;
|
|
74
|
+
libc?: string[] | string;
|
|
75
|
+
} | undefined;
|
|
76
|
+
buildState: "none" | "needed" | "built" | "failed";
|
|
77
|
+
}[];
|
|
78
|
+
delete: {
|
|
79
|
+
rawManifest?: import("@vltpkg/types").Override<import("@vltpkg/types").Manifest, import("@vltpkg/types").NormalizedFields> | undefined;
|
|
80
|
+
peerSetHash?: string | undefined;
|
|
81
|
+
id: import("@vltpkg/dep-id").DepID;
|
|
82
|
+
name: string;
|
|
83
|
+
version: string | undefined;
|
|
84
|
+
location: string;
|
|
85
|
+
importer: boolean;
|
|
86
|
+
manifest: import("@vltpkg/types").Override<import("@vltpkg/types").Manifest, import("@vltpkg/types").NormalizedFields> | undefined;
|
|
87
|
+
projectRoot: string;
|
|
88
|
+
integrity: `sha512-${string}` | undefined;
|
|
89
|
+
resolved: string | undefined;
|
|
90
|
+
dev: boolean;
|
|
91
|
+
optional: boolean;
|
|
92
|
+
confused: boolean;
|
|
93
|
+
modifier: string | undefined;
|
|
94
|
+
platform: {
|
|
95
|
+
engines?: Record<string, string>;
|
|
96
|
+
os?: string[] | string;
|
|
97
|
+
cpu?: string[] | string;
|
|
98
|
+
libc?: string[] | string;
|
|
99
|
+
} | undefined;
|
|
100
|
+
buildState: "none" | "needed" | "built" | "failed";
|
|
101
|
+
}[];
|
|
102
|
+
};
|
|
103
|
+
edges: {
|
|
104
|
+
add: {
|
|
105
|
+
from: import("@vltpkg/dep-id").DepID;
|
|
106
|
+
to: import("@vltpkg/dep-id").DepID | undefined;
|
|
107
|
+
type: import("@vltpkg/types").DependencyTypeShort;
|
|
108
|
+
spec: string;
|
|
109
|
+
}[];
|
|
110
|
+
delete: {
|
|
111
|
+
from: import("@vltpkg/dep-id").DepID;
|
|
112
|
+
to: import("@vltpkg/dep-id").DepID | undefined;
|
|
113
|
+
type: import("@vltpkg/types").DependencyTypeShort;
|
|
114
|
+
spec: string;
|
|
115
|
+
}[];
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
export {};
|
package/dist/diff.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { error } from '@vltpkg/error-cause';
|
|
2
|
+
// XXX should file deps *always* be considered changed?
|
|
3
|
+
// unless the thing containing it wasn't possibly changed because it's inside
|
|
4
|
+
// a dep that didn't change?
|
|
5
|
+
// Same with remote deps
|
|
6
|
+
const kCustomInspect = Symbol.for('nodejs.util.inspect.custom');
|
|
7
|
+
/**
|
|
8
|
+
* A Diff object is a representation of a set of changes from one
|
|
9
|
+
* graph to another, typically from the actual graph as it is reified
|
|
10
|
+
* on disk, to an intended ideal graph.
|
|
11
|
+
*
|
|
12
|
+
* The naming convention can get a bit confusing here, because it's a
|
|
13
|
+
* set of directed changes from one set of directed objects to another.
|
|
14
|
+
*
|
|
15
|
+
* Within the context the Diff object, `from` is the Graph we're coming from,
|
|
16
|
+
* and `to` is the Graph we're trying to create.
|
|
17
|
+
*/
|
|
18
|
+
export class Diff {
|
|
19
|
+
from;
|
|
20
|
+
to;
|
|
21
|
+
projectRoot;
|
|
22
|
+
/**
|
|
23
|
+
* If changes need to be made later for failures of optional nodes,
|
|
24
|
+
* set this flag so that we know to call graph.gc() at the appropriate time.
|
|
25
|
+
*/
|
|
26
|
+
hadOptionalFailures = false;
|
|
27
|
+
/**
|
|
28
|
+
* Collection of nodes to add and delete
|
|
29
|
+
*/
|
|
30
|
+
nodes = {
|
|
31
|
+
/** Nodes in the `to` graph that are not in the `from` graph */
|
|
32
|
+
add: new Set(),
|
|
33
|
+
/** Nodes in the `from` graph that are not in the `to` graph */
|
|
34
|
+
delete: new Set(),
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Collection of nodes to add and delete
|
|
38
|
+
*/
|
|
39
|
+
edges = {
|
|
40
|
+
/** Edges in the `to` graph that are not found in the `from` graph */
|
|
41
|
+
add: new Set(),
|
|
42
|
+
/** Edges in the `from` graph that are not found in the `to` graph */
|
|
43
|
+
delete: new Set(),
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* True if the diff only contains optional nodes (computed during construction)
|
|
47
|
+
*/
|
|
48
|
+
optionalOnly = true;
|
|
49
|
+
get [Symbol.toStringTag]() {
|
|
50
|
+
return '@vltpkg/graph.Diff';
|
|
51
|
+
}
|
|
52
|
+
constructor(from, to) {
|
|
53
|
+
this.from = from;
|
|
54
|
+
this.to = to;
|
|
55
|
+
this.projectRoot = from.projectRoot;
|
|
56
|
+
if (to.projectRoot !== from.projectRoot) {
|
|
57
|
+
throw error('projectRoot mismatch in Graph diff', {
|
|
58
|
+
wanted: from.projectRoot,
|
|
59
|
+
found: to.projectRoot,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
for (const [id, node] of this.from.nodes) {
|
|
63
|
+
if (!this.to.nodes.get(id)?.equals(node)) {
|
|
64
|
+
this.nodes.delete.add(node);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
for (const [id, node] of this.to.nodes) {
|
|
68
|
+
if (!this.from.nodes.get(id)?.equals(node)) {
|
|
69
|
+
this.nodes.add.add(node);
|
|
70
|
+
if (!node.optional) {
|
|
71
|
+
this.optionalOnly = false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
for (const edge of this.to.edges) {
|
|
76
|
+
// the node with this dep, in the from graph
|
|
77
|
+
const fromNode = this.from.nodes.get(edge.from.id);
|
|
78
|
+
const fromEdge = fromNode?.edgesOut.get(edge.spec.name);
|
|
79
|
+
if (fromEdge?.to?.id === edge.to?.id)
|
|
80
|
+
continue;
|
|
81
|
+
if (fromEdge?.to)
|
|
82
|
+
this.edges.delete.add(fromEdge);
|
|
83
|
+
if (edge.to) {
|
|
84
|
+
this.edges.add.add(edge);
|
|
85
|
+
if (!edge.optional) {
|
|
86
|
+
this.optionalOnly = false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const edge of this.from.edges) {
|
|
91
|
+
// the node with this dep, in the to graph
|
|
92
|
+
const toNode = this.to.nodes.get(edge.from.id);
|
|
93
|
+
const toEdge = toNode?.edgesOut.get(edge.spec.name);
|
|
94
|
+
if (toEdge?.to?.id === edge.to?.id)
|
|
95
|
+
continue;
|
|
96
|
+
if (edge.to)
|
|
97
|
+
this.edges.delete.add(edge);
|
|
98
|
+
if (toEdge?.to)
|
|
99
|
+
this.edges.add.add(toEdge);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
[kCustomInspect](_, options) {
|
|
103
|
+
const red = options?.colors ? ['\x1b[31m', '\x1b[m'] : ['', ''];
|
|
104
|
+
const green = options?.colors ? ['\x1b[32m', '\x1b[m'] : ['', ''];
|
|
105
|
+
const lines = [];
|
|
106
|
+
for (const node of this.nodes.add) {
|
|
107
|
+
lines.push(`+ ${node.id}`);
|
|
108
|
+
}
|
|
109
|
+
for (const node of this.nodes.delete) {
|
|
110
|
+
lines.push(`- ${node.id}`);
|
|
111
|
+
}
|
|
112
|
+
for (const edge of this.edges.add) {
|
|
113
|
+
/* c8 ignore next */
|
|
114
|
+
const to = edge.to?.id ?? '';
|
|
115
|
+
lines.push(`+ ${edge.from.id} ${edge.type} ${edge.spec} ${to}`.trim());
|
|
116
|
+
}
|
|
117
|
+
for (const edge of this.edges.delete) {
|
|
118
|
+
/* c8 ignore next */
|
|
119
|
+
const to = edge.to?.id ?? '';
|
|
120
|
+
lines.push(`- ${edge.from.id} ${edge.type} ${edge.spec} ${to}`.trim());
|
|
121
|
+
}
|
|
122
|
+
const wrap = (s, c) => c.join(s);
|
|
123
|
+
const color = options?.colors ?
|
|
124
|
+
(s) => wrap(s, s.startsWith('+') ? green : red)
|
|
125
|
+
: (s) => s;
|
|
126
|
+
return `${this[Symbol.toStringTag]} {
|
|
127
|
+
${lines
|
|
128
|
+
.sort((a, b) => a.substring(1).localeCompare(b.substring(1), 'en'))
|
|
129
|
+
.map(s => ' ' + color(s))
|
|
130
|
+
.join('\n')}
|
|
131
|
+
}`;
|
|
132
|
+
}
|
|
133
|
+
hasChanges() {
|
|
134
|
+
return (this.nodes.add.size > 0 ||
|
|
135
|
+
this.nodes.delete.size > 0 ||
|
|
136
|
+
this.edges.add.size > 0 ||
|
|
137
|
+
this.edges.delete.size > 0);
|
|
138
|
+
}
|
|
139
|
+
toJSON() {
|
|
140
|
+
return {
|
|
141
|
+
nodes: {
|
|
142
|
+
add: [...this.nodes.add].map(node => node.toJSON()),
|
|
143
|
+
delete: [...this.nodes.delete].map(node => node.toJSON()),
|
|
144
|
+
},
|
|
145
|
+
edges: {
|
|
146
|
+
add: [...this.edges.add].map(edge => edge.toJSON()),
|
|
147
|
+
delete: [...this.edges.delete].map(edge => edge.toJSON()),
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
package/dist/edge.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Spec } from '@vltpkg/spec';
|
|
2
|
+
import type { InspectOptions } from 'node:util';
|
|
3
|
+
import type { DependencyTypeShort, EdgeLike } from '@vltpkg/types';
|
|
4
|
+
import type { Node } from './node.ts';
|
|
5
|
+
declare const kCustomInspect: unique symbol;
|
|
6
|
+
export declare class Edge implements EdgeLike {
|
|
7
|
+
get [Symbol.toStringTag](): string;
|
|
8
|
+
[kCustomInspect](_: number, options: InspectOptions): string;
|
|
9
|
+
/**
|
|
10
|
+
* The Node this Edge is connecting from, this is usually the dependent.
|
|
11
|
+
*/
|
|
12
|
+
from: Node;
|
|
13
|
+
/**
|
|
14
|
+
* The node this Edge is connecting to, this is usually a direct dependency.
|
|
15
|
+
*/
|
|
16
|
+
to?: Node;
|
|
17
|
+
/**
|
|
18
|
+
* What type of dependency relationship `from` and `to` nodes have.
|
|
19
|
+
*/
|
|
20
|
+
type: DependencyTypeShort;
|
|
21
|
+
/**
|
|
22
|
+
* The defined spec value for `to` as parsed from the dependent metadata.
|
|
23
|
+
*/
|
|
24
|
+
spec: Spec;
|
|
25
|
+
constructor(type: DependencyTypeShort, spec: Spec, from: Node, to?: Node);
|
|
26
|
+
/**
|
|
27
|
+
* The name of the dependency `to` as defined in the dependent metadata.
|
|
28
|
+
*/
|
|
29
|
+
get name(): string;
|
|
30
|
+
/**
|
|
31
|
+
* This edge was defined as part of a `devDependencies` in `package.json`
|
|
32
|
+
*/
|
|
33
|
+
get dev(): boolean;
|
|
34
|
+
get optional(): boolean;
|
|
35
|
+
get peer(): boolean;
|
|
36
|
+
get peerOptional(): boolean;
|
|
37
|
+
valid(): boolean;
|
|
38
|
+
toJSON(): {
|
|
39
|
+
from: import("@vltpkg/dep-id").DepID;
|
|
40
|
+
to: import("@vltpkg/dep-id").DepID | undefined;
|
|
41
|
+
type: DependencyTypeShort;
|
|
42
|
+
spec: string;
|
|
43
|
+
};
|
|
44
|
+
toString(): string;
|
|
45
|
+
}
|
|
46
|
+
export {};
|
package/dist/edge.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { satisfies } from '@vltpkg/satisfies';
|
|
2
|
+
import { inspect } from 'node:util';
|
|
3
|
+
const kCustomInspect = Symbol.for('nodejs.util.inspect.custom');
|
|
4
|
+
export class Edge {
|
|
5
|
+
get [Symbol.toStringTag]() {
|
|
6
|
+
return '@vltpkg/graph.Edge';
|
|
7
|
+
}
|
|
8
|
+
[kCustomInspect](_, options) {
|
|
9
|
+
const str = inspect({
|
|
10
|
+
from: this.from.id,
|
|
11
|
+
type: this.type,
|
|
12
|
+
spec: String(this.spec),
|
|
13
|
+
to: this.to?.id,
|
|
14
|
+
}, options);
|
|
15
|
+
return `${this[Symbol.toStringTag]} ${str}`;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The Node this Edge is connecting from, this is usually the dependent.
|
|
19
|
+
*/
|
|
20
|
+
from;
|
|
21
|
+
/**
|
|
22
|
+
* The node this Edge is connecting to, this is usually a direct dependency.
|
|
23
|
+
*/
|
|
24
|
+
to;
|
|
25
|
+
/**
|
|
26
|
+
* What type of dependency relationship `from` and `to` nodes have.
|
|
27
|
+
*/
|
|
28
|
+
type;
|
|
29
|
+
/**
|
|
30
|
+
* The defined spec value for `to` as parsed from the dependent metadata.
|
|
31
|
+
*/
|
|
32
|
+
spec;
|
|
33
|
+
constructor(type, spec, from, to) {
|
|
34
|
+
this.from = from;
|
|
35
|
+
this.to = to;
|
|
36
|
+
this.type = type;
|
|
37
|
+
this.spec = spec;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The name of the dependency `to` as defined in the dependent metadata.
|
|
41
|
+
*/
|
|
42
|
+
get name() {
|
|
43
|
+
return this.spec.name;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* This edge was defined as part of a `devDependencies` in `package.json`
|
|
47
|
+
*/
|
|
48
|
+
get dev() {
|
|
49
|
+
return this.type === 'dev';
|
|
50
|
+
}
|
|
51
|
+
get optional() {
|
|
52
|
+
return this.type === 'peerOptional' || this.type === 'optional';
|
|
53
|
+
}
|
|
54
|
+
get peer() {
|
|
55
|
+
return this.type === 'peer' || this.type === 'peerOptional';
|
|
56
|
+
}
|
|
57
|
+
get peerOptional() {
|
|
58
|
+
return this.type === 'peerOptional';
|
|
59
|
+
}
|
|
60
|
+
valid() {
|
|
61
|
+
return !this.to ?
|
|
62
|
+
this.optional
|
|
63
|
+
: satisfies(this.to.id, this.spec, this.from.location, this.from.projectRoot);
|
|
64
|
+
}
|
|
65
|
+
toJSON() {
|
|
66
|
+
return {
|
|
67
|
+
from: this.from.id,
|
|
68
|
+
to: this.to?.id,
|
|
69
|
+
type: this.type,
|
|
70
|
+
spec: String(this.spec),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
toString() {
|
|
74
|
+
const to = `${this.name}${this.to ? '' : ' (missing)'}`;
|
|
75
|
+
return `Edge from: ${this.from.id} --|${this.type}|--> ${to}`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Spec } from '@vltpkg/spec';
|
|
2
|
+
import type { Dependency } from './dependencies.ts';
|
|
3
|
+
import type { Manifest } from '@vltpkg/types';
|
|
4
|
+
import type { SpecOptions } from '@vltpkg/spec';
|
|
5
|
+
/**
|
|
6
|
+
* When adding new dependencies, it's very common to not have a dependency
|
|
7
|
+
* name directly available to reference, e.g: `file:local/folder` or
|
|
8
|
+
* `remote:tarball-url.tgz`. In these cases, a placeholder `(unknown)` name
|
|
9
|
+
* is used in the `Spec` object and the `add` Map structure that holds
|
|
10
|
+
* references to added dependencies will use the stringified spec as a key.
|
|
11
|
+
*
|
|
12
|
+
* This helper function fixes unknown names in the `add` map by replacing
|
|
13
|
+
* placeholder specs with the correct names from the provided manifest.
|
|
14
|
+
*
|
|
15
|
+
* It also fixes empty bareSpec values (from CLI args like `vlt install foo`)
|
|
16
|
+
* by calculating the proper semver range from the resolved manifest version.
|
|
17
|
+
*/
|
|
18
|
+
export declare const fixupAddedNames: (add: Map<string, Dependency> | undefined, manifest: Pick<Manifest, "name" | "version"> | undefined, options: SpecOptions, spec: Spec) => Spec;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Spec } from '@vltpkg/spec';
|
|
2
|
+
import { calculateSaveValue } from "./reify/calculate-save-value.js";
|
|
3
|
+
/**
|
|
4
|
+
* When adding new dependencies, it's very common to not have a dependency
|
|
5
|
+
* name directly available to reference, e.g: `file:local/folder` or
|
|
6
|
+
* `remote:tarball-url.tgz`. In these cases, a placeholder `(unknown)` name
|
|
7
|
+
* is used in the `Spec` object and the `add` Map structure that holds
|
|
8
|
+
* references to added dependencies will use the stringified spec as a key.
|
|
9
|
+
*
|
|
10
|
+
* This helper function fixes unknown names in the `add` map by replacing
|
|
11
|
+
* placeholder specs with the correct names from the provided manifest.
|
|
12
|
+
*
|
|
13
|
+
* It also fixes empty bareSpec values (from CLI args like `vlt install foo`)
|
|
14
|
+
* by calculating the proper semver range from the resolved manifest version.
|
|
15
|
+
*/
|
|
16
|
+
export const fixupAddedNames = (add, manifest, options, spec) => {
|
|
17
|
+
// Handle nameless dependencies
|
|
18
|
+
if (add && manifest?.name && spec.name === '(unknown)') {
|
|
19
|
+
const s = add.get(String(spec));
|
|
20
|
+
if (s) {
|
|
21
|
+
// removes the previous, placeholder entry key
|
|
22
|
+
add.delete(String(spec));
|
|
23
|
+
// replaces spec with a version with the correct name
|
|
24
|
+
spec = Spec.parse(manifest.name, spec.bareSpec, options);
|
|
25
|
+
// updates the add map with the fixed up spec
|
|
26
|
+
const n = {
|
|
27
|
+
type: s.type,
|
|
28
|
+
spec,
|
|
29
|
+
};
|
|
30
|
+
add.set(manifest.name, n);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Fix empty bareSpec (usually from CLI args like `vlt install foo`)
|
|
34
|
+
// by calculating the proper semver range from the resolved manifest version
|
|
35
|
+
if (add && manifest?.version && !spec.bareSpec) {
|
|
36
|
+
const addEntry = add.get(spec.name);
|
|
37
|
+
if (addEntry) {
|
|
38
|
+
const saveValue = calculateSaveValue(spec.final.type, spec, undefined, manifest.version);
|
|
39
|
+
if (saveValue && saveValue !== spec.bareSpec) {
|
|
40
|
+
spec = Spec.parse(spec.name, saveValue, options);
|
|
41
|
+
addEntry.spec = spec;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return spec;
|
|
46
|
+
};
|