@vltpkg/graph 0.0.0-0.1730239248325

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +33 -0
  3. package/dist/esm/actual/load.d.ts +54 -0
  4. package/dist/esm/actual/load.d.ts.map +1 -0
  5. package/dist/esm/actual/load.js +243 -0
  6. package/dist/esm/actual/load.js.map +1 -0
  7. package/dist/esm/browser.d.ts +9 -0
  8. package/dist/esm/browser.d.ts.map +1 -0
  9. package/dist/esm/browser.js +11 -0
  10. package/dist/esm/browser.js.map +1 -0
  11. package/dist/esm/dependencies.d.ts +69 -0
  12. package/dist/esm/dependencies.d.ts.map +1 -0
  13. package/dist/esm/dependencies.js +71 -0
  14. package/dist/esm/dependencies.js.map +1 -0
  15. package/dist/esm/diff.d.ts +49 -0
  16. package/dist/esm/diff.d.ts.map +1 -0
  17. package/dist/esm/diff.js +123 -0
  18. package/dist/esm/diff.js.map +1 -0
  19. package/dist/esm/edge.d.ts +41 -0
  20. package/dist/esm/edge.d.ts.map +1 -0
  21. package/dist/esm/edge.js +66 -0
  22. package/dist/esm/edge.js.map +1 -0
  23. package/dist/esm/graph.d.ts +123 -0
  24. package/dist/esm/graph.d.ts.map +1 -0
  25. package/dist/esm/graph.js +301 -0
  26. package/dist/esm/graph.js.map +1 -0
  27. package/dist/esm/ideal/add-nodes.d.ts +19 -0
  28. package/dist/esm/ideal/add-nodes.d.ts.map +1 -0
  29. package/dist/esm/ideal/add-nodes.js +28 -0
  30. package/dist/esm/ideal/add-nodes.js.map +1 -0
  31. package/dist/esm/ideal/append-nodes.d.ts +9 -0
  32. package/dist/esm/ideal/append-nodes.d.ts.map +1 -0
  33. package/dist/esm/ideal/append-nodes.js +121 -0
  34. package/dist/esm/ideal/append-nodes.js.map +1 -0
  35. package/dist/esm/ideal/build-ideal-from-starting-graph.d.ts +15 -0
  36. package/dist/esm/ideal/build-ideal-from-starting-graph.d.ts.map +1 -0
  37. package/dist/esm/ideal/build-ideal-from-starting-graph.js +28 -0
  38. package/dist/esm/ideal/build-ideal-from-starting-graph.js.map +1 -0
  39. package/dist/esm/ideal/build.d.ts +32 -0
  40. package/dist/esm/ideal/build.d.ts.map +1 -0
  41. package/dist/esm/ideal/build.js +42 -0
  42. package/dist/esm/ideal/build.js.map +1 -0
  43. package/dist/esm/ideal/get-importer-specs.d.ts +13 -0
  44. package/dist/esm/ideal/get-importer-specs.d.ts.map +1 -0
  45. package/dist/esm/ideal/get-importer-specs.js +76 -0
  46. package/dist/esm/ideal/get-importer-specs.js.map +1 -0
  47. package/dist/esm/ideal/remove-nodes.d.ts +7 -0
  48. package/dist/esm/ideal/remove-nodes.d.ts.map +1 -0
  49. package/dist/esm/ideal/remove-nodes.js +19 -0
  50. package/dist/esm/ideal/remove-nodes.js.map +1 -0
  51. package/dist/esm/ideal/remove-satisfied-specs.d.ts +8 -0
  52. package/dist/esm/ideal/remove-satisfied-specs.d.ts.map +1 -0
  53. package/dist/esm/ideal/remove-satisfied-specs.js +35 -0
  54. package/dist/esm/ideal/remove-satisfied-specs.js.map +1 -0
  55. package/dist/esm/ideal/types.d.ts +35 -0
  56. package/dist/esm/ideal/types.d.ts.map +1 -0
  57. package/dist/esm/ideal/types.js +2 -0
  58. package/dist/esm/ideal/types.js.map +1 -0
  59. package/dist/esm/index.d.ts +31 -0
  60. package/dist/esm/index.d.ts.map +1 -0
  61. package/dist/esm/index.js +26 -0
  62. package/dist/esm/index.js.map +1 -0
  63. package/dist/esm/lockfile/load-edges.d.ts +5 -0
  64. package/dist/esm/lockfile/load-edges.d.ts.map +1 -0
  65. package/dist/esm/lockfile/load-edges.js +40 -0
  66. package/dist/esm/lockfile/load-edges.js.map +1 -0
  67. package/dist/esm/lockfile/load-nodes.d.ts +4 -0
  68. package/dist/esm/lockfile/load-nodes.d.ts.map +1 -0
  69. package/dist/esm/lockfile/load-nodes.js +28 -0
  70. package/dist/esm/lockfile/load-nodes.js.map +1 -0
  71. package/dist/esm/lockfile/load.d.ts +33 -0
  72. package/dist/esm/lockfile/load.d.ts.map +1 -0
  73. package/dist/esm/lockfile/load.js +53 -0
  74. package/dist/esm/lockfile/load.js.map +1 -0
  75. package/dist/esm/lockfile/save.d.ts +18 -0
  76. package/dist/esm/lockfile/save.d.ts.map +1 -0
  77. package/dist/esm/lockfile/save.js +128 -0
  78. package/dist/esm/lockfile/save.js.map +1 -0
  79. package/dist/esm/lockfile/types.d.ts +60 -0
  80. package/dist/esm/lockfile/types.d.ts.map +1 -0
  81. package/dist/esm/lockfile/types.js +13 -0
  82. package/dist/esm/lockfile/types.js.map +1 -0
  83. package/dist/esm/node.d.ts +144 -0
  84. package/dist/esm/node.d.ts.map +1 -0
  85. package/dist/esm/node.js +266 -0
  86. package/dist/esm/node.js.map +1 -0
  87. package/dist/esm/non-empty-list.d.ts +3 -0
  88. package/dist/esm/non-empty-list.d.ts.map +1 -0
  89. package/dist/esm/non-empty-list.js +3 -0
  90. package/dist/esm/non-empty-list.js.map +1 -0
  91. package/dist/esm/package.json +3 -0
  92. package/dist/esm/reify/add-edge.d.ts +11 -0
  93. package/dist/esm/reify/add-edge.d.ts.map +1 -0
  94. package/dist/esm/reify/add-edge.js +43 -0
  95. package/dist/esm/reify/add-edge.js.map +1 -0
  96. package/dist/esm/reify/add-edges.d.ts +6 -0
  97. package/dist/esm/reify/add-edges.d.ts.map +1 -0
  98. package/dist/esm/reify/add-edges.js +13 -0
  99. package/dist/esm/reify/add-edges.js.map +1 -0
  100. package/dist/esm/reify/add-nodes.d.ts +7 -0
  101. package/dist/esm/reify/add-nodes.d.ts.map +1 -0
  102. package/dist/esm/reify/add-nodes.js +37 -0
  103. package/dist/esm/reify/add-nodes.js.map +1 -0
  104. package/dist/esm/reify/bin-paths.d.ts +4 -0
  105. package/dist/esm/reify/bin-paths.d.ts.map +1 -0
  106. package/dist/esm/reify/bin-paths.js +23 -0
  107. package/dist/esm/reify/bin-paths.js.map +1 -0
  108. package/dist/esm/reify/build.d.ts +5 -0
  109. package/dist/esm/reify/build.d.ts.map +1 -0
  110. package/dist/esm/reify/build.js +90 -0
  111. package/dist/esm/reify/build.js.map +1 -0
  112. package/dist/esm/reify/delete-edge.d.ts +5 -0
  113. package/dist/esm/reify/delete-edge.d.ts.map +1 -0
  114. package/dist/esm/reify/delete-edge.js +29 -0
  115. package/dist/esm/reify/delete-edge.js.map +1 -0
  116. package/dist/esm/reify/delete-edges.d.ts +5 -0
  117. package/dist/esm/reify/delete-edges.d.ts.map +1 -0
  118. package/dist/esm/reify/delete-edges.js +14 -0
  119. package/dist/esm/reify/delete-edges.js.map +1 -0
  120. package/dist/esm/reify/delete-nodes.d.ts +5 -0
  121. package/dist/esm/reify/delete-nodes.d.ts.map +1 -0
  122. package/dist/esm/reify/delete-nodes.js +12 -0
  123. package/dist/esm/reify/delete-nodes.js.map +1 -0
  124. package/dist/esm/reify/index.d.ts +16 -0
  125. package/dist/esm/reify/index.d.ts.map +1 -0
  126. package/dist/esm/reify/index.js +85 -0
  127. package/dist/esm/reify/index.js.map +1 -0
  128. package/dist/esm/reify/optional-fail.d.ts +16 -0
  129. package/dist/esm/reify/optional-fail.d.ts.map +1 -0
  130. package/dist/esm/reify/optional-fail.js +16 -0
  131. package/dist/esm/reify/optional-fail.js.map +1 -0
  132. package/dist/esm/reify/rollback.d.ts +5 -0
  133. package/dist/esm/reify/rollback.d.ts.map +1 -0
  134. package/dist/esm/reify/rollback.js +24 -0
  135. package/dist/esm/reify/rollback.js.map +1 -0
  136. package/dist/esm/reify/update-importers-package-json.d.ts +36 -0
  137. package/dist/esm/reify/update-importers-package-json.d.ts.map +1 -0
  138. package/dist/esm/reify/update-importers-package-json.js +95 -0
  139. package/dist/esm/reify/update-importers-package-json.js.map +1 -0
  140. package/dist/esm/remove-optional-subgraph.d.ts +34 -0
  141. package/dist/esm/remove-optional-subgraph.d.ts.map +1 -0
  142. package/dist/esm/remove-optional-subgraph.js +48 -0
  143. package/dist/esm/remove-optional-subgraph.js.map +1 -0
  144. package/dist/esm/stringify-node.d.ts +3 -0
  145. package/dist/esm/stringify-node.d.ts.map +1 -0
  146. package/dist/esm/stringify-node.js +24 -0
  147. package/dist/esm/stringify-node.js.map +1 -0
  148. package/dist/esm/types.d.ts +39 -0
  149. package/dist/esm/types.d.ts.map +1 -0
  150. package/dist/esm/types.js +2 -0
  151. package/dist/esm/types.js.map +1 -0
  152. package/dist/esm/visualization/human-readable-output.d.ts +25 -0
  153. package/dist/esm/visualization/human-readable-output.d.ts.map +1 -0
  154. package/dist/esm/visualization/human-readable-output.js +132 -0
  155. package/dist/esm/visualization/human-readable-output.js.map +1 -0
  156. package/dist/esm/visualization/json-output.d.ts +37 -0
  157. package/dist/esm/visualization/json-output.d.ts.map +1 -0
  158. package/dist/esm/visualization/json-output.js +28 -0
  159. package/dist/esm/visualization/json-output.js.map +1 -0
  160. package/dist/esm/visualization/mermaid-output.d.ts +11 -0
  161. package/dist/esm/visualization/mermaid-output.d.ts.map +1 -0
  162. package/dist/esm/visualization/mermaid-output.js +68 -0
  163. package/dist/esm/visualization/mermaid-output.js.map +1 -0
  164. package/dist/esm/visualization/object-like-output.d.ts +3 -0
  165. package/dist/esm/visualization/object-like-output.d.ts.map +1 -0
  166. package/dist/esm/visualization/object-like-output.js +49 -0
  167. package/dist/esm/visualization/object-like-output.js.map +1 -0
  168. package/package.json +86 -0
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Copyright (c) vlt technology, Inc.
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
7
+ Subject to the terms and conditions of this license, each copyright holder and contributor hereby grants to those receiving rights under this license a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except for failure to satisfy the conditions of this license) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer this software, where such license applies only to those patent claims, already acquired or hereafter acquired, licensable by such copyright holder or contributor that are necessarily infringed by:
8
+
9
+ (a) their Contribution(s) (the licensed copyrights of copyright holders and non-copyrightable additions of contributors, in source or binary form) alone; or
10
+ (b) combination of their Contribution(s) with the work of authorship to which such Contribution(s) was added by such copyright holder or contributor, if, at the time the Contribution is added, such addition causes such combination to be necessarily infringed. The patent license shall not apply to any other combinations which include the Contribution.
11
+ Except as expressly stated above, no rights or licenses from any copyright holder or contributor is granted under this license, whether expressly, by implication, estoppel or otherwise.
12
+
13
+ DISCLAIMER
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # `@vltpkg/graph`
2
+
3
+ This is the graph library responsible for representing the packages
4
+ that are involved in a given install.
5
+
6
+ ## API
7
+
8
+ ### `actual.load({ projectRoot: string }): Graph`
9
+
10
+ Recursively loads the `node_modules` folder found at `projectRoot` in order to
11
+ create a graph representation of the current installed packages.
12
+
13
+ ### `async ideal.build({ projectRoot: string }): Promise<Graph>`
14
+
15
+ This method returns a new `Graph` object, reading from the `package.json`
16
+ file located at `projectRoot` dir and building up the graph representation
17
+ of nodes and edges from the files read from the local file system.
18
+
19
+ ### `lockfile.load({ mainManifest: Manifest, projectRoot: string }): Graph`
20
+
21
+ Loads the lockfile file found at `projectRoot` and returns the graph.
22
+
23
+ ## USAGE
24
+
25
+ Here's a quick example of how to use the `@vltpkg/graph.ideal.build` method to
26
+ build a graph representation of the install defined at the `projectRoot`
27
+ directory.
28
+
29
+ ```
30
+ import { ideal } from '@vltpkg/graph'
31
+
32
+ const graph = await ideal.build({ projectRoot: process.cwd() })
33
+ ```
@@ -0,0 +1,54 @@
1
+ import { PackageJson } from '@vltpkg/package-json';
2
+ import { SpecOptions } from '@vltpkg/spec';
3
+ import { Manifest } from '@vltpkg/types';
4
+ import { Monorepo } from '@vltpkg/workspaces';
5
+ import { Path, PathScurry } from 'path-scurry';
6
+ import { Graph } from '../graph.js';
7
+ export type LoadOptions = SpecOptions & {
8
+ /**
9
+ * The project root dirname.
10
+ */
11
+ projectRoot: string;
12
+ /**
13
+ * The project root manifest.
14
+ */
15
+ mainManifest?: Manifest;
16
+ /**
17
+ * A {@link Monorepo} object, for managing workspaces
18
+ */
19
+ monorepo?: Monorepo;
20
+ /**
21
+ * A {@link PackageJson} object, for sharing manifest caches
22
+ */
23
+ packageJson: PackageJson;
24
+ /**
25
+ * A {@link PathScurry} object, for use in globs
26
+ */
27
+ scurry: PathScurry;
28
+ /**
29
+ * If set to `false`, `actual.load` will not load any `package.json`
30
+ * files while traversing the file system.
31
+ *
32
+ * The resulting {@link Graph} from loading with `loadManifests=false`
33
+ * has no information on dependency types or the specs defined and
34
+ * no information on missing and extraneous dependencies.
35
+ */
36
+ loadManifests?: boolean;
37
+ /**
38
+ * If set to `true`, then do not shortcut the process by reading the
39
+ * hidden lockfile at `node_modules/.vlt-lock.json`
40
+ */
41
+ skipHiddenLockfile?: boolean;
42
+ };
43
+ export type ReadEntry = {
44
+ alias: string;
45
+ name: string;
46
+ realpath: Path;
47
+ };
48
+ /**
49
+ * Read the file system looking for `node_modules` folders and
50
+ * returns a new {@link Graph} that represents the relationship
51
+ * between the dependencies found.
52
+ */
53
+ export declare const load: (options: LoadOptions) => Graph;
54
+ //# sourceMappingURL=load.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../../src/actual/load.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EAAQ,WAAW,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAM9C,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAInC,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG;IACtC;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB;;OAEG;IACH,YAAY,CAAC,EAAE,QAAQ,CAAA;IACvB;;OAEG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB;;OAEG;IACH,WAAW,EAAE,WAAW,CAAA;IACxB;;OAEG;IACH,MAAM,EAAE,UAAU,CAAA;IAClB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,IAAI,CAAA;CACf,CAAA;AA6QD;;;;GAIG;AACH,eAAO,MAAM,IAAI,YAAa,WAAW,KAAG,KAqD3C,CAAA"}
@@ -0,0 +1,243 @@
1
+ import { asDepID, hydrate, joinDepIDTuple, } from '@vltpkg/dep-id';
2
+ import { Spec } from '@vltpkg/spec';
3
+ import { longDependencyTypes, shorten, } from '../dependencies.js';
4
+ import { Graph } from '../graph.js';
5
+ import { loadHidden } from '../lockfile/load.js';
6
+ const pathBasedType = new Set(['file', 'workspace']);
7
+ const isPathBasedType = (type) => pathBasedType.has(type);
8
+ const getPathBasedId = (spec, path) => isPathBasedType(spec.type) ?
9
+ joinDepIDTuple([spec.type, path])
10
+ : undefined;
11
+ /**
12
+ * Retrieve the {@link DepID} for a given package from its location.
13
+ */
14
+ const findDepID = ({ parent, name }) => parent?.name === '.vlt' ? asDepID(name)
15
+ : parent?.isCWD === false ? findDepID(parent)
16
+ : undefined;
17
+ /**
18
+ * Retrieves the closest `node_modules` parent {@link Path} found.
19
+ */
20
+ const findNodeModules = ({ parent, name, isCWD, }) => parent?.name === 'node_modules' ? parent
21
+ : parent && name !== '.vlt' && !isCWD ? findNodeModules(parent)
22
+ : undefined;
23
+ /**
24
+ * Retrieves the scoped-normalized package name from its {@link Path}.
25
+ */
26
+ const findName = ({ parent, name }) => parent?.name.startsWith('@') ? `${parent.name}/${name}` : name;
27
+ const isStringArray = (a) => Array.isArray(a) && !a.some(b => typeof b !== 'string');
28
+ /*
29
+ * Retrieves a map of all dependencies, of all types, that can be iterated
30
+ * on and consulted when parsing the directory contents of the current node.
31
+ */
32
+ const getDeps = (node) => {
33
+ const dependencies = new Map();
34
+ const bundleDeps = node.manifest?.bundleDependencies ?? [];
35
+ // if it's an importer, bundleDeps are just normal. if it's a dep,
36
+ // then they're ignored entirely.
37
+ const bundled = (!node.importer &&
38
+ !node.id.startsWith('git') &&
39
+ isStringArray(bundleDeps)) ?
40
+ new Set(bundleDeps)
41
+ : new Set();
42
+ for (const depType of longDependencyTypes) {
43
+ const obj = node.manifest?.[depType];
44
+ // only care about devDeps for importers and git or symlink deps
45
+ // technically this will also include devDeps for tarball file: specs,
46
+ // but that is likely rare enough to not worry about too much.
47
+ if (depType === 'devDependencies' &&
48
+ !node.importer &&
49
+ !node.id.startsWith('git') &&
50
+ !node.id.startsWith('file')) {
51
+ continue;
52
+ }
53
+ if (obj) {
54
+ for (const [name, bareSpec] of Object.entries(obj)) {
55
+ // if it's a bundled dependency, we just ignore it entirely.
56
+ if (bundled.has(name))
57
+ continue;
58
+ dependencies.set(name, {
59
+ name,
60
+ type: depType,
61
+ bareSpec,
62
+ registry: node.registry,
63
+ });
64
+ }
65
+ }
66
+ }
67
+ return dependencies;
68
+ };
69
+ /**
70
+ * Reads the current directory defined at `currDir` and looks for folder
71
+ * names and their realpath resolution, normalizing scoped package names
72
+ * and removing any invalid symlinks from the list of items that should
73
+ * be parsed through in order to build the graph.
74
+ */
75
+ const readDir = (scurry, currDir, fromNodeName) => {
76
+ const res = new Set();
77
+ for (const entry of scurry.readdirSync(currDir)) {
78
+ // ignore any hidden files / folders
79
+ if (entry.name.startsWith('.'))
80
+ continue;
81
+ // scope folder found, it will need to be read and iterated over
82
+ // in order to find any scoped packages inside
83
+ if (entry.name.startsWith('@')) {
84
+ const scopedItems = readDir(scurry, entry, fromNodeName);
85
+ for (const scopedItem of scopedItems) {
86
+ res.add(scopedItem);
87
+ }
88
+ continue;
89
+ }
90
+ // skip anything that isn't a symlink, it's not an edge
91
+ if (!entry.isSymbolicLink())
92
+ continue;
93
+ // we'll need to learn what is the real path for this entry in order
94
+ // to retrieve the `location` and `id` properties for the node, if a
95
+ // realpath is not found just move on to the next element
96
+ const realpath = entry.realpathSync();
97
+ if (!realpath) {
98
+ continue;
99
+ }
100
+ // infer both the alias and proper package names, including scopes
101
+ const alias = findName(entry);
102
+ const name = findName(realpath);
103
+ res.add({
104
+ alias,
105
+ name,
106
+ realpath,
107
+ });
108
+ }
109
+ return res;
110
+ };
111
+ /**
112
+ * Parses the files located at `currDir` and place packages found inside
113
+ * as dependencies of `fromNode`, building the instantiated `graph`.
114
+ */
115
+ const parseDir = (options, scurry, packageJson, depsFound, graph, fromNode, currDir) => {
116
+ const { loadManifests } = options;
117
+ const dependencies = getDeps(fromNode);
118
+ const seenDeps = new Set();
119
+ const readItems = readDir(scurry, currDir, fromNode.name);
120
+ for (const { alias, name, realpath } of readItems) {
121
+ let node;
122
+ // tracks what dependencies have been seen
123
+ // so that we can mark missing dependencies
124
+ seenDeps.add(alias);
125
+ // places the package in the graph reading
126
+ // its manifest only if necessary
127
+ if (!loadManifests) {
128
+ const depId = findDepID(realpath);
129
+ if (depId) {
130
+ const h = hydrate(depId, alias, {
131
+ ...options,
132
+ registry: fromNode.registry,
133
+ });
134
+ // graphs build with no manifest have no notion of
135
+ // dependency types and or spec definitions since those
136
+ // would have to be parsed from a manifest
137
+ node = graph.placePackage(fromNode, 'prod', // defaults to prod deps
138
+ h, // uses spec from hydrated id
139
+ {
140
+ name,
141
+ ...(h.registrySpec ?
142
+ { version: h.registrySpec } // adds version if available
143
+ : null),
144
+ }, depId);
145
+ }
146
+ }
147
+ // retrieve references to the current folder name found in `fromNode`
148
+ // manifest listed dependencies, removing it from the map will leave
149
+ // a list of missing dependencies at the end of the iteration
150
+ const deps = dependencies.get(alias);
151
+ // in case this graph is skipping manifests, this next block might
152
+ // still need to execute, thus actually loading a manifest file, for
153
+ // edge-cases such as loading a linked node that is not going to have
154
+ // DepID info available in its realpath or extraneous nodes
155
+ if (!node) {
156
+ const mani = packageJson.read(realpath.fullpath());
157
+ // declares fallback default values for both depType and bareSpec
158
+ // in order to support loadManifests=false fallback for link nodes
159
+ const type = deps?.type || 'dependencies';
160
+ const bareSpec = deps?.bareSpec || '*';
161
+ const depType = shorten(type, alias, fromNode.manifest);
162
+ const spec = Spec.parse(alias, bareSpec, {
163
+ ...options,
164
+ registry: fromNode.registry,
165
+ });
166
+ const maybeId = getPathBasedId(spec, realpath.relativePosix());
167
+ node = graph.placePackage(fromNode, depType, spec, mani, maybeId);
168
+ }
169
+ if (node) {
170
+ // If a found dependency is not declared in any of the original
171
+ // node dependencies, then add an edge to the graph pointing to it
172
+ // and mark it as extraneous.
173
+ //
174
+ // This only makes sense if full manifests are being loaded
175
+ // so that we have reference to dependencies info.
176
+ if (loadManifests && !deps) {
177
+ const [edge] = node.edgesIn;
178
+ if (edge) {
179
+ graph.extraneousDependencies.add(edge);
180
+ }
181
+ }
182
+ // for a succesfully created node, add its location
183
+ // property and queue up to read its dependencies
184
+ node.location = `./${realpath.relativePosix()}`;
185
+ const node_modules = findNodeModules(realpath);
186
+ // queue items up to continue parsing dirs in case a node was succesfully
187
+ // placed in the graph and its node_modules folder was correctly found
188
+ if (node_modules) {
189
+ depsFound.set(node, node_modules);
190
+ }
191
+ }
192
+ }
193
+ // any remaining dependencies that have not been found
194
+ // when reading the directory should be marked as missing
195
+ for (const { name, type, bareSpec } of dependencies.values()) {
196
+ if (!seenDeps.has(name)) {
197
+ const depType = shorten(type, name, fromNode.manifest);
198
+ const spec = Spec.parse(name, bareSpec, {
199
+ ...options,
200
+ registry: fromNode.registry,
201
+ });
202
+ graph.placePackage(fromNode, depType, spec);
203
+ }
204
+ }
205
+ };
206
+ /**
207
+ * Read the file system looking for `node_modules` folders and
208
+ * returns a new {@link Graph} that represents the relationship
209
+ * between the dependencies found.
210
+ */
211
+ export const load = (options) => {
212
+ // TODO: once hidden lockfile is more reliable, default to false here
213
+ const { skipHiddenLockfile = true, projectRoot, packageJson, scurry, monorepo, } = options;
214
+ const mainManifest = options.mainManifest ?? packageJson.read(projectRoot);
215
+ if (!skipHiddenLockfile) {
216
+ try {
217
+ const graph = loadHidden({
218
+ projectRoot,
219
+ mainManifest,
220
+ packageJson,
221
+ monorepo,
222
+ scurry,
223
+ });
224
+ // TODO: check mtime of lockfile vs .vlt folder
225
+ return graph;
226
+ }
227
+ catch { }
228
+ }
229
+ const graph = new Graph({ ...options, mainManifest });
230
+ const depsFound = new Map();
231
+ // starts the list of initial folders to parse using the importer nodes
232
+ for (const importer of graph.importers) {
233
+ depsFound.set(importer, scurry.cwd.resolve(`${importer.location}/node_modules`));
234
+ }
235
+ // breadth-first traversal of the file system tree reading deps found
236
+ // starting from the node_modules folder of every importer in order to
237
+ // find the actual installed dependencies at each location
238
+ for (const [node, path] of depsFound.entries()) {
239
+ parseDir(options, scurry, packageJson, depsFound, graph, node, path);
240
+ }
241
+ return graph;
242
+ };
243
+ //# sourceMappingURL=load.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../../../src/actual/load.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n asDepID,\n DepID,\n hydrate,\n joinDepIDTuple,\n} from '@vltpkg/dep-id'\nimport { PackageJson } from '@vltpkg/package-json'\nimport { Spec, SpecOptions } from '@vltpkg/spec'\nimport { Manifest } from '@vltpkg/types'\nimport { Monorepo } from '@vltpkg/workspaces'\nimport { Path, PathScurry } from 'path-scurry'\nimport {\n longDependencyTypes,\n RawDependency,\n shorten,\n} from '../dependencies.js'\nimport { Graph } from '../graph.js'\nimport { loadHidden } from '../lockfile/load.js'\nimport { Node } from '../node.js'\n\nexport type LoadOptions = SpecOptions & {\n /**\n * The project root dirname.\n */\n projectRoot: string\n /**\n * The project root manifest.\n */\n mainManifest?: Manifest\n /**\n * A {@link Monorepo} object, for managing workspaces\n */\n monorepo?: Monorepo\n /**\n * A {@link PackageJson} object, for sharing manifest caches\n */\n packageJson: PackageJson\n /**\n * A {@link PathScurry} object, for use in globs\n */\n scurry: PathScurry\n /**\n * If set to `false`, `actual.load` will not load any `package.json`\n * files while traversing the file system.\n *\n * The resulting {@link Graph} from loading with `loadManifests=false`\n * has no information on dependency types or the specs defined and\n * no information on missing and extraneous dependencies.\n */\n loadManifests?: boolean\n /**\n * If set to `true`, then do not shortcut the process by reading the\n * hidden lockfile at `node_modules/.vlt-lock.json`\n */\n skipHiddenLockfile?: boolean\n}\n\nexport type ReadEntry = {\n alias: string\n name: string\n realpath: Path\n}\n\nconst pathBasedType = new Set(['file', 'workspace'])\nconst isPathBasedType = (\n type: string,\n): type is 'file' | 'workspace' => pathBasedType.has(type)\nconst getPathBasedId = (\n spec: Spec,\n path: string,\n): DepID | undefined =>\n isPathBasedType(spec.type) ?\n joinDepIDTuple([spec.type, path])\n : undefined\n\n/**\n * Retrieve the {@link DepID} for a given package from its location.\n */\nconst findDepID = ({ parent, name }: Path): DepID | undefined =>\n parent?.name === '.vlt' ? asDepID(name)\n : parent?.isCWD === false ? findDepID(parent)\n : undefined\n\n/**\n * Retrieves the closest `node_modules` parent {@link Path} found.\n */\nconst findNodeModules = ({\n parent,\n name,\n isCWD,\n}: Path): Path | undefined =>\n parent?.name === 'node_modules' ? parent\n : parent && name !== '.vlt' && !isCWD ? findNodeModules(parent)\n : undefined\n\n/**\n * Retrieves the scoped-normalized package name from its {@link Path}.\n */\nconst findName = ({ parent, name }: Path): string =>\n parent?.name.startsWith('@') ? `${parent.name}/${name}` : name\n\nconst isStringArray = (a: unknown): a is string[] =>\n Array.isArray(a) && !a.some(b => typeof b !== 'string')\n\n/*\n * Retrieves a map of all dependencies, of all types, that can be iterated\n * on and consulted when parsing the directory contents of the current node.\n */\nconst getDeps = (node: Node) => {\n const dependencies = new Map<string, RawDependency>()\n const bundleDeps: unknown = node.manifest?.bundleDependencies ?? []\n // if it's an importer, bundleDeps are just normal. if it's a dep,\n // then they're ignored entirely.\n const bundled =\n (\n !node.importer &&\n !node.id.startsWith('git') &&\n isStringArray(bundleDeps)\n ) ?\n new Set(bundleDeps)\n : new Set<string>()\n for (const depType of longDependencyTypes) {\n const obj: Record<string, string> | undefined =\n node.manifest?.[depType]\n // only care about devDeps for importers and git or symlink deps\n // technically this will also include devDeps for tarball file: specs,\n // but that is likely rare enough to not worry about too much.\n if (\n depType === 'devDependencies' &&\n !node.importer &&\n !node.id.startsWith('git') &&\n !node.id.startsWith('file')\n ) {\n continue\n }\n if (obj) {\n for (const [name, bareSpec] of Object.entries(obj)) {\n // if it's a bundled dependency, we just ignore it entirely.\n if (bundled.has(name)) continue\n dependencies.set(name, {\n name,\n type: depType,\n bareSpec,\n registry: node.registry,\n })\n }\n }\n }\n return dependencies\n}\n\n/**\n * Reads the current directory defined at `currDir` and looks for folder\n * names and their realpath resolution, normalizing scoped package names\n * and removing any invalid symlinks from the list of items that should\n * be parsed through in order to build the graph.\n */\nconst readDir = (\n scurry: PathScurry,\n currDir: Path,\n fromNodeName?: string,\n) => {\n const res = new Set<ReadEntry>()\n for (const entry of scurry.readdirSync(currDir)) {\n // ignore any hidden files / folders\n if (entry.name.startsWith('.')) continue\n\n // scope folder found, it will need to be read and iterated over\n // in order to find any scoped packages inside\n if (entry.name.startsWith('@')) {\n const scopedItems = readDir(scurry, entry, fromNodeName)\n for (const scopedItem of scopedItems) {\n res.add(scopedItem)\n }\n continue\n }\n\n // skip anything that isn't a symlink, it's not an edge\n if (!entry.isSymbolicLink()) continue\n\n // we'll need to learn what is the real path for this entry in order\n // to retrieve the `location` and `id` properties for the node, if a\n // realpath is not found just move on to the next element\n const realpath = entry.realpathSync()\n if (!realpath) {\n continue\n }\n\n // infer both the alias and proper package names, including scopes\n const alias = findName(entry)\n const name = findName(realpath)\n res.add({\n alias,\n name,\n realpath,\n })\n }\n return res\n}\n\n/**\n * Parses the files located at `currDir` and place packages found inside\n * as dependencies of `fromNode`, building the instantiated `graph`.\n */\nconst parseDir = (\n options: LoadOptions,\n scurry: PathScurry,\n packageJson: PackageJson,\n depsFound: Map<Node, Path>,\n graph: Graph,\n fromNode: Node,\n currDir: Path,\n) => {\n const { loadManifests } = options\n const dependencies = getDeps(fromNode)\n const seenDeps = new Set<string>()\n const readItems: Set<ReadEntry> = readDir(\n scurry,\n currDir,\n fromNode.name,\n )\n\n for (const { alias, name, realpath } of readItems) {\n let node\n\n // tracks what dependencies have been seen\n // so that we can mark missing dependencies\n seenDeps.add(alias)\n\n // places the package in the graph reading\n // its manifest only if necessary\n if (!loadManifests) {\n const depId = findDepID(realpath)\n\n if (depId) {\n const h = hydrate(depId, alias, {\n ...options,\n registry: fromNode.registry,\n })\n\n // graphs build with no manifest have no notion of\n // dependency types and or spec definitions since those\n // would have to be parsed from a manifest\n node = graph.placePackage(\n fromNode,\n 'prod', // defaults to prod deps\n h, // uses spec from hydrated id\n {\n name,\n ...(h.registrySpec ?\n { version: h.registrySpec } // adds version if available\n : null),\n },\n depId,\n )\n }\n }\n\n // retrieve references to the current folder name found in `fromNode`\n // manifest listed dependencies, removing it from the map will leave\n // a list of missing dependencies at the end of the iteration\n const deps = dependencies.get(alias)\n\n // in case this graph is skipping manifests, this next block might\n // still need to execute, thus actually loading a manifest file, for\n // edge-cases such as loading a linked node that is not going to have\n // DepID info available in its realpath or extraneous nodes\n if (!node) {\n const mani = packageJson.read(realpath.fullpath())\n // declares fallback default values for both depType and bareSpec\n // in order to support loadManifests=false fallback for link nodes\n const type = deps?.type || 'dependencies'\n const bareSpec = deps?.bareSpec || '*'\n\n const depType = shorten(type, alias, fromNode.manifest)\n const spec = Spec.parse(alias, bareSpec, {\n ...options,\n registry: fromNode.registry,\n })\n const maybeId = getPathBasedId(spec, realpath.relativePosix())\n node = graph.placePackage(\n fromNode,\n depType,\n spec,\n mani,\n maybeId,\n )\n }\n\n if (node) {\n // If a found dependency is not declared in any of the original\n // node dependencies, then add an edge to the graph pointing to it\n // and mark it as extraneous.\n //\n // This only makes sense if full manifests are being loaded\n // so that we have reference to dependencies info.\n if (loadManifests && !deps) {\n const [edge] = node.edgesIn\n if (edge) {\n graph.extraneousDependencies.add(edge)\n }\n }\n\n // for a succesfully created node, add its location\n // property and queue up to read its dependencies\n node.location = `./${realpath.relativePosix()}`\n const node_modules = findNodeModules(realpath)\n\n // queue items up to continue parsing dirs in case a node was succesfully\n // placed in the graph and its node_modules folder was correctly found\n if (node_modules) {\n depsFound.set(node, node_modules)\n }\n }\n }\n\n // any remaining dependencies that have not been found\n // when reading the directory should be marked as missing\n for (const { name, type, bareSpec } of dependencies.values()) {\n if (!seenDeps.has(name)) {\n const depType = shorten(type, name, fromNode.manifest)\n const spec = Spec.parse(name, bareSpec, {\n ...options,\n registry: fromNode.registry,\n })\n graph.placePackage(fromNode, depType, spec)\n }\n }\n}\n\n/**\n * Read the file system looking for `node_modules` folders and\n * returns a new {@link Graph} that represents the relationship\n * between the dependencies found.\n */\nexport const load = (options: LoadOptions): Graph => {\n // TODO: once hidden lockfile is more reliable, default to false here\n const {\n skipHiddenLockfile = true,\n projectRoot,\n packageJson,\n scurry,\n monorepo,\n } = options\n const mainManifest =\n options.mainManifest ?? packageJson.read(projectRoot)\n\n if (!skipHiddenLockfile) {\n try {\n const graph = loadHidden({\n projectRoot,\n mainManifest,\n packageJson,\n monorepo,\n scurry,\n })\n // TODO: check mtime of lockfile vs .vlt folder\n return graph\n } catch {}\n }\n\n const graph = new Graph({ ...options, mainManifest })\n const depsFound = new Map<Node, Path>()\n\n // starts the list of initial folders to parse using the importer nodes\n for (const importer of graph.importers) {\n depsFound.set(\n importer,\n scurry.cwd.resolve(`${importer.location}/node_modules`),\n )\n }\n\n // breadth-first traversal of the file system tree reading deps found\n // starting from the node_modules folder of every importer in order to\n // find the actual installed dependencies at each location\n for (const [node, path] of depsFound.entries()) {\n parseDir(\n options,\n scurry,\n packageJson,\n depsFound,\n graph,\n node,\n path,\n )\n }\n\n return graph\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { asDependencyTypeShort } from './dependencies.js';
2
+ import { getBooleanFlagsFromNum } from './lockfile/types.js';
3
+ import { stringifyNode } from './stringify-node.js';
4
+ declare const lockfile: {
5
+ loadEdges: (graph: import("./types.js").GraphLike, edges: import("./lockfile/types.js").LockfileData["edges"], options: import("@vltpkg/spec").SpecOptions) => void;
6
+ loadNodes: (graph: import("./types.js").GraphLike, nodes: import("./lockfile/types.js").LockfileData["nodes"]) => void;
7
+ };
8
+ export { asDependencyTypeShort, getBooleanFlagsFromNum, lockfile, stringifyNode, };
9
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAInD,QAAA,MAAM,QAAQ;;;CAGb,CAAA;AAED,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,QAAQ,EACR,aAAa,GACd,CAAA"}
@@ -0,0 +1,11 @@
1
+ import { asDependencyTypeShort } from './dependencies.js';
2
+ import { getBooleanFlagsFromNum } from './lockfile/types.js';
3
+ import { stringifyNode } from './stringify-node.js';
4
+ import { loadEdges } from './lockfile/load-edges.js';
5
+ import { loadNodes } from './lockfile/load-nodes.js';
6
+ const lockfile = {
7
+ loadEdges,
8
+ loadNodes,
9
+ };
10
+ export { asDependencyTypeShort, getBooleanFlagsFromNum, lockfile, stringifyNode, };
11
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAEpD,MAAM,QAAQ,GAAG;IACf,SAAS;IACT,SAAS;CACV,CAAA;AAED,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,QAAQ,EACR,aAAa,GACd,CAAA","sourcesContent":["import { asDependencyTypeShort } from './dependencies.js'\nimport { getBooleanFlagsFromNum } from './lockfile/types.js'\nimport { stringifyNode } from './stringify-node.js'\nimport { loadEdges } from './lockfile/load-edges.js'\nimport { loadNodes } from './lockfile/load-nodes.js'\n\nconst lockfile = {\n loadEdges,\n loadNodes,\n}\n\nexport {\n asDependencyTypeShort,\n getBooleanFlagsFromNum,\n lockfile,\n stringifyNode,\n}\n"]}
@@ -0,0 +1,69 @@
1
+ import type { DepID } from '@vltpkg/dep-id';
2
+ import { type Spec } from '@vltpkg/spec';
3
+ import { type Manifest } from '@vltpkg/types';
4
+ /**
5
+ * Name of the package.json keys used to define different types of dependencies.
6
+ */
7
+ export type DependencyTypeLong = 'dependencies' | 'devDependencies' | 'optionalDependencies' | 'peerDependencies';
8
+ /**
9
+ * Unique keys that define different types of dependencies relationship.
10
+ */
11
+ export type DependencyTypeShort = 'dev' | 'optional' | 'peer' | 'peerOptional' | 'prod';
12
+ export declare const isDependencyTypeShort: (obj: any) => obj is DependencyTypeShort;
13
+ export declare const asDependencyTypeShort: (obj: any) => DependencyTypeShort;
14
+ /**
15
+ * Dependency entries info as defined in a package.json file.
16
+ */
17
+ export type RawDependency = {
18
+ name: string;
19
+ bareSpec: string;
20
+ type: DependencyTypeLong;
21
+ registry?: string;
22
+ };
23
+ /**
24
+ * Parsed dependency entries info.
25
+ */
26
+ export type Dependency = {
27
+ /**
28
+ * The parsed {@link Spec} object describing the dependency requirements.
29
+ */
30
+ spec: Spec;
31
+ /**
32
+ * The {@link DependencyTypeShort}, describing the type of dependency.
33
+ */
34
+ type: DependencyTypeShort;
35
+ };
36
+ /**
37
+ * A `Map` in which keys are {@link DepID} linking to another `Map` in which
38
+ * keys are the dependency names and values are {@link Dependency}. This
39
+ * structure represents dependencies that need to be added to the importer
40
+ * represented by {@link DepID}.
41
+ */
42
+ export type AddImportersDependenciesMap = Map<DepID, Map<string, Dependency>>;
43
+ /**
44
+ * A `Map` object representing nodes to be removed from the ideal graph.
45
+ * Each {@link DepID} key represents an importer node and the `Set` of
46
+ * dependency names to be removed from its dependency list.
47
+ */
48
+ export type RemoveImportersDependenciesMap = Map<DepID, Set<string>>;
49
+ export declare const isDependency: (obj: any) => obj is Dependency;
50
+ export declare const asDependency: (obj: any) => Dependency;
51
+ /**
52
+ * A set of the possible long dependency type names,
53
+ * as used in `package.json` files.
54
+ */
55
+ export declare const longDependencyTypes: Set<DependencyTypeLong>;
56
+ /**
57
+ * A set of the short type keys used to represent dependency relationships.
58
+ */
59
+ export declare const shortDependencyTypes: Set<DependencyTypeShort>;
60
+ /**
61
+ * Maps between long form names usually used in `package.json` files
62
+ * to a corresponding short form name, used in lockfiles.
63
+ */
64
+ export declare const dependencyTypes: Map<DependencyTypeLong, DependencyTypeShort>;
65
+ /**
66
+ * Get the {@link DependencyTypeShort} from a {@link DependencyTypeLong}.
67
+ */
68
+ export declare const shorten: (typeLong: DependencyTypeLong, name?: string, manifest?: Manifest) => DependencyTypeShort;
69
+ //# sourceMappingURL=dependencies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAE3C,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7C;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B,cAAc,GACd,iBAAiB,GACjB,sBAAsB,GACtB,kBAAkB,CAAA;AAEtB;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAC3B,KAAK,GACL,UAAU,GACV,MAAM,GACN,cAAc,GACd,MAAM,CAAA;AAEV,eAAO,MAAM,qBAAqB,QAC3B,GAAG,KACP,GAAG,IAAI,mBAAoD,CAAA;AAE9D,eAAO,MAAM,qBAAqB,QAC3B,GAAG,KACP,mBAQF,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,kBAAkB,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB;;OAEG;IACH,IAAI,EAAE,IAAI,CAAA;IACV;;OAEG;IACH,IAAI,EAAE,mBAAmB,CAAA;CAC1B,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,2BAA2B,GAAG,GAAG,CAC3C,KAAK,EACL,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CACxB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,8BAA8B,GAAG,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;AAEpE,eAAO,MAAM,YAAY,QAAS,GAAG,KAAG,GAAG,IAAI,UAEmB,CAAA;AAElE,eAAO,MAAM,YAAY,QAAS,GAAG,KAAG,UAKvC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,yBAK9B,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,0BAM/B,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,8CAQ1B,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,OAAO,aACR,kBAAkB,SACrB,MAAM,aACF,QAAQ,KAClB,mBAkBF,CAAA"}
@@ -0,0 +1,71 @@
1
+ import { error } from '@vltpkg/error-cause';
2
+ export const isDependencyTypeShort = (obj) => shortDependencyTypes.has(obj);
3
+ export const asDependencyTypeShort = (obj) => {
4
+ if (!isDependencyTypeShort(obj)) {
5
+ throw error('Invalid dependency type', {
6
+ found: obj,
7
+ validOptions: [...shortDependencyTypes],
8
+ });
9
+ }
10
+ return obj;
11
+ };
12
+ export const isDependency = (obj) =>
13
+ // TODO: it would be nice to have a @vltpkg/spec.isSpec method
14
+ obj?.spec?.type && obj?.type && isDependencyTypeShort(obj?.type);
15
+ export const asDependency = (obj) => {
16
+ if (!isDependency(obj)) {
17
+ throw error('Invalid dependency', { found: obj });
18
+ }
19
+ return obj;
20
+ };
21
+ /**
22
+ * A set of the possible long dependency type names,
23
+ * as used in `package.json` files.
24
+ */
25
+ export const longDependencyTypes = new Set([
26
+ 'dependencies',
27
+ 'devDependencies',
28
+ 'peerDependencies',
29
+ 'optionalDependencies',
30
+ ]);
31
+ /**
32
+ * A set of the short type keys used to represent dependency relationships.
33
+ */
34
+ export const shortDependencyTypes = new Set([
35
+ 'prod',
36
+ 'dev',
37
+ 'peer',
38
+ 'optional',
39
+ 'peerOptional',
40
+ ]);
41
+ /**
42
+ * Maps between long form names usually used in `package.json` files
43
+ * to a corresponding short form name, used in lockfiles.
44
+ */
45
+ export const dependencyTypes = new Map([
46
+ ['dependencies', 'prod'],
47
+ ['devDependencies', 'dev'],
48
+ ['peerDependencies', 'peer'],
49
+ ['optionalDependencies', 'optional'],
50
+ ]);
51
+ /**
52
+ * Get the {@link DependencyTypeShort} from a {@link DependencyTypeLong}.
53
+ */
54
+ export const shorten = (typeLong, name, manifest) => {
55
+ const shortName = dependencyTypes.get(typeLong);
56
+ if (!shortName) {
57
+ throw error('Invalid dependency type name', {
58
+ found: typeLong,
59
+ validOptions: [...longDependencyTypes],
60
+ });
61
+ }
62
+ if (shortName !== 'peer') {
63
+ return shortName;
64
+ }
65
+ if (name &&
66
+ manifest?.peerDependenciesMeta?.[name]?.optional === true) {
67
+ return 'peerOptional';
68
+ }
69
+ return 'peer';
70
+ };
71
+ //# sourceMappingURL=dependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../src/dependencies.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAuB3C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,GAAQ,EACoB,EAAE,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAE9D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,GAAQ,EACa,EAAE;IACvB,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,CAAC;QAChC,MAAM,KAAK,CAAC,yBAAyB,EAAE;YACrC,KAAK,EAAE,GAAG;YACV,YAAY,EAAE,CAAC,GAAG,oBAAoB,CAAC;SACxC,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AA4CD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAQ,EAAqB,EAAE;AAC1D,8DAA8D;AAC9D,GAAG,EAAE,IAAI,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,IAAI,qBAAqB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;AAElE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAQ,EAAc,EAAE;IACnD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,KAAK,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;IACnD,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAqB;IAC7D,cAAc;IACd,iBAAiB;IACjB,kBAAkB;IAClB,sBAAsB;CACvB,CAAC,CAAA;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAsB;IAC/D,MAAM;IACN,KAAK;IACL,MAAM;IACN,UAAU;IACV,cAAc;CACf,CAAC,CAAA;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,GAAG,CAGpC;IACA,CAAC,cAAc,EAAE,MAAM,CAAC;IACxB,CAAC,iBAAiB,EAAE,KAAK,CAAC;IAC1B,CAAC,kBAAkB,EAAE,MAAM,CAAC;IAC5B,CAAC,sBAAsB,EAAE,UAAU,CAAC;CACrC,CAAC,CAAA;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CACrB,QAA4B,EAC5B,IAAa,EACb,QAAmB,EACE,EAAE;IACvB,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC/C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,KAAK,CAAC,8BAA8B,EAAE;YAC1C,KAAK,EAAE,QAAQ;YACf,YAAY,EAAE,CAAC,GAAG,mBAAmB,CAAC;SACvC,CAAC,CAAA;IACJ,CAAC;IACD,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,IACE,IAAI;QACJ,QAAQ,EAAE,oBAAoB,EAAE,CAAC,IAAI,CAAC,EAAE,QAAQ,KAAK,IAAI,EACzD,CAAC;QACD,OAAO,cAAc,CAAA;IACvB,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC,CAAA","sourcesContent":["import type { DepID } from '@vltpkg/dep-id'\nimport { error } from '@vltpkg/error-cause'\nimport { type Spec } from '@vltpkg/spec'\nimport { type Manifest } from '@vltpkg/types'\n\n/**\n * Name of the package.json keys used to define different types of dependencies.\n */\nexport type DependencyTypeLong =\n | 'dependencies'\n | 'devDependencies'\n | 'optionalDependencies'\n | 'peerDependencies'\n\n/**\n * Unique keys that define different types of dependencies relationship.\n */\nexport type DependencyTypeShort =\n | 'dev'\n | 'optional'\n | 'peer'\n | 'peerOptional'\n | 'prod'\n\nexport const isDependencyTypeShort = (\n obj: any,\n): obj is DependencyTypeShort => shortDependencyTypes.has(obj)\n\nexport const asDependencyTypeShort = (\n obj: any,\n): DependencyTypeShort => {\n if (!isDependencyTypeShort(obj)) {\n throw error('Invalid dependency type', {\n found: obj,\n validOptions: [...shortDependencyTypes],\n })\n }\n return obj\n}\n\n/**\n * Dependency entries info as defined in a package.json file.\n */\nexport type RawDependency = {\n name: string\n bareSpec: string\n type: DependencyTypeLong\n registry?: string\n}\n\n/**\n * Parsed dependency entries info.\n */\nexport type Dependency = {\n /**\n * The parsed {@link Spec} object describing the dependency requirements.\n */\n spec: Spec\n /**\n * The {@link DependencyTypeShort}, describing the type of dependency.\n */\n type: DependencyTypeShort\n}\n\n/**\n * A `Map` in which keys are {@link DepID} linking to another `Map` in which\n * keys are the dependency names and values are {@link Dependency}. This\n * structure represents dependencies that need to be added to the importer\n * represented by {@link DepID}.\n */\nexport type AddImportersDependenciesMap = Map<\n DepID,\n Map<string, Dependency>\n>\n\n/**\n * A `Map` object representing nodes to be removed from the ideal graph.\n * Each {@link DepID} key represents an importer node and the `Set` of\n * dependency names to be removed from its dependency list.\n */\nexport type RemoveImportersDependenciesMap = Map<DepID, Set<string>>\n\nexport const isDependency = (obj: any): obj is Dependency =>\n // TODO: it would be nice to have a @vltpkg/spec.isSpec method\n obj?.spec?.type && obj?.type && isDependencyTypeShort(obj?.type)\n\nexport const asDependency = (obj: any): Dependency => {\n if (!isDependency(obj)) {\n throw error('Invalid dependency', { found: obj })\n }\n return obj\n}\n\n/**\n * A set of the possible long dependency type names,\n * as used in `package.json` files.\n */\nexport const longDependencyTypes = new Set<DependencyTypeLong>([\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'optionalDependencies',\n])\n\n/**\n * A set of the short type keys used to represent dependency relationships.\n */\nexport const shortDependencyTypes = new Set<DependencyTypeShort>([\n 'prod',\n 'dev',\n 'peer',\n 'optional',\n 'peerOptional',\n])\n\n/**\n * Maps between long form names usually used in `package.json` files\n * to a corresponding short form name, used in lockfiles.\n */\nexport const dependencyTypes = new Map<\n DependencyTypeLong,\n DependencyTypeShort\n>([\n ['dependencies', 'prod'],\n ['devDependencies', 'dev'],\n ['peerDependencies', 'peer'],\n ['optionalDependencies', 'optional'],\n])\n\n/**\n * Get the {@link DependencyTypeShort} from a {@link DependencyTypeLong}.\n */\nexport const shorten = (\n typeLong: DependencyTypeLong,\n name?: string,\n manifest?: Manifest,\n): DependencyTypeShort => {\n const shortName = dependencyTypes.get(typeLong)\n if (!shortName) {\n throw error('Invalid dependency type name', {\n found: typeLong,\n validOptions: [...longDependencyTypes],\n })\n }\n if (shortName !== 'peer') {\n return shortName\n }\n if (\n name &&\n manifest?.peerDependenciesMeta?.[name]?.optional === true\n ) {\n return 'peerOptional'\n }\n return 'peer'\n}\n"]}
@@ -0,0 +1,49 @@
1
+ import { InspectOptions } from 'node:util';
2
+ import { Edge } from './edge.js';
3
+ import { Graph } from './graph.js';
4
+ import { Node } from './node.js';
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
+ get [Symbol.toStringTag](): string;
45
+ constructor(from: Graph, to: Graph);
46
+ [kCustomInspect](_: number, options?: InspectOptions): string;
47
+ }
48
+ export {};
49
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/diff.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAOhC,QAAA,MAAM,cAAc,eAA2C,CAAA;AAE/D;;;;;;;;;;GAUG;AACH,qBAAa,IAAI;IACf,IAAI,EAAE,KAAK,CAAA;IACX,EAAE,EAAE,KAAK,CAAA;IAET,WAAW,EAAE,MAAM,CAAA;IAEnB;;;OAGG;IACH,mBAAmB,UAAQ;IAE3B;;OAEG;IACH,KAAK;QACH,+DAA+D;;QAE/D,+DAA+D;;MAEhE;IAED;;OAEG;IACH,KAAK;QACH,qEAAqE;;QAErE,qEAAqE;;MAEtE;IAED,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,WAEvB;gBAEW,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK;IAyClC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM;CAuC9D"}