@vltpkg/registry-client 0.0.0-23 → 0.0.0-25
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.
- package/README.md +1 -1
- package/dist/esm/cache-entry.d.ts +32 -8
- package/dist/esm/cache-entry.d.ts.map +1 -1
- package/dist/esm/cache-entry.js +141 -62
- package/dist/esm/cache-entry.js.map +1 -1
- package/dist/esm/handle-304-response.js +1 -1
- package/dist/esm/handle-304-response.js.map +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +11 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/raw-header.d.ts +3 -3
- package/dist/esm/raw-header.d.ts.map +1 -1
- package/dist/esm/raw-header.js +12 -11
- package/dist/esm/raw-header.js.map +1 -1
- package/dist/esm/redirect.d.ts +1 -1
- package/dist/esm/redirect.d.ts.map +1 -1
- package/dist/esm/redirect.js +5 -1
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/set-raw-header.d.ts +1 -1
- package/dist/esm/set-raw-header.d.ts.map +1 -1
- package/dist/esm/set-raw-header.js +6 -4
- package/dist/esm/set-raw-header.js.map +1 -1
- package/dist/esm/string-encoding.d.ts +9 -0
- package/dist/esm/string-encoding.d.ts.map +1 -0
- package/dist/esm/string-encoding.js +25 -0
- package/dist/esm/string-encoding.js.map +1 -0
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ If the response is `content-type: application/octet-stream` and starts
|
|
|
52
52
|
with the gzip header, then we return the raw body as we received it,
|
|
53
53
|
but as a best-effort background job, unzip it and update the cache
|
|
54
54
|
entry to be an unzipped response body. This is done in the
|
|
55
|
-
`@vltpkg/cache-unzip`
|
|
55
|
+
`@vltpkg/cache-unzip` child process.
|
|
56
56
|
|
|
57
57
|
So,
|
|
58
58
|
|
|
@@ -5,6 +5,19 @@ import type { InspectOptions } from 'node:util';
|
|
|
5
5
|
export type JSONObj = Record<string, JSONField>;
|
|
6
6
|
declare const kCustomInspect: unique symbol;
|
|
7
7
|
export type CacheEntryOptions = {
|
|
8
|
+
/**
|
|
9
|
+
* An optional body to use.
|
|
10
|
+
*
|
|
11
|
+
* This is used when decoding a cache entry from a buffer, and the body
|
|
12
|
+
* is already in a ArrayBuffer we can use. When this option is
|
|
13
|
+
* provided the `addBody` method should not be used.
|
|
14
|
+
*/
|
|
15
|
+
body?: Uint8Array;
|
|
16
|
+
/**
|
|
17
|
+
* An optional content length of the body to use, if undefined the
|
|
18
|
+
* content-length header will be used.
|
|
19
|
+
*/
|
|
20
|
+
contentLength?: number;
|
|
8
21
|
/**
|
|
9
22
|
* The expected integrity value for this response body
|
|
10
23
|
*/
|
|
@@ -37,7 +50,7 @@ export type CacheEntryOptions = {
|
|
|
37
50
|
};
|
|
38
51
|
export declare class CacheEntry {
|
|
39
52
|
#private;
|
|
40
|
-
constructor(statusCode: number, headers:
|
|
53
|
+
constructor(statusCode: number, headers: Uint8Array[], { body, integrity, trustIntegrity, 'stale-while-revalidate-factor': staleWhileRevalidateFactor, contentLength, }?: CacheEntryOptions);
|
|
41
54
|
toJSON(): {
|
|
42
55
|
[k: string]: string | number | boolean | [string, string][] | Date | ccp.CacheControl | undefined;
|
|
43
56
|
};
|
|
@@ -48,9 +61,16 @@ export declare class CacheEntry {
|
|
|
48
61
|
get staleWhileRevalidate(): boolean;
|
|
49
62
|
get contentType(): string;
|
|
50
63
|
get valid(): boolean;
|
|
51
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Add contents to the entry body.
|
|
66
|
+
*/
|
|
67
|
+
addBody(b: Uint8Array): void;
|
|
52
68
|
get statusCode(): number;
|
|
53
|
-
get headers():
|
|
69
|
+
get headers(): Uint8Array[];
|
|
70
|
+
/**
|
|
71
|
+
* Returns the body as a single Uint8Array, concatenating parts if needed.
|
|
72
|
+
*/
|
|
73
|
+
get _body(): Uint8Array;
|
|
54
74
|
/**
|
|
55
75
|
* Check that the sri integrity string that was provided to the ctor
|
|
56
76
|
* matches the body that we actually received. This should only be called
|
|
@@ -74,16 +94,20 @@ export declare class CacheEntry {
|
|
|
74
94
|
/**
|
|
75
95
|
* Give it a key, and it'll return the buffer of that header value
|
|
76
96
|
*/
|
|
77
|
-
getHeader(h: string):
|
|
97
|
+
getHeader(h: string): Uint8Array | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* Give it a key, and it'll return the decoded string of that header value
|
|
100
|
+
*/
|
|
101
|
+
getHeaderString(h: string): string | undefined;
|
|
78
102
|
/**
|
|
79
103
|
* Set a header to a specific value
|
|
80
104
|
*/
|
|
81
|
-
setHeader(h: string, value:
|
|
105
|
+
setHeader(h: string, value: Uint8Array | string): void;
|
|
82
106
|
/**
|
|
83
107
|
* Return the body of the entry as a Buffer
|
|
84
108
|
*/
|
|
85
109
|
buffer(): Buffer;
|
|
86
|
-
get body():
|
|
110
|
+
get body(): Uint8Array | Record<string, any>;
|
|
87
111
|
get isJSON(): boolean;
|
|
88
112
|
get isGzip(): boolean;
|
|
89
113
|
/**
|
|
@@ -106,8 +130,8 @@ export declare class CacheEntry {
|
|
|
106
130
|
* and this static method will decode it into a CacheEntry representing
|
|
107
131
|
* the cached response.
|
|
108
132
|
*/
|
|
109
|
-
static decode(buffer:
|
|
110
|
-
static isGzipEntry(buffer:
|
|
133
|
+
static decode(buffer: Uint8Array): CacheEntry;
|
|
134
|
+
static isGzipEntry(buffer: Uint8Array): boolean;
|
|
111
135
|
/**
|
|
112
136
|
* Encode the entry as a single Buffer for writing to the cache
|
|
113
137
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-entry.d.ts","sourceRoot":"","sources":["../../src/cache-entry.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,GAAG,MAAM,sBAAsB,CAAA;AAEtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"cache-entry.d.ts","sourceRoot":"","sources":["../../src/cache-entry.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,GAAG,MAAM,sBAAsB,CAAA;AAEtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAS/C,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;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,UAAU,CAAA;IAEjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IAExB;;;;;;;;;;;;;;OAcG;IACH,+BAA+B,CAAC,EAAE,MAAM,CAAA;CACzC,CAAA;AAED,qBAAa,UAAU;;gBAsBnB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,UAAU,EAAE,EACrB,EACE,IAAI,EACJ,SAAS,EACT,cAAsB,EACtB,+BAA+B,EAC7B,0BAA+B,EACjC,aAAa,GACd,GAAE,iBAAsB;IAwC3B,MAAM;;;IAwCN,CAAC,cAAc,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM;IAShE,IAAI,IAAI,IAAI,IAAI,GAAG,SAAS,CAK3B;IAGD,IAAI,MAAM,IAAI,MAAM,CAQnB;IAGD,IAAI,YAAY,IAAI,GAAG,CAAC,YAAY,CAKnC;IAGD,IAAI,oBAAoB,IAAI,OAAO,CAWlC;IAGD,IAAI,WAAW,WAId;IAOD,IAAI,KAAK,IAAI,OAAO,CAmBnB;IAED;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,UAAU;IAcrB,IAAI,UAAU,WAEb;IACD,IAAI,OAAO,IAAI,UAAU,EAAE,CAE1B;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,UAAU,CAYtB;IAED;;;;;;;;;;;;OAYG;IACH,cAAc,CACZ,OAAO,GAAE,iBAAsB,GAC9B,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,GAAG,UAAU,GAAG,SAAS;IAI5C;;OAEG;IACH,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAO9C;;OAEG;IACH,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM;IAI/C;;OAEG;IACH,MAAM,IAAI,MAAM;IAUhB,IAAI,IAAI,IAAI,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAE3C;IAGD,IAAI,MAAM,IAAI,OAAO,CAYpB;IAGD,IAAI,MAAM,IAAI,OAAO,CAcpB;IAED;;;;OAIG;IACH,KAAK;IAqBL;;;OAGG;IACH,IAAI;IAKJ;;OAEG;IACH,IAAI,IAAI,OAAO;IAQf;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU;IAuD7C,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO;IAO/C;;OAEG;IACH,MAAM,IAAI,MAAM;CAkDjB"}
|
package/dist/esm/cache-entry.js
CHANGED
|
@@ -24,6 +24,7 @@ import { createHash } from 'node:crypto';
|
|
|
24
24
|
import { inspect } from 'node:util';
|
|
25
25
|
import { gunzipSync } from 'node:zlib';
|
|
26
26
|
import { getRawHeader, setRawHeader } from "./raw-header.js";
|
|
27
|
+
import { getDecodedValue, getEncondedValue, } from "./string-encoding.js";
|
|
27
28
|
const readSize = (buf, offset) => {
|
|
28
29
|
const a = buf[offset];
|
|
29
30
|
const b = buf[offset + 1];
|
|
@@ -45,27 +46,57 @@ const readSize = (buf, offset) => {
|
|
|
45
46
|
const kCustomInspect = Symbol.for('nodejs.util.inspect.custom');
|
|
46
47
|
export class CacheEntry {
|
|
47
48
|
#statusCode;
|
|
49
|
+
/** The raw headers as an array of buffers */
|
|
48
50
|
#headers;
|
|
49
|
-
|
|
51
|
+
/** The body buffer, used if the content length is known. */
|
|
52
|
+
#body;
|
|
53
|
+
/**
|
|
54
|
+
* If the content length is unknown we save the body in multiple parts
|
|
55
|
+
* in order to only concatenate once at the end and save extra memory copies.
|
|
56
|
+
*/
|
|
57
|
+
#bodyParts = [];
|
|
58
|
+
/** Used to track the length of the body while reading chunks */
|
|
50
59
|
#bodyLength = 0;
|
|
60
|
+
/** The total length of the body, if known */
|
|
61
|
+
#contentLength;
|
|
51
62
|
#integrity;
|
|
52
63
|
#integrityActual;
|
|
53
64
|
#json;
|
|
54
65
|
#trustIntegrity;
|
|
55
66
|
#staleWhileRevalidateFactor;
|
|
56
|
-
constructor(statusCode, headers, { integrity, trustIntegrity = false, 'stale-while-revalidate-factor': staleWhileRevalidateFactor = 60, } = {}) {
|
|
67
|
+
constructor(statusCode, headers, { body, integrity, trustIntegrity = false, 'stale-while-revalidate-factor': staleWhileRevalidateFactor = 60, contentLength, } = {}) {
|
|
57
68
|
this.#headers = headers;
|
|
58
69
|
this.#statusCode = statusCode;
|
|
59
70
|
this.#trustIntegrity = trustIntegrity;
|
|
60
71
|
this.#staleWhileRevalidateFactor = staleWhileRevalidateFactor;
|
|
61
72
|
if (integrity)
|
|
62
73
|
this.integrity = integrity;
|
|
74
|
+
// if content-legnth is known then we'll only allocate that much memory
|
|
75
|
+
// and we'll avoid copying memory around when adding new chunks.
|
|
76
|
+
if (contentLength != null && typeof contentLength === 'number') {
|
|
77
|
+
this.#contentLength = contentLength;
|
|
78
|
+
}
|
|
79
|
+
// if a body is provided then use that, in this case the `addBody`
|
|
80
|
+
// method should no longer be used.
|
|
81
|
+
if (body) {
|
|
82
|
+
const buffer = new ArrayBuffer(body.byteLength);
|
|
83
|
+
this.#body = new Uint8Array(buffer, 0, body.byteLength);
|
|
84
|
+
this.#body.set(body, 0);
|
|
85
|
+
this.#bodyLength = body.byteLength;
|
|
86
|
+
/* c8 ignore start */
|
|
87
|
+
}
|
|
88
|
+
else if (this.#contentLength) {
|
|
89
|
+
const buffer = new ArrayBuffer(this.#contentLength);
|
|
90
|
+
this.#body = new Uint8Array(buffer, 0, this.#contentLength);
|
|
91
|
+
this.#bodyLength = 0;
|
|
92
|
+
}
|
|
93
|
+
/* c8 ignore stop */
|
|
63
94
|
}
|
|
64
95
|
get #headersAsObject() {
|
|
65
96
|
const ret = [];
|
|
66
97
|
for (let i = 0; i < this.#headers.length - 1; i += 2) {
|
|
67
|
-
const key =
|
|
68
|
-
const val =
|
|
98
|
+
const key = getDecodedValue(this.#headers[i]);
|
|
99
|
+
const val = getDecodedValue(this.#headers[i + 1]);
|
|
69
100
|
ret.push([key, val]);
|
|
70
101
|
}
|
|
71
102
|
return ret;
|
|
@@ -105,7 +136,7 @@ export class CacheEntry {
|
|
|
105
136
|
get date() {
|
|
106
137
|
if (this.#date)
|
|
107
138
|
return this.#date;
|
|
108
|
-
const dh = this.
|
|
139
|
+
const dh = this.getHeaderString('date');
|
|
109
140
|
if (dh)
|
|
110
141
|
this.#date = new Date(dh);
|
|
111
142
|
return this.#date;
|
|
@@ -125,7 +156,7 @@ export class CacheEntry {
|
|
|
125
156
|
get cacheControl() {
|
|
126
157
|
if (this.#cacheControl)
|
|
127
158
|
return this.#cacheControl;
|
|
128
|
-
const cc = this.
|
|
159
|
+
const cc = this.getHeaderString('cache-control');
|
|
129
160
|
this.#cacheControl = cc ? ccp.parse(cc) : {};
|
|
130
161
|
return this.#cacheControl;
|
|
131
162
|
}
|
|
@@ -145,8 +176,7 @@ export class CacheEntry {
|
|
|
145
176
|
get contentType() {
|
|
146
177
|
if (this.#contentType !== undefined)
|
|
147
178
|
return this.#contentType;
|
|
148
|
-
this.#contentType =
|
|
149
|
-
this.getHeader('content-type')?.toString() ?? '';
|
|
179
|
+
this.#contentType = this.getHeaderString('content-type') ?? '';
|
|
150
180
|
return this.#contentType;
|
|
151
181
|
}
|
|
152
182
|
/**
|
|
@@ -175,9 +205,22 @@ export class CacheEntry {
|
|
|
175
205
|
this.date.getTime() + this.maxAge * 1000 > Date.now();
|
|
176
206
|
return this.#valid;
|
|
177
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* Add contents to the entry body.
|
|
210
|
+
*/
|
|
178
211
|
addBody(b) {
|
|
179
|
-
|
|
180
|
-
|
|
212
|
+
// when the content length is uknown we store each chunk in an array that
|
|
213
|
+
// later on is concatenate into a single buffer, otherwise we just append
|
|
214
|
+
// the new chunk of bytes to the already allocated buffer keeping track
|
|
215
|
+
// of the current offset in the `this.#bodyLength` property.
|
|
216
|
+
if (!this.#body) {
|
|
217
|
+
this.#bodyParts.push(b);
|
|
218
|
+
this.#bodyLength += b.byteLength;
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
this.#body.set(b, this.#bodyLength);
|
|
222
|
+
this.#bodyLength += b.byteLength;
|
|
223
|
+
}
|
|
181
224
|
}
|
|
182
225
|
get statusCode() {
|
|
183
226
|
return this.#statusCode;
|
|
@@ -185,6 +228,23 @@ export class CacheEntry {
|
|
|
185
228
|
get headers() {
|
|
186
229
|
return this.#headers;
|
|
187
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Returns the body as a single Uint8Array, concatenating parts if needed.
|
|
233
|
+
*/
|
|
234
|
+
get _body() {
|
|
235
|
+
// if the body is known we'll just use that
|
|
236
|
+
if (this.#body)
|
|
237
|
+
return this.#body;
|
|
238
|
+
// otherwise we concatenate the body parts into a single buffer
|
|
239
|
+
const buffer = new ArrayBuffer(this.#bodyLength);
|
|
240
|
+
const b = new Uint8Array(buffer, 0, this.#bodyLength);
|
|
241
|
+
let off = 0;
|
|
242
|
+
for (const part of this.#bodyParts) {
|
|
243
|
+
b.set(part, off);
|
|
244
|
+
off += part.byteLength;
|
|
245
|
+
}
|
|
246
|
+
return b;
|
|
247
|
+
}
|
|
188
248
|
/**
|
|
189
249
|
* Check that the sri integrity string that was provided to the ctor
|
|
190
250
|
* matches the body that we actually received. This should only be called
|
|
@@ -216,8 +276,7 @@ export class CacheEntry {
|
|
|
216
276
|
if (this.#integrityActual)
|
|
217
277
|
return this.#integrityActual;
|
|
218
278
|
const hash = createHash('sha512');
|
|
219
|
-
|
|
220
|
-
hash.update(buf);
|
|
279
|
+
hash.update(this._body);
|
|
221
280
|
const i = `sha512-${hash.digest('base64')}`;
|
|
222
281
|
this.integrityActual = i;
|
|
223
282
|
return i;
|
|
@@ -242,6 +301,15 @@ export class CacheEntry {
|
|
|
242
301
|
getHeader(h) {
|
|
243
302
|
return getRawHeader(this.#headers, h);
|
|
244
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* Give it a key, and it'll return the decoded string of that header value
|
|
306
|
+
*/
|
|
307
|
+
getHeaderString(h) {
|
|
308
|
+
const value = getRawHeader(this.#headers, h);
|
|
309
|
+
if (value) {
|
|
310
|
+
return getDecodedValue(value);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
245
313
|
/**
|
|
246
314
|
* Set a header to a specific value
|
|
247
315
|
*/
|
|
@@ -252,14 +320,7 @@ export class CacheEntry {
|
|
|
252
320
|
* Return the body of the entry as a Buffer
|
|
253
321
|
*/
|
|
254
322
|
buffer() {
|
|
255
|
-
|
|
256
|
-
if (!b)
|
|
257
|
-
return Buffer.allocUnsafe(0);
|
|
258
|
-
if (this.#body.length === 1)
|
|
259
|
-
return b;
|
|
260
|
-
const cat = Buffer.concat(this.#body, this.#bodyLength);
|
|
261
|
-
this.#body = [cat];
|
|
262
|
-
return cat;
|
|
323
|
+
return Buffer.from(this._body.buffer, this._body.byteOffset, this._body.byteLength);
|
|
263
324
|
}
|
|
264
325
|
// return the buffer if it's a tarball, or the parsed
|
|
265
326
|
// JSON if it's not.
|
|
@@ -270,7 +331,7 @@ export class CacheEntry {
|
|
|
270
331
|
get isJSON() {
|
|
271
332
|
if (this.#isJSON !== undefined)
|
|
272
333
|
return this.#isJSON;
|
|
273
|
-
const ct = this.
|
|
334
|
+
const ct = this.getHeaderString('content-type');
|
|
274
335
|
// if it says it's json, assume json
|
|
275
336
|
if (ct)
|
|
276
337
|
return (this.#isJSON = /\bjson\b/.test(ct));
|
|
@@ -288,10 +349,10 @@ export class CacheEntry {
|
|
|
288
349
|
get isGzip() {
|
|
289
350
|
if (this.#isGzip !== undefined)
|
|
290
351
|
return this.#isGzip;
|
|
291
|
-
const ce = this.
|
|
352
|
+
const ce = this.getHeaderString('content-encoding');
|
|
292
353
|
if (ce && !/\bgzip\b/.test(ce))
|
|
293
354
|
return (this.#isGzip = false);
|
|
294
|
-
const buf = this.
|
|
355
|
+
const buf = this._body;
|
|
295
356
|
if (buf.length < 2)
|
|
296
357
|
return false;
|
|
297
358
|
this.#isGzip = buf[0] === 0x1f && buf[1] === 0x8b;
|
|
@@ -314,14 +375,16 @@ export class CacheEntry {
|
|
|
314
375
|
// we know that if we know it's gzip, that the body has been
|
|
315
376
|
// flattened to a single buffer, so save the extra call.
|
|
316
377
|
/* c8 ignore start */
|
|
317
|
-
if (this
|
|
378
|
+
if (this._body.length === 0)
|
|
318
379
|
throw error('Invalid buffer, cant unzip');
|
|
319
380
|
/* c8 ignore stop */
|
|
320
|
-
const b = gunzipSync(this
|
|
381
|
+
const b = gunzipSync(this._body);
|
|
321
382
|
this.setHeader('content-encoding', 'identity');
|
|
322
|
-
|
|
323
|
-
this.#
|
|
324
|
-
this
|
|
383
|
+
const u8 = new Uint8Array(b.buffer, b.byteOffset, b.byteLength);
|
|
384
|
+
this.#body = u8;
|
|
385
|
+
this.#bodyLength = u8.byteLength;
|
|
386
|
+
this.#contentLength = u8.byteLength;
|
|
387
|
+
this.setHeader('content-length', String(this.#contentLength));
|
|
325
388
|
this.#isGzip = false;
|
|
326
389
|
return true;
|
|
327
390
|
}
|
|
@@ -333,7 +396,7 @@ export class CacheEntry {
|
|
|
333
396
|
*/
|
|
334
397
|
text() {
|
|
335
398
|
this.unzip();
|
|
336
|
-
return this.
|
|
399
|
+
return getDecodedValue(this._body);
|
|
337
400
|
}
|
|
338
401
|
/**
|
|
339
402
|
* Parse the entry body as JSON and return the result
|
|
@@ -359,9 +422,9 @@ export class CacheEntry {
|
|
|
359
422
|
if (buffer.length < headSize) {
|
|
360
423
|
return emptyCacheEntry;
|
|
361
424
|
}
|
|
362
|
-
const statusCode = Number(buffer.subarray(4, 7)
|
|
425
|
+
const statusCode = Number(getDecodedValue(buffer.subarray(4, 7)));
|
|
363
426
|
const headersBuffer = buffer.subarray(7, headSize);
|
|
364
|
-
// walk through the headers array, building up the rawHeaders
|
|
427
|
+
// walk through the headers array, building up the rawHeaders
|
|
365
428
|
const headers = [];
|
|
366
429
|
let i = 0;
|
|
367
430
|
let integrity = undefined;
|
|
@@ -369,20 +432,21 @@ export class CacheEntry {
|
|
|
369
432
|
const size = readSize(headersBuffer, i);
|
|
370
433
|
const val = headersBuffer.subarray(i + 4, i + size);
|
|
371
434
|
// if the last one was the key integrity, then this one is the value
|
|
372
|
-
if (headers.length % 2 === 1
|
|
373
|
-
|
|
374
|
-
|
|
435
|
+
if (headers.length % 2 === 1) {
|
|
436
|
+
const k = getDecodedValue(headers[headers.length - 1]).toLowerCase();
|
|
437
|
+
if (k === 'integrity')
|
|
438
|
+
integrity = getDecodedValue(val);
|
|
375
439
|
}
|
|
376
440
|
headers.push(val);
|
|
377
441
|
i += size;
|
|
378
442
|
}
|
|
379
443
|
const body = buffer.subarray(headSize);
|
|
380
444
|
const c = new CacheEntry(statusCode, setRawHeader(headers, 'content-length', String(body.byteLength)), {
|
|
445
|
+
body,
|
|
381
446
|
integrity,
|
|
382
447
|
trustIntegrity: true,
|
|
448
|
+
contentLength: body.byteLength,
|
|
383
449
|
});
|
|
384
|
-
c.#body = [body];
|
|
385
|
-
c.#bodyLength = body.byteLength;
|
|
386
450
|
if (c.isJSON) {
|
|
387
451
|
try {
|
|
388
452
|
c.json();
|
|
@@ -403,37 +467,52 @@ export class CacheEntry {
|
|
|
403
467
|
/**
|
|
404
468
|
* Encode the entry as a single Buffer for writing to the cache
|
|
405
469
|
*/
|
|
406
|
-
// TODO: should this maybe not concat, and just return Buffer[]?
|
|
407
|
-
// Then we can writev it to the cache file and save the memory copy
|
|
408
470
|
encode() {
|
|
409
471
|
if (this.isJSON)
|
|
410
472
|
this.json();
|
|
411
|
-
const
|
|
412
|
-
const
|
|
413
|
-
|
|
473
|
+
const statusStr = String(this.#statusCode);
|
|
474
|
+
const statusBytes = getEncondedValue(statusStr);
|
|
475
|
+
// compute headLength = 4 (length field itself) + statusBytes + Σ(4 + headerLen) for each header item
|
|
476
|
+
let headLength = 4 + statusBytes.byteLength;
|
|
477
|
+
for (const h of this.#headers)
|
|
478
|
+
headLength += 4 + h.byteLength;
|
|
479
|
+
// allocate and fill head length prefix (big-endian)
|
|
480
|
+
const headLenBytes = new Uint8Array(4);
|
|
481
|
+
headLenBytes[0] = (headLength >> 24) & 0xff;
|
|
482
|
+
headLenBytes[1] = (headLength >> 16) & 0xff;
|
|
483
|
+
headLenBytes[2] = (headLength >> 8) & 0xff;
|
|
484
|
+
headLenBytes[3] = headLength & 0xff;
|
|
485
|
+
// header chunks: [len, bytes] for each header item
|
|
486
|
+
const headerChunks = [];
|
|
414
487
|
for (const h of this.#headers) {
|
|
415
|
-
const
|
|
416
|
-
const
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
488
|
+
const l = headLenBytes.byteLength + h.byteLength;
|
|
489
|
+
const lb = new Uint8Array(4);
|
|
490
|
+
lb[0] = (l >> 24) & 0xff;
|
|
491
|
+
lb[1] = (l >> 16) & 0xff;
|
|
492
|
+
lb[2] = (l >> 8) & 0xff;
|
|
493
|
+
lb[3] = l & 0xff;
|
|
494
|
+
headerChunks.push(lb, h);
|
|
495
|
+
}
|
|
496
|
+
// total size
|
|
497
|
+
const total = headLenBytes.byteLength +
|
|
498
|
+
statusBytes.byteLength +
|
|
499
|
+
headerChunks.reduce((n, b) => n + b.byteLength, 0) +
|
|
500
|
+
this._body.byteLength;
|
|
501
|
+
// returns the concatenate buffer with all the pieces
|
|
502
|
+
const outBuffer = new ArrayBuffer(total);
|
|
503
|
+
const out = Buffer.from(outBuffer, 0, total);
|
|
504
|
+
let off = 0;
|
|
505
|
+
out.set(headLenBytes, off);
|
|
506
|
+
off += headLenBytes.byteLength;
|
|
507
|
+
out.set(statusBytes, off);
|
|
508
|
+
off += statusBytes.byteLength;
|
|
509
|
+
for (const chunk of headerChunks) {
|
|
510
|
+
out.set(chunk, off);
|
|
511
|
+
off += chunk.byteLength;
|
|
425
512
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
(headLength >> 24) & 0xff,
|
|
429
|
-
(headLength >> 16) & 0xff,
|
|
430
|
-
(headLength >> 8) & 0xff,
|
|
431
|
-
headLength & 0xff,
|
|
432
|
-
], 0);
|
|
433
|
-
chunks.unshift(hlBuf);
|
|
434
|
-
chunks.push(...this.#body);
|
|
435
|
-
return Buffer.concat(chunks, headLength + this.#bodyLength);
|
|
513
|
+
out.set(this._body, off);
|
|
514
|
+
return out;
|
|
436
515
|
}
|
|
437
516
|
}
|
|
438
|
-
const emptyCacheEntry = new CacheEntry(0, []);
|
|
517
|
+
const emptyCacheEntry = new CacheEntry(0, [], { contentLength: 0 });
|
|
439
518
|
//# sourceMappingURL=cache-entry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-entry.js","sourceRoot":"","sources":["../../src/cache-entry.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,EAAE;AACF,4EAA4E;AAC5E,yDAAyD;AACzD,EAAE;AACF,sBAAsB;AACtB,EAAE;AACF,gBAAgB;AAChB,yBAAyB;AACzB,YAAY;AACZ,SAAS;AACT,EAAE;AACF,0EAA0E;AAC1E,+CAA+C;AAC/C,EAAE;AACF,8EAA8E;AAC9E,4DAA4D;AAC5D,EAAE;AACF,2EAA2E;AAC3E,eAAe;AAGf,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAE3C,OAAO,GAAG,MAAM,sBAAsB,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAI5D,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAE,MAAc,EAAE,EAAE;IAC/C,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAA;IACrB,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACzB,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACzB,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAEzB,oCAAoC;IACpC,qBAAqB;IACrB,IACE,CAAC,KAAK,SAAS;QACf,CAAC,KAAK,SAAS;QACf,CAAC,KAAK,SAAS;QACf,CAAC,KAAK,SAAS,EACf,CAAC;QACD,MAAM,KAAK,CAAC,6CAA6C,EAAE;YACzD,KAAK,EAAE,GAAG,CAAC,MAAM;SAClB,CAAC,CAAA;IACJ,CAAC;IACD,oBAAoB;IAEpB,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;AAC7C,CAAC,CAAA;AAED,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;AAmC/D,MAAM,OAAO,UAAU;IACrB,WAAW,CAAQ;IACnB,QAAQ,CAAU;IAClB,KAAK,GAAa,EAAE,CAAA;IACpB,WAAW,GAAG,CAAC,CAAA;IACf,UAAU,CAAY;IACtB,gBAAgB,CAAY;IAC5B,KAAK,CAAU;IACf,eAAe,CAAA;IACf,2BAA2B,CAAA;IAE3B,YACE,UAAkB,EAClB,OAAiB,EACjB,EACE,SAAS,EACT,cAAc,GAAG,KAAK,EACtB,+BAA+B,EAC7B,0BAA0B,GAAG,EAAE,MACZ,EAAE;QAEzB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,WAAW,GAAG,UAAU,CAAA;QAC7B,IAAI,CAAC,eAAe,GAAG,cAAc,CAAA;QACrC,IAAI,CAAC,2BAA2B,GAAG,0BAA0B,CAAA;QAC7D,IAAI,SAAS;YAAE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;IAC3C,CAAC;IAED,IAAI,gBAAgB;QAClB,MAAM,GAAG,GAAuB,EAAE,CAAA;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACrD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;YACpC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YACxC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;QACtB,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,MAAM;QACJ,MAAM,EACJ,UAAU,EACV,KAAK,EACL,oBAAoB,EACpB,YAAY,EACZ,IAAI,EACJ,WAAW,EACX,SAAS,EACT,MAAM,EACN,MAAM,EACN,MAAM,GACP,GAAG,IAAI,CAAA;QACR,qBAAqB;QACrB,MAAM,GAAG,GACP,IAAI,CAAC,CAAC;YACJ,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;YAClD,CAAC,CAAC,SAAS,CAAA;QACb,MAAM,OAAO,GACX,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAClE,mBAAmB;QACnB,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC;YACb,UAAU;YACV,OAAO,EAAE,IAAI,CAAC,gBAAgB;YAC9B,WAAW;YACX,SAAS;YACT,IAAI;YACJ,OAAO;YACP,YAAY;YACZ,KAAK;YACL,oBAAoB;YACpB,GAAG;YACH,MAAM;YACN,MAAM;YACN,MAAM;SACP,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CACvC,CAAA;IACH,CAAC;IAED,CAAC,cAAc,CAAC,CAAC,KAAa,EAAE,OAAuB;QACrD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE;YACjC,KAAK;YACL,GAAG,OAAO;SACX,CAAC,CAAA;QACF,OAAO,sCAAsC,GAAG,EAAE,CAAA;IACpD,CAAC;IAED,KAAK,CAAO;IACZ,IAAI,IAAI;QACN,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC,KAAK,CAAA;QACjC,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAA;QAC7C,IAAI,EAAE;YAAE,IAAI,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;QACjC,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED,OAAO,CAAS;IAChB,IAAI,MAAM;QACR,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,OAAO,CAAA;QACnD,8CAA8C;QAC9C,yDAAyD;QACzD,4CAA4C;QAC5C,MAAM,EAAE,GAAG,IAAI,CAAC,YAAY,CAAA;QAC5B,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,GAAG,CAAA;QACrD,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,aAAa,CAAmB;IAChC,IAAI,YAAY;QACd,IAAI,IAAI,CAAC,aAAa;YAAE,OAAO,IAAI,CAAC,aAAa,CAAA;QACjD,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,QAAQ,EAAE,CAAA;QACtD,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAC5C,OAAO,IAAI,CAAC,aAAa,CAAA;IAC3B,CAAC;IAED,qBAAqB,CAAU;IAC/B,IAAI,oBAAoB;QACtB,IAAI,IAAI,CAAC,qBAAqB,KAAK,SAAS;YAC1C,OAAO,IAAI,CAAC,qBAAqB,CAAA;QACnC,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAA;QACzC,MAAM,GAAG,GACP,IAAI,CAAC,YAAY,CAAC,wBAAwB,CAAC;YAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,2BAA2B,CAAA;QAEhD,IAAI,CAAC,qBAAqB;YACxB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC/C,OAAO,IAAI,CAAC,qBAAqB,CAAA;IACnC,CAAC;IAED,YAAY,CAAS;IACrB,IAAI,WAAW;QACb,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,YAAY,CAAA;QAC7D,IAAI,CAAC,YAAY;YACf,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;QAClD,OAAO,IAAI,CAAC,YAAY,CAAA;IAC1B,CAAC;IAED;;;OAGG;IACH,MAAM,CAAU;IAChB,IAAI,KAAK;QACP,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,MAAM,CAAA;QAEjD,4BAA4B;QAC5B,IAAI,IAAI,CAAC,YAAY,CAAC,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;QAE5D,0DAA0D;QAC1D,8CAA8C;QAC9C,8CAA8C;QAC9C,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAA;QAC3B,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;QAE3D,8CAA8C;QAC9C,yDAAyD;QACzD,4CAA4C;QAC5C,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAA;QAC5C,IAAI,CAAC,MAAM;YACT,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACvD,OAAO,IAAI,CAAC,MAAM,CAAA;IACpB,CAAC;IAED,OAAO,CAAC,CAAS;QACf,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAClB,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,UAAU,CAAA;IAClC,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAA;IACzB,CAAC;IACD,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,cAAc,CACZ,UAA6B,EAAE;QAE/B,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO,KAAK,CAAA;QAClC,IAAI,IAAI,CAAC,eAAe,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;YAC7C,MAAM,KAAK,CAAC,yBAAyB,EAAE;gBACrC,IAAI,EAAE,YAAY;gBAClB,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,IAAI,CAAC,UAAU;gBACvB,KAAK,EAAE,IAAI,CAAC,eAAe;gBAC3B,GAAG,OAAO;aACX,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,eAAe;QACjB,IAAI,IAAI,CAAC,gBAAgB;YAAE,OAAO,IAAI,CAAC,gBAAgB,CAAA;QACvD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;QACjC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC9C,MAAM,CAAC,GAAc,UAAU,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAA;QACtD,IAAI,CAAC,eAAe,GAAG,CAAC,CAAA;QACxB,OAAO,CAAC,CAAA;IACV,CAAC;IAED,IAAI,eAAe,CAAC,CAAY;QAC9B,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAA;QACzB,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;IAChC,CAAC;IAED,IAAI,SAAS,CAAC,CAAwB;QACpC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,UAAU,GAAG,CAAC,CAAA;YACnB,IAAI,IAAI,CAAC,eAAe;gBAAE,IAAI,CAAC,eAAe,GAAG,CAAC,CAAA;QACpD,CAAC;IACH,CAAC;IACD,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,UAAU,CAAA;IACxB,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,CAAS;QACjB,OAAO,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;IACvC,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,CAAS,EAAE,KAAsB;QACzC,IAAI,CAAC,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;IACvD,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACvB,IAAI,CAAC,CAAC;YAAE,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;QACpC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAA;QACrC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;QACvD,IAAI,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAA;QAClB,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,qDAAqD;IACrD,oBAAoB;IACpB,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAA;IAClD,CAAC;IAED,OAAO,CAAU;IACjB,IAAI,MAAM;QACR,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,OAAO,CAAA;QACnD,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAA;QACrD,oCAAoC;QACpC,IAAI,EAAE;YAAE,OAAO,CAAC,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;QACxB,sDAAsD;QACtD,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAA;QACvB,4DAA4D;QAC5D,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QACnC,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,WAAW,CAAC,CAAA;QAC7D,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,OAAO,CAAU;IACjB,IAAI,MAAM;QACR,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,OAAO,CAAA;QACnD,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,EAAE,QAAQ,EAAE,CAAA;QACzD,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAA;QAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAA;QACzB,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,KAAK,CAAA;QAChC,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;QACjD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,SAAS,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAA;QAC5C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAA;YAC9C,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAA;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED;;;;OAIG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,4DAA4D;YAC5D,wDAAwD;YACxD,qBAAqB;YACrB,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI;gBACvB,MAAM,KAAK,CAAC,4BAA4B,CAAC,CAAA;YAC3C,oBAAoB;YACpB,MAAM,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;YACnC,IAAI,CAAC,SAAS,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAA;YAC9C,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAA;YAChB,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,UAAU,CAAA;YAC/B,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAA;YAC1D,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;YACpB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;;OAGG;IACH,IAAI;QACF,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAA;IACjC,CAAC;IAED;;OAEG;IACH,IAAI;QACF,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,KAAK,CAAA;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAY,CAAA;QAC/C,IAAI,CAAC,KAAK,GAAG,GAAG,CAAA;QAChB,OAAO,GAAG,CAAA;IACZ,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,MAAc;QAC1B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,OAAO,eAAe,CAAA;QACxB,CAAC;QACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACpC,IAAI,MAAM,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;YAC7B,OAAO,eAAe,CAAA;QACxB,CAAC;QACD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC3D,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;QAClD,sEAAsE;QACtE,MAAM,OAAO,GAAa,EAAE,CAAA;QAC5B,IAAI,CAAC,GAAG,CAAC,CAAA;QACT,IAAI,SAAS,GAA0B,SAAS,CAAA;QAChD,OAAO,CAAC,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,CAAA;YACvC,MAAM,GAAG,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAA;YACnD,oEAAoE;YACpE,IACE,OAAO,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC;gBACxB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,WAAW,EACnD,CAAC;gBACD,SAAS,GAAG,MAAM,CAAC,GAAG,CAAc,CAAA;YACtC,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACjB,CAAC,IAAI,IAAI,CAAA;QACX,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAEtC,MAAM,CAAC,GAAG,IAAI,UAAU,CACtB,UAAU,EACV,YAAY,CACV,OAAO,EACP,gBAAgB,EAChB,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CACxB,EACD;YACE,SAAS;YACT,cAAc,EAAE,IAAI;SACrB,CACF,CAAA;QAED,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,CAAA;QAChB,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAA;QAC/B,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,CAAC,CAAC,IAAI,EAAE,CAAA;YACV,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,eAAe,CAAA;YACxB,CAAC;QACH,CAAC;QACD,OAAO,CAAC,CAAA;IACV,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,MAAc;QAC/B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,KAAK,CAAA;QACnC,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACpC,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAA;QACzD,OAAO,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IACvD,CAAC;IAED;;OAEG;IACH,gEAAgE;IAChE,mEAAmE;IACnE,MAAM;QACJ,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,EAAE,CAAA;QAC5B,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAA;QAChD,MAAM,MAAM,GAAa,CAAC,EAAE,CAAC,CAAA;QAC7B,IAAI,UAAU,GAAG,EAAE,CAAC,UAAU,GAAG,CAAC,CAAA;QAClC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;YACnC,MAAM,EAAE,GAAG,CAAC,CAAC,UAAU,GAAG,CAAC,CAAA;YAC3B,UAAU,IAAI,EAAE,CAAA;YAChB,KAAK,CAAC,GAAG,CACP;gBACE,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;gBACjB,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;gBACjB,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI;gBAChB,EAAE,GAAG,IAAI;aACV,EACD,CAAC,CACF,CAAA;YACD,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QACvB,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;QACnC,KAAK,CAAC,GAAG,CACP;YACE,CAAC,UAAU,IAAI,EAAE,CAAC,GAAG,IAAI;YACzB,CAAC,UAAU,IAAI,EAAE,CAAC,GAAG,IAAI;YACzB,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,IAAI;YACxB,UAAU,GAAG,IAAI;SAClB,EACD,CAAC,CACF,CAAA;QACD,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QACrB,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;QAC1B,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,CAAA;IAC7D,CAAC;CACF;AAED,MAAM,eAAe,GAAG,IAAI,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA","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 { ErrorCauseOptions } 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 'node:crypto'\nimport type { InspectOptions } from 'node:util'\nimport { inspect } from 'node:util'\nimport { gunzipSync } from 'node: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 /**\n * If the server does not serve a `stale-while-revalidate` value in the\n * `cache-control` header, then this multiplier is applied to the `max-age`\n * or `s-maxage` values.\n *\n * By default, this is `60`, so for example a response that is cacheable for\n * 5 minutes will allow a stale response while revalidating for up to 5\n * hours.\n *\n * If the server *does* provide a `stale-while-revalidate` value, then that\n * is always used.\n *\n * Set to 0 to prevent any `stale-while-revalidate` behavior unless\n * explicitly allowed by the server's `cache-control` header.\n */\n 'stale-while-revalidate-factor'?: number\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 #staleWhileRevalidateFactor\n\n constructor(\n statusCode: number,\n headers: Buffer[],\n {\n integrity,\n trustIntegrity = false,\n 'stale-while-revalidate-factor':\n staleWhileRevalidateFactor = 60,\n }: CacheEntryOptions = {},\n ) {\n this.#headers = headers\n this.#statusCode = statusCode\n this.#trustIntegrity = trustIntegrity\n this.#staleWhileRevalidateFactor = staleWhileRevalidateFactor\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 toJSON() {\n const {\n statusCode,\n valid,\n staleWhileRevalidate,\n cacheControl,\n date,\n contentType,\n integrity,\n maxAge,\n isGzip,\n isJSON,\n } = this\n /* c8 ignore start */\n const age =\n date ?\n Math.floor((Date.now() - date.getTime()) / 1000)\n : undefined\n const expires =\n date ? new Date(date.getTime() + this.maxAge * 1000) : undefined\n /* c8 ignore end */\n return Object.fromEntries(\n Object.entries({\n statusCode,\n headers: this.#headersAsObject,\n contentType,\n integrity,\n date,\n expires,\n cacheControl,\n valid,\n staleWhileRevalidate,\n age,\n maxAge,\n isGzip,\n isJSON,\n }).filter(([_, v]) => v !== undefined),\n )\n }\n\n [kCustomInspect](depth: number, options: InspectOptions): string {\n const str = inspect(this.toJSON(), {\n depth,\n ...options,\n })\n return `@vltpkg/registry-client.CacheEntry ${str}`\n }\n\n #date?: Date\n get date(): Date | undefined {\n if (this.#date) return this.#date\n const dh = this.getHeader('date')?.toString()\n if (dh) this.#date = new Date(dh)\n return this.#date\n }\n\n #maxAge?: number\n get maxAge(): number {\n if (this.#maxAge !== undefined) return this.#maxAge\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 cc = this.cacheControl\n this.#maxAge = cc['max-age'] || cc['s-maxage'] || 300\n return this.#maxAge\n }\n\n #cacheControl?: ccp.CacheControl\n get cacheControl(): ccp.CacheControl {\n if (this.#cacheControl) return this.#cacheControl\n const cc = this.getHeader('cache-control')?.toString()\n this.#cacheControl = cc ? ccp.parse(cc) : {}\n return this.#cacheControl\n }\n\n #staleWhileRevalidate?: boolean\n get staleWhileRevalidate(): boolean {\n if (this.#staleWhileRevalidate !== undefined)\n return this.#staleWhileRevalidate\n if (this.valid || !this.date) return true\n const swv =\n this.cacheControl['stale-while-revalidate'] ??\n this.maxAge * this.#staleWhileRevalidateFactor\n\n this.#staleWhileRevalidate =\n this.date.getTime() + swv * 1000 > Date.now()\n return this.#staleWhileRevalidate\n }\n\n #contentType?: string\n get contentType() {\n if (this.#contentType !== undefined) return this.#contentType\n this.#contentType =\n this.getHeader('content-type')?.toString() ?? ''\n return this.#contentType\n }\n\n /**\n * `true` if the entry represents a cached response that is still\n * valid to use.\n */\n #valid?: boolean\n get valid(): boolean {\n if (this.#valid !== undefined) return this.#valid\n\n // immutable = never changes\n if (this.cacheControl.immutable) return (this.#valid = 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 const ct = this.contentType\n if (ct && !/\\bjson\\b/.test(ct)) return (this.#valid = 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 if (!this.date) return (this.#valid = false)\n this.#valid =\n this.date.getTime() + this.maxAge * 1000 > Date.now()\n return this.#valid\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: ErrorCauseOptions = {},\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 text = this.text()\n const obj = JSON.parse(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
|
+
{"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 { ErrorCauseOptions } 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 'node:crypto'\nimport type { InspectOptions } from 'node:util'\nimport { inspect } from 'node:util'\nimport { gunzipSync } from 'node:zlib'\nimport { getRawHeader, setRawHeader } from './raw-header.ts'\nimport {\n getDecodedValue,\n getEncondedValue,\n} from './string-encoding.ts'\n\nexport type JSONObj = Record<string, JSONField>\n\nconst readSize = (buf: Uint8Array, 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 * An optional body to use.\n *\n * This is used when decoding a cache entry from a buffer, and the body\n * is already in a ArrayBuffer we can use. When this option is\n * provided the `addBody` method should not be used.\n */\n body?: Uint8Array\n\n /**\n * An optional content length of the body to use, if undefined the\n * content-length header will be used.\n */\n contentLength?: number\n\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 /**\n * If the server does not serve a `stale-while-revalidate` value in the\n * `cache-control` header, then this multiplier is applied to the `max-age`\n * or `s-maxage` values.\n *\n * By default, this is `60`, so for example a response that is cacheable for\n * 5 minutes will allow a stale response while revalidating for up to 5\n * hours.\n *\n * If the server *does* provide a `stale-while-revalidate` value, then that\n * is always used.\n *\n * Set to 0 to prevent any `stale-while-revalidate` behavior unless\n * explicitly allowed by the server's `cache-control` header.\n */\n 'stale-while-revalidate-factor'?: number\n}\n\nexport class CacheEntry {\n #statusCode: number\n /** The raw headers as an array of buffers */\n #headers: Uint8Array[]\n /** The body buffer, used if the content length is known. */\n #body?: Uint8Array\n /**\n * If the content length is unknown we save the body in multiple parts\n * in order to only concatenate once at the end and save extra memory copies.\n */\n #bodyParts: Uint8Array[] = []\n /** Used to track the length of the body while reading chunks */\n #bodyLength = 0\n /** The total length of the body, if known */\n #contentLength?: number\n #integrity?: Integrity\n #integrityActual?: Integrity\n #json?: JSONObj\n #trustIntegrity\n #staleWhileRevalidateFactor\n\n constructor(\n statusCode: number,\n headers: Uint8Array[],\n {\n body,\n integrity,\n trustIntegrity = false,\n 'stale-while-revalidate-factor':\n staleWhileRevalidateFactor = 60,\n contentLength,\n }: CacheEntryOptions = {},\n ) {\n this.#headers = headers\n this.#statusCode = statusCode\n this.#trustIntegrity = trustIntegrity\n this.#staleWhileRevalidateFactor = staleWhileRevalidateFactor\n if (integrity) this.integrity = integrity\n\n // if content-legnth is known then we'll only allocate that much memory\n // and we'll avoid copying memory around when adding new chunks.\n if (contentLength != null && typeof contentLength === 'number') {\n this.#contentLength = contentLength\n }\n\n // if a body is provided then use that, in this case the `addBody`\n // method should no longer be used.\n if (body) {\n const buffer = new ArrayBuffer(body.byteLength)\n this.#body = new Uint8Array(buffer, 0, body.byteLength)\n this.#body.set(body, 0)\n this.#bodyLength = body.byteLength\n /* c8 ignore start */\n } else if (this.#contentLength) {\n const buffer = new ArrayBuffer(this.#contentLength)\n this.#body = new Uint8Array(buffer, 0, this.#contentLength)\n this.#bodyLength = 0\n }\n /* c8 ignore stop */\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 = getDecodedValue(this.#headers[i])\n const val = getDecodedValue(this.#headers[i + 1])\n ret.push([key, val])\n }\n return ret\n }\n\n toJSON() {\n const {\n statusCode,\n valid,\n staleWhileRevalidate,\n cacheControl,\n date,\n contentType,\n integrity,\n maxAge,\n isGzip,\n isJSON,\n } = this\n /* c8 ignore start */\n const age =\n date ?\n Math.floor((Date.now() - date.getTime()) / 1000)\n : undefined\n const expires =\n date ? new Date(date.getTime() + this.maxAge * 1000) : undefined\n /* c8 ignore end */\n return Object.fromEntries(\n Object.entries({\n statusCode,\n headers: this.#headersAsObject,\n contentType,\n integrity,\n date,\n expires,\n cacheControl,\n valid,\n staleWhileRevalidate,\n age,\n maxAge,\n isGzip,\n isJSON,\n }).filter(([_, v]) => v !== undefined),\n )\n }\n\n [kCustomInspect](depth: number, options: InspectOptions): string {\n const str = inspect(this.toJSON(), {\n depth,\n ...options,\n })\n return `@vltpkg/registry-client.CacheEntry ${str}`\n }\n\n #date?: Date\n get date(): Date | undefined {\n if (this.#date) return this.#date\n const dh = this.getHeaderString('date')\n if (dh) this.#date = new Date(dh)\n return this.#date\n }\n\n #maxAge?: number\n get maxAge(): number {\n if (this.#maxAge !== undefined) return this.#maxAge\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 cc = this.cacheControl\n this.#maxAge = cc['max-age'] || cc['s-maxage'] || 300\n return this.#maxAge\n }\n\n #cacheControl?: ccp.CacheControl\n get cacheControl(): ccp.CacheControl {\n if (this.#cacheControl) return this.#cacheControl\n const cc = this.getHeaderString('cache-control')\n this.#cacheControl = cc ? ccp.parse(cc) : {}\n return this.#cacheControl\n }\n\n #staleWhileRevalidate?: boolean\n get staleWhileRevalidate(): boolean {\n if (this.#staleWhileRevalidate !== undefined)\n return this.#staleWhileRevalidate\n if (this.valid || !this.date) return true\n const swv =\n this.cacheControl['stale-while-revalidate'] ??\n this.maxAge * this.#staleWhileRevalidateFactor\n\n this.#staleWhileRevalidate =\n this.date.getTime() + swv * 1000 > Date.now()\n return this.#staleWhileRevalidate\n }\n\n #contentType?: string\n get contentType() {\n if (this.#contentType !== undefined) return this.#contentType\n this.#contentType = this.getHeaderString('content-type') ?? ''\n return this.#contentType\n }\n\n /**\n * `true` if the entry represents a cached response that is still\n * valid to use.\n */\n #valid?: boolean\n get valid(): boolean {\n if (this.#valid !== undefined) return this.#valid\n\n // immutable = never changes\n if (this.cacheControl.immutable) return (this.#valid = 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 const ct = this.contentType\n if (ct && !/\\bjson\\b/.test(ct)) return (this.#valid = 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 if (!this.date) return (this.#valid = false)\n this.#valid =\n this.date.getTime() + this.maxAge * 1000 > Date.now()\n return this.#valid\n }\n\n /**\n * Add contents to the entry body.\n */\n addBody(b: Uint8Array) {\n // when the content length is uknown we store each chunk in an array that\n // later on is concatenate into a single buffer, otherwise we just append\n // the new chunk of bytes to the already allocated buffer keeping track\n // of the current offset in the `this.#bodyLength` property.\n if (!this.#body) {\n this.#bodyParts.push(b)\n this.#bodyLength += b.byteLength\n } else {\n this.#body.set(b, this.#bodyLength)\n this.#bodyLength += b.byteLength\n }\n }\n\n get statusCode() {\n return this.#statusCode\n }\n get headers(): Uint8Array[] {\n return this.#headers\n }\n\n /**\n * Returns the body as a single Uint8Array, concatenating parts if needed.\n */\n get _body(): Uint8Array {\n // if the body is known we'll just use that\n if (this.#body) return this.#body\n // otherwise we concatenate the body parts into a single buffer\n const buffer = new ArrayBuffer(this.#bodyLength)\n const b = new Uint8Array(buffer, 0, this.#bodyLength)\n let off = 0\n for (const part of this.#bodyParts) {\n b.set(part, off)\n off += part.byteLength\n }\n return b\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: ErrorCauseOptions = {},\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 hash.update(this._body)\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): Uint8Array | undefined {\n return getRawHeader(this.#headers, h)\n }\n\n /**\n * Give it a key, and it'll return the decoded string of that header value\n */\n getHeaderString(h: string): string | undefined {\n const value = getRawHeader(this.#headers, h)\n if (value) {\n return getDecodedValue(value)\n }\n }\n\n /**\n * Set a header to a specific value\n */\n setHeader(h: string, value: Uint8Array | 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 return Buffer.from(\n this._body.buffer,\n this._body.byteOffset,\n this._body.byteLength,\n )\n }\n\n // return the buffer if it's a tarball, or the parsed\n // JSON if it's not.\n get body(): Uint8Array | 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.getHeaderString('content-type')\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.getHeaderString('content-encoding')\n if (ce && !/\\bgzip\\b/.test(ce)) return (this.#isGzip = false)\n const buf = this._body\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.length === 0)\n throw error('Invalid buffer, cant unzip')\n /* c8 ignore stop */\n const b = gunzipSync(this._body)\n this.setHeader('content-encoding', 'identity')\n const u8 = new Uint8Array(b.buffer, b.byteOffset, b.byteLength)\n this.#body = u8\n this.#bodyLength = u8.byteLength\n this.#contentLength = u8.byteLength\n this.setHeader('content-length', String(this.#contentLength))\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 getDecodedValue(this._body)\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 text = this.text()\n const obj = JSON.parse(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: Uint8Array): 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(getDecodedValue(buffer.subarray(4, 7)))\n const headersBuffer = buffer.subarray(7, headSize)\n // walk through the headers array, building up the rawHeaders\n const headers: Uint8Array[] = []\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 (headers.length % 2 === 1) {\n const k = getDecodedValue(\n headers[headers.length - 1],\n ).toLowerCase()\n if (k === 'integrity')\n integrity = getDecodedValue(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 body,\n integrity,\n trustIntegrity: true,\n contentLength: body.byteLength,\n },\n )\n\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: Uint8Array): 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 encode(): Buffer {\n if (this.isJSON) this.json()\n const statusStr = String(this.#statusCode)\n const statusBytes = getEncondedValue(statusStr)\n\n // compute headLength = 4 (length field itself) + statusBytes + Σ(4 + headerLen) for each header item\n let headLength = 4 + statusBytes.byteLength\n for (const h of this.#headers) headLength += 4 + h.byteLength\n\n // allocate and fill head length prefix (big-endian)\n const headLenBytes = new Uint8Array(4)\n headLenBytes[0] = (headLength >> 24) & 0xff\n headLenBytes[1] = (headLength >> 16) & 0xff\n headLenBytes[2] = (headLength >> 8) & 0xff\n headLenBytes[3] = headLength & 0xff\n\n // header chunks: [len, bytes] for each header item\n const headerChunks: Uint8Array[] = []\n for (const h of this.#headers) {\n const l = headLenBytes.byteLength + h.byteLength\n const lb = new Uint8Array(4)\n lb[0] = (l >> 24) & 0xff\n lb[1] = (l >> 16) & 0xff\n lb[2] = (l >> 8) & 0xff\n lb[3] = l & 0xff\n headerChunks.push(lb, h)\n }\n\n // total size\n const total =\n headLenBytes.byteLength +\n statusBytes.byteLength +\n headerChunks.reduce((n, b) => n + b.byteLength, 0) +\n this._body.byteLength\n\n // returns the concatenate buffer with all the pieces\n const outBuffer = new ArrayBuffer(total)\n const out = Buffer.from(outBuffer, 0, total)\n let off = 0\n out.set(headLenBytes, off)\n off += headLenBytes.byteLength\n out.set(statusBytes, off)\n off += statusBytes.byteLength\n for (const chunk of headerChunks) {\n out.set(chunk, off)\n off += chunk.byteLength\n }\n out.set(this._body, off)\n return out\n }\n}\n\nconst emptyCacheEntry = new CacheEntry(0, [], { contentLength: 0 })\n"]}
|
|
@@ -2,7 +2,7 @@ export const handle304Response = (resp, entry) => {
|
|
|
2
2
|
if (resp.statusCode !== 304 || !entry)
|
|
3
3
|
return false;
|
|
4
4
|
const d = String(resp.headers.date ?? '') || new Date().toUTCString();
|
|
5
|
-
entry.setHeader('date',
|
|
5
|
+
entry.setHeader('date', d);
|
|
6
6
|
// shouldn't have a body, but just in case.
|
|
7
7
|
resp.body.resume();
|
|
8
8
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handle-304-response.js","sourceRoot":"","sources":["../../src/handle-304-response.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,IAA6B,EAC7B,KAAkB,EACG,EAAE;IACvB,IAAI,IAAI,CAAC,UAAU,KAAK,GAAG,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IAEnD,MAAM,CAAC,GACL,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC7D,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"handle-304-response.js","sourceRoot":"","sources":["../../src/handle-304-response.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,IAA6B,EAC7B,KAAkB,EACG,EAAE;IACvB,IAAI,IAAI,CAAC,UAAU,KAAK,GAAG,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IAEnD,MAAM,CAAC,GACL,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC7D,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAC1B,2CAA2C;IAC3C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAA;IAClB,OAAO,IAAI,CAAA;AACb,CAAC,CAAA","sourcesContent":["import type { Dispatcher } from 'undici'\nimport type { CacheEntry } from './cache-entry.ts'\n\nexport const handle304Response = (\n resp: Dispatcher.ResponseData,\n entry?: CacheEntry,\n): entry is CacheEntry => {\n if (resp.statusCode !== 304 || !entry) return false\n\n const d =\n String(resp.headers.date ?? '') || new Date().toUTCString()\n entry.setHeader('date', d)\n // shouldn't have a body, but just in case.\n resp.body.resume()\n return true\n}\n"]}
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAKrC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAM9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,EAAS,UAAU,EAAE,MAAM,QAAQ,CAAA;AAE1C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EACL,WAAW,EACX,KAAK,EAEL,OAAO,EACP,SAAS,EACT,QAAQ,EACT,MAAM,WAAW,CAAA;AAClB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAO7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/index.js
CHANGED
|
@@ -20,6 +20,7 @@ import { isRedirect, redirect } from "./redirect.js";
|
|
|
20
20
|
import { setCacheHeaders } from "./set-cache-headers.js";
|
|
21
21
|
import { getTokenResponse } from "./token-response.js";
|
|
22
22
|
import { getWebAuthChallenge } from "./web-auth-challenge.js";
|
|
23
|
+
import { getEncondedValue } from "./string-encoding.js";
|
|
23
24
|
export { CacheEntry, deleteToken, getKC, isToken, keychains, setToken, };
|
|
24
25
|
export const isCacheableMethod = (m) => m === 'GET' || m === 'HEAD';
|
|
25
26
|
const { version } = loadPackageJson(import.meta.filename, process.env.__VLT_INTERNAL_REGISTRY_CLIENT_PACKAGE_JSON);
|
|
@@ -186,8 +187,8 @@ export class RegistryClient {
|
|
|
186
187
|
});
|
|
187
188
|
const { signal } = options;
|
|
188
189
|
if (response.statusCode === 202) {
|
|
189
|
-
const rt = response.
|
|
190
|
-
const retryAfter = rt ? Number(rt
|
|
190
|
+
const rt = response.getHeaderString('retry-after');
|
|
191
|
+
const retryAfter = rt ? Number(rt) : -1;
|
|
191
192
|
if (retryAfter > 0) {
|
|
192
193
|
await setTimeout(retryAfter * 1000, null, { signal });
|
|
193
194
|
}
|
|
@@ -266,7 +267,9 @@ export class RegistryClient {
|
|
|
266
267
|
result.checkIntegrity({ url });
|
|
267
268
|
}
|
|
268
269
|
if (useCache) {
|
|
269
|
-
|
|
270
|
+
// Get the encoded buffer from the cache entry
|
|
271
|
+
const buffer = result.encode();
|
|
272
|
+
this.cache.set(key, Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength), {
|
|
270
273
|
integrity: result.integrity,
|
|
271
274
|
});
|
|
272
275
|
}
|
|
@@ -284,11 +287,11 @@ export class RegistryClient {
|
|
|
284
287
|
for (const [key, value] of Object.entries(response.headers)) {
|
|
285
288
|
/* c8 ignore start - theoretical */
|
|
286
289
|
if (Array.isArray(value)) {
|
|
287
|
-
h.push(
|
|
290
|
+
h.push(getEncondedValue(key), getEncondedValue(value.join(', ')));
|
|
288
291
|
/* c8 ignore stop */
|
|
289
292
|
}
|
|
290
293
|
else if (typeof value === 'string') {
|
|
291
|
-
h.push(
|
|
294
|
+
h.push(getEncondedValue(key), getEncondedValue(value));
|
|
292
295
|
}
|
|
293
296
|
}
|
|
294
297
|
const { integrity, trustIntegrity } = options;
|
|
@@ -298,6 +301,9 @@ export class RegistryClient {
|
|
|
298
301
|
integrity,
|
|
299
302
|
trustIntegrity,
|
|
300
303
|
'stale-while-revalidate-factor': this.staleWhileRevalidateFactor,
|
|
304
|
+
contentLength: response.headers['content-length'] ?
|
|
305
|
+
Number(response.headers['content-length'])
|
|
306
|
+
: /* c8 ignore next */ undefined,
|
|
301
307
|
});
|
|
302
308
|
if (isRedirect(result)) {
|
|
303
309
|
response.body.resume();
|
package/dist/esm/index.js.map
CHANGED
|
@@ -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 as cacheUnzipRegister } from '@vltpkg/cache-unzip'\nimport { error } from '@vltpkg/error-cause'\nimport { asError } from '@vltpkg/types'\nimport { logRequest } from '@vltpkg/output'\nimport type { Integrity } from '@vltpkg/types'\nimport { urlOpen } from '@vltpkg/url-open'\nimport { XDG } from '@vltpkg/xdg'\nimport { dirname, resolve } from 'node:path'\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 { register } from './cache-revalidate.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 { getTokenResponse } from './token-response.ts'\nimport type { WebAuthChallenge } from './web-auth-challenge.ts'\nimport { getWebAuthChallenge } from './web-auth-challenge.ts'\nexport {\n CacheEntry,\n deleteToken,\n getKC,\n isToken,\n keychains,\n setToken,\n type JSONObj,\n type Token,\n type TokenResponse,\n type WebAuthChallenge,\n}\n\nexport type CacheableMethod = 'GET' | 'HEAD'\nexport const isCacheableMethod = (m: unknown): m is CacheableMethod =>\n m === 'GET' || m === 'HEAD'\n\nexport type RegistryClientOptions = {\n /**\n * Path on disk where the cache should be stored\n *\n * Defaults to the XDG cache folder for `vlt/registry-client`\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 /**\n * If the server does not serve a `stale-while-revalidate` value in the\n * `cache-control` header, then this multiplier is applied to the `max-age`\n * or `s-maxage` values.\n *\n * By default, this is `60`, so for example a response that is cacheable for\n * 5 minutes will allow a stale response while revalidating for up to 5\n * hours.\n *\n * If the server *does* provide a `stale-while-revalidate` value, then that\n * is always used.\n *\n * Set to 0 to prevent any `stale-while-revalidate` behavior unless\n * explicitly allowed by the server's `cache-control` header.\n */\n 'stale-while-revalidate-factor'?: number\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 useCache?: 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 /**\n * Set to false to explicitly prevent `stale-while-revalidate` behavior,\n * for use in revalidating while stale.\n * @internal\n */\n staleWhileRevalidate?: false\n}\n\nconst { version } = loadPackageJson(\n import.meta.filename,\n process.env.__VLT_INTERNAL_REGISTRY_CLIENT_PACKAGE_JSON,\n) as {\n version: string\n}\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)')\n\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 staleWhileRevalidateFactor: number\n\n constructor(options: RegistryClientOptions) {\n const {\n cache = xdg.cache(),\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 'stale-while-revalidate-factor':\n staleWhileRevalidateFactor = 60,\n } = options\n this.identity = identity\n this.staleWhileRevalidateFactor = staleWhileRevalidateFactor\n const path = resolve(cache, 'registry-client')\n this.cache = new Cache({\n path,\n onDiskWrite(_path, key, data) {\n if (CacheEntry.isGzipEntry(data)) {\n cacheUnzipRegister(path, key)\n }\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 useCache: 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 { useCache: 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, authUrl}\n // - open the authUrl\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 useCache: 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 = getWebAuthChallenge(response.json())\n if (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 `authUrl` in a browser and\n * hang on the `doneUrl` until it returns a {@link TokenResponse} object.\n */\n async webAuthOpener({ doneUrl, authUrl }: 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(authUrl, { signal }).catch((er: unknown) => {\n if (asError(er).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 useCache: 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 token = getTokenResponse(response.json())\n if (token) return token\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 staleWhileRevalidate = true,\n } = options\n let { trustIntegrity } = options\n\n const m = isCacheableMethod(method) ? method : undefined\n const { useCache = !!m } = options\n\n ;(signal as AbortSignal | null)?.throwIfAborted()\n\n // first, try to get from the cache before making any request.\n const { origin } = u\n const key = `${method !== 'GET' ? method + ' ' : ''}${u}`\n const buffer =\n useCache ?\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\n if (staleWhileRevalidate && entry?.staleWhileRevalidate && m) {\n // revalidate while returning the stale entry\n register(dirname(this.cache.path()), m, url)\n return entry\n }\n\n // either no cache entry, or need to revalidate before use.\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 let response: Dispatcher.ResponseData | null = null\n try {\n response = await this.agent.request(\n options as Dispatcher.RequestOptions,\n )\n /* c8 ignore start */\n } catch (er) {\n // Rethrow so we get a better stack trace\n throw error('Request failed', {\n code: 'EREQUEST',\n cause: er,\n url,\n method,\n })\n }\n /* c8 ignore stop */\n\n const result = await this.#handleResponse(\n u,\n options,\n response,\n entry,\n )\n\n if (result.getHeader('integrity')) {\n trustIntegrity = true\n }\n\n if (result.isGzip && !trustIntegrity) {\n result.checkIntegrity({ url })\n }\n if (useCache) {\n this.cache.set(key, result.encode(), {\n integrity: result.integrity,\n })\n }\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 {\n integrity,\n trustIntegrity,\n 'stale-while-revalidate-factor':\n this.staleWhileRevalidateFactor,\n },\n )\n\n if (isRedirect(result)) {\n response.body.resume()\n const [nextURL, nextOptions] = redirect(options, result, url)\n if (nextOptions && nextURL) {\n return await this.request(nextURL, nextOptions)\n }\n return result\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 as cacheUnzipRegister } from '@vltpkg/cache-unzip'\nimport { error } from '@vltpkg/error-cause'\nimport { asError } from '@vltpkg/types'\nimport { logRequest } from '@vltpkg/output'\nimport type { Integrity } from '@vltpkg/types'\nimport { urlOpen } from '@vltpkg/url-open'\nimport { XDG } from '@vltpkg/xdg'\nimport { dirname, resolve } from 'node:path'\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 { register } from './cache-revalidate.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 { getTokenResponse } from './token-response.ts'\nimport type { WebAuthChallenge } from './web-auth-challenge.ts'\nimport { getWebAuthChallenge } from './web-auth-challenge.ts'\nimport { getEncondedValue } from './string-encoding.ts'\nexport {\n CacheEntry,\n deleteToken,\n getKC,\n isToken,\n keychains,\n setToken,\n type JSONObj,\n type Token,\n type TokenResponse,\n type WebAuthChallenge,\n}\n\nexport type CacheableMethod = 'GET' | 'HEAD'\nexport const isCacheableMethod = (m: unknown): m is CacheableMethod =>\n m === 'GET' || m === 'HEAD'\n\nexport type RegistryClientOptions = {\n /**\n * Path on disk where the cache should be stored\n *\n * Defaults to the XDG cache folder for `vlt/registry-client`\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 /**\n * If the server does not serve a `stale-while-revalidate` value in the\n * `cache-control` header, then this multiplier is applied to the `max-age`\n * or `s-maxage` values.\n *\n * By default, this is `60`, so for example a response that is cacheable for\n * 5 minutes will allow a stale response while revalidating for up to 5\n * hours.\n *\n * If the server *does* provide a `stale-while-revalidate` value, then that\n * is always used.\n *\n * Set to 0 to prevent any `stale-while-revalidate` behavior unless\n * explicitly allowed by the server's `cache-control` header.\n */\n 'stale-while-revalidate-factor'?: number\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 useCache?: 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 /**\n * Set to false to explicitly prevent `stale-while-revalidate` behavior,\n * for use in revalidating while stale.\n * @internal\n */\n staleWhileRevalidate?: false\n}\n\nconst { version } = loadPackageJson(\n import.meta.filename,\n process.env.__VLT_INTERNAL_REGISTRY_CLIENT_PACKAGE_JSON,\n) as {\n version: string\n}\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)')\n\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 staleWhileRevalidateFactor: number\n\n constructor(options: RegistryClientOptions) {\n const {\n cache = xdg.cache(),\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 'stale-while-revalidate-factor':\n staleWhileRevalidateFactor = 60,\n } = options\n this.identity = identity\n this.staleWhileRevalidateFactor = staleWhileRevalidateFactor\n const path = resolve(cache, 'registry-client')\n this.cache = new Cache({\n path,\n onDiskWrite(_path, key, data) {\n if (CacheEntry.isGzipEntry(data)) {\n cacheUnzipRegister(path, key)\n }\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 useCache: 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 { useCache: 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, authUrl}\n // - open the authUrl\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 useCache: 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 = getWebAuthChallenge(response.json())\n if (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 `authUrl` in a browser and\n * hang on the `doneUrl` until it returns a {@link TokenResponse} object.\n */\n async webAuthOpener({ doneUrl, authUrl }: 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(authUrl, { signal }).catch((er: unknown) => {\n if (asError(er).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 useCache: false,\n })\n const { signal } = options as { signal?: AbortSignal }\n if (response.statusCode === 202) {\n const rt = response.getHeaderString('retry-after')\n const retryAfter = rt ? Number(rt) : -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 token = getTokenResponse(response.json())\n if (token) return token\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 staleWhileRevalidate = true,\n } = options\n let { trustIntegrity } = options\n\n const m = isCacheableMethod(method) ? method : undefined\n const { useCache = !!m } = options\n\n ;(signal as AbortSignal | null)?.throwIfAborted()\n\n // first, try to get from the cache before making any request.\n const { origin } = u\n const key = `${method !== 'GET' ? method + ' ' : ''}${u}`\n const buffer =\n useCache ?\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\n if (staleWhileRevalidate && entry?.staleWhileRevalidate && m) {\n // revalidate while returning the stale entry\n register(dirname(this.cache.path()), m, url)\n return entry\n }\n\n // either no cache entry, or need to revalidate before use.\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 let response: Dispatcher.ResponseData | null = null\n try {\n response = await this.agent.request(\n options as Dispatcher.RequestOptions,\n )\n /* c8 ignore start */\n } catch (er) {\n // Rethrow so we get a better stack trace\n throw error('Request failed', {\n code: 'EREQUEST',\n cause: er,\n url,\n method,\n })\n }\n /* c8 ignore stop */\n\n const result = await this.#handleResponse(\n u,\n options,\n response,\n entry,\n )\n\n if (result.getHeader('integrity')) {\n trustIntegrity = true\n }\n\n if (result.isGzip && !trustIntegrity) {\n result.checkIntegrity({ url })\n }\n if (useCache) {\n // Get the encoded buffer from the cache entry\n const buffer = result.encode()\n this.cache.set(\n key,\n Buffer.from(\n buffer.buffer,\n buffer.byteOffset,\n buffer.byteLength,\n ),\n {\n integrity: result.integrity,\n },\n )\n }\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: Uint8Array[] = []\n for (const [key, value] of Object.entries(response.headers)) {\n /* c8 ignore start - theoretical */\n if (Array.isArray(value)) {\n h.push(\n getEncondedValue(key),\n getEncondedValue(value.join(', ')),\n )\n /* c8 ignore stop */\n } else if (typeof value === 'string') {\n h.push(getEncondedValue(key), getEncondedValue(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 {\n integrity,\n trustIntegrity,\n 'stale-while-revalidate-factor':\n this.staleWhileRevalidateFactor,\n contentLength:\n response.headers['content-length'] ?\n Number(response.headers['content-length'])\n : /* c8 ignore next */ undefined,\n },\n )\n\n if (isRedirect(result)) {\n response.body.resume()\n const [nextURL, nextOptions] = redirect(options, result, url)\n if (nextOptions && nextURL) {\n return await this.request(nextURL, nextOptions)\n }\n return result\n }\n\n response.body.on('data', (chunk: Uint8Array) =>\n result.addBody(chunk),\n )\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/dist/esm/raw-header.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Give it a key, and it'll return the
|
|
2
|
+
* Give it a key, and it'll return the value of that header as a Uint8Array
|
|
3
3
|
*/
|
|
4
|
-
export declare const getRawHeader: (headers:
|
|
4
|
+
export declare const getRawHeader: (headers: Uint8Array[], key: string) => Uint8Array | undefined;
|
|
5
5
|
/**
|
|
6
6
|
* Give it a key and value, and it'll overwrite or add the header entry
|
|
7
7
|
*/
|
|
8
|
-
export declare const setRawHeader: (headers:
|
|
8
|
+
export declare const setRawHeader: (headers: Uint8Array[], key: string, value: Uint8Array | string) => Uint8Array[];
|
|
9
9
|
//# sourceMappingURL=raw-header.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raw-header.d.ts","sourceRoot":"","sources":["../../src/raw-header.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"raw-header.d.ts","sourceRoot":"","sources":["../../src/raw-header.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,eAAO,MAAM,YAAY,YACd,UAAU,EAAE,OAChB,MAAM,KACV,UAAU,GAAG,SAYf,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,YACd,UAAU,EAAE,OAChB,MAAM,SACJ,UAAU,GAAG,MAAM,KACzB,UAAU,EAmBZ,CAAA"}
|
package/dist/esm/raw-header.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import { getDecodedValue, getEncondedValue, } from "./string-encoding.js";
|
|
1
2
|
/**
|
|
2
|
-
* Give it a key, and it'll return the
|
|
3
|
+
* Give it a key, and it'll return the value of that header as a Uint8Array
|
|
3
4
|
*/
|
|
4
|
-
export const getRawHeader = (headers,
|
|
5
|
-
k =
|
|
5
|
+
export const getRawHeader = (headers, key) => {
|
|
6
|
+
const k = key.toLowerCase();
|
|
6
7
|
for (let i = 0; i < headers.length; i += 2) {
|
|
7
8
|
const name = headers[i];
|
|
8
9
|
if (name &&
|
|
9
|
-
name.length ===
|
|
10
|
-
name
|
|
10
|
+
name.length === key.length &&
|
|
11
|
+
getDecodedValue(name).toLowerCase() === k) {
|
|
11
12
|
return headers[i + 1];
|
|
12
13
|
}
|
|
13
14
|
}
|
|
@@ -15,21 +16,21 @@ export const getRawHeader = (headers, k) => {
|
|
|
15
16
|
/**
|
|
16
17
|
* Give it a key and value, and it'll overwrite or add the header entry
|
|
17
18
|
*/
|
|
18
|
-
export const setRawHeader = (headers,
|
|
19
|
-
k =
|
|
20
|
-
const
|
|
19
|
+
export const setRawHeader = (headers, key, value) => {
|
|
20
|
+
const k = key.toLowerCase();
|
|
21
|
+
const encVal = typeof value === 'string' ? getEncondedValue(value) : value;
|
|
21
22
|
for (let i = 0; i < headers.length; i += 2) {
|
|
22
23
|
const name = headers[i];
|
|
23
24
|
if (name &&
|
|
24
25
|
name.length === k.length &&
|
|
25
|
-
name
|
|
26
|
+
getDecodedValue(name).toLowerCase() === k) {
|
|
26
27
|
return [
|
|
27
28
|
...headers.slice(0, i + 1),
|
|
28
|
-
|
|
29
|
+
encVal,
|
|
29
30
|
...headers.slice(i + 2),
|
|
30
31
|
];
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
|
-
return [...headers,
|
|
34
|
+
return [...headers, getEncondedValue(k), encVal];
|
|
34
35
|
};
|
|
35
36
|
//# sourceMappingURL=raw-header.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raw-header.js","sourceRoot":"","sources":["../../src/raw-header.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,
|
|
1
|
+
{"version":3,"file":"raw-header.js","sourceRoot":"","sources":["../../src/raw-header.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,GACjB,MAAM,sBAAsB,CAAA;AAE7B;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAAqB,EACrB,GAAW,EACa,EAAE;IAC1B,MAAM,CAAC,GAAG,GAAG,CAAC,WAAW,EAAE,CAAA;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;QACvB,IACE,IAAI;YACJ,IAAI,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM;YAC1B,eAAe,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,EACzC,CAAC;YACD,OAAO,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QACvB,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAAqB,EACrB,GAAW,EACX,KAA0B,EACZ,EAAE;IAChB,MAAM,CAAC,GAAG,GAAG,CAAC,WAAW,EAAE,CAAA;IAC3B,MAAM,MAAM,GACV,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IAC7D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;QACvB,IACE,IAAI;YACJ,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;YACxB,eAAe,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,EACzC,CAAC;YACD,OAAO;gBACL,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;gBAC1B,MAAM;gBACN,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;aACxB,CAAA;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;AAClD,CAAC,CAAA","sourcesContent":["import {\n getDecodedValue,\n getEncondedValue,\n} from './string-encoding.ts'\n\n/**\n * Give it a key, and it'll return the value of that header as a Uint8Array\n */\nexport const getRawHeader = (\n headers: Uint8Array[],\n key: string,\n): Uint8Array | undefined => {\n const k = key.toLowerCase()\n for (let i = 0; i < headers.length; i += 2) {\n const name = headers[i]\n if (\n name &&\n name.length === key.length &&\n getDecodedValue(name).toLowerCase() === k\n ) {\n return headers[i + 1]\n }\n }\n}\n\n/**\n * Give it a key and value, and it'll overwrite or add the header entry\n */\nexport const setRawHeader = (\n headers: Uint8Array[],\n key: string,\n value: Uint8Array | string,\n): Uint8Array[] => {\n const k = key.toLowerCase()\n const encVal =\n typeof value === 'string' ? getEncondedValue(value) : value\n for (let i = 0; i < headers.length; i += 2) {\n const name = headers[i]\n if (\n name &&\n name.length === k.length &&\n getDecodedValue(name).toLowerCase() === k\n ) {\n return [\n ...headers.slice(0, i + 1),\n encVal,\n ...headers.slice(i + 2),\n ]\n }\n }\n return [...headers, getEncondedValue(k), encVal]\n}\n"]}
|
package/dist/esm/redirect.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { RegistryClientRequestOptions } from './index.ts';
|
|
|
3
3
|
export type RedirectStatus = 301 | 302 | 303 | 307 | 308;
|
|
4
4
|
export type RedirectResponse = CacheEntry & {
|
|
5
5
|
statusCode: RedirectStatus;
|
|
6
|
-
getHeader(key: 'location'):
|
|
6
|
+
getHeader(key: 'location'): Uint8Array | undefined;
|
|
7
7
|
};
|
|
8
8
|
export declare const isRedirect: (response: CacheEntry) => response is RedirectResponse;
|
|
9
9
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirect.d.ts","sourceRoot":"","sources":["../../src/redirect.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAA;AAE9D,MAAM,MAAM,cAAc,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AAIxD,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG;IAC1C,UAAU,EAAE,cAAc,CAAA;IAC1B,SAAS,CAAC,GAAG,EAAE,UAAU,GAAG,
|
|
1
|
+
{"version":3,"file":"redirect.d.ts","sourceRoot":"","sources":["../../src/redirect.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAA;AAE9D,MAAM,MAAM,cAAc,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AAIxD,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG;IAC1C,UAAU,EAAE,cAAc,CAAA;IAC1B,SAAS,CAAC,GAAG,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;CACnD,CAAA;AAED,eAAO,MAAM,UAAU,aACX,UAAU,KACnB,QAAQ,IAAI,gBAE2B,CAAA;AAE1C;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ,YACV,4BAA4B,YAC3B,gBAAgB,QACpB,GAAG,KACR,EAAE,GAAG,CAAC,GAAG,EAAE,4BAA4B,CA6CzC,CAAA"}
|
package/dist/esm/redirect.js
CHANGED
|
@@ -27,7 +27,11 @@ export const redirect = (options, response, from) => {
|
|
|
27
27
|
url: from,
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
|
-
const location =
|
|
30
|
+
const location = response.getHeaderString('location');
|
|
31
|
+
/* c8 ignore start */
|
|
32
|
+
if (!location)
|
|
33
|
+
throw error('Location header missing from redirect response');
|
|
34
|
+
/* c8 ignore stop */
|
|
31
35
|
const nextURL = new URL(location, from);
|
|
32
36
|
if (redirections.has(String(nextURL))) {
|
|
33
37
|
throw error('Redirection cycle detected', {
|
package/dist/esm/redirect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirect.js","sourceRoot":"","sources":["../../src/redirect.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAM3C,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;AAO3D,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,QAAoB,EACU,EAAE,CAChC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC;IACzC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;AAE1C;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,OAAqC,EACrC,QAA0B,EAC1B,IAAS,EACiC,EAAE;IAC5C,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,EAAU,EAAE,eAAe,GAAG,EAAE,EAAE,GAC9D,OAAO,CAAA;IACT,IAAI,eAAe,IAAI,CAAC;QAAE,OAAO,EAAE,CAAA;IACnC,IAAI,YAAY,CAAC,IAAI,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,CAAC,+BAA+B,EAAE;YAC3C,GAAG,EAAE,eAAe;YACpB,KAAK,EAAE,CAAC,GAAG,YAAY,CAAC;YACxB,GAAG,EAAE,IAAI;SACV,CAAC,CAAA;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,
|
|
1
|
+
{"version":3,"file":"redirect.js","sourceRoot":"","sources":["../../src/redirect.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAM3C,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;AAO3D,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,QAAoB,EACU,EAAE,CAChC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC;IACzC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;AAE1C;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,OAAqC,EACrC,QAA0B,EAC1B,IAAS,EACiC,EAAE;IAC5C,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,EAAU,EAAE,eAAe,GAAG,EAAE,EAAE,GAC9D,OAAO,CAAA;IACT,IAAI,eAAe,IAAI,CAAC;QAAE,OAAO,EAAE,CAAA;IACnC,IAAI,YAAY,CAAC,IAAI,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,CAAC,+BAA+B,EAAE;YAC3C,GAAG,EAAE,eAAe;YACpB,KAAK,EAAE,CAAC,GAAG,YAAY,CAAC;YACxB,GAAG,EAAE,IAAI;SACV,CAAC,CAAA;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC,CAAA;IACrD,qBAAqB;IACrB,IAAI,CAAC,QAAQ;QACX,MAAM,KAAK,CAAC,gDAAgD,CAAC,CAAA;IAC/D,oBAAoB;IACpB,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IACvC,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACtC,MAAM,KAAK,CAAC,4BAA4B,EAAE;YACxC,GAAG,EAAE,eAAe;YACpB,KAAK,EAAE,CAAC,GAAG,YAAY,CAAC;YACxB,GAAG,EAAE,IAAI;SACV,CAAC,CAAA;IACJ,CAAC;IACD,MAAM,WAAW,GAAiC;QAChD,GAAG,OAAO;QACV,YAAY;KACb,CAAA;IACD,4FAA4F;IAC5F,OAAO,WAAW,CAAC,IAAI,CAAA;IACvB,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;IACjC,QAAQ,QAAQ,CAAC,UAAU,EAAE,CAAC;QAC5B,KAAK,GAAG,CAAC,CAAC,CAAC;YACT,kCAAkC;YAClC,WAAW,CAAC,MAAM,GAAG,KAAK,CAAA;YAC1B,WAAW,CAAC,IAAI,GAAG,SAAS,CAAA;YAC5B,cAAc;QAChB,CAAC;QACD,KAAK,GAAG,CAAC;QACT,KAAK,GAAG,CAAC,CAAC,mDAAmD;QAC7D,KAAK,GAAG,CAAC;QACT,KAAK,GAAG,CAAC,CAAC,CAAC;YACT,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC;AACH,CAAC,CAAA","sourcesContent":["// given a RegistryClientOptions object, and a redirection response,\n\nimport { error } from '@vltpkg/error-cause'\nimport type { CacheEntry } from './cache-entry.ts'\nimport type { RegistryClientRequestOptions } from './index.ts'\n\nexport type RedirectStatus = 301 | 302 | 303 | 307 | 308\n\nconst redirectStatuses = new Set([301, 302, 303, 307, 308])\n\nexport type RedirectResponse = CacheEntry & {\n statusCode: RedirectStatus\n getHeader(key: 'location'): Uint8Array | undefined\n}\n\nexport const isRedirect = (\n response: CacheEntry,\n): response is RedirectResponse =>\n redirectStatuses.has(response.statusCode) &&\n !!response.getHeader('location')?.length\n\n/**\n * If this response is allowed to follow the redirect (because max has not\n * been hit, and the new location has not been seen already), then return\n * the [url, options] to use for the subsequent request.\n *\n * Return [] if the response should be returned as-is.\n *\n * Throws an error if maxRedirections is hit or the redirections set already\n * contains the new location.\n *\n * Ensure that the response is in fact a redirection first, by calling\n * {@link isRedirect} on it.\n */\nexport const redirect = (\n options: RegistryClientRequestOptions,\n response: RedirectResponse,\n from: URL,\n): [] | [URL, RegistryClientRequestOptions] => {\n const { redirections = new Set<string>(), maxRedirections = 10 } =\n options\n if (maxRedirections <= 0) return []\n if (redirections.size >= maxRedirections) {\n throw error('Maximum redirections exceeded', {\n max: maxRedirections,\n found: [...redirections],\n url: from,\n })\n }\n const location = response.getHeaderString('location')\n /* c8 ignore start */\n if (!location)\n throw error('Location header missing from redirect response')\n /* c8 ignore stop */\n const nextURL = new URL(location, from)\n if (redirections.has(String(nextURL))) {\n throw error('Redirection cycle detected', {\n max: maxRedirections,\n found: [...redirections],\n url: from,\n })\n }\n const nextOptions: RegistryClientRequestOptions = {\n ...options,\n redirections,\n }\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- thats why we are deleting it\n delete nextOptions.path\n redirections.add(String(nextURL))\n switch (response.statusCode) {\n case 303: {\n // drop body, change method to GET\n nextOptions.method = 'GET'\n nextOptions.body = undefined\n // fallthrough\n }\n case 301:\n case 302: // some user agents treat as 303, but they're wrong\n case 307:\n case 308: {\n return [nextURL, nextOptions]\n }\n }\n}\n"]}
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
* Given a rawHeaders array of [key, value, key2, value2, ...],
|
|
3
3
|
* overwrite the current value of a header, or if not found, append
|
|
4
4
|
*/
|
|
5
|
-
export declare const setRawHeader: (headers:
|
|
5
|
+
export declare const setRawHeader: (headers: Uint8Array[], key: string, value: Uint8Array | string) => Uint8Array[];
|
|
6
6
|
//# sourceMappingURL=set-raw-header.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set-raw-header.d.ts","sourceRoot":"","sources":["../../src/set-raw-header.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"set-raw-header.d.ts","sourceRoot":"","sources":["../../src/set-raw-header.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,eAAO,MAAM,YAAY,YACd,UAAU,EAAE,OAChB,MAAM,SACJ,UAAU,GAAG,MAAM,KACzB,UAAU,EAiBZ,CAAA"}
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
+
import { getDecodedValue, getEncondedValue, } from "./string-encoding.js";
|
|
1
2
|
/**
|
|
2
3
|
* Given a rawHeaders array of [key, value, key2, value2, ...],
|
|
3
4
|
* overwrite the current value of a header, or if not found, append
|
|
4
5
|
*/
|
|
5
6
|
export const setRawHeader = (headers, key, value) => {
|
|
6
7
|
key = key.toLowerCase();
|
|
7
|
-
const keyBuf =
|
|
8
|
-
const valBuf =
|
|
8
|
+
const keyBuf = getEncondedValue(key);
|
|
9
|
+
const valBuf = getEncondedValue(value);
|
|
9
10
|
for (let i = 0; i < headers.length; i += 2) {
|
|
10
11
|
const k = headers[i];
|
|
11
12
|
if (k &&
|
|
12
13
|
k.length === keyBuf.length &&
|
|
13
|
-
|
|
14
|
+
getDecodedValue(k).toLowerCase() === key) {
|
|
14
15
|
headers[i + 1] = valBuf;
|
|
15
|
-
return;
|
|
16
|
+
return headers;
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
headers.push(keyBuf, valBuf);
|
|
20
|
+
return headers;
|
|
19
21
|
};
|
|
20
22
|
//# sourceMappingURL=set-raw-header.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set-raw-header.js","sourceRoot":"","sources":["../../src/set-raw-header.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,
|
|
1
|
+
{"version":3,"file":"set-raw-header.js","sourceRoot":"","sources":["../../src/set-raw-header.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,GACjB,MAAM,sBAAsB,CAAA;AAE7B;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAAqB,EACrB,GAAW,EACX,KAA0B,EACZ,EAAE;IAChB,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,CAAA;IACvB,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAA;IACpC,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;IACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;QACpB,IACE,CAAC;YACD,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;YAC1B,eAAe,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,GAAG,EACxC,CAAC;YACD,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAA;YACvB,OAAO,OAAO,CAAA;QAChB,CAAC;IACH,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA","sourcesContent":["import {\n getDecodedValue,\n getEncondedValue,\n} from './string-encoding.ts'\n\n/**\n * Given a rawHeaders array of [key, value, key2, value2, ...],\n * overwrite the current value of a header, or if not found, append\n */\nexport const setRawHeader = (\n headers: Uint8Array[],\n key: string,\n value: Uint8Array | string,\n): Uint8Array[] => {\n key = key.toLowerCase()\n const keyBuf = getEncondedValue(key)\n const valBuf = getEncondedValue(value)\n for (let i = 0; i < headers.length; i += 2) {\n const k = headers[i]\n if (\n k &&\n k.length === keyBuf.length &&\n getDecodedValue(k).toLowerCase() === key\n ) {\n headers[i + 1] = valBuf\n return headers\n }\n }\n headers.push(keyBuf, valBuf)\n return headers\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decodes a string from a Uint8Array
|
|
3
|
+
*/
|
|
4
|
+
export declare const getDecodedValue: (value: string | Uint8Array | undefined) => string;
|
|
5
|
+
/**
|
|
6
|
+
* Encodes a string to a Uint8Array
|
|
7
|
+
*/
|
|
8
|
+
export declare const getEncondedValue: (value: Uint8Array | string | undefined) => Uint8Array;
|
|
9
|
+
//# sourceMappingURL=string-encoding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string-encoding.d.ts","sourceRoot":"","sources":["../../src/string-encoding.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,eAAe,UACnB,MAAM,GAAG,UAAU,GAAG,SAAS,KACrC,MAKF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,UACpB,UAAU,GAAG,MAAM,GAAG,SAAS,KACrC,UAOF,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const decoder = new TextDecoder();
|
|
2
|
+
/**
|
|
3
|
+
* Decodes a string from a Uint8Array
|
|
4
|
+
*/
|
|
5
|
+
export const getDecodedValue = (value) => {
|
|
6
|
+
if (value == undefined)
|
|
7
|
+
return '';
|
|
8
|
+
if (typeof value === 'string')
|
|
9
|
+
return value;
|
|
10
|
+
const res = decoder.decode(value);
|
|
11
|
+
return res;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Encodes a string to a Uint8Array
|
|
15
|
+
*/
|
|
16
|
+
export const getEncondedValue = (value) => {
|
|
17
|
+
if (value == undefined)
|
|
18
|
+
return new Uint8Array(0);
|
|
19
|
+
if (typeof value === 'string') {
|
|
20
|
+
const res = Buffer.from(value);
|
|
21
|
+
return res;
|
|
22
|
+
}
|
|
23
|
+
return value;
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=string-encoding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string-encoding.js","sourceRoot":"","sources":["../../src/string-encoding.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;AAEjC;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,KAAsC,EAC9B,EAAE;IACV,IAAI,KAAK,IAAI,SAAS;QAAE,OAAO,EAAE,CAAA;IACjC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC3C,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACjC,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,KAAsC,EAC1B,EAAE;IACd,IAAI,KAAK,IAAI,SAAS;QAAE,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAA;IAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC9B,OAAO,GAAG,CAAA;IACZ,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA","sourcesContent":["const decoder = new TextDecoder()\n\n/**\n * Decodes a string from a Uint8Array\n */\nexport const getDecodedValue = (\n value: string | Uint8Array | undefined,\n): string => {\n if (value == undefined) return ''\n if (typeof value === 'string') return value\n const res = decoder.decode(value)\n return res\n}\n\n/**\n * Encodes a string to a Uint8Array\n */\nexport const getEncondedValue = (\n value: Uint8Array | string | undefined,\n): Uint8Array => {\n if (value == undefined) return new Uint8Array(0)\n if (typeof value === 'string') {\n const res = Buffer.from(value)\n return res\n }\n return value\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
|
+
"version": "0.0.0-25",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/vltpkg/vltpkg.git",
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
"cache-control-parser": "^2.0.6",
|
|
24
24
|
"package-json-from-dist": "^1.0.1",
|
|
25
25
|
"undici": "^7.15.0",
|
|
26
|
-
"@vltpkg/cache": "0.0.0-
|
|
27
|
-
"@vltpkg/
|
|
28
|
-
"@vltpkg/
|
|
29
|
-
"@vltpkg/output": "0.0.0-
|
|
30
|
-
"@vltpkg/
|
|
31
|
-
"@vltpkg/
|
|
32
|
-
"@vltpkg/
|
|
33
|
-
"@vltpkg/
|
|
26
|
+
"@vltpkg/cache": "0.0.0-25",
|
|
27
|
+
"@vltpkg/cache-unzip": "0.0.0-25",
|
|
28
|
+
"@vltpkg/error-cause": "0.0.0-25",
|
|
29
|
+
"@vltpkg/output": "0.0.0-25",
|
|
30
|
+
"@vltpkg/keychain": "0.0.0-25",
|
|
31
|
+
"@vltpkg/types": "0.0.0-25",
|
|
32
|
+
"@vltpkg/url-open": "0.0.0-25",
|
|
33
|
+
"@vltpkg/xdg": "0.0.0-25"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@eslint/js": "^9.34.0",
|