@vltpkg/cli-js 0.0.0-7

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 (128) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +10 -0
  3. package/cache-unzip-src-unzip.js +7896 -0
  4. package/cache-unzip-src-unzip.js.map +7 -0
  5. package/chunk-36Z4IEW5.js +1010 -0
  6. package/chunk-36Z4IEW5.js.map +7 -0
  7. package/chunk-433RK6QP.js +72 -0
  8. package/chunk-433RK6QP.js.map +7 -0
  9. package/chunk-457WPPV5.js +969 -0
  10. package/chunk-457WPPV5.js.map +7 -0
  11. package/chunk-66GJ6BNX.js +2666 -0
  12. package/chunk-66GJ6BNX.js.map +7 -0
  13. package/chunk-AYOLWFFJ.js +10972 -0
  14. package/chunk-AYOLWFFJ.js.map +7 -0
  15. package/chunk-GQLKOYXI.js +1451 -0
  16. package/chunk-GQLKOYXI.js.map +7 -0
  17. package/chunk-GU2E2KHZ.js +152 -0
  18. package/chunk-GU2E2KHZ.js.map +7 -0
  19. package/chunk-H75RQSUK.js +5413 -0
  20. package/chunk-H75RQSUK.js.map +7 -0
  21. package/chunk-LJEVKV7R.js +36 -0
  22. package/chunk-LJEVKV7R.js.map +7 -0
  23. package/chunk-MF4RCNHU.js +71 -0
  24. package/chunk-MF4RCNHU.js.map +7 -0
  25. package/chunk-NM754OFF.js +1104 -0
  26. package/chunk-NM754OFF.js.map +7 -0
  27. package/chunk-OGUMFXHI.js +1136 -0
  28. package/chunk-OGUMFXHI.js.map +7 -0
  29. package/chunk-OKDQY2GQ.js +1866 -0
  30. package/chunk-OKDQY2GQ.js.map +7 -0
  31. package/chunk-OOZN2US4.js +61 -0
  32. package/chunk-OOZN2US4.js.map +7 -0
  33. package/chunk-OSVOPGNL.js +782 -0
  34. package/chunk-OSVOPGNL.js.map +7 -0
  35. package/chunk-PKKWJ5FM.js +11836 -0
  36. package/chunk-PKKWJ5FM.js.map +7 -0
  37. package/chunk-PPTEV6PS.js +27 -0
  38. package/chunk-PPTEV6PS.js.map +7 -0
  39. package/chunk-S7LRSSDW.js +40 -0
  40. package/chunk-S7LRSSDW.js.map +7 -0
  41. package/chunk-SJZXAMQQ.js +5233 -0
  42. package/chunk-SJZXAMQQ.js.map +7 -0
  43. package/chunk-TV2RDGWY.js +181 -0
  44. package/chunk-TV2RDGWY.js.map +7 -0
  45. package/chunk-V4TLWRQW.js +34 -0
  46. package/chunk-V4TLWRQW.js.map +7 -0
  47. package/chunk-VIE5PVDF.js +21788 -0
  48. package/chunk-VIE5PVDF.js.map +7 -0
  49. package/chunk-VO2MAWDF.js +53 -0
  50. package/chunk-VO2MAWDF.js.map +7 -0
  51. package/chunk-XCC42LF5.js +511 -0
  52. package/chunk-XCC42LF5.js.map +7 -0
  53. package/chunk-YS3ZYKCN.js +6499 -0
  54. package/chunk-YS3ZYKCN.js.map +7 -0
  55. package/chunk-ZLP22ACI.js +65 -0
  56. package/chunk-ZLP22ACI.js.map +7 -0
  57. package/chunk-ZSTAQQQN.js +2070 -0
  58. package/chunk-ZSTAQQQN.js.map +7 -0
  59. package/cli-package.json +104 -0
  60. package/config-M6ZTMEJC.js +184 -0
  61. package/config-M6ZTMEJC.js.map +7 -0
  62. package/devtools-PSS6DSS6.js +16681 -0
  63. package/devtools-PSS6DSS6.js.map +7 -0
  64. package/exec-5Q6ZP6JI.js +48 -0
  65. package/exec-5Q6ZP6JI.js.map +7 -0
  66. package/gui-667EH2M7.js +44 -0
  67. package/gui-667EH2M7.js.map +7 -0
  68. package/gui-assets/favicon.ico +0 -0
  69. package/gui-assets/fonts/courier-bold-italic.ttf +0 -0
  70. package/gui-assets/fonts/courier-bold.ttf +0 -0
  71. package/gui-assets/fonts/courier-italic.ttf +0 -0
  72. package/gui-assets/fonts/courier-regular.ttf +0 -0
  73. package/gui-assets/fonts/geist-mono.ttf +0 -0
  74. package/gui-assets/fonts/inter.ttf +0 -0
  75. package/gui-assets/images/folder.png +0 -0
  76. package/gui-assets/index.html +34 -0
  77. package/gui-assets/index.js +1573 -0
  78. package/gui-assets/index.js.map +7 -0
  79. package/gui-assets/main.css +1 -0
  80. package/help-JZ3VD6MH.js +24 -0
  81. package/help-JZ3VD6MH.js.map +7 -0
  82. package/init-4JOBGJ4C.js +24 -0
  83. package/init-4JOBGJ4C.js.map +7 -0
  84. package/install-I6UDMAKJ.js +53 -0
  85. package/install-I6UDMAKJ.js.map +7 -0
  86. package/install-exec-BGKORQDZ.js +27 -0
  87. package/install-exec-BGKORQDZ.js.map +7 -0
  88. package/list-NKJNNDAV.js +138 -0
  89. package/list-NKJNNDAV.js.map +7 -0
  90. package/login-5X5JKFYS.js +35 -0
  91. package/login-5X5JKFYS.js.map +7 -0
  92. package/logout-5NO6B4BW.js +35 -0
  93. package/logout-5NO6B4BW.js.map +7 -0
  94. package/package.json +25 -0
  95. package/pkg-CUX23YND.js +363 -0
  96. package/pkg-CUX23YND.js.map +7 -0
  97. package/query-XWAQ6U4O.js +126 -0
  98. package/query-XWAQ6U4O.js.map +7 -0
  99. package/registry-client-package.json +84 -0
  100. package/reporter-GV7DMKAK.js +17 -0
  101. package/reporter-GV7DMKAK.js.map +7 -0
  102. package/rollback-remove-src-remove.js +7397 -0
  103. package/rollback-remove-src-remove.js.map +7 -0
  104. package/run-GJDCKL7X.js +66 -0
  105. package/run-GJDCKL7X.js.map +7 -0
  106. package/run-exec-L3RGBBPL.js +39 -0
  107. package/run-exec-L3RGBBPL.js.map +7 -0
  108. package/source-ALZ2QHEZ.js +32 -0
  109. package/source-ALZ2QHEZ.js.map +7 -0
  110. package/src-XRLOORCU.js +92 -0
  111. package/src-XRLOORCU.js.map +7 -0
  112. package/token-JLM4D6QR.js +85 -0
  113. package/token-JLM4D6QR.js.map +7 -0
  114. package/uninstall-X72YAQHZ.js +53 -0
  115. package/uninstall-X72YAQHZ.js.map +7 -0
  116. package/vlix.js +13 -0
  117. package/vlix.js.map +7 -0
  118. package/vlr.js +13 -0
  119. package/vlr.js.map +7 -0
  120. package/vlrx.js +13 -0
  121. package/vlrx.js.map +7 -0
  122. package/vlt.js +13 -0
  123. package/vlt.js.map +7 -0
  124. package/vlx.js +13 -0
  125. package/vlx.js.map +7 -0
  126. package/whoami-CMKBD6ZT.js +45 -0
  127. package/whoami-CMKBD6ZT.js.map +7 -0
  128. package/yoga.wasm +0 -0
@@ -0,0 +1,2666 @@
1
+ var global = globalThis;
2
+ import {setTimeout,clearTimeout,setImmediate,clearImmediate,setInterval,clearInterval} from "node:timers";
3
+ import {createRequire as _vlt_createRequire} from "node:module";
4
+ var require = _vlt_createRequire(import.meta.filename);
5
+ import {
6
+ rimraf
7
+ } from "./chunk-OSVOPGNL.js";
8
+ import {
9
+ platformCheck
10
+ } from "./chunk-TV2RDGWY.js";
11
+ import {
12
+ graphStep
13
+ } from "./chunk-V4TLWRQW.js";
14
+ import {
15
+ run
16
+ } from "./chunk-OGUMFXHI.js";
17
+ import {
18
+ Monorepo,
19
+ asDepID,
20
+ getId,
21
+ graphRun,
22
+ hydrate,
23
+ hydrateTuple,
24
+ joinDepIDTuple,
25
+ splitDepID
26
+ } from "./chunk-457WPPV5.js";
27
+ import {
28
+ PackageJson,
29
+ Spec,
30
+ Spec2,
31
+ Version,
32
+ defaultGitHostArchives,
33
+ defaultGitHosts,
34
+ defaultRegistries,
35
+ defaultRegistry,
36
+ defaultScopeRegistries,
37
+ dependencyTypes,
38
+ fastSplit,
39
+ longDependencyTypes,
40
+ parse,
41
+ shortDependencyTypes
42
+ } from "./chunk-OKDQY2GQ.js";
43
+ import {
44
+ error,
45
+ typeError
46
+ } from "./chunk-LJEVKV7R.js";
47
+
48
+ // ../../src/graph/src/visualization/json-output.ts
49
+ function jsonOutput({ edges, nodes }) {
50
+ const res = [];
51
+ for (const node of nodes) {
52
+ if (node.importer) {
53
+ res.push({
54
+ /* c8 ignore next - name can't be missing but ts won't know */
55
+ name: node.name || node.id,
56
+ to: node
57
+ });
58
+ }
59
+ }
60
+ for (const edge of edges) {
61
+ res.push({
62
+ name: edge.name,
63
+ fromID: edge.from.id,
64
+ spec: String(edge.spec),
65
+ type: edge.type,
66
+ to: edge.to
67
+ });
68
+ }
69
+ return res;
70
+ }
71
+
72
+ // ../../src/graph/src/visualization/human-readable-output.ts
73
+ var chars = new Map(
74
+ Object.entries({
75
+ connection: "\u2500",
76
+ down: "\u2502",
77
+ "last-child": "\u2514",
78
+ "middle-child": "\u251C",
79
+ t: "\u252C"
80
+ })
81
+ );
82
+ var isSelected = (options, edge, node) => !!((!node || options.nodes.includes(node)) && (!edge || options.edges.includes(edge)));
83
+ var getTreeItems = (initialItems, options) => {
84
+ const seenNodes = /* @__PURE__ */ new Set();
85
+ const treeItems = /* @__PURE__ */ new Map();
86
+ const traverse = new Set(initialItems);
87
+ for (const item of traverse) {
88
+ if (item.node) {
89
+ if (seenNodes.has(item.node)) {
90
+ item.deduped = true;
91
+ continue;
92
+ }
93
+ seenNodes.add(item.node);
94
+ const edges = [...item.node.edgesOut.values()].sort(
95
+ (i) => Number(i.to?.importer)
96
+ );
97
+ for (const edge of edges) {
98
+ const toItems = treeItems.get(edge) ?? /* @__PURE__ */ new Map();
99
+ const nextItem = {
100
+ edge,
101
+ node: edge.to,
102
+ hasSibling: false,
103
+ padding: "",
104
+ prefix: "",
105
+ deduped: false,
106
+ include: isSelected(options, edge, edge.to),
107
+ parent: item
108
+ };
109
+ toItems.set(edge.to, nextItem);
110
+ treeItems.set(edge, toItems);
111
+ traverse.add(nextItem);
112
+ }
113
+ }
114
+ }
115
+ for (const item of [...traverse].reverse()) {
116
+ if (item.include && item.parent) {
117
+ item.parent.include = true;
118
+ }
119
+ }
120
+ return treeItems;
121
+ };
122
+ function humanReadableOutput(options, { colors }) {
123
+ const { importers } = options;
124
+ const noop = (s) => s;
125
+ const {
126
+ dim = noop,
127
+ red = noop,
128
+ reset = noop,
129
+ yellow = noop
130
+ } = colors ?? {};
131
+ const initialItems = /* @__PURE__ */ new Set();
132
+ for (const importer of importers) {
133
+ initialItems.add({
134
+ name: importer.name,
135
+ edge: void 0,
136
+ node: importer,
137
+ prefix: "",
138
+ padding: "",
139
+ hasSibling: false,
140
+ deduped: false,
141
+ include: isSelected(options, void 0, importer),
142
+ parent: void 0
143
+ });
144
+ }
145
+ const treeItems = getTreeItems(initialItems, options);
146
+ let res = "";
147
+ const traverse = (item) => {
148
+ let header = "";
149
+ let content = "";
150
+ const depIdTuple = item.node?.id && splitDepID(item.node.id);
151
+ const hasCustomReg = depIdTuple?.[0] === "registry" && depIdTuple[1];
152
+ const name = hasCustomReg ? `${depIdTuple[1]}:${item.name}` : item.name;
153
+ const decoratedName = options.highlightSelection && isSelected(options, item.edge, item.node) ? yellow(name) : name;
154
+ if (!item.node && item.include) {
155
+ const missing = item.edge?.type.endsWith("ptional") ? dim("(missing optional)") : red("(missing)");
156
+ return `${item.padding}${item.prefix}${decoratedName} ${missing}
157
+ `;
158
+ }
159
+ const deduped = item.deduped ? ` ${dim("(deduped)")}` : "";
160
+ header += `${item.padding}${item.prefix}${decoratedName}${deduped}
161
+ `;
162
+ if (!item.deduped) {
163
+ const edges = item.node ? [...item.node.edgesOut.values()] : [];
164
+ const nextItems = edges.map((i) => treeItems.get(i)?.get(i.to));
165
+ const includedItems = nextItems.filter((i) => i?.include);
166
+ for (const nextItem of nextItems) {
167
+ if (!nextItem) continue;
168
+ const parent = item;
169
+ const isLast = includedItems.indexOf(nextItem) === includedItems.length - 1;
170
+ const toName = nextItem.node?.version ? `${nextItem.node.name}@${nextItem.node.version}` : nextItem.node?.name;
171
+ const nextChar = isLast ? "last-child" : "middle-child";
172
+ nextItem.name = nextItem.node?.name && nextItem.edge?.name !== nextItem.edge?.to?.name ? `${nextItem.edge?.name} (${toName})` : `${nextItem.edge?.name}@${nextItem.node?.version || nextItem.edge?.spec.bareSpec}`;
173
+ nextItem.padding = parent.prefix.length ? `${parent.padding}${parent.hasSibling ? chars.get("down") : " "} ` : "";
174
+ nextItem.prefix = `${chars.get(nextChar)}${chars.get("connection")}${chars.get("connection")} `;
175
+ nextItem.hasSibling = !isLast;
176
+ content += traverse(nextItem);
177
+ }
178
+ }
179
+ const regularConnection = `${chars.get("connection")} `;
180
+ const parentConnection = `${chars.get("t")} `;
181
+ return item.include ? `${content ? header.replace(regularConnection, parentConnection) : header}${content}` : "";
182
+ };
183
+ for (const item of initialItems) {
184
+ res += traverse(item);
185
+ }
186
+ return reset(res);
187
+ }
188
+
189
+ // ../../src/satisfies/src/index.ts
190
+ import { relative, resolve } from "node:path";
191
+ var satisfies = (id, spec, fromLocation = process.cwd(), projectRoot = process.cwd(), monorepo) => !!id && satisfiesTuple(
192
+ splitDepID(id),
193
+ spec,
194
+ fromLocation,
195
+ projectRoot,
196
+ monorepo
197
+ );
198
+ var satisfiesTuple = (tuple, spec, fromLocation = process.cwd(), projectRoot = process.cwd(), monorepo) => {
199
+ const { options } = spec;
200
+ spec = spec.final;
201
+ const [type, first, second] = tuple;
202
+ if (spec.type !== type) return false;
203
+ switch (spec.type) {
204
+ case "registry": {
205
+ if (!first) {
206
+ if (spec.registry !== options.registry) {
207
+ return false;
208
+ }
209
+ } else {
210
+ const namedRegistry = options.registries[first];
211
+ if (namedRegistry && namedRegistry !== spec.registry) {
212
+ return false;
213
+ } else if (!namedRegistry && first !== spec.registry) {
214
+ return false;
215
+ }
216
+ }
217
+ if (!second) throw error("Invalid DepID", { found: tuple });
218
+ const [name, version] = parseNameVer(second);
219
+ return (
220
+ // mismatched name always invalid
221
+ name !== spec.name || !version ? false : !spec.range ? true : spec.range.test(Version.parse(version))
222
+ );
223
+ }
224
+ case "file": {
225
+ if (spec.file === void 0) return false;
226
+ const resolvedSpec = resolve(
227
+ projectRoot,
228
+ fromLocation,
229
+ spec.file
230
+ );
231
+ const resolvedId = resolve(projectRoot, first);
232
+ return !relative(resolvedSpec, resolvedId);
233
+ }
234
+ case "workspace": {
235
+ monorepo ??= Monorepo.load(projectRoot);
236
+ if (!spec.workspace) return false;
237
+ const fromID = monorepo.get(first);
238
+ const fromSpec = monorepo.get(spec.workspace);
239
+ if (fromID !== fromSpec || !fromSpec || !fromID) return false;
240
+ if (!spec.range) return true;
241
+ const v = parse(fromID.manifest.version ?? "");
242
+ return !!v && spec.range.test(v);
243
+ }
244
+ case "remote": {
245
+ return spec.remoteURL === first;
246
+ }
247
+ case "git": {
248
+ const {
249
+ gitRemote,
250
+ gitSelectorParsed = {},
251
+ gitSelector,
252
+ gitCommittish,
253
+ namedGitHost,
254
+ namedGitHostPath
255
+ } = spec;
256
+ if (gitRemote !== first) {
257
+ if (namedGitHost && namedGitHostPath) {
258
+ const ngh = `${namedGitHost}:`;
259
+ if (first.startsWith(ngh)) {
260
+ if (first !== ngh + namedGitHostPath) return false;
261
+ } else return false;
262
+ } else return false;
263
+ }
264
+ if (gitSelector && !second) return false;
265
+ const [parsed, committish] = Spec2.parseGitSelector(second ?? "");
266
+ if (gitCommittish && committish)
267
+ return !!committish.startsWith(gitCommittish);
268
+ for (const [k, v] of Object.entries(gitSelectorParsed)) {
269
+ if (parsed[k] !== v) return false;
270
+ }
271
+ return true;
272
+ }
273
+ /* c8 ignore start */
274
+ default: {
275
+ throw error("Invalid spec type", { spec });
276
+ }
277
+ }
278
+ };
279
+ var parseNameVer = (nv) => {
280
+ const at = nv.lastIndexOf("@");
281
+ return at <= 0 ? [nv, ""] : [nv.substring(0, at), nv.substring(at + 1)];
282
+ };
283
+
284
+ // ../../src/graph/src/edge.ts
285
+ import { inspect } from "node:util";
286
+ var kCustomInspect = Symbol.for("nodejs.util.inspect.custom");
287
+ var Edge = class {
288
+ get [Symbol.toStringTag]() {
289
+ return "@vltpkg/graph.Edge";
290
+ }
291
+ [kCustomInspect](_, options) {
292
+ const str = inspect(
293
+ {
294
+ from: this.from.id,
295
+ type: this.type,
296
+ spec: String(this.spec),
297
+ to: this.to?.id
298
+ },
299
+ options
300
+ );
301
+ return `${this[Symbol.toStringTag]} ${str}`;
302
+ }
303
+ /**
304
+ * The Node this Edge is connecting from, this is usually the dependent.
305
+ */
306
+ from;
307
+ /**
308
+ * The node this Edge is connecting to, this is usually a direct dependency.
309
+ */
310
+ to;
311
+ /**
312
+ * What type of dependency relationship `from` and `to` nodes have.
313
+ */
314
+ type;
315
+ /**
316
+ * The defined spec value for `to` as parsed from the dependent metadata.
317
+ */
318
+ spec;
319
+ constructor(type, spec, from, to) {
320
+ this.from = from;
321
+ this.to = to;
322
+ this.type = type;
323
+ this.spec = spec;
324
+ }
325
+ /**
326
+ * The name of the dependency `to` as defined in the dependent metadata.
327
+ */
328
+ get name() {
329
+ return this.spec.name;
330
+ }
331
+ /**
332
+ * This edge was defined as part of a `devDependencies` in `package.json`
333
+ */
334
+ get dev() {
335
+ return this.type === "dev";
336
+ }
337
+ get optional() {
338
+ return this.type === "peerOptional" || this.type === "optional";
339
+ }
340
+ get peer() {
341
+ return this.type === "peer" || this.type === "peerOptional";
342
+ }
343
+ get peerOptional() {
344
+ return this.type === "peerOptional";
345
+ }
346
+ valid() {
347
+ return !this.to ? this.optional : satisfies(
348
+ this.to.id,
349
+ this.spec,
350
+ this.from.location,
351
+ this.from.projectRoot
352
+ );
353
+ }
354
+ };
355
+
356
+ // ../../src/dep-id/src/browser.ts
357
+ var delimiter = "\xB7";
358
+ var depIDRegExp = new RegExp(
359
+ `^((git)?${delimiter}[^${delimiter}]*${delimiter}[^${delimiter}]*(${delimiter}[^${delimiter}]*)?$|^(file|remote|workspace)${delimiter}[^${delimiter}]*)(${delimiter}[^${delimiter}]*)?$`
360
+ );
361
+ var isDepID = (str) => typeof str === "string" && depIDRegExp.test(str);
362
+ var asDepID2 = (str) => {
363
+ if (!isDepID(str)) {
364
+ throw error("Expected dep id", {
365
+ found: str
366
+ });
367
+ }
368
+ return str;
369
+ };
370
+ var splitDepID2 = (id) => {
371
+ const [type, first = "", second, extra] = id.replaceAll("\xA7", "/").split(delimiter, 4);
372
+ const f = decodeURIComponent(first);
373
+ switch (type) {
374
+ case "git":
375
+ case "": {
376
+ if (second === void 0) {
377
+ throw error(`invalid ${type} id`, { found: id });
378
+ }
379
+ const t = [
380
+ type || "registry",
381
+ f,
382
+ decodeURIComponent(second)
383
+ ];
384
+ if (extra) t.push(decodeURIComponent(extra));
385
+ return t;
386
+ }
387
+ case "file":
388
+ case "remote":
389
+ case "workspace": {
390
+ const t = [type, f];
391
+ if (second) t.push(decodeURIComponent(second));
392
+ return t;
393
+ }
394
+ default: {
395
+ throw error("invalid DepID type", {
396
+ found: type,
397
+ validOptions: ["git", "file", "workspace", "remote", ""]
398
+ });
399
+ }
400
+ }
401
+ };
402
+ var hydrate2 = (id, name, options = {}) => hydrateTuple2(splitDepID2(id), name, options);
403
+ var hydrateTuple2 = (tuple, name, options = {}) => {
404
+ const [type, first, second] = tuple;
405
+ switch (type) {
406
+ case "remote": {
407
+ if (!first)
408
+ throw error("no remoteURL found on remote id", {
409
+ found: tuple
410
+ });
411
+ return Spec.parse(name ?? "(unknown)", first);
412
+ }
413
+ case "file": {
414
+ if (!first) {
415
+ throw error("no file path found on remote id", {
416
+ found: tuple
417
+ });
418
+ }
419
+ return Spec.parse(name ?? "(unknown)", `file:${first}`, options);
420
+ }
421
+ case "registry": {
422
+ if (typeof first !== "string") {
423
+ throw error("no registry url or name in registry ID", {
424
+ found: tuple
425
+ });
426
+ }
427
+ if (!second) {
428
+ throw error("no name/specifier in registry ID", {
429
+ found: tuple
430
+ });
431
+ }
432
+ if (!first) {
433
+ const s2 = Spec.parse(second);
434
+ if (name && s2.name !== name) {
435
+ return Spec.parse(`${name}@npm:${second}`);
436
+ } else {
437
+ return s2;
438
+ }
439
+ }
440
+ if (!/^https?:\/\//.test(first)) {
441
+ const reg = options.registries?.[first];
442
+ if (first !== "npm" && !reg) {
443
+ throw error("named registry not found in options", {
444
+ name: first,
445
+ found: tuple
446
+ });
447
+ }
448
+ return Spec.parse(
449
+ name ?? "(unknown)",
450
+ `${first}:${second}`,
451
+ options
452
+ );
453
+ }
454
+ const s = Spec.parse(
455
+ name ?? "(unknown)",
456
+ `registry:${first}#${second}`,
457
+ options
458
+ );
459
+ return name && s.final.name !== name ? Spec.parse(s.final.name + "@" + s.bareSpec) : s;
460
+ }
461
+ case "git": {
462
+ if (!first) {
463
+ throw error("no git remote in git ID", {
464
+ found: tuple
465
+ });
466
+ }
467
+ return Spec.parse(
468
+ name ?? "(unknown)",
469
+ first + "#" + second,
470
+ options
471
+ );
472
+ }
473
+ case "workspace": {
474
+ if (!first) {
475
+ throw error("no name/path on workspace id", { found: tuple });
476
+ }
477
+ return name && name !== first ? Spec.parse(name, `workspace:${first}@*`, options) : Spec.parse(first, `workspace:*`, options);
478
+ }
479
+ }
480
+ };
481
+
482
+ // ../../src/graph/src/stringify-node.ts
483
+ var stringifyNode = (node) => {
484
+ if (!node) return "";
485
+ const version = node.version ? `@${node.version}` : "";
486
+ const [type, ref, nameVersion] = splitDepID2(node.id);
487
+ if (type === "registry") {
488
+ const prefix = ref ? `${ref}:` : "npm:";
489
+ return `${prefix}${nameVersion}`;
490
+ } else if (type === "workspace") {
491
+ return `workspace:${node.name}`;
492
+ } else if (type === "file" && node.mainImporter) {
493
+ return `root:${node.name}`;
494
+ } else {
495
+ const nameVersion2 = node.name !== node.id ? `:${node.name}${version}` : "";
496
+ return `${type}(${ref})${nameVersion2}`;
497
+ }
498
+ };
499
+
500
+ // ../../src/graph/src/node.ts
501
+ var Node = class _Node {
502
+ get [Symbol.toStringTag]() {
503
+ return "@vltpkg/graph.Node";
504
+ }
505
+ #options;
506
+ #location;
507
+ #optional = false;
508
+ /**
509
+ * True if a node is only reachable via optional or peerOptional edges from
510
+ * any importer.
511
+ *
512
+ * Setting this to false, if previously set to true, will also unset
513
+ * the flag on any optional-flagged non-optional dependencies.
514
+ */
515
+ get optional() {
516
+ return this.#optional;
517
+ }
518
+ set optional(optional) {
519
+ const before = this.#optional;
520
+ this.#optional = optional;
521
+ if (before && !optional) {
522
+ for (const { to, optional: optional2 } of this.edgesOut.values()) {
523
+ if (!optional2 && to?.optional) to.optional = false;
524
+ }
525
+ }
526
+ }
527
+ isOptional() {
528
+ return this.#optional;
529
+ }
530
+ #dev = false;
531
+ /**
532
+ * True if a node is only reachable via dev edges from any importer.
533
+ *
534
+ * Setting this to false, if previously set to true, will also unset
535
+ * the flag on any dev-flagged non-dev dependencies.
536
+ */
537
+ get dev() {
538
+ return this.#dev;
539
+ }
540
+ set dev(dev) {
541
+ const before = this.#dev;
542
+ this.#dev = dev;
543
+ if (before && !dev) {
544
+ for (const { to, dev: dev2 } of this.edgesOut.values()) {
545
+ if (!dev2 && to?.dev) to.dev = false;
546
+ }
547
+ }
548
+ }
549
+ isDev() {
550
+ return this.#dev;
551
+ }
552
+ /**
553
+ * List of edges coming into this node.
554
+ */
555
+ edgesIn = /* @__PURE__ */ new Set();
556
+ /**
557
+ * List of edges from this node into other nodes. This usually represents
558
+ * that the connected node is a direct dependency of this node.
559
+ */
560
+ edgesOut = /* @__PURE__ */ new Map();
561
+ /**
562
+ * A reference to the {@link DepID} this node represents in the graph.
563
+ */
564
+ id;
565
+ /**
566
+ * True if this node is an importer node.
567
+ */
568
+ importer = false;
569
+ /**
570
+ * True if this node is the project root node.
571
+ */
572
+ mainImporter = false;
573
+ /**
574
+ * A reference to the graph this node is a part of.
575
+ */
576
+ graph;
577
+ /**
578
+ * The manifest integrity value.
579
+ */
580
+ integrity;
581
+ /**
582
+ * The manifest this node represents in the graph.
583
+ */
584
+ manifest;
585
+ /**
586
+ * Project where this node resides
587
+ */
588
+ projectRoot;
589
+ /**
590
+ * For registry nodes, this is the registry we fetched them from.
591
+ * Needed because their un-prefixed dependencies need to come from
592
+ * the same registry, if it's not the default.
593
+ */
594
+ registry;
595
+ /**
596
+ * The name of the package represented by this node, this is usually
597
+ * equivalent to `manifest.name` but in a few ways it may differ such as
598
+ * nodes loaded from a lockfile that lacks a loaded manifest.
599
+ * This field should be used to retrieve package names instead.
600
+ */
601
+ #name;
602
+ get name() {
603
+ if (this.#name) return this.#name;
604
+ this.#name = this.id;
605
+ return this.#name;
606
+ }
607
+ /**
608
+ * The version of the package represented by this node, this is usually
609
+ * equivalent to `manifest.version` but in a few ways it may differ such as
610
+ * nodes loaded from a lockfile that lacks a loaded manifest.
611
+ * This field should be used to retrieve package versions instead.
612
+ */
613
+ version;
614
+ /**
615
+ * An address {@link PackageInfoClient} may use to extract this package.
616
+ */
617
+ resolved;
618
+ /**
619
+ * The file system location for this node.
620
+ */
621
+ get location() {
622
+ if (this.#location) {
623
+ return this.#location;
624
+ }
625
+ this.#location = `./node_modules/.vlt/${this.id}/node_modules/${this.name}`;
626
+ this.inVltStore = () => true;
627
+ return this.#location;
628
+ }
629
+ set location(location) {
630
+ this.#location = location;
631
+ if (this.inVltStore !== _Node.prototype.inVltStore) {
632
+ this.inVltStore = _Node.prototype.inVltStore;
633
+ }
634
+ }
635
+ /**
636
+ * The resolved location of the node in the file system.
637
+ */
638
+ resolvedLocation(scurry) {
639
+ return scurry.cwd.resolve(this.location).fullpath();
640
+ }
641
+ /**
642
+ * The location of the node_modules folder where this node's edgesOut
643
+ * should be linked into. For nodes in the store, this is the parent
644
+ * directory, since they're extracted into a node_modules folder
645
+ * side by side with links to their deps. For nodes outside of the store
646
+ * (ie, importers and arbitrary link deps) this is the node_modules folder
647
+ * directly inside the node's directory.
648
+ */
649
+ nodeModules(scurry) {
650
+ const loc = this.resolvedLocation(scurry);
651
+ return this.inVltStore() ? loc.substring(0, loc.length - this.name.length - 1) : scurry.resolve(loc, "node_modules");
652
+ }
653
+ constructor(options, id, manifest, spec, name, version) {
654
+ this.#options = options;
655
+ this.projectRoot = options.projectRoot;
656
+ if (id) {
657
+ this.id = id;
658
+ } else {
659
+ if (!manifest || !spec) {
660
+ throw typeError(
661
+ "A new Node needs either a manifest & spec or an id parameter",
662
+ {
663
+ manifest
664
+ }
665
+ );
666
+ }
667
+ this.id = getId(spec, manifest);
668
+ }
669
+ this.graph = options.graph;
670
+ this.manifest = manifest;
671
+ this.#name = name || this.manifest?.name;
672
+ this.version = version || this.manifest?.version;
673
+ if (this.version?.startsWith("v")) {
674
+ this.version = this.version.slice(1);
675
+ }
676
+ }
677
+ /**
678
+ * return true if this node is located in the vlt store
679
+ * memoized the first time it's called, since the store location
680
+ * doesn't change within the context of a single operation.
681
+ */
682
+ inVltStore() {
683
+ const inStore = this.location.endsWith(
684
+ `.vlt/${this.id}/node_modules/${this.name}`
685
+ );
686
+ this.inVltStore = () => inStore;
687
+ return inStore;
688
+ }
689
+ #registryNodeResolved(tuple) {
690
+ const spec = hydrateTuple(tuple, this.#name, this.#options);
691
+ this.resolved = this.manifest?.dist?.tarball || spec.conventionalRegistryTarball;
692
+ this.integrity ??= this.manifest?.dist?.integrity;
693
+ }
694
+ equals(other) {
695
+ return this.id === other.id && this.location === other.location;
696
+ }
697
+ /**
698
+ * Sets the node as an importer along with its location.
699
+ */
700
+ setImporterLocation(location) {
701
+ this.#location = location;
702
+ this.importer = true;
703
+ }
704
+ /**
705
+ * Sets the appropriate resolve / integrity value for this node.
706
+ * Note that other places might also set these values, like for
707
+ * example the lockfile that might have already have this info.
708
+ */
709
+ setResolved() {
710
+ const tuple = splitDepID(this.id);
711
+ const [type, resolved] = tuple;
712
+ switch (type) {
713
+ case "registry":
714
+ this.#registryNodeResolved(tuple);
715
+ break;
716
+ default:
717
+ this.resolved = resolved;
718
+ break;
719
+ }
720
+ }
721
+ setDefaultLocation() {
722
+ const def = `./node_modules/.vlt/${this.id}/node_modules/${this.name}`;
723
+ if (!this.importer && (!this.#location || this.#location !== def && /^(?:\.\/)?node_modules\//.test(this.#location))) {
724
+ this.#location = def;
725
+ }
726
+ }
727
+ /**
728
+ * Add an edge from this node connecting it to a direct dependency.
729
+ */
730
+ addEdgesTo(type, spec, node) {
731
+ const edge = new Edge(type, spec, this, node);
732
+ node?.edgesIn.add(edge);
733
+ this.edgesOut.set(spec.name, edge);
734
+ return edge;
735
+ }
736
+ toJSON() {
737
+ return {
738
+ id: this.id,
739
+ name: this.name,
740
+ version: this.version,
741
+ location: this.location,
742
+ importer: this.importer,
743
+ manifest: this.manifest,
744
+ projectRoot: this.projectRoot,
745
+ integrity: this.integrity,
746
+ resolved: this.resolved,
747
+ dev: this.dev,
748
+ optional: this.optional
749
+ };
750
+ }
751
+ toString() {
752
+ return stringifyNode(this);
753
+ }
754
+ };
755
+
756
+ // ../../src/graph/src/visualization/mermaid-output.ts
757
+ var missingCount = 0;
758
+ var nodeLabel = (node) => `"${String(node).replaceAll("@", "#64;")}"`;
759
+ function parseNode(seenNodes, includedItems, node) {
760
+ if (seenNodes.has(node.id) || !includedItems.get(node)) {
761
+ return "";
762
+ }
763
+ seenNodes.add(node.id);
764
+ const edges = [...node.edgesOut.values()].map((e) => parseEdge(seenNodes, includedItems, e)).filter(Boolean).join("\n");
765
+ return `${encodeURIComponent(node.id)}(${nodeLabel(node)})${edges.length ? "\n" : ""}${edges}`;
766
+ }
767
+ function parseEdge(seenNodes, includedItems, edge) {
768
+ if (!includedItems.get(edge)) {
769
+ return "";
770
+ }
771
+ const edgeResult = `${encodeURIComponent(edge.from.id)}(${nodeLabel(edge.from)}) -->|"${String(edge.spec).replaceAll("@", "#64;")} (${edge.type})"| `;
772
+ const missingLabel = edge.type.endsWith("ptional") ? "Missing Optional" : "Missing";
773
+ if (!edge.to) {
774
+ return edgeResult + `missing-${missingCount++}(${missingLabel})
775
+ `;
776
+ }
777
+ return edgeResult + `${encodeURIComponent(edge.to.id)}(${nodeLabel(edge.to)})
778
+ ` + parseNode(seenNodes, includedItems, edge.to);
779
+ }
780
+ function mermaidOutput({
781
+ edges,
782
+ importers,
783
+ nodes
784
+ }) {
785
+ const seen = /* @__PURE__ */ new Set();
786
+ const includedItems = /* @__PURE__ */ new Map();
787
+ const traverse = new Set(
788
+ [...importers].map((i) => ({ self: i, parent: void 0 }))
789
+ );
790
+ for (const item of traverse) {
791
+ if (seen.has(item.self)) continue;
792
+ seen.add(item.self);
793
+ if (item.self instanceof Edge) {
794
+ if (edges.includes(item.self)) {
795
+ includedItems.set(item.self, true);
796
+ }
797
+ if (item.self.to) {
798
+ traverse.add({ self: item.self.to, parent: item.self });
799
+ }
800
+ }
801
+ if (item.self instanceof Node) {
802
+ if (nodes.includes(item.self)) {
803
+ includedItems.set(item.self, true);
804
+ }
805
+ for (const edge of item.self.edgesOut.values()) {
806
+ traverse.add({ self: edge, parent: item.self });
807
+ }
808
+ }
809
+ }
810
+ for (const item of [...traverse].reverse()) {
811
+ if (includedItems.has(item.self) && item.parent) {
812
+ includedItems.set(item.parent, true);
813
+ }
814
+ }
815
+ return "flowchart TD\n" + [...importers].map((i) => parseNode(/* @__PURE__ */ new Set(), includedItems, i)).join("\n");
816
+ }
817
+
818
+ // ../../src/graph/src/dependencies.ts
819
+ var isDependencyTypeShort = (obj) => shortDependencyTypes.has(obj);
820
+ var isObj = (o) => !!o && typeof o === "object";
821
+ var isDependency = (o) => (
822
+ // TODO: it would be nice to have a @vltpkg/spec.isSpec method
823
+ isObj(o) && isObj(o.spec) && !!o.spec.type && isDependencyTypeShort(o.type)
824
+ );
825
+ var asDependency = (obj) => {
826
+ if (!isDependency(obj)) {
827
+ throw error("Invalid dependency", { found: obj });
828
+ }
829
+ return obj;
830
+ };
831
+ var shorten = (typeLong, name, manifest) => {
832
+ const shortName = dependencyTypes.get(typeLong);
833
+ if (!shortName) {
834
+ throw error("Invalid dependency type name", {
835
+ found: typeLong,
836
+ validOptions: [...longDependencyTypes]
837
+ });
838
+ }
839
+ if (shortName !== "peer") {
840
+ return shortName;
841
+ }
842
+ if (name && manifest?.peerDependenciesMeta?.[name]?.optional === true) {
843
+ return "peerOptional";
844
+ }
845
+ return "peer";
846
+ };
847
+
848
+ // ../../src/graph/src/graph.ts
849
+ import { inspect as inspect2 } from "node:util";
850
+
851
+ // ../../src/graph/src/lockfile/save.ts
852
+ import { mkdirSync, writeFileSync } from "node:fs";
853
+ import { dirname, resolve as resolve2 } from "node:path";
854
+
855
+ // ../../src/graph/src/lockfile/types.ts
856
+ var getFlagNumFromNode = (node) => node.optional && node.dev ? LockfileNodeFlagDevOptional : node.optional ? LockfileNodeFlagOptional : node.dev ? LockfileNodeFlagDev : LockfileNodeFlagNone;
857
+ var getBooleanFlagsFromNum = (flags) => ({
858
+ dev: !!(flags & LockfileNodeFlagDev),
859
+ optional: !!(flags & LockfileNodeFlagOptional)
860
+ });
861
+ var LockfileNodeFlagNone = 0;
862
+ var LockfileNodeFlagOptional = 1;
863
+ var LockfileNodeFlagDev = 2;
864
+ var LockfileNodeFlagDevOptional = 3;
865
+
866
+ // ../../src/graph/src/lockfile/save.ts
867
+ var formatNodes = (nodes, saveManifests, registry) => {
868
+ const arr = [...nodes].filter((node) => !node.importer);
869
+ const orderedNodes = arr.sort(
870
+ (a, b) => a.id.localeCompare(b.id, "en")
871
+ );
872
+ const res = {};
873
+ for (const node of orderedNodes) {
874
+ const customRegistry = node.resolved && registry && !node.resolved.startsWith(registry);
875
+ const resolved = customRegistry ? node.resolved : void 0;
876
+ const location = node.id.startsWith("file") || node.location.endsWith(
877
+ "/node_modules/.vlt/" + node.id + "/node_modules/" + node.name
878
+ ) ? void 0 : node.location;
879
+ const flags = getFlagNumFromNode(node);
880
+ const lockfileNode = [flags, node.name];
881
+ if (node.integrity) {
882
+ lockfileNode[2] = node.integrity;
883
+ }
884
+ if (resolved) {
885
+ lockfileNode[3] = resolved;
886
+ }
887
+ if (location) {
888
+ lockfileNode[4] = location;
889
+ }
890
+ if (saveManifests) {
891
+ lockfileNode[5] = node.manifest;
892
+ }
893
+ res[node.id] = lockfileNode;
894
+ }
895
+ return res;
896
+ };
897
+ var formatEdges = (edges) => Object.fromEntries(
898
+ [...edges].sort(
899
+ (a, b) => (
900
+ /* c8 ignore start - nondeterminstic and annoying to test */
901
+ // sort importers to the top, then alphabetically by
902
+ // id, type, target
903
+ Number(b.from.importer) - Number(a.from.importer) || a.from.id.localeCompare(b.from.id, "en") || a.type.localeCompare(b.type, "en") || (a.to?.id ?? "").localeCompare(b.to?.id ?? "")
904
+ )
905
+ /* c8 ignore stop */
906
+ ).map((edge) => [
907
+ `${edge.from.id} ${edge.spec.name}`,
908
+ `${edge.type} ${edge.spec.bareSpec || "*"} ${edge.to?.id ?? "MISSING"}`
909
+ ])
910
+ );
911
+ var isRecordStringString = (registries) => !(!registries || typeof registries === "string");
912
+ var removeDefaultItems = (defaultItems, items) => {
913
+ const res = {};
914
+ for (const [key, value] of Object.entries(items)) {
915
+ if (!defaultItems[key] || defaultItems[key] !== value) {
916
+ res[key] = value;
917
+ }
918
+ }
919
+ return res;
920
+ };
921
+ var lockfileData = ({
922
+ graph,
923
+ "git-hosts": gitHosts,
924
+ "git-host-archives": gitHostArchives,
925
+ registry,
926
+ registries,
927
+ saveManifests,
928
+ "scope-registries": scopeRegistries
929
+ }) => {
930
+ const cleanGitHosts = isRecordStringString(gitHosts) ? removeDefaultItems(defaultGitHosts, gitHosts) : void 0;
931
+ const cleanGitHostArchives = isRecordStringString(gitHostArchives) ? removeDefaultItems(defaultGitHostArchives, gitHostArchives) : void 0;
932
+ const cleanRegistries = isRecordStringString(registries) ? removeDefaultItems(defaultRegistries, registries) : void 0;
933
+ const cleanScopeRegistries = isRecordStringString(scopeRegistries) ? removeDefaultItems(defaultScopeRegistries, scopeRegistries) : void 0;
934
+ const hasItems = (clean) => clean && Object.keys(clean).length;
935
+ return {
936
+ options: {
937
+ ...hasItems(cleanScopeRegistries) ? { "scope-registries": cleanScopeRegistries } : void 0,
938
+ ...registry !== void 0 && registry !== defaultRegistry ? { registry } : void 0,
939
+ ...hasItems(registries) ? { registries: cleanRegistries } : void 0,
940
+ ...hasItems(cleanGitHosts) ? { "git-hosts": cleanGitHosts } : void 0,
941
+ ...hasItems(cleanGitHostArchives) ? { "git-host-archives": cleanGitHostArchives } : void 0
942
+ },
943
+ nodes: formatNodes(graph.nodes.values(), saveManifests, registry),
944
+ edges: formatEdges(graph.edges)
945
+ };
946
+ };
947
+ var extraFormat = (jsonString) => {
948
+ const str = `${jsonString}
949
+ `;
950
+ const [init, ...parts] = str.split(' "nodes": {');
951
+ const res = [init];
952
+ for (const part of parts) {
953
+ res.push(
954
+ part.replaceAll("\n ", "").replaceAll("\n ]", "]")
955
+ );
956
+ }
957
+ return res.join(' "nodes": {');
958
+ };
959
+ var saveData = (data, fileName, saveManifests = false) => {
960
+ const json = JSON.stringify(data, null, 2);
961
+ const content = saveManifests ? json : extraFormat(json);
962
+ writeFileSync(fileName, content);
963
+ };
964
+ var save = (options) => {
965
+ const { graph } = options;
966
+ const data = lockfileData({ ...options, saveManifests: false });
967
+ const fileName = resolve2(graph.projectRoot, "vlt-lock.json");
968
+ return saveData(data, fileName, false);
969
+ };
970
+ var saveHidden = (options) => {
971
+ const { graph } = options;
972
+ const data = lockfileData({ ...options, saveManifests: true });
973
+ const fileName = resolve2(
974
+ graph.projectRoot,
975
+ "node_modules/.vlt-lock.json"
976
+ );
977
+ mkdirSync(dirname(fileName), { recursive: true });
978
+ return saveData(data, fileName, true);
979
+ };
980
+
981
+ // ../../src/graph/src/graph.ts
982
+ var kCustomInspect2 = Symbol.for("nodejs.util.inspect.custom");
983
+ var mainDepID = joinDepIDTuple(["file", "."]);
984
+ var getMap = (m) => m ?? /* @__PURE__ */ new Map();
985
+ var Graph = class {
986
+ get [Symbol.toStringTag]() {
987
+ return "@vltpkg/graph.Graph";
988
+ }
989
+ #options;
990
+ #nodeOptions;
991
+ /**
992
+ * A {@link Monorepo} instance, used for managing workspaces.
993
+ */
994
+ monorepo;
995
+ /**
996
+ * An inventory with all manifests related to an install.
997
+ */
998
+ manifests;
999
+ /**
1000
+ * A set of all edges in this graph.
1001
+ */
1002
+ edges = /* @__PURE__ */ new Set();
1003
+ /**
1004
+ * Map registered dep ids to the node that represent them in the graph.
1005
+ */
1006
+ nodes = /* @__PURE__ */ new Map();
1007
+ /**
1008
+ * Map of nodes by their name
1009
+ */
1010
+ nodesByName = /* @__PURE__ */ new Map();
1011
+ /**
1012
+ * Cached resolutions for spec lookups
1013
+ */
1014
+ resolutions = /* @__PURE__ */ new Map();
1015
+ /**
1016
+ * Reverse map of resolutions
1017
+ */
1018
+ resolutionsReverse = /* @__PURE__ */ new Map();
1019
+ /**
1020
+ * A set of importer nodes in this graph.
1021
+ */
1022
+ importers = /* @__PURE__ */ new Set();
1023
+ /**
1024
+ * The {@link Node} that represents the project root `package.json`.
1025
+ */
1026
+ mainImporter;
1027
+ /**
1028
+ * A set of extraneous dependencies found when building the graph.
1029
+ */
1030
+ extraneousDependencies = /* @__PURE__ */ new Set();
1031
+ /**
1032
+ * The root of the project this graph represents
1033
+ */
1034
+ projectRoot;
1035
+ constructor(options) {
1036
+ const { mainManifest, monorepo } = options;
1037
+ this.#options = options;
1038
+ this.manifests = getMap(options.manifests);
1039
+ this.projectRoot = options.projectRoot;
1040
+ this.#nodeOptions = {
1041
+ ...this.#options,
1042
+ graph: this
1043
+ };
1044
+ const mainImporterLocation = ".";
1045
+ const mainImporterSpec = Spec2.parse(
1046
+ mainManifest.name || "(root)",
1047
+ mainImporterLocation
1048
+ );
1049
+ const mainImporter = this.addNode(
1050
+ mainDepID,
1051
+ mainManifest,
1052
+ mainImporterSpec
1053
+ );
1054
+ mainImporter.setImporterLocation(mainImporterLocation);
1055
+ mainImporter.mainImporter = true;
1056
+ this.mainImporter = mainImporter;
1057
+ this.importers.add(mainImporter);
1058
+ this.manifests.set(mainImporter.id, mainManifest);
1059
+ this.monorepo = monorepo;
1060
+ if (this.monorepo) {
1061
+ for (const ws of this.monorepo) {
1062
+ const wsNode = this.addNode(
1063
+ ws.id,
1064
+ ws.manifest,
1065
+ void 0,
1066
+ ws.name
1067
+ );
1068
+ wsNode.setImporterLocation(`./${ws.path}`);
1069
+ if (wsNode.manifest) {
1070
+ this.manifests.set(wsNode.id, wsNode.manifest);
1071
+ }
1072
+ this.importers.add(wsNode);
1073
+ }
1074
+ }
1075
+ }
1076
+ /**
1077
+ * Delete all nodes that are unreachable from the importers.
1078
+ * The collection of deleted nodes is returned.
1079
+ *
1080
+ * NOTE: This can be extremely slow for large graphs, and is almost always
1081
+ * unnecessary! Only call when it is known that some unreachable nodes may
1082
+ * have been created, for example when deleting the unneeded subgraph when an
1083
+ * optional node fails to resolve/install.
1084
+ */
1085
+ gc() {
1086
+ const { nodes } = this;
1087
+ this.nodes = /* @__PURE__ */ new Map();
1088
+ const marked = new Set(this.importers);
1089
+ for (const imp of marked) {
1090
+ nodes.delete(imp.id);
1091
+ this.nodes.set(imp.id, imp);
1092
+ for (const { to } of imp.edgesOut.values()) {
1093
+ if (!to || marked.has(to)) continue;
1094
+ marked.add(to);
1095
+ nodes.delete(to.id);
1096
+ this.nodes.set(to.id, to);
1097
+ }
1098
+ }
1099
+ for (const node of nodes.values()) {
1100
+ this.removeNode(node);
1101
+ }
1102
+ return nodes;
1103
+ }
1104
+ /**
1105
+ * Create a new edge between two nodes of the graph in case both exist,
1106
+ * in case the destination node does not exists, then a dangling edge,
1107
+ * pointing to nothing will be created to represent that missing dependency.
1108
+ */
1109
+ addEdge(type, spec, from, to) {
1110
+ if (spec.name === "(unknown)") {
1111
+ if (to) {
1112
+ spec.name = to.name || "(unknown)";
1113
+ spec.spec = `${to.name}@${spec.bareSpec}`;
1114
+ } else {
1115
+ throw error(
1116
+ "Impossible to place a missing, nameless dependency",
1117
+ { spec }
1118
+ );
1119
+ }
1120
+ }
1121
+ const existing = from.edgesOut.get(spec.name);
1122
+ if (existing) {
1123
+ const edge = existing;
1124
+ if (edge.type === type && edge.spec.bareSpec === spec.bareSpec) {
1125
+ if (to && to !== edge.to) {
1126
+ edge.to = to;
1127
+ edge.to.edgesIn.add(edge);
1128
+ }
1129
+ return edge;
1130
+ }
1131
+ this.edges.delete(edge);
1132
+ }
1133
+ const f = from;
1134
+ const edgeOut = f.addEdgesTo(type, spec, to);
1135
+ this.edges.add(edgeOut);
1136
+ return edgeOut;
1137
+ }
1138
+ /**
1139
+ * Find an existing node to satisfy a dependency
1140
+ */
1141
+ findResolution(spec, fromNode) {
1142
+ const f = spec.final;
1143
+ const fromPref = f.type === "file" ? fromNode.location + " : " : "";
1144
+ const sf = fromPref + String(f);
1145
+ const cached = this.resolutions.get(sf);
1146
+ if (cached) return cached;
1147
+ const nbn = this.nodesByName.get(f.name);
1148
+ if (!nbn) return void 0;
1149
+ for (const node of nbn) {
1150
+ if (satisfies(
1151
+ node.id,
1152
+ f,
1153
+ fromNode.location,
1154
+ this.projectRoot,
1155
+ this.monorepo
1156
+ )) {
1157
+ this.resolutions.set(sf, node);
1158
+ this.resolutionsReverse.get(node)?.add(sf);
1159
+ return node;
1160
+ }
1161
+ }
1162
+ }
1163
+ /**
1164
+ * Create a new node in the graph.
1165
+ */
1166
+ addNode(id, manifest, spec, name, version) {
1167
+ const node = new Node(
1168
+ this.#nodeOptions,
1169
+ id,
1170
+ manifest,
1171
+ spec,
1172
+ name,
1173
+ version
1174
+ );
1175
+ this.nodes.set(node.id, node);
1176
+ const nbn = this.nodesByName.get(node.name) ?? /* @__PURE__ */ new Set();
1177
+ nbn.add(node);
1178
+ this.nodesByName.set(node.name, nbn);
1179
+ if (spec) {
1180
+ const f = String(spec.final);
1181
+ if (spec.final.type !== "file") {
1182
+ this.resolutions.set(f, node);
1183
+ const rrev = this.resolutionsReverse.get(node) ?? /* @__PURE__ */ new Set();
1184
+ rrev.add(f);
1185
+ this.resolutionsReverse.set(node, rrev);
1186
+ }
1187
+ }
1188
+ if (manifest) {
1189
+ this.manifests.set(node.id, manifest);
1190
+ }
1191
+ return node;
1192
+ }
1193
+ /**
1194
+ * Place a new package into the graph representation, creating the new
1195
+ * edges and possibly new nodes that are to be expected when traversing
1196
+ * the graph in a top-down direction, e.g: from importers to leafs.
1197
+ *
1198
+ * For different uses that are not a direct top-down traversal of the graph
1199
+ * consider using `addNode()` and `addEdge()` instead.
1200
+ */
1201
+ placePackage(fromNode, depType, spec, manifest, id) {
1202
+ if (!manifest && !id) {
1203
+ this.addEdge(depType, spec, fromNode);
1204
+ return;
1205
+ }
1206
+ const flags = {
1207
+ dev: fromNode.dev || depType === "dev",
1208
+ optional: fromNode.optional || depType === "optional" || depType === "peerOptional"
1209
+ };
1210
+ const depId = id || manifest && getId(spec, manifest);
1211
+ if (!depId) {
1212
+ throw error("Could not find dep id when placing package", {
1213
+ spec,
1214
+ manifest
1215
+ });
1216
+ }
1217
+ const toFoundNode = this.nodes.get(depId);
1218
+ if (toFoundNode) {
1219
+ this.addEdge(depType, spec, fromNode, toFoundNode);
1220
+ toFoundNode.dev &&= flags.dev;
1221
+ toFoundNode.optional &&= flags.optional;
1222
+ return toFoundNode;
1223
+ }
1224
+ const toNode = this.addNode(depId, manifest);
1225
+ toNode.registry = spec.registry;
1226
+ toNode.dev = flags.dev;
1227
+ toNode.optional = flags.optional;
1228
+ this.addEdge(depType, spec, fromNode, toNode);
1229
+ return toNode;
1230
+ }
1231
+ /**
1232
+ * Removes a node and its relevant edges from the graph.
1233
+ *
1234
+ * If a replacement is provided, then any edges that were previously
1235
+ * pointing to the removed node will be directed to the replacement,
1236
+ * if it is valid to do so.
1237
+ */
1238
+ removeNode(node, replacement) {
1239
+ this.nodes.delete(node.id);
1240
+ const nbn = this.nodesByName.get(node.name);
1241
+ if (nbn?.size === 1) this.nodesByName.delete(node.name);
1242
+ else nbn?.delete(node);
1243
+ for (const r of this.resolutionsReverse.get(node) ?? /* @__PURE__ */ new Set()) {
1244
+ this.resolutions.delete(r);
1245
+ }
1246
+ this.resolutionsReverse.delete(node);
1247
+ this.manifests.delete(node.id);
1248
+ for (const edge of node.edgesOut.values()) {
1249
+ this.edges.delete(edge);
1250
+ }
1251
+ for (const edge of node.edgesIn) {
1252
+ if (replacement && satisfies(
1253
+ replacement.id,
1254
+ edge.spec,
1255
+ edge.from.location,
1256
+ this.projectRoot,
1257
+ this.monorepo
1258
+ )) {
1259
+ edge.to = replacement;
1260
+ } else {
1261
+ edge.from.edgesOut.delete(edge.spec.name);
1262
+ this.edges.delete(edge);
1263
+ }
1264
+ }
1265
+ }
1266
+ toJSON() {
1267
+ return lockfileData({
1268
+ ...this.#options,
1269
+ graph: this,
1270
+ saveManifests: true
1271
+ });
1272
+ }
1273
+ [kCustomInspect2](_, options) {
1274
+ const data = this.toJSON();
1275
+ return `${this[Symbol.toStringTag]} ${inspect2(data, options)}`;
1276
+ }
1277
+ };
1278
+
1279
+ // ../../src/graph/src/lockfile/load.ts
1280
+ import { readFileSync } from "node:fs";
1281
+ import { resolve as resolve3 } from "node:path";
1282
+
1283
+ // ../../src/graph/src/lockfile/load-edges.ts
1284
+ var loadEdges = (graph, edges, options) => {
1285
+ const entries = Object.entries(edges);
1286
+ for (const [key, value] of entries) {
1287
+ const [fromId, specName] = fastSplit(key, " ", 2);
1288
+ const [depType, valRest] = fastSplit(value, " ", 2);
1289
+ const vrSplit = valRest?.lastIndexOf(" ") ?? -1;
1290
+ if (!valRest || !depType || !fromId || !specName || vrSplit < 1) {
1291
+ continue;
1292
+ }
1293
+ const spec = Spec.parse(
1294
+ specName,
1295
+ valRest.substring(0, vrSplit),
1296
+ options
1297
+ );
1298
+ const toId = valRest.substring(vrSplit + 1);
1299
+ const from = graph.nodes.get(asDepID2(fromId));
1300
+ if (!from) {
1301
+ throw error("Edge info missing its `from` node", {
1302
+ found: {
1303
+ nodes: [...graph.nodes].map(([id]) => id),
1304
+ from,
1305
+ fromId,
1306
+ edge: { [key]: value }
1307
+ }
1308
+ });
1309
+ }
1310
+ const to = toId === "MISSING" ? void 0 : graph.nodes.get(asDepID2(toId));
1311
+ if (!isDependencyTypeShort(depType)) {
1312
+ throw error("Found unsupported dependency type in lockfile", {
1313
+ validOptions: [...longDependencyTypes]
1314
+ });
1315
+ }
1316
+ graph.addEdge(depType, spec, from, to);
1317
+ }
1318
+ };
1319
+
1320
+ // ../../src/graph/src/lockfile/load-nodes.ts
1321
+ var loadNodes = (graph, nodes) => {
1322
+ const entries = Object.entries(nodes);
1323
+ for (const [id, lockfileNode] of entries) {
1324
+ if (graph.nodes.has(id)) continue;
1325
+ const [flags, name, integrity, resolved, location, manifest] = lockfileNode;
1326
+ const [type, , spec] = splitDepID2(id);
1327
+ const node = manifest ? graph.addNode(id, manifest) : graph.addNode(
1328
+ id,
1329
+ void 0,
1330
+ void 0,
1331
+ name ?? void 0,
1332
+ type === "registry" && spec.indexOf("@") > 0 ? spec.split("@").slice(-1)[0] : void 0
1333
+ );
1334
+ const { dev, optional } = getBooleanFlagsFromNum(flags);
1335
+ node.dev = dev;
1336
+ node.optional = optional;
1337
+ node.integrity = integrity ?? void 0;
1338
+ node.resolved = resolved ?? void 0;
1339
+ if (!node.resolved) node.setResolved();
1340
+ if (location) node.location = location;
1341
+ }
1342
+ };
1343
+
1344
+ // ../../src/graph/src/lockfile/load.ts
1345
+ var loadLockfile = (projectRoot, lockfilePath) => JSON.parse(
1346
+ readFileSync(resolve3(projectRoot, lockfilePath), {
1347
+ encoding: "utf8"
1348
+ })
1349
+ );
1350
+ var load = (options) => {
1351
+ const { projectRoot } = options;
1352
+ return loadObject(
1353
+ options,
1354
+ loadLockfile(projectRoot, "vlt-lock.json")
1355
+ );
1356
+ };
1357
+ var loadHidden = (options) => {
1358
+ const { projectRoot } = options;
1359
+ return loadObject(
1360
+ options,
1361
+ loadLockfile(projectRoot, "node_modules/.vlt-lock.json")
1362
+ );
1363
+ };
1364
+ var loadObject = (options, lockfileData2) => {
1365
+ const { mainManifest, scurry } = options;
1366
+ const packageJson = options.packageJson ?? new PackageJson();
1367
+ const monorepo = options.monorepo ?? Monorepo.maybeLoad(options.projectRoot, { packageJson, scurry });
1368
+ const {
1369
+ "scope-registries": scopeRegistries,
1370
+ registry,
1371
+ registries,
1372
+ "git-hosts": gitHosts,
1373
+ "git-host-archives": gitHostArchives
1374
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1375
+ } = lockfileData2.options || {};
1376
+ const mergedOptions = {
1377
+ ...options,
1378
+ "scope-registries": {
1379
+ ...options["scope-registries"],
1380
+ ...scopeRegistries
1381
+ },
1382
+ registry: registry ?? options.registry,
1383
+ registries: {
1384
+ ...options.registries,
1385
+ ...registries
1386
+ },
1387
+ "git-hosts": {
1388
+ ...options["git-hosts"],
1389
+ ...gitHosts
1390
+ },
1391
+ "git-host-archives": {
1392
+ ...options["git-host-archives"],
1393
+ ...gitHostArchives
1394
+ }
1395
+ };
1396
+ const graph = new Graph({
1397
+ ...mergedOptions,
1398
+ mainManifest,
1399
+ monorepo
1400
+ });
1401
+ loadNodes(graph, lockfileData2.nodes);
1402
+ loadEdges(graph, lockfileData2.edges, mergedOptions);
1403
+ return graph;
1404
+ };
1405
+
1406
+ // ../../src/graph/src/actual/load.ts
1407
+ var pathBasedType = /* @__PURE__ */ new Set(["file", "workspace"]);
1408
+ var isPathBasedType = (type) => pathBasedType.has(type);
1409
+ var getPathBasedId = (spec, path) => isPathBasedType(spec.type) ? joinDepIDTuple([spec.type, path]) : void 0;
1410
+ var findDepID = ({ parent, name }) => parent?.name === ".vlt" ? asDepID(name) : parent?.isCWD === false ? findDepID(parent) : void 0;
1411
+ var findNodeModules = ({
1412
+ parent,
1413
+ name,
1414
+ isCWD
1415
+ }) => parent?.name === "node_modules" ? parent : parent && name !== ".vlt" && !isCWD ? findNodeModules(parent) : void 0;
1416
+ var findName = ({ parent, name }) => parent?.name.startsWith("@") ? `${parent.name}/${name}` : name;
1417
+ var isStringArray = (a) => Array.isArray(a) && !a.some((b) => typeof b !== "string");
1418
+ var getDeps = (node) => {
1419
+ const dependencies = /* @__PURE__ */ new Map();
1420
+ const bundleDeps = node.manifest?.bundleDependencies ?? [];
1421
+ const bundled = !node.importer && !node.id.startsWith("git") && isStringArray(bundleDeps) ? new Set(bundleDeps) : /* @__PURE__ */ new Set();
1422
+ for (const depType of longDependencyTypes) {
1423
+ const obj = node.manifest?.[depType];
1424
+ if (depType === "devDependencies" && !node.importer && !node.id.startsWith("git") && !node.id.startsWith("file")) {
1425
+ continue;
1426
+ }
1427
+ if (obj) {
1428
+ for (const [name, bareSpec] of Object.entries(obj)) {
1429
+ if (bundled.has(name)) continue;
1430
+ dependencies.set(name, {
1431
+ name,
1432
+ type: depType,
1433
+ bareSpec,
1434
+ registry: node.registry
1435
+ });
1436
+ }
1437
+ }
1438
+ }
1439
+ return dependencies;
1440
+ };
1441
+ var readDir = (scurry, currDir, fromNodeName) => {
1442
+ const res = /* @__PURE__ */ new Set();
1443
+ for (const entry of scurry.readdirSync(currDir)) {
1444
+ if (entry.name.startsWith(".")) continue;
1445
+ if (entry.name.startsWith("@")) {
1446
+ const scopedItems = readDir(scurry, entry, fromNodeName);
1447
+ for (const scopedItem of scopedItems) {
1448
+ res.add(scopedItem);
1449
+ }
1450
+ continue;
1451
+ }
1452
+ if (!entry.isSymbolicLink()) continue;
1453
+ const realpath = entry.realpathSync();
1454
+ if (!realpath) {
1455
+ continue;
1456
+ }
1457
+ const alias = findName(entry);
1458
+ const name = findName(realpath);
1459
+ res.add({
1460
+ alias,
1461
+ name,
1462
+ realpath
1463
+ });
1464
+ }
1465
+ return res;
1466
+ };
1467
+ var parseDir = (options, scurry, packageJson, depsFound, graph, fromNode, currDir) => {
1468
+ const { loadManifests } = options;
1469
+ const dependencies = getDeps(fromNode);
1470
+ const seenDeps = /* @__PURE__ */ new Set();
1471
+ const readItems = readDir(
1472
+ scurry,
1473
+ currDir,
1474
+ fromNode.name
1475
+ );
1476
+ for (const { alias, name, realpath } of readItems) {
1477
+ let node;
1478
+ seenDeps.add(alias);
1479
+ if (!loadManifests) {
1480
+ const depId = findDepID(realpath);
1481
+ if (depId) {
1482
+ const h = hydrate(depId, alias, {
1483
+ ...options,
1484
+ registry: fromNode.registry
1485
+ });
1486
+ node = graph.placePackage(
1487
+ fromNode,
1488
+ "prod",
1489
+ // defaults to prod deps
1490
+ h,
1491
+ // uses spec from hydrated id
1492
+ {
1493
+ name,
1494
+ ...h.registrySpec ? { version: h.registrySpec } : null
1495
+ },
1496
+ depId
1497
+ );
1498
+ }
1499
+ }
1500
+ const deps = dependencies.get(alias);
1501
+ if (!node) {
1502
+ const mani = packageJson.read(realpath.fullpath());
1503
+ const type = deps?.type || "dependencies";
1504
+ const bareSpec = deps?.bareSpec || "*";
1505
+ const depType = shorten(type, alias, fromNode.manifest);
1506
+ const spec = Spec2.parse(alias, bareSpec, {
1507
+ ...options,
1508
+ registry: fromNode.registry
1509
+ });
1510
+ const maybeId = getPathBasedId(spec, realpath.relativePosix());
1511
+ node = graph.placePackage(
1512
+ fromNode,
1513
+ depType,
1514
+ spec,
1515
+ mani,
1516
+ maybeId
1517
+ );
1518
+ }
1519
+ if (node) {
1520
+ if (loadManifests && !deps) {
1521
+ const [edge] = node.edgesIn;
1522
+ if (edge) {
1523
+ graph.extraneousDependencies.add(edge);
1524
+ }
1525
+ }
1526
+ node.location = `./${realpath.relativePosix()}`;
1527
+ const node_modules = findNodeModules(realpath);
1528
+ if (node_modules) {
1529
+ depsFound.set(node, node_modules);
1530
+ }
1531
+ }
1532
+ }
1533
+ for (const { name, type, bareSpec } of dependencies.values()) {
1534
+ if (!seenDeps.has(name)) {
1535
+ const depType = shorten(type, name, fromNode.manifest);
1536
+ const spec = Spec2.parse(name, bareSpec, {
1537
+ ...options,
1538
+ registry: fromNode.registry
1539
+ });
1540
+ graph.placePackage(fromNode, depType, spec);
1541
+ }
1542
+ }
1543
+ };
1544
+ var load2 = (options) => {
1545
+ const done = graphStep("actual");
1546
+ const {
1547
+ skipHiddenLockfile = true,
1548
+ projectRoot,
1549
+ packageJson,
1550
+ scurry,
1551
+ monorepo
1552
+ } = options;
1553
+ const mainManifest = options.mainManifest ?? packageJson.read(projectRoot);
1554
+ if (!skipHiddenLockfile) {
1555
+ try {
1556
+ const graph2 = loadHidden({
1557
+ projectRoot,
1558
+ mainManifest,
1559
+ packageJson,
1560
+ monorepo,
1561
+ scurry
1562
+ });
1563
+ return graph2;
1564
+ } catch {
1565
+ }
1566
+ }
1567
+ const graph = new Graph({ ...options, mainManifest });
1568
+ const depsFound = /* @__PURE__ */ new Map();
1569
+ for (const importer of graph.importers) {
1570
+ depsFound.set(
1571
+ importer,
1572
+ scurry.cwd.resolve(`${importer.location}/node_modules`)
1573
+ );
1574
+ }
1575
+ for (const [node, path] of depsFound.entries()) {
1576
+ parseDir(
1577
+ options,
1578
+ scurry,
1579
+ packageJson,
1580
+ depsFound,
1581
+ graph,
1582
+ node,
1583
+ path
1584
+ );
1585
+ }
1586
+ done();
1587
+ return graph;
1588
+ };
1589
+
1590
+ // ../../src/graph/src/ideal/remove-satisfied-specs.ts
1591
+ var removeSatisfiedSpecs = ({
1592
+ add,
1593
+ graph
1594
+ }) => {
1595
+ for (const [depID, dependencies] of add.entries()) {
1596
+ const importer = graph.nodes.get(depID);
1597
+ if (!importer) {
1598
+ throw error("Referred importer node id could not be found", {
1599
+ found: depID
1600
+ });
1601
+ }
1602
+ for (const [name, dependency] of dependencies) {
1603
+ const edge = importer.edgesOut.get(name);
1604
+ if (!edge) {
1605
+ continue;
1606
+ }
1607
+ if (satisfies(
1608
+ edge.to?.id,
1609
+ dependency.spec,
1610
+ edge.from.location,
1611
+ graph.projectRoot,
1612
+ graph.monorepo
1613
+ )) {
1614
+ dependencies.delete(name);
1615
+ }
1616
+ }
1617
+ }
1618
+ for (const [depID, dependencies] of add.entries()) {
1619
+ if (dependencies.size === 0) {
1620
+ add.delete(depID);
1621
+ }
1622
+ }
1623
+ };
1624
+
1625
+ // ../../src/graph/src/ideal/get-importer-specs.ts
1626
+ var hasDepName = (importer, edge) => {
1627
+ for (const depType of longDependencyTypes) {
1628
+ const listedDeps = importer.manifest?.[depType];
1629
+ if (listedDeps && Object.hasOwn(listedDeps, edge.name))
1630
+ return true;
1631
+ }
1632
+ return false;
1633
+ };
1634
+ var AddImportersDependenciesMapImpl = class extends Map {
1635
+ modifiedDependencies = false;
1636
+ };
1637
+ var RemoveImportersDependenciesMapImpl = class extends Map {
1638
+ modifiedDependencies = false;
1639
+ };
1640
+ var getImporterSpecs = ({
1641
+ add,
1642
+ graph,
1643
+ remove
1644
+ }) => {
1645
+ const addResult = new AddImportersDependenciesMapImpl();
1646
+ const removeResult = new RemoveImportersDependenciesMapImpl();
1647
+ for (const importer of graph.importers) {
1648
+ const addDeps = /* @__PURE__ */ new Map();
1649
+ const removeDeps = /* @__PURE__ */ new Set();
1650
+ for (const edge of importer.edgesOut.values()) {
1651
+ if (!hasDepName(importer, edge) && !add.get(importer.id)?.has(edge.name)) {
1652
+ removeDeps.add(edge.name);
1653
+ removeResult.modifiedDependencies = true;
1654
+ }
1655
+ }
1656
+ for (const depType of longDependencyTypes) {
1657
+ const deps = Object.entries(importer.manifest?.[depType] ?? {});
1658
+ for (const [depName, depSpec] of deps) {
1659
+ const edge = importer.edgesOut.get(depName);
1660
+ if (!edge?.to) {
1661
+ addDeps.set(
1662
+ depName,
1663
+ asDependency({
1664
+ spec: Spec2.parse(depName, depSpec),
1665
+ type: shorten(depType, depName, importer.manifest)
1666
+ })
1667
+ );
1668
+ }
1669
+ }
1670
+ }
1671
+ addResult.set(importer.id, addDeps);
1672
+ removeResult.set(importer.id, removeDeps);
1673
+ }
1674
+ for (const [id, addDeps] of add.entries()) {
1675
+ const deps = addResult.get(id);
1676
+ if (!deps) {
1677
+ throw error("Not an importer", { found: id });
1678
+ }
1679
+ for (const [name, dep] of addDeps.entries()) {
1680
+ deps.set(name, dep);
1681
+ }
1682
+ }
1683
+ for (const [key, removeSet] of remove) {
1684
+ const importerRemoveItem = removeResult.get(key);
1685
+ if (importerRemoveItem) {
1686
+ for (const depName of removeSet) {
1687
+ importerRemoveItem.add(depName);
1688
+ }
1689
+ }
1690
+ }
1691
+ for (const [key, removeItem] of removeResult) {
1692
+ if (removeItem.size === 0) {
1693
+ removeResult.delete(key);
1694
+ }
1695
+ }
1696
+ removeSatisfiedSpecs({
1697
+ add: addResult,
1698
+ graph
1699
+ });
1700
+ for (const addDeps of addResult.values()) {
1701
+ if (addDeps.size > 0) {
1702
+ addResult.modifiedDependencies = true;
1703
+ break;
1704
+ }
1705
+ }
1706
+ return {
1707
+ add: addResult,
1708
+ remove: removeResult
1709
+ };
1710
+ };
1711
+
1712
+ // ../../src/graph/src/remove-optional-subgraph.ts
1713
+ var removeOptionalSubgraph = (graph, startingNode) => {
1714
+ const removed = /* @__PURE__ */ new Set();
1715
+ for (const node of findOptionalSubgraph(startingNode)) {
1716
+ graph.removeNode(node);
1717
+ removed.add(node);
1718
+ }
1719
+ return removed;
1720
+ };
1721
+ function* findOptionalSubgraph(node, seen = /* @__PURE__ */ new Set()) {
1722
+ if (seen.has(node)) return;
1723
+ seen.add(node);
1724
+ yield node;
1725
+ for (const { from, optional } of node.edgesIn) {
1726
+ if (from.isOptional() && !optional) {
1727
+ for (const dep of findOptionalSubgraph(from, seen)) yield dep;
1728
+ }
1729
+ }
1730
+ }
1731
+
1732
+ // ../../src/graph/src/ideal/append-nodes.ts
1733
+ var shouldInstallDepType = (node, depType) => depType !== "devDependencies" || node.importer || node.id.startsWith("git");
1734
+ var getFileTypeInfo = (spec, fromNode, scurry) => {
1735
+ const f = spec.final;
1736
+ if (f.type !== "file") return;
1737
+ if (!f.file) {
1738
+ throw error("no path on file specifier", { spec });
1739
+ }
1740
+ const target = scurry.cwd.resolve(fromNode.location).resolve(f.file);
1741
+ const path = target.relativePosix();
1742
+ const id = joinDepIDTuple(["file", path]);
1743
+ return {
1744
+ path,
1745
+ id,
1746
+ isDirectory: !!target.lstatSync()?.isDirectory()
1747
+ };
1748
+ };
1749
+ var isStringArray2 = (a) => Array.isArray(a) && !a.some((b) => typeof b !== "string");
1750
+ var appendNodes = async (add, packageInfo, graph, fromNode, deps, scurry, options, seen) => {
1751
+ if (seen.has(fromNode.id)) return;
1752
+ seen.add(fromNode.id);
1753
+ await Promise.all(
1754
+ deps.map(async ({ spec, type }) => {
1755
+ const fileTypeInfo = getFileTypeInfo(spec, fromNode, scurry);
1756
+ const existingNode = graph.findResolution(spec, fromNode);
1757
+ if (existingNode) {
1758
+ graph.addEdge(type, spec, fromNode, existingNode);
1759
+ return;
1760
+ }
1761
+ const edgeOptional = type === "optional" || type === "peerOptional";
1762
+ const mani = await packageInfo.manifest(spec, { from: scurry.resolve(fromNode.location) }).catch((er) => {
1763
+ if (edgeOptional || fromNode.optional) {
1764
+ return void 0;
1765
+ }
1766
+ throw er;
1767
+ });
1768
+ if (mani?.name && spec.name === "(unknown)") {
1769
+ const s = add.get(String(spec));
1770
+ if (s) {
1771
+ add.delete(String(spec));
1772
+ spec = Spec2.parse(mani.name, spec.bareSpec, options);
1773
+ const n = asDependency({
1774
+ ...s,
1775
+ spec
1776
+ });
1777
+ add.set(mani.name, n);
1778
+ }
1779
+ }
1780
+ if (!mani) {
1781
+ if (!edgeOptional && fromNode.isOptional()) {
1782
+ removeOptionalSubgraph(graph, fromNode);
1783
+ return;
1784
+ } else if (edgeOptional) {
1785
+ return;
1786
+ } else {
1787
+ throw error("failed to resolve dependency", {
1788
+ spec,
1789
+ from: fromNode.location
1790
+ });
1791
+ }
1792
+ }
1793
+ const node = graph.placePackage(
1794
+ fromNode,
1795
+ type,
1796
+ spec,
1797
+ mani,
1798
+ fileTypeInfo?.id
1799
+ );
1800
+ if (!node) {
1801
+ throw error("failed to place package", {
1802
+ from: fromNode.location,
1803
+ spec
1804
+ });
1805
+ }
1806
+ if (fileTypeInfo?.path && fileTypeInfo.isDirectory) {
1807
+ node.location = fileTypeInfo.path;
1808
+ }
1809
+ node.setResolved();
1810
+ const nestedAppends = [];
1811
+ const bundleDeps = node.manifest?.bundleDependencies;
1812
+ const bundled = new Set(
1813
+ node.id.startsWith("git") || node.importer || !isStringArray2(bundleDeps) ? [] : bundleDeps
1814
+ );
1815
+ const nextDeps = [];
1816
+ for (const depTypeName of longDependencyTypes) {
1817
+ const depRecord = mani[depTypeName];
1818
+ if (depRecord && shouldInstallDepType(node, depTypeName)) {
1819
+ for (const [name, bareSpec] of Object.entries(depRecord)) {
1820
+ if (bundled.has(name)) continue;
1821
+ nextDeps.push({
1822
+ type: shorten(depTypeName, name, mani),
1823
+ spec: Spec2.parse(name, bareSpec, {
1824
+ ...options,
1825
+ registry: spec.registry
1826
+ })
1827
+ });
1828
+ }
1829
+ }
1830
+ }
1831
+ if (nextDeps.length) {
1832
+ nestedAppends.push(
1833
+ appendNodes(
1834
+ add,
1835
+ packageInfo,
1836
+ graph,
1837
+ node,
1838
+ nextDeps,
1839
+ scurry,
1840
+ options,
1841
+ seen
1842
+ )
1843
+ );
1844
+ }
1845
+ await Promise.all(nestedAppends);
1846
+ })
1847
+ );
1848
+ };
1849
+
1850
+ // ../../src/graph/src/ideal/add-nodes.ts
1851
+ var addNodes = async ({
1852
+ add,
1853
+ graph,
1854
+ packageInfo,
1855
+ scurry,
1856
+ ...specOptions
1857
+ }) => {
1858
+ const seen = /* @__PURE__ */ new Set();
1859
+ for (const [depID, dependencies] of add) {
1860
+ const importer = graph.nodes.get(depID);
1861
+ if (!importer) {
1862
+ throw error("Could not find importer", { found: depID });
1863
+ }
1864
+ const deps = [...dependencies.values()];
1865
+ for (const { spec } of deps) {
1866
+ const node = importer.edgesOut.get(spec.name)?.to;
1867
+ if (node) graph.removeNode(node);
1868
+ }
1869
+ await appendNodes(
1870
+ dependencies,
1871
+ packageInfo,
1872
+ graph,
1873
+ importer,
1874
+ deps,
1875
+ scurry,
1876
+ specOptions,
1877
+ seen
1878
+ );
1879
+ }
1880
+ };
1881
+
1882
+ // ../../src/graph/src/ideal/remove-nodes.ts
1883
+ var removeNodes = ({
1884
+ graph,
1885
+ remove
1886
+ }) => {
1887
+ for (const [depID, names] of remove) {
1888
+ const importer = graph.nodes.get(depID);
1889
+ if (!importer) {
1890
+ throw error("Could not find importer", { found: depID });
1891
+ }
1892
+ for (const name of names) {
1893
+ const node = importer.edgesOut.get(name)?.to;
1894
+ if (node) graph.removeNode(node);
1895
+ }
1896
+ }
1897
+ };
1898
+
1899
+ // ../../src/graph/src/ideal/build-ideal-from-starting-graph.ts
1900
+ var buildIdealFromStartingGraph = async (options) => {
1901
+ const importerSpecs = getImporterSpecs(options);
1902
+ options.add.modifiedDependencies = options.add.modifiedDependencies || importerSpecs.add.modifiedDependencies;
1903
+ options.remove.modifiedDependencies = options.remove.modifiedDependencies || importerSpecs.remove.modifiedDependencies;
1904
+ for (const [importerId, deps] of importerSpecs.add) {
1905
+ if (!options.add.has(importerId)) {
1906
+ options.add.set(importerId, deps);
1907
+ continue;
1908
+ }
1909
+ for (const [depName, dep] of deps) {
1910
+ if (!options.add.get(importerId)?.has(depName)) {
1911
+ options.add.get(importerId)?.set(depName, dep);
1912
+ }
1913
+ }
1914
+ }
1915
+ await addNodes(options);
1916
+ for (const node of options.graph.nodes.values()) {
1917
+ node.setDefaultLocation();
1918
+ }
1919
+ removeNodes({ ...options, remove: importerSpecs.remove });
1920
+ options.graph.gc();
1921
+ return options.graph;
1922
+ };
1923
+
1924
+ // ../../src/graph/src/ideal/build.ts
1925
+ var getMap2 = (m) => m ?? /* @__PURE__ */ new Map();
1926
+ var build = async (options) => {
1927
+ const done = graphStep("build");
1928
+ const { packageInfo, packageJson, scurry, monorepo } = options;
1929
+ const mainManifest = options.mainManifest ?? packageJson.read(options.projectRoot);
1930
+ let graph;
1931
+ try {
1932
+ graph = load({
1933
+ ...options,
1934
+ mainManifest,
1935
+ monorepo
1936
+ });
1937
+ } catch {
1938
+ graph = load2({
1939
+ ...options,
1940
+ mainManifest,
1941
+ monorepo
1942
+ });
1943
+ }
1944
+ const res = await buildIdealFromStartingGraph({
1945
+ ...options,
1946
+ scurry,
1947
+ add: getMap2(options.add),
1948
+ graph,
1949
+ packageInfo,
1950
+ remove: getMap2(options.remove)
1951
+ });
1952
+ done();
1953
+ return res;
1954
+ };
1955
+
1956
+ // ../../src/rollback-remove/src/index.ts
1957
+ import { spawn } from "node:child_process";
1958
+ import { rename } from "node:fs/promises";
1959
+ import { basename, dirname as dirname2 } from "node:path";
1960
+
1961
+ // ../../src/rollback-remove/src/remove.ts
1962
+ import { resolve as resolve4 } from "node:path";
1963
+ var __CODE_SPLIT_SCRIPT_NAME = resolve4(import.meta.dirname, "rollback-remove-src-remove.js");
1964
+
1965
+ // ../../src/rollback-remove/src/index.ts
1966
+ var RollbackRemove = class {
1967
+ #key = String(Math.random()).substring(2);
1968
+ #paths = /* @__PURE__ */ new Map();
1969
+ async rm(path) {
1970
+ const target = `${dirname2(path)}/.VLT.DELETE.${this.#key}.${basename(path)}`;
1971
+ this.#paths.set(path, target);
1972
+ await rename(path, target).catch((e) => {
1973
+ if (e instanceof Error && "code" in e && e.code === "ENOENT") {
1974
+ this.#paths.delete(path);
1975
+ return;
1976
+ }
1977
+ throw e;
1978
+ });
1979
+ }
1980
+ confirm() {
1981
+ if (!this.#paths.size) return;
1982
+ const child = spawn(
1983
+ process.execPath,
1984
+ [__CODE_SPLIT_SCRIPT_NAME],
1985
+ {
1986
+ stdio: ["pipe", "ignore", "ignore"],
1987
+ detached: true
1988
+ }
1989
+ );
1990
+ child.unref();
1991
+ for (const path of this.#paths.values()) {
1992
+ child.stdin.write(path + "\0");
1993
+ }
1994
+ child.stdin.end();
1995
+ this.#paths.clear();
1996
+ }
1997
+ async rollback() {
1998
+ const promises = [];
1999
+ for (const [original, moved] of this.#paths) {
2000
+ promises.push(
2001
+ rimraf(original).catch(() => {
2002
+ }).then(() => rename(moved, original))
2003
+ );
2004
+ }
2005
+ await Promise.all(promises);
2006
+ this.#paths.clear();
2007
+ }
2008
+ };
2009
+
2010
+ // ../../src/graph/src/reify/index.ts
2011
+ import { availableParallelism as availableParallelism2 } from "node:os";
2012
+
2013
+ // ../../node_modules/.pnpm/promise-call-limit@3.0.2/node_modules/promise-call-limit/dist/esm/index.js
2014
+ import * as os from "node:os";
2015
+ var defLimit = "availableParallelism" in os ? Math.max(1, os.availableParallelism() - 1) : Math.max(1, os.cpus().length - 1);
2016
+ var callLimit = (queue, { limit: limit2 = defLimit, rejectLate } = {}) => new Promise((res, rej) => {
2017
+ let active = 0;
2018
+ let current = 0;
2019
+ const results = [];
2020
+ let rejected = false;
2021
+ let rejection;
2022
+ const reject = (er) => {
2023
+ if (rejected)
2024
+ return;
2025
+ rejected = true;
2026
+ rejection ??= er;
2027
+ if (!rejectLate)
2028
+ rej(rejection);
2029
+ };
2030
+ let resolved = false;
2031
+ const resolve5 = () => {
2032
+ if (resolved || active > 0)
2033
+ return;
2034
+ resolved = true;
2035
+ res(results);
2036
+ };
2037
+ const run2 = () => {
2038
+ const c = current++;
2039
+ if (c >= queue.length)
2040
+ return rejected ? reject() : resolve5();
2041
+ active++;
2042
+ const step = queue[c];
2043
+ if (!step)
2044
+ throw new Error("walked off queue");
2045
+ results[c] = step().then((result) => {
2046
+ active--;
2047
+ results[c] = result;
2048
+ return result;
2049
+ }, (er) => {
2050
+ active--;
2051
+ reject(er);
2052
+ }).then((result) => {
2053
+ if (rejected && active === 0)
2054
+ return rej(rejection);
2055
+ run2();
2056
+ return result;
2057
+ });
2058
+ };
2059
+ for (let i = 0; i < limit2; i++)
2060
+ run2();
2061
+ });
2062
+
2063
+ // ../../src/graph/src/diff.ts
2064
+ var kCustomInspect3 = Symbol.for("nodejs.util.inspect.custom");
2065
+ var Diff = class {
2066
+ from;
2067
+ to;
2068
+ projectRoot;
2069
+ /**
2070
+ * If changes need to be made later for failures of optional nodes,
2071
+ * set this flag so that we know to call graph.gc() at the appropriate time.
2072
+ */
2073
+ hadOptionalFailures = false;
2074
+ /**
2075
+ * Collection of nodes to add and delete
2076
+ */
2077
+ nodes = {
2078
+ /** Nodes in the `to` graph that are not in the `from` graph */
2079
+ add: /* @__PURE__ */ new Set(),
2080
+ /** Nodes in the `from` graph that are not in the `to` graph */
2081
+ delete: /* @__PURE__ */ new Set()
2082
+ };
2083
+ /**
2084
+ * Collection of nodes to add and delete
2085
+ */
2086
+ edges = {
2087
+ /** Edges in the `to` graph that are not found in the `from` graph */
2088
+ add: /* @__PURE__ */ new Set(),
2089
+ /** Edges in the `from` graph that are not found in the `to` graph */
2090
+ delete: /* @__PURE__ */ new Set()
2091
+ };
2092
+ get [Symbol.toStringTag]() {
2093
+ return "@vltpkg/graph.Diff";
2094
+ }
2095
+ constructor(from, to) {
2096
+ this.from = from;
2097
+ this.to = to;
2098
+ this.projectRoot = from.projectRoot;
2099
+ if (to.projectRoot !== from.projectRoot) {
2100
+ throw error("projectRoot mismatch in Graph diff", {
2101
+ wanted: from.projectRoot,
2102
+ found: to.projectRoot
2103
+ });
2104
+ }
2105
+ for (const [id, node] of this.from.nodes) {
2106
+ if (!this.to.nodes.get(id)?.equals(node)) {
2107
+ this.nodes.delete.add(node);
2108
+ }
2109
+ }
2110
+ for (const [id, node] of this.to.nodes) {
2111
+ if (!this.from.nodes.get(id)?.equals(node)) {
2112
+ this.nodes.add.add(node);
2113
+ }
2114
+ }
2115
+ for (const edge of this.to.edges) {
2116
+ const fromNode = this.from.nodes.get(edge.from.id);
2117
+ const fromEdge = fromNode?.edgesOut.get(edge.spec.name);
2118
+ if (fromEdge?.to?.id === edge.to?.id) continue;
2119
+ if (fromEdge?.to) this.edges.delete.add(fromEdge);
2120
+ if (edge.to) this.edges.add.add(edge);
2121
+ }
2122
+ for (const edge of this.from.edges) {
2123
+ const toNode = this.to.nodes.get(edge.from.id);
2124
+ const toEdge = toNode?.edgesOut.get(edge.spec.name);
2125
+ if (toEdge?.to?.id === edge.to?.id) continue;
2126
+ if (edge.to) this.edges.delete.add(edge);
2127
+ if (toEdge?.to) this.edges.add.add(toEdge);
2128
+ }
2129
+ }
2130
+ [kCustomInspect3](_, options) {
2131
+ const red = options?.colors ? ["\x1B[31m", "\x1B[m"] : ["", ""];
2132
+ const green = options?.colors ? ["\x1B[32m", "\x1B[m"] : ["", ""];
2133
+ const lines = [];
2134
+ for (const node of this.nodes.add) {
2135
+ lines.push(`+ ${node.id}`);
2136
+ }
2137
+ for (const node of this.nodes.delete) {
2138
+ lines.push(`- ${node.id}`);
2139
+ }
2140
+ for (const edge of this.edges.add) {
2141
+ const to = edge.to?.id ?? "";
2142
+ lines.push(
2143
+ `+ ${edge.from.id} ${edge.type} ${edge.spec} ${to}`.trim()
2144
+ );
2145
+ }
2146
+ for (const edge of this.edges.delete) {
2147
+ const to = edge.to?.id ?? "";
2148
+ lines.push(
2149
+ `- ${edge.from.id} ${edge.type} ${edge.spec} ${to}`.trim()
2150
+ );
2151
+ }
2152
+ const wrap = (s, c) => c.join(s);
2153
+ const color = options?.colors ? (s) => wrap(s, s.startsWith("+") ? green : red) : (s) => s;
2154
+ return `${this[Symbol.toStringTag]} {
2155
+ ${lines.sort((a, b) => a.substring(1).localeCompare(b.substring(1), "en")).map((s) => " " + color(s)).join("\n")}
2156
+ }`;
2157
+ }
2158
+ };
2159
+
2160
+ // ../../src/graph/src/uninstall.ts
2161
+ var uninstall = async (options, remove) => {
2162
+ const mainManifest = options.packageJson.read(options.projectRoot);
2163
+ const graph = await build({
2164
+ ...options,
2165
+ remove,
2166
+ mainManifest,
2167
+ loadManifests: true
2168
+ });
2169
+ const act = load2({
2170
+ ...options,
2171
+ mainManifest,
2172
+ loadManifests: true
2173
+ });
2174
+ const diff = await reify({
2175
+ ...options,
2176
+ remove,
2177
+ actual: act,
2178
+ graph,
2179
+ loadManifests: true
2180
+ });
2181
+ return { graph, diff };
2182
+ };
2183
+
2184
+ // ../../src/graph/src/index.ts
2185
+ var actual = { load: load2 };
2186
+ var lockfile = {
2187
+ load,
2188
+ loadEdges,
2189
+ loadNodes,
2190
+ save
2191
+ };
2192
+
2193
+ // ../../src/graph/src/reify/add-edge.ts
2194
+ import { mkdir, symlink } from "node:fs/promises";
2195
+ import { dirname as dirname3, relative as relative2 } from "node:path";
2196
+
2197
+ // ../../src/graph/src/reify/bin-paths.ts
2198
+ var parseScope = (scoped) => {
2199
+ if (scoped.startsWith("@")) {
2200
+ const [scope, name, ...rest] = scoped.split("/");
2201
+ if (scope && name && rest.length === 0) return [scope, name];
2202
+ }
2203
+ return [void 0, scoped];
2204
+ };
2205
+ var binPaths = (manifest) => {
2206
+ const { name, bin } = manifest;
2207
+ if (bin) {
2208
+ if (name && typeof bin === "string") {
2209
+ const [_scope, pkg] = parseScope(name);
2210
+ return { [pkg]: bin };
2211
+ } else if (typeof bin === "object") {
2212
+ return bin;
2213
+ }
2214
+ }
2215
+ return {};
2216
+ };
2217
+
2218
+ // ../../src/graph/src/reify/add-edge.ts
2219
+ var clobberSymlink = async (target, link, remover, type = "file") => {
2220
+ await mkdir(dirname3(link), { recursive: true });
2221
+ try {
2222
+ await symlink(target, link, type);
2223
+ } catch (e) {
2224
+ const er = e;
2225
+ if (er.code === "EEXIST") {
2226
+ return remover.rm(link).then(() => symlink(target, link));
2227
+ } else {
2228
+ throw er;
2229
+ }
2230
+ }
2231
+ };
2232
+ var addEdge = async (edge, manifest, scurry, remover) => {
2233
+ if (!edge.to) return;
2234
+ const binRoot = scurry.resolve(
2235
+ edge.from.nodeModules(scurry),
2236
+ ".bin"
2237
+ );
2238
+ const path = scurry.resolve(
2239
+ edge.from.nodeModules(scurry),
2240
+ edge.spec.name
2241
+ );
2242
+ const promises = [];
2243
+ const target = relative2(
2244
+ dirname3(path),
2245
+ edge.to.resolvedLocation(scurry)
2246
+ );
2247
+ promises.push(clobberSymlink(target, path, remover, "dir"));
2248
+ const bp = binPaths(manifest);
2249
+ for (const [key, val] of Object.entries(bp)) {
2250
+ const link = scurry.resolve(binRoot, key);
2251
+ const target2 = relative2(binRoot, scurry.resolve(path, val));
2252
+ promises.push(clobberSymlink(target2, link, remover));
2253
+ }
2254
+ await Promise.all(promises);
2255
+ };
2256
+
2257
+ // ../../src/graph/src/reify/add-edges.ts
2258
+ var addEdges = (diff, packageJson, scurry, remover) => {
2259
+ const actions = [];
2260
+ for (const edge of diff.edges.add) {
2261
+ const { to } = edge;
2262
+ if (!to) continue;
2263
+ const mani = to.manifest ?? packageJson.read(to.resolvedLocation(scurry));
2264
+ actions.push(addEdge(edge, mani, scurry, remover));
2265
+ }
2266
+ return actions;
2267
+ };
2268
+
2269
+ // ../../src/graph/src/reify/optional-fail.ts
2270
+ function optionalFail(diff, node) {
2271
+ return node.isOptional() ? () => del(diff, node) : void 0;
2272
+ }
2273
+ var del = (diff, node) => {
2274
+ diff.hadOptionalFailures = true;
2275
+ for (const del2 of removeOptionalSubgraph(diff.to, node)) {
2276
+ diff.nodes.delete.add(del2);
2277
+ diff.nodes.add.delete(del2);
2278
+ }
2279
+ diff.nodes.add.delete(node);
2280
+ diff.nodes.delete.add(node);
2281
+ };
2282
+
2283
+ // ../../src/graph/src/reify/add-nodes.ts
2284
+ var addNodes2 = (diff, scurry, remover, options, packageInfo) => {
2285
+ const actions = [];
2286
+ for (const node of diff.nodes.add) {
2287
+ const { manifest = {} } = node;
2288
+ if (!node.inVltStore()) continue;
2289
+ const target = node.resolvedLocation(scurry);
2290
+ const from = scurry.resolve("");
2291
+ const spec = hydrate(node.id, manifest.name, options);
2292
+ const onErr = optionalFail(diff, node);
2293
+ const { integrity, resolved } = node;
2294
+ if (onErr && (manifest.deprecated || !platformCheck(
2295
+ manifest,
2296
+ process.version,
2297
+ process.platform,
2298
+ process.arch
2299
+ ))) {
2300
+ onErr();
2301
+ continue;
2302
+ }
2303
+ actions.push(
2304
+ () => remover.rm(target).then(
2305
+ () => onErr ? packageInfo.extract(spec, target, { from, integrity, resolved }).then((x) => x, onErr) : packageInfo.extract(spec, target, {
2306
+ from,
2307
+ integrity,
2308
+ resolved
2309
+ })
2310
+ )
2311
+ );
2312
+ }
2313
+ return actions;
2314
+ };
2315
+
2316
+ // ../../src/graph/src/reify/build.ts
2317
+ import { statSync } from "node:fs";
2318
+ import { chmod } from "node:fs/promises";
2319
+
2320
+ // ../../src/graph/src/non-empty-list.ts
2321
+ var isNonEmptyList = (list) => !!list.length;
2322
+ var nonEmptyList = (nodes) => isNonEmptyList(nodes) ? nodes : void 0;
2323
+
2324
+ // ../../src/graph/src/reify/build.ts
2325
+ var build2 = async (diff, packageJson, scurry) => {
2326
+ const graph = diff.to;
2327
+ const nodes = nonEmptyList([...graph.importers]);
2328
+ if (!nodes) return;
2329
+ await graphRun({
2330
+ graph: nodes,
2331
+ visit: async (node, signal, path) => {
2332
+ if (!node.importer && !diff.nodes.add.has(node)) return;
2333
+ await visit(packageJson, scurry, node, signal, path).then(
2334
+ (x) => x,
2335
+ optionalFail(diff, node)
2336
+ );
2337
+ },
2338
+ getDeps: (node) => {
2339
+ const deps = [];
2340
+ for (const { to } of node.edgesOut.values()) {
2341
+ if (to) deps.push(to);
2342
+ }
2343
+ return deps;
2344
+ }
2345
+ });
2346
+ };
2347
+ var visit = async (packageJson, scurry, node, signal, _path) => {
2348
+ node.manifest ??= packageJson.read(node.resolvedLocation(scurry));
2349
+ const { manifest } = node;
2350
+ const { scripts = {} } = manifest;
2351
+ const {
2352
+ install: install2,
2353
+ preinstall,
2354
+ postinstall,
2355
+ prepare,
2356
+ preprepare,
2357
+ postprepare
2358
+ } = scripts;
2359
+ const runInstall = !!(install2 || preinstall || postinstall);
2360
+ if (runInstall) {
2361
+ await run({
2362
+ signal,
2363
+ arg0: "install",
2364
+ ignoreMissing: true,
2365
+ packageJson,
2366
+ cwd: node.resolvedLocation(scurry),
2367
+ projectRoot: node.projectRoot,
2368
+ manifest
2369
+ });
2370
+ }
2371
+ const prepable = node.id.startsWith("git") || node.importer || !node.inVltStore();
2372
+ const runPrepare = !!(prepare || preprepare || postprepare) && prepable;
2373
+ if (runPrepare) {
2374
+ await run({
2375
+ signal,
2376
+ arg0: "prepare",
2377
+ ignoreMissing: true,
2378
+ packageJson,
2379
+ cwd: node.resolvedLocation(scurry),
2380
+ projectRoot: node.projectRoot,
2381
+ manifest
2382
+ });
2383
+ }
2384
+ const chmods = [];
2385
+ for (const bin of Object.values(binPaths(manifest))) {
2386
+ const path = scurry.resolve(
2387
+ `${node.resolvedLocation(scurry)}/${bin}`
2388
+ );
2389
+ chmods.push(makeExecutable(path));
2390
+ }
2391
+ await Promise.all(chmods);
2392
+ };
2393
+ var execMode = 0;
2394
+ var makeExecutable = async (path) => {
2395
+ if (!execMode) {
2396
+ execMode = statSync(path).mode & 511 | 73;
2397
+ }
2398
+ await chmod(path, execMode);
2399
+ };
2400
+
2401
+ // ../../src/graph/src/reify/delete-edge.ts
2402
+ var rmBinPosix = (remover, bin) => {
2403
+ return [remover.rm(bin)];
2404
+ };
2405
+ var rmBinWin32 = (remover, bin) => {
2406
+ return [
2407
+ remover.rm(bin),
2408
+ remover.rm(bin + ".cmd"),
2409
+ remover.rm(bin + ".pwsh")
2410
+ ];
2411
+ };
2412
+ var rmBin = process.platform === "win32" ? rmBinWin32 : rmBinPosix;
2413
+ var deleteEdge = async (edge, scurry, remover) => {
2414
+ const {
2415
+ spec: { name },
2416
+ to
2417
+ } = edge;
2418
+ const nm = edge.from.nodeModules(scurry);
2419
+ const path = scurry.resolve(nm, name);
2420
+ const binRoot = scurry.cwd.resolve(`${nm}/.bin`);
2421
+ const promises = [];
2422
+ promises.push(remover.rm(path));
2423
+ const manifest = to?.manifest;
2424
+ if (manifest) {
2425
+ for (const key of Object.keys(binPaths(manifest))) {
2426
+ const bin = binRoot.resolve(key).fullpath();
2427
+ promises.push(...rmBin(remover, bin));
2428
+ }
2429
+ }
2430
+ await Promise.all(promises);
2431
+ };
2432
+
2433
+ // ../../src/graph/src/reify/delete-edges.ts
2434
+ var deleteEdges = (diff, scurry, remover) => {
2435
+ const promises = [];
2436
+ for (const edge of diff.edges.delete) {
2437
+ if (diff.nodes.delete.has(edge.from) && edge.from.inVltStore()) {
2438
+ continue;
2439
+ }
2440
+ promises.push(() => deleteEdge(edge, scurry, remover));
2441
+ }
2442
+ return promises;
2443
+ };
2444
+
2445
+ // ../../src/graph/src/reify/delete-nodes.ts
2446
+ var deleteNodes = (diff, remover, scurry) => {
2447
+ const store = scurry.resolve("node_modules/.vlt");
2448
+ const rmActions = [];
2449
+ for (const node of diff.nodes.delete) {
2450
+ if (!node.inVltStore()) continue;
2451
+ rmActions.push(remover.rm(scurry.resolve(store, node.id)));
2452
+ }
2453
+ return rmActions;
2454
+ };
2455
+
2456
+ // ../../src/graph/src/reify/rollback.ts
2457
+ var rollback = async (remover, diff, scurry) => {
2458
+ const promises = [];
2459
+ const store = scurry.resolve("node_modules/.vlt");
2460
+ const backRoller = new RollbackRemove();
2461
+ for (const node of diff.nodes.add) {
2462
+ if (!node.inVltStore()) continue;
2463
+ const path = scurry.resolve(store, node.id);
2464
+ promises.push(backRoller.rm(path).catch(() => {
2465
+ }));
2466
+ }
2467
+ for (const edge of diff.edges.add) {
2468
+ promises.push(deleteEdge(edge, scurry, backRoller));
2469
+ }
2470
+ await Promise.all(promises).catch(() => {
2471
+ });
2472
+ backRoller.confirm();
2473
+ await remover.rollback().catch(() => {
2474
+ });
2475
+ };
2476
+
2477
+ // ../../src/graph/src/reify/update-importers-package-json.ts
2478
+ var SAVE_PREFIX = "^";
2479
+ var depTypesMap = /* @__PURE__ */ new Map([
2480
+ ["prod", "dependencies"],
2481
+ ["dev", "devDependencies"],
2482
+ ["peer", "peerDependencies"],
2483
+ ["peerOptional", "peerDependencies"],
2484
+ ["optional", "optionalDependencies"]
2485
+ ]);
2486
+ var addOrRemoveDeps = (importerId, graph, addOrRemove) => {
2487
+ const importer = graph.nodes.get(importerId);
2488
+ if (!importer) {
2489
+ throw error("Failed to retrieve importer node", {
2490
+ found: importerId
2491
+ });
2492
+ }
2493
+ const manifest = importer.manifest;
2494
+ if (!manifest) {
2495
+ throw error("Could not find manifest data for node", {
2496
+ found: importerId
2497
+ });
2498
+ }
2499
+ const deps = addOrRemove?.get(importerId);
2500
+ if (!deps) {
2501
+ throw error("Failed to retrieve added deps info", {
2502
+ manifest
2503
+ });
2504
+ }
2505
+ let manifestChanged = false;
2506
+ for (const deleteNameOrAddItem of deps) {
2507
+ if (typeof deleteNameOrAddItem === "string") {
2508
+ const name = deleteNameOrAddItem;
2509
+ for (const depType of longDependencyTypes) {
2510
+ if (manifest[depType]?.[name]) {
2511
+ delete manifest[depType][name];
2512
+ manifestChanged = true;
2513
+ }
2514
+ }
2515
+ } else {
2516
+ const [name, dep] = deleteNameOrAddItem;
2517
+ const depType = depTypesMap.get(dep.type);
2518
+ if (!depType) {
2519
+ throw error("Failed to retrieve dependency type", {
2520
+ validOptions: [...depTypesMap.keys()],
2521
+ found: dep.type
2522
+ });
2523
+ }
2524
+ const node = importer.edgesOut.get(name)?.to;
2525
+ if (!node) {
2526
+ throw error("Dependency node could not be found");
2527
+ }
2528
+ const [nodeType] = splitDepID(node.id);
2529
+ const dependencies = manifest[depType] ?? (manifest[depType] = {});
2530
+ dependencies[name] = nodeType === "registry" && (!dep.spec.final.semver || !dep.spec.final.range) ? dep.spec.subspec && dep.spec.namedRegistry ? `${dep.spec.final.namedRegistry}:${dep.spec.final.name}@${SAVE_PREFIX}${node.version}` : `${SAVE_PREFIX}${node.version}` : dep.spec.bareSpec;
2531
+ manifestChanged = true;
2532
+ }
2533
+ }
2534
+ return manifestChanged ? manifest : void 0;
2535
+ };
2536
+ var updatePackageJson = ({
2537
+ add,
2538
+ graph,
2539
+ packageJson,
2540
+ remove
2541
+ }) => {
2542
+ const manifestsToUpdate = /* @__PURE__ */ new Set();
2543
+ const operations = /* @__PURE__ */ new Set([add, remove]);
2544
+ for (const operation of operations) {
2545
+ if (operation) {
2546
+ for (const importerId of operation.keys()) {
2547
+ const manifest = addOrRemoveDeps(importerId, graph, operation);
2548
+ if (manifest) {
2549
+ manifestsToUpdate.add(manifest);
2550
+ }
2551
+ }
2552
+ }
2553
+ }
2554
+ const commit = () => {
2555
+ for (const manifest of manifestsToUpdate) {
2556
+ packageJson.save(manifest);
2557
+ }
2558
+ };
2559
+ return commit;
2560
+ };
2561
+
2562
+ // ../../src/graph/src/reify/index.ts
2563
+ var limit = Math.max(availableParallelism2() - 1, 1) * 8;
2564
+ var reify = async (options) => {
2565
+ const done = graphStep("reify");
2566
+ const { graph, scurry } = options;
2567
+ const actual2 = options.actual ?? load2({
2568
+ ...options,
2569
+ loadManifests: true
2570
+ });
2571
+ const diff = new Diff(actual2, graph);
2572
+ const remover = new RollbackRemove();
2573
+ let success = false;
2574
+ try {
2575
+ await reify_(options, diff, remover);
2576
+ remover.confirm();
2577
+ success = true;
2578
+ } finally {
2579
+ if (!success) {
2580
+ await rollback(remover, diff, scurry).catch(() => {
2581
+ });
2582
+ }
2583
+ }
2584
+ done();
2585
+ return diff;
2586
+ };
2587
+ var reify_ = async (options, diff, remover) => {
2588
+ const { add, remove, packageInfo, packageJson, scurry } = options;
2589
+ const saveImportersPackageJson = add?.modifiedDependencies || remove?.modifiedDependencies ? updatePackageJson({
2590
+ add,
2591
+ remove,
2592
+ graph: options.graph,
2593
+ packageJson
2594
+ }) : void 0;
2595
+ const lfData = lockfileData(options);
2596
+ const actions = addNodes2(
2597
+ diff,
2598
+ scurry,
2599
+ remover,
2600
+ options,
2601
+ packageInfo
2602
+ ).concat(deleteEdges(diff, scurry, remover));
2603
+ if (actions.length) await callLimit(actions, { limit });
2604
+ const edgeActions = addEdges(
2605
+ diff,
2606
+ packageJson,
2607
+ scurry,
2608
+ remover
2609
+ );
2610
+ if (edgeActions.length) await Promise.all(edgeActions);
2611
+ await build2(diff, packageJson, scurry);
2612
+ lockfile.save(options);
2613
+ if (diff.hadOptionalFailures) {
2614
+ for (const node of options.graph.gc().values()) {
2615
+ diff.nodes.add.delete(node);
2616
+ diff.nodes.delete.add(node);
2617
+ }
2618
+ }
2619
+ saveHidden(options);
2620
+ const rmActions = deleteNodes(
2621
+ diff,
2622
+ remover,
2623
+ scurry
2624
+ );
2625
+ if (rmActions.length) await Promise.all(rmActions);
2626
+ saveImportersPackageJson?.();
2627
+ saveData(lfData, scurry.resolve("vlt-lock.json"), false);
2628
+ };
2629
+
2630
+ // ../../src/graph/src/install.ts
2631
+ var install = async (options, add) => {
2632
+ const mainManifest = options.packageJson.read(options.projectRoot);
2633
+ const graph = await build({
2634
+ ...options,
2635
+ add,
2636
+ mainManifest,
2637
+ loadManifests: true
2638
+ });
2639
+ const act = load2({
2640
+ ...options,
2641
+ mainManifest,
2642
+ loadManifests: true
2643
+ });
2644
+ const diff = await reify({
2645
+ ...options,
2646
+ add,
2647
+ actual: act,
2648
+ graph,
2649
+ loadManifests: true
2650
+ });
2651
+ return { graph, diff };
2652
+ };
2653
+
2654
+ export {
2655
+ callLimit,
2656
+ splitDepID2 as splitDepID,
2657
+ hydrate2 as hydrate,
2658
+ asDependency,
2659
+ jsonOutput,
2660
+ humanReadableOutput,
2661
+ mermaidOutput,
2662
+ install,
2663
+ uninstall,
2664
+ actual
2665
+ };
2666
+ //# sourceMappingURL=chunk-66GJ6BNX.js.map