@vltpkg/cli-js 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/{access-SXQICNAN.js → access-5WETTBDZ.js} +9 -7
  2. package/{bugs-OOPMFRCI.js → bugs-KONFLIQQ.js} +19 -18
  3. package/{build-HDXI5OA7.js → build-S7G2DU7I.js} +12 -10
  4. package/{cache-RW4Y4XNQ.js → cache-Z4OIMLXQ.js} +23 -21
  5. package/{chunk-RXNA2XCX.js → chunk-4KCU2KZL.js} +8 -1
  6. package/{chunk-F2FKLPZD.js → chunk-5B23EKN4.js} +4 -4
  7. package/{chunk-4ZXA6RLP.js → chunk-5QJEOGEM.js} +3 -1
  8. package/{chunk-CCQYIYTA.js → chunk-5UPPEUG2.js} +11 -11
  9. package/chunk-BJBFEQRR.js +667 -0
  10. package/{chunk-MU7Y4R5E.js → chunk-DYCF76WI.js} +4 -4
  11. package/{chunk-EHEVBLDB.js → chunk-E737X73P.js} +38 -24
  12. package/{chunk-ICJRCXSG.js → chunk-FFOXTPQA.js} +12 -9
  13. package/chunk-G7UPIJAP.js +903 -0
  14. package/{chunk-CNSTFT7U.js → chunk-HAYXR3MW.js} +1 -1
  15. package/{chunk-U6DM3ROE.js → chunk-HNCE3YE5.js} +1649 -1569
  16. package/{chunk-2PLIV3N3.js → chunk-IITIX4ID.js} +740 -6
  17. package/chunk-LPIBYUMT.js +854 -0
  18. package/{chunk-E5YE7UTZ.js → chunk-LZGKX7JI.js} +114 -50
  19. package/{chunk-3SQ5Y324.js → chunk-NXEH3NQZ.js} +11 -13
  20. package/{chunk-MT76WHSM.js → chunk-OCJDISSI.js} +12 -6
  21. package/chunk-RNJSI3NZ.js +75 -0
  22. package/{chunk-FAG776ZD.js → chunk-T4GYDWUJ.js} +1 -1
  23. package/{chunk-VM2RMMY4.js → chunk-TMBNGWXK.js} +3 -3
  24. package/{chunk-EQ633HIM.js → chunk-UAAZW4N6.js} +4 -4
  25. package/{chunk-D5CP6O6G.js → chunk-UXIRAU5T.js} +4 -4
  26. package/{chunk-EFWPI6IY.js → chunk-VB3IWNHX.js} +1 -1
  27. package/chunk-VE6CCH33.js +3000 -0
  28. package/{chunk-UCD3RJYG.js → chunk-W2Q5EIMH.js} +8 -8
  29. package/{chunk-VZ7UNZHR.js → chunk-XQSBCMSC.js} +5 -5
  30. package/{reporter-2XBYWAVU.js → chunk-XU5SMHXP.js} +35 -10
  31. package/{ci-MTYU2K2A.js → ci-RZZE375O.js} +17 -16
  32. package/cli-package.json +1 -1
  33. package/{config-TVAXCTQO.js → config-LL3RLMZG.js} +9 -12
  34. package/{config-6NXV2BXW.js → config-MDFY3ORD.js} +15 -18
  35. package/{create-LXI5DCDW.js → create-GVSDTOGQ.js} +23 -23
  36. package/{deprecate-2AQBL5XT.js → deprecate-T4TQLGXQ.js} +16 -14
  37. package/{dist-tag-BFSYLRIH.js → dist-tag-GO46UQUN.js} +11 -9
  38. package/{docs-ADPJ4B4C.js → docs-FJME563T.js} +19 -18
  39. package/{exec-GMS54RAC.js → exec-M22KBPCK.js} +23 -23
  40. package/{exec-cache-R5LVZL5Z.js → exec-cache-3UNLDUAP.js} +22 -22
  41. package/{exec-local-TVCLZGIM.js → exec-local-YHVO5RLU.js} +20 -18
  42. package/{help-6CECUD6C.js → help-ZEWMLOJX.js} +3 -3
  43. package/{init-XXFLGYVP.js → init-4HPZY2KN.js} +12 -10
  44. package/{install-6KMXYSF5.js → install-2TZIP4PJ.js} +18 -17
  45. package/{list-RUO3SUKY.js → list-NFFXER43.js} +20 -18
  46. package/{login-6I2CGO7I.js → login-KV5YC5Z2.js} +9 -7
  47. package/{logout-JTU4BJKH.js → logout-I2VT3NAR.js} +9 -7
  48. package/{pack-NCWH2TUA.js → pack-47ZKFSHI.js} +16 -14
  49. package/package.json +6 -6
  50. package/{ping-4MEAC2WD.js → ping-Q7Y7QV63.js} +9 -7
  51. package/{pkg-ENSKG6G7.js → pkg-VTJS2ISJ.js} +13 -11
  52. package/{profile-62YHNFSO.js → profile-YXZYVEUX.js} +9 -7
  53. package/{publish-PPY724N2.js → publish-CBN67KN2.js} +21 -19
  54. package/{query-NLWXKOOT.js → query-U3QHF3ZE.js} +20 -18
  55. package/{registry-QGI44LG4.js → registry-CZPFR3OF.js} +3 -3
  56. package/registry-client-package.json +1 -1
  57. package/registry-client-src-revalidate.js +2080 -349
  58. package/{repo-BFRAXIVU.js → repo-4UIQRBI7.js} +19 -18
  59. package/{chunk-4RZDJQ5U.js → reporter-DKZTTACW.js} +5 -5
  60. package/{run-7O65747G.js → run-5DUYI6GL.js} +20 -18
  61. package/{run-exec-2OYWHL6K.js → run-exec-HPNBVAXH.js} +20 -18
  62. package/security-archive-src-update-expired.js +39 -4
  63. package/{setup-MMIDAIJI.js → setup-23W5FQVW.js} +24 -15
  64. package/{src-OK3KHDYR.js → src-2NB67FPG.js} +22 -23
  65. package/src-6OKPBJJT.js +59 -0
  66. package/src-M5RRGKUM.js +913 -0
  67. package/{token-VLVXUW54.js → token-SRCS5CRU.js} +9 -7
  68. package/{uninstall-TAG6QIAG.js → uninstall-JXHAFXZ2.js} +18 -17
  69. package/{unpublish-Y4L5J2IA.js → unpublish-GRYB5KQH.js} +12 -10
  70. package/{update-RYH4RKBS.js → update-GDLL4ER6.js} +17 -16
  71. package/{version-COHB32ON.js → version-JVG4CI4L.js} +13 -11
  72. package/{view-P7U4MF43.js → view-ABQLVL4L.js} +13 -15
  73. package/vlr.js +1 -1
  74. package/vlrx.js +1 -1
  75. package/vlt.js +1 -1
  76. package/vlx.js +1 -1
  77. package/vlxl.js +1 -1
  78. package/{whoami-47MVFMZC.js → whoami-RCCZ7BXI.js} +9 -7
  79. package/chunk-7NHXV6AH.js +0 -4488
  80. package/chunk-HB7CKTYO.js +0 -75
  81. package/chunk-PW6S6AIO.js +0 -716
  82. package/chunk-WXMYKCQW.js +0 -1640
  83. package/{chunk-Y7CQIZ7Y.js → chunk-FEIPJIEN.js} +3 -3
@@ -0,0 +1,903 @@
1
+ var global = globalThis;
2
+ import {Buffer} from "node:buffer";
3
+ import {setTimeout as _vlt_setTimeout,clearTimeout as _vlt_clearTimeout,setImmediate as _vlt_setImmediate,clearImmediate as _vlt_clearImmediate,setInterval as _vlt_setInterval,clearInterval as _vlt_clearInterval} from "node:timers";
4
+ globalThis.setTimeout = _vlt_setTimeout;
5
+ globalThis.clearTimeout = _vlt_clearTimeout;
6
+ globalThis.setImmediate = _vlt_setImmediate;
7
+ globalThis.clearImmediate = _vlt_clearImmediate;
8
+ globalThis.setInterval = _vlt_setInterval;
9
+ globalThis.clearInterval = _vlt_clearInterval;
10
+ import {createRequire as _vlt_createRequire} from "node:module";
11
+ var require = _vlt_createRequire(import.meta.filename);
12
+ import {
13
+ Qn,
14
+ require_lib
15
+ } from "./chunk-FWKQ7YDF.js";
16
+ import {
17
+ Monorepo,
18
+ PackageJson,
19
+ clone,
20
+ pickManifest,
21
+ resolve,
22
+ revs
23
+ } from "./chunk-FFOXTPQA.js";
24
+ import {
25
+ Spec
26
+ } from "./chunk-XU5SMHXP.js";
27
+ import {
28
+ XDG
29
+ } from "./chunk-XNLSTHDK.js";
30
+ import {
31
+ asPackument
32
+ } from "./chunk-IITIX4ID.js";
33
+ import {
34
+ error
35
+ } from "./chunk-WZWDS3W4.js";
36
+ import {
37
+ __toESM
38
+ } from "./chunk-PZLD7RTK.js";
39
+
40
+ // ../../src/package-info/src/index.ts
41
+ var import_ssri = __toESM(require_lib(), 1);
42
+ import { createHash, randomBytes } from "node:crypto";
43
+ import {
44
+ mkdir,
45
+ readFile,
46
+ rm as rm2,
47
+ stat,
48
+ symlink,
49
+ unlink,
50
+ writeFile
51
+ } from "node:fs/promises";
52
+ import {
53
+ basename,
54
+ dirname,
55
+ resolve as pathResolve,
56
+ relative
57
+ } from "node:path";
58
+
59
+ // ../../src/package-info/src/rename.ts
60
+ import { rename as fsRename, rm } from "node:fs/promises";
61
+ var { platform } = process;
62
+ var rename = platform !== "win32" ? fsRename : (async function(oldPath, newPath) {
63
+ let retries = 3;
64
+ const retry = async (er) => {
65
+ if (retries > 0 && er.code === "EPERM") {
66
+ retries--;
67
+ await rm(newPath, { recursive: true, force: true });
68
+ return fsRename(oldPath, newPath).then(() => {
69
+ }, retry);
70
+ } else {
71
+ throw er;
72
+ }
73
+ };
74
+ return fsRename(oldPath, newPath).then(() => {
75
+ }, retry);
76
+ });
77
+
78
+ // ../../src/package-info/src/index.ts
79
+ var xdg = new XDG("vlt");
80
+ var delimiter = "~";
81
+ var manifestCacheMaxAge = 5 * 60 * 1e3;
82
+ var noRegistryError = (spec) => error(
83
+ 'No registry configured to resolve this spec. Set "registry" in vlt.json, pass --registry, or run `vlt login --registry=<url>`. See https://docs.vlt.sh/cli',
84
+ { code: "ECONFIG", spec }
85
+ );
86
+ var PackageInfoClient = class {
87
+ #registryClient;
88
+ #projectRoot;
89
+ #tarPool;
90
+ options;
91
+ #resolutions = /* @__PURE__ */ new Map();
92
+ packageJson;
93
+ monorepo;
94
+ #trustedIntegrities = /* @__PURE__ */ new Map();
95
+ #manifestCacheMinAge = Date.now() - manifestCacheMaxAge;
96
+ #cachePath;
97
+ // In-flight coalescing key is `${registry}${name}` — no representation
98
+ // component. Safe only because every caller requests the same full
99
+ // packument (see #fetchPackument).
100
+ #packumentPromises = /* @__PURE__ */ new Map();
101
+ // unique temp file names for atomic manifest cache writes
102
+ #manifestWriteRandom = randomBytes(6).toString("hex");
103
+ #manifestWriteCount = 0;
104
+ // cache paths already written this run. manifest() is called many
105
+ // times for the same cache key per install and content for a given
106
+ // path is deterministic within a run, so only the first write is
107
+ // needed. entries are removed when the on-disk file is invalidated
108
+ // so the refreshed manifest can be written again.
109
+ #manifestWritePaths = /* @__PURE__ */ new Set();
110
+ #registryClientPromise;
111
+ #tarPoolPromise;
112
+ async getRegistryClient() {
113
+ if (this.#registryClient) return this.#registryClient;
114
+ this.#registryClientPromise ??= import("./src-6OKPBJJT.js").then(({ RegistryClient }) => {
115
+ this.#registryClient = new RegistryClient(this.options);
116
+ return this.#registryClient;
117
+ });
118
+ return this.#registryClientPromise;
119
+ }
120
+ async getTarPool() {
121
+ if (this.#tarPool) return this.#tarPool;
122
+ this.#tarPoolPromise ??= import("./src-M5RRGKUM.js").then(
123
+ ({ Pool }) => {
124
+ this.#tarPool = new Pool();
125
+ return this.#tarPool;
126
+ }
127
+ );
128
+ return this.#tarPoolPromise;
129
+ }
130
+ constructor(options = {}) {
131
+ this.options = options;
132
+ this.#projectRoot = options.projectRoot || process.cwd();
133
+ this.packageJson = options.packageJson ?? new PackageJson();
134
+ const wsLoad = {
135
+ ...options.workspace?.length && { paths: options.workspace },
136
+ ...options["workspace-group"]?.length && {
137
+ groups: options["workspace-group"]
138
+ }
139
+ };
140
+ this.monorepo = options.monorepo ?? Monorepo.maybeLoad(this.#projectRoot, {
141
+ load: wsLoad,
142
+ packageJson: this.packageJson
143
+ });
144
+ this.#cachePath = options.cache ?? xdg.cache();
145
+ void mkdir(pathResolve(this.#cachePath, "package-info"), {
146
+ recursive: true
147
+ }).catch(() => {
148
+ });
149
+ }
150
+ async extract(spec, target, options = {}) {
151
+ if (typeof spec === "string")
152
+ spec = Spec.parse(spec, this.options);
153
+ const {
154
+ from = this.#projectRoot,
155
+ integrity,
156
+ resolved,
157
+ fromLockfile = false
158
+ } = options;
159
+ const f = spec.final;
160
+ const alreadyResolved = !!(integrity && resolved);
161
+ const r = alreadyResolved ? { resolved, integrity, spec } : await this.resolve(spec, options);
162
+ switch (f.type) {
163
+ case "git": {
164
+ const {
165
+ gitRemote,
166
+ gitCommittish,
167
+ remoteURL,
168
+ gitSelectorParsed
169
+ } = f;
170
+ if (!remoteURL) {
171
+ if (!gitRemote)
172
+ throw this.#resolveError(
173
+ spec,
174
+ options,
175
+ "no remote on git: specifier"
176
+ );
177
+ const { path } = gitSelectorParsed ?? {};
178
+ if (path !== void 0) {
179
+ const tmp = pathResolve(
180
+ dirname(target),
181
+ `.TEMP.${basename(target)}-${randomBytes(6).toString("hex")}`
182
+ );
183
+ await clone(gitRemote, gitCommittish, tmp, { spec });
184
+ const src = pathResolve(tmp, path);
185
+ await rename(src, target);
186
+ void rm2(tmp, { recursive: true, force: true });
187
+ } else {
188
+ await clone(gitRemote, gitCommittish, target, { spec });
189
+ void rm2(target + "/.git", { recursive: true });
190
+ }
191
+ return r;
192
+ }
193
+ }
194
+ case "registry": {
195
+ const fetchTarball = async (useCache) => {
196
+ const trustIntegrity = this.#trustedIntegrities.get(r.resolved) === r.integrity;
197
+ const response = await (await this.getRegistryClient()).request(r.resolved, {
198
+ integrity: r.integrity,
199
+ trustIntegrity,
200
+ ...useCache === false ? { useCache } : {}
201
+ });
202
+ if (response.statusCode !== 200) {
203
+ throw this.#resolveError(
204
+ spec,
205
+ options,
206
+ `Registry returned HTTP ${response.statusCode} when fetching the tarball for ${spec}. The resolved version may have been unpublished, or the registry may be misconfigured or unreachable.`,
207
+ {
208
+ url: r.resolved,
209
+ response
210
+ }
211
+ );
212
+ }
213
+ if (!trustIntegrity && response.checkIntegrity({ spec, url: resolved })) {
214
+ this.#trustedIntegrities.set(
215
+ r.resolved,
216
+ response.integrity
217
+ );
218
+ }
219
+ const buf2 = response.buffer();
220
+ if (r.integrity && !fromLockfile && !response.fromCache) {
221
+ const hash = createHash("sha512");
222
+ hash.update(buf2);
223
+ const computed = `sha512-${hash.digest("base64")}`;
224
+ if (computed !== r.integrity) {
225
+ throw error("Tarball integrity check failed", {
226
+ code: "EINTEGRITY",
227
+ spec,
228
+ url: r.resolved,
229
+ wanted: r.integrity,
230
+ found: computed
231
+ });
232
+ }
233
+ }
234
+ return buf2;
235
+ };
236
+ let buf;
237
+ try {
238
+ buf = await fetchTarball();
239
+ } catch (er) {
240
+ if (er instanceof Error && "cause" in er && er.cause?.code === "EINTEGRITY") {
241
+ buf = await fetchTarball(false);
242
+ } else {
243
+ throw er;
244
+ }
245
+ }
246
+ try {
247
+ await (await this.getTarPool()).unpack(buf, target);
248
+ } catch (er) {
249
+ throw this.#resolveError(
250
+ spec,
251
+ options,
252
+ "tar unpack failed",
253
+ { cause: er }
254
+ );
255
+ }
256
+ return r;
257
+ }
258
+ case "remote": {
259
+ const response = await (await this.getRegistryClient()).request(r.resolved);
260
+ if (response.statusCode !== 200) {
261
+ throw this.#resolveError(
262
+ spec,
263
+ options,
264
+ "failed to fetch remote tarball",
265
+ {
266
+ url: r.resolved,
267
+ response
268
+ }
269
+ );
270
+ }
271
+ const buf = response.buffer();
272
+ const computed = import_ssri.default.fromData(buf, { algorithms: ["sha512"] }).toString();
273
+ if (r.integrity && r.integrity !== computed) {
274
+ throw error("Integrity check failure", {
275
+ code: "EINTEGRITY",
276
+ spec,
277
+ url: r.resolved,
278
+ wanted: r.integrity,
279
+ found: computed
280
+ });
281
+ }
282
+ r.integrity = computed;
283
+ try {
284
+ await (await this.getTarPool()).unpack(buf, target);
285
+ } catch (er) {
286
+ throw this.#resolveError(
287
+ spec,
288
+ options,
289
+ "remote tar unpack failed",
290
+ { cause: er }
291
+ );
292
+ }
293
+ return r;
294
+ }
295
+ case "file": {
296
+ const { file } = f;
297
+ if (file === void 0)
298
+ throw this.#resolveError(spec, options, "no file path");
299
+ const path = pathResolve(from, file);
300
+ const st = await stat(path);
301
+ if (st.isFile()) {
302
+ try {
303
+ await (await this.getTarPool()).unpack(await this.tarball(spec, options), target);
304
+ } catch (er) {
305
+ throw this.#resolveError(
306
+ spec,
307
+ options,
308
+ "tar unpack failed",
309
+ { cause: er }
310
+ );
311
+ }
312
+ } else if (st.isDirectory()) {
313
+ const rel = relative(dirname(target), path);
314
+ await symlink(rel, target, "dir");
315
+ } else {
316
+ throw this.#resolveError(
317
+ spec,
318
+ options,
319
+ "file: specifier does not resolve to directory or tarball"
320
+ );
321
+ }
322
+ return r;
323
+ }
324
+ case "workspace": {
325
+ const ws = this.#getWS(spec, options);
326
+ const rel = relative(dirname(target), ws.fullpath);
327
+ await symlink(rel, target, "dir");
328
+ return r;
329
+ }
330
+ }
331
+ }
332
+ #getWS(spec, options) {
333
+ const { workspace } = spec;
334
+ if (workspace === void 0)
335
+ throw this.#resolveError(spec, options, "no workspace ID");
336
+ if (!this.monorepo) {
337
+ throw this.#resolveError(
338
+ spec,
339
+ options,
340
+ "Not in a monorepo, cannot resolve workspace spec"
341
+ );
342
+ }
343
+ const ws = this.monorepo.get(workspace);
344
+ if (!ws) {
345
+ throw this.#resolveError(spec, options, "workspace not found", {
346
+ wanted: workspace
347
+ });
348
+ }
349
+ return ws;
350
+ }
351
+ /**
352
+ * Return the manifest cache key for a spec and the current options.
353
+ */
354
+ #manifestCacheKey(spec, options) {
355
+ let extra = "";
356
+ if (options["node-version"]) {
357
+ extra += `${delimiter}node-version:${options["node-version"]}`;
358
+ }
359
+ if (options.os) {
360
+ extra += `${delimiter}os:${options.os}`;
361
+ }
362
+ if (options.arch) {
363
+ extra += `${delimiter}arch:${options.arch}`;
364
+ }
365
+ return encodeURIComponent(
366
+ `${spec.registry ?? ""}${delimiter}${spec}${extra}`
367
+ );
368
+ }
369
+ /**
370
+ * Conditionally return the path to the manifest cache file. The logic
371
+ * to determine if caching should be skipped aligns with `pickManifest`
372
+ * and is used to avoid caching manifest results that can be variable.
373
+ */
374
+ _manifestCachePath(spec, options) {
375
+ if (options.before) {
376
+ return;
377
+ }
378
+ const f = spec.final;
379
+ if (f.distTag || f.range?.isAny) {
380
+ return;
381
+ }
382
+ const key = this.#manifestCacheKey(f, options);
383
+ return pathResolve(this.#cachePath, "package-info", key);
384
+ }
385
+ /**
386
+ * Write a manifest cache file atomically (write to a temp file in
387
+ * the same directory, then rename over the destination) so that
388
+ * concurrent readers never observe a partially written manifest.
389
+ * Freshness is tracked via the resulting file's mtime.
390
+ */
391
+ async #writeManifestCache(cachePath, json) {
392
+ const tmp = `${cachePath}.${this.#manifestWriteRandom}.${this.#manifestWriteCount++}`;
393
+ try {
394
+ try {
395
+ await writeFile(tmp, json, "utf8");
396
+ } catch (err) {
397
+ if (!(err instanceof Error && "code" in err && err.code === "ENOENT")) {
398
+ throw err;
399
+ }
400
+ await mkdir(dirname(cachePath), { recursive: true });
401
+ await writeFile(tmp, json, "utf8");
402
+ }
403
+ await rename(tmp, cachePath);
404
+ } catch {
405
+ }
406
+ }
407
+ async tarball(spec, options = {}) {
408
+ if (typeof spec === "string")
409
+ spec = Spec.parse(spec, this.options);
410
+ const f = spec.final;
411
+ switch (f.type) {
412
+ case "registry": {
413
+ const { dist } = await this.manifest(spec, options);
414
+ if (!dist)
415
+ throw this.#resolveError(
416
+ spec,
417
+ options,
418
+ `The registry manifest for ${spec} has no "dist" section, so no tarball can be resolved. The package version may be malformed or unpublished.`
419
+ );
420
+ const { tarball, integrity } = dist;
421
+ if (!tarball) {
422
+ throw this.#resolveError(
423
+ spec,
424
+ options,
425
+ `The registry manifest for ${spec} is missing a tarball URL (dist.tarball). The package version may be malformed or unpublished in this registry.`
426
+ );
427
+ }
428
+ const fetchTarball = async (useCache) => {
429
+ const trustIntegrity = this.#trustedIntegrities.get(tarball) === integrity;
430
+ const response = await (await this.getRegistryClient()).request(tarball, {
431
+ ...options,
432
+ integrity,
433
+ trustIntegrity,
434
+ ...useCache === false ? { useCache } : {}
435
+ });
436
+ if (response.statusCode !== 200) {
437
+ throw this.#resolveError(
438
+ spec,
439
+ options,
440
+ `Registry returned HTTP ${response.statusCode} when fetching the tarball for ${spec} at ${tarball}. The version may have been unpublished, or the registry may be misconfigured or unreachable.`,
441
+ { response, url: tarball }
442
+ );
443
+ }
444
+ if (!trustIntegrity && response.checkIntegrity({ spec, url: tarball })) {
445
+ this.#trustedIntegrities.set(tarball, response.integrity);
446
+ }
447
+ const buf = response.buffer();
448
+ if (integrity && !response.fromCache) {
449
+ const hash = createHash("sha512");
450
+ hash.update(buf);
451
+ const computed = `sha512-${hash.digest("base64")}`;
452
+ if (computed !== integrity) {
453
+ throw error("Tarball integrity check failed", {
454
+ code: "EINTEGRITY",
455
+ spec,
456
+ url: tarball,
457
+ wanted: integrity,
458
+ found: computed
459
+ });
460
+ }
461
+ }
462
+ return buf;
463
+ };
464
+ try {
465
+ return await fetchTarball();
466
+ } catch (er) {
467
+ if (er instanceof Error && "cause" in er && er.cause?.code === "EINTEGRITY") {
468
+ return await fetchTarball(false);
469
+ }
470
+ throw er;
471
+ }
472
+ }
473
+ case "git": {
474
+ const {
475
+ remoteURL,
476
+ gitRemote,
477
+ gitCommittish,
478
+ gitSelectorParsed
479
+ } = f;
480
+ const s = spec;
481
+ if (!remoteURL) {
482
+ if (!gitRemote) {
483
+ throw this.#resolveError(
484
+ spec,
485
+ options,
486
+ "no remote on git: specifier"
487
+ );
488
+ }
489
+ const { path } = gitSelectorParsed ?? {};
490
+ return await this.#tmpdir(async (dir) => {
491
+ await clone(gitRemote, gitCommittish, dir + "/package", {
492
+ spec: s
493
+ });
494
+ let cwd = dir;
495
+ if (path !== void 0) {
496
+ const src = pathResolve(dir, "package", path);
497
+ cwd = dirname(src);
498
+ const pkg = pathResolve(cwd, "package");
499
+ if (src !== pkg) {
500
+ const rand = randomBytes(6).toString("hex");
501
+ await rename(pkg, pkg + rand).catch(() => {
502
+ });
503
+ await rename(src, pkg);
504
+ }
505
+ }
506
+ return Qn({ cwd, gzip: true }, ["package"]).concat();
507
+ });
508
+ }
509
+ }
510
+ case "remote": {
511
+ const { remoteURL } = f;
512
+ if (!remoteURL) {
513
+ throw this.#resolveError(spec, options);
514
+ }
515
+ const response = await (await this.getRegistryClient()).request(remoteURL);
516
+ if (response.statusCode !== 200) {
517
+ throw this.#resolveError(
518
+ spec,
519
+ options,
520
+ "failed to fetch URL",
521
+ { response, url: remoteURL }
522
+ );
523
+ }
524
+ return response.buffer();
525
+ }
526
+ case "file": {
527
+ const { file } = f;
528
+ if (file === void 0)
529
+ throw this.#resolveError(spec, options, "no file path");
530
+ const { from = this.#projectRoot } = options;
531
+ const path = pathResolve(from, file);
532
+ const st = await stat(path);
533
+ if (st.isDirectory()) {
534
+ const p = dirname(path);
535
+ const b = basename(path);
536
+ return Qn({ cwd: p, gzip: true }, [b]).concat();
537
+ }
538
+ return readFile(path);
539
+ }
540
+ case "workspace": {
541
+ const ws = this.#getWS(spec, options);
542
+ const p = dirname(ws.fullpath);
543
+ const b = basename(ws.fullpath);
544
+ return Qn({ cwd: p, gzip: true }, [b]).concat();
545
+ }
546
+ }
547
+ }
548
+ async manifest(spec, options = {}) {
549
+ const { from = this.#projectRoot } = options;
550
+ if (typeof spec === "string")
551
+ spec = Spec.parse(spec, this.options);
552
+ const f = spec.final;
553
+ switch (f.type) {
554
+ case "registry": {
555
+ const cachePath = this._manifestCachePath(spec, options);
556
+ if (cachePath) {
557
+ try {
558
+ const [st, cached] = await Promise.all([
559
+ stat(cachePath),
560
+ readFile(cachePath, "utf8")
561
+ ]);
562
+ const json = JSON.parse(cached);
563
+ if (st.mtimeMs < this.#manifestCacheMinAge || json.__VLT_MANIFEST_CACHE_TIMESTAMP !== void 0) {
564
+ this.#manifestWritePaths.delete(cachePath);
565
+ void unlink(cachePath).catch(() => {
566
+ });
567
+ throw new Error("manifest cache expired");
568
+ }
569
+ return json;
570
+ } catch {
571
+ }
572
+ }
573
+ const mani = pickManifest(
574
+ await this.packument(f, options),
575
+ spec,
576
+ options
577
+ );
578
+ if (!mani) throw this.#resolveError(spec, options);
579
+ if (cachePath && !this.#manifestWritePaths.has(cachePath)) {
580
+ this.#manifestWritePaths.add(cachePath);
581
+ void this.#writeManifestCache(
582
+ cachePath,
583
+ JSON.stringify(mani)
584
+ );
585
+ }
586
+ return mani;
587
+ }
588
+ case "git": {
589
+ const {
590
+ gitRemote,
591
+ gitCommittish,
592
+ remoteURL,
593
+ gitSelectorParsed
594
+ } = f;
595
+ if (!remoteURL) {
596
+ const s = spec;
597
+ if (!gitRemote)
598
+ throw this.#resolveError(spec, options, "no git remote");
599
+ return await this.#tmpdir(async (dir) => {
600
+ await clone(gitRemote, gitCommittish, dir, { spec: s });
601
+ const { path } = gitSelectorParsed ?? {};
602
+ const pkgDir = path !== void 0 ? pathResolve(dir, path) : dir;
603
+ return this.#readExtracted(pkgDir, s, options);
604
+ });
605
+ }
606
+ }
607
+ case "remote": {
608
+ const { remoteURL } = f;
609
+ if (!remoteURL) {
610
+ throw this.#resolveError(
611
+ spec,
612
+ options,
613
+ "no remoteURL on remote specifier"
614
+ );
615
+ }
616
+ const s = spec;
617
+ return await this.#tmpdir(async (dir) => {
618
+ const response = await (await this.getRegistryClient()).request(remoteURL);
619
+ if (response.statusCode !== 200) {
620
+ throw this.#resolveError(
621
+ s,
622
+ options,
623
+ "failed to fetch URL",
624
+ { response, url: remoteURL }
625
+ );
626
+ }
627
+ const buf = response.buffer();
628
+ const computed = import_ssri.default.fromData(buf, { algorithms: ["sha512"] }).toString();
629
+ try {
630
+ await (await this.getTarPool()).unpack(buf, dir);
631
+ } catch (er) {
632
+ throw this.#resolveError(
633
+ s,
634
+ options,
635
+ "tar unpack failed",
636
+ { cause: er }
637
+ );
638
+ }
639
+ const mani = this.#readExtracted(dir, s, options);
640
+ mani.dist = { integrity: computed };
641
+ return mani;
642
+ });
643
+ }
644
+ case "file": {
645
+ const { file } = f;
646
+ if (file === void 0)
647
+ throw this.#resolveError(spec, options, "no file path");
648
+ const path = pathResolve(from, file);
649
+ const st = await stat(path);
650
+ if (st.isDirectory()) {
651
+ return this.packageJson.read(path);
652
+ }
653
+ const s = spec;
654
+ return await this.#tmpdir(async (dir) => {
655
+ try {
656
+ await (await this.getTarPool()).unpack(await readFile(path), dir);
657
+ } catch (er) {
658
+ throw this.#resolveError(
659
+ s,
660
+ options,
661
+ "tar unpack failed",
662
+ { cause: er }
663
+ );
664
+ }
665
+ return this.#readExtracted(dir, s, options);
666
+ });
667
+ }
668
+ case "workspace": {
669
+ return this.#getWS(spec, options).manifest;
670
+ }
671
+ }
672
+ }
673
+ async packument(spec, options = {}) {
674
+ if (typeof spec === "string")
675
+ spec = Spec.parse(spec, this.options);
676
+ const f = spec.final;
677
+ switch (f.type) {
678
+ // RevDoc is the equivalent of a packument for a git repo
679
+ case "git": {
680
+ const { gitRemote } = f;
681
+ if (!gitRemote) {
682
+ throw this.#resolveError(
683
+ spec,
684
+ options,
685
+ "git remote could not be determined"
686
+ );
687
+ }
688
+ const revDoc = await revs(gitRemote, {
689
+ cwd: this.options.projectRoot
690
+ });
691
+ if (!revDoc) throw this.#resolveError(spec, options);
692
+ return asPackument(revDoc);
693
+ }
694
+ // these are all faked packuments
695
+ case "file":
696
+ case "workspace":
697
+ case "remote": {
698
+ const manifest = await this.manifest(f, options);
699
+ return {
700
+ name: manifest.name ?? "",
701
+ "dist-tags": {
702
+ latest: manifest.version ?? ""
703
+ },
704
+ versions: {
705
+ [manifest.version ?? ""]: manifest
706
+ }
707
+ };
708
+ }
709
+ case "registry": {
710
+ const { registry, name } = f;
711
+ if (!registry) throw noRegistryError(spec);
712
+ const packumentKey = `${registry}${name}`;
713
+ const inflight = this.#packumentPromises.get(packumentKey);
714
+ if (inflight) return inflight;
715
+ const pakuURL = new URL(name, registry);
716
+ const promise = this.#fetchPackument(spec, options, pakuURL);
717
+ this.#packumentPromises.set(packumentKey, promise);
718
+ promise.then(
719
+ () => this.#packumentPromises.delete(packumentKey),
720
+ () => this.#packumentPromises.delete(packumentKey)
721
+ );
722
+ return promise;
723
+ }
724
+ }
725
+ }
726
+ async #fetchPackument(spec, options, pakuURL, useCache) {
727
+ const response = await (await this.getRegistryClient()).request(pakuURL, {
728
+ headers: { accept: "application/json" },
729
+ ...useCache === false ? { useCache } : {}
730
+ });
731
+ if (response.statusCode !== 200) {
732
+ throw this.#resolveError(
733
+ spec,
734
+ options,
735
+ "failed to fetch packument",
736
+ {
737
+ url: pakuURL,
738
+ response
739
+ }
740
+ );
741
+ }
742
+ try {
743
+ return response.json();
744
+ } catch (er) {
745
+ if (useCache !== false) {
746
+ return this.#fetchPackument(spec, options, pakuURL, false);
747
+ }
748
+ throw er;
749
+ }
750
+ }
751
+ async resolve(spec, options = {}) {
752
+ const memoKey = String(spec);
753
+ if (typeof spec === "string")
754
+ spec = Spec.parse(spec, this.options);
755
+ const memo = this.#resolutions.get(memoKey);
756
+ if (memo) return memo;
757
+ const f = spec.final;
758
+ switch (f.type) {
759
+ case "file": {
760
+ const { file } = f;
761
+ if (!file || !f.file) {
762
+ throw this.#resolveError(
763
+ spec,
764
+ options,
765
+ "no path on file: specifier"
766
+ );
767
+ }
768
+ const { from = this.#projectRoot } = options;
769
+ const resolved = pathResolve(from, f.file);
770
+ const r = { resolved, spec };
771
+ this.#resolutions.set(memoKey, r);
772
+ return r;
773
+ }
774
+ case "remote": {
775
+ const { remoteURL } = f;
776
+ if (!remoteURL)
777
+ throw this.#resolveError(
778
+ spec,
779
+ options,
780
+ "no URL in remote specifier"
781
+ );
782
+ const r = { resolved: remoteURL, spec };
783
+ this.#resolutions.set(memoKey, r);
784
+ return r;
785
+ }
786
+ case "workspace": {
787
+ const ws = this.#getWS(spec, options);
788
+ return {
789
+ resolved: ws.fullpath,
790
+ spec
791
+ };
792
+ }
793
+ case "registry": {
794
+ const mani = await this.manifest(spec, options);
795
+ if (mani.dist) {
796
+ const { integrity, tarball, signatures } = mani.dist;
797
+ if (tarball) {
798
+ const r = {
799
+ resolved: tarball,
800
+ integrity,
801
+ signatures,
802
+ spec
803
+ };
804
+ this.#resolutions.set(memoKey, r);
805
+ return r;
806
+ }
807
+ }
808
+ throw this.#resolveError(spec, options);
809
+ }
810
+ case "git": {
811
+ const { gitRemote, remoteURL, gitSelectorParsed } = f;
812
+ if (remoteURL && gitSelectorParsed?.path === void 0) {
813
+ const r = { resolved: remoteURL, spec };
814
+ this.#resolutions.set(memoKey, r);
815
+ return r;
816
+ }
817
+ if (!gitRemote) {
818
+ throw this.#resolveError(
819
+ spec,
820
+ options,
821
+ "no remote on git specifier"
822
+ );
823
+ }
824
+ const rev = await resolve(gitRemote, f.gitCommittish, {
825
+ spec
826
+ });
827
+ if (rev) {
828
+ const r = {
829
+ resolved: `${gitRemote}#${rev.sha}`,
830
+ spec
831
+ };
832
+ if (gitSelectorParsed) {
833
+ r.resolved += Object.entries(gitSelectorParsed).filter(([_, v]) => v).map(([k, v]) => `::${k}:${v}`).join("");
834
+ }
835
+ this.#resolutions.set(memoKey, r);
836
+ return r;
837
+ }
838
+ const s = spec;
839
+ return this.#tmpdir(async (tmpdir) => {
840
+ const sha = await clone(
841
+ gitRemote,
842
+ s.gitCommittish,
843
+ tmpdir,
844
+ {
845
+ spec: s
846
+ }
847
+ );
848
+ const r = {
849
+ resolved: `${gitRemote}#${sha}`,
850
+ spec: s
851
+ };
852
+ this.#resolutions.set(memoKey, r);
853
+ return r;
854
+ });
855
+ }
856
+ }
857
+ }
858
+ /**
859
+ * Read the manifest out of a directory we cloned or unpacked. Failures are
860
+ * labeled with the spec, because the internal directory says nothing about
861
+ * which dependency is at fault.
862
+ */
863
+ #readExtracted(dir, spec, options) {
864
+ try {
865
+ return this.packageJson.read(dir);
866
+ } catch (er) {
867
+ throw this.#resolveError(
868
+ spec,
869
+ options,
870
+ "invalid package manifest",
871
+ { cause: er }
872
+ );
873
+ }
874
+ }
875
+ async #tmpdir(fn) {
876
+ const p = `package-info/${randomBytes(6).toString("hex")}`;
877
+ const dir = xdg.runtime(p);
878
+ try {
879
+ return await fn(dir);
880
+ } finally {
881
+ void rm2(dir, { recursive: true, force: true });
882
+ }
883
+ }
884
+ // error resolving
885
+ #resolveError(spec, options = {}, message = "Could not resolve", extra = {}) {
886
+ const { from = this.#projectRoot } = options;
887
+ const er = error(
888
+ message,
889
+ {
890
+ code: "ERESOLVE",
891
+ spec,
892
+ from,
893
+ ...extra
894
+ },
895
+ this.#resolveError
896
+ );
897
+ return er;
898
+ }
899
+ };
900
+
901
+ export {
902
+ PackageInfoClient
903
+ };