@adonix.org/cloud-spark 2.0.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cache.d.ts +58 -0
- package/dist/cache.js +2 -2
- package/dist/cache.js.map +1 -1
- package/dist/cors.d.ts +106 -0
- package/dist/cors.js +1 -1
- package/dist/cors.js.map +1 -1
- package/dist/index.d.ts +11 -504
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware-CfKw8AlN.d.ts +106 -0
- package/dist/sessions.d.ts +207 -0
- package/dist/websocket.d.ts +29 -0
- package/dist/websocket.js +1 -1
- package/dist/websocket.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants/cache.ts","../src/constants/methods.ts","../src/constants/time.ts","../src/constants/headers.ts","../src/guards/basic.ts","../src/guards/methods.ts","../src/constants/media.ts","../src/guards/responses.ts","../src/utils/compare.ts","../src/utils/headers.ts","../src/utils/media.ts","../src/responses.ts","../src/errors.ts","../src/guards/middleware.ts","../src/workers/base.ts","../src/workers/middleware.ts","../src/workers/basic.ts","../src/routes.ts","../src/workers/route.ts"],"names":["CacheControl","CacheLib","Method","GET","PUT","HEAD","POST","PATCH","DELETE","OPTIONS","Time","HttpHeader","FORBIDDEN_304_HEADERS","FORBIDDEN_204_HEADERS","isString","value","isNumber","METHOD_SET","isMethod","isMethodArray","assertMethods","desc","UTF8_CHARSET","assertOctetStreamInit","obj","size","offset","length","lexCompare","a","b","setHeader","headers","key","raw","values","v","mergeHeader","merged","getHeaderValues","filterHeaders","keys","withCharset","mediaType","charset","BaseResponse","StatusCodes","getReasonPhrase","CacheResponse","cache","WorkerResponse","body","CopyResponse","response","NotModified","SuccessResponse","status","JsonResponse","json","HtmlResponse","TextResponse","OctetStream","_OctetStream","stream","init","normalized","R2ObjectStream","_R2ObjectStream","source","useCache","range","WebSocketUpgrade","client","Head","get","Options","worker","allowed","HttpError","details","LoggedHttpError","error","uuid","BadRequest","Unauthorized","Forbidden","NotFound","MethodNotAllowed","methods","PreconditionFailed","UpgradeRequired","InternalServerError","NotImplemented","MethodNotImplemented","ServiceUnavailable","assertMiddleware","BaseWorker","_request","_env","_ctx","method","request","ctor","ResponseClass","args","env","ctx","MiddlewareWorker","middleware","next","handler","BasicWorker","Routes","routes","path","matcher","match","url","pathname","route","found","RouteWorker","_RouteWorker"],"mappings":"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","file":"index.js","sourcesContent":["/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport CacheLib from \"cache-control-parser\";\n\n/**\n * @see {@link https://github.com/etienne-martin/cache-control-parser | cache-control-parser}\n */\nexport type CacheControl = CacheLib.CacheControl;\nexport const CacheControl = {\n parse: CacheLib.parse,\n stringify: CacheLib.stringify,\n\n /** A CacheControl directive that disables all caching. */\n DISABLE: Object.freeze({\n \"no-cache\": true,\n \"no-store\": true,\n \"must-revalidate\": true,\n \"max-age\": 0,\n }) satisfies CacheControl,\n};\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Standard HTTP request methods.\n */\nexport enum Method {\n GET = \"GET\",\n PUT = \"PUT\",\n HEAD = \"HEAD\",\n POST = \"POST\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n OPTIONS = \"OPTIONS\",\n}\n\n/**\n * Shorthand constants for each HTTP method.\n *\n * These are equivalent to the corresponding enum members in `Method`.\n * For example, `GET === Method.GET`.\n */\nexport const { GET, PUT, HEAD, POST, PATCH, DELETE, OPTIONS } = Method;\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Time constants in seconds. Month is approximated as 30 days.\n */\nexport const Time = {\n Second: 1,\n Minute: 60,\n Hour: 3600, // 60 * 60\n Day: 86400, // 60 * 60 * 24\n Week: 604800, // 60 * 60 * 24 * 7\n Month: 2592000, // 60 * 60 * 24 * 30\n Year: 31536000, // 60 * 60 * 24 * 365\n} as const;\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internally used headers.\n */\nexport const HttpHeader = {\n ACCEPT: \"accept\",\n ACCEPT_ENCODING: \"accept-encoding\",\n ACCEPT_LANGUAGE: \"accept-language\",\n ACCEPT_RANGES: \"accept-ranges\",\n ALLOW: \"allow\",\n AUTHORIZATION: \"authorization\",\n CACHE_CONTROL: \"cache-control\",\n CONNECTION: \"connection\",\n CONTENT_DISPOSITION: \"content-disposition\",\n CONTENT_ENCODING: \"content-encoding\",\n CONTENT_LANGUAGE: \"content-language\",\n CONTENT_LENGTH: \"content-length\",\n CONTENT_RANGE: \"content-range\",\n CONTENT_TYPE: \"content-type\",\n CONTENT_MD5: \"content-md5\",\n COOKIE: \"cookie\",\n ETAG: \"etag\",\n IF_MATCH: \"if-match\",\n IF_MODIFIED_SINCE: \"if-modified-since\",\n IF_NONE_MATCH: \"if-none-match\",\n IF_UNMODIFIED_SINCE: \"if-unmodified-since\",\n LAST_MODIFIED: \"last-modified\",\n ORIGIN: \"origin\",\n RANGE: \"range\",\n SET_COOKIE: \"set-cookie\",\n VARY: \"vary\",\n\n // Cors Headers\n ACCESS_CONTROL_ALLOW_CREDENTIALS: \"access-control-allow-credentials\",\n ACCESS_CONTROL_ALLOW_HEADERS: \"access-control-allow-headers\",\n ACCESS_CONTROL_ALLOW_METHODS: \"access-control-allow-methods\",\n ACCESS_CONTROL_ALLOW_ORIGIN: \"access-control-allow-origin\",\n ACCESS_CONTROL_EXPOSE_HEADERS: \"access-control-expose-headers\",\n ACCESS_CONTROL_MAX_AGE: \"access-control-max-age\",\n\n // Websocket Headers\n SEC_WEBSOCKET_VERSION: \"sec-websocket-version\",\n UPGRADE: \"upgrade\",\n\n // Internal Headers\n INTERNAL_VARIANT_SET: \"internal-variant-set\",\n} as const;\n\n/**\n * Headers that must not be sent in 304 Not Modified responses.\n * These are stripped to comply with the HTTP spec.\n */\nexport const FORBIDDEN_304_HEADERS = [\n HttpHeader.CONTENT_TYPE,\n HttpHeader.CONTENT_LENGTH,\n HttpHeader.CONTENT_RANGE,\n HttpHeader.CONTENT_ENCODING,\n HttpHeader.CONTENT_LANGUAGE,\n HttpHeader.CONTENT_DISPOSITION,\n HttpHeader.CONTENT_MD5,\n];\n\n/**\n * Headers that should not be sent in 204 No Content responses.\n * Stripping them is recommended but optional per spec.\n */\nexport const FORBIDDEN_204_HEADERS = [HttpHeader.CONTENT_LENGTH, HttpHeader.CONTENT_RANGE];\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Checks if the provided value is an array of strings.\n *\n * @param value - The value to check.\n * @returns True if `array` is an array where every item is a string.\n */\nexport function isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\n/**\n * Checks if a value is a string.\n *\n * @param value - The value to check.\n * @returns `true` if the value is a string, otherwise `false`.\n */\nexport function isString(value: unknown): value is string {\n return typeof value === \"string\";\n}\n\n\n/**\n * Checks if a value is a valid number (not NaN).\n *\n * This function returns `true` if the value is of type `number`\n * and is not `NaN`. It works as a type guard for TypeScript.\n *\n * @param value - The value to check.\n * @returns `true` if the value is a number and not `NaN`, otherwise `false`.\n */\nexport function isNumber(value: unknown): value is number {\n return typeof value === \"number\" && !Number.isNaN(value);\n}\n\n/**\n * Checks if a value is a boolean.\n *\n * @param value - The value to check.\n * @returns `true` if the value is a boolean (`true` or `false`), otherwise `false`.\n */\nexport function isBoolean(value: unknown): value is boolean {\n return typeof value === \"boolean\";\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Method } from \"../constants/methods\";\n\nimport { isString } from \"./basic\";\n\n/**\n * A set containing all supported HTTP methods.\n *\n * Useful for runtime checks like validating request methods.\n */\nconst METHOD_SET: Set<string> = new Set(Object.values(Method));\n\n/**\n * Type guard that checks if a string is a valid HTTP method.\n *\n * @param value - The string to test.\n * @returns True if `value` is a recognized HTTP method.\n */\nexport function isMethod(value: unknown): value is Method {\n return isString(value) && METHOD_SET.has(value);\n}\n\n/**\n * Checks if a value is an array of valid HTTP methods.\n *\n * Each element is verified using the `isMethod` type guard.\n *\n * @param value - The value to check.\n * @returns `true` if `value` is an array and every element is a valid `Method`, otherwise `false`.\n */\nexport function isMethodArray(value: unknown): value is Method[] {\n return Array.isArray(value) && value.every(isMethod);\n}\n\n/**\n * Asserts that a value is an array of valid HTTP methods.\n *\n * This function uses {@link isMethodArray} to validate the input. If the\n * value is not an array of `Method` elements, it throws a `TypeError`.\n * Otherwise, TypeScript will narrow the type of `value` to `Method[]`\n * within the calling scope.\n *\n * @param value - The value to check.\n * @throws TypeError If `value` is not a valid {@link Method} array.\n */\nexport function assertMethods(value: unknown): asserts value is Method[] {\n if (!isMethodArray(value)) {\n const desc = Array.isArray(value) ? JSON.stringify(value) : String(value);\n throw new TypeError(`Invalid method array: ${desc}`);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const UTF8_CHARSET = \"utf-8\";\n\n/**\n * Internal media types.\n */\nexport enum MediaType {\n PLAIN_TEXT = \"text/plain\",\n HTML = \"text/html\",\n JSON = \"application/json\",\n OCTET_STREAM = \"application/octet-stream\",\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { OctetStreamInit } from \"../interfaces\";\n\nimport { isNumber } from \"./basic\";\n\n/**\n * Asserts that a given value is a valid `OctetStreamInit` object.\n *\n * Properties:\n * - `size` (required): must be a non-negative number.\n * - `offset` (optional): if provided, must be a number between 0 and `size`.\n * - `length` (optional): if provided, must be a non-negative number such that `offset + length <= size`.\n *\n * If `offset` or `length` are `undefined`, they are considered as `0` and `size` respectively.\n *\n * Throws an error if validation fails.\n *\n * Acts as a TypeScript type predicate, so after calling it, `value` is narrowed to `OctetStreamInit`.\n *\n * @param value - The value to validate as `OctetStreamInit`.\n * @throws TypeError If the value is not a non-null object.\n * @throws RangeError If `size`, `offset`, or `length` are invalid.\n */\nexport function assertOctetStreamInit(value: unknown): asserts value is OctetStreamInit {\n if (typeof value !== \"object\" || value === null) {\n throw new TypeError(\"OctetStreamInit must be an object.\");\n }\n\n const obj = value as Record<string, unknown>;\n\n // size\n const size = obj[\"size\"];\n if (!isNumber(size) || size < 0 || !Number.isInteger(size)) {\n throw new RangeError(\n `OctetStreamInit.size must be a non-negative integer (size=${JSON.stringify(size)}).`,\n );\n }\n\n // offset\n const offset = obj[\"offset\"] ?? 0;\n if (!isNumber(offset) || offset < 0 || offset > size || !Number.isInteger(offset)) {\n throw new RangeError(\n `OctetStreamInit.offset must be a non-negative integer less than or equal to size (size=${JSON.stringify(size)}, offset=${JSON.stringify(offset)}).`,\n );\n }\n\n // length\n const length = obj[\"length\"] ?? size - offset;\n if (!isNumber(length) || length < 0 || offset + length > size || !Number.isInteger(length)) {\n throw new RangeError(\n `OctetStreamInit.length must be a non-negative integer less than or equal to size - offset (size=${JSON.stringify(size)}, offset=${JSON.stringify(offset)}, length=${JSON.stringify(length)}).`,\n );\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Lexicographically compares two strings.\n *\n * This comparator can be used in `Array.prototype.sort()` to produce a\n * consistent, stable ordering of string arrays.\n *\n * @param a - The first string to compare.\n * @param b - The second string to compare.\n * @returns A number indicating the relative order of `a` and `b`.\n */\nexport function lexCompare(a: string, b: string): number {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { lexCompare } from \"./compare\";\n\n/**\n * Sets a header on the given Headers object.\n *\n * - If `value` is an array, any duplicates and empty strings are removed.\n * - If the resulting value is empty, the header is deleted.\n * - Otherwise, values are joined with `\", \"` and set as the header value.\n *\n * @param headers - The Headers object to modify.\n * @param key - The header name to set.\n * @param value - The header value(s) to set. Can be a string or array of strings.\n */\nexport function setHeader(headers: Headers, key: string, value: string | string[]): void {\n const raw = Array.isArray(value) ? value : [value];\n const values = Array.from(new Set(raw.map((v) => v.trim())))\n .filter((v) => v.length)\n .sort(lexCompare);\n\n if (!values.length) {\n headers.delete(key);\n return;\n }\n\n headers.set(key, values.join(\", \"));\n}\n\n/**\n * Merges new value(s) into an existing header on the given Headers object.\n *\n * - Preserves any existing values and adds new ones.\n * - Removes duplicates and trims all values.\n * - If the header does not exist, it is created.\n * - If the resulting value array is empty, the header is deleted.\n *\n * @param headers - The Headers object to modify.\n * @param key - The header name to merge into.\n * @param value - The new header value(s) to add. Can be a string or array of strings.\n */\nexport function mergeHeader(headers: Headers, key: string, value: string | string[]): void {\n const values = Array.isArray(value) ? value : [value];\n if (values.length === 0) return;\n\n const existing = getHeaderValues(headers, key);\n const merged = existing.concat(values.map((v) => v.trim()));\n\n setHeader(headers, key, merged);\n}\n\n/**\n * Returns the values of an HTTP header as an array of strings.\n *\n * This helper:\n * - Retrieves the header value by `key`.\n * - Splits the value on commas.\n * - Trims surrounding whitespace from each entry.\n * - Filters out any empty tokens.\n * - Removes duplicate values (case-sensitive)\n *\n * If the header is not present, an empty array is returned.\n *\n */\nexport function getHeaderValues(headers: Headers, key: string): string[] {\n const values =\n headers\n .get(key)\n ?.split(\",\")\n .map((v) => v.trim())\n .filter((v) => v.length > 0) ?? [];\n return Array.from(new Set(values)).sort(lexCompare);\n}\n\n/**\n * Removes a list of header fields from a {@link Headers} object.\n *\n * @param headers - The {@link Headers} object to modify in place.\n * @param keys - An array of header field names to remove. Header names are\n * matched case-insensitively per the Fetch spec.\n */\nexport function filterHeaders(headers: Headers, keys: string[]): void {\n for (const key of keys) {\n headers.delete(key);\n }\n}\n\n/**\n * Extracts all header names from a `Headers` object, normalizes them,\n * and returns them in a stable, lexicographically sorted array.\n *\n * @param headers - The `Headers` object to extract keys from.\n * @returns A sorted array of lowercase header names.\n */\nexport function getHeaderKeys(headers: Headers): string[] {\n return [...headers.keys()].sort(lexCompare);\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Appends a charset parameter to a given media type string,\n * avoiding duplicates and ignoring empty charsets.\n *\n * @param {string} mediaType - The MIME type (e.g., \"text/html\").\n * @param {string} charset - The character set to append (e.g., \"utf-8\").\n * @returns {string} The media type with charset appended if provided.\n */\nexport function withCharset(mediaType: string, charset: string): string {\n if (!charset || mediaType.toLowerCase().includes(\"charset=\")) {\n return mediaType;\n }\n return `${mediaType}; charset=${charset.toLowerCase()}`;\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { StatusCodes } from \"http-status-codes/build/es/status-codes\";\nimport { getReasonPhrase } from \"http-status-codes/build/es/utils-functions\";\n\nimport { CacheControl } from \"./constants/cache\";\nimport { FORBIDDEN_204_HEADERS, FORBIDDEN_304_HEADERS, HttpHeader } from \"./constants/headers\";\nimport { MediaType, UTF8_CHARSET } from \"./constants/media\";\nimport { GET, HEAD } from \"./constants/methods\";\nimport { assertMethods } from \"./guards/methods\";\nimport { assertOctetStreamInit } from \"./guards/responses\";\nimport { Worker } from \"./interfaces\";\nimport { OctetStreamInit } from \"./interfaces/response\";\nimport { filterHeaders, mergeHeader, setHeader } from \"./utils/headers\";\nimport { withCharset } from \"./utils/media\";\n\n/**\n * Base class for building HTTP responses.\n * Manages headers, status, and media type.\n */\nabstract class BaseResponse {\n /** HTTP headers for the response. */\n public headers: Headers = new Headers();\n\n /** HTTP status code (default 200 OK). */\n public status: StatusCodes = StatusCodes.OK;\n\n /** Optional status text. Defaults to standard reason phrase. */\n public statusText?: string;\n\n /** Optional websocket property. */\n public webSocket?: WebSocket | null;\n\n /** Default media type of the response body. */\n public mediaType: string = withCharset(MediaType.PLAIN_TEXT, UTF8_CHARSET);\n\n /** Converts current state to ResponseInit for constructing a Response. */\n protected get responseInit(): ResponseInit {\n return {\n headers: this.headers,\n status: this.status,\n statusText: this.statusText ?? getReasonPhrase(this.status),\n webSocket: this.webSocket,\n encodeBody: \"automatic\",\n };\n }\n\n /** Sets a header, overwriting any existing value. */\n public setHeader(key: string, value: string | string[]): void {\n setHeader(this.headers, key, value);\n }\n\n /** Merges a header with existing values (does not overwrite). */\n public mergeHeader(key: string, value: string | string[]): void {\n mergeHeader(this.headers, key, value);\n }\n\n /** Adds a Content-Type header if not already existing (does not overwrite). */\n public addContentType() {\n if (!this.headers.get(HttpHeader.CONTENT_TYPE)) {\n this.setHeader(HttpHeader.CONTENT_TYPE, this.mediaType);\n }\n }\n\n /**\n * Removes headers that are disallowed or discouraged based on the current\n * status code.\n *\n * - **204 No Content:** strips headers that \"should not\" be sent\n * (`Content-Length`, `Content-Range`), per the HTTP spec.\n * - **304 Not Modified:** strips headers that \"must not\" be sent\n * (`Content-Type`, `Content-Length`, `Content-Range`, etc.), per the HTTP spec.\n *\n * This ensures that responses remain compliant with HTTP/1.1 standards while preserving\n * custom headers that are allowed.\n */\n public filterHeaders(): void {\n if (this.status === StatusCodes.NO_CONTENT) {\n filterHeaders(this.headers, FORBIDDEN_204_HEADERS);\n } else if (this.status === StatusCodes.NOT_MODIFIED) {\n filterHeaders(this.headers, FORBIDDEN_304_HEADERS);\n }\n }\n}\n\n/**\n * Base response class that adds caching headers.\n */\nabstract class CacheResponse extends BaseResponse {\n constructor(public cache?: CacheControl) {\n super();\n }\n\n /** Adds Cache-Control header if caching is configured. */\n protected addCacheHeader(): void {\n if (this.cache) {\n this.setHeader(HttpHeader.CACHE_CONTROL, CacheControl.stringify(this.cache));\n }\n }\n}\n\n/**\n * Core response. Combines caching, and content type headers.\n */\nexport abstract class WorkerResponse extends CacheResponse {\n constructor(\n private readonly body: BodyInit | null = null,\n cache?: CacheControl,\n ) {\n super(cache);\n }\n\n /** Builds the Response with body, headers, and status. */\n public async response(): Promise<Response> {\n this.addCacheHeader();\n\n const body = [StatusCodes.NO_CONTENT, StatusCodes.NOT_MODIFIED].includes(this.status)\n ? null\n : this.body;\n\n if (body) this.addContentType();\n\n this.filterHeaders();\n\n return new Response(body, this.responseInit);\n }\n}\n\n/**\n * Copies an existing response for mutation. Pass in a CacheControl\n * to be used for the response, overriding any existing `cache-control`\n * on the source response.\n */\nexport class CopyResponse extends WorkerResponse {\n constructor(response: Response, cache?: CacheControl) {\n super(response.body, cache);\n this.status = response.status;\n this.statusText = response.statusText;\n this.headers = new Headers(response.headers);\n }\n}\n\n/**\n * Copies the response, but with null body and status 304 Not Modified.\n */\nexport class NotModified extends WorkerResponse {\n constructor(response: Response) {\n super();\n this.status = StatusCodes.NOT_MODIFIED;\n this.headers = new Headers(response.headers);\n }\n}\n\n/**\n * Represents a successful response with customizable body, cache and status.\n */\nexport class SuccessResponse extends WorkerResponse {\n constructor(\n body: BodyInit | null = null,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n ) {\n super(body, cache);\n this.status = status;\n }\n}\n\n/**\n * JSON response. Automatically sets Content-Type to application/json.\n */\nexport class JsonResponse extends SuccessResponse {\n constructor(json: unknown = {}, cache?: CacheControl, status: StatusCodes = StatusCodes.OK) {\n super(JSON.stringify(json), cache, status);\n this.mediaType = withCharset(MediaType.JSON, UTF8_CHARSET);\n }\n}\n\n/**\n * HTML response. Automatically sets Content-Type to text/html.\n */\nexport class HtmlResponse extends SuccessResponse {\n constructor(\n body: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n charset: string = UTF8_CHARSET,\n ) {\n super(body, cache, status);\n this.mediaType = withCharset(MediaType.HTML, charset);\n }\n}\n\n/**\n * Plain text response. Automatically sets Content-Type to text/plain.\n */\nexport class TextResponse extends SuccessResponse {\n constructor(\n body: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n charset: string = UTF8_CHARSET,\n ) {\n super(body, cache, status);\n this.mediaType = withCharset(MediaType.PLAIN_TEXT, charset);\n }\n}\n\n/**\n * Represents an HTTP response for serving binary data as `application/octet-stream`.\n *\n * This class wraps a `ReadableStream` and sets all necessary headers for both\n * full and partial content responses, handling range requests in a hybrid way\n * to maximize browser and CDN caching.\n *\n * Key behaviors:\n * - `Content-Type` is set to `application/octet-stream`.\n * - `Accept-Ranges: bytes` is always included.\n * - `Content-Length` is always set to the validated length of the response body.\n * - If the request is a true partial range (offset > 0 or length < size), the response\n * will be `206 Partial Content` with the appropriate `Content-Range` header.\n * - If the requested range covers the entire file (even if a Range header is present),\n * the response will return `200 OK` to enable browser and edge caching.\n * - Zero-length streams (`size = 0`) are never treated as partial.\n * - Special case: a requested range of `0-0` on a non-empty file is normalized to 1 byte.\n */\nexport class OctetStream extends WorkerResponse {\n constructor(stream: ReadableStream, init: OctetStreamInit, cache?: CacheControl) {\n assertOctetStreamInit(init);\n\n super(stream, cache);\n this.mediaType = MediaType.OCTET_STREAM;\n\n const normalized = OctetStream.normalizeInit(init);\n const { size, offset, length } = normalized;\n\n if (OctetStream.isPartial(normalized)) {\n this.setHeader(\n HttpHeader.CONTENT_RANGE,\n `bytes ${offset}-${offset + length - 1}/${size}`,\n );\n this.status = StatusCodes.PARTIAL_CONTENT;\n }\n\n this.setHeader(HttpHeader.ACCEPT_RANGES, \"bytes\");\n this.setHeader(HttpHeader.CONTENT_LENGTH, `${length}`);\n }\n\n /**\n * Normalizes a partially-specified `OctetStreamInit` into a fully-specified object.\n *\n * Ensures that all required fields (`size`, `offset`, `length`) are defined:\n * - `offset` defaults to 0 if not provided.\n * - `length` defaults to `size - offset` if not provided.\n * - Special case: if `offset` and `length` are both 0 but `size > 0`, `length` is set to 1\n * to avoid zero-length partial streams.\n *\n * @param init - The initial `OctetStreamInit` object, possibly with missing `offset` or `length`.\n * @returns A fully-specified `OctetStreamInit` object with `size`, `offset`, and `length` guaranteed.\n */\n private static normalizeInit(init: OctetStreamInit): Required<OctetStreamInit> {\n const { size } = init;\n const offset = init.offset ?? 0;\n let length = init.length ?? size - offset;\n\n if (offset === 0 && length === 0 && size > 0) {\n length = 1;\n }\n\n return { size, offset, length };\n }\n\n /**\n * Determines whether the given `OctetStreamInit` represents a partial range.\n *\n * Partial ranges are defined as any range that does **not** cover the entire file:\n * - If `size === 0`, the stream is never partial.\n * - If `offset === 0` and `length === size`, the stream is treated as a full file (not partial),\n * even if a Range header is present. This enables browser and CDN caching.\n * - All other cases are considered partial, and will result in a `206 Partial Content` response.\n *\n * @param init - A fully-normalized `OctetStreamInit` object.\n * @returns `true` if the stream represents a partial range; `false` if it represents the full file.\n */\n private static isPartial(init: Required<OctetStreamInit>): boolean {\n if (init.size === 0) return false;\n return !(init.offset === 0 && init.length === init.size);\n }\n}\n\n/**\n * A streaming response for Cloudflare R2 objects.\n *\n * **Partial content support:** To enable HTTP 206 streaming, you must provide\n * request headers containing the `Range` header when calling the R2 bucket's `get()` method.\n *\n * Example:\n * ```ts\n * const stream = await this.env.R2_BUCKET.get(\"key\", { range: this.request.headers });\n * ```\n *\n * @param source - The R2 object to stream.\n * @param cache - Optional caching override.\n */\nexport class R2ObjectStream extends OctetStream {\n constructor(source: R2ObjectBody, cache?: CacheControl) {\n let useCache = cache;\n if (!useCache && source.httpMetadata?.cacheControl) {\n useCache = CacheControl.parse(source.httpMetadata.cacheControl);\n }\n\n super(source.body, R2ObjectStream.computeRange(source.size, source.range), useCache);\n\n this.setHeader(HttpHeader.ETAG, source.httpEtag);\n\n if (source.httpMetadata?.contentType) {\n this.mediaType = source.httpMetadata.contentType;\n }\n }\n\n /**\n * Computes an `OctetStreamInit` object from a given R2 range.\n *\n * This function normalizes a Cloudflare R2 `R2Range` into the shape expected\n * by `OctetStream`. It handles the following cases:\n *\n * - No range provided: returns `{ size }` (full content).\n * - `suffix` range: calculates the offset and length from the end of the file.\n * - Explicit `offset` and/or `length`: passed through as-is.\n *\n * @param size - The total size of the file/object.\n * @param range - Optional range to extract (from R2). Can be:\n * - `{ offset: number; length?: number }`\n * - `{ offset?: number; length: number }`\n * - `{ suffix: number }`\n * @returns An `OctetStreamInit` object suitable for `OctetStream`.\n */\n private static computeRange(size: number, range?: R2Range): OctetStreamInit {\n if (!range) return { size };\n\n if (\"suffix\" in range) {\n const offset = Math.max(0, size - range.suffix);\n const length = size - offset;\n return { size, offset, length };\n }\n\n return { size, ...range };\n }\n}\n\n/**\n * Response for WebSocket upgrade requests.\n * Automatically sets status to 101 and attaches the client socket.\n */\nexport class WebSocketUpgrade extends WorkerResponse {\n constructor(client: WebSocket) {\n super();\n this.status = StatusCodes.SWITCHING_PROTOCOLS;\n this.webSocket = client;\n }\n}\n\n/**\n * Response for `HEAD` requests. Copy headers and status from a `GET` response\n * without the body.\n */\nexport class Head extends WorkerResponse {\n constructor(get: Response) {\n super();\n this.status = get.status;\n this.statusText = get.statusText;\n this.headers = new Headers(get.headers);\n }\n}\n\n/**\n * Response for `OPTIONS` requests.\n */\nexport class Options extends WorkerResponse {\n constructor(worker: Worker) {\n const allowed = Array.from(new Set([GET, HEAD, ...worker.getAllowedMethods()]));\n assertMethods(allowed);\n\n super();\n this.status = StatusCodes.NO_CONTENT;\n this.setHeader(HttpHeader.ALLOW, allowed);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { StatusCodes } from \"http-status-codes/build/es/status-codes\";\nimport { getReasonPhrase } from \"http-status-codes/build/es/utils-functions\";\n\nimport { CacheControl } from \"./constants/cache\";\nimport { HttpHeader } from \"./constants/headers\";\nimport { assertMethods } from \"./guards/methods\";\nimport { ErrorJson } from \"./interfaces/error\";\nimport { Worker } from \"./interfaces/worker\";\nimport { WS_VERSION } from \"./middleware/websocket/constants\";\nimport { JsonResponse } from \"./responses\";\n\n/**\n * Generic HTTP error response.\n * Sends a JSON body with status, error message, and details.\n */\nexport class HttpError extends JsonResponse {\n /**\n * @param worker The worker handling the request.\n * @param status HTTP status code.\n * @param details Optional detailed error message.\n */\n constructor(\n status: StatusCodes,\n protected readonly details?: string,\n ) {\n const json: ErrorJson = {\n status,\n error: getReasonPhrase(status),\n details: details ?? \"\",\n };\n super(json, CacheControl.DISABLE, status);\n }\n}\n\n/**\n * Creates a structured error response without exposing the error\n * details to the client. Links the sent response to the logged\n * error via a generated correlation ID.\n *\n * Status defaults to 500 Internal Server Error.\n */\nexport class LoggedHttpError extends HttpError {\n constructor(error: unknown, status: StatusCodes = StatusCodes.INTERNAL_SERVER_ERROR) {\n const uuid = crypto.randomUUID();\n console.error(uuid, error);\n super(status, uuid);\n }\n}\n\n/** 400 Bad Request error response. */\nexport class BadRequest extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.BAD_REQUEST, details);\n }\n}\n\n/** 401 Unauthorized error response. */\nexport class Unauthorized extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.UNAUTHORIZED, details);\n }\n}\n\n/** 403 Forbidden error response. */\nexport class Forbidden extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.FORBIDDEN, details);\n }\n}\n\n/** 404 Not Found error response. */\nexport class NotFound extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.NOT_FOUND, details);\n }\n}\n\n/** 405 Method Not Allowed error response. */\nexport class MethodNotAllowed extends HttpError {\n constructor(worker: Worker) {\n const methods = worker.getAllowedMethods();\n assertMethods(methods);\n\n super(StatusCodes.METHOD_NOT_ALLOWED, `${worker.request.method} method not allowed.`);\n this.setHeader(HttpHeader.ALLOW, methods);\n }\n}\n\n/** 412 Precondition Failed error response */\nexport class PreconditionFailed extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.PRECONDITION_FAILED, details);\n }\n}\n\n/** 426 Upgrade Required error response. */\nexport class UpgradeRequired extends HttpError {\n constructor() {\n super(StatusCodes.UPGRADE_REQUIRED);\n this.setHeader(HttpHeader.SEC_WEBSOCKET_VERSION, WS_VERSION);\n }\n}\n\n/** 500 Internal Server Error response. */\nexport class InternalServerError extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.INTERNAL_SERVER_ERROR, details);\n }\n}\n\n/** 501 Not Implemented error response. */\nexport class NotImplemented extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.NOT_IMPLEMENTED, details);\n }\n}\n\n/** 501 Method Not Implemented error response for unsupported HTTP methods. */\nexport class MethodNotImplemented extends NotImplemented {\n constructor(worker: Worker) {\n super(`${worker.request.method} method not implemented.`);\n }\n}\n\n/** 503 Service Unavailable error response. */\nexport class ServiceUnavailable extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.SERVICE_UNAVAILABLE, details);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Middleware } from \"../interfaces/middleware\";\n\n/**\n * Asserts at runtime that a value implements the `Middleware` interface.\n *\n * @param value - The value to check.\n * @throws TypeError If `handler` does not have a `handle` method.\n */\nexport function assertMiddleware(value: unknown): asserts value is Middleware {\n if (\n value === null ||\n typeof value !== \"object\" ||\n typeof (value as Middleware).handle !== \"function\"\n ) {\n throw new TypeError(\n \"Handler must implement the Middleware interface (have a handle method).\",\n );\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { GET, HEAD, Method } from \"../constants/methods\";\nimport { assertMethods, isMethod } from \"../guards/methods\";\nimport { FetchHandler } from \"../interfaces/fetch\";\nimport { Worker, WorkerClass } from \"../interfaces/worker\";\n\n/**\n * Provides the foundational structure for handling requests,\n * environment bindings, and the worker execution context.\n *\n * Features:\n * - Holds the current `Request` object (`request` getter).\n * - Provides access to environment bindings (`env` getter).\n * - Provides access to the worker execution context (`ctx` getter).\n * - Subclasses must implement `fetch()` to process the request.\n */\nexport abstract class BaseWorker implements Worker {\n constructor(\n private readonly _request: Request,\n private readonly _env: Env,\n private readonly _ctx: ExecutionContext,\n ) {}\n\n /** The Request object associated with this worker invocation */\n public get request(): Request {\n return this._request;\n }\n\n /** Environment bindings (e.g., KV, secrets, or other globals) */\n public get env(): Env {\n return this._env;\n }\n\n /** Execution context for background tasks or `waitUntil` */\n public get ctx(): ExecutionContext {\n return this._ctx;\n }\n\n /**\n * Dispatches the incoming request to the appropriate handler and produces a response.\n *\n * Subclasses must implement this method to define how the worker generates a `Response`\n * for the current request. This is the central point where request processing occurs.\n *\n * @returns A Promise that resolves to the `Response` for the request.\n */\n protected abstract dispatch(): Promise<Response>;\n\n /**\n * Determines whether a given HTTP method is allowed for this worker.\n *\n * - GET and HEAD are **always allowed**, in compliance with RFC 9110,\n * even if they are not explicitly listed in `getAllowedMethods()`.\n * - Other methods are allowed only if included in the array returned by\n * `getAllowedMethods()` and are valid HTTP methods.\n *\n * @param method - The HTTP method to check (e.g., \"GET\", \"POST\").\n * @returns `true` if the method is allowed, `false` otherwise.\n */\n public isAllowed(method: string): boolean {\n const methods = this.getAllowedMethods();\n assertMethods(methods);\n\n // GET and HEAD are always allowed per RFC\n if (method === GET || method === HEAD) return true;\n\n return isMethod(method) && methods.includes(method);\n }\n\n public abstract getAllowedMethods(): Method[];\n\n /**\n * Creates a new instance of the current Worker subclass.\n *\n * @param request - The {@link Request} to pass to the new worker instance.\n * @returns A new worker instance of the same subclass as `this`.\n */\n protected create(request: Request): this {\n const ctor = this.constructor as WorkerClass<this>;\n return new ctor(request, this.env, this.ctx);\n }\n\n /**\n * Process the {@link Request} and produce a {@link Response}.\n *\n * @returns A {@link Response} promise for the {@link Request}.\n */\n public abstract fetch(): Promise<Response>;\n\n /**\n * Simplify and standardize {@link Response} creation by extending {@link WorkerResponse}\n * or any of its subclasses and passing to this method.\n *\n * Or directly use any of the built-in classes.\n *\n * ```ts\n * this.response(TextResponse, \"Hello World!\")\n * ```\n *\n * @param ResponseClass The response class to instantiate\n * @param args Additional constructor arguments\n * @returns A Promise resolving to the {@link Response} object\n */\n protected response<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Ctor extends new (...args: any[]) => { response(): Promise<Response> },\n >(ResponseClass: Ctor, ...args: ConstructorParameters<Ctor>): Promise<Response> {\n return new ResponseClass(...args).response();\n }\n\n /**\n * **Ignite** your `Worker` implementation into a Cloudflare handler.\n *\n * @returns A `FetchHandler` that launches a new worker instance for each request.\n *\n * ```ts\n * export default MyWorker.ignite();\n * ```\n */\n public static ignite<W extends Worker>(this: WorkerClass<W>): FetchHandler {\n return {\n fetch: (request: Request, env: Env, ctx: ExecutionContext) =>\n new this(request, env, ctx).fetch(),\n };\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { MethodNotAllowed } from \"../errors\";\nimport { assertMiddleware } from \"../guards/middleware\";\nimport { Middleware } from \"../interfaces/middleware\";\n\nimport { BaseWorker } from \"./base\";\n\n/** Base worker for handling middleware chains. */\nexport abstract class MiddlewareWorker extends BaseWorker {\n /** Middleware handlers registered for this worker. */\n protected readonly middlewares: Middleware[] = [];\n\n /**\n * Hook for subclasses to perform any initialization.\n */\n protected init(): void | Promise<void> {\n return;\n }\n\n /**\n * Add one or more middleware instances to this worker.\n *\n * The middleware will run for every request handled by this worker,\n * in the order they are added.\n *\n * @param middleware - One or more middleware instances to run.\n * @returns `this` to allow chaining multiple `.use()` calls.\n */\n public use(...middleware: Middleware[]): this {\n for (const value of middleware) {\n assertMiddleware(value);\n }\n\n this.middlewares.push(...middleware);\n return this;\n }\n\n /**\n * Executes the middleware chain and dispatches the request if the method\n * is allowed by the worker.\n *\n * @returns The Response produced by the last middleware or `dispatch()`.\n */\n public override async fetch(): Promise<Response> {\n /**\n * Allow subclasses to add middleware to be used for the request.\n */\n await this.init();\n\n const chain = this.middlewares.reduceRight(\n (next, handler) => () => handler.handle(this, next),\n () => {\n if (!this.isAllowed(this.request.method)) {\n return this.response(MethodNotAllowed, this);\n }\n return this.dispatch();\n },\n );\n return chain();\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { GET, HEAD, Method, OPTIONS } from \"../constants/methods\";\nimport { LoggedHttpError, MethodNotAllowed, MethodNotImplemented, NotFound } from \"../errors\";\nimport { Head, Options } from \"../responses\";\n\nimport { MiddlewareWorker } from \"./middleware\";\n\n/**\n * Basic worker class providing HTTP method dispatching and error handling.\n */\nexport abstract class BasicWorker extends MiddlewareWorker {\n /**\n * Entry point to handle a fetch request.\n */\n public override async fetch(): Promise<Response> {\n try {\n return await super.fetch();\n } catch (error) {\n return this.response(LoggedHttpError, error);\n }\n }\n\n /**\n * Dispatches the request to the method-specific handler.\n */\n protected override dispatch(): Promise<Response> {\n const method = this.request.method as Method;\n const handler: Record<Method, () => Promise<Response>> = {\n GET: () => this.get(),\n PUT: () => this.put(),\n HEAD: () => this.head(),\n POST: () => this.post(),\n PATCH: () => this.patch(),\n DELETE: () => this.delete(),\n OPTIONS: () => this.options(),\n };\n\n return (handler[method] ?? (() => this.response(MethodNotAllowed, this)))();\n }\n\n /** Override and implement this method for `GET` requests. */\n protected get(): Promise<Response> {\n return this.response(NotFound);\n }\n\n /** Override and implement this method for `PUT` requests. */\n protected put(): Promise<Response> {\n return this.response(MethodNotImplemented, this);\n }\n\n /** Override and implement this method for `POST` requests. */\n protected post(): Promise<Response> {\n return this.response(MethodNotImplemented, this);\n }\n\n /** Override and implement this method for `PATCH` requests. */\n protected patch(): Promise<Response> {\n return this.response(MethodNotImplemented, this);\n }\n\n /** Override and implement this method for `DELETE` requests. */\n protected delete(): Promise<Response> {\n return this.response(MethodNotImplemented, this);\n }\n\n /** Returns the default `OPTIONS` response. */\n protected options(): Promise<Response> {\n return this.response(Options, this);\n }\n\n /**\n * Default handler for `HEAD` requests.\n * Performs a `GET` request and removes the body for `HEAD` semantics.\n *\n * Usually does not need to be overridden as this behavior covers\n * standard `HEAD` requirements.\n */\n protected async head(): Promise<Response> {\n const worker = this.create(\n new Request(this.request.url, { method: GET, headers: this.request.headers }),\n );\n return this.response(Head, await worker.fetch());\n }\n\n /**\n * Returns the HTTP methods allowed by this worker.\n *\n * - GET and HEAD are always allowed per RFC 9110, even if subclasses do not include them here.\n * - OPTIONS is included by default since a default handler is implemented.\n * - Subclasses can override this method to allow additional methods or change the defaults.\n */\n public getAllowedMethods(): Method[] {\n return [GET, HEAD, OPTIONS];\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { match } from \"path-to-regexp\";\n\nimport { Method } from \"./constants/methods\";\nimport { MatchedRoute, PathParams, Route, RouteTable } from \"./interfaces/route\";\n\n/**\n * Container for route definitions and matching logic.\n * Implements Iterable to allow iteration over all routes.\n */\nexport class Routes implements Iterable<Route> {\n /** Internal array of registered routes */\n private readonly routes: Route[] = [];\n\n /**\n * Add routes to the router.\n *\n * Accepts any iterable of [method, path, handler] tuples.\n * This includes arrays, Sets, or generators.\n *\n * @param routes - Iterable of route tuples to add.\n */\n public add(routes: RouteTable): void {\n for (const [method, path, handler] of routes) {\n const matcher = match<PathParams>(path);\n this.routes.push({ method, matcher, handler });\n }\n }\n\n /**\n * Attempt to match a URL against the registered routes.\n *\n * @param method - HTTP method of the request\n * @param url - Full URL string to match against\n * @returns A MatchedRoute object if a route matches, otherwise null\n */\n public match(method: Method, url: string): MatchedRoute | null {\n const pathname = new URL(url).pathname;\n\n for (const route of this) {\n if (route.method !== method) continue;\n\n const found = route.matcher(pathname);\n if (found) return { route, params: found.params };\n }\n\n return null;\n }\n\n /**\n * Iterate over all registered routes.\n */\n public *[Symbol.iterator](): Iterator<Route> {\n yield* this.routes;\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Method } from \"../constants/methods\";\nimport { NotFound } from \"../errors\";\nimport { RouteHandler, RouteTable } from \"../interfaces/route\";\nimport { WorkerClass } from \"../interfaces/worker\";\nimport { Routes } from \"../routes\";\n\nimport { BaseWorker } from \"./base\";\nimport { BasicWorker } from \"./basic\";\n\n/**\n * Base worker supporting route-based request handling.\n *\n * Subclass `RouteWorker` to define a worker with multiple route handlers.\n *\n * Routes can be registered individually via `route()` or in bulk via `routes()`.\n */\nexport abstract class RouteWorker extends BasicWorker {\n /** Internal table of registered routes. */\n private readonly _routes: Routes = new Routes();\n\n /**\n * Registers a single new route in the worker.\n *\n * When a request matches the specified method and path, the provided handler\n * will be executed. The handler can be either:\n * - A function that receives URL parameters, or\n * - A Worker subclass that will handle the request.\n *\n * @param method - HTTP method for the route (`GET`, `POST`, etc.).\n * @param path - URL path pattern (path-to-regexp, e.g., \"/users/:id\").\n * @param handler - The function or Worker class to run when the route matches.\n * @returns The current worker instance, allowing method chaining.\n */\n protected route(method: Method, path: string, handler: RouteHandler): this {\n this.routes([[method, path, handler]]);\n return this;\n }\n\n /**\n * Registers multiple routes at once in the worker.\n *\n * Each route should be a tuple `[method, path, handler]` where:\n * - `method` - HTTP method for the route (`GET`, `POST`, etc.).\n * - `path` - URL path pattern (path-to-regexp e.g., \"/users/:id\").\n * - `handler` - A function that receives URL parameters or a Worker subclass\n * that will handle the request.\n *\n * @param routes - An iterable of routes to register. Each item is a `[method, path, handler]` tuple.\n * @returns The current worker instance, allowing method chaining.\n */\n protected routes(routes: RouteTable): this {\n this._routes.add(routes);\n return this;\n }\n\n /**\n * Matches the incoming request against registered routes and dispatches it.\n *\n * If a route is found:\n * - If the handler is a Worker class, a new instance is created and its `fetch()` is called.\n * - If the handler is a callback function, it is invoked with the extracted path parameters.\n *\n * If no route matches, the request is passed to the superclass ({@link BasicWorker})\n * `dispatch()` handler.\n *\n * @returns A `Promise<Response>` from the matched handler or parent dispatch.\n */\n protected override async dispatch(): Promise<Response> {\n const found = this._routes.match(this.request.method as Method, this.request.url);\n if (!found) return super.dispatch();\n\n const { handler } = found.route;\n if (RouteWorker.isWorkerClass(handler)) {\n return new handler(this.request, this.env, this.ctx).fetch();\n }\n return handler.call(this, found.params);\n }\n\n /**\n * Runtime type guard to check if a given handler is a Worker class.\n *\n * A Worker class is any class that extends `BaseWorker`.\n *\n * @param handler - The constructor function to test.\n * @returns `true` if `handler` is a subclass of `BaseWorker` at runtime, `false` otherwise.\n */\n private static isWorkerClass(handler: RouteHandler): handler is WorkerClass {\n return Object.prototype.isPrototypeOf.call(BaseWorker.prototype, handler.prototype);\n }\n\n protected override put(): Promise<Response> {\n return this.response(NotFound);\n }\n\n protected override post(): Promise<Response> {\n return this.response(NotFound);\n }\n\n protected override patch(): Promise<Response> {\n return this.response(NotFound);\n }\n\n protected override delete(): Promise<Response> {\n return this.response(NotFound);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants/cache.ts","../src/constants/methods.ts","../src/constants/time.ts","../src/constants/headers.ts","../src/guards/basic.ts","../src/guards/methods.ts","../src/constants/media.ts","../src/guards/responses.ts","../src/utils/compare.ts","../src/utils/headers.ts","../src/utils/media.ts","../src/responses.ts","../src/errors.ts","../src/guards/middleware.ts","../src/workers/base.ts","../src/workers/middleware.ts","../src/workers/basic.ts","../src/routes.ts","../src/workers/route.ts"],"names":["CacheControl","CacheLib","Method","GET","PUT","HEAD","POST","PATCH","DELETE","OPTIONS","Time","HttpHeader","FORBIDDEN_304_HEADERS","FORBIDDEN_204_HEADERS","isString","value","isNumber","METHOD_SET","isMethod","isMethodArray","assertMethods","desc","UTF8_CHARSET","assertOctetStreamInit","obj","size","offset","length","lexCompare","a","b","setHeader","headers","key","raw","values","v","mergeHeader","merged","getHeaderValues","filterHeaders","keys","withCharset","mediaType","charset","BaseResponse","StatusCodes","getReasonPhrase","CacheResponse","cache","WorkerResponse","body","CopyResponse","response","NotModified","SuccessResponse","status","JsonResponse","json","HtmlResponse","TextResponse","OctetStream","_OctetStream","stream","init","normalized","R2ObjectStream","_R2ObjectStream","source","useCache","range","WebSocketUpgrade","client","Head","get","Options","worker","allowed","HttpError","details","LoggedHttpError","error","uuid","BadRequest","Unauthorized","Forbidden","NotFound","MethodNotAllowed","methods","PreconditionFailed","UpgradeRequired","InternalServerError","NotImplemented","MethodNotImplemented","ServiceUnavailable","assertMiddleware","BaseWorker","_request","_env","_ctx","method","request","ctor","ResponseClass","args","env","ctx","MiddlewareWorker","middleware","next","handler","BasicWorker","Routes","routes","path","matcher","match","url","pathname","route","found","RouteWorker","_RouteWorker"],"mappings":"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","file":"index.js","sourcesContent":["/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport CacheLib from \"cache-control-parser\";\n\n/**\n * @see {@link https://github.com/etienne-martin/cache-control-parser | cache-control-parser}\n */\nexport type CacheControl = CacheLib.CacheControl;\nexport const CacheControl = {\n parse: CacheLib.parse,\n stringify: CacheLib.stringify,\n\n /** A CacheControl directive that disables all caching. */\n DISABLE: Object.freeze({\n \"no-cache\": true,\n \"no-store\": true,\n \"must-revalidate\": true,\n \"max-age\": 0,\n }) satisfies CacheControl,\n};\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Standard HTTP request methods.\n */\nexport enum Method {\n GET = \"GET\",\n PUT = \"PUT\",\n HEAD = \"HEAD\",\n POST = \"POST\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n OPTIONS = \"OPTIONS\",\n}\n\n/**\n * Shorthand constants for each HTTP method.\n *\n * These are equivalent to the corresponding enum members in `Method`.\n * For example, `GET === Method.GET`.\n */\nexport const { GET, PUT, HEAD, POST, PATCH, DELETE, OPTIONS } = Method;\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Time constants in seconds. Month is approximated as 30 days.\n */\nexport const Time = {\n Second: 1,\n Minute: 60,\n Hour: 3600, // 60 * 60\n Day: 86400, // 60 * 60 * 24\n Week: 604800, // 60 * 60 * 24 * 7\n Month: 2592000, // 60 * 60 * 24 * 30\n Year: 31536000, // 60 * 60 * 24 * 365\n} as const;\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internally used headers.\n */\nexport const HttpHeader = {\n ACCEPT: \"accept\",\n ACCEPT_ENCODING: \"accept-encoding\",\n ACCEPT_LANGUAGE: \"accept-language\",\n ACCEPT_RANGES: \"accept-ranges\",\n ALLOW: \"allow\",\n AUTHORIZATION: \"authorization\",\n CACHE_CONTROL: \"cache-control\",\n CONNECTION: \"connection\",\n CONTENT_DISPOSITION: \"content-disposition\",\n CONTENT_ENCODING: \"content-encoding\",\n CONTENT_LANGUAGE: \"content-language\",\n CONTENT_LENGTH: \"content-length\",\n CONTENT_RANGE: \"content-range\",\n CONTENT_TYPE: \"content-type\",\n CONTENT_MD5: \"content-md5\",\n COOKIE: \"cookie\",\n ETAG: \"etag\",\n IF_MATCH: \"if-match\",\n IF_MODIFIED_SINCE: \"if-modified-since\",\n IF_NONE_MATCH: \"if-none-match\",\n IF_UNMODIFIED_SINCE: \"if-unmodified-since\",\n LAST_MODIFIED: \"last-modified\",\n ORIGIN: \"origin\",\n RANGE: \"range\",\n SET_COOKIE: \"set-cookie\",\n VARY: \"vary\",\n\n // Cors Headers\n ACCESS_CONTROL_ALLOW_CREDENTIALS: \"access-control-allow-credentials\",\n ACCESS_CONTROL_ALLOW_HEADERS: \"access-control-allow-headers\",\n ACCESS_CONTROL_ALLOW_METHODS: \"access-control-allow-methods\",\n ACCESS_CONTROL_ALLOW_ORIGIN: \"access-control-allow-origin\",\n ACCESS_CONTROL_EXPOSE_HEADERS: \"access-control-expose-headers\",\n ACCESS_CONTROL_MAX_AGE: \"access-control-max-age\",\n\n // Websocket Headers\n SEC_WEBSOCKET_VERSION: \"sec-websocket-version\",\n UPGRADE: \"upgrade\",\n\n // Internal Headers\n INTERNAL_VARIANT_SET: \"internal-variant-set\",\n} as const;\n\n/**\n * Headers that must not be sent in 304 Not Modified responses.\n * These are stripped to comply with the HTTP spec.\n */\nexport const FORBIDDEN_304_HEADERS = [\n HttpHeader.CONTENT_TYPE,\n HttpHeader.CONTENT_LENGTH,\n HttpHeader.CONTENT_RANGE,\n HttpHeader.CONTENT_ENCODING,\n HttpHeader.CONTENT_LANGUAGE,\n HttpHeader.CONTENT_DISPOSITION,\n HttpHeader.CONTENT_MD5,\n];\n\n/**\n * Headers that should not be sent in 204 No Content responses.\n * Stripping them is recommended but optional per spec.\n */\nexport const FORBIDDEN_204_HEADERS = [HttpHeader.CONTENT_LENGTH, HttpHeader.CONTENT_RANGE];\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Checks if the provided value is an array of strings.\n *\n * @param value - The value to check.\n * @returns True if `array` is an array where every item is a string.\n */\nexport function isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\n/**\n * Checks if a value is a string.\n *\n * @param value - The value to check.\n * @returns `true` if the value is a string, otherwise `false`.\n */\nexport function isString(value: unknown): value is string {\n return typeof value === \"string\";\n}\n\n\n/**\n * Checks if a value is a valid number (not NaN).\n *\n * This function returns `true` if the value is of type `number`\n * and is not `NaN`. It works as a type guard for TypeScript.\n *\n * @param value - The value to check.\n * @returns `true` if the value is a number and not `NaN`, otherwise `false`.\n */\nexport function isNumber(value: unknown): value is number {\n return typeof value === \"number\" && !Number.isNaN(value);\n}\n\n/**\n * Checks if a value is a boolean.\n *\n * @param value - The value to check.\n * @returns `true` if the value is a boolean (`true` or `false`), otherwise `false`.\n */\nexport function isBoolean(value: unknown): value is boolean {\n return typeof value === \"boolean\";\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Method } from \"../constants/methods\";\n\nimport { isString } from \"./basic\";\n\n/**\n * A set containing all supported HTTP methods.\n *\n * Useful for runtime checks like validating request methods.\n */\nconst METHOD_SET: Set<string> = new Set(Object.values(Method));\n\n/**\n * Type guard that checks if a string is a valid HTTP method.\n *\n * @param value - The string to test.\n * @returns True if `value` is a recognized HTTP method.\n */\nexport function isMethod(value: unknown): value is Method {\n return isString(value) && METHOD_SET.has(value);\n}\n\n/**\n * Checks if a value is an array of valid HTTP methods.\n *\n * Each element is verified using the `isMethod` type guard.\n *\n * @param value - The value to check.\n * @returns `true` if `value` is an array and every element is a valid `Method`, otherwise `false`.\n */\nexport function isMethodArray(value: unknown): value is Method[] {\n return Array.isArray(value) && value.every(isMethod);\n}\n\n/**\n * Asserts that a value is an array of valid HTTP methods.\n *\n * This function uses {@link isMethodArray} to validate the input. If the\n * value is not an array of `Method` elements, it throws a `TypeError`.\n * Otherwise, TypeScript will narrow the type of `value` to `Method[]`\n * within the calling scope.\n *\n * @param value - The value to check.\n * @throws TypeError If `value` is not a valid {@link Method} array.\n */\nexport function assertMethods(value: unknown): asserts value is Method[] {\n if (!isMethodArray(value)) {\n const desc = Array.isArray(value) ? JSON.stringify(value) : String(value);\n throw new TypeError(`Invalid method array: ${desc}`);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const UTF8_CHARSET = \"utf-8\";\n\n/**\n * Internal media types.\n */\nexport enum MediaType {\n PLAIN_TEXT = \"text/plain\",\n HTML = \"text/html\",\n JSON = \"application/json\",\n OCTET_STREAM = \"application/octet-stream\",\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { OctetStreamInit } from \"../interfaces\";\n\nimport { isNumber } from \"./basic\";\n\n/**\n * Asserts that a given value is a valid `OctetStreamInit` object.\n *\n * Properties:\n * - `size` (required): must be a non-negative number.\n * - `offset` (optional): if provided, must be a number between 0 and `size`.\n * - `length` (optional): if provided, must be a non-negative number such that `offset + length <= size`.\n *\n * If `offset` or `length` are `undefined`, they are considered as `0` and `size` respectively.\n *\n * Throws an error if validation fails.\n *\n * Acts as a TypeScript type predicate, so after calling it, `value` is narrowed to `OctetStreamInit`.\n *\n * @param value - The value to validate as `OctetStreamInit`.\n * @throws TypeError If the value is not a non-null object.\n * @throws RangeError If `size`, `offset`, or `length` are invalid.\n */\nexport function assertOctetStreamInit(value: unknown): asserts value is OctetStreamInit {\n if (typeof value !== \"object\" || value === null) {\n throw new TypeError(\"OctetStreamInit must be an object.\");\n }\n\n const obj = value as Record<string, unknown>;\n\n // size\n const size = obj[\"size\"];\n if (!isNumber(size) || size < 0 || !Number.isInteger(size)) {\n throw new RangeError(\n `OctetStreamInit.size must be a non-negative integer (size=${JSON.stringify(size)}).`,\n );\n }\n\n // offset\n const offset = obj[\"offset\"] ?? 0;\n if (!isNumber(offset) || offset < 0 || offset > size || !Number.isInteger(offset)) {\n throw new RangeError(\n `OctetStreamInit.offset must be a non-negative integer less than or equal to size (size=${JSON.stringify(size)}, offset=${JSON.stringify(offset)}).`,\n );\n }\n\n // length\n const length = obj[\"length\"] ?? size - offset;\n if (!isNumber(length) || length < 0 || offset + length > size || !Number.isInteger(length)) {\n throw new RangeError(\n `OctetStreamInit.length must be a non-negative integer less than or equal to size - offset (size=${JSON.stringify(size)}, offset=${JSON.stringify(offset)}, length=${JSON.stringify(length)}).`,\n );\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Lexicographically compares two strings.\n *\n * This comparator can be used in `Array.prototype.sort()` to produce a\n * consistent, stable ordering of string arrays.\n *\n * @param a - The first string to compare.\n * @param b - The second string to compare.\n * @returns A number indicating the relative order of `a` and `b`.\n */\nexport function lexCompare(a: string, b: string): number {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { lexCompare } from \"./compare\";\n\n/**\n * Sets a header on the given Headers object.\n *\n * - If `value` is an array, any duplicates and empty strings are removed.\n * - If the resulting value is empty, the header is deleted.\n * - Otherwise, values are joined with `\", \"` and set as the header value.\n *\n * @param headers - The Headers object to modify.\n * @param key - The header name to set.\n * @param value - The header value(s) to set. Can be a string or array of strings.\n */\nexport function setHeader(headers: Headers, key: string, value: string | string[]): void {\n const raw = Array.isArray(value) ? value : [value];\n const values = Array.from(new Set(raw.map((v) => v.trim())))\n .filter((v) => v.length)\n .sort(lexCompare);\n\n if (!values.length) {\n headers.delete(key);\n return;\n }\n\n headers.set(key, values.join(\", \"));\n}\n\n/**\n * Merges new value(s) into an existing header on the given Headers object.\n *\n * - Preserves any existing values and adds new ones.\n * - Removes duplicates and trims all values.\n * - If the header does not exist, it is created.\n * - If the resulting value array is empty, the header is deleted.\n *\n * @param headers - The Headers object to modify.\n * @param key - The header name to merge into.\n * @param value - The new header value(s) to add. Can be a string or array of strings.\n */\nexport function mergeHeader(headers: Headers, key: string, value: string | string[]): void {\n const values = Array.isArray(value) ? value : [value];\n if (values.length === 0) return;\n\n const existing = getHeaderValues(headers, key);\n const merged = existing.concat(values.map((v) => v.trim()));\n\n setHeader(headers, key, merged);\n}\n\n/**\n * Returns the values of an HTTP header as an array of strings.\n *\n * This helper:\n * - Retrieves the header value by `key`.\n * - Splits the value on commas.\n * - Trims surrounding whitespace from each entry.\n * - Filters out any empty tokens.\n * - Removes duplicate values (case-sensitive)\n *\n * If the header is not present, an empty array is returned.\n *\n */\nexport function getHeaderValues(headers: Headers, key: string): string[] {\n const values =\n headers\n .get(key)\n ?.split(\",\")\n .map((v) => v.trim())\n .filter((v) => v.length > 0) ?? [];\n return Array.from(new Set(values)).sort(lexCompare);\n}\n\n/**\n * Removes a list of header fields from a {@link Headers} object.\n *\n * @param headers - The {@link Headers} object to modify in place.\n * @param keys - An array of header field names to remove. Header names are\n * matched case-insensitively per the Fetch spec.\n */\nexport function filterHeaders(headers: Headers, keys: string[]): void {\n for (const key of keys) {\n headers.delete(key);\n }\n}\n\n/**\n * Extracts all header names from a `Headers` object, normalizes them,\n * and returns them in a stable, lexicographically sorted array.\n *\n * @param headers - The `Headers` object to extract keys from.\n * @returns A sorted array of lowercase header names.\n */\nexport function getHeaderKeys(headers: Headers): string[] {\n return [...headers.keys()].sort(lexCompare);\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Appends a charset parameter to a given media type string,\n * avoiding duplicates and ignoring empty charsets.\n *\n * @param {string} mediaType - The MIME type (e.g., \"text/html\").\n * @param {string} charset - The character set to append (e.g., \"utf-8\").\n * @returns {string} The media type with charset appended if provided.\n */\nexport function withCharset(mediaType: string, charset: string): string {\n if (!charset || mediaType.toLowerCase().includes(\"charset=\")) {\n return mediaType;\n }\n return `${mediaType}; charset=${charset.toLowerCase()}`;\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getReasonPhrase } from \"http-status-codes/build/es/utils-functions\";\n\nimport { StatusCodes } from \"./constants\";\nimport { CacheControl } from \"./constants/cache\";\nimport { FORBIDDEN_204_HEADERS, FORBIDDEN_304_HEADERS, HttpHeader } from \"./constants/headers\";\nimport { MediaType, UTF8_CHARSET } from \"./constants/media\";\nimport { GET, HEAD } from \"./constants/methods\";\nimport { assertMethods } from \"./guards/methods\";\nimport { assertOctetStreamInit } from \"./guards/responses\";\nimport { Worker } from \"./interfaces\";\nimport { OctetStreamInit } from \"./interfaces/response\";\nimport { filterHeaders, mergeHeader, setHeader } from \"./utils/headers\";\nimport { withCharset } from \"./utils/media\";\n\n/**\n * Base class for building HTTP responses.\n * Manages headers, status, and media type.\n */\nabstract class BaseResponse {\n /** HTTP headers for the response. */\n public headers: Headers = new Headers();\n\n /** HTTP status code (default 200 OK). */\n public status: StatusCodes = StatusCodes.OK;\n\n /** Optional status text. Defaults to standard reason phrase. */\n public statusText?: string;\n\n /** Optional websocket property. */\n public webSocket?: WebSocket | null;\n\n /** Default media type of the response body. */\n public mediaType: string = withCharset(MediaType.PLAIN_TEXT, UTF8_CHARSET);\n\n /** Converts current state to ResponseInit for constructing a Response. */\n protected get responseInit(): ResponseInit {\n return {\n headers: this.headers,\n status: this.status,\n statusText: this.statusText ?? getReasonPhrase(this.status),\n webSocket: this.webSocket,\n encodeBody: \"automatic\",\n };\n }\n\n /** Sets a header, overwriting any existing value. */\n public setHeader(key: string, value: string | string[]): void {\n setHeader(this.headers, key, value);\n }\n\n /** Merges a header with existing values (does not overwrite). */\n public mergeHeader(key: string, value: string | string[]): void {\n mergeHeader(this.headers, key, value);\n }\n\n /** Adds a Content-Type header if not already existing (does not overwrite). */\n public addContentType() {\n if (!this.headers.get(HttpHeader.CONTENT_TYPE)) {\n this.setHeader(HttpHeader.CONTENT_TYPE, this.mediaType);\n }\n }\n\n /**\n * Removes headers that are disallowed or discouraged based on the current\n * status code.\n *\n * - **204 No Content:** strips headers that \"should not\" be sent\n * (`Content-Length`, `Content-Range`), per the HTTP spec.\n * - **304 Not Modified:** strips headers that \"must not\" be sent\n * (`Content-Type`, `Content-Length`, `Content-Range`, etc.), per the HTTP spec.\n *\n * This ensures that responses remain compliant with HTTP/1.1 standards while preserving\n * custom headers that are allowed.\n */\n public filterHeaders(): void {\n if (this.status === StatusCodes.NO_CONTENT) {\n filterHeaders(this.headers, FORBIDDEN_204_HEADERS);\n } else if (this.status === StatusCodes.NOT_MODIFIED) {\n filterHeaders(this.headers, FORBIDDEN_304_HEADERS);\n }\n }\n}\n\n/**\n * Base response class that adds caching headers.\n */\nabstract class CacheResponse extends BaseResponse {\n constructor(public cache?: CacheControl) {\n super();\n }\n\n /** Adds Cache-Control header if caching is configured. */\n protected addCacheHeader(): void {\n if (this.cache) {\n this.setHeader(HttpHeader.CACHE_CONTROL, CacheControl.stringify(this.cache));\n }\n }\n}\n\n/**\n * Core response. Combines caching, and content type headers.\n */\nexport abstract class WorkerResponse extends CacheResponse {\n constructor(\n private readonly body: BodyInit | null = null,\n cache?: CacheControl,\n ) {\n super(cache);\n }\n\n /** Builds the Response with body, headers, and status. */\n public async response(): Promise<Response> {\n this.addCacheHeader();\n\n const body = [StatusCodes.NO_CONTENT, StatusCodes.NOT_MODIFIED].includes(this.status)\n ? null\n : this.body;\n\n if (body) this.addContentType();\n\n this.filterHeaders();\n\n return new Response(body, this.responseInit);\n }\n}\n\n/**\n * Copies an existing response for mutation. Pass in a CacheControl\n * to be used for the response, overriding any existing `cache-control`\n * on the source response.\n */\nexport class CopyResponse extends WorkerResponse {\n constructor(response: Response, cache?: CacheControl) {\n super(response.body, cache);\n this.status = response.status;\n this.statusText = response.statusText;\n this.headers = new Headers(response.headers);\n }\n}\n\n/**\n * Copies the response, but with null body and status 304 Not Modified.\n */\nexport class NotModified extends WorkerResponse {\n constructor(response: Response) {\n super();\n this.status = StatusCodes.NOT_MODIFIED;\n this.headers = new Headers(response.headers);\n }\n}\n\n/**\n * Represents a successful response with customizable body, cache and status.\n */\nexport class SuccessResponse extends WorkerResponse {\n constructor(\n body: BodyInit | null = null,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n ) {\n super(body, cache);\n this.status = status;\n }\n}\n\n/**\n * JSON response. Automatically sets Content-Type to application/json.\n */\nexport class JsonResponse extends SuccessResponse {\n constructor(json: unknown = {}, cache?: CacheControl, status: StatusCodes = StatusCodes.OK) {\n super(JSON.stringify(json), cache, status);\n this.mediaType = withCharset(MediaType.JSON, UTF8_CHARSET);\n }\n}\n\n/**\n * HTML response. Automatically sets Content-Type to text/html.\n */\nexport class HtmlResponse extends SuccessResponse {\n constructor(\n body: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n charset: string = UTF8_CHARSET,\n ) {\n super(body, cache, status);\n this.mediaType = withCharset(MediaType.HTML, charset);\n }\n}\n\n/**\n * Plain text response. Automatically sets Content-Type to text/plain.\n */\nexport class TextResponse extends SuccessResponse {\n constructor(\n body: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n charset: string = UTF8_CHARSET,\n ) {\n super(body, cache, status);\n this.mediaType = withCharset(MediaType.PLAIN_TEXT, charset);\n }\n}\n\n/**\n * Represents an HTTP response for serving binary data as `application/octet-stream`.\n *\n * This class wraps a `ReadableStream` and sets all necessary headers for both\n * full and partial content responses, handling range requests in a hybrid way\n * to maximize browser and CDN caching.\n *\n * Key behaviors:\n * - `Content-Type` is set to `application/octet-stream`.\n * - `Accept-Ranges: bytes` is always included.\n * - `Content-Length` is always set to the validated length of the response body.\n * - If the request is a true partial range (offset > 0 or length < size), the response\n * will be `206 Partial Content` with the appropriate `Content-Range` header.\n * - If the requested range covers the entire file (even if a Range header is present),\n * the response will return `200 OK` to enable browser and edge caching.\n * - Zero-length streams (`size = 0`) are never treated as partial.\n * - Special case: a requested range of `0-0` on a non-empty file is normalized to 1 byte.\n */\nexport class OctetStream extends WorkerResponse {\n constructor(stream: ReadableStream, init: OctetStreamInit, cache?: CacheControl) {\n assertOctetStreamInit(init);\n\n super(stream, cache);\n this.mediaType = MediaType.OCTET_STREAM;\n\n const normalized = OctetStream.normalizeInit(init);\n const { size, offset, length } = normalized;\n\n if (OctetStream.isPartial(normalized)) {\n this.setHeader(\n HttpHeader.CONTENT_RANGE,\n `bytes ${offset}-${offset + length - 1}/${size}`,\n );\n this.status = StatusCodes.PARTIAL_CONTENT;\n }\n\n this.setHeader(HttpHeader.ACCEPT_RANGES, \"bytes\");\n this.setHeader(HttpHeader.CONTENT_LENGTH, `${length}`);\n }\n\n /**\n * Normalizes a partially-specified `OctetStreamInit` into a fully-specified object.\n *\n * Ensures that all required fields (`size`, `offset`, `length`) are defined:\n * - `offset` defaults to 0 if not provided.\n * - `length` defaults to `size - offset` if not provided.\n * - Special case: if `offset` and `length` are both 0 but `size > 0`, `length` is set to 1\n * to avoid zero-length partial streams.\n *\n * @param init - The initial `OctetStreamInit` object, possibly with missing `offset` or `length`.\n * @returns A fully-specified `OctetStreamInit` object with `size`, `offset`, and `length` guaranteed.\n */\n private static normalizeInit(init: OctetStreamInit): Required<OctetStreamInit> {\n const { size } = init;\n const offset = init.offset ?? 0;\n let length = init.length ?? size - offset;\n\n if (offset === 0 && length === 0 && size > 0) {\n length = 1;\n }\n\n return { size, offset, length };\n }\n\n /**\n * Determines whether the given `OctetStreamInit` represents a partial range.\n *\n * Partial ranges are defined as any range that does **not** cover the entire file:\n * - If `size === 0`, the stream is never partial.\n * - If `offset === 0` and `length === size`, the stream is treated as a full file (not partial),\n * even if a Range header is present. This enables browser and CDN caching.\n * - All other cases are considered partial, and will result in a `206 Partial Content` response.\n *\n * @param init - A fully-normalized `OctetStreamInit` object.\n * @returns `true` if the stream represents a partial range; `false` if it represents the full file.\n */\n private static isPartial(init: Required<OctetStreamInit>): boolean {\n if (init.size === 0) return false;\n return !(init.offset === 0 && init.length === init.size);\n }\n}\n\n/**\n * A streaming response for Cloudflare R2 objects.\n *\n * **Partial content support:** To enable HTTP 206 streaming, you must provide\n * request headers containing the `Range` header when calling the R2 bucket's `get()` method.\n *\n * Example:\n * ```ts\n * const stream = await this.env.R2_BUCKET.get(\"key\", { range: this.request.headers });\n * ```\n *\n * @param source - The R2 object to stream.\n * @param cache - Optional caching override.\n */\nexport class R2ObjectStream extends OctetStream {\n constructor(source: R2ObjectBody, cache?: CacheControl) {\n let useCache = cache;\n if (!useCache && source.httpMetadata?.cacheControl) {\n useCache = CacheControl.parse(source.httpMetadata.cacheControl);\n }\n\n super(source.body, R2ObjectStream.computeRange(source.size, source.range), useCache);\n\n this.setHeader(HttpHeader.ETAG, source.httpEtag);\n\n if (source.httpMetadata?.contentType) {\n this.mediaType = source.httpMetadata.contentType;\n }\n }\n\n /**\n * Computes an `OctetStreamInit` object from a given R2 range.\n *\n * This function normalizes a Cloudflare R2 `R2Range` into the shape expected\n * by `OctetStream`. It handles the following cases:\n *\n * - No range provided: returns `{ size }` (full content).\n * - `suffix` range: calculates the offset and length from the end of the file.\n * - Explicit `offset` and/or `length`: passed through as-is.\n *\n * @param size - The total size of the file/object.\n * @param range - Optional range to extract (from R2). Can be:\n * - `{ offset: number; length?: number }`\n * - `{ offset?: number; length: number }`\n * - `{ suffix: number }`\n * @returns An `OctetStreamInit` object suitable for `OctetStream`.\n */\n private static computeRange(size: number, range?: R2Range): OctetStreamInit {\n if (!range) return { size };\n\n if (\"suffix\" in range) {\n const offset = Math.max(0, size - range.suffix);\n const length = size - offset;\n return { size, offset, length };\n }\n\n return { size, ...range };\n }\n}\n\n/**\n * Response for WebSocket upgrade requests.\n * Automatically sets status to 101 and attaches the client socket.\n */\nexport class WebSocketUpgrade extends WorkerResponse {\n constructor(client: WebSocket) {\n super();\n this.status = StatusCodes.SWITCHING_PROTOCOLS;\n this.webSocket = client;\n }\n}\n\n/**\n * Response for `HEAD` requests. Copy headers and status from a `GET` response\n * without the body.\n */\nexport class Head extends WorkerResponse {\n constructor(get: Response) {\n super();\n this.status = get.status;\n this.statusText = get.statusText;\n this.headers = new Headers(get.headers);\n }\n}\n\n/**\n * Response for `OPTIONS` requests.\n */\nexport class Options extends WorkerResponse {\n constructor(worker: Worker) {\n const allowed = Array.from(new Set([GET, HEAD, ...worker.getAllowedMethods()]));\n assertMethods(allowed);\n\n super();\n this.status = StatusCodes.NO_CONTENT;\n this.setHeader(HttpHeader.ALLOW, allowed);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getReasonPhrase } from \"http-status-codes/build/es/utils-functions\";\n\nimport { StatusCodes } from \"./constants\";\nimport { CacheControl } from \"./constants/cache\";\nimport { HttpHeader } from \"./constants/headers\";\nimport { assertMethods } from \"./guards/methods\";\nimport { ErrorJson } from \"./interfaces/error\";\nimport { Worker } from \"./interfaces/worker\";\nimport { WS_VERSION } from \"./middleware/websocket/constants\";\nimport { JsonResponse } from \"./responses\";\n\n/**\n * Generic HTTP error response.\n * Sends a JSON body with status, error message, and details.\n */\nexport class HttpError extends JsonResponse {\n /**\n * @param worker The worker handling the request.\n * @param status HTTP status code.\n * @param details Optional detailed error message.\n */\n constructor(\n status: StatusCodes,\n protected readonly details?: string,\n ) {\n const json: ErrorJson = {\n status,\n error: getReasonPhrase(status),\n details: details ?? \"\",\n };\n super(json, CacheControl.DISABLE, status);\n }\n}\n\n/**\n * Creates a structured error response without exposing the error\n * details to the client. Links the sent response to the logged\n * error via a generated correlation ID.\n *\n * Status defaults to 500 Internal Server Error.\n */\nexport class LoggedHttpError extends HttpError {\n constructor(error: unknown, status: StatusCodes = StatusCodes.INTERNAL_SERVER_ERROR) {\n const uuid = crypto.randomUUID();\n console.error(uuid, error);\n super(status, uuid);\n }\n}\n\n/** 400 Bad Request error response. */\nexport class BadRequest extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.BAD_REQUEST, details);\n }\n}\n\n/** 401 Unauthorized error response. */\nexport class Unauthorized extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.UNAUTHORIZED, details);\n }\n}\n\n/** 403 Forbidden error response. */\nexport class Forbidden extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.FORBIDDEN, details);\n }\n}\n\n/** 404 Not Found error response. */\nexport class NotFound extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.NOT_FOUND, details);\n }\n}\n\n/** 405 Method Not Allowed error response. */\nexport class MethodNotAllowed extends HttpError {\n constructor(worker: Worker) {\n const methods = worker.getAllowedMethods();\n assertMethods(methods);\n\n super(StatusCodes.METHOD_NOT_ALLOWED, `${worker.request.method} method not allowed.`);\n this.setHeader(HttpHeader.ALLOW, methods);\n }\n}\n\n/** 412 Precondition Failed error response */\nexport class PreconditionFailed extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.PRECONDITION_FAILED, details);\n }\n}\n\n/** 426 Upgrade Required error response. */\nexport class UpgradeRequired extends HttpError {\n constructor() {\n super(StatusCodes.UPGRADE_REQUIRED);\n this.setHeader(HttpHeader.SEC_WEBSOCKET_VERSION, WS_VERSION);\n }\n}\n\n/** 500 Internal Server Error response. */\nexport class InternalServerError extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.INTERNAL_SERVER_ERROR, details);\n }\n}\n\n/** 501 Not Implemented error response. */\nexport class NotImplemented extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.NOT_IMPLEMENTED, details);\n }\n}\n\n/** 501 Method Not Implemented error response for unsupported HTTP methods. */\nexport class MethodNotImplemented extends NotImplemented {\n constructor(worker: Worker) {\n super(`${worker.request.method} method not implemented.`);\n }\n}\n\n/** 503 Service Unavailable error response. */\nexport class ServiceUnavailable extends HttpError {\n constructor(details?: string) {\n super(StatusCodes.SERVICE_UNAVAILABLE, details);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Middleware } from \"../interfaces/middleware\";\n\n/**\n * Asserts at runtime that a value implements the `Middleware` interface.\n *\n * @param value - The value to check.\n * @throws TypeError If `handler` does not have a `handle` method.\n */\nexport function assertMiddleware(value: unknown): asserts value is Middleware {\n if (\n value === null ||\n typeof value !== \"object\" ||\n typeof (value as Middleware).handle !== \"function\"\n ) {\n throw new TypeError(\n \"Handler must implement the Middleware interface (have a handle method).\",\n );\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { GET, HEAD, Method } from \"../constants/methods\";\nimport { assertMethods, isMethod } from \"../guards/methods\";\nimport { FetchHandler } from \"../interfaces/fetch\";\nimport { Worker, WorkerClass } from \"../interfaces/worker\";\n\n/**\n * Provides the foundational structure for handling requests,\n * environment bindings, and the worker execution context.\n *\n * Features:\n * - Holds the current `Request` object (`request` getter).\n * - Provides access to environment bindings (`env` getter).\n * - Provides access to the worker execution context (`ctx` getter).\n * - Subclasses must implement `fetch()` to process the request.\n */\nexport abstract class BaseWorker implements Worker {\n constructor(\n private readonly _request: Request,\n private readonly _env: Env,\n private readonly _ctx: ExecutionContext,\n ) {}\n\n /** The Request object associated with this worker invocation */\n public get request(): Request {\n return this._request;\n }\n\n /** Environment bindings (e.g., KV, secrets, or other globals) */\n public get env(): Env {\n return this._env;\n }\n\n /** Execution context for background tasks or `waitUntil` */\n public get ctx(): ExecutionContext {\n return this._ctx;\n }\n\n /**\n * Dispatches the incoming request to the appropriate handler and produces a response.\n *\n * Subclasses must implement this method to define how the worker generates a `Response`\n * for the current request. This is the central point where request processing occurs.\n *\n * @returns A Promise that resolves to the `Response` for the request.\n */\n protected abstract dispatch(): Promise<Response>;\n\n /**\n * Determines whether a given HTTP method is allowed for this worker.\n *\n * - GET and HEAD are **always allowed**, in compliance with RFC 9110,\n * even if they are not explicitly listed in `getAllowedMethods()`.\n * - Other methods are allowed only if included in the array returned by\n * `getAllowedMethods()` and are valid HTTP methods.\n *\n * @param method - The HTTP method to check (e.g., \"GET\", \"POST\").\n * @returns `true` if the method is allowed, `false` otherwise.\n */\n public isAllowed(method: string): boolean {\n const methods = this.getAllowedMethods();\n assertMethods(methods);\n\n // GET and HEAD are always allowed per RFC\n if (method === GET || method === HEAD) return true;\n\n return isMethod(method) && methods.includes(method);\n }\n\n public abstract getAllowedMethods(): Method[];\n\n /**\n * Creates a new instance of the current Worker subclass.\n *\n * @param request - The {@link Request} to pass to the new worker instance.\n * @returns A new worker instance of the same subclass as `this`.\n */\n protected create(request: Request): this {\n const ctor = this.constructor as WorkerClass<this>;\n return new ctor(request, this.env, this.ctx);\n }\n\n /**\n * Process the {@link Request} and produce a {@link Response}.\n *\n * @returns A {@link Response} promise for the {@link Request}.\n */\n public abstract fetch(): Promise<Response>;\n\n /**\n * Simplify and standardize {@link Response} creation by extending {@link WorkerResponse}\n * or any of its subclasses and passing to this method.\n *\n * Or directly use any of the built-in classes.\n *\n * ```ts\n * this.response(TextResponse, \"Hello World!\")\n * ```\n *\n * @param ResponseClass The response class to instantiate\n * @param args Additional constructor arguments\n * @returns A Promise resolving to the {@link Response} object\n */\n protected response<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Ctor extends new (...args: any[]) => { response(): Promise<Response> },\n >(ResponseClass: Ctor, ...args: ConstructorParameters<Ctor>): Promise<Response> {\n return new ResponseClass(...args).response();\n }\n\n /**\n * **Ignite** your `Worker` implementation into a Cloudflare handler.\n *\n * @returns A `FetchHandler` that launches a new worker instance for each request.\n *\n * ```ts\n * export default MyWorker.ignite();\n * ```\n */\n public static ignite<W extends Worker>(this: WorkerClass<W>): FetchHandler {\n return {\n fetch: (request: Request, env: Env, ctx: ExecutionContext) =>\n new this(request, env, ctx).fetch(),\n };\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { MethodNotAllowed } from \"../errors\";\nimport { assertMiddleware } from \"../guards/middleware\";\nimport { Middleware } from \"../interfaces/middleware\";\n\nimport { BaseWorker } from \"./base\";\n\n/** Base worker for handling middleware chains. */\nexport abstract class MiddlewareWorker extends BaseWorker {\n /** Middleware handlers registered for this worker. */\n protected readonly middlewares: Middleware[] = [];\n\n /**\n * Hook for subclasses to perform any initialization.\n */\n protected init(): void | Promise<void> {\n return;\n }\n\n /**\n * Add one or more middleware instances to this worker.\n *\n * The middleware will run for every request handled by this worker,\n * in the order they are added.\n *\n * @param middleware - One or more middleware instances to run.\n * @returns `this` to allow chaining multiple `.use()` calls.\n */\n public use(...middleware: Middleware[]): this {\n for (const value of middleware) {\n assertMiddleware(value);\n }\n\n this.middlewares.push(...middleware);\n return this;\n }\n\n /**\n * Executes the middleware chain and dispatches the request if the method\n * is allowed by the worker.\n *\n * @returns The Response produced by the last middleware or `dispatch()`.\n */\n public override async fetch(): Promise<Response> {\n /**\n * Allow subclasses to add middleware to be used for the request.\n */\n await this.init();\n\n const chain = this.middlewares.reduceRight(\n (next, handler) => () => handler.handle(this, next),\n () => {\n if (!this.isAllowed(this.request.method)) {\n return this.response(MethodNotAllowed, this);\n }\n return this.dispatch();\n },\n );\n return chain();\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { GET, HEAD, Method, OPTIONS } from \"../constants/methods\";\nimport { LoggedHttpError, MethodNotAllowed, MethodNotImplemented, NotFound } from \"../errors\";\nimport { Head, Options } from \"../responses\";\n\nimport { MiddlewareWorker } from \"./middleware\";\n\n/**\n * Basic worker class providing HTTP method dispatching and error handling.\n */\nexport abstract class BasicWorker extends MiddlewareWorker {\n /**\n * Entry point to handle a fetch request.\n */\n public override async fetch(): Promise<Response> {\n try {\n return await super.fetch();\n } catch (error) {\n return this.response(LoggedHttpError, error);\n }\n }\n\n /**\n * Dispatches the request to the method-specific handler.\n */\n protected override dispatch(): Promise<Response> {\n const method = this.request.method as Method;\n const handler: Record<Method, () => Promise<Response>> = {\n GET: () => this.get(),\n PUT: () => this.put(),\n HEAD: () => this.head(),\n POST: () => this.post(),\n PATCH: () => this.patch(),\n DELETE: () => this.delete(),\n OPTIONS: () => this.options(),\n };\n\n return (handler[method] ?? (() => this.response(MethodNotAllowed, this)))();\n }\n\n /** Override and implement this method for `GET` requests. */\n protected get(): Promise<Response> {\n return this.response(NotFound);\n }\n\n /** Override and implement this method for `PUT` requests. */\n protected put(): Promise<Response> {\n return this.response(MethodNotImplemented, this);\n }\n\n /** Override and implement this method for `POST` requests. */\n protected post(): Promise<Response> {\n return this.response(MethodNotImplemented, this);\n }\n\n /** Override and implement this method for `PATCH` requests. */\n protected patch(): Promise<Response> {\n return this.response(MethodNotImplemented, this);\n }\n\n /** Override and implement this method for `DELETE` requests. */\n protected delete(): Promise<Response> {\n return this.response(MethodNotImplemented, this);\n }\n\n /** Returns the default `OPTIONS` response. */\n protected options(): Promise<Response> {\n return this.response(Options, this);\n }\n\n /**\n * Default handler for `HEAD` requests.\n * Performs a `GET` request and removes the body for `HEAD` semantics.\n *\n * Usually does not need to be overridden as this behavior covers\n * standard `HEAD` requirements.\n */\n protected async head(): Promise<Response> {\n const worker = this.create(\n new Request(this.request.url, { method: GET, headers: this.request.headers }),\n );\n return this.response(Head, await worker.fetch());\n }\n\n /**\n * Returns the HTTP methods allowed by this worker.\n *\n * - GET and HEAD are always allowed per RFC 9110, even if subclasses do not include them here.\n * - OPTIONS is included by default since a default handler is implemented.\n * - Subclasses can override this method to allow additional methods or change the defaults.\n */\n public getAllowedMethods(): Method[] {\n return [GET, HEAD, OPTIONS];\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { match } from \"path-to-regexp\";\n\nimport { Method } from \"./constants/methods\";\nimport { MatchedRoute, PathParams, Route, RouteTable } from \"./interfaces/route\";\n\n/**\n * Container for route definitions and matching logic.\n * Implements Iterable to allow iteration over all routes.\n */\nexport class Routes implements Iterable<Route> {\n /** Internal array of registered routes */\n private readonly routes: Route[] = [];\n\n /**\n * Add routes to the router.\n *\n * Accepts any iterable of [method, path, handler] tuples.\n * This includes arrays, Sets, or generators.\n *\n * @param routes - Iterable of route tuples to add.\n */\n public add(routes: RouteTable): void {\n for (const [method, path, handler] of routes) {\n const matcher = match<PathParams>(path);\n this.routes.push({ method, matcher, handler });\n }\n }\n\n /**\n * Attempt to match a URL against the registered routes.\n *\n * @param method - HTTP method of the request\n * @param url - Full URL string to match against\n * @returns A MatchedRoute object if a route matches, otherwise null\n */\n public match(method: Method, url: string): MatchedRoute | null {\n const pathname = new URL(url).pathname;\n\n for (const route of this) {\n if (route.method !== method) continue;\n\n const found = route.matcher(pathname);\n if (found) return { route, params: found.params };\n }\n\n return null;\n }\n\n /**\n * Iterate over all registered routes.\n */\n public *[Symbol.iterator](): Iterator<Route> {\n yield* this.routes;\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Method } from \"../constants/methods\";\nimport { NotFound } from \"../errors\";\nimport { RouteHandler, RouteTable } from \"../interfaces/route\";\nimport { WorkerClass } from \"../interfaces/worker\";\nimport { Routes } from \"../routes\";\n\nimport { BaseWorker } from \"./base\";\nimport { BasicWorker } from \"./basic\";\n\n/**\n * Base worker supporting route-based request handling.\n *\n * Subclass `RouteWorker` to define a worker with multiple route handlers.\n *\n * Routes can be registered individually via `route()` or in bulk via `routes()`.\n */\nexport abstract class RouteWorker extends BasicWorker {\n /** Internal table of registered routes. */\n private readonly _routes: Routes = new Routes();\n\n /**\n * Registers a single new route in the worker.\n *\n * When a request matches the specified method and path, the provided handler\n * will be executed. The handler can be either:\n * - A function that receives URL parameters, or\n * - A Worker subclass that will handle the request.\n *\n * @param method - HTTP method for the route (`GET`, `POST`, etc.).\n * @param path - URL path pattern (path-to-regexp, e.g., \"/users/:id\").\n * @param handler - The function or Worker class to run when the route matches.\n * @returns The current worker instance, allowing method chaining.\n */\n protected route(method: Method, path: string, handler: RouteHandler): this {\n this.routes([[method, path, handler]]);\n return this;\n }\n\n /**\n * Registers multiple routes at once in the worker.\n *\n * Each route should be a tuple `[method, path, handler]` where:\n * - `method` - HTTP method for the route (`GET`, `POST`, etc.).\n * - `path` - URL path pattern (path-to-regexp e.g., \"/users/:id\").\n * - `handler` - A function that receives URL parameters or a Worker subclass\n * that will handle the request.\n *\n * @param routes - An iterable of routes to register. Each item is a `[method, path, handler]` tuple.\n * @returns The current worker instance, allowing method chaining.\n */\n protected routes(routes: RouteTable): this {\n this._routes.add(routes);\n return this;\n }\n\n /**\n * Matches the incoming request against registered routes and dispatches it.\n *\n * If a route is found:\n * - If the handler is a Worker class, a new instance is created and its `fetch()` is called.\n * - If the handler is a callback function, it is invoked with the extracted path parameters.\n *\n * If no route matches, the request is passed to the superclass ({@link BasicWorker})\n * `dispatch()` handler.\n *\n * @returns A `Promise<Response>` from the matched handler or parent dispatch.\n */\n protected override async dispatch(): Promise<Response> {\n const found = this._routes.match(this.request.method as Method, this.request.url);\n if (!found) return super.dispatch();\n\n const { handler } = found.route;\n if (RouteWorker.isWorkerClass(handler)) {\n return new handler(this.request, this.env, this.ctx).fetch();\n }\n return handler.call(this, found.params);\n }\n\n /**\n * Runtime type guard to check if a given handler is a Worker class.\n *\n * A Worker class is any class that extends `BaseWorker`.\n *\n * @param handler - The constructor function to test.\n * @returns `true` if `handler` is a subclass of `BaseWorker` at runtime, `false` otherwise.\n */\n private static isWorkerClass(handler: RouteHandler): handler is WorkerClass {\n return Object.prototype.isPrototypeOf.call(BaseWorker.prototype, handler.prototype);\n }\n\n protected override put(): Promise<Response> {\n return this.response(NotFound);\n }\n\n protected override post(): Promise<Response> {\n return this.response(NotFound);\n }\n\n protected override patch(): Promise<Response> {\n return this.response(NotFound);\n }\n\n protected override delete(): Promise<Response> {\n return this.response(NotFound);\n }\n}\n"]}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard HTTP request methods.
|
|
3
|
+
*/
|
|
4
|
+
declare enum Method {
|
|
5
|
+
GET = "GET",
|
|
6
|
+
PUT = "PUT",
|
|
7
|
+
HEAD = "HEAD",
|
|
8
|
+
POST = "POST",
|
|
9
|
+
PATCH = "PATCH",
|
|
10
|
+
DELETE = "DELETE",
|
|
11
|
+
OPTIONS = "OPTIONS"
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Shorthand constants for each HTTP method.
|
|
15
|
+
*
|
|
16
|
+
* These are equivalent to the corresponding enum members in `Method`.
|
|
17
|
+
* For example, `GET === Method.GET`.
|
|
18
|
+
*/
|
|
19
|
+
declare const GET: Method;
|
|
20
|
+
declare const PUT: Method;
|
|
21
|
+
declare const HEAD: Method;
|
|
22
|
+
declare const POST: Method;
|
|
23
|
+
declare const PATCH: Method;
|
|
24
|
+
declare const DELETE: Method;
|
|
25
|
+
declare const OPTIONS: Method;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Represents the constructor of a Worker subclass.
|
|
29
|
+
*
|
|
30
|
+
* @template T - The specific type of Worker being constructed. Defaults to `Worker`.
|
|
31
|
+
* @param req - The `Request` object to be handled by the worker instance.
|
|
32
|
+
* @param env - The environment bindings available to the worker.
|
|
33
|
+
* @param ctx - The `ExecutionContext` for the worker invocation.
|
|
34
|
+
* @returns An instance of the worker type `T`.
|
|
35
|
+
*/
|
|
36
|
+
type WorkerClass<T extends Worker = Worker> = new (request: Request, env: Env, ctx: ExecutionContext) => T;
|
|
37
|
+
/**
|
|
38
|
+
* Defines the contract for a Cloudflare-compatible Worker.
|
|
39
|
+
*
|
|
40
|
+
* Implementations are responsible for handling incoming requests,
|
|
41
|
+
* providing access to the request, environment bindings, and
|
|
42
|
+
* execution context.
|
|
43
|
+
*/
|
|
44
|
+
interface Worker {
|
|
45
|
+
/**
|
|
46
|
+
* Processes the incoming {@link Request} and produces a {@link Response}.
|
|
47
|
+
*
|
|
48
|
+
* @returns A Promise that resolves to the HTTP {@link Response}.
|
|
49
|
+
*/
|
|
50
|
+
fetch(): Promise<Response>;
|
|
51
|
+
/**
|
|
52
|
+
* The original {@link Request} being processed by this worker instance.
|
|
53
|
+
*/
|
|
54
|
+
get request(): Request;
|
|
55
|
+
/**
|
|
56
|
+
* The environment bindings provided at runtime (e.g., KV, R2, secrets).
|
|
57
|
+
*/
|
|
58
|
+
get env(): Env;
|
|
59
|
+
/**
|
|
60
|
+
* The {@link ExecutionContext} associated with the current request,
|
|
61
|
+
* used to manage background tasks and request lifecycle.
|
|
62
|
+
*/
|
|
63
|
+
get ctx(): ExecutionContext;
|
|
64
|
+
/**
|
|
65
|
+
* Returns the list of HTTP methods that are allowed for this worker.
|
|
66
|
+
*
|
|
67
|
+
* @returns An array of allowed HTTP methods.
|
|
68
|
+
*/
|
|
69
|
+
getAllowedMethods(): Method[];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Middleware interface for request/response processing.
|
|
74
|
+
*
|
|
75
|
+
* Middleware objects implement logic that can process requests and responses
|
|
76
|
+
* in a chainable manner. Each middleware receives a `Worker` object and a
|
|
77
|
+
* `next` function that invokes the next middleware in the chain.
|
|
78
|
+
*
|
|
79
|
+
* Implementers **must provide** the `handle` method.
|
|
80
|
+
*
|
|
81
|
+
* Example implementation:
|
|
82
|
+
* ```ts
|
|
83
|
+
* class LoggingMiddleware implements Middleware {
|
|
84
|
+
* public async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {
|
|
85
|
+
* console.log(`Processing request: ${worker.request.url}`);
|
|
86
|
+
* const response = await next();
|
|
87
|
+
* console.log(`Response status: ${response.status}`);
|
|
88
|
+
* return response;
|
|
89
|
+
* }
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
interface Middleware {
|
|
94
|
+
/**
|
|
95
|
+
* Process a request in the middleware chain.
|
|
96
|
+
*
|
|
97
|
+
* @param worker - The `Worker` instance representing the request context.
|
|
98
|
+
* @param next - Function to invoke the next middleware in the chain.
|
|
99
|
+
* Must be called to continue the chain unless the middleware
|
|
100
|
+
* terminates early (e.g., returns a response directly).
|
|
101
|
+
* @returns A `Response` object, either returned directly or from `next()`.
|
|
102
|
+
*/
|
|
103
|
+
handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export { DELETE as D, GET as G, HEAD as H, Method as M, OPTIONS as O, PUT as P, type WorkerClass as W, type Worker as a, type Middleware as b, POST as c, PATCH as d };
|