@vltpkg/cli-js 1.1.1 → 1.3.0

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 (85) hide show
  1. package/{access-YYMAAPHV.js → access-HIVJOWXZ.js} +10 -10
  2. package/{bugs-RK5JBPSC.js → bugs-2KFUYMPS.js} +19 -19
  3. package/{build-DVJSYCNF.js → build-CX6YZ4LS.js} +12 -12
  4. package/{cache-JKQNGZ7L.js → cache-I6L5ZRGD.js} +145 -16
  5. package/cache-unzip-src-unzip.js +2953 -164
  6. package/{src-MOKZQTH2.js → chunk-263MHLR3.js} +299 -43
  7. package/{chunk-3LUM7NX5.js → chunk-2HXJ4ZSF.js} +3 -3
  8. package/{chunk-GDJ7JT2R.js → chunk-33HBY5CF.js} +1 -1
  9. package/{chunk-MZA6N2TA.js → chunk-C6LK7C3L.js} +4 -4
  10. package/{chunk-34TE4HZS.js → chunk-CU752KW7.js} +2 -2
  11. package/{chunk-2PWSMJD7.js → chunk-D2LEK7VS.js} +1 -1
  12. package/{chunk-CEHPRPGQ.js → chunk-ENSGPOLR.js} +46 -0
  13. package/{chunk-V4YCZZHY.js → chunk-EP7AVBIO.js} +16 -8
  14. package/{chunk-DS7YMIHP.js → chunk-FHMIECHI.js} +158 -59
  15. package/chunk-GDV5LSQ2.js +75 -0
  16. package/{chunk-BWEH7DHQ.js → chunk-HCZOVC3Y.js} +1 -1
  17. package/{chunk-CBASIDQH.js → chunk-I6QGYSB4.js} +1 -1
  18. package/{chunk-KDF7PEBY.js → chunk-ILRJWH6A.js} +5 -5
  19. package/{chunk-JZJWASXL.js → chunk-J2WL3A3C.js} +134 -68
  20. package/{chunk-YOE3VZFX.js → chunk-J3R4XWB3.js} +2 -2
  21. package/{chunk-DF5K4CYR.js → chunk-JFHEXCG5.js} +5 -5
  22. package/{chunk-LR42WTKN.js → chunk-MJWUULO6.js} +14 -12
  23. package/{chunk-QQYTPGIL.js → chunk-N4RCKCHY.js} +1 -1
  24. package/{chunk-X2AWQGYG.js → chunk-P4LLYWCG.js} +112 -23
  25. package/{chunk-BHJT53TP.js → chunk-PDWPFR5T.js} +1 -1
  26. package/{chunk-XIF734VO.js → chunk-QETVMIIT.js} +4 -4
  27. package/{chunk-WE2TQN32.js → chunk-QWJDHBV7.js} +4 -3
  28. package/{chunk-VFBCWAOC.js → chunk-RH2Y7MPW.js} +29 -0
  29. package/{chunk-LN2A74PF.js → chunk-SVMH3NDM.js} +277 -50
  30. package/{chunk-DR4Z63B6.js → chunk-TYLYZKVA.js} +14 -11
  31. package/{chunk-XKVU23NC.js → chunk-V7EQZOO5.js} +1 -1
  32. package/{chunk-YBVTY6ZW.js → chunk-VBADA6QU.js} +1 -1
  33. package/{chunk-GDT6KI4I.js → chunk-W6UMN2YJ.js} +4 -4
  34. package/{chunk-VE6CCH33.js → chunk-Y5PA7DVK.js} +1 -0
  35. package/{chunk-6FT6K5YN.js → chunk-YZWFWSY7.js} +25 -7
  36. package/{chunk-SNOBGFNM.js → chunk-ZNUXDX6R.js} +50 -8
  37. package/{ci-WVYVR4XK.js → ci-BX54SEU3.js} +12 -12
  38. package/cli-package.json +3 -2
  39. package/{config-VYOTYBGS.js → config-HFF6XDCV.js} +9 -9
  40. package/{config-2MFZVP2N.js → config-WBVJX42R.js} +12 -12
  41. package/{create-OJPLHBRR.js → create-W67HRHWZ.js} +20 -20
  42. package/{deprecate-V4PKGFF7.js → deprecate-5T6JTGJ3.js} +14 -14
  43. package/{devtools-UEMPW5GG.js → devtools-UMJUK42W.js} +2 -2
  44. package/{dist-tag-DNLV4VDE.js → dist-tag-YIZTS7GF.js} +10 -10
  45. package/{docs-LXHDCGL5.js → docs-G7CKMPCL.js} +19 -19
  46. package/{exec-P32YSP44.js → exec-YYCAZZ6Z.js} +20 -20
  47. package/{exec-cache-JZ5PDTOY.js → exec-cache-6ENHAGC6.js} +18 -18
  48. package/{exec-local-HHA464H4.js → exec-local-OXG3PSLF.js} +17 -17
  49. package/{help-GVTTOYUL.js → help-RMOIAILM.js} +4 -4
  50. package/{init-RENGG74N.js → init-UPEQXC4D.js} +12 -12
  51. package/{install-V6VXOBH2.js → install-U7LLEQU6.js} +18 -18
  52. package/{list-7N7Y5OXB.js → list-N6CKPXTK.js} +20 -20
  53. package/{login-D2QSAUJC.js → login-MCO4ZLVF.js} +14 -14
  54. package/{logout-QPOYBQNF.js → logout-BJ4QRZYG.js} +10 -10
  55. package/{pack-4YYGXP3A.js → pack-U6PYRFZ6.js} +13 -13
  56. package/package.json +1 -1
  57. package/{ping-QYRIZONU.js → ping-VFB6SCMH.js} +10 -10
  58. package/{pkg-WQTNABKT.js → pkg-ZNK5SCF4.js} +13 -13
  59. package/{profile-PRI7WXK7.js → profile-TW32HLYA.js} +10 -10
  60. package/{publish-PSBYJQS7.js → publish-AHOITWZQ.js} +36 -21
  61. package/{query-UFYLQW4N.js → query-KKP5PNSQ.js} +20 -20
  62. package/{registry-YTJZ3AQD.js → registry-VHB65BWD.js} +5 -5
  63. package/registry-client-src-revalidate.js +5936 -5801
  64. package/{repo-4S6ETFXX.js → repo-BHTVK5KE.js} +19 -19
  65. package/{reporter-GLWYHI2Y.js → reporter-VQU7HYKM.js} +77 -77
  66. package/{run-OU7NUB7A.js → run-UD32OTUJ.js} +17 -17
  67. package/{run-exec-QPBY7ULE.js → run-exec-NOCIUNGL.js} +17 -17
  68. package/security-archive-src-update-expired.js +1 -1
  69. package/{setup-23QXG473.js → setup-PBCWOSTV.js} +18 -18
  70. package/{src-575IYJOL.js → src-LRKPUV4J.js} +16 -16
  71. package/src-T5FBZFMV.js +222 -0
  72. package/{src-3GN7TDNH.js → src-Z44JKVWS.js} +9 -7
  73. package/{token-FCIA3RGD.js → token-PCPB6NOL.js} +10 -10
  74. package/{uninstall-BQVZVKB5.js → uninstall-LOGSQXFS.js} +14 -14
  75. package/{unpublish-YGJ5HEYF.js → unpublish-O3UFCTEJ.js} +10 -10
  76. package/{update-WCGV66JK.js → update-WBCLWGLN.js} +17 -17
  77. package/{version-7EA3UQG7.js → version-S3LCB2TQ.js} +13 -13
  78. package/{view-5FWIENVE.js → view-LMPENVAJ.js} +12 -12
  79. package/vlr.js +1 -1
  80. package/vlrx.js +1 -1
  81. package/vlt.js +1 -1
  82. package/vlx.js +1 -1
  83. package/vlxl.js +1 -1
  84. package/{whoami-O4ZTBIC4.js → whoami-LYMG7R3P.js} +10 -10
  85. package/chunk-WD74RJXW.js +0 -75
@@ -20,22 +20,27 @@ import {
20
20
  pickManifest,
21
21
  resolve,
22
22
  revs
23
- } from "./chunk-X2AWQGYG.js";
23
+ } from "./chunk-P4LLYWCG.js";
24
24
  import {
25
25
  Spec
26
- } from "./chunk-XKVU23NC.js";
26
+ } from "./chunk-V7EQZOO5.js";
27
27
  import {
28
- registryErrorMessage
29
- } from "./chunk-SNOBGFNM.js";
28
+ registryErrorMessage,
29
+ storeRoot,
30
+ tokenRefusalAdvice
31
+ } from "./chunk-ZNUXDX6R.js";
30
32
  import {
31
33
  logRequest
32
34
  } from "./chunk-U7TEQCBN.js";
33
- import {
34
- asPackument
35
- } from "./chunk-VFBCWAOC.js";
36
35
  import {
37
36
  XDG
38
37
  } from "./chunk-XNLSTHDK.js";
38
+ import {
39
+ asPackument,
40
+ brotliTarballUrl,
41
+ integrityHex,
42
+ tarballFormat
43
+ } from "./chunk-RH2Y7MPW.js";
39
44
  import {
40
45
  error
41
46
  } from "./chunk-WZWDS3W4.js";
@@ -63,6 +68,59 @@ import {
63
68
  } from "node:path";
64
69
  import { debuglog } from "node:util";
65
70
 
71
+ // ../../src/package-info/src/capabilities.ts
72
+ var none = Object.freeze({});
73
+ var asked = /* @__PURE__ */ new Map();
74
+ var known = /* @__PURE__ */ new Map();
75
+ var peekCapabilities = (client, registry) => {
76
+ const url = capabilitiesUrl(registry);
77
+ const seen = known.get(url);
78
+ if (seen) return seen;
79
+ void getCapabilities(client, registry);
80
+ return void 0;
81
+ };
82
+ var getCapabilities = async (client, registry) => {
83
+ const url = capabilitiesUrl(registry);
84
+ const seen = asked.get(url);
85
+ if (seen) return seen;
86
+ const doc = fetchCapabilities(client, url).then((caps) => {
87
+ known.set(url, caps);
88
+ return caps;
89
+ });
90
+ asked.set(url, doc);
91
+ return doc;
92
+ };
93
+ var capabilitiesUrl = (registry) => String(new URL("-/vlt/capabilities", registry));
94
+ var fetchCapabilities = async (client, url) => {
95
+ try {
96
+ const response = await client.request(url, {
97
+ headers: { accept: "application/json" }
98
+ });
99
+ if (response.statusCode !== 200) return none;
100
+ return asCapabilities(response.json());
101
+ } catch {
102
+ return none;
103
+ }
104
+ };
105
+ var asCapabilities = (body) => {
106
+ if (typeof body !== "object" || body === null) return none;
107
+ const doc = body;
108
+ const caps = {};
109
+ for (const key of [
110
+ "manifests",
111
+ "resolve",
112
+ "stable-filter"
113
+ ]) {
114
+ const version = doc[key];
115
+ if (typeof version === "string") caps[key] = version;
116
+ }
117
+ const { mimeTypes } = doc;
118
+ if (Array.isArray(mimeTypes) && mimeTypes.every((type) => typeof type === "string")) {
119
+ caps.mimeTypes = mimeTypes;
120
+ }
121
+ return caps;
122
+ };
123
+
66
124
  // ../../src/package-info/src/rename.ts
67
125
  import { rename as fsRename, rm } from "node:fs/promises";
68
126
  var { platform } = process;
@@ -86,13 +144,20 @@ var rename = platform !== "win32" ? fsRename : (async function(oldPath, newPath)
86
144
  var debug = debuglog("vlt");
87
145
  var xdg = new XDG("vlt");
88
146
  var delimiter = "~";
89
- var PACKUMENT_ACCEPT = "application/vnd.vlt.packument-v1+json; q=1.0, application/json; q=0.8, */*; q=0.1";
147
+ var VLT_PACKUMENT_MIME = "application/vnd.vlt.packument-v1+json";
148
+ var PACKUMENT_ACCEPT = `${VLT_PACKUMENT_MIME}; q=1.0, application/json; q=0.8, */*; q=0.1`;
90
149
  var manifestCacheMaxAge = 5 * 60 * 1e3;
91
150
  var noRegistryError = (spec) => error(
92
151
  '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',
93
152
  { code: "ECONFIG", spec }
94
153
  );
95
154
  var isMovingSelector = (f) => !!(f.distTag || f.range?.isAny);
155
+ var isStableSelector = (f) => {
156
+ const { range } = f;
157
+ if (!range) return false;
158
+ return !range.isAny && !range.raw.includes("-");
159
+ };
160
+ var storeLinkers = /* @__PURE__ */ new Set(["auto", "hardlink", "copy"]);
96
161
  var PackageInfoClient = class {
97
162
  #registryClient;
98
163
  #projectRoot;
@@ -102,8 +167,26 @@ var PackageInfoClient = class {
102
167
  packageJson;
103
168
  monorepo;
104
169
  #trustedIntegrities = /* @__PURE__ */ new Map();
170
+ // `${registry}${name}` of every packument served as VLT_PACKUMENT_MIME
171
+ #vltPackuments = /* @__PURE__ */ new Set();
105
172
  #manifestCacheMinAge = Date.now() - manifestCacheMaxAge;
106
173
  #cachePath;
174
+ #storeRoot;
175
+ #storeLinker;
176
+ #storeHits = { link: 0, copy: 0 };
177
+ #storeMisses = 0;
178
+ #storeHitRateLogged = false;
179
+ #logStoreHitRate = () => {
180
+ const { link, copy } = this.#storeHits;
181
+ const n = Math.max(1, link + copy + this.#storeMisses);
182
+ debug(
183
+ "global store: linked=%d copied=%d missed=%d hit rate=%s%%",
184
+ link,
185
+ copy,
186
+ this.#storeMisses,
187
+ ((link + copy) / n * 100).toFixed(1)
188
+ );
189
+ };
107
190
  // In-flight coalescing key is `${registry}${name}` — no representation
108
191
  // component. Safe only because every caller requests the same full
109
192
  // packument (see #fetchPackument). The one thing that does vary per
@@ -123,15 +206,47 @@ var PackageInfoClient = class {
123
206
  #tarPoolPromise;
124
207
  async getRegistryClient() {
125
208
  if (this.#registryClient) return this.#registryClient;
126
- this.#registryClientPromise ??= import("./src-3GN7TDNH.js").then(({ RegistryClient }) => {
209
+ this.#registryClientPromise ??= import("./src-Z44JKVWS.js").then(({ RegistryClient }) => {
127
210
  this.#registryClient = new RegistryClient(this.options);
128
211
  return this.#registryClient;
129
212
  });
130
213
  return this.#registryClientPromise;
131
214
  }
215
+ /**
216
+ * The vlt extensions `registry` serves, from its
217
+ * `GET /-/vlt/capabilities` document. A registry that does not answer
218
+ * one reads as an empty document, so a missing key means unsupported.
219
+ */
220
+ async capabilities(registry) {
221
+ return getCapabilities(await this.getRegistryClient(), registry);
222
+ }
223
+ /**
224
+ * Whether the packument for `f` can be fetched with `?stable`: the
225
+ * selector has to be one a prerelease cannot answer, and the registry
226
+ * must not have told us it does not serve the filter.
227
+ *
228
+ * Never waits on the capability document, which would put a round trip in
229
+ * front of the first packument of every cold install. Until that document
230
+ * arrives the answer is yes: a registry that does not know `?stable`
231
+ * ignores the parameter and serves the full packument, which resolution
232
+ * reads just as well. Once the document does arrive it is authoritative,
233
+ * so a registry that does not serve the filter stops being asked with it.
234
+ */
235
+ #stable(f) {
236
+ const { registry } = f;
237
+ if (!registry || !isStableSelector(f)) return false;
238
+ const client = this.#registryClient;
239
+ if (!client) {
240
+ void this.capabilities(registry).catch(() => {
241
+ });
242
+ return true;
243
+ }
244
+ const caps = peekCapabilities(client, registry);
245
+ return !caps || !!caps["stable-filter"];
246
+ }
132
247
  async getTarPool() {
133
248
  if (this.#tarPool) return this.#tarPool;
134
- this.#tarPoolPromise ??= import("./src-MOKZQTH2.js").then(
249
+ this.#tarPoolPromise ??= import("./src-T5FBZFMV.js").then(
135
250
  ({ Pool }) => {
136
251
  this.#tarPool = new Pool();
137
252
  return this.#tarPool;
@@ -139,6 +254,17 @@ var PackageInfoClient = class {
139
254
  );
140
255
  return this.#tarPoolPromise;
141
256
  }
257
+ /**
258
+ * The absolute URL of a version's Brotli (`.tar.br`) tarball, or
259
+ * undefined when the registry advertised none, advertised one this
260
+ * client does not use (see {@link brotliTarballUrl}), or
261
+ * `--no-brotli-tarballs` is set. `dist.tarball` is already absolute
262
+ * here -- see `absolutizeTarballs`.
263
+ */
264
+ #brotliTarball(tarball, alternates) {
265
+ if (this.options["brotli-tarballs"] === false) return void 0;
266
+ return brotliTarballUrl(tarball, alternates);
267
+ }
142
268
  constructor(options = {}) {
143
269
  this.options = options;
144
270
  this.#projectRoot = options.projectRoot || process.cwd();
@@ -154,6 +280,9 @@ var PackageInfoClient = class {
154
280
  packageJson: this.packageJson
155
281
  });
156
282
  this.#cachePath = options.cache ?? xdg.cache();
283
+ this.#storeRoot = options.storeRoot ?? storeRoot(this.#cachePath);
284
+ const linker = options["store-linker"];
285
+ this.#storeLinker = linker && storeLinkers.has(linker) ? linker : "unpack";
157
286
  void mkdir(pathResolve(this.#cachePath, "package-info"), {
158
287
  recursive: true
159
288
  }).catch(() => {
@@ -166,11 +295,17 @@ var PackageInfoClient = class {
166
295
  from = this.#projectRoot,
167
296
  integrity,
168
297
  resolved,
169
- fromLockfile = false
298
+ fromLockfile = false,
299
+ installScripts = false
170
300
  } = options;
171
301
  const f = spec.final;
172
- const alreadyResolved = !!(integrity && resolved);
173
- const r = alreadyResolved ? { resolved, integrity, spec } : await this.resolve(spec, options);
302
+ const brotli = !!resolved && tarballFormat(resolved) === "brotli";
303
+ const r = resolved && (integrity || brotli) ? {
304
+ resolved,
305
+ integrity,
306
+ spec,
307
+ ...brotli && !integrity ? { digestRequired: true } : {}
308
+ } : await this.resolve(spec, options);
174
309
  switch (f.type) {
175
310
  case "git": {
176
311
  const {
@@ -204,14 +339,45 @@ var PackageInfoClient = class {
204
339
  }
205
340
  }
206
341
  case "registry": {
207
- const cached = (await this.getRegistryClient()).cachedBody(
208
- r.resolved,
209
- { integrity: r.integrity }
210
- );
342
+ const pool = await this.getTarPool();
343
+ const format = tarballFormat(r.resolved);
344
+ const hex = f.type === "registry" && this.#storeLinker !== "unpack" ? integrityHex(r.integrity) : void 0;
345
+ const copy = this.#storeLinker === "copy" || installScripts;
346
+ if (hex) {
347
+ if (debug.enabled && !this.#storeHitRateLogged) {
348
+ this.#storeHitRateLogged = true;
349
+ process.once("beforeExit", this.#logStoreHitRate);
350
+ }
351
+ const linked = await pool.linkFromStore(
352
+ pathResolve(this.#storeRoot, hex),
353
+ target,
354
+ { copy }
355
+ );
356
+ if (linked) {
357
+ const { how, index } = linked;
358
+ this.#storeHits[how]++;
359
+ logRequest(r.resolved, how === "link" ? "store" : "cache");
360
+ return {
361
+ ...r,
362
+ manifest: index.manifest,
363
+ // implies scripts, so most packages skip the scan
364
+ bindingGyp: index.scripts && index.files.some((f2) => f2[0] === "binding.gyp")
365
+ };
366
+ }
367
+ this.#storeMisses++;
368
+ }
369
+ const rc = await this.getRegistryClient();
370
+ const cached = rc.cachedBody(r.resolved, {
371
+ integrity: r.integrity
372
+ });
211
373
  if (cached) {
212
374
  try {
213
- await (await this.getTarPool()).unpack(cached.body, target);
375
+ await pool.unpack(cached.body, target, format);
214
376
  logRequest(r.resolved, "cache");
377
+ r.integrity ??= cached.integrity;
378
+ if (hex || cached.gzip) {
379
+ rc.queueForStore(cached.key, r.integrity);
380
+ }
215
381
  return r;
216
382
  } catch (er) {
217
383
  debug(
@@ -226,6 +392,7 @@ var PackageInfoClient = class {
226
392
  const response = await (await this.getRegistryClient()).request(r.resolved, {
227
393
  integrity: r.integrity,
228
394
  trustIntegrity,
395
+ verifyDigest: r.digestRequired ? "required" : true,
229
396
  ...useCache === false ? { useCache } : {}
230
397
  });
231
398
  if (response.statusCode !== 200) {
@@ -239,26 +406,33 @@ var PackageInfoClient = class {
239
406
  }
240
407
  );
241
408
  }
242
- if (!trustIntegrity && response.checkIntegrity({ spec, url: resolved })) {
409
+ const verified = !trustIntegrity && response.checkIntegrity({ spec, url: resolved });
410
+ if (verified) {
243
411
  this.#trustedIntegrities.set(
244
412
  r.resolved,
245
413
  response.integrity
246
414
  );
247
415
  }
248
416
  const buf2 = response.buffer();
249
- if (r.integrity && !fromLockfile && !response.fromCache) {
250
- const hash = createHash("sha512");
251
- hash.update(buf2);
252
- const computed = `sha512-${hash.digest("base64")}`;
253
- if (computed !== r.integrity) {
254
- throw error("Tarball integrity check failed", {
255
- code: "EINTEGRITY",
256
- spec,
257
- url: r.resolved,
258
- wanted: r.integrity,
259
- found: computed
260
- });
417
+ if (r.integrity) {
418
+ if (!verified && !fromLockfile && !response.fromCache) {
419
+ const hash = createHash("sha512");
420
+ hash.update(buf2);
421
+ const computed = `sha512-${hash.digest("base64")}`;
422
+ if (computed !== r.integrity) {
423
+ throw error("Tarball integrity check failed", {
424
+ code: "EINTEGRITY",
425
+ spec,
426
+ url: r.resolved,
427
+ wanted: r.integrity,
428
+ found: computed
429
+ });
430
+ }
261
431
  }
432
+ } else if (response.fromCache) {
433
+ r.integrity = response.integrity;
434
+ } else {
435
+ r.integrity = response.integrityActual;
262
436
  }
263
437
  return buf2;
264
438
  };
@@ -273,7 +447,7 @@ var PackageInfoClient = class {
273
447
  }
274
448
  }
275
449
  try {
276
- await (await this.getTarPool()).unpack(buf, target);
450
+ await pool.unpack(buf, target, format);
277
451
  } catch (er) {
278
452
  throw this.#resolveError(
279
453
  spec,
@@ -460,6 +634,9 @@ var PackageInfoClient = class {
460
634
  ...options,
461
635
  integrity,
462
636
  trustIntegrity,
637
+ // no dist.integrity: checked against the digest the registry
638
+ // sent with it instead, before the client caches it
639
+ verifyDigest: this.#vltPackuments.has(`${f.registry}${f.name}`) ? "required" : true,
463
640
  ...useCache === false ? { useCache } : {}
464
641
  });
465
642
  if (response.statusCode !== 200) {
@@ -470,11 +647,12 @@ var PackageInfoClient = class {
470
647
  { response, url: tarball }
471
648
  );
472
649
  }
473
- if (!trustIntegrity && response.checkIntegrity({ spec, url: tarball })) {
650
+ const verified = !trustIntegrity && response.checkIntegrity({ spec, url: tarball });
651
+ if (verified) {
474
652
  this.#trustedIntegrities.set(tarball, response.integrity);
475
653
  }
476
654
  const buf = response.buffer();
477
- if (integrity && !response.fromCache) {
655
+ if (integrity && !verified && !response.fromCache) {
478
656
  const hash = createHash("sha512");
479
657
  hash.update(buf);
480
658
  const computed = `sha512-${hash.digest("base64")}`;
@@ -595,21 +773,30 @@ var PackageInfoClient = class {
595
773
  });
596
774
  throw new Error("manifest cache expired");
597
775
  }
776
+ if (json.__VLT_PACKUMENT) {
777
+ this.#vltPackuments.add(`${f.registry}${f.name}`);
778
+ delete json.__VLT_PACKUMENT;
779
+ }
598
780
  return json;
599
781
  } catch {
600
782
  }
601
783
  }
602
784
  const mani = pickManifest(
603
- await this.packument(f, options),
785
+ await this.#packument(f, options, this.#stable(f)),
604
786
  spec,
605
787
  options
606
788
  );
607
789
  if (!mani) throw this.#resolveError(spec, options);
608
790
  if (cachePath && !this.#manifestWritePaths.has(cachePath)) {
609
791
  this.#manifestWritePaths.add(cachePath);
792
+ const vlt = this.#vltPackuments.has(
793
+ `${f.registry}${f.name}`
794
+ );
610
795
  void this.#writeManifestCache(
611
796
  cachePath,
612
- JSON.stringify(mani)
797
+ JSON.stringify(
798
+ vlt ? { ...mani, __VLT_PACKUMENT: true } : mani
799
+ )
613
800
  );
614
801
  }
615
802
  return mani;
@@ -699,7 +886,15 @@ var PackageInfoClient = class {
699
886
  }
700
887
  }
701
888
  }
889
+ /**
890
+ * The packument for `spec`, with every version the registry has. Callers
891
+ * that only pick a manifest out of it go through `#packument` instead,
892
+ * which can ask for the prerelease-free one.
893
+ */
702
894
  async packument(spec, options = {}) {
895
+ return this.#packument(spec, options, false);
896
+ }
897
+ async #packument(spec, options, stable) {
703
898
  if (typeof spec === "string")
704
899
  spec = Spec.parse(spec, this.options);
705
900
  const f = spec.final;
@@ -738,12 +933,25 @@ var PackageInfoClient = class {
738
933
  case "registry": {
739
934
  const { registry, name } = f;
740
935
  if (!registry) throw noRegistryError(spec);
741
- const packumentKey = `${registry}${name}`;
936
+ if (options.full)
937
+ return this.#fetchPackument(
938
+ spec,
939
+ options,
940
+ new URL(name, registry)
941
+ );
942
+ const fullKey = `${registry}${name}`;
943
+ const packumentKey = stable ? `${fullKey}?stable` : fullKey;
742
944
  const forced = isMovingSelector(f);
743
- const inflight = this.#packumentPromises.get(packumentKey);
945
+ const inflight = this.#packumentPromises.get(packumentKey) ?? // the full packument is a superset of the stable one, so an
946
+ // in-flight full request answers a stable ask too, and a package
947
+ // wanted both ways is still fetched once
948
+ (stable ? this.#packumentPromises.get(fullKey) : void 0);
744
949
  if (inflight && (!forced || inflight.forced))
745
950
  return inflight.promise;
746
- const pakuURL = new URL(name, registry);
951
+ const pakuURL = new URL(
952
+ stable ? `${name}?stable` : name,
953
+ registry
954
+ );
747
955
  const promise = this.#fetchPackument(spec, options, pakuURL);
748
956
  const record = { promise, forced };
749
957
  this.#packumentPromises.set(packumentKey, record);
@@ -759,8 +967,10 @@ var PackageInfoClient = class {
759
967
  }
760
968
  async #fetchPackument(spec, options, pakuURL, useCache) {
761
969
  const response = await (await this.getRegistryClient()).request(pakuURL, {
762
- headers: { accept: PACKUMENT_ACCEPT },
763
- ...useCache === false ? { useCache } : {},
970
+ headers: {
971
+ accept: options.full ? "application/json" : PACKUMENT_ACCEPT
972
+ },
973
+ ...useCache === false || options.full ? { useCache: false } : {},
764
974
  // costs a conditional GET per moving selector on an otherwise warm
765
975
  // cache, install included. 304s are cheap but not free; the
766
976
  // alternative is serving a dist tag that moved (#1656).
@@ -777,14 +987,21 @@ var PackageInfoClient = class {
777
987
  }
778
988
  );
779
989
  }
990
+ let paku;
780
991
  try {
781
- return response.json();
992
+ paku = response.json();
782
993
  } catch (er) {
783
994
  if (useCache !== false) {
784
995
  return this.#fetchPackument(spec, options, pakuURL, false);
785
996
  }
786
997
  throw er;
787
998
  }
999
+ const { registry, name } = spec.final;
1000
+ if (response.contentType.startsWith(VLT_PACKUMENT_MIME)) {
1001
+ this.#vltPackuments.add(`${registry}${name}`);
1002
+ }
1003
+ if (registry) absolutizeTarballs(paku, registry);
1004
+ return paku;
788
1005
  }
789
1006
  async resolve(spec, options = {}) {
790
1007
  const memoKey = String(spec);
@@ -831,14 +1048,13 @@ var PackageInfoClient = class {
831
1048
  case "registry": {
832
1049
  const mani = await this.manifest(spec, options);
833
1050
  if (mani.dist) {
834
- const { integrity, tarball, signatures } = mani.dist;
1051
+ const { integrity, tarball, signatures, alternates } = mani.dist;
835
1052
  if (tarball) {
836
- const r = {
837
- resolved: tarball,
838
- integrity,
839
- signatures,
840
- spec
841
- };
1053
+ const brotli = this.#brotliTarball(tarball, alternates);
1054
+ const r = brotli ? { resolved: brotli, spec, digestRequired: true } : { resolved: tarball, integrity, signatures, spec };
1055
+ if (!brotli && !integrity && this.#vltPackuments.has(`${f.registry}${f.name}`)) {
1056
+ r.digestRequired = true;
1057
+ }
842
1058
  this.#resolutions.set(memoKey, r);
843
1059
  return r;
844
1060
  }
@@ -922,8 +1138,10 @@ var PackageInfoClient = class {
922
1138
  // error resolving
923
1139
  #resolveError(spec, options = {}, message = "Could not resolve", extra = {}) {
924
1140
  const { from = this.#projectRoot } = options;
1141
+ const advice = spec?.final.type === "registry" ? tokenRefusalAdvice(extra.response, extra.url) : void 0;
925
1142
  const er = error(
926
- message,
1143
+ advice ? `${message}
1144
+ \u26A0\uFE0F ${advice}` : message,
927
1145
  {
928
1146
  code: "ERESOLVE",
929
1147
  spec,
@@ -935,6 +1153,15 @@ var PackageInfoClient = class {
935
1153
  return er;
936
1154
  }
937
1155
  };
1156
+ var absolutizeTarballs = (paku, registry) => {
1157
+ const base = registry.endsWith("/") ? registry : registry + "/";
1158
+ for (const { dist } of Object.values(paku.versions)) {
1159
+ const tarball = dist?.tarball;
1160
+ if (tarball && !/^[a-z][a-z0-9+.-]*:/i.test(tarball)) {
1161
+ dist.tarball = String(new URL(tarball, base));
1162
+ }
1163
+ }
1164
+ };
938
1165
 
939
1166
  export {
940
1167
  PackageInfoClient
@@ -12,15 +12,16 @@ var require = _vlt_createRequire(import.meta.filename);
12
12
  import {
13
13
  init,
14
14
  install
15
- } from "./chunk-JZJWASXL.js";
15
+ } from "./chunk-J2WL3A3C.js";
16
16
  import {
17
17
  commandUsage
18
- } from "./chunk-CBASIDQH.js";
18
+ } from "./chunk-I6QGYSB4.js";
19
19
  import {
20
- asWSConfig,
21
20
  assertWSConfig,
22
- minimatch
23
- } from "./chunk-X2AWQGYG.js";
21
+ minimatch,
22
+ resolveWSConfig,
23
+ splitNegatedPatterns
24
+ } from "./chunk-P4LLYWCG.js";
24
25
  import {
25
26
  load,
26
27
  save
@@ -74,8 +75,11 @@ Modify/add properties using \`vlt pkg\`. For example:
74
75
  var command = async (conf) => {
75
76
  const allowScripts = conf.get("allow-scripts") ? String(conf.get("allow-scripts")) : ":not(*)";
76
77
  if (conf.values.workspace?.length) {
77
- const workspacesConfig = load("workspaces", assertWSConfig);
78
- const parsedWSConfig = asWSConfig(workspacesConfig ?? {});
78
+ const { config: parsedWSConfig, source } = resolveWSConfig(
79
+ conf.options.projectRoot,
80
+ conf.options.packageJson
81
+ );
82
+ const workspacesConfig = load("workspaces", assertWSConfig) ?? (source === "package.json" ? Object.values(parsedWSConfig).flat() : void 0);
79
83
  const results = [];
80
84
  const addToConfig = [];
81
85
  for (const workspace of conf.values.workspace) {
@@ -83,10 +87,9 @@ var command = async (conf) => {
83
87
  mkdirSync(cwd, { recursive: true });
84
88
  results.push(await init({ cwd }));
85
89
  const isMatched = Object.values(parsedWSConfig).some(
86
- (patterns) => {
87
- return patterns.some(
88
- (pattern) => minimatch(workspace, pattern)
89
- );
90
+ (group) => {
91
+ const { patterns, ignore } = splitNegatedPatterns(group);
92
+ return patterns.some((pattern) => minimatch(workspace, pattern)) && !ignore.some((pattern) => minimatch(workspace, pattern));
90
93
  }
91
94
  );
92
95
  if (!isMatched) {
@@ -12,7 +12,7 @@ var require = _vlt_createRequire(import.meta.filename);
12
12
  import {
13
13
  Spec,
14
14
  kCustomInspect
15
- } from "./chunk-VFBCWAOC.js";
15
+ } from "./chunk-RH2Y7MPW.js";
16
16
 
17
17
  // ../../src/spec/src/index.ts
18
18
  import { homedir } from "node:os";
@@ -14,7 +14,7 @@ var require = _vlt_createRequire(import.meta.filename);
14
14
  var package_default = {
15
15
  name: "@vltpkg/user-agent",
16
16
  description: "The User-Agent string that vlt sends with every outbound request",
17
- version: "1.1.1",
17
+ version: "1.3.0",
18
18
  repository: {
19
19
  type: "git",
20
20
  url: "git+https://github.com/vltpkg/vltpkg.git",
@@ -11,19 +11,19 @@ import {createRequire as _vlt_createRequire} from "node:module";
11
11
  var require = _vlt_createRequire(import.meta.filename);
12
12
  import {
13
13
  openUrl
14
- } from "./chunk-BWEH7DHQ.js";
14
+ } from "./chunk-HCZOVC3Y.js";
15
15
  import {
16
16
  stderr
17
- } from "./chunk-LR42WTKN.js";
17
+ } from "./chunk-MJWUULO6.js";
18
18
  import {
19
19
  mermaidOutput
20
- } from "./chunk-JZJWASXL.js";
20
+ } from "./chunk-J2WL3A3C.js";
21
21
  import {
22
22
  ViewClass
23
23
  } from "./chunk-4KCU2KZL.js";
24
24
  import {
25
25
  getTokenByURL
26
- } from "./chunk-DS7YMIHP.js";
26
+ } from "./chunk-FHMIECHI.js";
27
27
 
28
28
  // ../../src/cli-sdk/src/query-auth.ts
29
29
  var createGetAuthHeader = (conf) => async (url) => getTokenByURL(url, conf.options.identity);
@@ -2995,6 +2995,7 @@ var Ze = Object.assign(Je, { glob: Je, globSync: ts, sync: Ui, globStream: Qe, s
2995
2995
  Ze.glob = Ze;
2996
2996
 
2997
2997
  export {
2998
+ ot,
2998
2999
  ts,
2999
3000
  Ze
3000
3001
  };