@vltpkg/registry-client 0.0.0-2 → 0.0.0-21
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 +50 -53
- package/dist/esm/cache-entry.d.ts +55 -9
- package/dist/esm/cache-entry.d.ts.map +1 -1
- package/dist/esm/cache-entry.js +152 -37
- package/dist/esm/cache-entry.js.map +1 -1
- package/dist/esm/cache-revalidate.d.ts +2 -0
- package/dist/esm/cache-revalidate.d.ts.map +1 -0
- package/dist/esm/cache-revalidate.js +66 -0
- package/dist/esm/cache-revalidate.js.map +1 -0
- package/dist/esm/index.d.ts +40 -9
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +87 -50
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/otplease.d.ts.map +1 -1
- package/dist/esm/otplease.js +33 -25
- package/dist/esm/otplease.js.map +1 -1
- package/dist/esm/revalidate.d.ts +5 -0
- package/dist/esm/revalidate.d.ts.map +1 -0
- package/dist/esm/revalidate.js +55 -0
- package/dist/esm/revalidate.js.map +1 -0
- package/dist/esm/token-response.d.ts +1 -1
- package/dist/esm/token-response.d.ts.map +1 -1
- package/dist/esm/token-response.js +5 -2
- package/dist/esm/token-response.js.map +1 -1
- package/dist/esm/web-auth-challenge.d.ts +2 -2
- package/dist/esm/web-auth-challenge.d.ts.map +1 -1
- package/dist/esm/web-auth-challenge.js +13 -6
- package/dist/esm/web-auth-challenge.js.map +1 -1
- package/package.json +19 -20
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-entry.js","sourceRoot":"","sources":["../../src/cache-entry.ts"],"names":[],"mappings":"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","sourcesContent":["// A response object in the cache.\n//\n// The cache stores Buffer objects, and it's convenient to have headers/body\n// together, so we have a simple data structure for this.\n//\n// The shape of it is:\n//\n// [head length]\n// <status code in ascii>\n// [headers]\n// [body]\n//\n// The [UInt32BE head length] is 4 bytes specifying the full length of the\n// status code plus all header keys and values.\n//\n// The [headers] section is key/value/key2/value2/... where each key and value\n// is a 4-byte Uint32BE length, followed by that many bytes.\n//\n// From there, the body can be of any indeterminate length, and is the rest\n// of the file.\n\nimport { error } from '@vltpkg/error-cause'\nimport type { Integrity, JSONField } from '@vltpkg/types'\nimport ccp from 'cache-control-parser'\nimport { createHash } from 'crypto'\nimport { inspect } from 'util'\nimport type { InspectOptions } from 'util'\nimport { gunzipSync } from 'zlib'\nimport { getRawHeader, setRawHeader } from './raw-header.ts'\n\nexport type JSONObj = Record<string, JSONField>\n\nconst readSize = (buf: Buffer, offset: number) => {\n const a = buf[offset]\n const b = buf[offset + 1]\n const c = buf[offset + 2]\n const d = buf[offset + 3]\n\n // not possible, we check the length\n /* c8 ignore start */\n if (\n a === undefined ||\n b === undefined ||\n c === undefined ||\n d === undefined\n ) {\n throw error('Invalid buffer, not long enough to readSize', {\n found: buf.length,\n })\n }\n /* c8 ignore stop */\n\n return (a << 24) | (b << 16) | (c << 8) | d\n}\n\nconst kCustomInspect = Symbol.for('nodejs.util.inspect.custom')\n\nexport class CacheEntry {\n #statusCode: number\n #headers: Buffer[]\n #body: Buffer[] = []\n #bodyLength = 0\n #integrity?: Integrity\n #integrityActual?: Integrity\n #json?: JSONObj\n\n constructor(\n statusCode: number,\n headers: Buffer[],\n integrity?: Integrity,\n ) {\n this.#integrity = integrity\n this.#statusCode = statusCode\n this.#headers = headers\n }\n\n get #headersAsObject(): [string, string][] {\n const ret: [string, string][] = []\n for (let i = 0; i < this.#headers.length - 1; i += 2) {\n const key = String(this.#headers[i])\n const val = String(this.#headers[i + 1])\n ret.push([key, val])\n }\n return ret\n }\n\n [kCustomInspect](depth: number, options: InspectOptions): string {\n const str = inspect(\n {\n statusCode: this.statusCode,\n headers: this.#headersAsObject,\n text: this.text(),\n },\n {\n depth,\n ...options,\n },\n )\n return `@vltpkg/registry-client.CacheEntry ${str}`\n }\n\n /**\n * `true` if the entry represents a cached response that is still\n * valid to use.\n */\n get valid(): boolean {\n const cc_ = this.getHeader('cache-control')?.toString()\n const cc = cc_ ? ccp.parse(cc_) : {}\n const ct = this.getHeader('content-type')?.toString() ?? ''\n const dh = this.getHeader('date')?.toString()\n\n // immutable = never changes\n if (cc.immutable) return true\n\n // some registries do text/json, some do application/json,\n // some do application/vnd.npm.install-v1+json\n // If it's NOT json, it's an immutable tarball\n if (ct !== '' && !/\\bjson\\b/.test(ct)) return true\n\n // see if the max-age has not yet been crossed\n // default to 5m if maxage is not set, as some registries\n // do not set a cache control header at all.\n const ma = cc['max-age'] || cc['s-maxage'] || 300\n if (ma && dh) {\n return Date.parse(dh) + ma * 1000 > Date.now()\n }\n return false\n }\n\n addBody(b: Buffer) {\n this.#body.push(b)\n this.#bodyLength += b.byteLength\n }\n\n get statusCode() {\n return this.#statusCode\n }\n get headers() {\n return this.#headers\n }\n\n /**\n * check that the sri integrity string that was provided to the ctor\n * matches the body that we actually received. This should only be called\n * AFTER the entire body has been completely downloaded.\n *\n * Note that this will *usually* not be true if the value is coming out of\n * the cache, because the cache entries are un-gzipped in place. It should\n * _only_ be called for artifacts that come from an actual http response.\n */\n checkIntegrity(): boolean {\n if (!this.#integrity) return false\n return this.integrityActual === this.#integrity\n }\n get integrityActual(): Integrity {\n if (this.#integrityActual) return this.#integrityActual\n const hash = createHash('sha512')\n for (const buf of this.#body) hash.update(buf)\n this.#integrityActual = `sha512-${hash.digest('base64')}`\n return this.#integrityActual\n }\n get integrity() {\n return this.#integrity\n }\n\n /**\n * Give it a key, and it'll return the buffer of that header value\n */\n getHeader(h: string) {\n return getRawHeader(this.#headers, h)\n }\n\n /**\n * Set a header to a specific value\n */\n setHeader(h: string, value: Buffer | string) {\n this.#headers = setRawHeader(this.#headers, h, value)\n }\n\n /**\n * Return the body of the entry as a Buffer\n */\n buffer(): Buffer {\n const b = this.#body[0]\n if (!b) return Buffer.allocUnsafe(0)\n if (this.#body.length === 1) return b\n const cat = Buffer.concat(this.#body, this.#bodyLength)\n this.#body = [cat]\n return cat\n }\n\n // return the buffer if it's a tarball, or the parsed\n // JSON if it's not.\n get body(): Buffer | Record<string, any> {\n return this.isJSON ? this.json() : this.buffer()\n }\n\n #isJSON?: boolean\n get isJSON(): boolean {\n if (this.#isJSON !== undefined) return this.#isJSON\n const ct = this.getHeader('content-type')?.toString()\n // if it says it's json, assume json\n if (ct) return (this.#isJSON = /\\bjson\\b/.test(ct))\n const text = this.text()\n // don't cache, because we might just not have it yet.\n if (!text) return false\n // all registry json starts with {, and no tarball ever can.\n this.#isJSON = text.startsWith('{')\n if (this.#isJSON) this.setHeader('content-type', 'text/json')\n return this.#isJSON\n }\n\n #isGzip?: boolean\n get isGzip(): boolean {\n if (this.#isGzip !== undefined) return this.#isGzip\n const ce = this.getHeader('content-encoding')?.toString()\n if (ce && !/\\bgzip\\b/.test(ce)) return (this.#isGzip = false)\n const buf = this.buffer()\n if (buf.length < 2) return false\n this.#isGzip = buf[0] === 0x1f && buf[1] === 0x8b\n if (this.#isGzip) {\n this.setHeader('content-encoding', 'gzip')\n } else {\n this.setHeader('content-encoding', 'identity')\n this.setHeader('content-length', String(this.#bodyLength))\n }\n return this.#isGzip\n }\n\n /**\n * Un-gzip encode the body.\n * Returns true if it was previously gzip (so something was done), otherwise\n * returns false.\n */\n unzip() {\n if (this.isGzip) {\n // we know that if we know it's gzip, that the body has been\n // flattened to a single buffer, so save the extra call.\n /* c8 ignore start */\n if (this.#body[0] == null)\n throw error('Invalid buffer, cant unzip')\n /* c8 ignore stop */\n const b = gunzipSync(this.#body[0])\n this.setHeader('content-encoding', 'identity')\n this.#body = [b]\n this.#bodyLength = b.byteLength\n this.setHeader('content-length', String(this.#bodyLength))\n this.#isGzip = false\n return true\n }\n return false\n }\n\n /**\n * Return the body of the entry as utf8 text\n * Automatically unzips if the content is gzip encoded\n */\n text() {\n this.unzip()\n return this.buffer().toString()\n }\n\n /**\n * Parse the entry body as JSON and return the result\n */\n json(): JSONObj {\n if (this.#json !== undefined) return this.#json\n const obj = JSON.parse(this.text()) as JSONObj\n this.#json = obj\n return obj\n }\n\n /**\n * Pass the contents of a @vltpkg/cache.Cache object as a buffer,\n * and this static method will decode it into a CacheEntry representing\n * the cached response.\n */\n static decode(buffer: Buffer): CacheEntry {\n if (buffer.length < 4) {\n return new CacheEntry(0, [])\n }\n const headSize = readSize(buffer, 0)\n if (buffer.length < headSize) {\n return new CacheEntry(0, [])\n }\n const statusCode = Number(buffer.subarray(4, 7).toString())\n const headersBuffer = buffer.subarray(7, headSize)\n // walk through the headers array, building up the rawHeaders Buffer[]\n const headers: Buffer[] = []\n let i = 0\n while (i < headersBuffer.length - 4) {\n const size = readSize(headersBuffer, i)\n headers.push(headersBuffer.subarray(i + 4, i + size))\n i += size\n }\n const c = new CacheEntry(statusCode, headers)\n const body = buffer.subarray(headSize)\n c.#body = [body]\n c.#bodyLength = body.byteLength\n c.setHeader('content-length', String(c.#bodyLength))\n if (c.isJSON) {\n try {\n c.json()\n } catch {\n return new CacheEntry(0, [])\n }\n }\n return c\n }\n\n /**\n * Encode the entry as a single Buffer for writing to the cache\n */\n // TODO: should this maybe not concat, and just return Buffer[]?\n // Then we can writev it to the cache file and save the memory copy\n encode(): Buffer {\n // store json results as a serialized object.\n if (this.isJSON) this.json()\n const sb = Buffer.from(String(this.#statusCode))\n const chunks: Buffer[] = [sb]\n let headLength = sb.byteLength + 4\n for (const h of this.#headers) {\n const hlBuf = Buffer.allocUnsafe(4)\n const hl = h.byteLength + 4\n headLength += hl\n hlBuf.set(\n [\n (hl >> 24) & 0xff,\n (hl >> 16) & 0xff,\n (hl >> 8) & 0xff,\n hl & 0xff,\n ],\n 0,\n )\n chunks.push(hlBuf, h)\n }\n\n const hlBuf = Buffer.allocUnsafe(4)\n hlBuf.set(\n [\n (headLength >> 24) & 0xff,\n (headLength >> 16) & 0xff,\n (headLength >> 8) & 0xff,\n headLength & 0xff,\n ],\n 0,\n )\n chunks.unshift(hlBuf)\n chunks.push(...this.#body)\n return Buffer.concat(chunks, headLength + this.#bodyLength)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cache-entry.js","sourceRoot":"","sources":["../../src/cache-entry.ts"],"names":[],"mappings":"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","sourcesContent":["// A response object in the cache.\n//\n// The cache stores Buffer objects, and it's convenient to have headers/body\n// together, so we have a simple data structure for this.\n//\n// The shape of it is:\n//\n// [head length]\n// <status code in ascii>\n// [headers]\n// [body]\n//\n// The [UInt32BE head length] is 4 bytes specifying the full length of the\n// status code plus all header keys and values.\n//\n// The [headers] section is key/value/key2/value2/... where each key and value\n// is a 4-byte Uint32BE length, followed by that many bytes.\n//\n// From there, the body can be of any indeterminate length, and is the rest\n// of the file.\n\nimport type { 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"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-revalidate.d.ts","sourceRoot":"","sources":["../../src/cache-revalidate.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,QAAQ,SACb,MAAM,UACJ,MAAM,GAAG,KAAK,OACjB,MAAM,GAAG,GAAG,KAChB,IASF,CAAA"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { __CODE_SPLIT_SCRIPT_NAME } from "./revalidate.js";
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
const isDeno = globalThis.Deno != undefined;
|
|
5
|
+
let didProcessBeforeExitHook = false;
|
|
6
|
+
const registered = new Map();
|
|
7
|
+
export const register = (path, method, url) => {
|
|
8
|
+
const r = registered.get(path) ?? new Set();
|
|
9
|
+
const key = `${method} ${url}`;
|
|
10
|
+
r.add(key);
|
|
11
|
+
registered.set(path, r);
|
|
12
|
+
if (!didProcessBeforeExitHook) {
|
|
13
|
+
didProcessBeforeExitHook = true;
|
|
14
|
+
process.on('beforeExit', handleBeforeExit);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const handleBeforeExit = () => {
|
|
18
|
+
for (const [path, r] of registered) {
|
|
19
|
+
/* c8 ignore next */
|
|
20
|
+
if (!r.size)
|
|
21
|
+
return;
|
|
22
|
+
const env = { ...process.env };
|
|
23
|
+
const args = [];
|
|
24
|
+
/* c8 ignore start */
|
|
25
|
+
// When compiled the script to be run is passed as an
|
|
26
|
+
// environment variable and then routed by the main entry point
|
|
27
|
+
if (process.env.__VLT_INTERNAL_COMPILED) {
|
|
28
|
+
env.__VLT_INTERNAL_MAIN = pathToFileURL(__CODE_SPLIT_SCRIPT_NAME).toString();
|
|
29
|
+
args.push(path);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// If we are running deno from source we need to add the
|
|
33
|
+
// unstable flags we need. The '-A' flag does not need
|
|
34
|
+
// to be passed in as Deno supplies that automatically.
|
|
35
|
+
if (isDeno) {
|
|
36
|
+
args.push('--unstable-node-globals', '--unstable-bare-node-builtins');
|
|
37
|
+
}
|
|
38
|
+
/* c8 ignore stop */
|
|
39
|
+
args.push(__CODE_SPLIT_SCRIPT_NAME, path);
|
|
40
|
+
}
|
|
41
|
+
registered.delete(path);
|
|
42
|
+
// Deno on Windows does not support detached processes
|
|
43
|
+
// https://github.com/denoland/deno/issues/25867
|
|
44
|
+
// TODO: figure out something better to do here?
|
|
45
|
+
/* c8 ignore next */
|
|
46
|
+
const detached = !(isDeno && process.platform === 'win32');
|
|
47
|
+
const proc = spawn(process.execPath, args, {
|
|
48
|
+
detached,
|
|
49
|
+
stdio: ['pipe', 'ignore', 'ignore'],
|
|
50
|
+
env,
|
|
51
|
+
});
|
|
52
|
+
for (const key of r) {
|
|
53
|
+
proc.stdin.write(`${key}\0`);
|
|
54
|
+
}
|
|
55
|
+
proc.stdin.end();
|
|
56
|
+
// Another Deno oddity. Calling unref on a spawned process will kill the
|
|
57
|
+
// process unless it is detached. https://github.com/denoland/deno/issues/21446
|
|
58
|
+
// So in this case Deno on Windows will be slower to exit the main process
|
|
59
|
+
// since it will wait for the child process to exit.
|
|
60
|
+
// TODO: figure out something better to do here?
|
|
61
|
+
if (detached) {
|
|
62
|
+
proc.unref();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=cache-revalidate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-revalidate.js","sourceRoot":"","sources":["../../src/cache-revalidate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,MAAM,MAAM,GACT,UAAiD,CAAC,IAAI,IAAI,SAAS,CAAA;AAEtE,IAAI,wBAAwB,GAAG,KAAK,CAAA;AACpC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAA;AAEjD,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,IAAY,EACZ,MAAsB,EACtB,GAAiB,EACX,EAAE;IACR,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,EAAU,CAAA;IACnD,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,GAAG,EAAE,CAAA;IAC9B,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACV,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;IACvB,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAC9B,wBAAwB,GAAG,IAAI,CAAA;QAC/B,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAA;IAC5C,CAAC;AACH,CAAC,CAAA;AAED,MAAM,gBAAgB,GAAG,GAAG,EAAE;IAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,UAAU,EAAE,CAAC;QACnC,oBAAoB;QACpB,IAAI,CAAC,CAAC,CAAC,IAAI;YAAE,OAAM;QACnB,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;QAC9B,MAAM,IAAI,GAAG,EAAE,CAAA;QACf,qBAAqB;QACrB,qDAAqD;QACrD,+DAA+D;QAC/D,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC;YACxC,GAAG,CAAC,mBAAmB,GAAG,aAAa,CACrC,wBAAwB,CACzB,CAAC,QAAQ,EAAE,CAAA;YACZ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjB,CAAC;aAAM,CAAC;YACN,wDAAwD;YACxD,sDAAsD;YACtD,uDAAuD;YACvD,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,IAAI,CACP,yBAAyB,EACzB,+BAA+B,CAChC,CAAA;YACH,CAAC;YACD,oBAAoB;YACpB,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAA;QAC3C,CAAC;QACD,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACvB,sDAAsD;QACtD,gDAAgD;QAChD,gDAAgD;QAChD,oBAAoB;QACpB,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAA;QAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE;YACzC,QAAQ;YACR,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC;YACnC,GAAG;SACJ,CAAC,CAAA;QACF,KAAK,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;YACpB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAA;QAC9B,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;QAChB,wEAAwE;QACxE,+EAA+E;QAC/E,0EAA0E;QAC1E,oDAAoD;QACpD,gDAAgD;QAChD,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;AACH,CAAC,CAAA","sourcesContent":["import { spawn } from 'node:child_process'\nimport { __CODE_SPLIT_SCRIPT_NAME } from './revalidate.ts'\nimport { pathToFileURL } from 'node:url'\n\nconst isDeno =\n (globalThis as typeof globalThis & { Deno?: any }).Deno != undefined\n\nlet didProcessBeforeExitHook = false\nconst registered = new Map<string, Set<string>>()\n\nexport const register = (\n path: string,\n method: 'HEAD' | 'GET',\n url: string | URL,\n): void => {\n const r = registered.get(path) ?? new Set<string>()\n const key = `${method} ${url}`\n r.add(key)\n registered.set(path, r)\n if (!didProcessBeforeExitHook) {\n didProcessBeforeExitHook = true\n process.on('beforeExit', handleBeforeExit)\n }\n}\n\nconst handleBeforeExit = () => {\n for (const [path, r] of registered) {\n /* c8 ignore next */\n if (!r.size) return\n const env = { ...process.env }\n const args = []\n /* c8 ignore start */\n // When compiled the script to be run is passed as an\n // environment variable and then routed by the main entry point\n if (process.env.__VLT_INTERNAL_COMPILED) {\n env.__VLT_INTERNAL_MAIN = pathToFileURL(\n __CODE_SPLIT_SCRIPT_NAME,\n ).toString()\n args.push(path)\n } else {\n // If we are running deno from source we need to add the\n // unstable flags we need. The '-A' flag does not need\n // to be passed in as Deno supplies that automatically.\n if (isDeno) {\n args.push(\n '--unstable-node-globals',\n '--unstable-bare-node-builtins',\n )\n }\n /* c8 ignore stop */\n args.push(__CODE_SPLIT_SCRIPT_NAME, path)\n }\n registered.delete(path)\n // Deno on Windows does not support detached processes\n // https://github.com/denoland/deno/issues/25867\n // TODO: figure out something better to do here?\n /* c8 ignore next */\n const detached = !(isDeno && process.platform === 'win32')\n const proc = spawn(process.execPath, args, {\n detached,\n stdio: ['pipe', 'ignore', 'ignore'],\n env,\n })\n for (const key of r) {\n proc.stdin.write(`${key}\\0`)\n }\n proc.stdin.end()\n // Another Deno oddity. Calling unref on a spawned process will kill the\n // process unless it is detached. https://github.com/denoland/deno/issues/21446\n // So in this case Deno on Windows will be slower to exit the main process\n // since it will wait for the child process to exit.\n // TODO: figure out something better to do here?\n if (detached) {\n proc.unref()\n }\n }\n}\n"]}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { Cache } from '@vltpkg/cache';
|
|
2
2
|
import type { Integrity } from '@vltpkg/types';
|
|
3
|
-
import { RetryAgent } from 'undici';
|
|
4
3
|
import type { Dispatcher } from 'undici';
|
|
5
|
-
import {
|
|
4
|
+
import { RetryAgent } from 'undici';
|
|
6
5
|
import type { Token } from './auth.ts';
|
|
7
|
-
import {
|
|
6
|
+
import { deleteToken, getKC, isToken, keychains, setToken } from './auth.ts';
|
|
8
7
|
import type { JSONObj } from './cache-entry.ts';
|
|
8
|
+
import { CacheEntry } from './cache-entry.ts';
|
|
9
9
|
import type { TokenResponse } from './token-response.ts';
|
|
10
10
|
import type { WebAuthChallenge } from './web-auth-challenge.ts';
|
|
11
|
-
export {
|
|
12
|
-
export
|
|
11
|
+
export { CacheEntry, deleteToken, getKC, isToken, keychains, setToken, type JSONObj, type Token, type TokenResponse, type WebAuthChallenge, };
|
|
12
|
+
export type CacheableMethod = 'GET' | 'HEAD';
|
|
13
|
+
export declare const isCacheableMethod: (m: unknown) => m is CacheableMethod;
|
|
13
14
|
export type RegistryClientOptions = {
|
|
14
15
|
/**
|
|
15
16
|
* Path on disk where the cache should be stored
|
|
16
|
-
*
|
|
17
|
+
*
|
|
18
|
+
* Defaults to the XDG cache folder for `vlt/registry-client`
|
|
17
19
|
*/
|
|
18
20
|
cache?: string;
|
|
19
21
|
/**
|
|
@@ -29,6 +31,22 @@ export type RegistryClientOptions = {
|
|
|
29
31
|
'fetch-retry-maxtimeout'?: number;
|
|
30
32
|
/** the identity to use for storing auth tokens */
|
|
31
33
|
identity?: string;
|
|
34
|
+
/**
|
|
35
|
+
* If the server does not serve a `stale-while-revalidate` value in the
|
|
36
|
+
* `cache-control` header, then this multiplier is applied to the `max-age`
|
|
37
|
+
* or `s-maxage` values.
|
|
38
|
+
*
|
|
39
|
+
* By default, this is `60`, so for example a response that is cacheable for
|
|
40
|
+
* 5 minutes will allow a stale response while revalidating for up to 5
|
|
41
|
+
* hours.
|
|
42
|
+
*
|
|
43
|
+
* If the server *does* provide a `stale-while-revalidate` value, then that
|
|
44
|
+
* is always used.
|
|
45
|
+
*
|
|
46
|
+
* Set to 0 to prevent any `stale-while-revalidate` behavior unless
|
|
47
|
+
* explicitly allowed by the server's `cache-control` header.
|
|
48
|
+
*/
|
|
49
|
+
'stale-while-revalidate-factor'?: number;
|
|
32
50
|
};
|
|
33
51
|
export type RegistryClientRequestOptions = Omit<Dispatcher.RequestOptions, 'method' | 'path'> & {
|
|
34
52
|
/**
|
|
@@ -49,6 +67,12 @@ export type RegistryClientRequestOptions = Omit<Dispatcher.RequestOptions, 'meth
|
|
|
49
67
|
* the local disk cache, items are assumed to be trustworthy.
|
|
50
68
|
*/
|
|
51
69
|
integrity?: Integrity;
|
|
70
|
+
/**
|
|
71
|
+
* Set to true if the integrity should be trusted implicitly without
|
|
72
|
+
* a recalculation, for example if it comes from a trusted registry that
|
|
73
|
+
* also serves the tarball itself.
|
|
74
|
+
*/
|
|
75
|
+
trustIntegrity?: boolean;
|
|
52
76
|
/**
|
|
53
77
|
* Follow up to 10 redirections by default. Set this to 0 to just return
|
|
54
78
|
* the 3xx response. If the max redirections are expired, and we still get
|
|
@@ -66,7 +90,7 @@ export type RegistryClientRequestOptions = Omit<Dispatcher.RequestOptions, 'meth
|
|
|
66
90
|
* Set to `false` to suppress ANY lookups from cache. This will also
|
|
67
91
|
* prevent storing the result to the cache.
|
|
68
92
|
*/
|
|
69
|
-
|
|
93
|
+
useCache?: false;
|
|
70
94
|
/**
|
|
71
95
|
* Set to pass an `npm-otp` header on the request.
|
|
72
96
|
*
|
|
@@ -75,6 +99,12 @@ export type RegistryClientRequestOptions = Omit<Dispatcher.RequestOptions, 'meth
|
|
|
75
99
|
* @internal
|
|
76
100
|
*/
|
|
77
101
|
otp?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Set to false to explicitly prevent `stale-while-revalidate` behavior,
|
|
104
|
+
* for use in revalidating while stale.
|
|
105
|
+
* @internal
|
|
106
|
+
*/
|
|
107
|
+
staleWhileRevalidate?: false;
|
|
78
108
|
};
|
|
79
109
|
export declare const userAgent: string;
|
|
80
110
|
export declare class RegistryClient {
|
|
@@ -82,6 +112,7 @@ export declare class RegistryClient {
|
|
|
82
112
|
agent: RetryAgent;
|
|
83
113
|
cache: Cache;
|
|
84
114
|
identity: string;
|
|
115
|
+
staleWhileRevalidateFactor: number;
|
|
85
116
|
constructor(options: RegistryClientOptions);
|
|
86
117
|
/**
|
|
87
118
|
* Fetch the entire set of a paginated list of objects
|
|
@@ -104,10 +135,10 @@ export declare class RegistryClient {
|
|
|
104
135
|
*/
|
|
105
136
|
login(registry: string): Promise<void>;
|
|
106
137
|
/**
|
|
107
|
-
* Given a {@link WebAuthChallenge}, open the `
|
|
138
|
+
* Given a {@link WebAuthChallenge}, open the `authUrl` in a browser and
|
|
108
139
|
* hang on the `doneUrl` until it returns a {@link TokenResponse} object.
|
|
109
140
|
*/
|
|
110
|
-
webAuthOpener({ doneUrl,
|
|
141
|
+
webAuthOpener({ doneUrl, authUrl }: WebAuthChallenge): Promise<TokenResponse>;
|
|
111
142
|
request(url: URL | string, options?: RegistryClientRequestOptions): Promise<CacheEntry>;
|
|
112
143
|
}
|
|
113
144
|
//# sourceMappingURL=index.d.ts.map
|
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;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import { Cache } from '@vltpkg/cache';
|
|
2
|
-
import { register } from '@vltpkg/cache-unzip';
|
|
2
|
+
import { register as cacheUnzipRegister } from '@vltpkg/cache-unzip';
|
|
3
3
|
import { error } from '@vltpkg/error-cause';
|
|
4
|
+
import { asError } from '@vltpkg/types';
|
|
5
|
+
import { logRequest } from '@vltpkg/output';
|
|
4
6
|
import { urlOpen } from '@vltpkg/url-open';
|
|
5
7
|
import { XDG } from '@vltpkg/xdg';
|
|
8
|
+
import { dirname, resolve } from 'node:path';
|
|
6
9
|
import { setTimeout } from 'node:timers/promises';
|
|
7
10
|
import { loadPackageJson } from 'package-json-from-dist';
|
|
8
11
|
import { Agent, RetryAgent } from 'undici';
|
|
9
12
|
import { addHeader } from "./add-header.js";
|
|
10
13
|
import { deleteToken, getKC, getToken, isToken, keychains, setToken, } from "./auth.js";
|
|
11
14
|
import { CacheEntry } from "./cache-entry.js";
|
|
15
|
+
import { register } from "./cache-revalidate.js";
|
|
12
16
|
import { bun, deno, node } from "./env.js";
|
|
13
17
|
import { handle304Response } from "./handle-304-response.js";
|
|
14
18
|
import { otplease } from "./otplease.js";
|
|
15
19
|
import { isRedirect, redirect } from "./redirect.js";
|
|
16
20
|
import { setCacheHeaders } from "./set-cache-headers.js";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
export
|
|
21
|
+
import { getTokenResponse } from "./token-response.js";
|
|
22
|
+
import { getWebAuthChallenge } from "./web-auth-challenge.js";
|
|
23
|
+
export { CacheEntry, deleteToken, getKC, isToken, keychains, setToken, };
|
|
24
|
+
export const isCacheableMethod = (m) => m === 'GET' || m === 'HEAD';
|
|
21
25
|
const { version } = loadPackageJson(import.meta.filename, process.env.__VLT_INTERNAL_REGISTRY_CLIENT_PACKAGE_JSON);
|
|
22
26
|
const nua = globalThis.navigator?.userAgent ??
|
|
23
27
|
(bun ? `Bun/${bun}`
|
|
@@ -45,14 +49,18 @@ export class RegistryClient {
|
|
|
45
49
|
agent;
|
|
46
50
|
cache;
|
|
47
51
|
identity;
|
|
52
|
+
staleWhileRevalidateFactor;
|
|
48
53
|
constructor(options) {
|
|
49
|
-
const { cache = xdg.cache(
|
|
54
|
+
const { cache = xdg.cache(), 'fetch-retry-factor': timeoutFactor = 2, 'fetch-retry-mintimeout': minTimeout = 0, 'fetch-retry-maxtimeout': maxTimeout = 30_000, 'fetch-retries': maxRetries = 3, identity = '', 'stale-while-revalidate-factor': staleWhileRevalidateFactor = 60, } = options;
|
|
50
55
|
this.identity = identity;
|
|
56
|
+
this.staleWhileRevalidateFactor = staleWhileRevalidateFactor;
|
|
57
|
+
const path = resolve(cache, 'registry-client');
|
|
51
58
|
this.cache = new Cache({
|
|
52
|
-
path
|
|
59
|
+
path,
|
|
53
60
|
onDiskWrite(_path, key, data) {
|
|
54
|
-
if (CacheEntry.
|
|
55
|
-
|
|
61
|
+
if (CacheEntry.isGzipEntry(data)) {
|
|
62
|
+
cacheUnzipRegister(path, key);
|
|
63
|
+
}
|
|
56
64
|
},
|
|
57
65
|
});
|
|
58
66
|
const dispatch = new Agent(agentOptions);
|
|
@@ -103,11 +111,11 @@ export class RegistryClient {
|
|
|
103
111
|
const s = tok.replace(/^(Bearer|Basic) /i, '');
|
|
104
112
|
const tokensUrl = new URL('-/npm/v1/tokens', registry);
|
|
105
113
|
const record = await this.seek(tokensUrl, ({ token }) => s.startsWith(token), {
|
|
106
|
-
|
|
114
|
+
useCache: false,
|
|
107
115
|
}).catch(() => undefined);
|
|
108
116
|
if (record) {
|
|
109
117
|
const { key } = record;
|
|
110
|
-
await this.request(new URL(`-/npm/v1/tokens/token/${key}`, registry), {
|
|
118
|
+
await this.request(new URL(`-/npm/v1/tokens/token/${key}`, registry), { useCache: false, method: 'DELETE' });
|
|
111
119
|
}
|
|
112
120
|
await deleteToken(registry, this.identity);
|
|
113
121
|
}
|
|
@@ -120,15 +128,15 @@ export class RegistryClient {
|
|
|
120
128
|
async login(registry) {
|
|
121
129
|
// - make POST to '/-/v1/login'
|
|
122
130
|
// - include a body of {} and npm-auth-type:web
|
|
123
|
-
// - get a {doneUrl,
|
|
124
|
-
// - open the
|
|
131
|
+
// - get a {doneUrl, authUrl}
|
|
132
|
+
// - open the authUrl
|
|
125
133
|
// - hang on the doneUrl until done
|
|
126
134
|
//
|
|
127
135
|
// if that fails: fall back to couchdb login
|
|
128
136
|
const webLoginURL = new URL('-/v1/login', registry);
|
|
129
137
|
const response = await this.request(webLoginURL, {
|
|
130
138
|
method: 'POST',
|
|
131
|
-
|
|
139
|
+
useCache: false,
|
|
132
140
|
headers: {
|
|
133
141
|
'content-type': 'application/json',
|
|
134
142
|
'npm-auth-type': 'web',
|
|
@@ -136,8 +144,8 @@ export class RegistryClient {
|
|
|
136
144
|
body: '{}',
|
|
137
145
|
});
|
|
138
146
|
if (response.statusCode === 200) {
|
|
139
|
-
const challenge = response.json();
|
|
140
|
-
if (
|
|
147
|
+
const challenge = getWebAuthChallenge(response.json());
|
|
148
|
+
if (challenge) {
|
|
141
149
|
const result = await this.webAuthOpener(challenge);
|
|
142
150
|
await setToken(registry, `Bearer ${result.token}`, this.identity);
|
|
143
151
|
return;
|
|
@@ -149,10 +157,10 @@ export class RegistryClient {
|
|
|
149
157
|
}
|
|
150
158
|
/* c8 ignore stop */
|
|
151
159
|
/**
|
|
152
|
-
* Given a {@link WebAuthChallenge}, open the `
|
|
160
|
+
* Given a {@link WebAuthChallenge}, open the `authUrl` in a browser and
|
|
153
161
|
* hang on the `doneUrl` until it returns a {@link TokenResponse} object.
|
|
154
162
|
*/
|
|
155
|
-
async webAuthOpener({ doneUrl,
|
|
163
|
+
async webAuthOpener({ doneUrl, authUrl }) {
|
|
156
164
|
const ac = new AbortController();
|
|
157
165
|
const { signal } = ac;
|
|
158
166
|
/* c8 ignore start - race condition */
|
|
@@ -161,8 +169,8 @@ export class RegistryClient {
|
|
|
161
169
|
ac.abort();
|
|
162
170
|
return result;
|
|
163
171
|
}),
|
|
164
|
-
urlOpen(
|
|
165
|
-
if (er.name === 'AbortError')
|
|
172
|
+
urlOpen(authUrl, { signal }).catch((er) => {
|
|
173
|
+
if (asError(er).name === 'AbortError')
|
|
166
174
|
return;
|
|
167
175
|
ac.abort();
|
|
168
176
|
throw er;
|
|
@@ -174,7 +182,7 @@ export class RegistryClient {
|
|
|
174
182
|
async #checkLogin(url, options = {}) {
|
|
175
183
|
const response = await this.request(url, {
|
|
176
184
|
...options,
|
|
177
|
-
|
|
185
|
+
useCache: false,
|
|
178
186
|
});
|
|
179
187
|
const { signal } = options;
|
|
180
188
|
if (response.statusCode === 202) {
|
|
@@ -186,9 +194,9 @@ export class RegistryClient {
|
|
|
186
194
|
return await this.#checkLogin(url, options);
|
|
187
195
|
}
|
|
188
196
|
if (response.statusCode === 200) {
|
|
189
|
-
const
|
|
190
|
-
if (
|
|
191
|
-
return
|
|
197
|
+
const token = getTokenResponse(response.json());
|
|
198
|
+
if (token)
|
|
199
|
+
return token;
|
|
192
200
|
}
|
|
193
201
|
throw error('Invalid response from web login endpoint', {
|
|
194
202
|
response,
|
|
@@ -197,22 +205,27 @@ export class RegistryClient {
|
|
|
197
205
|
async request(url, options = {}) {
|
|
198
206
|
logRequest(url, 'start');
|
|
199
207
|
const u = typeof url === 'string' ? new URL(url) : url;
|
|
200
|
-
const { method = 'GET', integrity, redirections = new Set(), signal, otp = (process.env.VLT_OTP ?? '').trim(), } = options;
|
|
201
|
-
|
|
208
|
+
const { method = 'GET', integrity, redirections = new Set(), signal, otp = (process.env.VLT_OTP ?? '').trim(), staleWhileRevalidate = true, } = options;
|
|
209
|
+
let { trustIntegrity } = options;
|
|
210
|
+
const m = isCacheableMethod(method) ? method : undefined;
|
|
211
|
+
const { useCache = !!m } = options;
|
|
202
212
|
signal?.throwIfAborted();
|
|
203
213
|
// first, try to get from the cache before making any request.
|
|
204
|
-
const { origin
|
|
205
|
-
const key =
|
|
206
|
-
const buffer =
|
|
214
|
+
const { origin } = u;
|
|
215
|
+
const key = `${method !== 'GET' ? method + ' ' : ''}${u}`;
|
|
216
|
+
const buffer = useCache ?
|
|
207
217
|
await this.cache.fetch(key, { context: { integrity } })
|
|
208
218
|
: undefined;
|
|
209
219
|
const entry = buffer ? CacheEntry.decode(buffer) : undefined;
|
|
210
|
-
if (entry?.valid)
|
|
220
|
+
if (entry?.valid) {
|
|
221
|
+
return entry;
|
|
222
|
+
}
|
|
223
|
+
if (staleWhileRevalidate && entry?.staleWhileRevalidate && m) {
|
|
224
|
+
// revalidate while returning the stale entry
|
|
225
|
+
register(dirname(this.cache.path()), m, url);
|
|
211
226
|
return entry;
|
|
212
|
-
|
|
213
|
-
//
|
|
214
|
-
// in the background without waiting for it.
|
|
215
|
-
// either no cache entry, or need to revalidate it.
|
|
227
|
+
}
|
|
228
|
+
// either no cache entry, or need to revalidate before use.
|
|
216
229
|
setCacheHeaders(options, entry);
|
|
217
230
|
redirections.add(String(url));
|
|
218
231
|
Object.assign(options, {
|
|
@@ -224,12 +237,39 @@ export class RegistryClient {
|
|
|
224
237
|
if (otp) {
|
|
225
238
|
options.headers = addHeader(options.headers, 'npm-otp', otp);
|
|
226
239
|
}
|
|
240
|
+
if (integrity) {
|
|
241
|
+
options.headers = addHeader(options.headers, 'accept-integrity', integrity);
|
|
242
|
+
}
|
|
227
243
|
options.method = options.method ?? 'GET';
|
|
228
244
|
// will remove if we don't have a token.
|
|
229
245
|
options.headers = addHeader(options.headers, 'authorization', await getToken(origin, this.identity));
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
this.
|
|
246
|
+
let response = null;
|
|
247
|
+
try {
|
|
248
|
+
response = await this.agent.request(options);
|
|
249
|
+
/* c8 ignore start */
|
|
250
|
+
}
|
|
251
|
+
catch (er) {
|
|
252
|
+
// Rethrow so we get a better stack trace
|
|
253
|
+
throw error('Request failed', {
|
|
254
|
+
code: 'EREQUEST',
|
|
255
|
+
cause: er,
|
|
256
|
+
url,
|
|
257
|
+
method,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
/* c8 ignore stop */
|
|
261
|
+
const result = await this.#handleResponse(u, options, response, entry);
|
|
262
|
+
if (result.getHeader('integrity')) {
|
|
263
|
+
trustIntegrity = true;
|
|
264
|
+
}
|
|
265
|
+
if (result.isGzip && !trustIntegrity) {
|
|
266
|
+
result.checkIntegrity({ url });
|
|
267
|
+
}
|
|
268
|
+
if (useCache) {
|
|
269
|
+
this.cache.set(key, result.encode(), {
|
|
270
|
+
integrity: result.integrity,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
233
273
|
return result;
|
|
234
274
|
}
|
|
235
275
|
async #handleResponse(url, options, response, entry) {
|
|
@@ -251,24 +291,21 @@ export class RegistryClient {
|
|
|
251
291
|
h.push(Buffer.from(key), Buffer.from(value));
|
|
252
292
|
}
|
|
253
293
|
}
|
|
294
|
+
const { integrity, trustIntegrity } = options;
|
|
254
295
|
const result = new CacheEntry(
|
|
255
296
|
/* c8 ignore next - should always have a status code */
|
|
256
|
-
response.statusCode || 200, h,
|
|
297
|
+
response.statusCode || 200, h, {
|
|
298
|
+
integrity,
|
|
299
|
+
trustIntegrity,
|
|
300
|
+
'stale-while-revalidate-factor': this.staleWhileRevalidateFactor,
|
|
301
|
+
});
|
|
257
302
|
if (isRedirect(result)) {
|
|
258
303
|
response.body.resume();
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
if (nextOptions && nextURL) {
|
|
263
|
-
return await this.request(nextURL, nextOptions);
|
|
264
|
-
}
|
|
265
|
-
return result;
|
|
266
|
-
}
|
|
267
|
-
catch (er) {
|
|
268
|
-
/* c8 ignore start */
|
|
269
|
-
throw er instanceof Error ? er : (new Error(typeof er === 'string' ? er : 'Unknown error'));
|
|
270
|
-
/* c8 ignore stop */
|
|
304
|
+
const [nextURL, nextOptions] = redirect(options, result, url);
|
|
305
|
+
if (nextOptions && nextURL) {
|
|
306
|
+
return await this.request(nextURL, nextOptions);
|
|
271
307
|
}
|
|
308
|
+
return result;
|
|
272
309
|
}
|
|
273
310
|
response.body.on('data', (chunk) => result.addBody(chunk));
|
|
274
311
|
return await new Promise((res, rej) => {
|