@vltpkg/registry-client 0.0.0-0.1730239248325
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/LICENSE +15 -0
- package/README.md +122 -0
- package/dist/esm/add-header.d.ts +2 -0
- package/dist/esm/add-header.d.ts.map +1 -0
- package/dist/esm/add-header.js +24 -0
- package/dist/esm/add-header.js.map +1 -0
- package/dist/esm/cache-entry.d.ts +69 -0
- package/dist/esm/cache-entry.d.ts.map +1 -0
- package/dist/esm/cache-entry.js +335 -0
- package/dist/esm/cache-entry.js.map +1 -0
- package/dist/esm/env.d.ts +11 -0
- package/dist/esm/env.d.ts.map +1 -0
- package/dist/esm/env.js +16 -0
- package/dist/esm/env.js.map +1 -0
- package/dist/esm/get-header.d.ts +2 -0
- package/dist/esm/get-header.d.ts.map +1 -0
- package/dist/esm/get-header.js +37 -0
- package/dist/esm/get-header.js.map +1 -0
- package/dist/esm/handle-304-response.d.ts +4 -0
- package/dist/esm/handle-304-response.d.ts.map +1 -0
- package/dist/esm/handle-304-response.js +10 -0
- package/dist/esm/handle-304-response.js.map +1 -0
- package/dist/esm/index.d.ts +55 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +122 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/is-cacheable.d.ts +5 -0
- package/dist/esm/is-cacheable.d.ts.map +1 -0
- package/dist/esm/is-cacheable.js +10 -0
- package/dist/esm/is-cacheable.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/raw-header.d.ts +9 -0
- package/dist/esm/raw-header.d.ts.map +1 -0
- package/dist/esm/raw-header.js +35 -0
- package/dist/esm/raw-header.js.map +1 -0
- package/dist/esm/redirect.d.ts +23 -0
- package/dist/esm/redirect.d.ts.map +1 -0
- package/dist/esm/redirect.js +60 -0
- package/dist/esm/redirect.js.map +1 -0
- package/dist/esm/serdes.d.ts +15 -0
- package/dist/esm/serdes.d.ts.map +1 -0
- package/dist/esm/serdes.js +19 -0
- package/dist/esm/serdes.js.map +1 -0
- package/dist/esm/set-cache-headers.d.ts +4 -0
- package/dist/esm/set-cache-headers.d.ts.map +1 -0
- package/dist/esm/set-cache-headers.js +17 -0
- package/dist/esm/set-cache-headers.js.map +1 -0
- package/dist/esm/set-raw-header.d.ts +6 -0
- package/dist/esm/set-raw-header.d.ts.map +1 -0
- package/dist/esm/set-raw-header.js +20 -0
- package/dist/esm/set-raw-header.js.map +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,cAAc,CAAA;AAE/B,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,UAGrB,CAAA;AAED,MAAM,KAAK,GAAG,CAAC,CAAU,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAA;AAE1D,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAA;AACjC,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAA;AAC1C,kEAAkE;AAClE,gCAAgC;AAChC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAA;AAElE,4DAA4D;AAC5D,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAA;AACxD,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;AAC3D,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;AAE3D,MAAM,CAAC,MAAM,MAAM,GACjB,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;IAC5D,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE;QAC9C,CAAC,CAAC,SAAS,CAAA","sourcesContent":["import proc from 'node:process'\n\nconst { Deno, Bun } = globalThis as typeof globalThis & {\n Deno: undefined | object\n Bun: undefined | object\n}\n\nconst isObj = (v: unknown) => typeof v === 'object' && !!v\n\nexport const isDeno = isObj(Deno)\nexport const isBun = !isDeno && isObj(Bun)\n// bun and deno also report 'node' in process.versions so its only\n// node if it is not bun or deno\nexport const isNode = !isDeno && !isBun && 'node' in proc.versions\n\n// All the runtimes put their versions into process.versions\nexport const bun = isBun ? proc.versions.bun : undefined\nexport const deno = isDeno ? proc.versions.deno : undefined\nexport const node = isNode ? proc.versions.node : undefined\n\nexport const engine =\n isNode || isDeno ? { name: 'v8', version: proc.versions.v8 }\n : isBun && bun ? { name: 'bun', version: bun }\n : undefined\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-header.d.ts","sourceRoot":"","sources":["../../src/get-header.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,YAEhB,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC,GACjD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC,GAC7C,MAAM,EAAE,GACR,IAAI,GACJ,SAAS,OACR,MAAM,KACV,MAAM,EAAE,GAAG,MAAM,GAAG,SA8BtB,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const isIterable = (o) => !!o && !!o[Symbol.iterator];
|
|
2
|
+
export const getHeader = (headers, key) => {
|
|
3
|
+
if (!headers)
|
|
4
|
+
return undefined;
|
|
5
|
+
key = key.toLowerCase();
|
|
6
|
+
if (Array.isArray(headers)) {
|
|
7
|
+
if (!headers.length)
|
|
8
|
+
return undefined;
|
|
9
|
+
if (Array.isArray(headers[0])) {
|
|
10
|
+
// [string,HeaderValue][]
|
|
11
|
+
for (const [k, v] of headers) {
|
|
12
|
+
if (k.toLowerCase() === key)
|
|
13
|
+
return v;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
else if (headers.length % 2 === 0) {
|
|
17
|
+
// [k, v, k2, v2, ...]
|
|
18
|
+
for (let i = 0; i < headers.length; i += 2) {
|
|
19
|
+
if (headers[i]?.toLowerCase() === key)
|
|
20
|
+
return headers[i + 1];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else if (isIterable(headers)) {
|
|
25
|
+
for (const [k, v] of headers) {
|
|
26
|
+
if (k.toLowerCase() === key)
|
|
27
|
+
return v;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
32
|
+
if (k.toLowerCase() === key)
|
|
33
|
+
return v;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=get-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-header.js","sourceRoot":"","sources":["../../src/get-header.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,CAAI,CAAM,EAAoB,EAAE,CACjD,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;AAE7B,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,OAKa,EACb,GAAW,EACoB,EAAE;IACjC,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAA;IAC9B,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,CAAA;IACvB,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,OAAO,SAAS,CAAA;QACrC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9B,yBAAyB;YACzB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAGlB,EAAE,CAAC;gBACJ,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,GAAG;oBAAE,OAAO,CAAC,CAAA;YACvC,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,sBAAsB;YACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3C,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,GAAG;oBAAE,OAAO,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YAC9D,CAAC;QACH,CAAC;IACH,CAAC;SAAM,IACL,UAAU,CAA0C,OAAO,CAAC,EAC5D,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,GAAG;gBAAE,OAAO,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,GAAG;gBAAE,OAAO,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;AACH,CAAC,CAAA","sourcesContent":["const isIterable = <T>(o: any): o is Iterable<T> =>\n !!o && !!o[Symbol.iterator]\n\nexport const getHeader = (\n headers:\n | Iterable<[string, string[] | string | undefined]>\n | Record<string, string[] | string | undefined>\n | string[]\n | null\n | undefined,\n key: string,\n): string[] | string | undefined => {\n if (!headers) return undefined\n key = key.toLowerCase()\n if (Array.isArray(headers)) {\n if (!headers.length) return undefined\n if (Array.isArray(headers[0])) {\n // [string,HeaderValue][]\n for (const [k, v] of headers as unknown as [\n string,\n string[] | string,\n ][]) {\n if (k.toLowerCase() === key) return v\n }\n } else if (headers.length % 2 === 0) {\n // [k, v, k2, v2, ...]\n for (let i = 0; i < headers.length; i += 2) {\n if (headers[i]?.toLowerCase() === key) return headers[i + 1]\n }\n }\n } else if (\n isIterable<[string, string[] | string | undefined]>(headers)\n ) {\n for (const [k, v] of headers) {\n if (k.toLowerCase() === key) return v\n }\n } else {\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() === key) return v\n }\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle-304-response.d.ts","sourceRoot":"","sources":["../../src/handle-304-response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,eAAO,MAAM,iBAAiB,SACtB,UAAU,CAAC,YAAY,UACrB,UAAU,KACjB,KAAK,IAAI,UASX,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const handle304Response = (resp, entry) => {
|
|
2
|
+
if (resp.statusCode !== 304 || !entry)
|
|
3
|
+
return false;
|
|
4
|
+
const d = String(resp.headers.date ?? '') || new Date().toUTCString();
|
|
5
|
+
entry.setHeader('date', Buffer.from(d));
|
|
6
|
+
// shouldn't have a body, but just in case.
|
|
7
|
+
resp.body.resume();
|
|
8
|
+
return true;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=handle-304-response.js.map
|
|
@@ -0,0 +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,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IACvC,2CAA2C;IAC3C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAA;IAClB,OAAO,IAAI,CAAA;AACb,CAAC,CAAA","sourcesContent":["import { Dispatcher } from 'undici'\nimport { CacheEntry } from './cache-entry.js'\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', Buffer.from(d))\n // shouldn't have a body, but just in case.\n resp.body.resume()\n return true\n}\n"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Cache } from '@vltpkg/cache';
|
|
2
|
+
import { Integrity } from '@vltpkg/types';
|
|
3
|
+
import { Agent, Dispatcher } from 'undici';
|
|
4
|
+
import { CacheEntry } from './cache-entry.js';
|
|
5
|
+
export { type CacheEntry };
|
|
6
|
+
export type RegistryClientOptions = {
|
|
7
|
+
/**
|
|
8
|
+
* Path on disk where the cache should be stored
|
|
9
|
+
*
|
|
10
|
+
* @default `$HOME/.config/vlt/cache`
|
|
11
|
+
*/
|
|
12
|
+
cache?: string;
|
|
13
|
+
};
|
|
14
|
+
export type RegistryClientRequestOptions = Omit<Dispatcher.DispatchOptions, 'method' | 'path'> & {
|
|
15
|
+
/**
|
|
16
|
+
* `path` should not be set when using the RegistryClient.
|
|
17
|
+
* It will be overwritten with the path on the URL being requested.
|
|
18
|
+
* This only here for compliance with the DispatchOptions base type.
|
|
19
|
+
* @deprecated
|
|
20
|
+
*/
|
|
21
|
+
path?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Method is optional, defaults to 'GET'
|
|
24
|
+
*/
|
|
25
|
+
method?: Dispatcher.DispatchOptions['method'];
|
|
26
|
+
/**
|
|
27
|
+
* Provide an SRI string to verify integrity of the item being fetched.
|
|
28
|
+
*
|
|
29
|
+
* This is only relevant when it must make a request to the registry. Once in
|
|
30
|
+
* the local disk cache, items are assumed to be trustworthy.
|
|
31
|
+
*/
|
|
32
|
+
integrity?: Integrity;
|
|
33
|
+
/**
|
|
34
|
+
* Follow up to 10 redirections by default. Set this to 0 to just return
|
|
35
|
+
* the 3xx response. If the max redirections are expired, and we still get
|
|
36
|
+
* a redirection response, then fail the request. Redirection cycles are
|
|
37
|
+
* always treated as an error.
|
|
38
|
+
*/
|
|
39
|
+
maxRedirections?: number;
|
|
40
|
+
/**
|
|
41
|
+
* the number of redirections that have already been seen. This is used
|
|
42
|
+
* internally, and should always start at 0.
|
|
43
|
+
*
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
redirections?: Set<string>;
|
|
47
|
+
};
|
|
48
|
+
export declare const userAgent: string;
|
|
49
|
+
export declare class RegistryClient {
|
|
50
|
+
agent: Agent;
|
|
51
|
+
cache: Cache;
|
|
52
|
+
constructor({ cache, }: RegistryClientOptions);
|
|
53
|
+
request(url: URL | string, options?: RegistryClientRequestOptions): Promise<CacheEntry>;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAErC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAGzC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAM7C,OAAO,EAAE,KAAK,UAAU,EAAE,CAAA;AAE1B,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAC7C,UAAU,CAAC,eAAe,EAC1B,QAAQ,GAAG,MAAM,CAClB,GAAG;IACF;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAA;IAC7C;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,CAAA;IAErB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAC3B,CAAA;AASD,eAAO,MAAM,SAAS,QAA8C,CAAA;AAoBpE,qBAAa,cAAc;IACzB,KAAK,EAAE,KAAK,CAAA;IACZ,KAAK,EAAE,KAAK,CAAA;gBAEA,EACV,KAAoC,GACrC,EAAE,qBAAqB;IAUlB,OAAO,CACX,GAAG,EAAE,GAAG,GAAG,MAAM,EACjB,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,UAAU,CAAC;CAmGvB"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Cache } from '@vltpkg/cache';
|
|
2
|
+
import { register } from '@vltpkg/cache-unzip';
|
|
3
|
+
import { XDG } from '@vltpkg/xdg';
|
|
4
|
+
import { loadPackageJson } from 'package-json-from-dist';
|
|
5
|
+
import { Agent } from 'undici';
|
|
6
|
+
import { addHeader } from './add-header.js';
|
|
7
|
+
import { CacheEntry } from './cache-entry.js';
|
|
8
|
+
import { bun, deno, node } from './env.js';
|
|
9
|
+
import { handle304Response } from './handle-304-response.js';
|
|
10
|
+
import { isRedirect, redirect } from './redirect.js';
|
|
11
|
+
import { setCacheHeaders } from './set-cache-headers.js';
|
|
12
|
+
const { version } = loadPackageJson(import.meta.filename);
|
|
13
|
+
const nua = globalThis.navigator?.userAgent ??
|
|
14
|
+
(bun ? `Bun/${bun}`
|
|
15
|
+
: deno ? `Deno/${deno}`
|
|
16
|
+
: node ? `Node.js/${node}`
|
|
17
|
+
: '(unknown platform)');
|
|
18
|
+
export const userAgent = `@vltpkg/registry-client/${version} ${nua}`;
|
|
19
|
+
const agentOptions = {
|
|
20
|
+
bodyTimeout: 600_000,
|
|
21
|
+
headersTimeout: 600_000,
|
|
22
|
+
keepAliveMaxTimeout: 1_200_000,
|
|
23
|
+
keepAliveTimeout: 600_000,
|
|
24
|
+
keepAliveTimeoutThreshold: 30_000,
|
|
25
|
+
connect: {
|
|
26
|
+
timeout: 600_000,
|
|
27
|
+
keepAlive: true,
|
|
28
|
+
keepAliveInitialDelay: 30_000,
|
|
29
|
+
sessionTimeout: 600,
|
|
30
|
+
},
|
|
31
|
+
connections: 128,
|
|
32
|
+
pipelining: 10,
|
|
33
|
+
};
|
|
34
|
+
const xdg = new XDG('vlt');
|
|
35
|
+
export class RegistryClient {
|
|
36
|
+
agent;
|
|
37
|
+
cache;
|
|
38
|
+
constructor({ cache = xdg.cache('registry-client'), }) {
|
|
39
|
+
this.cache = new Cache({
|
|
40
|
+
path: cache,
|
|
41
|
+
onDiskWrite(_path, key, data) {
|
|
42
|
+
if (CacheEntry.decode(data).isGzip)
|
|
43
|
+
register(cache, key);
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
this.agent = new Agent(agentOptions);
|
|
47
|
+
}
|
|
48
|
+
async request(url, options = {}) {
|
|
49
|
+
const u = typeof url === 'string' ? new URL(url) : url;
|
|
50
|
+
const { method = 'GET', integrity, redirections = new Set(), } = options;
|
|
51
|
+
// first, try to get from the cache before making any request.
|
|
52
|
+
const { origin, pathname } = u;
|
|
53
|
+
const key = JSON.stringify([origin, method, pathname]);
|
|
54
|
+
const buffer = await this.cache.fetch(key, {
|
|
55
|
+
context: { integrity },
|
|
56
|
+
});
|
|
57
|
+
const entry = buffer ? CacheEntry.decode(buffer) : undefined;
|
|
58
|
+
if (entry?.valid)
|
|
59
|
+
return entry;
|
|
60
|
+
// TODO: stale-while-revalidate timeout, say 1 day, where we'll
|
|
61
|
+
// use the cached response even if it's invalid, and validate
|
|
62
|
+
// in the background without waiting for it.
|
|
63
|
+
// either no cache entry, or need to revalidate it.
|
|
64
|
+
setCacheHeaders(options, entry);
|
|
65
|
+
redirections.add(String(url));
|
|
66
|
+
Object.assign(options, {
|
|
67
|
+
path: u.pathname.replace(/\/+$/, '') + u.search,
|
|
68
|
+
...agentOptions,
|
|
69
|
+
});
|
|
70
|
+
options.origin = u.origin;
|
|
71
|
+
options.headers = addHeader(addHeader(options.headers, 'accept-encoding', 'gzip;q=1.0, identity;q=0.5'), 'user-agent', userAgent);
|
|
72
|
+
options.method = options.method ?? 'GET';
|
|
73
|
+
const result = await new Promise((res, rej) => {
|
|
74
|
+
/* c8 ignore start - excessive type setting for eslint */
|
|
75
|
+
this.agent
|
|
76
|
+
.request(options)
|
|
77
|
+
.then(res)
|
|
78
|
+
.catch((er) => rej(er));
|
|
79
|
+
/* c8 ignore stop */
|
|
80
|
+
}).then(resp => {
|
|
81
|
+
if (handle304Response(resp, entry))
|
|
82
|
+
return entry;
|
|
83
|
+
const h = [];
|
|
84
|
+
for (const [key, value] of Object.entries(resp.headers)) {
|
|
85
|
+
/* c8 ignore start - theoretical */
|
|
86
|
+
if (Array.isArray(value)) {
|
|
87
|
+
h.push(Buffer.from(key), Buffer.from(value.join(', ')));
|
|
88
|
+
/* c8 ignore stop */
|
|
89
|
+
}
|
|
90
|
+
else if (typeof value === 'string') {
|
|
91
|
+
h.push(Buffer.from(key), Buffer.from(value));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const result = new CacheEntry(
|
|
95
|
+
/* c8 ignore next - should always have a status code */
|
|
96
|
+
resp.statusCode || 200, h, options.integrity);
|
|
97
|
+
if (isRedirect(result)) {
|
|
98
|
+
resp.body.resume();
|
|
99
|
+
try {
|
|
100
|
+
const [nextURL, nextOptions] = redirect(options, result, u);
|
|
101
|
+
if (nextOptions && nextURL) {
|
|
102
|
+
return this.request(nextURL, nextOptions);
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
catch (er) {
|
|
107
|
+
/* c8 ignore start */
|
|
108
|
+
throw er instanceof Error ? er : (new Error(typeof er === 'string' ? er : 'Unknown error'));
|
|
109
|
+
/* c8 ignore stop */
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
resp.body.on('data', (chunk) => result.addBody(chunk));
|
|
113
|
+
return new Promise((res, rej) => {
|
|
114
|
+
resp.body.on('error', rej);
|
|
115
|
+
resp.body.on('end', () => res(result));
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
this.cache.set(key, result.encode());
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { Cache } from '@vltpkg/cache'\nimport { register } from '@vltpkg/cache-unzip'\nimport { Integrity } from '@vltpkg/types'\nimport { XDG } from '@vltpkg/xdg'\nimport { loadPackageJson } from 'package-json-from-dist'\nimport { Agent, Dispatcher } from 'undici'\nimport { addHeader } from './add-header.js'\nimport { CacheEntry } from './cache-entry.js'\nimport { bun, deno, node } from './env.js'\nimport { handle304Response } from './handle-304-response.js'\nimport { isRedirect, redirect } from './redirect.js'\nimport { setCacheHeaders } from './set-cache-headers.js'\n\nexport { type CacheEntry }\n\nexport type RegistryClientOptions = {\n /**\n * Path on disk where the cache should be stored\n *\n * @default `$HOME/.config/vlt/cache`\n */\n cache?: string\n}\n\nexport type RegistryClientRequestOptions = Omit<\n Dispatcher.DispatchOptions,\n 'method' | 'path'\n> & {\n /**\n * `path` should not be set when using the RegistryClient.\n * It will be overwritten with the path on the URL being requested.\n * This only here for compliance with the DispatchOptions base type.\n * @deprecated\n */\n path?: string\n\n /**\n * Method is optional, defaults to 'GET'\n */\n method?: Dispatcher.DispatchOptions['method']\n /**\n * Provide an SRI string to verify integrity of the item being fetched.\n *\n * This is only relevant when it must make a request to the registry. Once in\n * the local disk cache, items are assumed to be trustworthy.\n */\n integrity?: Integrity\n\n /**\n * Follow up to 10 redirections by default. Set this to 0 to just return\n * the 3xx response. If the max redirections are expired, and we still get\n * a redirection response, then fail the request. Redirection cycles are\n * always treated as an error.\n */\n maxRedirections?: number\n\n /**\n * the number of redirections that have already been seen. This is used\n * internally, and should always start at 0.\n *\n * @internal\n */\n redirections?: Set<string>\n}\n\nconst { version } = loadPackageJson(import.meta.filename)\nconst nua =\n (globalThis.navigator as Navigator | undefined)?.userAgent ??\n (bun ? `Bun/${bun}`\n : deno ? `Deno/${deno}`\n : node ? `Node.js/${node}`\n : '(unknown platform)')\nexport const userAgent = `@vltpkg/registry-client/${version} ${nua}`\n\nconst agentOptions: Agent.Options = {\n bodyTimeout: 600_000,\n headersTimeout: 600_000,\n keepAliveMaxTimeout: 1_200_000,\n keepAliveTimeout: 600_000,\n keepAliveTimeoutThreshold: 30_000,\n connect: {\n timeout: 600_000,\n keepAlive: true,\n keepAliveInitialDelay: 30_000,\n sessionTimeout: 600,\n },\n connections: 128,\n pipelining: 10,\n}\n\nconst xdg = new XDG('vlt')\n\nexport class RegistryClient {\n agent: Agent\n cache: Cache\n\n constructor({\n cache = xdg.cache('registry-client'),\n }: RegistryClientOptions) {\n this.cache = new Cache({\n path: cache,\n onDiskWrite(_path, key, data) {\n if (CacheEntry.decode(data).isGzip) register(cache, key)\n },\n })\n this.agent = new Agent(agentOptions)\n }\n\n async request(\n url: URL | string,\n options: RegistryClientRequestOptions = {},\n ): Promise<CacheEntry> {\n const u = typeof url === 'string' ? new URL(url) : url\n const {\n method = 'GET',\n integrity,\n redirections = new Set(),\n } = options\n\n // first, try to get from the cache before making any request.\n const { origin, pathname } = u\n const key = JSON.stringify([origin, method, pathname])\n const buffer = await this.cache.fetch(key, {\n context: { integrity },\n })\n\n const entry = buffer ? CacheEntry.decode(buffer) : undefined\n if (entry?.valid) return entry\n // TODO: stale-while-revalidate timeout, say 1 day, where we'll\n // use the cached response even if it's invalid, and validate\n // in the background without waiting for it.\n\n // either no cache entry, or need to revalidate it.\n setCacheHeaders(options, entry)\n\n redirections.add(String(url))\n\n Object.assign(options, {\n path: u.pathname.replace(/\\/+$/, '') + u.search,\n ...agentOptions,\n })\n\n options.origin = u.origin\n options.headers = addHeader(\n addHeader(\n options.headers,\n 'accept-encoding',\n 'gzip;q=1.0, identity;q=0.5',\n ),\n 'user-agent',\n userAgent,\n )\n options.method = options.method ?? 'GET'\n\n const result = await new Promise<Dispatcher.ResponseData>(\n (res, rej) => {\n /* c8 ignore start - excessive type setting for eslint */\n this.agent\n .request(options as Dispatcher.RequestOptions)\n .then(res)\n .catch((er: unknown) => rej(er as Error))\n /* c8 ignore stop */\n },\n ).then(resp => {\n if (handle304Response(resp, entry)) return entry\n\n const h: Buffer[] = []\n for (const [key, value] of Object.entries(resp.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 const result = new CacheEntry(\n /* c8 ignore next - should always have a status code */\n resp.statusCode || 200,\n h,\n options.integrity,\n )\n\n if (isRedirect(result)) {\n resp.body.resume()\n try {\n const [nextURL, nextOptions] = redirect(options, result, u)\n if (nextOptions && nextURL) {\n return this.request(nextURL, nextOptions)\n }\n return result\n } catch (er) {\n /* c8 ignore start */\n throw er instanceof Error ? er : (\n new Error(typeof er === 'string' ? er : 'Unknown error')\n )\n /* c8 ignore stop */\n }\n }\n\n resp.body.on('data', (chunk: Buffer) => result.addBody(chunk))\n return new Promise<CacheEntry>((res, rej) => {\n resp.body.on('error', rej)\n resp.body.on('end', () => res(result))\n })\n })\n\n this.cache.set(key, result.encode())\n return result\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-cacheable.d.ts","sourceRoot":"","sources":["../../src/is-cacheable.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,WAAW,eAAgB,MAAM,YAMrC,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determine whether we're allowed to cache it, based on status code
|
|
3
|
+
*/
|
|
4
|
+
export const isCacheable = (statusCode) => statusCode < 200 ? false
|
|
5
|
+
: statusCode < 300 ? true
|
|
6
|
+
: statusCode === 301 ? true
|
|
7
|
+
: statusCode === 308 ? true
|
|
8
|
+
: statusCode === 410 ? true
|
|
9
|
+
: false;
|
|
10
|
+
//# sourceMappingURL=is-cacheable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-cacheable.js","sourceRoot":"","sources":["../../src/is-cacheable.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,UAAkB,EAAE,EAAE,CAChD,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK;IACxB,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI;QACzB,CAAC,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI;YAC3B,CAAC,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI;gBAC3B,CAAC,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI;oBAC3B,CAAC,CAAC,KAAK,CAAA","sourcesContent":["/**\n * Determine whether we're allowed to cache it, based on status code\n */\nexport const isCacheable = (statusCode: number) =>\n statusCode < 200 ? false\n : statusCode < 300 ? true\n : statusCode === 301 ? true\n : statusCode === 308 ? true\n : statusCode === 410 ? true\n : false\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Give it a key, and it'll return the buffer of that header value
|
|
3
|
+
*/
|
|
4
|
+
export declare const getRawHeader: (headers: Buffer[], k: string) => Buffer | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* Give it a key and value, and it'll overwrite or add the header entry
|
|
7
|
+
*/
|
|
8
|
+
export declare const setRawHeader: (headers: Buffer[], k: string, v: Buffer | string) => Buffer[];
|
|
9
|
+
//# sourceMappingURL=raw-header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-header.d.ts","sourceRoot":"","sources":["../../src/raw-header.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,YAAY,YAAa,MAAM,EAAE,KAAK,MAAM,uBAYxD,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,YACd,MAAM,EAAE,KACd,MAAM,KACN,MAAM,GAAG,MAAM,KACjB,MAAM,EAkBR,CAAA"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Give it a key, and it'll return the buffer of that header value
|
|
3
|
+
*/
|
|
4
|
+
export const getRawHeader = (headers, k) => {
|
|
5
|
+
k = k.toLowerCase();
|
|
6
|
+
for (let i = 0; i < headers.length; i += 2) {
|
|
7
|
+
const name = headers[i];
|
|
8
|
+
if (name &&
|
|
9
|
+
name.length === k.length &&
|
|
10
|
+
name.toString().toLowerCase() === k) {
|
|
11
|
+
return headers[i + 1];
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Give it a key and value, and it'll overwrite or add the header entry
|
|
17
|
+
*/
|
|
18
|
+
export const setRawHeader = (headers, k, v) => {
|
|
19
|
+
k = k.toLowerCase();
|
|
20
|
+
const value = typeof v === 'string' ? Buffer.from(v) : v;
|
|
21
|
+
for (let i = 0; i < headers.length; i += 2) {
|
|
22
|
+
const name = headers[i];
|
|
23
|
+
if (name &&
|
|
24
|
+
name.length === k.length &&
|
|
25
|
+
name.toString().toLowerCase() === k) {
|
|
26
|
+
return [
|
|
27
|
+
...headers.slice(0, i + 1),
|
|
28
|
+
value,
|
|
29
|
+
...headers.slice(i + 2),
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return [...headers, Buffer.from(k), value];
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=raw-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-header.js","sourceRoot":"","sources":["../../src/raw-header.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAiB,EAAE,CAAS,EAAE,EAAE;IAC3D,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;IACnB,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,IAAI,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,EACnC,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,OAAiB,EACjB,CAAS,EACT,CAAkB,EACR,EAAE;IACZ,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;IACnB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACxD,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,IAAI,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,EACnC,CAAC;YACD,OAAO;gBACL,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;gBAC1B,KAAK;gBACL,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;aACxB,CAAA;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;AAC5C,CAAC,CAAA","sourcesContent":["/**\n * Give it a key, and it'll return the buffer of that header value\n */\nexport const getRawHeader = (headers: Buffer[], k: string) => {\n k = k.toLowerCase()\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 name.toString().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: Buffer[],\n k: string,\n v: Buffer | string,\n): Buffer[] => {\n k = k.toLowerCase()\n const value = typeof v === 'string' ? Buffer.from(v) : v\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 name.toString().toLowerCase() === k\n ) {\n return [\n ...headers.slice(0, i + 1),\n value,\n ...headers.slice(i + 2),\n ]\n }\n }\n return [...headers, Buffer.from(k), value]\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CacheEntry } from './cache-entry.js';
|
|
2
|
+
import { RegistryClientRequestOptions } from './index.js';
|
|
3
|
+
export type RedirectStatus = 301 | 302 | 303 | 307 | 308;
|
|
4
|
+
export type RedirectResponse = CacheEntry & {
|
|
5
|
+
statusCode: RedirectStatus;
|
|
6
|
+
getHeader(key: 'location'): Buffer;
|
|
7
|
+
};
|
|
8
|
+
export declare const isRedirect: (response: CacheEntry) => response is RedirectResponse;
|
|
9
|
+
/**
|
|
10
|
+
* If this response is allowed to follow the redirect (because max has not
|
|
11
|
+
* been hit, and the new location has not been seen already), then return
|
|
12
|
+
* the [url, options] to use for the subsequent request.
|
|
13
|
+
*
|
|
14
|
+
* Return [] if the response should be returned as-is.
|
|
15
|
+
*
|
|
16
|
+
* Throws an error if maxRedirections is hit or the redirections set already
|
|
17
|
+
* contains the new location.
|
|
18
|
+
*
|
|
19
|
+
* Ensure that the response is in fact a redirection first, by calling
|
|
20
|
+
* {@link isRedirect} on it.
|
|
21
|
+
*/
|
|
22
|
+
export declare const redirect: (options: RegistryClientRequestOptions, response: RedirectResponse, from: URL) => [] | [URL, RegistryClientRequestOptions];
|
|
23
|
+
//# sourceMappingURL=redirect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect.d.ts","sourceRoot":"","sources":["../../src/redirect.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAA;AAEzD,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,MAAM,CAAA;CACnC,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,CAwCzC,CAAA"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// given a RegistryClientOptions object, and a redirection response,
|
|
2
|
+
import { error } from '@vltpkg/error-cause';
|
|
3
|
+
const redirectStatuses = new Set([301, 302, 303, 307, 308]);
|
|
4
|
+
export const isRedirect = (response) => redirectStatuses.has(response.statusCode) &&
|
|
5
|
+
!!response.getHeader('location')?.length;
|
|
6
|
+
/**
|
|
7
|
+
* If this response is allowed to follow the redirect (because max has not
|
|
8
|
+
* been hit, and the new location has not been seen already), then return
|
|
9
|
+
* the [url, options] to use for the subsequent request.
|
|
10
|
+
*
|
|
11
|
+
* Return [] if the response should be returned as-is.
|
|
12
|
+
*
|
|
13
|
+
* Throws an error if maxRedirections is hit or the redirections set already
|
|
14
|
+
* contains the new location.
|
|
15
|
+
*
|
|
16
|
+
* Ensure that the response is in fact a redirection first, by calling
|
|
17
|
+
* {@link isRedirect} on it.
|
|
18
|
+
*/
|
|
19
|
+
export const redirect = (options, response, from) => {
|
|
20
|
+
const { redirections = new Set(), maxRedirections = 10 } = options;
|
|
21
|
+
if (maxRedirections <= 0)
|
|
22
|
+
return [];
|
|
23
|
+
if (redirections.size >= maxRedirections) {
|
|
24
|
+
throw error('Maximum redirections exceeded', {
|
|
25
|
+
max: maxRedirections,
|
|
26
|
+
found: [...redirections],
|
|
27
|
+
url: from,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
const location = String(response.getHeader('location'));
|
|
31
|
+
const nextURL = new URL(location, from);
|
|
32
|
+
if (redirections.has(String(nextURL))) {
|
|
33
|
+
throw error('Redirection cycle detected', {
|
|
34
|
+
max: maxRedirections,
|
|
35
|
+
found: [...redirections],
|
|
36
|
+
url: from,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const nextOptions = {
|
|
40
|
+
...options,
|
|
41
|
+
redirections,
|
|
42
|
+
};
|
|
43
|
+
delete nextOptions.path;
|
|
44
|
+
redirections.add(String(nextURL));
|
|
45
|
+
switch (response.statusCode) {
|
|
46
|
+
case 303: {
|
|
47
|
+
// drop body, change method to GET
|
|
48
|
+
nextOptions.method = 'GET';
|
|
49
|
+
nextOptions.body = undefined;
|
|
50
|
+
// fallthrough
|
|
51
|
+
}
|
|
52
|
+
case 301:
|
|
53
|
+
case 302: // some user agents treat as 303, but they're wrong
|
|
54
|
+
case 307:
|
|
55
|
+
case 308: {
|
|
56
|
+
return [nextURL, nextOptions];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=redirect.js.map
|
|
@@ -0,0 +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,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAA;IACvD,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,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 { CacheEntry } from './cache-entry.js'\nimport { RegistryClientRequestOptions } from './index.js'\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'): Buffer\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 = String(response.getHeader('location'))\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 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"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This tiny module abstracts out the v8-specific serialization mechanism,
|
|
3
|
+
* so that we can swap out based on platform.
|
|
4
|
+
*
|
|
5
|
+
* Bun, Deno, and Node all export serialize/deserialize from the `node:v8`
|
|
6
|
+
* built-in module, but only Deno and Node are v8, Bun uses JSC's wire format.
|
|
7
|
+
*
|
|
8
|
+
* Any change to the serialization format is a semver-major change,
|
|
9
|
+
* but not every major-version bump is a serialization change. So, this is
|
|
10
|
+
* somewhat more conservative than necessary, but saves us having to track
|
|
11
|
+
* which major versions changed the serialization wire format.
|
|
12
|
+
*/
|
|
13
|
+
export declare const serializedHeader: string | undefined;
|
|
14
|
+
export { deserialize, serialize } from 'node:v8';
|
|
15
|
+
//# sourceMappingURL=serdes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serdes.d.ts","sourceRoot":"","sources":["../../src/serdes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,eAAO,MAAM,gBAAgB,oBAGhB,CAAA;AAEb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This tiny module abstracts out the v8-specific serialization mechanism,
|
|
3
|
+
* so that we can swap out based on platform.
|
|
4
|
+
*
|
|
5
|
+
* Bun, Deno, and Node all export serialize/deserialize from the `node:v8`
|
|
6
|
+
* built-in module, but only Deno and Node are v8, Bun uses JSC's wire format.
|
|
7
|
+
*
|
|
8
|
+
* Any change to the serialization format is a semver-major change,
|
|
9
|
+
* but not every major-version bump is a serialization change. So, this is
|
|
10
|
+
* somewhat more conservative than necessary, but saves us having to track
|
|
11
|
+
* which major versions changed the serialization wire format.
|
|
12
|
+
*/
|
|
13
|
+
import { engine } from './env.js';
|
|
14
|
+
// these aren't used if we couldn't determine the engine type & version
|
|
15
|
+
export const serializedHeader = engine ?
|
|
16
|
+
`${engine.name}-serialize-${parseInt(engine.version.replace(/[^0-9]/g, ' ').trim(), 10)}`
|
|
17
|
+
: undefined;
|
|
18
|
+
export { deserialize, serialize } from 'node:v8';
|
|
19
|
+
//# sourceMappingURL=serdes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serdes.js","sourceRoot":"","sources":["../../src/serdes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,uEAAuE;AACvE,MAAM,CAAC,MAAM,gBAAgB,GAC3B,MAAM,CAAC,CAAC;IACN,GAAG,MAAM,CAAC,IAAI,cAAc,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE;IAC3F,CAAC,CAAC,SAAS,CAAA;AAEb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA","sourcesContent":["/**\n * This tiny module abstracts out the v8-specific serialization mechanism,\n * so that we can swap out based on platform.\n *\n * Bun, Deno, and Node all export serialize/deserialize from the `node:v8`\n * built-in module, but only Deno and Node are v8, Bun uses JSC's wire format.\n *\n * Any change to the serialization format is a semver-major change,\n * but not every major-version bump is a serialization change. So, this is\n * somewhat more conservative than necessary, but saves us having to track\n * which major versions changed the serialization wire format.\n */\n\nimport { engine } from './env.js'\n\n// these aren't used if we couldn't determine the engine type & version\nexport const serializedHeader =\n engine ?\n `${engine.name}-serialize-${parseInt(engine.version.replace(/[^0-9]/g, ' ').trim(), 10)}`\n : undefined\n\nexport { deserialize, serialize } from 'node:v8'\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-cache-headers.d.ts","sourceRoot":"","sources":["../../src/set-cache-headers.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAA;AAEzD,eAAO,MAAM,eAAe,YACjB,4BAA4B,UAC7B,UAAU,KACjB,IAqBF,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Set the cache headers on a request options object
|
|
2
|
+
// based on what we know from a CacheEntry
|
|
3
|
+
import { addHeader } from './add-header.js';
|
|
4
|
+
export const setCacheHeaders = (options, entry) => {
|
|
5
|
+
if (!entry)
|
|
6
|
+
return;
|
|
7
|
+
const etag = entry.getHeader('etag')?.toString();
|
|
8
|
+
if (etag) {
|
|
9
|
+
options.headers = addHeader(options.headers, 'if-none-match', etag);
|
|
10
|
+
}
|
|
11
|
+
const date = entry.getHeader('date')?.toString() ??
|
|
12
|
+
entry.getHeader('last-modified')?.toString();
|
|
13
|
+
if (date) {
|
|
14
|
+
options.headers = addHeader(options.headers, 'if-modified-since', date);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=set-cache-headers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-cache-headers.js","sourceRoot":"","sources":["../../src/set-cache-headers.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,0CAA0C;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAI3C,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,OAAqC,EACrC,KAAkB,EACZ,EAAE;IACR,IAAI,CAAC,KAAK;QAAE,OAAM;IAClB,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAA;IAChD,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,OAAO,GAAG,SAAS,CACzB,OAAO,CAAC,OAAO,EACf,eAAe,EACf,IAAI,CACL,CAAA;IACH,CAAC;IAED,MAAM,IAAI,GACR,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE;QACnC,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,QAAQ,EAAE,CAAA;IAC9C,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,OAAO,GAAG,SAAS,CACzB,OAAO,CAAC,OAAO,EACf,mBAAmB,EACnB,IAAI,CACL,CAAA;IACH,CAAC;AACH,CAAC,CAAA","sourcesContent":["// Set the cache headers on a request options object\n// based on what we know from a CacheEntry\n\nimport { addHeader } from './add-header.js'\nimport { CacheEntry } from './cache-entry.js'\nimport { RegistryClientRequestOptions } from './index.js'\n\nexport const setCacheHeaders = (\n options: RegistryClientRequestOptions,\n entry?: CacheEntry,\n): void => {\n if (!entry) return\n const etag = entry.getHeader('etag')?.toString()\n if (etag) {\n options.headers = addHeader(\n options.headers,\n 'if-none-match',\n etag,\n )\n }\n\n const date =\n entry.getHeader('date')?.toString() ??\n entry.getHeader('last-modified')?.toString()\n if (date) {\n options.headers = addHeader(\n options.headers,\n 'if-modified-since',\n date,\n )\n }\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Given a rawHeaders array of [key, value, key2, value2, ...],
|
|
3
|
+
* overwrite the current value of a header, or if not found, append
|
|
4
|
+
*/
|
|
5
|
+
export declare const setRawHeader: (headers: Buffer[], key: string, value: Buffer | string) => void;
|
|
6
|
+
//# sourceMappingURL=set-raw-header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-raw-header.d.ts","sourceRoot":"","sources":["../../src/set-raw-header.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,YAAY,YACd,MAAM,EAAE,OACZ,MAAM,SACJ,MAAM,GAAG,MAAM,SAiBvB,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Given a rawHeaders array of [key, value, key2, value2, ...],
|
|
3
|
+
* overwrite the current value of a header, or if not found, append
|
|
4
|
+
*/
|
|
5
|
+
export const setRawHeader = (headers, key, value) => {
|
|
6
|
+
key = key.toLowerCase();
|
|
7
|
+
const keyBuf = Buffer.from(key);
|
|
8
|
+
const valBuf = Buffer.isBuffer(value) ? value : Buffer.from(value);
|
|
9
|
+
for (let i = 0; i < headers.length; i += 2) {
|
|
10
|
+
const k = headers[i];
|
|
11
|
+
if (k &&
|
|
12
|
+
k.length === keyBuf.length &&
|
|
13
|
+
String(k).toLowerCase() === key) {
|
|
14
|
+
headers[i + 1] = valBuf;
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
headers.push(keyBuf, valBuf);
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=set-raw-header.js.map
|
|
@@ -0,0 +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,OAAiB,EACjB,GAAW,EACX,KAAsB,EACtB,EAAE;IACF,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,CAAA;IACvB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAClE,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,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,GAAG,EAC/B,CAAC;YACD,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAA;YACvB,OAAM;QACR,CAAC;IACH,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAC9B,CAAC,CAAA","sourcesContent":["/**\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: Buffer[],\n key: string,\n value: Buffer | string,\n) => {\n key = key.toLowerCase()\n const keyBuf = Buffer.from(key)\n const valBuf = Buffer.isBuffer(value) ? value : Buffer.from(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 String(k).toLowerCase() === key\n ) {\n headers[i + 1] = valBuf\n return\n }\n }\n headers.push(keyBuf, valBuf)\n}\n"]}
|