{
  "version": 3,
  "sources": ["../../../../src/workers/shared/blob.worker.ts", "../../../../src/workers/shared/data.ts", "../../../../src/workers/shared/constants.ts", "../../../../src/workers/shared/keyvalue.worker.ts", "../../../../src/workers/shared/sql.worker.ts", "../../../../src/workers/shared/matcher.ts", "../../../../src/workers/shared/object.worker.ts", "../../../../src/workers/shared/router.worker.ts", "../../../../src/workers/shared/timers.worker.ts", "../../../../src/workers/shared/types.ts", "../../../../src/workers/shared/public-url.ts", "../../../../src/workers/shared/range.ts", "../../../../src/workers/shared/sync.ts"],
  "sourcesContent": ["import assert from \"node:assert\";\nimport { Buffer } from \"node:buffer\";\nimport { sanitisePath } from \"./data\";\nimport type { InclusiveRange } from \"./range\";\n\nconst ENCODER = new TextEncoder();\n\nexport async function readPrefix(\n\tstream: ReadableStream<Uint8Array>,\n\tprefixLength: number\n): Promise<[prefix: Uint8Array, rest: ReadableStream]> {\n\tconst reader = await stream.getReader({ mode: \"byob\" });\n\tconst result = await reader.readAtLeast(\n\t\tprefixLength,\n\t\tnew Uint8Array(prefixLength)\n\t);\n\tassert(result.value !== undefined);\n\treader.releaseLock();\n\t// Without this `pipeThrough()`, getting uncaught `TypeError: Can't read from\n\t// request stream after response has been sent.`\n\tconst rest = stream.pipeThrough(new IdentityTransformStream());\n\treturn [result.value, rest];\n}\n\nfunction rangeHeaders(range: InclusiveRange) {\n\treturn { Range: `bytes=${range.start}-${range.end}` };\n}\n\nfunction assertFullRangeRequest(range: InclusiveRange, contentLength: number) {\n\tassert(\n\t\trange.start === 0 && range.end === contentLength - 1,\n\t\t\"Received full content, but requested partial content\"\n\t);\n}\n\nasync function fetchSingleRange(\n\tfetcher: Fetcher,\n\turl: URL,\n\trange?: InclusiveRange\n): Promise<ReadableStream | null> {\n\tconst headers: HeadersInit = range === undefined ? {} : rangeHeaders(range);\n\tconst res = await fetcher.fetch(url, { headers });\n\n\t// If we couldn't find the resource, return `null`\n\tif (res.status === 404) return null;\n\n\t// Otherwise, make sure we have the expected response, and return the body\n\tassert(res.ok && res.body !== null);\n\tif (range !== undefined && res.status !== 206) {\n\t\t// If we specified a range, but received full content, make sure the range\n\t\t// covered the full content\n\t\tconst contentLength = parseInt(res.headers.get(\"Content-Length\") ?? \"NaN\");\n\t\tassert(!Number.isNaN(contentLength));\n\t\tassertFullRangeRequest(range, contentLength);\n\t}\n\treturn res.body;\n}\n\nexport interface MultipartOptions {\n\tcontentType?: string;\n}\nexport interface MultipartReadableStream {\n\tmultipartContentType: string;\n\tbody: ReadableStream<Uint8Array>;\n}\nasync function writeMultipleRanges(\n\tfetcher: Fetcher,\n\turl: URL,\n\tranges: InclusiveRange[],\n\tboundary: string,\n\twritable: WritableStream,\n\tcontentLength: number,\n\tcontentType?: string\n): Promise<void> {\n\tfor (let i = 0; i < ranges.length; i++) {\n\t\tconst range = ranges[i];\n\t\tconst writer = writable.getWriter();\n\t\t// If this isn't the first thing we've written, we'll need to prepend CRLF\n\t\tif (i > 0) await writer.write(ENCODER.encode(\"\\r\\n\"));\n\t\t// Write boundary and headers\n\t\tawait writer.write(ENCODER.encode(`--${boundary}\\r\\n`));\n\t\tif (contentType !== undefined) {\n\t\t\tawait writer.write(ENCODER.encode(`Content-Type: ${contentType}\\r\\n`));\n\t\t}\n\t\tconst start = range.start;\n\t\tconst end = Math.min(range.end, contentLength - 1);\n\t\tawait writer.write(\n\t\t\tENCODER.encode(\n\t\t\t\t`Content-Range: bytes ${start}-${end}/${contentLength}\\r\\n\\r\\n`\n\t\t\t)\n\t\t);\n\t\twriter.releaseLock();\n\t\t// Fetch and write the range\n\t\tconst res = await fetcher.fetch(url, { headers: rangeHeaders(range) });\n\t\tassert(\n\t\t\tres.ok && res.body !== null,\n\t\t\t`Failed to fetch ${url}[${range.start},${range.end}], received ${res.status} ${res.statusText}`\n\t\t);\n\t\t// If we specified a range, but received full content, make sure the range\n\t\t// covered the full content\n\t\tif (res.status !== 206) assertFullRangeRequest(range, contentLength);\n\t\tawait res.body.pipeTo(writable, { preventClose: true });\n\t}\n\t// Finished writing all ranges, now write the trailer\n\tconst writer = writable.getWriter();\n\tif (ranges.length > 0) await writer.write(ENCODER.encode(\"\\r\\n\"));\n\tawait writer.write(ENCODER.encode(`--${boundary}--`));\n\tawait writer.close();\n}\nasync function fetchMultipleRanges(\n\tfetcher: Fetcher,\n\turl: URL,\n\tranges: InclusiveRange[],\n\topts?: MultipartOptions\n): Promise<MultipartReadableStream | null> {\n\t// Check resource exists, and get content length\n\tconst res = await fetcher.fetch(url, { method: \"HEAD\" });\n\tif (res.status === 404) return null;\n\tassert(res.ok);\n\n\tconst contentLength = parseInt(res.headers.get(\"Content-Length\") ?? \"NaN\");\n\tassert(!Number.isNaN(contentLength));\n\n\t// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests#multipart_ranges\n\t// for details on `multipart/byteranges` responses\n\tconst boundary = `miniflare-boundary-${crypto.randomUUID()}`;\n\tconst multipartContentType = `multipart/byteranges; boundary=${boundary}`;\n\tconst { readable, writable } = new IdentityTransformStream();\n\tvoid writeMultipleRanges(\n\t\tfetcher,\n\t\turl,\n\t\tranges,\n\t\tboundary,\n\t\twritable,\n\t\tcontentLength,\n\t\topts?.contentType\n\t).catch((e) => console.error(\"Error writing multipart stream:\", e));\n\treturn { multipartContentType, body: readable };\n}\n\nasync function fetchRange(\n\tfetcher: Fetcher,\n\turl: URL,\n\trange?: InclusiveRange | InclusiveRange[],\n\topts?: MultipartOptions\n): Promise<ReadableStream<Uint8Array> | MultipartReadableStream | null> {\n\tif (Array.isArray(range)) {\n\t\treturn fetchMultipleRanges(fetcher, url, range, opts);\n\t} else {\n\t\treturn fetchSingleRange(fetcher, url, range);\n\t}\n}\n\nfunction generateBlobId(): BlobId {\n\tconst idBuffer = Buffer.alloc(40);\n\tcrypto.getRandomValues(\n\t\tnew Uint8Array(idBuffer.buffer, idBuffer.byteOffset, 32)\n\t);\n\tidBuffer.writeBigInt64BE(\n\t\tBigInt(performance.timeOrigin + performance.now()),\n\t\t32\n\t);\n\treturn idBuffer.toString(\"hex\");\n}\n\n// Serialisable, opaque, unguessable blob identifier\nexport type BlobId = string;\nexport class BlobStore {\n\t// Database for binary large objects. Provides single and multi-ranged\n\t// streaming reads and writes.\n\t//\n\t// Blobs have unguessable identifiers, can be deleted, but are otherwise\n\t// immutable. These properties make it possible to perform atomic updates with\n\t// the SQLite metadata store. No other operations will be able to interact\n\t// with the blob until it's committed to the metadata store, because they\n\t// won't be able to guess the ID, and we don't allow listing blobs.\n\t//\n\t// For example, if we put a blob in the store, then fail to insert the blob ID\n\t// into the SQLite database for some reason during a transaction (e.g.\n\t// `onlyIf` condition failed), no other operations can read that blob because\n\t// the ID is lost (we'll just background-delete the blob in this case).\n\n\treadonly #fetcher: Fetcher;\n\treadonly #baseURL: string;\n\treadonly #stickyBlobs: boolean;\n\n\tconstructor(fetcher: Fetcher, namespace: string, stickyBlobs: boolean) {\n\t\tnamespace = encodeURIComponent(sanitisePath(namespace));\n\t\tthis.#fetcher = fetcher;\n\t\t// `baseURL`'s `pathname` (`/${namespace}/blobs/`) is relative to the\n\t\t// `*Persist` (e.g. `kvPersist`) option if defined. For example, if\n\t\t// `kvPersist` is `/path/to/kv`, the `blobs` directory for a KV namespace\n\t\t// with ID `TEST_NAMESPACE` would be `/path/to/kv/TEST_NAMESPACE/blobs`.\n\t\tthis.#baseURL = `http://placeholder/${namespace}/blobs/`;\n\t\tthis.#stickyBlobs = stickyBlobs;\n\t}\n\n\tprivate idURL(id: BlobId) {\n\t\tconst url = new URL(this.#baseURL + id);\n\t\treturn url.toString().startsWith(this.#baseURL) ? url : null;\n\t}\n\n\tget(\n\t\tid: BlobId,\n\t\trange?: InclusiveRange\n\t): Promise<ReadableStream<Uint8Array> | null>;\n\tget(\n\t\tid: BlobId,\n\t\tranges: InclusiveRange[],\n\t\topts?: MultipartOptions\n\t): Promise<MultipartReadableStream | null>;\n\tasync get(\n\t\tid: BlobId,\n\t\trange?: InclusiveRange | InclusiveRange[],\n\t\topts?: MultipartOptions\n\t): Promise<ReadableStream<Uint8Array> | MultipartReadableStream | null> {\n\t\t// Get path for this ID, returning null if it's outside the root\n\t\tconst idURL = this.idURL(id);\n\t\tif (idURL === null) return null;\n\t\t// Get correct response for range, returning null if not found\n\t\treturn fetchRange(this.#fetcher, idURL, range, opts);\n\t}\n\n\tasync put(stream: ReadableStream<Uint8Array>): Promise<BlobId> {\n\t\tconst id = generateBlobId();\n\n\t\t// Get path for this ID, this should never be null as blob IDs are encoded\n\t\tconst idURL = this.idURL(id);\n\t\tassert(idURL !== null);\n\t\t// Write stream to file\n\t\t// TODO(someday): add support for exclusive flag to assert new file creation\n\t\t// TODO(someday): add support for marking file read-only\n\t\tawait this.#fetcher.fetch(idURL, {\n\t\t\tmethod: \"PUT\",\n\t\t\tbody: stream,\n\t\t});\n\n\t\treturn id;\n\t}\n\n\tasync delete(id: BlobId): Promise<void> {\n\t\t// If sticky blobs are enabled, don't delete any blobs\n\t\tif (this.#stickyBlobs) return;\n\t\t// Get path for this ID and delete, ignoring if outside root or not found\n\t\tconst idURL = this.idURL(id);\n\t\tif (idURL === null) return;\n\t\tconst res = await this.#fetcher.fetch(idURL, { method: \"DELETE\" });\n\t\tassert(res.ok || res.status === 404);\n\t}\n}\n", "import { Buffer } from \"node:buffer\";\n\nexport function viewToBuffer(view: ArrayBufferView): ArrayBuffer {\n\treturn view.buffer.slice(\n\t\tview.byteOffset,\n\t\tview.byteOffset + view.byteLength\n\t) as ArrayBuffer;\n}\n\nexport function base64Encode(value: string): string {\n\treturn Buffer.from(value, \"utf8\").toString(\"base64\");\n}\nexport function base64Decode(encoded: string): string {\n\treturn Buffer.from(encoded, \"base64\").toString(\"utf8\");\n}\n\n/*! Path sanitisation regexps adapted from node-sanitize-filename:\n * https://github.com/parshap/node-sanitize-filename/blob/209c39b914c8eb48ee27bcbde64b2c7822fdf3de/index.js#L4-L37\n *\n * Licensed under the ISC license:\n *\n * Copyright Parsha Pourkhomami <parshap@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the\n * above copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY\n * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\n * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\nconst dotRegexp = /(^|\\/|\\\\)(\\.+)(\\/|\\\\|$)/g;\nconst illegalRegexp = /[?<>*\"'^/\\\\:|\\x00-\\x1f\\x80-\\x9f]/g;\nconst windowsReservedRegexp = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\\..*)?$/i;\nconst leadingRegexp = /^[ /\\\\]+/;\nconst trailingRegexp = /[ /\\\\]+$/;\n\nfunction dotReplacement(match: string, g1: string, g2: string, g3: string) {\n\treturn `${g1}${\"\".padStart(g2.length, \"_\")}${g3}`;\n}\n\nfunction underscoreReplacement(match: string) {\n\treturn \"\".padStart(match.length, \"_\");\n}\n\nexport function sanitisePath(unsafe: string): string {\n\treturn unsafe\n\t\t.replace(dotRegexp, dotReplacement)\n\t\t.replace(dotRegexp, dotReplacement)\n\t\t.replace(illegalRegexp, \"_\")\n\t\t.replace(windowsReservedRegexp, \"_\")\n\t\t.replace(leadingRegexp, underscoreReplacement)\n\t\t.replace(trailingRegexp, underscoreReplacement)\n\t\t.substring(0, 255);\n}\n", "export const SharedHeaders = {\n\tLOG_LEVEL: \"MF-Log-Level\",\n} as const;\n\nexport const SharedBindings = {\n\tTEXT_NAMESPACE: \"MINIFLARE_NAMESPACE\",\n\tDURABLE_OBJECT_NAMESPACE_OBJECT: \"MINIFLARE_OBJECT\",\n\tMAYBE_SERVICE_BLOBS: \"MINIFLARE_BLOBS\",\n\tMAYBE_SERVICE_LOOPBACK: \"MINIFLARE_LOOPBACK\",\n\tMAYBE_JSON_ENABLE_CONTROL_ENDPOINTS: \"MINIFLARE_ENABLE_CONTROL_ENDPOINTS\",\n\tMAYBE_JSON_ENABLE_STICKY_BLOBS: \"MINIFLARE_STICKY_BLOBS\",\n} as const;\n\nexport enum LogLevel {\n\tNONE,\n\tERROR,\n\tWARN,\n\tINFO,\n\tDEBUG,\n\tVERBOSE,\n}\n", "import assert from \"node:assert\";\nimport { base64Decode, base64Encode } from \"./data\";\nimport { all, drain, get } from \"./sql.worker\";\nimport type {\n\tBlobId,\n\tBlobStore,\n\tMultipartOptions,\n\tMultipartReadableStream,\n} from \"./blob.worker\";\nimport type { MiniflareDurableObject } from \"./object.worker\";\nimport type { InclusiveRange } from \"./range\";\nimport type { TypedSql } from \"./sql.worker\";\nimport type { Timers } from \"./timers.worker\";\nimport type { Awaitable } from \"./types\";\n\nexport interface KeyEntry<Metadata = unknown> {\n\tkey: string;\n\texpiration?: number; // milliseconds since unix epoch\n\tmetadata?: Metadata;\n}\nexport interface KeyValueEntry<Metadata = unknown> extends KeyEntry<Metadata> {\n\tvalue: ReadableStream<Uint8Array>;\n}\nexport interface KeyMultipartValueEntry<\n\tMetadata = unknown,\n> extends KeyEntry<Metadata> {\n\tvalue: MultipartReadableStream;\n}\n\nexport interface KeyEntriesQuery {\n\tprefix?: string;\n\tcursor?: string;\n\tlimit: number;\n}\nexport interface KeyEntries<Metadata = unknown> {\n\tkeys: KeyEntry<Metadata>[];\n\tcursor?: string;\n}\n\ntype Row = {\n\tkey: string;\n\tblob_id: BlobId;\n\texpiration: number | null; // milliseconds since unix epoch\n\tmetadata: string | null;\n};\nconst SQL_SCHEMA = `\nCREATE TABLE IF NOT EXISTS _mf_entries (\n  key TEXT PRIMARY KEY,\n  blob_id TEXT NOT NULL,\n  expiration INTEGER,\n  metadata TEXT\n);\nCREATE INDEX IF NOT EXISTS _mf_entries_expiration_idx ON _mf_entries(expiration);\n`;\nfunction sqlStmts(db: TypedSql) {\n\tconst stmtGetBlobIdByKey = db.stmt<Pick<Row, \"key\">, Pick<Row, \"blob_id\">>(\n\t\t\"SELECT blob_id FROM _mf_entries WHERE key = :key\"\n\t);\n\tconst stmtPut = db.stmt<Row>(\n\t\t`INSERT OR REPLACE INTO _mf_entries (key, blob_id, expiration, metadata)\n    VALUES (:key, :blob_id, :expiration, :metadata)`\n\t);\n\n\treturn {\n\t\tdb,\n\t\tgetByKey: db.prepare<[key_1: string], Row>(\n\t\t\t\"SELECT key, blob_id, expiration, metadata FROM _mf_entries WHERE key = ?1\"\n\t\t),\n\t\tput: db.txn((newEntry: Row) => {\n\t\t\t// TODO(perf): would be really nice if we didn't have to use a transaction\n\t\t\t//  here, need old blob ID for cleanup\n\t\t\tconst key = newEntry.key;\n\t\t\tconst previousEntry = get(stmtGetBlobIdByKey({ key }));\n\t\t\tstmtPut(newEntry);\n\t\t\treturn previousEntry?.blob_id;\n\t\t}),\n\t\tdeleteByKey: db.stmt<Pick<Row, \"key\">, Pick<Row, \"blob_id\" | \"expiration\">>(\n\t\t\t\"DELETE FROM _mf_entries WHERE key = :key RETURNING blob_id, expiration\"\n\t\t),\n\t\tdeleteExpired: db.stmt<{ now: number }, Pick<Row, \"blob_id\">>(\n\t\t\t// `expiration` may be `NULL`, but `NULL < ...` should be falsy\n\t\t\t\"DELETE FROM _mf_entries WHERE expiration < :now RETURNING blob_id\"\n\t\t),\n\t\tdeleteAll: db.prepare<[], Pick<Row, \"blob_id\">>(\n\t\t\t\"DELETE FROM _mf_entries RETURNING blob_id\"\n\t\t),\n\t\tlist: db.stmt<\n\t\t\t{\n\t\t\t\tnow: number;\n\t\t\t\tprefix: string;\n\t\t\t\tstart_after: string;\n\t\t\t\tlimit: number;\n\t\t\t},\n\t\t\tOmit<Row, \"blob_id\">\n\t\t>(\n\t\t\t`SELECT key, expiration, metadata FROM _mf_entries\n        WHERE substr(key, 1, length(:prefix)) = :prefix\n        AND key > :start_after\n        AND (expiration IS NULL OR expiration >= :now)\n        ORDER BY key LIMIT :limit`\n\t\t),\n\t};\n}\n\nfunction rowEntry<Metadata>(entry: Omit<Row, \"blob_id\">): KeyEntry<Metadata> {\n\treturn {\n\t\tkey: entry.key,\n\t\texpiration: entry.expiration ?? undefined,\n\t\tmetadata: entry.metadata === null ? undefined : JSON.parse(entry.metadata),\n\t};\n}\n\nexport type KeyValueRangesFactory<Metadata> = (\n\tmetadata: Metadata\n) => { ranges?: InclusiveRange[] } & MultipartOptions;\n\nexport class KeyValueStorage<Metadata = unknown> {\n\treadonly #stmts: ReturnType<typeof sqlStmts>;\n\treadonly #blob: BlobStore;\n\treadonly #timers: Timers;\n\n\tconstructor(object: MiniflareDurableObject) {\n\t\tobject.db.exec(\"PRAGMA case_sensitive_like = TRUE\");\n\t\tobject.db.exec(SQL_SCHEMA);\n\t\tthis.#stmts = sqlStmts(object.db);\n\t\tthis.#blob = object.blob;\n\t\tthis.#timers = object.timers;\n\t}\n\n\t#hasExpired(entry: Pick<Row, \"expiration\">) {\n\t\treturn entry.expiration !== null && entry.expiration <= this.#timers.now();\n\t}\n\n\t#backgroundDelete(blobId: string) {\n\t\t// Once rows are deleted, or if they failed to insert, we delete the\n\t\t// corresponding blobs in the background, ignoring errors. Blob IDs are\n\t\t// unguessable, so if there aren't any references to them, they can't be\n\t\t// accessed. This means if we fail to delete a blob for any reason, it\n\t\t// doesn't matter, we'll just have a dangling file taking up disk space.\n\t\tthis.#timers.queueMicrotask(() =>\n\t\t\tthis.#blob.delete(blobId).catch(() => {})\n\t\t);\n\t}\n\n\tget(key: string): Promise<KeyValueEntry<Metadata> | null>;\n\tget(\n\t\tkey: string,\n\t\toptsFactory?: KeyValueRangesFactory<Metadata>\n\t): Promise<KeyMultipartValueEntry<Metadata> | null>;\n\tasync get(\n\t\tkey: string,\n\t\toptsFactory?: KeyValueRangesFactory<Metadata>\n\t): Promise<\n\t\tKeyValueEntry<Metadata> | KeyMultipartValueEntry<Metadata> | null\n\t> {\n\t\t// Try to get key from metadata store, returning null if not found\n\t\tconst row = get(this.#stmts.getByKey(key));\n\t\tif (row === undefined) return null;\n\n\t\tif (this.#hasExpired(row)) {\n\t\t\t// If expired, delete from metadata and blob stores. Assuming a\n\t\t\t// monotonically increasing clock, this doesn't need to be in a\n\t\t\t// transaction with the above get. If we call `get()` again, the current\n\t\t\t// time will be >= now, so the entry will still be expired. Trying to\n\t\t\t// delete an already deleted row won't do anything, and we'll ignore the\n\t\t\t// blob not found error.\n\t\t\t// TODO(cleanup): once https://github.com/cloudflare/workerd/issues/959\n\t\t\t//  is fixed, should be able to remove `drain()`\n\t\t\tdrain(this.#stmts.deleteByKey({ key }));\n\t\t\t// Garbage collect expired blob\n\t\t\tthis.#backgroundDelete(row.blob_id);\n\t\t\treturn null;\n\t\t}\n\n\t\t// Return the blob as a stream\n\t\tconst entry = rowEntry<Metadata>(row);\n\t\tconst opts = entry.metadata && optsFactory?.(entry.metadata);\n\t\tif (opts?.ranges === undefined || opts.ranges.length <= 1) {\n\t\t\t// If no range was requested, or just a single one was, return a regular\n\t\t\t// stream\n\t\t\tconst value = await this.#blob.get(row.blob_id, opts?.ranges?.[0]);\n\t\t\tif (value === null) return null;\n\t\t\treturn { ...entry, value };\n\t\t} else {\n\t\t\t// Otherwise, if multiple ranges were requested, return a multipart stream\n\t\t\tconst value = await this.#blob.get(row.blob_id, opts.ranges, opts);\n\t\t\tif (value === null) return null;\n\t\t\treturn { ...entry, value };\n\t\t}\n\t}\n\n\tasync put(\n\t\tentry: KeyValueEntry<Awaitable<Metadata>> & { signal?: AbortSignal }\n\t): Promise<void> {\n\t\t// (NOTE: `Awaitable` allows metadata to be a `Promise`, this is used by\n\t\t// the `CacheObject` to include `size` in the metadata, which may only be\n\t\t// known once the stream is written to the blob store if no `Content-Length`\n\t\t// header was specified)\n\n\t\t// Empty keys are not permitted because we default to starting after \"\" when\n\t\t// listing. See `list()` for more details.\n\t\tassert(entry.key !== \"\");\n\n\t\t// Write the value to the blob store. Note we don't abort the put until\n\t\t// after it's fully completed. This ensures \"too large\" error messages that\n\t\t// measure the length of the stream using a `TransformStream` see the full\n\t\t// value, and can include the correct number of bytes in the message.\n\t\tconst blobId = await this.#blob.put(entry.value);\n\t\tif (entry.signal?.aborted) {\n\t\t\tthis.#backgroundDelete(blobId);\n\t\t\tentry.signal.throwIfAborted();\n\t\t}\n\n\t\t// Put new entry into metadata store, returning old entry's blob ID if any\n\t\tconst maybeOldBlobId = this.#stmts.put({\n\t\t\tkey: entry.key,\n\t\t\tblob_id: blobId,\n\t\t\texpiration: entry.expiration ?? null,\n\t\t\tmetadata:\n\t\t\t\tentry.metadata === undefined\n\t\t\t\t\t? null\n\t\t\t\t\t: JSON.stringify(await entry.metadata),\n\t\t});\n\t\t// Garbage collect previous entry's blob\n\t\tif (maybeOldBlobId !== undefined) this.#backgroundDelete(maybeOldBlobId);\n\t}\n\n\tasync delete(key: string): Promise<boolean> {\n\t\t// Try to delete key from metadata store, returning false if not found\n\t\tconst cursor = this.#stmts.deleteByKey({ key });\n\t\tconst row = get(cursor);\n\t\tif (row === undefined) return false;\n\t\t// Garbage collect deleted entry's blob\n\t\tthis.#backgroundDelete(row.blob_id);\n\t\t// Return true iff this entry hasn't expired\n\t\treturn !this.#hasExpired(row);\n\t}\n\n\tdeleteAll(): number {\n\t\t// Get all blob IDs and delete all entries in one statement\n\t\tconst rows = all(this.#stmts.deleteAll());\n\n\t\t// Garbage collect all blobs in the background\n\t\tfor (const { blob_id } of rows) {\n\t\t\tthis.#backgroundDelete(blob_id);\n\t\t}\n\n\t\treturn rows.length;\n\t}\n\n\tasync list(opts: KeyEntriesQuery): Promise<KeyEntries<Metadata>> {\n\t\t// Find non-expired entries matching query after cursor\n\t\tconst now = this.#timers.now();\n\t\tconst prefix = opts.prefix ?? \"\";\n\t\t// Note the \"\" default here prohibits empty string keys. The consumers\n\t\t// of this class are KV and Cache. KV validates keys are non-empty.\n\t\t// Cache keys are usually URLs, but can be customised with `cf.cacheKey`.\n\t\t// If this is empty, we can just not cache the response, since that\n\t\t// satisfies the Cache API contract.\n\t\tconst start_after =\n\t\t\topts.cursor === undefined ? \"\" : base64Decode(opts.cursor);\n\t\t// Increase the queried limit by 1, if we return this many results, we\n\t\t// know there are more rows. We'll truncate to the original limit before\n\t\t// returning results.\n\t\tconst limit = opts.limit + 1;\n\t\tconst rowsCursor = this.#stmts.list({\n\t\t\tnow,\n\t\t\tprefix,\n\t\t\tstart_after,\n\t\t\tlimit,\n\t\t});\n\t\tconst rows = Array.from(rowsCursor);\n\n\t\t// Garbage collect expired entries. As with `get()`, assuming a\n\t\t// monotonically increasing clock, this doesn't need to be in a transaction.\n\t\tconst expiredRows = this.#stmts.deleteExpired({ now });\n\t\tfor (const row of expiredRows) this.#backgroundDelete(row.blob_id);\n\n\t\t// If there are more results, we'll be returning a cursor\n\t\tconst hasMoreRows = rows.length === opts.limit + 1;\n\t\trows.splice(opts.limit, 1);\n\n\t\tconst keys = rows.map((row) => rowEntry<Metadata>(row));\n\n\t\t// The cursor encodes a key to start after rather than the key to start at\n\t\t// to ensure keys added between `list()` calls are returned.\n\t\tconst nextCursor = hasMoreRows\n\t\t\t? base64Encode(rows[opts.limit - 1].key)\n\t\t\t: undefined;\n\n\t\treturn { keys, cursor: nextCursor };\n\t}\n}\n", "import assert from \"node:assert\";\n\n// TODO(soon): we control these types, so we should fix them to make them nice\n\nexport type TypedValue = ArrayBuffer | string | number | null;\nexport type TypedResult = Record<string, TypedValue>;\n\nexport function isTypedValue(value: unknown): value is TypedValue {\n\treturn (\n\t\tvalue === null ||\n\t\ttypeof value === \"string\" ||\n\t\ttypeof value === \"number\" ||\n\t\tvalue instanceof ArrayBuffer\n\t);\n}\n\nexport interface TypedSqlStorage {\n\texec<R extends TypedResult = TypedResult>(\n\t\tquery: string,\n\t\t...bindings: TypedValue[]\n\t): TypedSqlStorageCursor<R>;\n\tprepare<\n\t\tP extends TypedValue[] = TypedValue[],\n\t\tR extends TypedResult = TypedResult,\n\t>(\n\t\tquery: string\n\t): TypedSqlStorageStatement<P, R>;\n}\nexport interface TypedSqlStorageCursor<R extends TypedResult = TypedResult> {\n\traw(): IterableIterator<R[keyof R][]>;\n\t[Symbol.iterator](): IterableIterator<R>;\n\treadonly columnNames: string[];\n\treadonly rowsRead: number;\n\treadonly rowsWritten: number;\n}\nexport interface TypedSqlStorageStatement<\n\tP extends TypedValue[] = TypedValue[],\n\tR extends TypedResult = TypedResult,\n> {\n\t(...bindings: P): TypedSqlStorageCursor<R>;\n}\n\nexport type StatementFactory = <\n\tP extends Record<string, TypedValue>,\n\tR extends TypedResult = TypedResult,\n>(\n\tquery: string\n) => (argsObject: P) => TypedSqlStorageCursor<R>;\nfunction createStatementFactory(sql: TypedSqlStorage): StatementFactory {\n\treturn <\n\t\tP extends Record<string, TypedValue>,\n\t\tR extends TypedResult = TypedResult,\n\t>(\n\t\tquery: string\n\t) => {\n\t\t// Replace named parameters (e.g. :key) with numerics (e.g. ?1)\n\t\tconst keyIndices = new Map<string, number>();\n\t\tquery = query.replace(/[:@$]([a-z0-9_]+)/gi, (_, name: string) => {\n\t\t\tlet index = keyIndices.get(name);\n\t\t\tif (index === undefined) {\n\t\t\t\tindex = keyIndices.size;\n\t\t\t\tkeyIndices.set(name, index);\n\t\t\t}\n\t\t\treturn `?${index + 1}`; // SQLite's parameters are 1-indexed\n\t\t});\n\t\tconst stmt = sql.prepare<TypedValue[], R>(query);\n\n\t\t// Return function taking arguments object\n\t\treturn (argsObject: P) => {\n\t\t\t// Convert arguments object to array\n\t\t\tconst entries = Object.entries(argsObject);\n\t\t\tassert.strictEqual(\n\t\t\t\tentries.length,\n\t\t\t\tkeyIndices.size,\n\t\t\t\t\"Expected same number of keys in bindings and query\"\n\t\t\t);\n\t\t\tconst argsArray = new Array<TypedValue>(entries.length);\n\t\t\tfor (const [key, value] of entries) {\n\t\t\t\tconst index = keyIndices.get(key);\n\t\t\t\tassert(index !== undefined, `Unexpected binding key: ${key}`);\n\t\t\t\targsArray[index] = value;\n\t\t\t}\n\n\t\t\treturn stmt(...argsArray);\n\t\t};\n\t};\n}\n\nexport type TransactionFactory = <P extends unknown[], R>(\n\tclosure: (...args: P) => R\n) => (...args: P) => R;\nfunction createTransactionFactory(\n\tstorage: DurableObjectStorage\n): TransactionFactory {\n\treturn <P extends unknown[], R>(closure: (...args: P) => R) =>\n\t\t(...args: P) =>\n\t\t\tstorage.transactionSync(() => closure(...args));\n}\n\nexport type TypedSql = TypedSqlStorage & {\n\tstmt: StatementFactory;\n\ttxn: TransactionFactory;\n};\nexport function createTypedSql(storage: DurableObjectStorage): TypedSql {\n\tconst sql = storage.sql as unknown as TypedSql;\n\tsql.stmt = createStatementFactory(sql);\n\tsql.txn = createTransactionFactory(storage);\n\treturn sql;\n}\n\nexport function get<R extends TypedResult>(\n\tcursor: TypedSqlStorageCursor<R>\n): R | undefined {\n\tlet result: R | undefined;\n\tfor (const row of cursor) result ??= row;\n\treturn result;\n}\n\nexport function all<R extends TypedResult>(\n\tcursor: TypedSqlStorageCursor<R>\n): R[] {\n\treturn Array.from(cursor);\n}\n\nexport function drain<R extends TypedResult>(cursor: TypedSqlStorageCursor<R>) {\n\tfor (const _ of cursor) {\n\t}\n}\n", "// Split conversion to RegExps and testing to allow RegExps to be serialised\n// into Workers Sites KV namespace script. This will apply filtering, before\n// passing back to Miniflare's loopback server for storage access.\nexport interface MatcherRegExps {\n\tinclude: RegExp[];\n\texclude: RegExp[];\n}\n\nexport function testRegExps(matcher: MatcherRegExps, value: string): boolean {\n\tfor (const exclude of matcher.exclude) if (exclude.test(value)) return false;\n\tfor (const include of matcher.include) if (include.test(value)) return true;\n\treturn false;\n}\n", "import assert from \"node:assert\";\nimport { BlobStore } from \"./blob.worker\";\nimport { SharedBindings, SharedHeaders } from \"./constants\";\nimport { Router } from \"./router.worker\";\nimport { all, createTypedSql, isTypedValue } from \"./sql.worker\";\nimport { Timers } from \"./timers.worker\";\nimport { reduceError } from \"./types\";\nimport type { LogLevel } from \"./constants\";\nimport type { TypedSql } from \"./sql.worker\";\n\nexport interface MiniflareDurableObjectEnv {\n\t// NOTE: \"in-memory\" storage is never in-memory. We always back simulator\n\t// Durable Objects with a disk directory service, so data is persisted between\n\t// `Miniflare#setOptions()` calls which restart the `workerd` instance. When\n\t// users disable persistence, we just set the persistence directory to a\n\t// temporary directory. This also simplifies the implementation, we can always\n\t// assume a `Fetcher`. This binding is optional so simulators that don't\n\t// persist data (e.g. Queues), don't need to provide it.\n\t[SharedBindings.MAYBE_SERVICE_BLOBS]?: Fetcher;\n\t// NOTE: this binding is optional so simulators can run standalone, without\n\t// a Node.js loopback server. In this case, logging is a no-op.\n\t[SharedBindings.MAYBE_SERVICE_LOOPBACK]?: Fetcher;\n\t// If set to `true`, Miniflare enables additional endpoints in Durable Objects\n\t// for testing. Note these endpoints allow anyone with access to the Miniflare\n\t// dev server to run arbitrary SQL queries and read arbitrary blobs.\n\t[SharedBindings.MAYBE_JSON_ENABLE_CONTROL_ENDPOINTS]?: boolean;\n\t// If set to `true`, Miniflare won't delete blobs when deleting/overriding\n\t// existing keys. This is a requirement for \"stacked storage\": when popping\n\t// from the storage stack, we need to guarantee the blobs created in and\n\t// before that storage stack frame still exist.\n\t[SharedBindings.MAYBE_JSON_ENABLE_STICKY_BLOBS]?: boolean;\n}\n\nexport interface MiniflareDurableObjectCfControlOp {\n\tname: string;\n\targs?: unknown[];\n}\n\nexport interface MiniflareDurableObjectCf {\n\tminiflare?: {\n\t\tname?: string;\n\t\tcontrolOp?: MiniflareDurableObjectCfControlOp;\n\t};\n}\n\nexport abstract class MiniflareDurableObject<\n\tEnv extends MiniflareDurableObjectEnv = MiniflareDurableObjectEnv,\n> extends Router {\n\treadonly timers = new Timers();\n\t// If this Durable Object receives a control op, assume it's being tested.\n\t// We use this to adjust some limits in tests.\n\tbeingTested = false;\n\n\tconstructor(\n\t\treadonly state: DurableObjectState,\n\t\treadonly env: Env\n\t) {\n\t\tsuper();\n\t}\n\n\t#db?: TypedSql;\n\tget db(): TypedSql {\n\t\treturn (this.#db ??= createTypedSql(this.state.storage));\n\t}\n\n\t#name?: string;\n\tget name(): string {\n\t\t// `name` should only be accessed in a `fetch` request, which will make sure\n\t\t// `#name` is initialised on first request\n\t\tassert(\n\t\t\tthis.#name !== undefined,\n\t\t\t\"Expected `MiniflareDurableObject#fetch()` call before `name` access\"\n\t\t);\n\t\treturn this.#name;\n\t}\n\n\t#blob?: BlobStore;\n\tget blob(): BlobStore {\n\t\tif (this.#blob !== undefined) return this.#blob;\n\t\tconst maybeBlobsService = this.env[SharedBindings.MAYBE_SERVICE_BLOBS];\n\t\tconst stickyBlobs =\n\t\t\t!!this.env[SharedBindings.MAYBE_JSON_ENABLE_STICKY_BLOBS];\n\t\tassert(\n\t\t\tmaybeBlobsService !== undefined,\n\t\t\t`Expected ${SharedBindings.MAYBE_SERVICE_BLOBS} service binding`\n\t\t);\n\t\tthis.#blob = new BlobStore(maybeBlobsService, this.name, stickyBlobs);\n\t\treturn this.#blob;\n\t}\n\n\tasync logWithLevel(level: LogLevel, message: string) {\n\t\tawait this.env[SharedBindings.MAYBE_SERVICE_LOOPBACK]?.fetch(\n\t\t\t\"http://localhost/core/log\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { [SharedHeaders.LOG_LEVEL]: level.toString() },\n\t\t\t\tbody: message,\n\t\t\t}\n\t\t);\n\t}\n\n\tasync #handleControlOp({\n\t\tname,\n\t\targs,\n\t}: MiniflareDurableObjectCfControlOp): Promise<Response> {\n\t\t// Tests send control ops to update fake time, and access internal storage.\n\t\tthis.beingTested = true;\n\t\tif (name === \"sqlQuery\") {\n\t\t\t// Run arbitrary SQL query (e.g. get blob ID for object)\n\t\t\tassert(args !== undefined);\n\t\t\tconst [query, ...params] = args;\n\t\t\tassert(typeof query === \"string\");\n\t\t\tassert(params.every(isTypedValue));\n\t\t\tconst results = all(this.db.prepare(query)(...params));\n\t\t\treturn Response.json(results);\n\t\t} else if (name === \"getBlob\") {\n\t\t\t// Get an arbitrary blob\n\t\t\tassert(args !== undefined);\n\t\t\tconst [id] = args;\n\t\t\tassert(typeof id === \"string\");\n\t\t\tconst stream = await this.blob.get(id);\n\t\t\treturn new Response(stream, { status: stream === null ? 404 : 200 });\n\t\t} else {\n\t\t\t// Enable/disable fake timers, advance time, or wait for tasks\n\t\t\tconst func: unknown = this.timers[name as keyof Timers];\n\t\t\tassert(typeof func === \"function\");\n\t\t\tconst result = await func.apply(this.timers, args);\n\t\t\treturn Response.json(result ?? null);\n\t\t}\n\t}\n\n\tasync fetch(req: Request<unknown, MiniflareDurableObjectCf>) {\n\t\t// Allow control of object internals by specifying operations in the `cf`\n\t\t// object. Used by tests to update fake time, and access internal storage.\n\t\tif (this.env[SharedBindings.MAYBE_JSON_ENABLE_CONTROL_ENDPOINTS] === true) {\n\t\t\tconst controlOp = req?.cf?.miniflare?.controlOp;\n\t\t\tif (controlOp !== undefined) return this.#handleControlOp(controlOp);\n\t\t}\n\n\t\t// Each regular request to a `MiniflareDurableObject` includes the object\n\t\t// ID's name, so we can create the `BlobStore`. Note, we could just use the\n\t\t// object's ID to namespace the blob store, but we previously did this by\n\t\t// name, so we do this to avoid a breaking change to persistence format.\n\t\tconst name = req.cf?.miniflare?.name;\n\t\tassert(name !== undefined, \"Expected `cf.miniflare.name`\");\n\t\tthis.#name = name;\n\n\t\t// Dispatch the request to the underlying router\n\t\ttry {\n\t\t\treturn await super.fetch(req);\n\t\t} catch (e) {\n\t\t\t// `HttpError`s are handled by `Router`. If we threw another error log it.\n\t\t\tconst error = reduceError(e);\n\t\t\tconst fallback = error.stack ?? error.message;\n\n\t\t\tconst loopbackService = this.env[SharedBindings.MAYBE_SERVICE_LOOPBACK];\n\t\t\tif (loopbackService !== undefined) {\n\t\t\t\t// If we have a connected loopback service, log a source mapped error\n\t\t\t\tvoid loopbackService\n\t\t\t\t\t.fetch(\"http://localhost/core/error\", {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\tbody: JSON.stringify(error),\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t// ...falling back to `workerd` logging (requires `--verbose` flag)\n\t\t\t\t\t\tconsole.error(fallback);\n\t\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Otherwise, just use `workerd`'s logging (requires `--verbose` flag)\n\t\t\t\tconsole.error(fallback);\n\t\t\t}\n\n\t\t\treturn new Response(fallback, { status: 500 });\n\t\t} finally {\n\t\t\t// Make sure we consume the request body if specified. Otherwise, calls\n\t\t\t// which make requests to this object may hang and never resolve.\n\t\t\t// See https://github.com/cloudflare/workerd/issues/960.\n\t\t\tif (req.body !== null && !req.bodyUsed) {\n\t\t\t\tawait req.body.pipeTo(new WritableStream());\n\t\t\t}\n\t\t}\n\t}\n}\n", "import type { Awaitable } from \"./types\";\n\nexport class HttpError extends Error {\n\tconstructor(\n\t\treadonly code: number,\n\t\tmessage?: string\n\t) {\n\t\tsuper(message);\n\t\t// Restore prototype chain:\n\t\t// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget\n\t\tObject.setPrototypeOf(this, new.target.prototype);\n\t\tthis.name = `${new.target.name} [${code}]`;\n\t}\n\n\ttoResponse(): Response {\n\t\treturn new Response(this.message, {\n\t\t\tstatus: this.code,\n\t\t\t// Custom statusMessage is required for runtime error messages\n\t\t\tstatusText: this.message.substring(0, 512),\n\t\t});\n\t}\n}\n\ntype MethodRouteMap = Map<string, (readonly [RegExp, PropertyKey])[]>;\n\nconst kRoutesTemplate = Symbol(\"kRoutesTemplate\");\n\nexport abstract class Router {\n\t// Routes added by @METHOD decorators\n\t#routes?: MethodRouteMap;\n\n\tconstructor() {\n\t\t// Initialise `#routes` from subclass's prototype\n\t\tthis.#routes = (new.target.prototype as RouterPrototype)[kRoutesTemplate];\n\t}\n\n\tasync fetch(req: Request<unknown, unknown>) {\n\t\tconst url = new URL(req.url);\n\t\tconst methodRoutes = this.#routes?.get(req.method);\n\t\tif (methodRoutes === undefined) return new Response(null, { status: 405 });\n\t\tconst handlers = this as unknown as Record<PropertyKey, RouteHandler>;\n\t\ttry {\n\t\t\tfor (const [path, key] of methodRoutes) {\n\t\t\t\tconst match = path.exec(url.pathname);\n\t\t\t\tif (match !== null) return await handlers[key](req, match.groups, url);\n\t\t\t}\n\t\t\treturn new Response(null, { status: 404 });\n\t\t} catch (e) {\n\t\t\tif (e instanceof HttpError) {\n\t\t\t\treturn e.toResponse();\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t}\n}\n\n// Prototype of a `Router` subclass, @METHOD decorators will add routes to this\nexport type RouterPrototype = typeof Router.prototype & {\n\t[kRoutesTemplate]?: MethodRouteMap;\n};\n\nexport type RouteHandler<Params = unknown, Cf = unknown> = (\n\treq: Request<unknown, Cf>,\n\tparams: Params,\n\turl: URL\n) => Awaitable<Response>;\n\nfunction pathToRegexp(path?: string): RegExp {\n\tif (path === undefined) return /^.*$/;\n\t// Optionally allow trailing slashes\n\tif (!path.endsWith(\"/\")) path += \"/?\";\n\t// Escape forward slashes\n\tpath = path.replace(/\\//g, \"\\\\/\");\n\t// Replace `:key` with named capture groups\n\tpath = path.replace(/:(\\w+)/g, \"(?<$1>[^\\\\/]+)\");\n\t// Return RegExp, asserting start and end of line\n\treturn new RegExp(`^${path}$`);\n}\n\nconst createRouteDecorator =\n\t(method: string) =>\n\t(path?: string) =>\n\t(prototype: RouterPrototype, key: PropertyKey) => {\n\t\tconst route = [pathToRegexp(path), key] as const;\n\t\tconst routes = (prototype[kRoutesTemplate] ??= new Map());\n\t\tconst methodRoutes = routes.get(method);\n\t\tif (methodRoutes) methodRoutes.push(route);\n\t\telse routes.set(method, [route]);\n\t};\n\nexport const GET = createRouteDecorator(\"GET\");\nexport const HEAD = createRouteDecorator(\"HEAD\");\nexport const POST = createRouteDecorator(\"POST\");\nexport const PUT = createRouteDecorator(\"PUT\");\nexport const DELETE = createRouteDecorator(\"DELETE\");\nexport const PURGE = createRouteDecorator(\"PURGE\");\nexport const PATCH = createRouteDecorator(\"PATCH\");\n", "import assert from \"node:assert\";\nimport type { Awaitable } from \"./types\";\n\nconst kFakeTimerHandle = Symbol(\"kFakeTimerHandle\");\nexport type TimerHandle = number | { [kFakeTimerHandle]: number };\n\ninterface FakeTimeout {\n\ttriggerTimestamp: number;\n\tclosure: () => Awaitable<unknown>;\n}\n\nexport class Timers {\n\t// Fake unix time in milliseconds. If defined, fake timers will be enabled.\n\t#fakeTimestamp?: number;\n\n\t#fakeNextTimerHandle = 0;\n\t#fakePendingTimeouts = new Map<number, FakeTimeout>();\n\t#fakeRunningTasks = new Set<Promise<unknown>>();\n\n\t// Timers API\n\n\tnow = () => this.#fakeTimestamp ?? Date.now();\n\n\tsetTimeout<Args extends any[]>(\n\t\tclosure: (...args: Args) => Awaitable<unknown>,\n\t\tdelay: number,\n\t\t...args: Args\n\t): TimerHandle {\n\t\tif (this.#fakeTimestamp === undefined) {\n\t\t\treturn setTimeout(closure, delay, ...args) as unknown as TimerHandle;\n\t\t}\n\n\t\tconst handle = this.#fakeNextTimerHandle++;\n\t\tconst argsClosure = () => closure(...args);\n\t\tif (delay === 0) {\n\t\t\tthis.queueMicrotask(argsClosure);\n\t\t} else {\n\t\t\tconst timeout: FakeTimeout = {\n\t\t\t\ttriggerTimestamp: this.#fakeTimestamp + delay,\n\t\t\t\tclosure: argsClosure,\n\t\t\t};\n\t\t\tthis.#fakePendingTimeouts.set(handle, timeout);\n\t\t}\n\t\treturn { [kFakeTimerHandle]: handle };\n\t}\n\n\tclearTimeout(handle: TimerHandle): void {\n\t\tif (typeof handle === \"number\") return clearTimeout(handle);\n\t\telse this.#fakePendingTimeouts.delete(handle[kFakeTimerHandle]);\n\t}\n\n\tqueueMicrotask(closure: () => Awaitable<unknown>): void {\n\t\tif (this.#fakeTimestamp === undefined) return queueMicrotask(closure);\n\n\t\tconst result = closure();\n\t\tif (result instanceof Promise) {\n\t\t\tthis.#fakeRunningTasks.add(result);\n\t\t\tresult.finally(() => this.#fakeRunningTasks.delete(result));\n\t\t}\n\t}\n\n\t// Fake Timers Control API\n\n\t#runPendingTimeouts() {\n\t\tif (this.#fakeTimestamp === undefined) return;\n\t\tfor (const [handle, timeout] of this.#fakePendingTimeouts) {\n\t\t\tif (timeout.triggerTimestamp <= this.#fakeTimestamp) {\n\t\t\t\tthis.#fakePendingTimeouts.delete(handle);\n\t\t\t\tthis.queueMicrotask(timeout.closure);\n\t\t\t}\n\t\t}\n\t}\n\n\tenableFakeTimers(timestamp: number) {\n\t\tthis.#fakeTimestamp = timestamp;\n\t\tthis.#runPendingTimeouts();\n\t}\n\tdisableFakeTimers() {\n\t\tthis.#fakeTimestamp = undefined;\n\t\tthis.#fakePendingTimeouts.clear();\n\t}\n\tadvanceFakeTime(delta: number) {\n\t\tassert(\n\t\t\tthis.#fakeTimestamp !== undefined,\n\t\t\t\"Expected fake timers to be enabled before `advanceFakeTime()` call\"\n\t\t);\n\t\tthis.#fakeTimestamp += delta;\n\t\tthis.#runPendingTimeouts();\n\t}\n\n\tasync waitForFakeTasks() {\n\t\twhile (this.#fakeRunningTasks.size > 0) {\n\t\t\tawait Promise.all(this.#fakeRunningTasks);\n\t\t}\n\t}\n}\n", "export type Awaitable<T> = T | Promise<T>;\n\n// { a: A, b: B, ... } => A | B | ...\nexport type ValueOf<T> = T[keyof T];\n\nexport interface JsonError {\n\tmessage?: string;\n\tname?: string;\n\tstack?: string;\n\tcause?: JsonError;\n}\n\nexport function reduceError(e: any): JsonError {\n\treturn {\n\t\tname: e?.name,\n\t\tmessage: e?.message ?? String(e),\n\t\tstack: e?.stack,\n\t\tcause: e?.cause === undefined ? undefined : reduceError(e.cause),\n\t};\n}\n\nexport function maybeApply<From, To>(\n\tf: (value: From) => To,\n\tmaybeValue: From | undefined\n): To | undefined {\n\treturn maybeValue === undefined ? undefined : f(maybeValue);\n}\n", "// Fetches the public URL from the Miniflare loopback. This returns\n// the publicUrl if one was set (e.g. Vite dev server URL), otherwise\n// falls back to the runtime entry URL. Using the loopback means the\n// binding always sees the latest value \u2014 even if the URL was\n// updated after workerd started (e.g. when Vite bumps the port).\nexport async function getPublicUrl(loopback: Fetcher): Promise<URL> {\n\tconst resp = await loopback.fetch(\"http://localhost/core/public-url\");\n\tconst url = (await resp.json()) as string | null;\n\tif (!url) {\n\t\tthrow new Error(\n\t\t\t\"Runtime entry URL is not available. This may be because the worker is not yet ready to accept requests.\"\n\t\t);\n\t}\n\treturn new URL(url);\n}\n", "export interface InclusiveRange {\n\tstart: number; // inclusive\n\tend: number; // inclusive\n}\n\n// Matches case-insensitive string \"bytes\", ignoring surrounding whitespace,\n// followed by \"=\" (example matches: \"bytes=...\", \"ByTeS=...\", \"   bytes  =...\")\nconst rangePrefixRegexp = /^ *bytes *=/i;\n\n// Matches single range, with optional start/end numbers, ignoring whitespace\n// (example matches: \"1-2\", \"1-\", \"2-\", \"  1   -    2   \", \"  -  \" [note this\n// last case is invalid and will be handled separately in `_parseRanges`])\nconst rangeRegexp = /^ *(?<start>\\d+)? *- *(?<end>\\d+)? *$/;\ninterface RangeRegexpGroups {\n\tstart?: string;\n\tend?: string;\n}\n\n/**\n * Parses an HTTP `Range` header (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range),\n * returning either:\n * - `undefined` indicating the range is unsatisfiable\n * - An empty array indicating the entire response should be returned\n * - A non-empty array of inclusive ranges of the response to return\n */\nexport function parseRanges(\n\trangeHeader: string,\n\tlength: number\n): InclusiveRange[] | undefined {\n\t// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range\n\n\t// Make sure unit is \"bytes\"\n\tconst prefixMatch = rangePrefixRegexp.exec(rangeHeader);\n\tif (prefixMatch === null) return; // Invalid unit (Range Not Satisfiable)\n\n\t// Accept empty range header\n\trangeHeader = rangeHeader.substring(prefixMatch[0].length);\n\tif (rangeHeader.trimStart() === \"\") return [];\n\n\t// Split ranges after prefix by \",\"\n\tconst ranges = rangeHeader.split(\",\");\n\tconst result: InclusiveRange[] = [];\n\tfor (const range of ranges) {\n\t\tconst match = rangeRegexp.exec(range);\n\t\tif (match === null) return; // Invalid range format (Range Not Satisfiable)\n\t\tconst { start, end } = match.groups as RangeRegexpGroups;\n\t\tif (start !== undefined && end !== undefined) {\n\t\t\tconst rangeStart = parseInt(start);\n\t\t\tlet rangeEnd = parseInt(end);\n\t\t\tif (rangeStart > rangeEnd) return; // Start after end (Range Not Satisfiable)\n\t\t\tif (rangeStart >= length) return; // Start after content (Range Not Satisfiable)\n\t\t\tif (rangeEnd >= length) rangeEnd = length - 1;\n\t\t\tresult.push({ start: rangeStart, end: rangeEnd });\n\t\t} else if (start !== undefined && end === undefined) {\n\t\t\tconst rangeStart = parseInt(start);\n\t\t\tif (rangeStart >= length) return; // Start after content (Range Not Satisfiable)\n\t\t\tresult.push({ start: rangeStart, end: length - 1 });\n\t\t} else if (start === undefined && end !== undefined) {\n\t\t\tconst suffix = parseInt(end);\n\t\t\tif (suffix >= length) return []; // Entire Response\n\t\t\tif (suffix === 0) continue; // Empty range\n\t\t\tresult.push({ start: length - suffix, end: length - 1 });\n\t\t} else {\n\t\t\treturn; // Invalid range format, missing both start & end (Range Not Satisfiable)\n\t\t}\n\t}\n\treturn result;\n}\n", "import assert from \"node:assert\";\nimport type { Awaitable } from \"./types\";\n\nexport type DeferredPromiseResolve<T> = (value: T | PromiseLike<T>) => void;\nexport type DeferredPromiseReject = (reason?: any) => void;\n\nexport class DeferredPromise<T> extends Promise<T> {\n\treadonly resolve: DeferredPromiseResolve<T>;\n\treadonly reject: DeferredPromiseReject;\n\n\tconstructor(\n\t\texecutor: (\n\t\t\tresolve: (value: T | PromiseLike<T>) => void,\n\t\t\treject: (reason?: any) => void\n\t\t) => void = () => {}\n\t) {\n\t\tlet promiseResolve: DeferredPromiseResolve<T> | undefined = undefined;\n\t\tlet promiseReject: DeferredPromiseReject | undefined = undefined;\n\t\tsuper((resolve, reject) => {\n\t\t\tpromiseResolve = resolve;\n\t\t\tpromiseReject = reject;\n\t\t\treturn executor(resolve, reject);\n\t\t});\n\t\t// Note: `promiseResolve` and `promiseReject` should be defined\n\t\t//        since `super()` is executed immediately\n\t\tassert(promiseResolve);\n\t\tassert(promiseReject);\n\t\t// Note: Cannot access `this` until after `super`\n\t\tthis.resolve = promiseResolve;\n\t\tthis.reject = promiseReject;\n\t}\n}\n\nexport class Mutex {\n\tprivate locked = false;\n\tprivate resolveQueue: (() => void)[] = [];\n\tprivate drainQueue: (() => void)[] = [];\n\n\tprivate lock(): Awaitable<void> {\n\t\tif (!this.locked) {\n\t\t\tthis.locked = true;\n\t\t\treturn;\n\t\t}\n\t\treturn new Promise((resolve) => this.resolveQueue.push(resolve));\n\t}\n\n\tprivate unlock(): void {\n\t\tassert(this.locked);\n\t\tif (this.resolveQueue.length > 0) {\n\t\t\tthis.resolveQueue.shift()?.();\n\t\t} else {\n\t\t\tthis.locked = false;\n\t\t\tlet resolve: (() => void) | undefined;\n\t\t\twhile ((resolve = this.drainQueue.shift()) !== undefined) resolve();\n\t\t}\n\t}\n\n\tget hasWaiting(): boolean {\n\t\treturn this.resolveQueue.length > 0;\n\t}\n\n\tasync runWith<T>(closure: () => Awaitable<T>): Promise<T> {\n\t\tconst acquireAwaitable = this.lock();\n\t\tif (acquireAwaitable instanceof Promise) await acquireAwaitable;\n\t\ttry {\n\t\t\tconst awaitable = closure();\n\t\t\tif (awaitable instanceof Promise) return await awaitable;\n\t\t\treturn awaitable;\n\t\t} finally {\n\t\t\tthis.unlock();\n\t\t}\n\t}\n\n\tasync drained(): Promise<void> {\n\t\tif (this.resolveQueue.length === 0 && !this.locked) return;\n\t\treturn new Promise((resolve) => this.drainQueue.push(resolve));\n\t}\n}\n\nexport class WaitGroup {\n\tprivate counter = 0;\n\tprivate resolveQueue: (() => void)[] = [];\n\n\tadd(): void {\n\t\tthis.counter++;\n\t}\n\n\tdone(): void {\n\t\tassert(this.counter > 0);\n\t\tthis.counter--;\n\t\tif (this.counter === 0) {\n\t\t\tlet resolve: (() => void) | undefined;\n\t\t\twhile ((resolve = this.resolveQueue.shift()) !== undefined) resolve();\n\t\t}\n\t}\n\n\twait(): Promise<void> {\n\t\tif (this.counter === 0) return Promise.resolve();\n\t\treturn new Promise((resolve) => this.resolveQueue.push(resolve));\n\t}\n}\n"],
  "mappings": "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",
  "names": ["Buffer", "writer", "Buffer", "LogLevel", "assert", "assert", "assert", "assert", "assert", "assert", "assert"]
}
