@vltpkg/registry-client 0.0.0-4 → 0.0.0-6

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.
@@ -1,10 +1,26 @@
1
+ import type { ErrorCauseObject } from '@vltpkg/error-cause';
1
2
  import type { Integrity, JSONField } from '@vltpkg/types';
2
3
  import type { InspectOptions } from 'util';
3
4
  export type JSONObj = Record<string, JSONField>;
4
5
  declare const kCustomInspect: unique symbol;
6
+ export type CacheEntryOptions = {
7
+ /**
8
+ * The expected integrity value for this response body
9
+ */
10
+ integrity?: Integrity;
11
+ /**
12
+ * Whether to trust the integrity, or calculate the actual value.
13
+ *
14
+ * This indicates that we just accept whatever the integrity is as the actual
15
+ * integrity for saving back to the cache, because it's coming directly from
16
+ * the registry that we fetched a packument from, and is an initial gzipped
17
+ * artifact request.
18
+ */
19
+ trustIntegrity?: boolean;
20
+ };
5
21
  export declare class CacheEntry {
6
22
  #private;
7
- constructor(statusCode: number, headers: Buffer[], integrity?: Integrity);
23
+ constructor(statusCode: number, headers: Buffer[], { integrity, trustIntegrity }?: CacheEntryOptions);
8
24
  [kCustomInspect](depth: number, options: InspectOptions): string;
9
25
  /**
10
26
  * `true` if the entry represents a cached response that is still
@@ -15,17 +31,25 @@ export declare class CacheEntry {
15
31
  get statusCode(): number;
16
32
  get headers(): Buffer<ArrayBufferLike>[];
17
33
  /**
18
- * check that the sri integrity string that was provided to the ctor
34
+ * Check that the sri integrity string that was provided to the ctor
19
35
  * matches the body that we actually received. This should only be called
20
36
  * AFTER the entire body has been completely downloaded.
21
37
  *
38
+ * This method **will throw** if the integrity values do not match.
39
+ *
22
40
  * Note that this will *usually* not be true if the value is coming out of
23
41
  * the cache, because the cache entries are un-gzipped in place. It should
24
42
  * _only_ be called for artifacts that come from an actual http response.
43
+ *
44
+ * Returns true if anything was actually verified.
25
45
  */
26
- checkIntegrity(): boolean;
46
+ checkIntegrity(context?: ErrorCauseObject): this is CacheEntry & {
47
+ integrity: Integrity;
48
+ };
27
49
  get integrityActual(): Integrity;
28
- get integrity(): `sha512-${string}` | undefined;
50
+ set integrityActual(i: Integrity);
51
+ set integrity(i: Integrity | undefined);
52
+ get integrity(): Integrity | undefined;
29
53
  /**
30
54
  * Give it a key, and it'll return the buffer of that header value
31
55
  */
@@ -62,6 +86,7 @@ export declare class CacheEntry {
62
86
  * the cached response.
63
87
  */
64
88
  static decode(buffer: Buffer): CacheEntry;
89
+ static isGzipEntry(buffer: Buffer): boolean;
65
90
  /**
66
91
  * Encode the entry as a single Buffer for writing to the cache
67
92
  */
@@ -1 +1 @@
1
- {"version":3,"file":"cache-entry.d.ts","sourceRoot":"","sources":["../../src/cache-entry.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAIzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,MAAM,CAAA;AAI1C,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;AAyB/C,QAAA,MAAM,cAAc,eAA2C,CAAA;AAE/D,qBAAa,UAAU;;gBAUnB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,CAAC,EAAE,SAAS;IAiBvB,CAAC,cAAc,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM;IAehE;;;OAGG;IACH,IAAI,KAAK,IAAI,OAAO,CAsBnB;IAED,OAAO,CAAC,CAAC,EAAE,MAAM;IAKjB,IAAI,UAAU,WAEb;IACD,IAAI,OAAO,8BAEV;IAED;;;;;;;;OAQG;IACH,cAAc,IAAI,OAAO;IAIzB,IAAI,eAAe,IAAI,SAAS,CAM/B;IACD,IAAI,SAAS,mCAEZ;IAED;;OAEG;IACH,SAAS,CAAC,CAAC,EAAE,MAAM;IAInB;;OAEG;IACH,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAI3C;;OAEG;IACH,MAAM,IAAI,MAAM;IAWhB,IAAI,IAAI,IAAI,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAEvC;IAGD,IAAI,MAAM,IAAI,OAAO,CAYpB;IAGD,IAAI,MAAM,IAAI,OAAO,CAcpB;IAED;;;;OAIG;IACH,KAAK;IAmBL;;;OAGG;IACH,IAAI;IAKJ;;OAEG;IACH,IAAI,IAAI,OAAO;IAOf;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU;IAiCzC;;OAEG;IAGH,MAAM,IAAI,MAAM;CAoCjB"}
1
+ {"version":3,"file":"cache-entry.d.ts","sourceRoot":"","sources":["../../src/cache-entry.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAE3D,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAGzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,MAAM,CAAA;AAK1C,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;AAyB/C,QAAA,MAAM,cAAc,eAA2C,CAAA;AAE/D,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAAA;AAED,qBAAa,UAAU;;gBAWnB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EAAE,EACjB,EAAE,SAAS,EAAE,cAAsB,EAAE,GAAE,iBAAsB;IAkB/D,CAAC,cAAc,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM;IAuBhE;;;OAGG;IACH,IAAI,KAAK,IAAI,OAAO,CAsBnB;IAED,OAAO,CAAC,CAAC,EAAE,MAAM;IAKjB,IAAI,UAAU,WAEb;IACD,IAAI,OAAO,8BAEV;IAED;;;;;;;;;;;;OAYG;IACH,cAAc,CACZ,OAAO,GAAE,gBAAqB,GAC7B,IAAI,IAAI,UAAU,GAAG;QAAE,SAAS,EAAE,SAAS,CAAA;KAAE;IAchD,IAAI,eAAe,IAAI,SAAS,CAO/B;IAED,IAAI,eAAe,CAAC,CAAC,EAAE,SAAS,EAG/B;IAED,IAAI,SAAS,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,EAKrC;IACD,IAAI,SAAS,IANI,SAAS,GAAG,SAAS,CAQrC;IAED;;OAEG;IACH,SAAS,CAAC,CAAC,EAAE,MAAM;IAInB;;OAEG;IACH,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAI3C;;OAEG;IACH,MAAM,IAAI,MAAM;IAWhB,IAAI,IAAI,IAAI,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAEvC;IAGD,IAAI,MAAM,IAAI,OAAO,CAYpB;IAGD,IAAI,MAAM,IAAI,OAAO,CAcpB;IAED;;;;OAIG;IACH,KAAK;IAmBL;;;OAGG;IACH,IAAI;IAKJ;;OAEG;IACH,IAAI,IAAI,OAAO;IAOf;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU;IAsDzC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAO3C;;OAEG;IAGH,MAAM,IAAI,MAAM;CAmCjB"}
@@ -51,10 +51,13 @@ export class CacheEntry {
51
51
  #integrity;
52
52
  #integrityActual;
53
53
  #json;
54
- constructor(statusCode, headers, integrity) {
55
- this.#integrity = integrity;
56
- this.#statusCode = statusCode;
54
+ #trustIntegrity;
55
+ constructor(statusCode, headers, { integrity, trustIntegrity = false } = {}) {
57
56
  this.#headers = headers;
57
+ this.#statusCode = statusCode;
58
+ this.#trustIntegrity = trustIntegrity;
59
+ if (integrity)
60
+ this.integrity = integrity;
58
61
  }
59
62
  get #headersAsObject() {
60
63
  const ret = [];
@@ -66,10 +69,17 @@ export class CacheEntry {
66
69
  return ret;
67
70
  }
68
71
  [kCustomInspect](depth, options) {
72
+ const raw = this.text();
73
+ const isBinary = raw.includes('\x00');
74
+ const show = isBinary ? '[binary data]' : raw.substring(0, 512);
75
+ const text = !isBinary && show.length < raw.length ? raw + '…' : show;
69
76
  const str = inspect({
70
77
  statusCode: this.statusCode,
71
78
  headers: this.#headersAsObject,
72
- text: this.text(),
79
+ // we know that gzip and tar data will always include at least
80
+ // one \x00, and json never will, so this is fine for our purpose,
81
+ // to avoid dumping bells and whatnot to the terminal.
82
+ text,
73
83
  }, {
74
84
  depth,
75
85
  ...options,
@@ -113,18 +123,31 @@ export class CacheEntry {
113
123
  return this.#headers;
114
124
  }
115
125
  /**
116
- * check that the sri integrity string that was provided to the ctor
126
+ * Check that the sri integrity string that was provided to the ctor
117
127
  * matches the body that we actually received. This should only be called
118
128
  * AFTER the entire body has been completely downloaded.
119
129
  *
130
+ * This method **will throw** if the integrity values do not match.
131
+ *
120
132
  * Note that this will *usually* not be true if the value is coming out of
121
133
  * the cache, because the cache entries are un-gzipped in place. It should
122
134
  * _only_ be called for artifacts that come from an actual http response.
135
+ *
136
+ * Returns true if anything was actually verified.
123
137
  */
124
- checkIntegrity() {
138
+ checkIntegrity(context = {}) {
125
139
  if (!this.#integrity)
126
140
  return false;
127
- return this.integrityActual === this.#integrity;
141
+ if (this.integrityActual !== this.#integrity) {
142
+ throw error('Integrity check failure', {
143
+ code: 'EINTEGRITY',
144
+ response: this,
145
+ wanted: this.#integrity,
146
+ found: this.integrityActual,
147
+ ...context,
148
+ });
149
+ }
150
+ return true;
128
151
  }
129
152
  get integrityActual() {
130
153
  if (this.#integrityActual)
@@ -132,8 +155,20 @@ export class CacheEntry {
132
155
  const hash = createHash('sha512');
133
156
  for (const buf of this.#body)
134
157
  hash.update(buf);
135
- this.#integrityActual = `sha512-${hash.digest('base64')}`;
136
- return this.#integrityActual;
158
+ const i = `sha512-${hash.digest('base64')}`;
159
+ this.integrityActual = i;
160
+ return i;
161
+ }
162
+ set integrityActual(i) {
163
+ this.#integrityActual = i;
164
+ this.setHeader('integrity', i);
165
+ }
166
+ set integrity(i) {
167
+ if (!this.#integrity && i) {
168
+ this.#integrity = i;
169
+ if (this.#trustIntegrity)
170
+ this.integrityActual = i;
171
+ }
137
172
  }
138
173
  get integrity() {
139
174
  return this.#integrity;
@@ -254,44 +289,59 @@ export class CacheEntry {
254
289
  */
255
290
  static decode(buffer) {
256
291
  if (buffer.length < 4) {
257
- return new CacheEntry(0, []);
292
+ return emptyCacheEntry;
258
293
  }
259
294
  const headSize = readSize(buffer, 0);
260
295
  if (buffer.length < headSize) {
261
- return new CacheEntry(0, []);
296
+ return emptyCacheEntry;
262
297
  }
263
298
  const statusCode = Number(buffer.subarray(4, 7).toString());
264
299
  const headersBuffer = buffer.subarray(7, headSize);
265
300
  // walk through the headers array, building up the rawHeaders Buffer[]
266
301
  const headers = [];
267
302
  let i = 0;
303
+ let integrity = undefined;
268
304
  while (i < headersBuffer.length - 4) {
269
305
  const size = readSize(headersBuffer, i);
270
- headers.push(headersBuffer.subarray(i + 4, i + size));
306
+ const val = headersBuffer.subarray(i + 4, i + size);
307
+ // if the last one was the key integrity, then this one is the value
308
+ if (headers.length % 2 === 1 &&
309
+ String(headers[headers.length - 1]) === 'integrity') {
310
+ integrity = String(val);
311
+ }
312
+ headers.push(val);
271
313
  i += size;
272
314
  }
273
- const c = new CacheEntry(statusCode, headers);
274
315
  const body = buffer.subarray(headSize);
316
+ const c = new CacheEntry(statusCode, setRawHeader(headers, 'content-length', String(body.byteLength)), {
317
+ integrity,
318
+ trustIntegrity: true,
319
+ });
275
320
  c.#body = [body];
276
321
  c.#bodyLength = body.byteLength;
277
- c.setHeader('content-length', String(c.#bodyLength));
278
322
  if (c.isJSON) {
279
323
  try {
280
324
  c.json();
281
325
  }
282
326
  catch {
283
- return new CacheEntry(0, []);
327
+ return emptyCacheEntry;
284
328
  }
285
329
  }
286
330
  return c;
287
331
  }
332
+ static isGzipEntry(buffer) {
333
+ if (buffer.length < 4)
334
+ return false;
335
+ const headSize = readSize(buffer, 0);
336
+ const gzipBytes = buffer.subarray(headSize, headSize + 2);
337
+ return gzipBytes[0] === 0x1f && gzipBytes[1] === 0x8b;
338
+ }
288
339
  /**
289
340
  * Encode the entry as a single Buffer for writing to the cache
290
341
  */
291
342
  // TODO: should this maybe not concat, and just return Buffer[]?
292
343
  // Then we can writev it to the cache file and save the memory copy
293
344
  encode() {
294
- // store json results as a serialized object.
295
345
  if (this.isJSON)
296
346
  this.json();
297
347
  const sb = Buffer.from(String(this.#statusCode));
@@ -321,4 +371,5 @@ export class CacheEntry {
321
371
  return Buffer.concat(chunks, headLength + this.#bodyLength);
322
372
  }
323
373
  }
374
+ const emptyCacheEntry = new CacheEntry(0, []);
324
375
  //# sourceMappingURL=cache-entry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache-entry.js","sourceRoot":"","sources":["../../src/cache-entry.ts"],"names":[],"mappings":"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","sourcesContent":["// A response object in the cache.\n//\n// The cache stores Buffer objects, and it's convenient to have headers/body\n// together, so we have a simple data structure for this.\n//\n// The shape of it is:\n//\n// [head length]\n// <status code in ascii>\n// [headers]\n// [body]\n//\n// The [UInt32BE head length] is 4 bytes specifying the full length of the\n// status code plus all header keys and values.\n//\n// The [headers] section is key/value/key2/value2/... where each key and value\n// is a 4-byte Uint32BE length, followed by that many bytes.\n//\n// From there, the body can be of any indeterminate length, and is the rest\n// of the file.\n\nimport { error } from '@vltpkg/error-cause'\nimport type { Integrity, JSONField } from '@vltpkg/types'\nimport ccp from 'cache-control-parser'\nimport { createHash } from 'crypto'\nimport { inspect } from 'util'\nimport type { InspectOptions } from 'util'\nimport { gunzipSync } from 'zlib'\nimport { getRawHeader, setRawHeader } from './raw-header.ts'\n\nexport type JSONObj = Record<string, JSONField>\n\nconst readSize = (buf: Buffer, offset: number) => {\n const a = buf[offset]\n const b = buf[offset + 1]\n const c = buf[offset + 2]\n const d = buf[offset + 3]\n\n // not possible, we check the length\n /* c8 ignore start */\n if (\n a === undefined ||\n b === undefined ||\n c === undefined ||\n d === undefined\n ) {\n throw error('Invalid buffer, not long enough to readSize', {\n found: buf.length,\n })\n }\n /* c8 ignore stop */\n\n return (a << 24) | (b << 16) | (c << 8) | d\n}\n\nconst kCustomInspect = Symbol.for('nodejs.util.inspect.custom')\n\nexport class CacheEntry {\n #statusCode: number\n #headers: Buffer[]\n #body: Buffer[] = []\n #bodyLength = 0\n #integrity?: Integrity\n #integrityActual?: Integrity\n #json?: JSONObj\n\n constructor(\n statusCode: number,\n headers: Buffer[],\n integrity?: Integrity,\n ) {\n this.#integrity = integrity\n this.#statusCode = statusCode\n this.#headers = headers\n }\n\n get #headersAsObject(): [string, string][] {\n const ret: [string, string][] = []\n for (let i = 0; i < this.#headers.length - 1; i += 2) {\n const key = String(this.#headers[i])\n const val = String(this.#headers[i + 1])\n ret.push([key, val])\n }\n return ret\n }\n\n [kCustomInspect](depth: number, options: InspectOptions): string {\n const str = inspect(\n {\n statusCode: this.statusCode,\n headers: this.#headersAsObject,\n text: this.text(),\n },\n {\n depth,\n ...options,\n },\n )\n return `@vltpkg/registry-client.CacheEntry ${str}`\n }\n\n /**\n * `true` if the entry represents a cached response that is still\n * valid to use.\n */\n get valid(): boolean {\n const cc_ = this.getHeader('cache-control')?.toString()\n const cc = cc_ ? ccp.parse(cc_) : {}\n const ct = this.getHeader('content-type')?.toString() ?? ''\n const dh = this.getHeader('date')?.toString()\n\n // immutable = never changes\n if (cc.immutable) return true\n\n // some registries do text/json, some do application/json,\n // some do application/vnd.npm.install-v1+json\n // If it's NOT json, it's an immutable tarball\n if (ct !== '' && !/\\bjson\\b/.test(ct)) return true\n\n // see if the max-age has not yet been crossed\n // default to 5m if maxage is not set, as some registries\n // do not set a cache control header at all.\n const ma = cc['max-age'] || cc['s-maxage'] || 300\n if (ma && dh) {\n return Date.parse(dh) + ma * 1000 > Date.now()\n }\n return false\n }\n\n addBody(b: Buffer) {\n this.#body.push(b)\n this.#bodyLength += b.byteLength\n }\n\n get statusCode() {\n return this.#statusCode\n }\n get headers() {\n return this.#headers\n }\n\n /**\n * check that the sri integrity string that was provided to the ctor\n * matches the body that we actually received. This should only be called\n * AFTER the entire body has been completely downloaded.\n *\n * Note that this will *usually* not be true if the value is coming out of\n * the cache, because the cache entries are un-gzipped in place. It should\n * _only_ be called for artifacts that come from an actual http response.\n */\n checkIntegrity(): boolean {\n if (!this.#integrity) return false\n return this.integrityActual === this.#integrity\n }\n get integrityActual(): Integrity {\n if (this.#integrityActual) return this.#integrityActual\n const hash = createHash('sha512')\n for (const buf of this.#body) hash.update(buf)\n this.#integrityActual = `sha512-${hash.digest('base64')}`\n return this.#integrityActual\n }\n get integrity() {\n return this.#integrity\n }\n\n /**\n * Give it a key, and it'll return the buffer of that header value\n */\n getHeader(h: string) {\n return getRawHeader(this.#headers, h)\n }\n\n /**\n * Set a header to a specific value\n */\n setHeader(h: string, value: Buffer | string) {\n this.#headers = setRawHeader(this.#headers, h, value)\n }\n\n /**\n * Return the body of the entry as a Buffer\n */\n buffer(): Buffer {\n const b = this.#body[0]\n if (!b) return Buffer.allocUnsafe(0)\n if (this.#body.length === 1) return b\n const cat = Buffer.concat(this.#body, this.#bodyLength)\n this.#body = [cat]\n return cat\n }\n\n // return the buffer if it's a tarball, or the parsed\n // JSON if it's not.\n get body(): Buffer | Record<string, any> {\n return this.isJSON ? this.json() : this.buffer()\n }\n\n #isJSON?: boolean\n get isJSON(): boolean {\n if (this.#isJSON !== undefined) return this.#isJSON\n const ct = this.getHeader('content-type')?.toString()\n // if it says it's json, assume json\n if (ct) return (this.#isJSON = /\\bjson\\b/.test(ct))\n const text = this.text()\n // don't cache, because we might just not have it yet.\n if (!text) return false\n // all registry json starts with {, and no tarball ever can.\n this.#isJSON = text.startsWith('{')\n if (this.#isJSON) this.setHeader('content-type', 'text/json')\n return this.#isJSON\n }\n\n #isGzip?: boolean\n get isGzip(): boolean {\n if (this.#isGzip !== undefined) return this.#isGzip\n const ce = this.getHeader('content-encoding')?.toString()\n if (ce && !/\\bgzip\\b/.test(ce)) return (this.#isGzip = false)\n const buf = this.buffer()\n if (buf.length < 2) return false\n this.#isGzip = buf[0] === 0x1f && buf[1] === 0x8b\n if (this.#isGzip) {\n this.setHeader('content-encoding', 'gzip')\n } else {\n this.setHeader('content-encoding', 'identity')\n this.setHeader('content-length', String(this.#bodyLength))\n }\n return this.#isGzip\n }\n\n /**\n * Un-gzip encode the body.\n * Returns true if it was previously gzip (so something was done), otherwise\n * returns false.\n */\n unzip() {\n if (this.isGzip) {\n // we know that if we know it's gzip, that the body has been\n // flattened to a single buffer, so save the extra call.\n /* c8 ignore start */\n if (this.#body[0] == null)\n throw error('Invalid buffer, cant unzip')\n /* c8 ignore stop */\n const b = gunzipSync(this.#body[0])\n this.setHeader('content-encoding', 'identity')\n this.#body = [b]\n this.#bodyLength = b.byteLength\n this.setHeader('content-length', String(this.#bodyLength))\n this.#isGzip = false\n return true\n }\n return false\n }\n\n /**\n * Return the body of the entry as utf8 text\n * Automatically unzips if the content is gzip encoded\n */\n text() {\n this.unzip()\n return this.buffer().toString()\n }\n\n /**\n * Parse the entry body as JSON and return the result\n */\n json(): JSONObj {\n if (this.#json !== undefined) return this.#json\n const obj = JSON.parse(this.text()) as JSONObj\n this.#json = obj\n return obj\n }\n\n /**\n * Pass the contents of a @vltpkg/cache.Cache object as a buffer,\n * and this static method will decode it into a CacheEntry representing\n * the cached response.\n */\n static decode(buffer: Buffer): CacheEntry {\n if (buffer.length < 4) {\n return new CacheEntry(0, [])\n }\n const headSize = readSize(buffer, 0)\n if (buffer.length < headSize) {\n return new CacheEntry(0, [])\n }\n const statusCode = Number(buffer.subarray(4, 7).toString())\n const headersBuffer = buffer.subarray(7, headSize)\n // walk through the headers array, building up the rawHeaders Buffer[]\n const headers: Buffer[] = []\n let i = 0\n while (i < headersBuffer.length - 4) {\n const size = readSize(headersBuffer, i)\n headers.push(headersBuffer.subarray(i + 4, i + size))\n i += size\n }\n const c = new CacheEntry(statusCode, headers)\n const body = buffer.subarray(headSize)\n c.#body = [body]\n c.#bodyLength = body.byteLength\n c.setHeader('content-length', String(c.#bodyLength))\n if (c.isJSON) {\n try {\n c.json()\n } catch {\n return new CacheEntry(0, [])\n }\n }\n return c\n }\n\n /**\n * Encode the entry as a single Buffer for writing to the cache\n */\n // TODO: should this maybe not concat, and just return Buffer[]?\n // Then we can writev it to the cache file and save the memory copy\n encode(): Buffer {\n // store json results as a serialized object.\n if (this.isJSON) this.json()\n const sb = Buffer.from(String(this.#statusCode))\n const chunks: Buffer[] = [sb]\n let headLength = sb.byteLength + 4\n for (const h of this.#headers) {\n const hlBuf = Buffer.allocUnsafe(4)\n const hl = h.byteLength + 4\n headLength += hl\n hlBuf.set(\n [\n (hl >> 24) & 0xff,\n (hl >> 16) & 0xff,\n (hl >> 8) & 0xff,\n hl & 0xff,\n ],\n 0,\n )\n chunks.push(hlBuf, h)\n }\n\n const hlBuf = Buffer.allocUnsafe(4)\n hlBuf.set(\n [\n (headLength >> 24) & 0xff,\n (headLength >> 16) & 0xff,\n (headLength >> 8) & 0xff,\n headLength & 0xff,\n ],\n 0,\n )\n chunks.unshift(hlBuf)\n chunks.push(...this.#body)\n return Buffer.concat(chunks, headLength + this.#bodyLength)\n }\n}\n"]}
1
+ {"version":3,"file":"cache-entry.js","sourceRoot":"","sources":["../../src/cache-entry.ts"],"names":[],"mappings":"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","sourcesContent":["// A response object in the cache.\n//\n// The cache stores Buffer objects, and it's convenient to have headers/body\n// together, so we have a simple data structure for this.\n//\n// The shape of it is:\n//\n// [head length]\n// <status code in ascii>\n// [headers]\n// [body]\n//\n// The [UInt32BE head length] is 4 bytes specifying the full length of the\n// status code plus all header keys and values.\n//\n// The [headers] section is key/value/key2/value2/... where each key and value\n// is a 4-byte Uint32BE length, followed by that many bytes.\n//\n// From there, the body can be of any indeterminate length, and is the rest\n// of the file.\n\nimport type { ErrorCauseObject } from '@vltpkg/error-cause'\nimport { error } from '@vltpkg/error-cause'\nimport type { Integrity, JSONField } from '@vltpkg/types'\nimport ccp from 'cache-control-parser'\nimport { createHash } from 'crypto'\nimport type { InspectOptions } from 'util'\nimport { inspect } from 'util'\nimport { gunzipSync } from 'zlib'\nimport { getRawHeader, setRawHeader } from './raw-header.ts'\n\nexport type JSONObj = Record<string, JSONField>\n\nconst readSize = (buf: Buffer, offset: number) => {\n const a = buf[offset]\n const b = buf[offset + 1]\n const c = buf[offset + 2]\n const d = buf[offset + 3]\n\n // not possible, we check the length\n /* c8 ignore start */\n if (\n a === undefined ||\n b === undefined ||\n c === undefined ||\n d === undefined\n ) {\n throw error('Invalid buffer, not long enough to readSize', {\n found: buf.length,\n })\n }\n /* c8 ignore stop */\n\n return (a << 24) | (b << 16) | (c << 8) | d\n}\n\nconst kCustomInspect = Symbol.for('nodejs.util.inspect.custom')\n\nexport type CacheEntryOptions = {\n /**\n * The expected integrity value for this response body\n */\n integrity?: Integrity\n /**\n * Whether to trust the integrity, or calculate the actual value.\n *\n * This indicates that we just accept whatever the integrity is as the actual\n * integrity for saving back to the cache, because it's coming directly from\n * the registry that we fetched a packument from, and is an initial gzipped\n * artifact request.\n */\n trustIntegrity?: boolean\n}\n\nexport class CacheEntry {\n #statusCode: number\n #headers: Buffer[]\n #body: Buffer[] = []\n #bodyLength = 0\n #integrity?: Integrity\n #integrityActual?: Integrity\n #json?: JSONObj\n #trustIntegrity\n\n constructor(\n statusCode: number,\n headers: Buffer[],\n { integrity, trustIntegrity = false }: CacheEntryOptions = {},\n ) {\n this.#headers = headers\n this.#statusCode = statusCode\n this.#trustIntegrity = trustIntegrity\n if (integrity) this.integrity = integrity\n }\n\n get #headersAsObject(): [string, string][] {\n const ret: [string, string][] = []\n for (let i = 0; i < this.#headers.length - 1; i += 2) {\n const key = String(this.#headers[i])\n const val = String(this.#headers[i + 1])\n ret.push([key, val])\n }\n return ret\n }\n\n [kCustomInspect](depth: number, options: InspectOptions): string {\n const raw = this.text()\n const isBinary = raw.includes('\\x00')\n const show = isBinary ? '[binary data]' : raw.substring(0, 512)\n const text =\n !isBinary && show.length < raw.length ? raw + '…' : show\n const str = inspect(\n {\n statusCode: this.statusCode,\n headers: this.#headersAsObject,\n // we know that gzip and tar data will always include at least\n // one \\x00, and json never will, so this is fine for our purpose,\n // to avoid dumping bells and whatnot to the terminal.\n text,\n },\n {\n depth,\n ...options,\n },\n )\n return `@vltpkg/registry-client.CacheEntry ${str}`\n }\n\n /**\n * `true` if the entry represents a cached response that is still\n * valid to use.\n */\n get valid(): boolean {\n const cc_ = this.getHeader('cache-control')?.toString()\n const cc = cc_ ? ccp.parse(cc_) : {}\n const ct = this.getHeader('content-type')?.toString() ?? ''\n const dh = this.getHeader('date')?.toString()\n\n // immutable = never changes\n if (cc.immutable) return true\n\n // some registries do text/json, some do application/json,\n // some do application/vnd.npm.install-v1+json\n // If it's NOT json, it's an immutable tarball\n if (ct !== '' && !/\\bjson\\b/.test(ct)) return true\n\n // see if the max-age has not yet been crossed\n // default to 5m if maxage is not set, as some registries\n // do not set a cache control header at all.\n const ma = cc['max-age'] || cc['s-maxage'] || 300\n if (ma && dh) {\n return Date.parse(dh) + ma * 1000 > Date.now()\n }\n return false\n }\n\n addBody(b: Buffer) {\n this.#body.push(b)\n this.#bodyLength += b.byteLength\n }\n\n get statusCode() {\n return this.#statusCode\n }\n get headers() {\n return this.#headers\n }\n\n /**\n * Check that the sri integrity string that was provided to the ctor\n * matches the body that we actually received. This should only be called\n * AFTER the entire body has been completely downloaded.\n *\n * This method **will throw** if the integrity values do not match.\n *\n * Note that this will *usually* not be true if the value is coming out of\n * the cache, because the cache entries are un-gzipped in place. It should\n * _only_ be called for artifacts that come from an actual http response.\n *\n * Returns true if anything was actually verified.\n */\n checkIntegrity(\n context: ErrorCauseObject = {},\n ): this is CacheEntry & { integrity: Integrity } {\n if (!this.#integrity) return false\n if (this.integrityActual !== this.#integrity) {\n throw error('Integrity check failure', {\n code: 'EINTEGRITY',\n response: this,\n wanted: this.#integrity,\n found: this.integrityActual,\n ...context,\n })\n }\n return true\n }\n\n get integrityActual(): Integrity {\n if (this.#integrityActual) return this.#integrityActual\n const hash = createHash('sha512')\n for (const buf of this.#body) hash.update(buf)\n const i: Integrity = `sha512-${hash.digest('base64')}`\n this.integrityActual = i\n return i\n }\n\n set integrityActual(i: Integrity) {\n this.#integrityActual = i\n this.setHeader('integrity', i)\n }\n\n set integrity(i: Integrity | undefined) {\n if (!this.#integrity && i) {\n this.#integrity = i\n if (this.#trustIntegrity) this.integrityActual = i\n }\n }\n get integrity() {\n return this.#integrity\n }\n\n /**\n * Give it a key, and it'll return the buffer of that header value\n */\n getHeader(h: string) {\n return getRawHeader(this.#headers, h)\n }\n\n /**\n * Set a header to a specific value\n */\n setHeader(h: string, value: Buffer | string) {\n this.#headers = setRawHeader(this.#headers, h, value)\n }\n\n /**\n * Return the body of the entry as a Buffer\n */\n buffer(): Buffer {\n const b = this.#body[0]\n if (!b) return Buffer.allocUnsafe(0)\n if (this.#body.length === 1) return b\n const cat = Buffer.concat(this.#body, this.#bodyLength)\n this.#body = [cat]\n return cat\n }\n\n // return the buffer if it's a tarball, or the parsed\n // JSON if it's not.\n get body(): Buffer | Record<string, any> {\n return this.isJSON ? this.json() : this.buffer()\n }\n\n #isJSON?: boolean\n get isJSON(): boolean {\n if (this.#isJSON !== undefined) return this.#isJSON\n const ct = this.getHeader('content-type')?.toString()\n // if it says it's json, assume json\n if (ct) return (this.#isJSON = /\\bjson\\b/.test(ct))\n const text = this.text()\n // don't cache, because we might just not have it yet.\n if (!text) return false\n // all registry json starts with {, and no tarball ever can.\n this.#isJSON = text.startsWith('{')\n if (this.#isJSON) this.setHeader('content-type', 'text/json')\n return this.#isJSON\n }\n\n #isGzip?: boolean\n get isGzip(): boolean {\n if (this.#isGzip !== undefined) return this.#isGzip\n const ce = this.getHeader('content-encoding')?.toString()\n if (ce && !/\\bgzip\\b/.test(ce)) return (this.#isGzip = false)\n const buf = this.buffer()\n if (buf.length < 2) return false\n this.#isGzip = buf[0] === 0x1f && buf[1] === 0x8b\n if (this.#isGzip) {\n this.setHeader('content-encoding', 'gzip')\n } else {\n this.setHeader('content-encoding', 'identity')\n this.setHeader('content-length', String(this.#bodyLength))\n }\n return this.#isGzip\n }\n\n /**\n * Un-gzip encode the body.\n * Returns true if it was previously gzip (so something was done), otherwise\n * returns false.\n */\n unzip() {\n if (this.isGzip) {\n // we know that if we know it's gzip, that the body has been\n // flattened to a single buffer, so save the extra call.\n /* c8 ignore start */\n if (this.#body[0] == null)\n throw error('Invalid buffer, cant unzip')\n /* c8 ignore stop */\n const b = gunzipSync(this.#body[0])\n this.setHeader('content-encoding', 'identity')\n this.#body = [b]\n this.#bodyLength = b.byteLength\n this.setHeader('content-length', String(this.#bodyLength))\n this.#isGzip = false\n return true\n }\n return false\n }\n\n /**\n * Return the body of the entry as utf8 text\n * Automatically unzips if the content is gzip encoded\n */\n text() {\n this.unzip()\n return this.buffer().toString()\n }\n\n /**\n * Parse the entry body as JSON and return the result\n */\n json(): JSONObj {\n if (this.#json !== undefined) return this.#json\n const obj = JSON.parse(this.text()) as JSONObj\n this.#json = obj\n return obj\n }\n\n /**\n * Pass the contents of a @vltpkg/cache.Cache object as a buffer,\n * and this static method will decode it into a CacheEntry representing\n * the cached response.\n */\n static decode(buffer: Buffer): CacheEntry {\n if (buffer.length < 4) {\n return emptyCacheEntry\n }\n const headSize = readSize(buffer, 0)\n if (buffer.length < headSize) {\n return emptyCacheEntry\n }\n const statusCode = Number(buffer.subarray(4, 7).toString())\n const headersBuffer = buffer.subarray(7, headSize)\n // walk through the headers array, building up the rawHeaders Buffer[]\n const headers: Buffer[] = []\n let i = 0\n let integrity: Integrity | undefined = undefined\n while (i < headersBuffer.length - 4) {\n const size = readSize(headersBuffer, i)\n const val = headersBuffer.subarray(i + 4, i + size)\n // if the last one was the key integrity, then this one is the value\n if (\n headers.length % 2 === 1 &&\n String(headers[headers.length - 1]) === 'integrity'\n ) {\n integrity = String(val) as Integrity\n }\n headers.push(val)\n i += size\n }\n const body = buffer.subarray(headSize)\n\n const c = new CacheEntry(\n statusCode,\n setRawHeader(\n headers,\n 'content-length',\n String(body.byteLength),\n ),\n {\n integrity,\n trustIntegrity: true,\n },\n )\n\n c.#body = [body]\n c.#bodyLength = body.byteLength\n if (c.isJSON) {\n try {\n c.json()\n } catch {\n return emptyCacheEntry\n }\n }\n return c\n }\n\n static isGzipEntry(buffer: Buffer): boolean {\n if (buffer.length < 4) return false\n const headSize = readSize(buffer, 0)\n const gzipBytes = buffer.subarray(headSize, headSize + 2)\n return gzipBytes[0] === 0x1f && gzipBytes[1] === 0x8b\n }\n\n /**\n * Encode the entry as a single Buffer for writing to the cache\n */\n // TODO: should this maybe not concat, and just return Buffer[]?\n // Then we can writev it to the cache file and save the memory copy\n encode(): Buffer {\n if (this.isJSON) this.json()\n const sb = Buffer.from(String(this.#statusCode))\n const chunks: Buffer[] = [sb]\n let headLength = sb.byteLength + 4\n for (const h of this.#headers) {\n const hlBuf = Buffer.allocUnsafe(4)\n const hl = h.byteLength + 4\n headLength += hl\n hlBuf.set(\n [\n (hl >> 24) & 0xff,\n (hl >> 16) & 0xff,\n (hl >> 8) & 0xff,\n hl & 0xff,\n ],\n 0,\n )\n chunks.push(hlBuf, h)\n }\n\n const hlBuf = Buffer.allocUnsafe(4)\n hlBuf.set(\n [\n (headLength >> 24) & 0xff,\n (headLength >> 16) & 0xff,\n (headLength >> 8) & 0xff,\n headLength & 0xff,\n ],\n 0,\n )\n chunks.unshift(hlBuf)\n chunks.push(...this.#body)\n return Buffer.concat(chunks, headLength + this.#bodyLength)\n }\n}\n\nconst emptyCacheEntry = new CacheEntry(0, [])\n"]}
@@ -1,15 +1,14 @@
1
1
  import { Cache } from '@vltpkg/cache';
2
2
  import type { Integrity } from '@vltpkg/types';
3
- import { RetryAgent } from 'undici';
4
3
  import type { Dispatcher } from 'undici';
5
- import { deleteToken, getKC, isToken, keychains, setToken } from './auth.ts';
4
+ import { RetryAgent } from 'undici';
6
5
  import type { Token } from './auth.ts';
7
- import { CacheEntry } from './cache-entry.ts';
6
+ import { deleteToken, getKC, isToken, keychains, setToken } from './auth.ts';
8
7
  import type { JSONObj } from './cache-entry.ts';
8
+ import { CacheEntry } from './cache-entry.ts';
9
9
  import type { TokenResponse } from './token-response.ts';
10
10
  import type { WebAuthChallenge } from './web-auth-challenge.ts';
11
- export { type JSONObj, type CacheEntry, type Token, type WebAuthChallenge, type TokenResponse, };
12
- export { keychains, getKC, setToken, deleteToken, isToken };
11
+ export { deleteToken, getKC, isToken, keychains, setToken, type CacheEntry, type JSONObj, type Token, type TokenResponse, type WebAuthChallenge, };
13
12
  export type RegistryClientOptions = {
14
13
  /**
15
14
  * Path on disk where the cache should be stored
@@ -49,6 +48,12 @@ export type RegistryClientRequestOptions = Omit<Dispatcher.RequestOptions, 'meth
49
48
  * the local disk cache, items are assumed to be trustworthy.
50
49
  */
51
50
  integrity?: Integrity;
51
+ /**
52
+ * Set to true if the integrity should be trusted implicitly without
53
+ * a recalculation, for example if it comes from a trusted registry that
54
+ * also serves the tarball itself.
55
+ */
56
+ trustIntegrity?: boolean;
52
57
  /**
53
58
  * Follow up to 10 redirections by default. Set this to 0 to just return
54
59
  * the 3xx response. If the max redirections are expired, and we still get
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
package/dist/esm/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Cache } from '@vltpkg/cache';
2
2
  import { register } from '@vltpkg/cache-unzip';
3
3
  import { error } from '@vltpkg/error-cause';
4
+ import { logRequest } from '@vltpkg/output';
4
5
  import { urlOpen } from '@vltpkg/url-open';
5
6
  import { XDG } from '@vltpkg/xdg';
6
7
  import { setTimeout } from 'node:timers/promises';
@@ -14,10 +15,9 @@ import { handle304Response } from "./handle-304-response.js";
14
15
  import { otplease } from "./otplease.js";
15
16
  import { isRedirect, redirect } from "./redirect.js";
16
17
  import { setCacheHeaders } from "./set-cache-headers.js";
17
- import { logRequest } from '@vltpkg/output';
18
18
  import { isTokenResponse } from "./token-response.js";
19
19
  import { isWebAuthChallenge } from "./web-auth-challenge.js";
20
- export { keychains, getKC, setToken, deleteToken, isToken };
20
+ export { deleteToken, getKC, isToken, keychains, setToken, };
21
21
  const { version } = loadPackageJson(import.meta.filename, process.env.__VLT_INTERNAL_REGISTRY_CLIENT_PACKAGE_JSON);
22
22
  const nua = globalThis.navigator?.userAgent ??
23
23
  (bun ? `Bun/${bun}`
@@ -51,7 +51,7 @@ export class RegistryClient {
51
51
  this.cache = new Cache({
52
52
  path: cache,
53
53
  onDiskWrite(_path, key, data) {
54
- if (CacheEntry.decode(data).isGzip)
54
+ if (CacheEntry.isGzipEntry(data))
55
55
  register(cache, key);
56
56
  },
57
57
  });
@@ -207,8 +207,9 @@ export class RegistryClient {
207
207
  await this.cache.fetch(key, { context: { integrity } })
208
208
  : undefined;
209
209
  const entry = buffer ? CacheEntry.decode(buffer) : undefined;
210
- if (entry?.valid)
210
+ if (entry?.valid) {
211
211
  return entry;
212
+ }
212
213
  // TODO: stale-while-revalidate timeout, say 1 day, where we'll
213
214
  // use the cached response even if it's invalid, and validate
214
215
  // in the background without waiting for it.
@@ -224,6 +225,9 @@ export class RegistryClient {
224
225
  if (otp) {
225
226
  options.headers = addHeader(options.headers, 'npm-otp', otp);
226
227
  }
228
+ if (integrity) {
229
+ options.headers = addHeader(options.headers, 'accept-integrity', integrity);
230
+ }
227
231
  options.method = options.method ?? 'GET';
228
232
  // will remove if we don't have a token.
229
233
  options.headers = addHeader(options.headers, 'authorization', await getToken(origin, this.identity));
@@ -251,9 +255,10 @@ export class RegistryClient {
251
255
  h.push(Buffer.from(key), Buffer.from(value));
252
256
  }
253
257
  }
258
+ const { integrity, trustIntegrity } = options;
254
259
  const result = new CacheEntry(
255
260
  /* c8 ignore next - should always have a status code */
256
- response.statusCode || 200, h, options.integrity);
261
+ response.statusCode || 200, h, { integrity, trustIntegrity });
257
262
  if (isRedirect(result)) {
258
263
  response.body.resume();
259
264
  // remove the try/catch once rebasing onto main with Luke's error-cause stuff
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { Cache } from '@vltpkg/cache'\nimport { register } from '@vltpkg/cache-unzip'\nimport { error } from '@vltpkg/error-cause'\nimport type { Integrity } from '@vltpkg/types'\nimport { urlOpen } from '@vltpkg/url-open'\nimport { XDG } from '@vltpkg/xdg'\nimport { setTimeout } from 'node:timers/promises'\nimport { loadPackageJson } from 'package-json-from-dist'\nimport { Agent, RetryAgent } from 'undici'\nimport type { Dispatcher } from 'undici'\nimport { addHeader } from './add-header.ts'\nimport {\n deleteToken,\n getKC,\n getToken,\n isToken,\n keychains,\n setToken,\n} from './auth.ts'\nimport type { Token } from './auth.ts'\nimport { CacheEntry } from './cache-entry.ts'\nimport type { JSONObj } from './cache-entry.ts'\nimport { bun, deno, node } from './env.ts'\nimport { handle304Response } from './handle-304-response.ts'\nimport { otplease } from './otplease.ts'\nimport { isRedirect, redirect } from './redirect.ts'\nimport { setCacheHeaders } from './set-cache-headers.ts'\nimport { logRequest } from '@vltpkg/output'\nimport { isTokenResponse } from './token-response.ts'\nimport type { TokenResponse } from './token-response.ts'\nimport { isWebAuthChallenge } from './web-auth-challenge.ts'\nimport type { WebAuthChallenge } from './web-auth-challenge.ts'\nexport {\n type JSONObj,\n type CacheEntry,\n type Token,\n type WebAuthChallenge,\n type TokenResponse,\n}\nexport { keychains, getKC, setToken, deleteToken, isToken }\n\nexport type RegistryClientOptions = {\n /**\n * Path on disk where the cache should be stored\n * @default `$HOME/.config/vlt/cache`\n */\n cache?: string\n /**\n * Number of retries to perform when encountering network errors or\n * likely-transient errors from git hosts.\n */\n 'fetch-retries'?: number\n /** The exponential backoff factor to use when retrying git hosts */\n 'fetch-retry-factor'?: number\n /** Number of milliseconds before starting first retry */\n 'fetch-retry-mintimeout'?: number\n /** Maximum number of milliseconds between two retries */\n 'fetch-retry-maxtimeout'?: number\n\n /** the identity to use for storing auth tokens */\n identity?: string\n}\n\nexport type RegistryClientRequestOptions = Omit<\n Dispatcher.RequestOptions,\n 'method' | 'path'\n> & {\n /**\n * `path` should not be set when using the RegistryClient.\n * It will be overwritten with the path on the URL being requested.\n * This only here for compliance with the DispatchOptions base type.\n * @deprecated\n */\n path?: string\n\n /**\n * Method is optional, defaults to 'GET'\n */\n method?: Dispatcher.DispatchOptions['method']\n /**\n * Provide an SRI string to verify integrity of the item being fetched.\n *\n * This is only relevant when it must make a request to the registry. Once in\n * the local disk cache, items are assumed to be trustworthy.\n */\n integrity?: Integrity\n\n /**\n * Follow up to 10 redirections by default. Set this to 0 to just return\n * the 3xx response. If the max redirections are expired, and we still get\n * a redirection response, then fail the request. Redirection cycles are\n * always treated as an error.\n */\n maxRedirections?: number\n\n /**\n * the number of redirections that have already been seen. This is used\n * internally, and should always start at 0.\n * @internal\n */\n redirections?: Set<string>\n\n /**\n * Set to `false` to suppress ANY lookups from cache. This will also\n * prevent storing the result to the cache.\n */\n cache?: false\n\n /**\n * Set to pass an `npm-otp` header on the request.\n *\n * This should not be set except by the RegistryClient itself, when\n * we receive a 401 response with an OTP challenge.\n * @internal\n */\n otp?: string\n}\n\nconst { version } = loadPackageJson(\n import.meta.filename,\n process.env.__VLT_INTERNAL_REGISTRY_CLIENT_PACKAGE_JSON,\n) as {\n version: string\n}\nconst nua =\n (globalThis.navigator as Navigator | undefined)?.userAgent ??\n (bun ? `Bun/${bun}`\n : deno ? `Deno/${deno}`\n : node ? `Node.js/${node}`\n : '(unknown platform)')\nexport const userAgent = `@vltpkg/registry-client/${version} ${nua}`\n\nconst agentOptions: Agent.Options = {\n bodyTimeout: 600_000,\n headersTimeout: 600_000,\n keepAliveMaxTimeout: 1_200_000,\n keepAliveTimeout: 600_000,\n keepAliveTimeoutThreshold: 30_000,\n connect: {\n timeout: 600_000,\n keepAlive: true,\n keepAliveInitialDelay: 30_000,\n sessionTimeout: 600,\n },\n connections: 128,\n pipelining: 10,\n}\n\nconst xdg = new XDG('vlt')\n\nexport class RegistryClient {\n agent: RetryAgent\n cache: Cache\n identity: string\n\n constructor(options: RegistryClientOptions) {\n const {\n cache = xdg.cache('registry-client'),\n 'fetch-retry-factor': timeoutFactor = 2,\n 'fetch-retry-mintimeout': minTimeout = 0,\n 'fetch-retry-maxtimeout': maxTimeout = 30_000,\n 'fetch-retries': maxRetries = 3,\n identity = '',\n } = options\n this.identity = identity\n this.cache = new Cache({\n path: cache,\n onDiskWrite(_path, key, data) {\n if (CacheEntry.decode(data).isGzip) register(cache, key)\n },\n })\n const dispatch = new Agent(agentOptions)\n this.agent = new RetryAgent(dispatch, {\n maxRetries,\n timeoutFactor,\n minTimeout,\n maxTimeout,\n retryAfter: true,\n errorCodes: [\n 'ECONNREFUSED',\n 'ECONNRESET',\n 'EHOSTDOWN',\n 'ENETDOWN',\n 'ENETUNREACH',\n 'ENOTFOUND',\n 'EPIPE',\n 'UND_ERR_SOCKET',\n ],\n })\n }\n\n /**\n * Fetch the entire set of a paginated list of objects\n */\n async scroll<T>(\n url: URL | string,\n options: RegistryClientRequestOptions = {},\n seek?: (obj: T) => boolean,\n ): Promise<T[]> {\n const resp = await this.request(url, options)\n const { objects, urls } = resp.json() as {\n objects: T[]\n urls: { next?: string }\n }\n // if we have more, and haven't found our target, fetch more\n return urls.next && !(seek && objects.some(seek)) ?\n objects.concat(await this.scroll<T>(urls.next, options, seek))\n : objects\n }\n\n /**\n * find a given item in a paginated set\n */\n async seek<T>(\n url: URL | string,\n seek: (obj: T) => boolean,\n options: RegistryClientRequestOptions = {},\n ): Promise<T | undefined> {\n return (await this.scroll(url, options, seek)).find(seek)\n }\n\n /**\n * Log out from the registry specified, attempting to destroy the\n * token if the registry supports that endpoint.\n */\n async logout(registry: string) {\n // if we have no token for that registry, nothing to do\n const tok = await getToken(registry, this.identity)\n if (!tok) return\n\n const s = tok.replace(/^(Bearer|Basic) /i, '')\n\n const tokensUrl = new URL('-/npm/v1/tokens', registry)\n const record = await this.seek<{\n key: string\n token: string\n }>(tokensUrl, ({ token }) => s.startsWith(token), {\n cache: false,\n }).catch(() => undefined)\n\n if (record) {\n const { key } = record\n await this.request(\n new URL(`-/npm/v1/tokens/token/${key}`, registry),\n { cache: false, method: 'DELETE' },\n )\n }\n\n await deleteToken(registry, this.identity)\n }\n\n /**\n * Log into the registry specified\n *\n * Does not return the token or expose it, just saves to the auth keychain\n * and returns void if it worked. Otherwise, error is raised.\n */\n async login(registry: string) {\n // - make POST to '/-/v1/login'\n // - include a body of {} and npm-auth-type:web\n // - get a {doneUrl, loginUrl}\n // - open the loginUrl\n // - hang on the doneUrl until done\n //\n // if that fails: fall back to couchdb login\n const webLoginURL = new URL('-/v1/login', registry)\n const response = await this.request(webLoginURL, {\n method: 'POST',\n cache: false,\n headers: {\n 'content-type': 'application/json',\n 'npm-auth-type': 'web',\n },\n body: '{}',\n })\n\n if (response.statusCode === 200) {\n const challenge = response.json()\n if (isWebAuthChallenge(challenge)) {\n const result = await this.webAuthOpener(challenge)\n await setToken(\n registry,\n `Bearer ${result.token}`,\n this.identity,\n )\n return\n }\n }\n /* c8 ignore start */\n // TODO: fall back to username/password login, and/or couchdb PUT login\n throw error('Failed to perform web login', { response })\n }\n /* c8 ignore stop */\n\n /**\n * Given a {@link WebAuthChallenge}, open the `loginUrl` in a browser and\n * hang on the `doneUrl` until it returns a {@link TokenResponse} object.\n */\n async webAuthOpener({ doneUrl, loginUrl }: WebAuthChallenge) {\n const ac = new AbortController()\n const { signal } = ac\n /* c8 ignore start - race condition */\n const [result] = await Promise.all([\n this.#checkLogin(doneUrl, { signal }).then(result => {\n ac.abort()\n return result\n }),\n urlOpen(loginUrl, { signal }).catch((er: unknown) => {\n if ((er as Error).name === 'AbortError') return\n ac.abort()\n throw er\n }),\n ])\n /* c8 ignore stop */\n return result\n }\n\n async #checkLogin(\n url: URL | string,\n options: RegistryClientRequestOptions = {},\n ): Promise<TokenResponse> {\n const response = await this.request(url, {\n ...options,\n cache: false,\n })\n const { signal } = options as { signal?: AbortSignal }\n if (response.statusCode === 202) {\n const rt = response.getHeader('retry-after')\n const retryAfter = rt ? Number(rt.toString()) : -1\n if (retryAfter > 0) {\n await setTimeout(retryAfter * 1000, null, { signal })\n }\n return await this.#checkLogin(url, options)\n }\n if (response.statusCode === 200) {\n const body = response.json()\n if (isTokenResponse(body)) return body\n }\n throw error('Invalid response from web login endpoint', {\n response,\n })\n }\n\n async request(\n url: URL | string,\n options: RegistryClientRequestOptions = {},\n ): Promise<CacheEntry> {\n logRequest(url, 'start')\n\n const u = typeof url === 'string' ? new URL(url) : url\n const {\n method = 'GET',\n integrity,\n redirections = new Set(),\n signal,\n otp = (process.env.VLT_OTP ?? '').trim(),\n } = options\n\n const { cache = method === 'GET' || method === 'HEAD' } = options\n\n ;(signal as AbortSignal | null)?.throwIfAborted()\n\n // first, try to get from the cache before making any request.\n const { origin, pathname } = u\n const key = JSON.stringify([origin, method, pathname])\n const buffer =\n cache ?\n await this.cache.fetch(key, { context: { integrity } })\n : undefined\n\n const entry = buffer ? CacheEntry.decode(buffer) : undefined\n if (entry?.valid) return entry\n // TODO: stale-while-revalidate timeout, say 1 day, where we'll\n // use the cached response even if it's invalid, and validate\n // in the background without waiting for it.\n\n // either no cache entry, or need to revalidate it.\n setCacheHeaders(options, entry)\n\n redirections.add(String(url))\n\n Object.assign(options, {\n path: u.pathname.replace(/\\/+$/, '') + u.search,\n ...agentOptions,\n })\n\n options.origin = u.origin\n options.headers = addHeader(\n addHeader(\n options.headers,\n 'accept-encoding',\n 'gzip;q=1.0, identity;q=0.5',\n ),\n 'user-agent',\n userAgent,\n )\n if (otp) {\n options.headers = addHeader(options.headers, 'npm-otp', otp)\n }\n options.method = options.method ?? 'GET'\n\n // will remove if we don't have a token.\n options.headers = addHeader(\n options.headers,\n 'authorization',\n await getToken(origin, this.identity),\n )\n\n const result = await this.#handleResponse(\n u,\n options,\n await this.agent.request(options as Dispatcher.RequestOptions),\n entry,\n )\n\n if (cache) this.cache.set(key, result.encode())\n return result\n }\n\n async #handleResponse(\n url: URL,\n options: RegistryClientRequestOptions,\n response: Dispatcher.ResponseData,\n entry?: CacheEntry,\n ): Promise<CacheEntry> {\n if (handle304Response(response, entry)) return entry\n\n if (response.statusCode === 401) {\n const repeatRequest = await otplease(this, options, response)\n if (repeatRequest) return await this.request(url, repeatRequest)\n }\n\n const h: Buffer[] = []\n for (const [key, value] of Object.entries(response.headers)) {\n /* c8 ignore start - theoretical */\n if (Array.isArray(value)) {\n h.push(Buffer.from(key), Buffer.from(value.join(', ')))\n /* c8 ignore stop */\n } else if (typeof value === 'string') {\n h.push(Buffer.from(key), Buffer.from(value))\n }\n }\n\n const result = new CacheEntry(\n /* c8 ignore next - should always have a status code */\n response.statusCode || 200,\n h,\n options.integrity,\n )\n\n if (isRedirect(result)) {\n response.body.resume()\n // remove the try/catch once rebasing onto main with Luke's error-cause stuff\n try {\n const [nextURL, nextOptions] = redirect(options, result, url)\n if (nextOptions && nextURL) {\n return await this.request(nextURL, nextOptions)\n }\n return result\n } catch (er) {\n /* c8 ignore start */\n throw er instanceof Error ? er : (\n new Error(typeof er === 'string' ? er : 'Unknown error')\n )\n /* c8 ignore stop */\n }\n }\n\n response.body.on('data', (chunk: Buffer) => result.addBody(chunk))\n return await new Promise<CacheEntry>((res, rej) => {\n response.body.on('error', rej)\n response.body.on('end', () => res(result))\n })\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { Cache } from '@vltpkg/cache'\nimport { register } from '@vltpkg/cache-unzip'\nimport { error } from '@vltpkg/error-cause'\nimport { logRequest } from '@vltpkg/output'\nimport type { Integrity } from '@vltpkg/types'\nimport { urlOpen } from '@vltpkg/url-open'\nimport { XDG } from '@vltpkg/xdg'\nimport { setTimeout } from 'node:timers/promises'\nimport { loadPackageJson } from 'package-json-from-dist'\nimport type { Dispatcher } from 'undici'\nimport { Agent, RetryAgent } from 'undici'\nimport { addHeader } from './add-header.ts'\nimport type { Token } from './auth.ts'\nimport {\n deleteToken,\n getKC,\n getToken,\n isToken,\n keychains,\n setToken,\n} from './auth.ts'\nimport type { JSONObj } from './cache-entry.ts'\nimport { CacheEntry } from './cache-entry.ts'\nimport { bun, deno, node } from './env.ts'\nimport { handle304Response } from './handle-304-response.ts'\nimport { otplease } from './otplease.ts'\nimport { isRedirect, redirect } from './redirect.ts'\nimport { setCacheHeaders } from './set-cache-headers.ts'\nimport type { TokenResponse } from './token-response.ts'\nimport { isTokenResponse } from './token-response.ts'\nimport type { WebAuthChallenge } from './web-auth-challenge.ts'\nimport { isWebAuthChallenge } from './web-auth-challenge.ts'\nexport {\n deleteToken,\n getKC,\n isToken,\n keychains,\n setToken,\n type CacheEntry,\n type JSONObj,\n type Token,\n type TokenResponse,\n type WebAuthChallenge,\n}\n\nexport type RegistryClientOptions = {\n /**\n * Path on disk where the cache should be stored\n * @default `$HOME/.config/vlt/cache`\n */\n cache?: string\n /**\n * Number of retries to perform when encountering network errors or\n * likely-transient errors from git hosts.\n */\n 'fetch-retries'?: number\n /** The exponential backoff factor to use when retrying git hosts */\n 'fetch-retry-factor'?: number\n /** Number of milliseconds before starting first retry */\n 'fetch-retry-mintimeout'?: number\n /** Maximum number of milliseconds between two retries */\n 'fetch-retry-maxtimeout'?: number\n\n /** the identity to use for storing auth tokens */\n identity?: string\n}\n\nexport type RegistryClientRequestOptions = Omit<\n Dispatcher.RequestOptions,\n 'method' | 'path'\n> & {\n /**\n * `path` should not be set when using the RegistryClient.\n * It will be overwritten with the path on the URL being requested.\n * This only here for compliance with the DispatchOptions base type.\n * @deprecated\n */\n path?: string\n\n /**\n * Method is optional, defaults to 'GET'\n */\n method?: Dispatcher.DispatchOptions['method']\n /**\n * Provide an SRI string to verify integrity of the item being fetched.\n *\n * This is only relevant when it must make a request to the registry. Once in\n * the local disk cache, items are assumed to be trustworthy.\n */\n integrity?: Integrity\n\n /**\n * Set to true if the integrity should be trusted implicitly without\n * a recalculation, for example if it comes from a trusted registry that\n * also serves the tarball itself.\n */\n trustIntegrity?: boolean\n\n /**\n * Follow up to 10 redirections by default. Set this to 0 to just return\n * the 3xx response. If the max redirections are expired, and we still get\n * a redirection response, then fail the request. Redirection cycles are\n * always treated as an error.\n */\n maxRedirections?: number\n\n /**\n * the number of redirections that have already been seen. This is used\n * internally, and should always start at 0.\n * @internal\n */\n redirections?: Set<string>\n\n /**\n * Set to `false` to suppress ANY lookups from cache. This will also\n * prevent storing the result to the cache.\n */\n cache?: false\n\n /**\n * Set to pass an `npm-otp` header on the request.\n *\n * This should not be set except by the RegistryClient itself, when\n * we receive a 401 response with an OTP challenge.\n * @internal\n */\n otp?: string\n}\n\nconst { version } = loadPackageJson(\n import.meta.filename,\n process.env.__VLT_INTERNAL_REGISTRY_CLIENT_PACKAGE_JSON,\n) as {\n version: string\n}\nconst nua =\n (globalThis.navigator as Navigator | undefined)?.userAgent ??\n (bun ? `Bun/${bun}`\n : deno ? `Deno/${deno}`\n : node ? `Node.js/${node}`\n : '(unknown platform)')\nexport const userAgent = `@vltpkg/registry-client/${version} ${nua}`\n\nconst agentOptions: Agent.Options = {\n bodyTimeout: 600_000,\n headersTimeout: 600_000,\n keepAliveMaxTimeout: 1_200_000,\n keepAliveTimeout: 600_000,\n keepAliveTimeoutThreshold: 30_000,\n connect: {\n timeout: 600_000,\n keepAlive: true,\n keepAliveInitialDelay: 30_000,\n sessionTimeout: 600,\n },\n connections: 128,\n pipelining: 10,\n}\n\nconst xdg = new XDG('vlt')\n\nexport class RegistryClient {\n agent: RetryAgent\n cache: Cache\n identity: string\n\n constructor(options: RegistryClientOptions) {\n const {\n cache = xdg.cache('registry-client'),\n 'fetch-retry-factor': timeoutFactor = 2,\n 'fetch-retry-mintimeout': minTimeout = 0,\n 'fetch-retry-maxtimeout': maxTimeout = 30_000,\n 'fetch-retries': maxRetries = 3,\n identity = '',\n } = options\n this.identity = identity\n this.cache = new Cache({\n path: cache,\n onDiskWrite(_path, key, data) {\n if (CacheEntry.isGzipEntry(data)) register(cache, key)\n },\n })\n const dispatch = new Agent(agentOptions)\n this.agent = new RetryAgent(dispatch, {\n maxRetries,\n timeoutFactor,\n minTimeout,\n maxTimeout,\n retryAfter: true,\n errorCodes: [\n 'ECONNREFUSED',\n 'ECONNRESET',\n 'EHOSTDOWN',\n 'ENETDOWN',\n 'ENETUNREACH',\n 'ENOTFOUND',\n 'EPIPE',\n 'UND_ERR_SOCKET',\n ],\n })\n }\n\n /**\n * Fetch the entire set of a paginated list of objects\n */\n async scroll<T>(\n url: URL | string,\n options: RegistryClientRequestOptions = {},\n seek?: (obj: T) => boolean,\n ): Promise<T[]> {\n const resp = await this.request(url, options)\n const { objects, urls } = resp.json() as {\n objects: T[]\n urls: { next?: string }\n }\n // if we have more, and haven't found our target, fetch more\n return urls.next && !(seek && objects.some(seek)) ?\n objects.concat(await this.scroll<T>(urls.next, options, seek))\n : objects\n }\n\n /**\n * find a given item in a paginated set\n */\n async seek<T>(\n url: URL | string,\n seek: (obj: T) => boolean,\n options: RegistryClientRequestOptions = {},\n ): Promise<T | undefined> {\n return (await this.scroll(url, options, seek)).find(seek)\n }\n\n /**\n * Log out from the registry specified, attempting to destroy the\n * token if the registry supports that endpoint.\n */\n async logout(registry: string) {\n // if we have no token for that registry, nothing to do\n const tok = await getToken(registry, this.identity)\n if (!tok) return\n\n const s = tok.replace(/^(Bearer|Basic) /i, '')\n\n const tokensUrl = new URL('-/npm/v1/tokens', registry)\n const record = await this.seek<{\n key: string\n token: string\n }>(tokensUrl, ({ token }) => s.startsWith(token), {\n cache: false,\n }).catch(() => undefined)\n\n if (record) {\n const { key } = record\n await this.request(\n new URL(`-/npm/v1/tokens/token/${key}`, registry),\n { cache: false, method: 'DELETE' },\n )\n }\n\n await deleteToken(registry, this.identity)\n }\n\n /**\n * Log into the registry specified\n *\n * Does not return the token or expose it, just saves to the auth keychain\n * and returns void if it worked. Otherwise, error is raised.\n */\n async login(registry: string) {\n // - make POST to '/-/v1/login'\n // - include a body of {} and npm-auth-type:web\n // - get a {doneUrl, loginUrl}\n // - open the loginUrl\n // - hang on the doneUrl until done\n //\n // if that fails: fall back to couchdb login\n const webLoginURL = new URL('-/v1/login', registry)\n const response = await this.request(webLoginURL, {\n method: 'POST',\n cache: false,\n headers: {\n 'content-type': 'application/json',\n 'npm-auth-type': 'web',\n },\n body: '{}',\n })\n\n if (response.statusCode === 200) {\n const challenge = response.json()\n if (isWebAuthChallenge(challenge)) {\n const result = await this.webAuthOpener(challenge)\n await setToken(\n registry,\n `Bearer ${result.token}`,\n this.identity,\n )\n return\n }\n }\n /* c8 ignore start */\n // TODO: fall back to username/password login, and/or couchdb PUT login\n throw error('Failed to perform web login', { response })\n }\n /* c8 ignore stop */\n\n /**\n * Given a {@link WebAuthChallenge}, open the `loginUrl` in a browser and\n * hang on the `doneUrl` until it returns a {@link TokenResponse} object.\n */\n async webAuthOpener({ doneUrl, loginUrl }: WebAuthChallenge) {\n const ac = new AbortController()\n const { signal } = ac\n /* c8 ignore start - race condition */\n const [result] = await Promise.all([\n this.#checkLogin(doneUrl, { signal }).then(result => {\n ac.abort()\n return result\n }),\n urlOpen(loginUrl, { signal }).catch((er: unknown) => {\n if ((er as Error).name === 'AbortError') return\n ac.abort()\n throw er\n }),\n ])\n /* c8 ignore stop */\n return result\n }\n\n async #checkLogin(\n url: URL | string,\n options: RegistryClientRequestOptions = {},\n ): Promise<TokenResponse> {\n const response = await this.request(url, {\n ...options,\n cache: false,\n })\n const { signal } = options as { signal?: AbortSignal }\n if (response.statusCode === 202) {\n const rt = response.getHeader('retry-after')\n const retryAfter = rt ? Number(rt.toString()) : -1\n if (retryAfter > 0) {\n await setTimeout(retryAfter * 1000, null, { signal })\n }\n return await this.#checkLogin(url, options)\n }\n if (response.statusCode === 200) {\n const body = response.json()\n if (isTokenResponse(body)) return body\n }\n throw error('Invalid response from web login endpoint', {\n response,\n })\n }\n\n async request(\n url: URL | string,\n options: RegistryClientRequestOptions = {},\n ): Promise<CacheEntry> {\n logRequest(url, 'start')\n\n const u = typeof url === 'string' ? new URL(url) : url\n const {\n method = 'GET',\n integrity,\n redirections = new Set(),\n signal,\n otp = (process.env.VLT_OTP ?? '').trim(),\n } = options\n\n const { cache = method === 'GET' || method === 'HEAD' } = options\n\n ;(signal as AbortSignal | null)?.throwIfAborted()\n\n // first, try to get from the cache before making any request.\n const { origin, pathname } = u\n const key = JSON.stringify([origin, method, pathname])\n const buffer =\n cache ?\n await this.cache.fetch(key, { context: { integrity } })\n : undefined\n\n const entry = buffer ? CacheEntry.decode(buffer) : undefined\n if (entry?.valid) {\n return entry\n }\n // TODO: stale-while-revalidate timeout, say 1 day, where we'll\n // use the cached response even if it's invalid, and validate\n // in the background without waiting for it.\n\n // either no cache entry, or need to revalidate it.\n setCacheHeaders(options, entry)\n\n redirections.add(String(url))\n\n Object.assign(options, {\n path: u.pathname.replace(/\\/+$/, '') + u.search,\n ...agentOptions,\n })\n\n options.origin = u.origin\n options.headers = addHeader(\n addHeader(\n options.headers,\n 'accept-encoding',\n 'gzip;q=1.0, identity;q=0.5',\n ),\n 'user-agent',\n userAgent,\n )\n if (otp) {\n options.headers = addHeader(options.headers, 'npm-otp', otp)\n }\n if (integrity) {\n options.headers = addHeader(\n options.headers,\n 'accept-integrity',\n integrity,\n )\n }\n options.method = options.method ?? 'GET'\n\n // will remove if we don't have a token.\n options.headers = addHeader(\n options.headers,\n 'authorization',\n await getToken(origin, this.identity),\n )\n\n const result = await this.#handleResponse(\n u,\n options,\n await this.agent.request(options as Dispatcher.RequestOptions),\n entry,\n )\n\n if (cache) this.cache.set(key, result.encode())\n return result\n }\n\n async #handleResponse(\n url: URL,\n options: RegistryClientRequestOptions,\n response: Dispatcher.ResponseData,\n entry?: CacheEntry,\n ): Promise<CacheEntry> {\n if (handle304Response(response, entry)) return entry\n\n if (response.statusCode === 401) {\n const repeatRequest = await otplease(this, options, response)\n if (repeatRequest) return await this.request(url, repeatRequest)\n }\n\n const h: Buffer[] = []\n for (const [key, value] of Object.entries(response.headers)) {\n /* c8 ignore start - theoretical */\n if (Array.isArray(value)) {\n h.push(Buffer.from(key), Buffer.from(value.join(', ')))\n /* c8 ignore stop */\n } else if (typeof value === 'string') {\n h.push(Buffer.from(key), Buffer.from(value))\n }\n }\n\n const { integrity, trustIntegrity } = options\n const result = new CacheEntry(\n /* c8 ignore next - should always have a status code */\n response.statusCode || 200,\n h,\n { integrity, trustIntegrity },\n )\n\n if (isRedirect(result)) {\n response.body.resume()\n // remove the try/catch once rebasing onto main with Luke's error-cause stuff\n try {\n const [nextURL, nextOptions] = redirect(options, result, url)\n if (nextOptions && nextURL) {\n return await this.request(nextURL, nextOptions)\n }\n return result\n } catch (er) {\n /* c8 ignore start */\n throw er instanceof Error ? er : (\n new Error(typeof er === 'string' ? er : 'Unknown error')\n )\n /* c8 ignore stop */\n }\n }\n\n response.body.on('data', (chunk: Buffer) => result.addBody(chunk))\n return await new Promise<CacheEntry>((res, rej) => {\n response.body.on('error', rej)\n response.body.on('end', () => res(result))\n })\n }\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vltpkg/registry-client",
3
3
  "description": "Fetch package artifacts and metadata from registries",
4
- "version": "0.0.0-4",
4
+ "version": "0.0.0-6",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/vltpkg/vltpkg.git",
@@ -22,16 +22,16 @@
22
22
  "dependencies": {
23
23
  "cache-control-parser": "^2.0.5",
24
24
  "package-json-from-dist": "^1.0.0",
25
- "undici": "^6.20.0",
26
- "@vltpkg/cache": "0.0.0-4",
27
- "@vltpkg/cache-unzip": "0.0.0-4",
28
- "@vltpkg/error-cause": "0.0.0-4",
29
- "@vltpkg/keychain": "0.0.0-4",
30
- "@vltpkg/output": "0.0.0-4",
31
- "@vltpkg/promise-spawn": "0.0.0-4",
32
- "@vltpkg/types": "0.0.0-4",
33
- "@vltpkg/xdg": "0.0.0-4",
34
- "@vltpkg/url-open": "0.0.0-4"
25
+ "undici": "^7.5.0",
26
+ "@vltpkg/cache": "0.0.0-6",
27
+ "@vltpkg/cache-unzip": "0.0.0-6",
28
+ "@vltpkg/error-cause": "0.0.0-6",
29
+ "@vltpkg/keychain": "0.0.0-6",
30
+ "@vltpkg/output": "0.0.0-6",
31
+ "@vltpkg/promise-spawn": "0.0.0-6",
32
+ "@vltpkg/types": "0.0.0-6",
33
+ "@vltpkg/url-open": "0.0.0-6",
34
+ "@vltpkg/xdg": "0.0.0-6"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@eslint/js": "^9.20.0",