@decdn/client 0.0.0-stage → 0.1.1

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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/errors.ts", "../src/hex.ts", "../src/uri.ts", "../src/base32.ts", "../src/hash.ts", "../src/manifest.ts", "../src/capability.ts", "../src/http.ts", "../src/loopback.ts", "../src/mime.ts", "../src/pointer.ts", "../src/verify.ts", "../src/client.ts"],
4
+ "sourcesContent": ["/** What went wrong, as a stable code a caller can branch on. */\nexport type DecdnErrorCode =\n /** 402: the gateway's allowance is spent, or the content does not fit what is left, or no capability covers the host. */\n | \"PAYMENT_REQUIRED\"\n /** 503: the gateway's pool cannot pay. */\n | \"POOL_UNFUNDED\"\n /** 404. */\n | \"NOT_FOUND\"\n /** 416: the range starts past the end; `size` holds the entry's size. */\n | \"RANGE_NOT_SATISFIABLE\"\n /** 401: the loopback token is missing or wrong. */\n | \"UNAUTHORIZED\"\n /** 403. */\n | \"FORBIDDEN\"\n /** 400, or a `decdn:` URI that does not parse. */\n | \"BAD_URI\"\n /** 429. */\n | \"RATE_LIMITED\"\n /** 502: the gateway's pull failed upstream. */\n | \"UPSTREAM\"\n /** 413. */\n | \"PAYLOAD_TOO_LARGE\"\n /** 409: a pointer `seq` that is not newer, or a capability already registered. */\n | \"CONFLICT\"\n /** 422. */\n | \"UNPROCESSABLE\"\n /** The bytes do not hash to the hash that names them. */\n | \"HASH_MISMATCH\"\n /** The body is shorter or longer than declared, or the stream failed. */\n | \"TRUNCATED\"\n /** A bundle manifest that does not parse. */\n | \"MALFORMED_MANIFEST\"\n /** A `dcap1:` capability token that does not decode. */\n | \"BAD_CAPABILITY\"\n /** The gateway could not be reached. */\n | \"NETWORK\"\n /** The client is not set up for the call, or the call cannot be honoured as asked. */\n | \"CONFIG\"\n /** A status the gateway contract does not name. */\n | \"HTTP\";\n\n/** Fields a {@link DecdnError} may carry besides its code and message. */\nexport interface DecdnErrorDetails {\n /** The HTTP status, when the gateway answered. */\n status?: number;\n /** Seconds to wait before a retry, from `Retry-After` or the JSON body. */\n retryAfterSecs?: number;\n /** The canonical `decdn:` URI to fetch with a paying client instead. */\n fallbackUri?: string;\n /** The entry's size, on `RANGE_NOT_SATISFIABLE`. */\n size?: number;\n /** The highest stored `seq`, on a pointer `CONFLICT`. */\n seq?: bigint;\n /** The response body, as text. */\n body?: string;\n /** What caused this error. */\n cause?: unknown;\n}\n\n/** Every failure the SDK reports. */\nexport class DecdnError extends Error {\n override readonly name = \"DecdnError\";\n readonly code: DecdnErrorCode;\n readonly status?: number;\n readonly retryAfterSecs?: number;\n readonly fallbackUri?: string;\n readonly size?: number;\n readonly seq?: bigint;\n readonly body?: string;\n\n constructor(\n code: DecdnErrorCode,\n message: string,\n details: DecdnErrorDetails = {},\n ) {\n super(\n message,\n details.cause === undefined ? undefined : { cause: details.cause },\n );\n this.code = code;\n if (details.status !== undefined) this.status = details.status;\n if (details.retryAfterSecs !== undefined)\n this.retryAfterSecs = details.retryAfterSecs;\n if (details.fallbackUri !== undefined)\n this.fallbackUri = details.fallbackUri;\n if (details.size !== undefined) this.size = details.size;\n if (details.seq !== undefined) this.seq = details.seq;\n if (details.body !== undefined) this.body = details.body;\n }\n}\n", "/** Lowercase hex of `bytes`. */\nexport function toHex(bytes: Uint8Array): string {\n let out = \"\";\n for (const b of bytes) out += b.toString(16).padStart(2, \"0\");\n return out;\n}\n\n/** The bytes of an even-length hex string, or `undefined` if it is not hex. */\nexport function fromHex(hex: string): Uint8Array | undefined {\n if (hex.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex)) return undefined;\n const out = new Uint8Array(hex.length / 2);\n for (let i = 0; i < out.length; i++)\n out[i] = parseInt(hex.slice(2 * i, 2 * i + 2), 16);\n return out;\n}\n\n/** Whether `s` is a BLAKE3 hash spelled as 64 hex characters. */\nexport function isHash(s: string): boolean {\n return /^[0-9a-fA-F]{64}$/.test(s);\n}\n", "// `decdn:` URIs, the grammar of the Rust client\n// (https://github.com/decdn/decdn/blob/main/crates/client/src/uri.rs):\n//\n// decdn:<hash>[/<path>][?ns=<id>]\n//\n// `<hash>` is 64 hex characters (no `b3:`/`0x`), a trailing `/` names a\n// bundle, `<path>` is a manifest entry path with each segment an RFC 3986\n// `pchar`, and `ns` is a decimal namespace id of at least 1.\nimport { DecdnError } from \"./errors.js\";\nimport { isHash } from \"./hex.js\";\n\n/** The scheme prefix of every `decdn:` URI. */\nexport const SCHEME = \"decdn:\";\n\nconst U64_MAX = (1n << 64n) - 1n;\n\n/** A parsed `decdn:` URI. */\nexport interface DecdnUri {\n /** The BLAKE3 hash, 64 lowercase hex characters: of the blob, or of the bundle manifest. */\n hash: string;\n /** What the hash names: a raw blob, a whole bundle, or one entry of a bundle. */\n kind: \"blob\" | \"bundle\" | \"entry\";\n /** The decoded manifest path of an entry. */\n path?: string;\n /** The namespace routing hint, never `0n`. */\n namespace?: bigint;\n}\n\nfunction bad(message: string): DecdnError {\n return new DecdnError(\"BAD_URI\", message);\n}\n\n/** An RFC 3986 `pchar` other than `%`: unreserved, sub-delims, `:` and `@`. */\nfunction isPchar(b: number): boolean {\n return (\n (b >= 0x30 && b <= 0x39) ||\n (b >= 0x41 && b <= 0x5a) ||\n (b >= 0x61 && b <= 0x7a) ||\n \"-._~!$&'()*+,;=:@\".includes(String.fromCharCode(b))\n );\n}\n\nfunction hexValue(c: string | undefined): number | undefined {\n return c !== undefined && /^[0-9a-fA-F]$/.test(c)\n ? parseInt(c, 16)\n : undefined;\n}\n\nconst utf8 = new TextDecoder(\"utf-8\", { fatal: true });\n\nfunction decodeSegment(segment: string): string {\n const out: number[] = [];\n for (let i = 0; i < segment.length; i++) {\n const c = segment.charCodeAt(i);\n if (c === 0x25) {\n const hi = hexValue(segment[i + 1]);\n const lo = hexValue(segment[i + 2]);\n if (hi === undefined || lo === undefined) {\n throw bad(\"invalid bundle entry path in decdn URI: bad `%` escape\");\n }\n out.push((hi << 4) | lo);\n i += 2;\n } else if (c < 0x80 && isPchar(c)) {\n out.push(c);\n } else {\n throw bad(\n `invalid bundle entry path in decdn URI: character ${JSON.stringify(segment[i])} must be percent-encoded`,\n );\n }\n }\n try {\n return utf8.decode(new Uint8Array(out));\n } catch {\n throw bad(\"invalid bundle entry path in decdn URI: not UTF-8 once decoded\");\n }\n}\n\nfunction decodePath(raw: string): string {\n const segments = raw.split(\"/\").map((segment) => {\n const decoded = decodeSegment(segment);\n let why: string | undefined;\n if (decoded === \"\")\n why =\n \"empty segment (a leading, trailing or doubled `/` inside the path)\";\n else if (decoded === \".\" || decoded === \"..\")\n why = `\\`${decoded}\\` segment`;\n else if (decoded.includes(\"/\")) why = \"encoded `/` (`%2F`) in a segment\";\n else if (decoded.includes(\"\\0\")) why = \"NUL byte\";\n if (why !== undefined)\n throw bad(`invalid bundle entry path in decdn URI: ${why}`);\n return decoded;\n });\n return segments.join(\"/\");\n}\n\nfunction badNamespace(why: string): DecdnError {\n return bad(\n `invalid namespace in decdn URI (${why}): expected \\`ns=<id>\\` with a decimal id of at least 1; omit \\`ns\\` for no namespace`,\n );\n}\n\nfunction badQuery(why: string): DecdnError {\n return bad(`invalid query in decdn URI (${why}): the only key is \\`ns\\``);\n}\n\nfunction parseQuery(query: string): bigint {\n let namespace: bigint | undefined;\n for (const pair of query.split(\"&\")) {\n const eq = pair.indexOf(\"=\");\n if (eq < 0) throw badQuery(`\\`${pair}\\` is not \\`key=value\\``);\n const key = pair.slice(0, eq);\n const value = pair.slice(eq + 1);\n if (key !== \"ns\") throw badQuery(`unknown key \\`${key}\\``);\n if (namespace !== undefined) throw badQuery(\"`ns` given twice\");\n if (!/^[0-9]+$/.test(value))\n throw badNamespace(`\\`${value}\\` is not a decimal id`);\n const id = BigInt(value);\n if (id > U64_MAX) throw badNamespace(`\\`${value}\\` is out of range`);\n if (id === 0n) throw badNamespace(\"0 means no namespace\");\n namespace = id;\n }\n if (namespace === undefined) throw badQuery(\"empty query\");\n return namespace;\n}\n\n/**\n * Parse a `decdn:` URI. Throws a {@link DecdnError} with code `BAD_URI` for\n * anything the Rust client would refuse.\n */\nexport function parseUri(s: string): DecdnUri {\n if (!s.startsWith(SCHEME))\n throw bad(\"not a decdn URI: expected `decdn:<hash>`\");\n const rest = s.slice(SCHEME.length);\n if (rest.startsWith(\"//\")) {\n throw bad(\n \"a decdn URI has no `//`: write `decdn:<hash>`, not `decdn://<hash>`\",\n );\n }\n const q = rest.indexOf(\"?\");\n const body = q < 0 ? rest : rest.slice(0, q);\n const query = q < 0 ? undefined : rest.slice(q + 1);\n const slash = body.indexOf(\"/\");\n const hash = slash < 0 ? body : body.slice(0, slash);\n const path = slash < 0 ? undefined : body.slice(slash + 1);\n if (!isHash(hash)) {\n const why = hash.length !== 64 ? `${hash.length} characters` : \"not hex\";\n throw bad(\n `invalid hash in decdn URI (${why}): expected 64 hex characters with no \\`b3:\\` or \\`0x\\` prefix`,\n );\n }\n const uri: DecdnUri = { hash: hash.toLowerCase(), kind: \"blob\" };\n if (path === \"\") uri.kind = \"bundle\";\n else if (path !== undefined) {\n uri.kind = \"entry\";\n uri.path = decodePath(path);\n }\n if (query !== undefined) uri.namespace = parseQuery(query);\n return uri;\n}\n\nfunction encodeSegment(segment: string): string {\n let out = \"\";\n for (const b of new TextEncoder().encode(segment)) {\n out += isPchar(b)\n ? String.fromCharCode(b)\n : `%${b.toString(16).toUpperCase().padStart(2, \"0\")}`;\n }\n return out;\n}\n\n/** The canonical string of `uri`: lowercase hex, uppercase `%XX` escapes. */\nexport function formatUri(uri: DecdnUri): string {\n let out = SCHEME + uri.hash.toLowerCase();\n if (uri.kind === \"bundle\") out += \"/\";\n else if (uri.kind === \"entry\") {\n for (const segment of (uri.path ?? \"\").split(\"/\"))\n out += `/${encodeSegment(segment)}`;\n }\n if (uri.namespace !== undefined) out += `?ns=${uri.namespace}`;\n return out;\n}\n", "// Site labels: a bundle's manifest hash as RFC 4648 base32, lowercase and\n// unpadded (52 characters, inside the 63-character DNS label limit), as the\n// gateway writes them\n// (https://github.com/decdn/decdn/blob/main/crates/cli/src/commands/gateway/site.rs).\nimport { DecdnError } from \"./errors.js\";\nimport { fromHex, isHash, toHex } from \"./hex.js\";\n\nconst ALPHABET = \"abcdefghijklmnopqrstuvwxyz234567\";\nconst LABEL_LEN = 52;\n\n/** The site label of a 64-hex-character hash. */\nexport function hashToBase32(hash: string): string {\n const bytes = isHash(hash) ? fromHex(hash) : undefined;\n if (bytes === undefined)\n throw new DecdnError(\"BAD_URI\", `not a 64-hex-character hash: ${hash}`);\n let out = \"\";\n let buffer = 0;\n let bits = 0;\n for (const b of bytes) {\n buffer = (buffer << 8) | b;\n bits += 8;\n while (bits >= 5) {\n bits -= 5;\n out += ALPHABET[(buffer >> bits) & 31];\n }\n }\n if (bits > 0) out += ALPHABET[(buffer << (5 - bits)) & 31];\n return out;\n}\n\n/**\n * The hash a canonical site label encodes, as 64 lowercase hex characters, or\n * `undefined` for anything else: the wrong length, uppercase, or nonzero\n * trailing bits (a second spelling the gateway refuses).\n */\nexport function base32ToHash(label: string): string | undefined {\n if (label.length !== LABEL_LEN || !/^[a-z2-7]+$/.test(label))\n return undefined;\n const out = new Uint8Array(32);\n let buffer = 0;\n let bits = 0;\n let n = 0;\n for (const c of label) {\n buffer = ((buffer << 5) | ALPHABET.indexOf(c)) & 0xfff;\n bits += 5;\n if (bits >= 8) {\n bits -= 8;\n out[n++] = (buffer >> bits) & 0xff;\n }\n }\n if ((buffer & ((1 << bits) - 1)) !== 0) return undefined;\n return toHex(out);\n}\n", "import { blake3 } from \"@noble/hashes/blake3.js\";\nimport { toHex } from \"./hex.js\";\n\n/** The BLAKE3 hash of `bytes`, as 64 lowercase hex characters. */\nexport function blake3Hex(bytes: Uint8Array): string {\n return toHex(blake3(bytes));\n}\n\n/** An incremental BLAKE3 hasher, for bytes that arrive in chunks. */\nexport interface Blake3Hasher {\n update(chunk: Uint8Array): void;\n /** The hash of every chunk so far, as 64 lowercase hex characters. */\n hex(): string;\n}\n\n/** A new incremental BLAKE3 hasher. */\nexport function createBlake3(): Blake3Hasher {\n const state = blake3.create();\n return {\n update(chunk) {\n state.update(chunk);\n },\n hex() {\n return toHex(state.digest());\n },\n };\n}\n", "// Bundle manifests, as `BundleManifest::parse` reads them\n// (https://github.com/decdn/decdn/blob/main/crates/client/src/bundle.rs): `{\"version\":1,\"entries\":[{\"path\",\"hash\",\"size\"?,\"chunks\"?}]}`,\n// the version checked before any hash, every hash 64 hex characters after an\n// optional `b3:` or `0x`.\nimport { DecdnError } from \"./errors.js\";\nimport { blake3Hex } from \"./hash.js\";\nimport { isHash } from \"./hex.js\";\n\n/** The largest manifest the gateway pulls, and the SDK reads (64 MiB). */\nexport const MAX_MANIFEST_BYTES = 64 * 1024 * 1024;\n\n/** One chunk of an entry: an independently addressed run of its bytes. */\nexport interface ManifestChunk {\n hash: string;\n size: number;\n}\n\n/** One file of a bundle. */\nexport interface ManifestEntry {\n /** The entry's relative POSIX path: what a `decdn:<hash>/<path>` URI names. */\n path: string;\n /** The BLAKE3 hash of the whole file, 64 lowercase hex characters. */\n hash: string;\n /** The file's size in bytes, when the manifest declares it. */\n size?: number;\n /** The file's chunk decomposition, a dedup hint. */\n chunks?: ManifestChunk[];\n}\n\n/** A parsed bundle manifest. */\nexport interface BundleManifest {\n /** The manifest blob's BLAKE3 hash: what `decdn:<hash>/` names. */\n hash: string;\n entries: ManifestEntry[];\n}\n\nfunction malformed(message: string): DecdnError {\n return new DecdnError(\"MALFORMED_MANIFEST\", message);\n}\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction isSize(v: unknown): v is number {\n return typeof v === \"number\" && Number.isSafeInteger(v) && v >= 0;\n}\n\nfunction parseHash(s: unknown): string | undefined {\n if (typeof s !== \"string\") return undefined;\n const hex = s.startsWith(\"0x\")\n ? s.slice(2)\n : s.startsWith(\"b3:\")\n ? s.slice(3)\n : s;\n return isHash(hex) ? hex.toLowerCase() : undefined;\n}\n\nfunction parseEntry(raw: unknown, i: number): ManifestEntry {\n if (!isRecord(raw) || typeof raw.path !== \"string\") {\n throw malformed(`bundle entry ${i} has no string \\`path\\``);\n }\n const path = raw.path;\n const named = JSON.stringify(path);\n const hash = parseHash(raw.hash);\n if (hash === undefined) {\n throw malformed(\n `bundle entry ${named} has a malformed hash: ${JSON.stringify(raw.hash)}`,\n );\n }\n const entry: ManifestEntry = { path, hash };\n if (raw.size !== undefined && raw.size !== null) {\n if (!isSize(raw.size))\n throw malformed(`bundle entry ${named} has a malformed size`);\n entry.size = raw.size;\n }\n if (raw.chunks !== undefined && raw.chunks !== null) {\n if (!Array.isArray(raw.chunks))\n throw malformed(`bundle entry ${named} has malformed chunks`);\n entry.chunks = raw.chunks.map((c: unknown, n) => {\n const chunkHash = isRecord(c) ? parseHash(c.hash) : undefined;\n if (!isRecord(c) || chunkHash === undefined) {\n throw malformed(\n `bundle entry ${named} has a malformed chunk ${n} hash`,\n );\n }\n if (!isSize(c.size))\n throw malformed(\n `bundle entry ${named} has a malformed chunk ${n} size`,\n );\n return { hash: chunkHash, size: c.size };\n });\n }\n return entry;\n}\n\n/**\n * Parse manifest bytes. With `expectedHash`, the bytes must hash to it first\n * (`HASH_MISMATCH` otherwise). Anything that is not a v1 manifest is\n * `MALFORMED_MANIFEST`.\n */\nexport function parseManifest(\n bytes: Uint8Array,\n expectedHash?: string,\n): BundleManifest {\n const hash = blake3Hex(bytes);\n if (expectedHash !== undefined && hash !== expectedHash.toLowerCase()) {\n throw new DecdnError(\n \"HASH_MISMATCH\",\n `bundle manifest hashes to ${hash}, not ${expectedHash.toLowerCase()}`,\n );\n }\n let json: unknown;\n try {\n json = JSON.parse(new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes));\n } catch (e) {\n throw new DecdnError(\n \"MALFORMED_MANIFEST\",\n \"parse bundle JSON (expected v1 manifest)\",\n {\n cause: e,\n },\n );\n }\n if (\n !isRecord(json) ||\n typeof json.version !== \"number\" ||\n !Array.isArray(json.entries)\n ) {\n throw malformed(\n \"parse bundle JSON (expected v1 manifest): missing `version` or `entries`\",\n );\n }\n if (json.version !== 1) {\n throw malformed(\n `unsupported bundle version ${json.version} (this SDK supports v1)`,\n );\n }\n return { hash, entries: json.entries.map(parseEntry) };\n}\n", "// `dcap1:` capability tokens, as the Rust encoder writes them\n// (https://github.com/decdn/decdn/blob/main/crates/incentive/src/capability_grant.rs): `dcap1:` + base64url (no padding) of the postcard encoding of\n// `{pool_id: [u8;32], signer: [u8;20], spending_cap: u64, expiry: u64,\n// owner_signature: Vec<u8>}`. Postcard writes a byte string as a varint\n// length and the bytes, and an integer as a LEB128 varint.\nimport { DecdnError } from \"./errors.js\";\nimport { toHex } from \"./hex.js\";\n\nconst PREFIX = \"dcap1:\";\nconst B64URL =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n\n/** A pool owner's spending grant to a delegate signer. */\nexport interface Capability {\n /** The on-chain pool, `0x` + 64 hex. */\n poolId: string;\n /** The delegate voucher-signing address, `0x` + 40 hex. */\n signer: string;\n /** Cumulative spend ceiling in USDC base units. */\n spendingCap: bigint;\n /** Unix-seconds expiry. */\n expiry: bigint;\n /** The owner's raw EIP-712 signature, `0x` + hex. */\n ownerSignature: string;\n}\n\nfunction bad(message: string): DecdnError {\n return new DecdnError(\"BAD_CAPABILITY\", message);\n}\n\nfunction fromBase64Url(body: string): Uint8Array {\n const out: number[] = [];\n let buffer = 0;\n let bits = 0;\n for (const c of body) {\n const v = B64URL.indexOf(c);\n if (v < 0) throw bad(\"capability token body is not valid base64url\");\n buffer = ((buffer << 6) | v) & 0xffff;\n bits += 6;\n if (bits >= 8) {\n bits -= 8;\n out.push((buffer >> bits) & 0xff);\n }\n }\n if (body.length % 4 === 1 || (buffer & ((1 << bits) - 1)) !== 0) {\n throw bad(\"capability token body is not valid base64url\");\n }\n return new Uint8Array(out);\n}\n\nclass Reader {\n private at = 0;\n constructor(private readonly bytes: Uint8Array) {}\n\n varint(): bigint {\n let value = 0n;\n for (let shift = 0n; shift < 70n; shift += 7n) {\n const b = this.bytes[this.at++];\n if (b === undefined) throw truncated();\n value |= BigInt(b & 0x7f) << shift;\n if ((b & 0x80) === 0) {\n if (value >= 1n << 64n) throw truncated();\n return value;\n }\n }\n throw truncated();\n }\n\n bytesOf(len?: number): Uint8Array {\n const n = Number(this.varint());\n if (len !== undefined && n !== len) throw truncated();\n if (this.at + n > this.bytes.length) throw truncated();\n const out = this.bytes.subarray(this.at, this.at + n);\n this.at += n;\n return out;\n }\n\n done(): boolean {\n return this.at === this.bytes.length;\n }\n}\n\nfunction truncated(): DecdnError {\n return bad(\"capability token payload is malformed (truncated or corrupt)\");\n}\n\n/** Decode a `dcap1:` token. Throws `BAD_CAPABILITY` for anything else. */\nexport function parseCapability(token: string): Capability {\n if (!token.startsWith(PREFIX)) {\n throw bad(\"not a dcap1 capability token (missing the `dcap1:` prefix)\");\n }\n const r = new Reader(fromBase64Url(token.slice(PREFIX.length)));\n const capability: Capability = {\n poolId: `0x${toHex(r.bytesOf(32))}`,\n signer: `0x${toHex(r.bytesOf(20))}`,\n spendingCap: r.varint(),\n expiry: r.varint(),\n ownerSignature: `0x${toHex(r.bytesOf())}`,\n };\n if (!r.done()) throw truncated();\n return capability;\n}\n", "// The fetch wrapper: every non-2xx answer of the gateway becomes a\n// `DecdnError` with the fields its contract carries (Retry-After, the\n// `Link: <decdn:\u2026>; rel=\"alternate\"` fallback, the 402/503 JSON body, the\n// 416 size, the pointer 409 `seq`).\nimport { DecdnError, type DecdnErrorCode } from \"./errors.js\";\n\nexport type Fetch = typeof globalThis.fetch;\n\nconst CODES: Record<number, DecdnErrorCode> = {\n 400: \"BAD_URI\",\n 401: \"UNAUTHORIZED\",\n 402: \"PAYMENT_REQUIRED\",\n 403: \"FORBIDDEN\",\n 404: \"NOT_FOUND\",\n 409: \"CONFLICT\",\n 413: \"PAYLOAD_TOO_LARGE\",\n 416: \"RANGE_NOT_SATISFIABLE\",\n 422: \"UNPROCESSABLE\",\n 429: \"RATE_LIMITED\",\n 502: \"UPSTREAM\",\n 503: \"POOL_UNFUNDED\",\n};\n\n/** `fetch`, with a failure to reach the gateway as `NETWORK` and an abort passed through. */\nexport async function send(\n fetch: Fetch,\n url: string,\n init: RequestInit,\n): Promise<Response> {\n try {\n return await fetch(url, init);\n } catch (e) {\n if (init.signal?.aborted) throw init.signal.reason ?? e;\n throw new DecdnError(\n \"NETWORK\",\n `cannot reach ${new URL(url).origin}: ${(e as Error).message}`,\n {\n cause: e,\n },\n );\n }\n}\n\nfunction linkUri(link: string | null): string | undefined {\n if (link === null) return undefined;\n const m = /<(decdn:[^>]+)>\\s*;\\s*rel=\"?alternate\"?/.exec(link);\n return m?.[1];\n}\n\n/** The error for a gateway answer that is not a success. Reads the body. */\nexport async function errorOf(response: Response): Promise<DecdnError> {\n const status = response.status;\n const code = CODES[status] ?? \"HTTP\";\n let body = \"\";\n try {\n body = await response.text();\n } catch {\n // The status still says what went wrong.\n }\n const details: ConstructorParameters<typeof DecdnError>[2] = { status };\n let message = body.trim();\n if (message !== \"\") details.body = message;\n const retryAfter = response.headers.get(\"retry-after\");\n if (retryAfter !== null && /^\\d+$/.test(retryAfter.trim()))\n details.retryAfterSecs = Number(retryAfter.trim());\n const link = linkUri(response.headers.get(\"link\"));\n if (link !== undefined) details.fallbackUri = link;\n if (\n (response.headers.get(\"content-type\") ?? \"\").startsWith(\"application/json\")\n ) {\n try {\n const parsed: unknown = JSON.parse(body);\n if (typeof parsed === \"object\" && parsed !== null) {\n const o = parsed as Record<string, unknown>;\n if (typeof o.error === \"string\") message = o.error;\n if (typeof o.uri === \"string\") details.fallbackUri = o.uri;\n if (typeof o.retry_after_secs === \"number\")\n details.retryAfterSecs = o.retry_after_secs;\n }\n // A u64 `seq` may exceed 2^53: read its digits, not the parsed number.\n const seq = /\"seq\"\\s*:\\s*(\\d+)/.exec(body)?.[1];\n if (seq !== undefined) details.seq = BigInt(seq);\n } catch {\n // Not JSON after all: the text stands.\n }\n }\n if (status === 416) {\n const size = /^bytes \\*\\/(\\d+)$/.exec(\n response.headers.get(\"content-range\") ?? \"\",\n )?.[1];\n if (size !== undefined) details.size = Number(size);\n }\n return new DecdnError(\n code,\n message === \"\" ? `gateway answered ${status}` : message,\n details,\n );\n}\n\n/**\n * `text` parsed as JSON with the integer values of `fields` read as `bigint`:\n * the gateway writes u64 ids, caps and expiries as JSON numbers, which may\n * exceed 2^53.\n */\nexport function parseWithBigInts(text: string, fields: string[]): unknown {\n const names = fields.join(\"|\");\n const quoted = text.replace(\n new RegExp(`(\"(?:${names})\"\\\\s*:\\\\s*)(\\\\d+)`, \"g\"),\n '$1\"$2\"',\n );\n return JSON.parse(quoted, (key, value: unknown) =>\n fields.includes(key) && typeof value === \"string\" && /^\\d+$/.test(value)\n ? BigInt(value)\n : value,\n );\n}\n", "// The loopback gateway's API\n// (https://github.com/decdn/decdn/blob/main/crates/cli/src/commands/gateway.rs):\n// `GET /_delegate` mints a delegate key, `PUT /_capability` registers a\n// `dcap1:` capability issued to it for a scope, `GET /_capability` lists the\n// registered ones (token only). A page calls the first two cross-origin; the\n// token holder calls all three.\nimport type { DecdnClient } from \"./client.js\";\nimport { DecdnError } from \"./errors.js\";\nimport { errorOf, parseWithBigInts, send } from \"./http.js\";\n\n/** A capability the gateway holds. */\nexport interface RegisteredCapability {\n signer: string;\n pool: string;\n scope: string;\n /** The page origin that registered it, or `null` for the token holder. */\n origin: string | null;\n /** The spending cap, in USDC base units. */\n cap: bigint;\n /** Unix-seconds expiry. */\n expiry: bigint;\n /** Whether a pull found it spent. */\n spent: boolean;\n}\n\nexport class LoopbackApi {\n /** @internal */\n constructor(private readonly client: DecdnClient) {}\n\n private async call(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<string> {\n if (this.client.context !== \"loopback\") {\n throw new DecdnError(\n \"CONFIG\",\n \"the delegate and capability API is a loopback gateway's alone\",\n );\n }\n const init: RequestInit = {\n method,\n headers: { ...this.client.authHeaders() },\n };\n if (body !== undefined) {\n init.body = JSON.stringify(body);\n (init.headers as Record<string, string>)[\"content-type\"] =\n \"application/json\";\n }\n const response = await send(\n this.client.fetch,\n `${this.client.origin}${path}`,\n init,\n );\n if (response.status < 200 || response.status > 299)\n throw await errorOf(response);\n return response.text();\n }\n\n /** A fresh delegate key the gateway holds for 15 minutes unless a capability claims it. */\n async delegate(): Promise<{ address: string }> {\n const parsed = JSON.parse(await this.call(\"GET\", \"/_delegate\")) as {\n address: string;\n };\n return { address: parsed.address };\n }\n\n /** Register `capability` (a `dcap1:` issued to a delegate) for `scope`: `example.com`, `*.example.com` or `*`. */\n async registerCapability(args: {\n capability: string;\n scope: string;\n }): Promise<{ signer: string; scope: string; expiry: bigint }> {\n const text = await this.call(\"PUT\", \"/_capability\", {\n capability: args.capability,\n scope: args.scope,\n });\n return parseWithBigInts(text, [\"expiry\"]) as {\n signer: string;\n scope: string;\n expiry: bigint;\n };\n }\n\n /** The capabilities the gateway holds. Needs the token. */\n async capabilities(): Promise<RegisteredCapability[]> {\n const text = await this.call(\"GET\", \"/_capability\");\n return parseWithBigInts(text, [\"cap\", \"expiry\"]) as RegisteredCapability[];\n }\n}\n", "// What the gateway does with an entry by the extension of its name: whether a\n// site rewrites it as it streams (the gateway rewrites the types mime_guess\n// maps these extensions to:\n// https://github.com/decdn/decdn/blob/main/crates/cli/src/commands/gateway/rewrite.rs),\n// and the type a site serves it as, for the common web types. When it\n// verifies off loopback, the client fetches these entries by their hash up\n// front, and fetches by hash again any other entry a site answers with a\n// type it rewrites.\n\n/** Extensions a site serves as `text/html` or `text/css`, rewritten as they stream. */\nconst REWRITTEN = /\\.(html?|hxt|shtml|css)$/i;\n\n/** Whether a site rewrites the entry at `path`, so its bytes need not hash to the entry hash. */\nexport function rewritten(path: string): boolean {\n return REWRITTEN.test(path);\n}\n\nconst TYPES: Record<string, string> = {\n html: \"text/html\",\n htm: \"text/html\",\n css: \"text/css\",\n js: \"text/javascript\",\n mjs: \"text/javascript\",\n json: \"application/json\",\n txt: \"text/plain\",\n md: \"text/markdown\",\n csv: \"text/csv\",\n xml: \"text/xml\",\n svg: \"image/svg+xml\",\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n avif: \"image/avif\",\n ico: \"image/x-icon\",\n wasm: \"application/wasm\",\n pdf: \"application/pdf\",\n zip: \"application/zip\",\n gz: \"application/gzip\",\n tar: \"application/x-tar\",\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n mp3: \"audio/mpeg\",\n ogg: \"audio/ogg\",\n woff: \"font/woff\",\n woff2: \"font/woff2\",\n};\n\n/** The type a site serves the entry at `path` as: text in UTF-8, bytes for an unknown extension. */\nexport function siteType(path: string): string {\n const ext = /\\.([^./]+)$/.exec(path)?.[1]?.toLowerCase() ?? \"\";\n const t = TYPES[ext] ?? \"application/octet-stream\";\n return t.startsWith(\"text/\") ? `${t}; charset=utf-8` : t;\n}\n", "// Namespace pointers\n// (https://github.com/decdn/decdn/blob/main/crates/cli/src/commands/gateway/pointer.rs):\n// an owner-signed EIP-712 record\n//\n// Pointer(uint256 namespaceId,bytes32 root,uint64 seq)\n//\n// under the domain {name: \"decdn-pointer\", version: \"1\", chainId,\n// verifyingContract: PublisherRegistry}. The gateway takes a 65-byte\n// `r\u2016s\u2016v` signature with a low `s` only.\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport { keccak_256 } from \"@noble/hashes/sha3.js\";\nimport type { DecdnClient } from \"./client.js\";\nimport { DecdnError } from \"./errors.js\";\nimport { fromHex, isHash, toHex } from \"./hex.js\";\nimport { errorOf, parseWithBigInts, send } from \"./http.js\";\nimport { parseUri, SCHEME } from \"./uri.js\";\n\n/** The chain a pointer is signed for: the EIP-712 domain of `PUT /_pointer`. */\nexport interface PointerDomain {\n chainId: bigint | number;\n /** The `PublisherRegistry` contract address. */\n publisherRegistry: string;\n}\n\n/** A pointer from a namespace to the bundle whose manifest hash is `root`. */\nexport interface Pointer {\n namespace: bigint;\n /** The bundle's manifest hash, 64 hex characters. */\n root: string;\n seq: bigint;\n}\n\n/** The EIP-712 typed data of a pointer, in the shape viem's `signTypedData` takes. */\nexport interface PointerTypedData {\n domain: {\n name: \"decdn-pointer\";\n version: \"1\";\n chainId: bigint;\n verifyingContract: string;\n };\n types: { Pointer: { name: string; type: string }[] };\n primaryType: \"Pointer\";\n message: { namespaceId: bigint; root: string; seq: bigint };\n}\n\n/** Anything that signs EIP-712 typed data: a viem account, or a wallet behind the same call shape. */\nexport interface TypedDataSigner {\n signTypedData(typedData: PointerTypedData): Promise<string>;\n}\n\n/** A signer: a typed-data signer, or a raw secp256k1 key (`0x` hex or bytes). */\nexport type PointerSigner =\n TypedDataSigner | { privateKey: string | Uint8Array };\n\nconst N = secp256k1.Point.CURVE().n;\nconst U64_MAX = (1n << 64n) - 1n;\nconst U256_MAX = (1n << 256n) - 1n;\nconst enc = new TextEncoder();\n\n/** @internal `value` as a bigint; `CONFIG` for a number that is not a safe integer. */\nexport function integer(value: bigint | number, what: string): bigint {\n if (typeof value === \"number\" && !Number.isSafeInteger(value))\n throw bad(`${what} is an integer below 2^53, or a bigint: got ${value}`);\n return BigInt(value);\n}\n\n/** The domain's chain id: an integer of at least 1 that fits a uint256. */\nfunction chainIdOf(domain: PointerDomain): bigint {\n const id = integer(domain.chainId, \"a chain id\");\n if (id < 1n || id > U256_MAX)\n throw bad(\"a chain id is a uint256 of at least 1\");\n return id;\n}\n\n/** `n` as a 32-byte big-endian word. */\nfunction word(n: bigint): Uint8Array {\n const bytes =\n n >= 0n && n <= U256_MAX\n ? fromHex(n.toString(16).padStart(64, \"0\"))\n : undefined;\n if (bytes === undefined) throw bad(`${n} does not fit a uint256`);\n return bytes;\n}\n\nfunction concat(...parts: Uint8Array[]): Uint8Array {\n const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0));\n let at = 0;\n for (const p of parts) {\n out.set(p, at);\n at += p.length;\n }\n return out;\n}\n\nconst DOMAIN_TYPE = keccak_256(\n enc.encode(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\",\n ),\n);\nconst POINTER_TYPE = keccak_256(\n enc.encode(\"Pointer(uint256 namespaceId,bytes32 root,uint64 seq)\"),\n);\n\nfunction bad(message: string): DecdnError {\n return new DecdnError(\"CONFIG\", message);\n}\n\nfunction address(s: string): Uint8Array {\n const bytes = /^0x[0-9a-fA-F]{40}$/.test(s) ? fromHex(s.slice(2)) : undefined;\n if (bytes === undefined) throw bad(`not an address: ${s}`);\n return bytes;\n}\n\nfunction checked(p: Pointer): Uint8Array {\n if (p.namespace < 1n || p.namespace > U64_MAX)\n throw bad(\"a namespace id is a u64 of at least 1\");\n if (p.seq < 0n || p.seq > U64_MAX) throw bad(\"a pointer seq is a u64\");\n const root = p.root.startsWith(\"0x\") ? p.root.slice(2) : p.root;\n const bytes = isHash(root) ? fromHex(root) : undefined;\n if (bytes === undefined) throw bad(`not a manifest hash: ${p.root}`);\n return bytes;\n}\n\n/** The typed data a wallet signs for `pointer`. */\nexport function pointerTypedData(\n domain: PointerDomain,\n pointer: Pointer,\n): PointerTypedData {\n const root = checked(pointer);\n address(domain.publisherRegistry);\n return {\n domain: {\n name: \"decdn-pointer\",\n version: \"1\",\n chainId: chainIdOf(domain),\n verifyingContract: domain.publisherRegistry,\n },\n types: {\n Pointer: [\n { name: \"namespaceId\", type: \"uint256\" },\n { name: \"root\", type: \"bytes32\" },\n { name: \"seq\", type: \"uint64\" },\n ],\n },\n primaryType: \"Pointer\",\n message: {\n namespaceId: pointer.namespace,\n root: `0x${toHex(root)}`,\n seq: pointer.seq,\n },\n };\n}\n\nfunction digest(domain: PointerDomain, pointer: Pointer): Uint8Array {\n const root = checked(pointer);\n const separator = keccak_256(\n concat(\n DOMAIN_TYPE,\n keccak_256(enc.encode(\"decdn-pointer\")),\n keccak_256(enc.encode(\"1\")),\n word(chainIdOf(domain)),\n concat(new Uint8Array(12), address(domain.publisherRegistry)),\n ),\n );\n const struct = keccak_256(\n concat(POINTER_TYPE, word(pointer.namespace), root, word(pointer.seq)),\n );\n return keccak_256(concat(Uint8Array.of(0x19, 0x01), separator, struct));\n}\n\n/** The EIP-712 signing hash of `pointer`, `0x` + 64 hex. */\nexport function pointerSigningHash(\n domain: PointerDomain,\n pointer: Pointer,\n): string {\n return `0x${toHex(digest(domain, pointer))}`;\n}\n\n/** A 65-byte `r\u2016s\u2016v` signature with a low `s` and `v` of 27 or 28, as the gateway takes it. */\nfunction normalised(signature: string): string {\n const hex = signature.startsWith(\"0x\") ? signature.slice(2) : signature;\n if (!/^[0-9a-fA-F]{130}$/.test(hex))\n throw new DecdnError(\"CONFIG\", \"the signer returned no 65-byte signature\");\n const r = hex.slice(0, 64);\n let s = BigInt(`0x${hex.slice(64, 128)}`);\n let parity = parseInt(hex.slice(128), 16);\n parity = parity >= 27 ? parity - 27 : parity;\n if (parity !== 0 && parity !== 1)\n throw new DecdnError(\"CONFIG\", \"the signature's v is not 0, 1, 27 or 28\");\n if (s > N / 2n) {\n s = N - s;\n parity ^= 1;\n }\n return `0x${r.toLowerCase()}${s.toString(16).padStart(64, \"0\")}${(27 + parity).toString(16)}`;\n}\n\n/** Sign `pointer` for `domain` with `signer`. */\nexport async function signPointer(\n domain: PointerDomain,\n pointer: Pointer,\n signer: PointerSigner,\n): Promise<string> {\n if (\"privateKey\" in signer) {\n const key =\n typeof signer.privateKey === \"string\"\n ? fromHex(\n signer.privateKey.startsWith(\"0x\")\n ? signer.privateKey.slice(2)\n : signer.privateKey,\n )\n : signer.privateKey;\n if (key === undefined || key.length !== 32)\n throw bad(\"a private key is 32 bytes\");\n const sig = secp256k1.sign(digest(domain, pointer), key, {\n prehash: false,\n lowS: true,\n format: \"recovered\",\n });\n return normalised(`${toHex(sig.subarray(1))}${toHex(sig.subarray(0, 1))}`);\n }\n return normalised(\n await signer.signTypedData(pointerTypedData(domain, pointer)),\n );\n}\n\n/** The lowercase address that signed `pointer` with `signature`; `UNPROCESSABLE` for a malformed or high-`s` one. */\nexport function recoverPointerSigner(\n domain: PointerDomain,\n pointer: Pointer,\n signature: string,\n): string {\n const hex = signature.startsWith(\"0x\") ? signature.slice(2) : signature;\n const bytes = /^[0-9a-fA-F]{130}$/.test(hex) ? fromHex(hex) : undefined;\n const v = bytes?.[64];\n const malformed = () =>\n new DecdnError(\"UNPROCESSABLE\", \"the pointer signature is malformed\");\n if (bytes === undefined || v === undefined || (v !== 27 && v !== 28))\n throw malformed();\n if (BigInt(`0x${hex.slice(64, 128)}`) > N / 2n) throw malformed();\n try {\n const recovered = concat(Uint8Array.of(v - 27), bytes.subarray(0, 64));\n const key = secp256k1.recoverPublicKey(recovered, digest(domain, pointer), {\n prehash: false,\n });\n const point = secp256k1.Point.fromBytes(key).toBytes(false);\n return `0x${toHex(keccak_256(point.subarray(1)).subarray(12))}`;\n } catch {\n throw malformed();\n }\n}\n\n/** What `pointer.set` stored. */\nexport interface PointerSet {\n namespace: bigint;\n /** The bundle's manifest hash. */\n root: string;\n seq: bigint;\n /** The namespace's host on the gateway. */\n url: string;\n}\n\n/** Namespace pointers on a public gateway. */\nexport class PointerApi {\n /** @internal */\n constructor(private readonly client: DecdnClient) {}\n\n /**\n * Sign a pointer from `namespace` to the bundle `root` (`decdn:<hash>/` or\n * its manifest hash) and `PUT` it. `seq` defaults to the current Unix\n * second; the gateway takes only a `seq` above the one it holds from the\n * same signer. The signer must own the namespace on the `PublisherRegistry`\n * of `open({ pointer })`.\n */\n async set(args: {\n namespace: bigint | number;\n root: string;\n seq?: bigint | number;\n signer: PointerSigner;\n signal?: AbortSignal;\n }): Promise<PointerSet> {\n const domain = this.client.pointerDomain;\n if (this.client.context !== \"public\")\n throw bad(\"namespace pointers live on a public gateway\");\n if (domain === undefined) {\n throw bad(\n \"pointer.set needs open({ pointer: { chainId, publisherRegistry } })\",\n );\n }\n let root = args.root.startsWith(\"0x\") ? args.root.slice(2) : args.root;\n if (root.startsWith(SCHEME)) {\n const uri = parseUri(root);\n if (uri.kind !== \"bundle\") {\n throw new DecdnError(\n \"BAD_URI\",\n \"a pointer names a bundle: pass `decdn:<hash>/`, the manifest hash with its trailing slash\",\n );\n }\n root = uri.hash;\n } else if (!isHash(root)) {\n throw new DecdnError(\"BAD_URI\", `not a manifest hash: ${args.root}`);\n }\n const pointer: Pointer = {\n namespace: integer(args.namespace, \"a namespace id\"),\n root: root.toLowerCase(),\n seq:\n args.seq === undefined\n ? BigInt(Math.floor(Date.now() / 1000))\n : integer(args.seq, \"a pointer seq\"),\n };\n const signature = await signPointer(domain, pointer, args.signer);\n const init: RequestInit = {\n method: \"PUT\",\n headers: { \"content-type\": \"application/json\" },\n body: `{\"namespace\":${pointer.namespace},\"root\":\"0x${pointer.root}\",\"seq\":${pointer.seq},\"signature\":\"${signature}\"}`,\n };\n if (args.signal !== undefined) init.signal = args.signal;\n const response = await send(\n this.client.fetch,\n `${this.client.origin}/_pointer`,\n init,\n );\n if (response.status < 200 || response.status > 299)\n throw await errorOf(response);\n return parseWithBigInts(await response.text(), [\n \"namespace\",\n \"seq\",\n ]) as PointerSet;\n }\n}\n", "// The body guard: a stream that passes the gateway's bytes through, hashes\n// them as they go when the request named the bytes by hash, and ends with an\n// error instead of `done` when they do not hash to it, when fewer bytes arrive\n// than declared, or when more arrive than the body may hold.\nimport { DecdnError } from \"./errors.js\";\nimport { createBlake3 } from \"./hash.js\";\n\nexport interface GuardOptions {\n /** The hash the whole body must have, or `undefined` to skip the check. */\n hash?: string;\n /** The fewest bytes the body holds: the manifest's size, or Content-Length. */\n length?: number;\n /** The most bytes the body may hold: the manifest's size, or the window asked for. */\n max?: number;\n /** The request's signal: a read it aborts fails with its reason. */\n signal?: AbortSignal;\n}\n\n/** `body`, guarded: a failed read is `TRUNCATED`, a short or long body `TRUNCATED`, a wrong hash `HASH_MISMATCH`. */\nexport function guard(\n body: ReadableStream<Uint8Array> | null,\n opts: GuardOptions,\n): ReadableStream<Uint8Array> {\n const reader = body?.getReader();\n const hasher = opts.hash === undefined ? undefined : createBlake3();\n let delivered = 0;\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n let chunk: ReadableStreamReadResult<Uint8Array>;\n try {\n chunk =\n reader === undefined\n ? { done: true, value: undefined }\n : await reader.read();\n } catch (e) {\n controller.error(\n e instanceof DecdnError\n ? e\n : opts.signal?.aborted === true\n ? opts.signal.reason\n : new DecdnError(\"TRUNCATED\", \"the body ended early\", {\n cause: e,\n }),\n );\n return;\n }\n if (!chunk.done) {\n delivered += chunk.value.length;\n if (opts.max !== undefined && delivered > opts.max) {\n controller.error(\n new DecdnError(\n \"TRUNCATED\",\n `the body ran past the ${opts.max} bytes it may hold`,\n ),\n );\n // The error is the caller's already; a failed cancel adds nothing.\n reader?.cancel().catch(() => undefined);\n return;\n }\n hasher?.update(chunk.value);\n controller.enqueue(chunk.value);\n return;\n }\n if (opts.length !== undefined && delivered < opts.length) {\n controller.error(\n new DecdnError(\n \"TRUNCATED\",\n `the body ended after ${delivered} of ${opts.length} bytes`,\n ),\n );\n return;\n }\n if (hasher !== undefined && opts.hash !== undefined) {\n const got = hasher.hex();\n if (got !== opts.hash) {\n controller.error(\n new DecdnError(\n \"HASH_MISMATCH\",\n `the body hashes to ${got}, not ${opts.hash}`,\n ),\n );\n return;\n }\n }\n controller.close();\n },\n cancel(reason) {\n return reader?.cancel(reason);\n },\n });\n}\n\n/** Every byte of `stream`, joined. */\nexport async function collect(\n stream: ReadableStream<Uint8Array>,\n limit?: number,\n): Promise<Uint8Array> {\n const reader = stream.getReader();\n const parts: Uint8Array[] = [];\n let total = 0;\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.length;\n if (limit !== undefined && total > limit) {\n await reader.cancel();\n throw new DecdnError(\n \"MALFORMED_MANIFEST\",\n `the body is larger than ${limit} bytes`,\n );\n }\n parts.push(value);\n }\n const out = new Uint8Array(total);\n let at = 0;\n for (const p of parts) {\n out.set(p, at);\n at += p.length;\n }\n return out;\n}\n", "// The client: one of three contexts over a `decdn gateway`.\n//\n// - `public`: a gateway with `--public-url`; blobs from the bare host, entries\n// from their site host, every request paid by the operator.\n// - `loopback`: the local gateway with its token; every request on the bare\n// host, paid by the capability that covers `host`. A page reaches it\n// without the token, for `/_delegate` and `/_capability` alone.\n// - `site`: a page served from a site origin; its own entries same-origin and\n// other content through `/_decdn/`.\nimport { base32ToHash, hashToBase32 } from \"./base32.js\";\nimport { DecdnError } from \"./errors.js\";\nimport { errorOf, send, type Fetch } from \"./http.js\";\nimport { isHash } from \"./hex.js\";\nimport {\n MAX_MANIFEST_BYTES,\n parseManifest,\n type BundleManifest,\n type ManifestEntry,\n} from \"./manifest.js\";\nimport { LoopbackApi } from \"./loopback.js\";\nimport { rewritten, siteType } from \"./mime.js\";\nimport { integer, PointerApi, type PointerDomain } from \"./pointer.js\";\nimport { formatUri, parseUri, SCHEME, type DecdnUri } from \"./uri.js\";\nimport { collect, guard } from \"./verify.js\";\n\n/** Where the client runs and how it reaches the gateway. */\nexport type Context = \"public\" | \"loopback\" | \"site\";\n\n/** `\"auto\"` verifies what can be verified; `true` refuses what cannot; `false` verifies nothing. */\nexport type VerifyMode = \"auto\" | boolean;\n\nexport interface OpenOptions {\n /** The gateway's origin: `https://decdn.link`, or `http://127.0.0.1:8484` for a loopback gateway. */\n gatewayUrl?: string;\n /** The loopback gateway's token (`~/.decdn/gateway/token`). */\n token?: string;\n /** The host whose capability pays on a loopback gateway, sent as `x-decdn-host`. Required with `token`. */\n host?: string;\n /** The chain and registry pointers are signed for. Required by `pointer.set`. */\n pointer?: PointerDomain;\n /** The `fetch` to use. Default: the global one. */\n fetch?: Fetch;\n /** The default verification of `get`. Default `\"auto\"`. */\n verify?: VerifyMode;\n /** How many manifests the client keeps parsed, by hash. Default 64. */\n manifestCacheSize?: number;\n}\n\n/** A byte window: `length` bytes from `offset`, or to the end without `length`. */\nexport interface ByteRange {\n offset: number;\n length?: number;\n}\n\nexport interface GetOptions {\n range?: ByteRange;\n signal?: AbortSignal;\n verify?: VerifyMode;\n /** Wait out one `Retry-After` on 402, 429 or 503 and try once more. */\n retry?: boolean;\n}\n\n/** What `head` knows about content without fetching it. */\nexport interface HeadInfo {\n size?: number;\n hash?: string;\n contentType?: string;\n}\n\n/** What a URI names, once its manifest is read. */\nexport interface Resolved {\n kind: DecdnUri[\"kind\"];\n /** The URI's hash: of the blob, or of the bundle manifest. */\n hash: string;\n /** The manifest entry an entry URI names. */\n entry?: ManifestEntry;\n /** The bundle or entry on its site origin. */\n siteUrl?: string;\n /** The URI on the gateway's bare host (or under `/_decdn/` on a site). */\n bareUrl: string;\n}\n\n/** The gateway's answer: a stream that ends with an error rather than `done` when its bytes fail verification. */\nexport class DecdnResponse {\n readonly status: number;\n readonly headers: Headers;\n readonly url: string;\n readonly contentType: string;\n readonly contentLength?: number;\n readonly contentRange?: { offset: number; length: number; size: number };\n /**\n * `true`: the body is hashed as it streams, and ends with `HASH_MISMATCH`\n * instead of `done` unless it hashes to the hash that names it.\n * `\"skipped\"`: the bytes cannot be verified (a range, a rewritten page, a\n * bundle listing). `false`: verification was turned off.\n */\n readonly verified: boolean | \"skipped\";\n readonly body: ReadableStream<Uint8Array>;\n\n /** @internal */\n constructor(\n response: Response,\n body: ReadableStream<Uint8Array>,\n verified: boolean | \"skipped\",\n contentType?: string,\n ) {\n this.status = response.status;\n this.headers = response.headers;\n this.url = response.url;\n this.contentType =\n contentType ??\n response.headers.get(\"content-type\") ??\n \"application/octet-stream\";\n const length = response.headers.get(\"content-length\");\n if (length !== null && /^\\d+$/.test(length))\n this.contentLength = Number(length);\n const range = /^bytes (\\d+)-(\\d+)\\/(\\d+)$/.exec(\n response.headers.get(\"content-range\") ?? \"\",\n );\n if (range !== null) {\n const [, a = \"0\", b = \"0\", size = \"0\"] = range;\n this.contentRange = {\n offset: Number(a),\n length: Number(b) - Number(a) + 1,\n size: Number(size),\n };\n }\n this.verified = verified;\n this.body = body;\n }\n\n /** The whole body. Rejects with `HASH_MISMATCH` or `TRUNCATED`. */\n bytes(): Promise<Uint8Array> {\n return collect(this.body);\n }\n\n async text(): Promise<string> {\n return new TextDecoder().decode(await this.bytes());\n }\n\n async json(): Promise<unknown> {\n return JSON.parse(await this.text());\n }\n}\n\n/** A site origin's own bundle and namespace, and the suffix its siblings share. */\ninterface SiteOrigin {\n origin: string;\n protocol: string;\n /** `<rest>` of `[<ns>.]<hash32>.<rest>`, or `<host>` of `<ns>.<host>`. */\n suffix: string;\n /** The page's bundle; unknown on a namespace host. */\n hash?: string;\n namespace?: bigint;\n}\n\nconst NAMESPACE_LABEL = /^[1-9][0-9]*$/;\n\n/** The site origin `host` is, under `gatewayHost` when one is configured. */\nfunction siteOf(\n protocol: string,\n host: string,\n gatewayHost?: string,\n): SiteOrigin | undefined {\n const labels = host.split(\".\");\n const origin = `${protocol}//${host}`;\n const first = labels[0] ?? \"\";\n const hash = base32ToHash(first);\n if (hash !== undefined && labels.length > 1) {\n return { origin, protocol, suffix: labels.slice(1).join(\".\"), hash };\n }\n const second = base32ToHash(labels[1] ?? \"\");\n if (\n second !== undefined &&\n NAMESPACE_LABEL.test(first) &&\n labels.length > 2\n ) {\n return {\n origin,\n protocol,\n suffix: labels.slice(2).join(\".\"),\n hash: second,\n namespace: BigInt(first),\n };\n }\n if (\n gatewayHost !== undefined &&\n NAMESPACE_LABEL.test(first) &&\n labels.slice(1).join(\".\") === gatewayHost\n ) {\n return { origin, protocol, suffix: gatewayHost, namespace: BigInt(first) };\n }\n return undefined;\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return (\n hostname === \"127.0.0.1\" ||\n hostname === \"localhost\" ||\n hostname === \"[::1]\" ||\n hostname === \"::1\"\n );\n}\n\nfunction config(message: string): DecdnError {\n return new DecdnError(\"CONFIG\", message);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted === true) return Promise.reject(signal.reason);\n return new Promise((resolve, reject) => {\n const abort = () => {\n clearTimeout(timer);\n reject(signal?.reason);\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", abort);\n resolve();\n }, ms);\n signal?.addEventListener(\"abort\", abort, { once: true });\n });\n}\n\n/** `promise`, or `signal`'s reason as soon as it aborts. */\nfunction untilAborted<T>(\n promise: Promise<T>,\n signal?: AbortSignal,\n): Promise<T> {\n if (signal === undefined) return promise;\n if (signal.aborted) return Promise.reject(signal.reason);\n return new Promise<T>((resolve, reject) => {\n const abort = () => reject(signal.reason);\n signal.addEventListener(\"abort\", abort, { once: true });\n promise\n .then(resolve, reject)\n .finally(() => signal.removeEventListener(\"abort\", abort));\n });\n}\n\n/** `uri` without `decdn:` and the hash: `[/<path>][?ns=<id>]`, canonically encoded. */\nfunction tail(uri: DecdnUri): string {\n return formatUri(uri).slice(SCHEME.length + 64);\n}\n\n/** One request `get` sends, and what its body must hash to. */\ninterface Plan {\n url: string;\n hash?: string;\n length?: number;\n verified: boolean | \"skipped\";\n /** The entry by its hash, unrewritten: where a verified entry comes from when its site answers with a type the gateway rewrites. */\n blobUrl?: string;\n}\n\n/** The types a site rewrites as it streams (`Rewrite::for_type` in the gateway). */\nfunction isRewrittenType(contentType: string | null): boolean {\n const essence = (contentType ?? \"\").split(\";\")[0]?.trim().toLowerCase();\n return essence === \"text/html\" || essence === \"text/css\";\n}\n\nexport class DecdnClient {\n readonly context: Context;\n /** Namespace pointers (public gateway). */\n readonly pointer: PointerApi = new PointerApi(this);\n /** The delegate and capability API (loopback gateway). */\n readonly loopback: LoopbackApi = new LoopbackApi(this);\n /** @internal */\n readonly fetch: Fetch;\n /** @internal The bare origin: the gateway URL's, or the site's own. */\n readonly origin: string;\n /** @internal */\n readonly pointerDomain?: PointerDomain;\n private readonly gateway?: URL;\n private readonly site?: SiteOrigin;\n private readonly token?: string;\n private readonly host?: string;\n private readonly verify: VerifyMode;\n private readonly cacheSize: number;\n private readonly manifests = new Map<string, Promise<BundleManifest>>();\n\n private constructor(\n context: Context,\n opts: OpenOptions,\n gateway?: URL,\n site?: SiteOrigin,\n ) {\n this.context = context;\n this.fetch = opts.fetch ?? ((input, init) => globalThis.fetch(input, init));\n this.verify = opts.verify ?? \"auto\";\n this.cacheSize = opts.manifestCacheSize ?? 64;\n if (gateway !== undefined) this.gateway = gateway;\n if (site !== undefined) this.site = site;\n if (opts.token !== undefined) this.token = opts.token;\n if (opts.host !== undefined) this.host = opts.host;\n if (opts.pointer !== undefined) this.pointerDomain = opts.pointer;\n this.origin = site?.origin ?? gateway?.origin ?? \"\";\n }\n\n /**\n * A client for the gateway at `gatewayUrl`, or, in a page served from a\n * site origin (`[<ns>.]<hash32>.<host>`, or `<ns>.<host>` under the\n * configured gateway), for that site. A loopback `gatewayUrl` opens the\n * loopback gateway from any page; a page, which cannot send the token,\n * reaches its delegate and capability API alone.\n */\n static async open(opts: OpenOptions = {}): Promise<DecdnClient> {\n let gateway: URL | undefined;\n if (opts.gatewayUrl !== undefined) {\n try {\n gateway = new URL(opts.gatewayUrl);\n } catch (e) {\n throw new DecdnError(\n \"CONFIG\",\n `not a gateway URL: ${opts.gatewayUrl}`,\n { cause: e },\n );\n }\n }\n const loopback =\n gateway !== undefined &&\n (opts.token !== undefined || isLoopbackHost(gateway.hostname));\n const loc = (\n globalThis as { location?: { protocol?: string; host?: string } }\n ).location;\n if (\n !loopback &&\n loc?.host !== undefined &&\n loc.host !== \"\" &&\n loc.protocol !== undefined\n ) {\n const site = siteOf(loc.protocol, loc.host, gateway?.host);\n if (site !== undefined)\n return new DecdnClient(\"site\", opts, gateway, site);\n }\n if (gateway === undefined) {\n throw config(\"no gatewayUrl, and the page is not on a site origin\");\n }\n if (\n opts.token !== undefined &&\n (opts.host === undefined || opts.host === \"\")\n ) {\n throw config(\n \"a loopback token needs `host`: the host whose capability pays, sent as x-decdn-host\",\n );\n }\n return new DecdnClient(loopback ? \"loopback\" : \"public\", opts, gateway);\n }\n\n /** @internal Headers every bare-host request carries. */\n authHeaders(): Record<string, string> {\n if (this.token === undefined || this.host === undefined) return {};\n return { \"x-decdn-token\": this.token, \"x-decdn-host\": this.host };\n }\n\n private parse(uri: string | DecdnUri): DecdnUri {\n return typeof uri === \"string\" ? parseUri(uri) : uri;\n }\n\n /** The URI on the bare host, or under `/_decdn/` on a site. */\n private bareUrl(uri: DecdnUri): string {\n const rest = `${uri.hash}${tail(uri)}`;\n return this.site !== undefined\n ? `${this.site.origin}/_decdn/${rest}`\n : `${this.origin}/${rest}`;\n }\n\n /** The site URL of a bundle or an entry. */\n siteUrl(uri: string | DecdnUri): string {\n const u = this.parse(uri);\n if (u.kind === \"blob\")\n throw config(\"a blob has no site: only a bundle or an entry does\");\n const label = hashToBase32(u.hash);\n const host = u.namespace === undefined ? label : `${u.namespace}.${label}`;\n const path = tail({\n hash: u.hash,\n kind: u.kind,\n ...(u.path === undefined ? {} : { path: u.path }),\n });\n if (this.site !== undefined)\n return `${this.site.protocol}//${host}.${this.site.suffix}${path}`;\n const gw = this.gateway as URL;\n if (this.context === \"loopback\") {\n const port =\n gw.port !== \"\" ? gw.port : gw.protocol === \"https:\" ? \"443\" : \"80\";\n return `${gw.protocol}//${host}.localhost:${port}${path}`;\n }\n return `${gw.protocol}//${host}.${gw.host}${path}`;\n }\n\n /** The host a namespace's pointer serves at on a public gateway: `https://<ns>.<host>/`. */\n namespaceUrl(namespace: bigint | number): string {\n const ns = integer(namespace, \"a namespace id\");\n if (ns <= 0n) throw config(\"a namespace id is at least 1\");\n if (this.site !== undefined)\n return `${this.site.protocol}//${ns}.${this.site.suffix}/`;\n if (this.context === \"loopback\")\n throw config(\"a loopback gateway holds no namespace pointers\");\n const gw = this.gateway as URL;\n return `${gw.protocol}//${ns}.${gw.host}/`;\n }\n\n /** The hash a manifest call names, or the site's own. */\n private manifestHash(hashOrUri?: string | DecdnUri): string {\n if (hashOrUri === undefined) {\n if (this.site?.hash !== undefined) return this.site.hash;\n throw config(\n this.site === undefined\n ? \"manifest needs a hash outside a site page\"\n : \"the manifest hash is unknown on a namespace host\",\n );\n }\n if (typeof hashOrUri === \"string\" && isHash(hashOrUri))\n return hashOrUri.toLowerCase();\n return this.parse(hashOrUri).hash;\n }\n\n /** The bundle manifest a hash or URI names, parsed and verified; cached per client by hash. */\n async manifest(\n hashOrUri?: string | DecdnUri,\n signal?: AbortSignal,\n ): Promise<BundleManifest> {\n const hash = this.manifestHash(hashOrUri);\n const cached = this.manifests.get(hash);\n if (cached !== undefined) {\n this.manifests.delete(hash);\n this.manifests.set(hash, cached);\n return untilAborted(cached, signal);\n }\n // One read serves every caller waiting on this hash, so it carries no\n // caller's signal: each caller stops waiting on its own abort instead.\n const pending = (async () => {\n const response = await this.request(\n this.bareUrl({ hash, kind: \"blob\" }),\n \"GET\",\n {},\n );\n return parseManifest(\n await collect(guard(response.body, {}), MAX_MANIFEST_BYTES),\n hash,\n );\n })();\n this.manifests.set(hash, pending);\n // A failed read drops its own entry only: once evicted, the hash's slot\n // may hold a newer read.\n pending.catch(() => {\n if (this.manifests.get(hash) === pending) this.manifests.delete(hash);\n });\n while (this.manifests.size > this.cacheSize) {\n const oldest = this.manifests.keys().next().value;\n if (oldest === undefined) break;\n this.manifests.delete(oldest);\n }\n return untilAborted(pending, signal);\n }\n\n /** The manifest entry `uri` names; `NOT_FOUND` when the bundle has none. */\n private async entryOf(\n uri: DecdnUri,\n signal?: AbortSignal,\n ): Promise<ManifestEntry> {\n const manifest = await this.manifest(uri.hash, signal);\n const entry = manifest.entries.find((e) => e.path === uri.path);\n if (entry === undefined) {\n throw new DecdnError(\n \"NOT_FOUND\",\n `bundle ${uri.hash} has no entry ${JSON.stringify(uri.path)}`,\n );\n }\n return entry;\n }\n\n /** What `uri` names: for a bundle or an entry, after reading its manifest. */\n async resolve(uri: string | DecdnUri): Promise<Resolved> {\n const u = this.parse(uri);\n const out: Resolved = {\n kind: u.kind,\n hash: u.hash,\n bareUrl: this.bareUrl(u),\n };\n if (u.kind === \"blob\") return out;\n out.siteUrl = this.siteUrl(u);\n if (u.kind === \"bundle\") await this.manifest(u.hash);\n else out.entry = await this.entryOf(u);\n return out;\n }\n\n /** A request to the gateway; a non-2xx answer is thrown as a `DecdnError`. */\n private async request(\n url: string,\n method: string,\n headers: Record<string, string>,\n signal?: AbortSignal,\n ): Promise<Response> {\n const bare = this.site === undefined && url.startsWith(`${this.origin}/`);\n const init: RequestInit = {\n method,\n headers: bare ? { ...this.authHeaders(), ...headers } : headers,\n };\n if (signal !== undefined) init.signal = signal;\n const response = await send(this.fetch, url, init);\n if (response.status < 200 || response.status > 299)\n throw await errorOf(response);\n return response;\n }\n\n /** An entry by its own hash, as a blob: the bytes the manifest names, unrewritten. */\n private entryBlobUrl(uri: DecdnUri, entry: ManifestEntry): string {\n return this.bareUrl({\n hash: entry.hash,\n kind: \"blob\",\n ...(uri.namespace === undefined ? {} : { namespace: uri.namespace }),\n });\n }\n\n /**\n * Where an entry comes from, given its manifest entry (when verifying).\n * `own` holds the query of a path on the site's own bundle: the site serves\n * by path alone and leaves the query to the page, and its host already\n * names the namespace.\n */\n private entryUrl(uri: DecdnUri, own?: string, entry?: ManifestEntry): string {\n if (\n entry !== undefined &&\n rewritten(uri.path ?? \"\") &&\n this.context !== \"loopback\"\n ) {\n return this.entryBlobUrl(uri, entry);\n }\n if (this.site !== undefined)\n return own !== undefined\n ? `${this.site.origin}${tail({\n hash: uri.hash,\n kind: \"entry\",\n ...(uri.path === undefined ? {} : { path: uri.path }),\n })}${own}`\n : this.bareUrl(uri);\n return this.context === \"loopback\" ? this.bareUrl(uri) : this.siteUrl(uri);\n }\n\n private async plan(\n target: string | DecdnUri,\n mode: VerifyMode,\n ranged: boolean,\n signal?: AbortSignal,\n ): Promise<Plan> {\n const off: Plan[\"verified\"] = mode === false ? false : \"skipped\";\n const unverifiable = (why: string): void => {\n if (mode === true) throw config(`verify: true, but ${why}`);\n };\n if (typeof target === \"string\" && target.startsWith(\"/\")) {\n if (this.site === undefined)\n throw config(\n \"a path is relative to a site: open the client on a site page\",\n );\n const path = target.split(/[?#]/)[0] ?? \"/\";\n const query = target.slice(path.length).split(\"#\")[0] ?? \"\";\n if (this.site.hash === undefined || path === \"/\") {\n unverifiable(\n this.site.hash === undefined\n ? \"the bundle is unknown on a namespace host\"\n : \"a bundle listing is not content\",\n );\n return { url: `${this.site.origin}${target}`, verified: off };\n }\n const entry = path.endsWith(\"/\") ? `${path}index.html` : path;\n const uri = parseUri(`${SCHEME}${this.site.hash}${entry}`);\n if (this.site.namespace !== undefined)\n uri.namespace = this.site.namespace;\n return this.planEntry(uri, query, mode, ranged, signal);\n }\n const uri = this.parse(target);\n if (uri.kind === \"blob\") {\n // The gateway serves a blob whole: nothing declares its size, so a\n // range would come back as every byte, or as an unverifiable window.\n if (ranged)\n throw config(\n \"a blob has no declared size to range: fetch it whole, or range a bundle entry\",\n );\n return mode === false\n ? { url: this.bareUrl(uri), verified: false }\n : { url: this.bareUrl(uri), hash: uri.hash, verified: true };\n }\n if (uri.kind === \"bundle\") {\n unverifiable(\"a bundle's index is a page the gateway rewrites\");\n const own = this.site !== undefined && this.site.hash === uri.hash;\n const url =\n this.site !== undefined\n ? own\n ? `${this.site.origin}/`\n : this.bareUrl(uri)\n : this.context === \"loopback\"\n ? this.bareUrl(uri)\n : this.siteUrl(uri);\n return { url, verified: off };\n }\n const own = this.site !== undefined && this.site.hash === uri.hash;\n return this.planEntry(uri, own ? \"\" : undefined, mode, ranged, signal);\n }\n\n private async planEntry(\n uri: DecdnUri,\n own: string | undefined,\n mode: VerifyMode,\n ranged: boolean,\n signal?: AbortSignal,\n ): Promise<Plan> {\n if (mode === false || ranged) {\n if (ranged && mode === true)\n throw config(\"verify: true, but a range cannot be verified\");\n return {\n url: this.entryUrl(uri, own),\n verified: mode === false ? false : \"skipped\",\n };\n }\n const entry = await this.entryOf(uri, signal);\n const plan: Plan = {\n url: this.entryUrl(uri, own, entry),\n hash: entry.hash,\n verified: true,\n };\n if (entry.size !== undefined) plan.length = entry.size;\n const blobUrl = this.entryBlobUrl(uri, entry);\n if (plan.url !== blobUrl && this.context !== \"loopback\")\n plan.blobUrl = blobUrl;\n return plan;\n }\n\n /**\n * Fetch what `uri` names: a `decdn:` URI, or on a site page a path of its\n * own bundle. Verification follows `verify` (see {@link DecdnResponse.verified}).\n */\n async get(\n uri: string | DecdnUri,\n opts: GetOptions = {},\n ): Promise<DecdnResponse> {\n const mode = opts.verify ?? this.verify;\n const plan = await this.plan(\n uri,\n mode,\n opts.range !== undefined,\n opts.signal,\n );\n const headers: Record<string, string> = {};\n if (opts.range !== undefined) {\n const { offset, length } = opts.range;\n if (\n !Number.isSafeInteger(offset) ||\n offset < 0 ||\n (length !== undefined && (!Number.isSafeInteger(length) || length < 1))\n ) {\n throw config(\"a range is a non-negative offset and a positive length\");\n }\n headers.range = `bytes=${offset}-${length === undefined ? \"\" : offset + length - 1}`;\n }\n let response = await this.fetchRetrying(plan.url, headers, opts);\n // A site rewrites what it serves as HTML or CSS. `rewritten` picks those\n // entries out by name up front; any other the site answers with such a\n // type comes by its hash, keeping the site's type.\n let contentType: string | undefined;\n if (\n plan.blobUrl !== undefined &&\n isRewrittenType(response.headers.get(\"content-type\"))\n ) {\n contentType = response.headers.get(\"content-type\") ?? undefined;\n // The page is dropped unread, without waiting: a tee branch's cancel\n // settles only once its sibling does, and a failure changes nothing.\n response.body?.cancel().catch(() => undefined);\n response = await this.fetchRetrying(plan.blobUrl, headers, opts);\n }\n // Only a window the caller asked for goes unhashed: whatever status the\n // gateway answers a whole-body request with, its bytes must hash.\n const whole = opts.range === undefined || response.status === 200;\n const verified =\n plan.verified === true && !whole ? \"skipped\" : plan.verified;\n const length = response.headers.get(\"content-length\");\n const guardOpts: Parameters<typeof guard>[1] = {};\n if (verified === true && plan.hash !== undefined)\n guardOpts.hash = plan.hash;\n // The manifest's size bounds a whole entry both ways, and a window holds\n // at most what was asked for. Content-Length bounds a body from below\n // only: a body decoded on the way can run past it.\n if (whole && plan.length !== undefined) {\n guardOpts.length = plan.length;\n guardOpts.max = plan.length;\n } else {\n if (length !== null && /^\\d+$/.test(length))\n guardOpts.length = Number(length);\n if (!whole && opts.range?.length !== undefined)\n guardOpts.max = opts.range.length;\n }\n if (opts.signal !== undefined) guardOpts.signal = opts.signal;\n return new DecdnResponse(\n response,\n guard(response.body, guardOpts),\n verified,\n contentType,\n );\n }\n\n /** A `GET` of `url`, once more after one `Retry-After` when `opts.retry` asks. */\n private async fetchRetrying(\n url: string,\n headers: Record<string, string>,\n opts: GetOptions,\n ): Promise<Response> {\n try {\n return await this.request(url, \"GET\", headers, opts.signal);\n } catch (e) {\n const retryable =\n e instanceof DecdnError &&\n [\"PAYMENT_REQUIRED\", \"POOL_UNFUNDED\", \"RATE_LIMITED\"].includes(e.code);\n if (!opts.retry || !retryable || e.retryAfterSecs === undefined) throw e;\n await sleep(e.retryAfterSecs * 1000, opts.signal);\n return this.request(url, \"GET\", headers, opts.signal);\n }\n }\n\n /**\n * What is known about `uri` without its bytes: on a public gateway from\n * `HEAD`, elsewhere (where `HEAD` would cost a pull) from the manifest. A\n * public `HEAD` of a raw blob whose size the gateway does not know yet\n * pays for one chunk group, the proof of its size, and is refused or fails\n * as its `GET` would be.\n */\n async head(uri: string | DecdnUri): Promise<HeadInfo> {\n const u = this.parse(uri);\n if (this.context === \"public\") {\n const url = u.kind === \"blob\" ? this.bareUrl(u) : this.siteUrl(u);\n const response = await this.request(url, \"HEAD\", {});\n const info: HeadInfo = {};\n const length = response.headers.get(\"content-length\");\n if (length !== null && /^\\d+$/.test(length)) info.size = Number(length);\n const etag = /^\"?([0-9a-fA-F]{64})\"?$/.exec(\n response.headers.get(\"etag\") ?? \"\",\n )?.[1];\n if (etag !== undefined) info.hash = etag.toLowerCase();\n const type = response.headers.get(\"content-type\");\n if (type !== null) info.contentType = type;\n return info;\n }\n if (u.kind !== \"entry\") return { hash: u.hash };\n const entry = await this.entryOf(u);\n const info: HeadInfo = {\n hash: entry.hash,\n contentType: siteType(entry.path),\n };\n if (entry.size !== undefined) info.size = entry.size;\n return info;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["bad", "U64_MAX", "bad", "malformed", "uri", "own", "length", "info"]
7
+ }
package/dist/node.cjs ADDED
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/node.ts
21
+ var node_exports = {};
22
+ __export(node_exports, {
23
+ defaultDataDir: () => defaultDataDir,
24
+ readLoopbackToken: () => readLoopbackToken
25
+ });
26
+ module.exports = __toCommonJS(node_exports);
27
+ var import_promises = require("node:fs/promises");
28
+ var import_node_os = require("node:os");
29
+ var import_node_path = require("node:path");
30
+
31
+ // src/errors.ts
32
+ var DecdnError = class extends Error {
33
+ name = "DecdnError";
34
+ code;
35
+ status;
36
+ retryAfterSecs;
37
+ fallbackUri;
38
+ size;
39
+ seq;
40
+ body;
41
+ constructor(code, message, details = {}) {
42
+ super(
43
+ message,
44
+ details.cause === void 0 ? void 0 : { cause: details.cause }
45
+ );
46
+ this.code = code;
47
+ if (details.status !== void 0) this.status = details.status;
48
+ if (details.retryAfterSecs !== void 0)
49
+ this.retryAfterSecs = details.retryAfterSecs;
50
+ if (details.fallbackUri !== void 0)
51
+ this.fallbackUri = details.fallbackUri;
52
+ if (details.size !== void 0) this.size = details.size;
53
+ if (details.seq !== void 0) this.seq = details.seq;
54
+ if (details.body !== void 0) this.body = details.body;
55
+ }
56
+ };
57
+
58
+ // src/node.ts
59
+ function defaultDataDir() {
60
+ return (0, import_node_path.join)((0, import_node_os.homedir)(), ".decdn", "gateway");
61
+ }
62
+ async function readLoopbackToken(dataDir = defaultDataDir()) {
63
+ const path = (0, import_node_path.join)(dataDir, "token");
64
+ let token;
65
+ try {
66
+ token = (await (0, import_promises.readFile)(path, "utf8")).trim();
67
+ } catch (e) {
68
+ throw new DecdnError(
69
+ "CONFIG",
70
+ `cannot read the gateway token at ${path}: start \`decdn gateway\` first`,
71
+ {
72
+ cause: e
73
+ }
74
+ );
75
+ }
76
+ if (!/^[0-9a-f]{64}$/i.test(token)) {
77
+ throw new DecdnError(
78
+ "CONFIG",
79
+ `${path} does not hold a gateway token (64 hex characters)`
80
+ );
81
+ }
82
+ return token;
83
+ }
84
+ //# sourceMappingURL=node.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/node.ts", "../src/errors.ts"],
4
+ "sourcesContent": ["// Node.js helpers: `@decdn/client/node`, under the `node` export condition.\nimport { readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { DecdnError } from \"./errors.js\";\n\n/** The loopback gateway's default data dir, `~/.decdn/gateway`. */\nexport function defaultDataDir(): string {\n return join(homedir(), \".decdn\", \"gateway\");\n}\n\n/**\n * The token a loopback `decdn gateway` keeps in `<dataDir>/token` (mode 0600),\n * for `DecdnClient.open({ token })`. `dataDir` is the gateway's `--data-dir`.\n */\nexport async function readLoopbackToken(\n dataDir: string = defaultDataDir(),\n): Promise<string> {\n const path = join(dataDir, \"token\");\n let token: string;\n try {\n token = (await readFile(path, \"utf8\")).trim();\n } catch (e) {\n throw new DecdnError(\n \"CONFIG\",\n `cannot read the gateway token at ${path}: start \\`decdn gateway\\` first`,\n {\n cause: e,\n },\n );\n }\n if (!/^[0-9a-f]{64}$/i.test(token)) {\n throw new DecdnError(\n \"CONFIG\",\n `${path} does not hold a gateway token (64 hex characters)`,\n );\n }\n return token;\n}\n", "/** What went wrong, as a stable code a caller can branch on. */\nexport type DecdnErrorCode =\n /** 402: the gateway's allowance is spent, or the content does not fit what is left, or no capability covers the host. */\n | \"PAYMENT_REQUIRED\"\n /** 503: the gateway's pool cannot pay. */\n | \"POOL_UNFUNDED\"\n /** 404. */\n | \"NOT_FOUND\"\n /** 416: the range starts past the end; `size` holds the entry's size. */\n | \"RANGE_NOT_SATISFIABLE\"\n /** 401: the loopback token is missing or wrong. */\n | \"UNAUTHORIZED\"\n /** 403. */\n | \"FORBIDDEN\"\n /** 400, or a `decdn:` URI that does not parse. */\n | \"BAD_URI\"\n /** 429. */\n | \"RATE_LIMITED\"\n /** 502: the gateway's pull failed upstream. */\n | \"UPSTREAM\"\n /** 413. */\n | \"PAYLOAD_TOO_LARGE\"\n /** 409: a pointer `seq` that is not newer, or a capability already registered. */\n | \"CONFLICT\"\n /** 422. */\n | \"UNPROCESSABLE\"\n /** The bytes do not hash to the hash that names them. */\n | \"HASH_MISMATCH\"\n /** The body is shorter or longer than declared, or the stream failed. */\n | \"TRUNCATED\"\n /** A bundle manifest that does not parse. */\n | \"MALFORMED_MANIFEST\"\n /** A `dcap1:` capability token that does not decode. */\n | \"BAD_CAPABILITY\"\n /** The gateway could not be reached. */\n | \"NETWORK\"\n /** The client is not set up for the call, or the call cannot be honoured as asked. */\n | \"CONFIG\"\n /** A status the gateway contract does not name. */\n | \"HTTP\";\n\n/** Fields a {@link DecdnError} may carry besides its code and message. */\nexport interface DecdnErrorDetails {\n /** The HTTP status, when the gateway answered. */\n status?: number;\n /** Seconds to wait before a retry, from `Retry-After` or the JSON body. */\n retryAfterSecs?: number;\n /** The canonical `decdn:` URI to fetch with a paying client instead. */\n fallbackUri?: string;\n /** The entry's size, on `RANGE_NOT_SATISFIABLE`. */\n size?: number;\n /** The highest stored `seq`, on a pointer `CONFLICT`. */\n seq?: bigint;\n /** The response body, as text. */\n body?: string;\n /** What caused this error. */\n cause?: unknown;\n}\n\n/** Every failure the SDK reports. */\nexport class DecdnError extends Error {\n override readonly name = \"DecdnError\";\n readonly code: DecdnErrorCode;\n readonly status?: number;\n readonly retryAfterSecs?: number;\n readonly fallbackUri?: string;\n readonly size?: number;\n readonly seq?: bigint;\n readonly body?: string;\n\n constructor(\n code: DecdnErrorCode,\n message: string,\n details: DecdnErrorDetails = {},\n ) {\n super(\n message,\n details.cause === undefined ? undefined : { cause: details.cause },\n );\n this.code = code;\n if (details.status !== undefined) this.status = details.status;\n if (details.retryAfterSecs !== undefined)\n this.retryAfterSecs = details.retryAfterSecs;\n if (details.fallbackUri !== undefined)\n this.fallbackUri = details.fallbackUri;\n if (details.size !== undefined) this.size = details.size;\n if (details.seq !== undefined) this.seq = details.seq;\n if (details.body !== undefined) this.body = details.body;\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,sBAAyB;AACzB,qBAAwB;AACxB,uBAAqB;;;ACyDd,IAAM,aAAN,cAAyB,MAAM;AAAA,EAClB,OAAO;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,MACA,SACA,UAA6B,CAAC,GAC9B;AACA;AAAA,MACE;AAAA,MACA,QAAQ,UAAU,SAAY,SAAY,EAAE,OAAO,QAAQ,MAAM;AAAA,IACnE;AACA,SAAK,OAAO;AACZ,QAAI,QAAQ,WAAW,OAAW,MAAK,SAAS,QAAQ;AACxD,QAAI,QAAQ,mBAAmB;AAC7B,WAAK,iBAAiB,QAAQ;AAChC,QAAI,QAAQ,gBAAgB;AAC1B,WAAK,cAAc,QAAQ;AAC7B,QAAI,QAAQ,SAAS,OAAW,MAAK,OAAO,QAAQ;AACpD,QAAI,QAAQ,QAAQ,OAAW,MAAK,MAAM,QAAQ;AAClD,QAAI,QAAQ,SAAS,OAAW,MAAK,OAAO,QAAQ;AAAA,EACtD;AACF;;;ADlFO,SAAS,iBAAyB;AACvC,aAAO,2BAAK,wBAAQ,GAAG,UAAU,SAAS;AAC5C;AAMA,eAAsB,kBACpB,UAAkB,eAAe,GAChB;AACjB,QAAM,WAAO,uBAAK,SAAS,OAAO;AAClC,MAAI;AACJ,MAAI;AACF,aAAS,UAAM,0BAAS,MAAM,MAAM,GAAG,KAAK;AAAA,EAC9C,SAAS,GAAG;AACV,UAAM,IAAI;AAAA,MACR;AAAA,MACA,oCAAoC,IAAI;AAAA,MACxC;AAAA,QACE,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,kBAAkB,KAAK,KAAK,GAAG;AAClC,UAAM,IAAI;AAAA,MACR;AAAA,MACA,GAAG,IAAI;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ export * from "./types/node.js";
package/dist/node.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./types/node.js";
package/dist/node.js ADDED
@@ -0,0 +1,63 @@
1
+ // src/node.ts
2
+ import { readFile } from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+
6
+ // src/errors.ts
7
+ var DecdnError = class extends Error {
8
+ name = "DecdnError";
9
+ code;
10
+ status;
11
+ retryAfterSecs;
12
+ fallbackUri;
13
+ size;
14
+ seq;
15
+ body;
16
+ constructor(code, message, details = {}) {
17
+ super(
18
+ message,
19
+ details.cause === void 0 ? void 0 : { cause: details.cause }
20
+ );
21
+ this.code = code;
22
+ if (details.status !== void 0) this.status = details.status;
23
+ if (details.retryAfterSecs !== void 0)
24
+ this.retryAfterSecs = details.retryAfterSecs;
25
+ if (details.fallbackUri !== void 0)
26
+ this.fallbackUri = details.fallbackUri;
27
+ if (details.size !== void 0) this.size = details.size;
28
+ if (details.seq !== void 0) this.seq = details.seq;
29
+ if (details.body !== void 0) this.body = details.body;
30
+ }
31
+ };
32
+
33
+ // src/node.ts
34
+ function defaultDataDir() {
35
+ return join(homedir(), ".decdn", "gateway");
36
+ }
37
+ async function readLoopbackToken(dataDir = defaultDataDir()) {
38
+ const path = join(dataDir, "token");
39
+ let token;
40
+ try {
41
+ token = (await readFile(path, "utf8")).trim();
42
+ } catch (e) {
43
+ throw new DecdnError(
44
+ "CONFIG",
45
+ `cannot read the gateway token at ${path}: start \`decdn gateway\` first`,
46
+ {
47
+ cause: e
48
+ }
49
+ );
50
+ }
51
+ if (!/^[0-9a-f]{64}$/i.test(token)) {
52
+ throw new DecdnError(
53
+ "CONFIG",
54
+ `${path} does not hold a gateway token (64 hex characters)`
55
+ );
56
+ }
57
+ return token;
58
+ }
59
+ export {
60
+ defaultDataDir,
61
+ readLoopbackToken
62
+ };
63
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/node.ts", "../src/errors.ts"],
4
+ "sourcesContent": ["// Node.js helpers: `@decdn/client/node`, under the `node` export condition.\nimport { readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { DecdnError } from \"./errors.js\";\n\n/** The loopback gateway's default data dir, `~/.decdn/gateway`. */\nexport function defaultDataDir(): string {\n return join(homedir(), \".decdn\", \"gateway\");\n}\n\n/**\n * The token a loopback `decdn gateway` keeps in `<dataDir>/token` (mode 0600),\n * for `DecdnClient.open({ token })`. `dataDir` is the gateway's `--data-dir`.\n */\nexport async function readLoopbackToken(\n dataDir: string = defaultDataDir(),\n): Promise<string> {\n const path = join(dataDir, \"token\");\n let token: string;\n try {\n token = (await readFile(path, \"utf8\")).trim();\n } catch (e) {\n throw new DecdnError(\n \"CONFIG\",\n `cannot read the gateway token at ${path}: start \\`decdn gateway\\` first`,\n {\n cause: e,\n },\n );\n }\n if (!/^[0-9a-f]{64}$/i.test(token)) {\n throw new DecdnError(\n \"CONFIG\",\n `${path} does not hold a gateway token (64 hex characters)`,\n );\n }\n return token;\n}\n", "/** What went wrong, as a stable code a caller can branch on. */\nexport type DecdnErrorCode =\n /** 402: the gateway's allowance is spent, or the content does not fit what is left, or no capability covers the host. */\n | \"PAYMENT_REQUIRED\"\n /** 503: the gateway's pool cannot pay. */\n | \"POOL_UNFUNDED\"\n /** 404. */\n | \"NOT_FOUND\"\n /** 416: the range starts past the end; `size` holds the entry's size. */\n | \"RANGE_NOT_SATISFIABLE\"\n /** 401: the loopback token is missing or wrong. */\n | \"UNAUTHORIZED\"\n /** 403. */\n | \"FORBIDDEN\"\n /** 400, or a `decdn:` URI that does not parse. */\n | \"BAD_URI\"\n /** 429. */\n | \"RATE_LIMITED\"\n /** 502: the gateway's pull failed upstream. */\n | \"UPSTREAM\"\n /** 413. */\n | \"PAYLOAD_TOO_LARGE\"\n /** 409: a pointer `seq` that is not newer, or a capability already registered. */\n | \"CONFLICT\"\n /** 422. */\n | \"UNPROCESSABLE\"\n /** The bytes do not hash to the hash that names them. */\n | \"HASH_MISMATCH\"\n /** The body is shorter or longer than declared, or the stream failed. */\n | \"TRUNCATED\"\n /** A bundle manifest that does not parse. */\n | \"MALFORMED_MANIFEST\"\n /** A `dcap1:` capability token that does not decode. */\n | \"BAD_CAPABILITY\"\n /** The gateway could not be reached. */\n | \"NETWORK\"\n /** The client is not set up for the call, or the call cannot be honoured as asked. */\n | \"CONFIG\"\n /** A status the gateway contract does not name. */\n | \"HTTP\";\n\n/** Fields a {@link DecdnError} may carry besides its code and message. */\nexport interface DecdnErrorDetails {\n /** The HTTP status, when the gateway answered. */\n status?: number;\n /** Seconds to wait before a retry, from `Retry-After` or the JSON body. */\n retryAfterSecs?: number;\n /** The canonical `decdn:` URI to fetch with a paying client instead. */\n fallbackUri?: string;\n /** The entry's size, on `RANGE_NOT_SATISFIABLE`. */\n size?: number;\n /** The highest stored `seq`, on a pointer `CONFLICT`. */\n seq?: bigint;\n /** The response body, as text. */\n body?: string;\n /** What caused this error. */\n cause?: unknown;\n}\n\n/** Every failure the SDK reports. */\nexport class DecdnError extends Error {\n override readonly name = \"DecdnError\";\n readonly code: DecdnErrorCode;\n readonly status?: number;\n readonly retryAfterSecs?: number;\n readonly fallbackUri?: string;\n readonly size?: number;\n readonly seq?: bigint;\n readonly body?: string;\n\n constructor(\n code: DecdnErrorCode,\n message: string,\n details: DecdnErrorDetails = {},\n ) {\n super(\n message,\n details.cause === undefined ? undefined : { cause: details.cause },\n );\n this.code = code;\n if (details.status !== undefined) this.status = details.status;\n if (details.retryAfterSecs !== undefined)\n this.retryAfterSecs = details.retryAfterSecs;\n if (details.fallbackUri !== undefined)\n this.fallbackUri = details.fallbackUri;\n if (details.size !== undefined) this.size = details.size;\n if (details.seq !== undefined) this.seq = details.seq;\n if (details.body !== undefined) this.body = details.body;\n }\n}\n"],
5
+ "mappings": ";AACA,SAAS,gBAAgB;AACzB,SAAS,eAAe;AACxB,SAAS,YAAY;;;ACyDd,IAAM,aAAN,cAAyB,MAAM;AAAA,EAClB,OAAO;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,MACA,SACA,UAA6B,CAAC,GAC9B;AACA;AAAA,MACE;AAAA,MACA,QAAQ,UAAU,SAAY,SAAY,EAAE,OAAO,QAAQ,MAAM;AAAA,IACnE;AACA,SAAK,OAAO;AACZ,QAAI,QAAQ,WAAW,OAAW,MAAK,SAAS,QAAQ;AACxD,QAAI,QAAQ,mBAAmB;AAC7B,WAAK,iBAAiB,QAAQ;AAChC,QAAI,QAAQ,gBAAgB;AAC1B,WAAK,cAAc,QAAQ;AAC7B,QAAI,QAAQ,SAAS,OAAW,MAAK,OAAO,QAAQ;AACpD,QAAI,QAAQ,QAAQ,OAAW,MAAK,MAAM,QAAQ;AAClD,QAAI,QAAQ,SAAS,OAAW,MAAK,OAAO,QAAQ;AAAA,EACtD;AACF;;;ADlFO,SAAS,iBAAyB;AACvC,SAAO,KAAK,QAAQ,GAAG,UAAU,SAAS;AAC5C;AAMA,eAAsB,kBACpB,UAAkB,eAAe,GAChB;AACjB,QAAM,OAAO,KAAK,SAAS,OAAO;AAClC,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,SAAS,MAAM,MAAM,GAAG,KAAK;AAAA,EAC9C,SAAS,GAAG;AACV,UAAM,IAAI;AAAA,MACR;AAAA,MACA,oCAAoC,IAAI;AAAA,MACxC;AAAA,QACE,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,kBAAkB,KAAK,KAAK,GAAG;AAClC,UAAM,IAAI;AAAA,MACR;AAAA,MACA,GAAG,IAAI;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,8 @@
1
+ /** The site label of a 64-hex-character hash. */
2
+ export declare function hashToBase32(hash: string): string;
3
+ /**
4
+ * The hash a canonical site label encodes, as 64 lowercase hex characters, or
5
+ * `undefined` for anything else: the wrong length, uppercase, or nonzero
6
+ * trailing bits (a second spelling the gateway refuses).
7
+ */
8
+ export declare function base32ToHash(label: string): string | undefined;
@@ -0,0 +1,15 @@
1
+ /** A pool owner's spending grant to a delegate signer. */
2
+ export interface Capability {
3
+ /** The on-chain pool, `0x` + 64 hex. */
4
+ poolId: string;
5
+ /** The delegate voucher-signing address, `0x` + 40 hex. */
6
+ signer: string;
7
+ /** Cumulative spend ceiling in USDC base units. */
8
+ spendingCap: bigint;
9
+ /** Unix-seconds expiry. */
10
+ expiry: bigint;
11
+ /** The owner's raw EIP-712 signature, `0x` + hex. */
12
+ ownerSignature: string;
13
+ }
14
+ /** Decode a `dcap1:` token. Throws `BAD_CAPABILITY` for anything else. */
15
+ export declare function parseCapability(token: string): Capability;