@adonix.org/cloud-spark 0.0.113 → 0.0.115

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/index.d.ts CHANGED
@@ -515,29 +515,6 @@ declare class Routes implements Iterable<Route> {
515
515
  [Symbol.iterator](): Iterator<Route>;
516
516
  }
517
517
 
518
- /**
519
- * Abstract base class for Worker middleware.
520
- * Provides a structured pre/post pattern around the next middleware or final handler,
521
- * with optional short-circuit support.
522
- */
523
- declare abstract class Middleware {
524
- abstract handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
525
- }
526
-
527
- /**
528
- * Middleware that automatically applies CORS headers to responses.
529
- *
530
- * Uses a `CorsProvider` to determine the allowed origins, allowed headers,
531
- * exposed headers, and max age for preflight caching.
532
- *
533
- * Can be registered with a `MiddlewareWorker` or any worker that supports middleware.
534
- */
535
- declare class CorsHandler extends Middleware {
536
- private readonly provider;
537
- constructor(provider?: CorsProvider);
538
- handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
539
- }
540
-
541
518
  /**
542
519
  * A type-safe Cloudflare Worker handler.
543
520
  *
@@ -618,10 +595,10 @@ declare abstract class BaseWorker implements Worker {
618
595
  static ignite<W extends Worker>(this: WorkerConstructor<W>): FetchHandler;
619
596
  }
620
597
 
621
- /**
622
- * Worker that supports class-based middleware with optional always-run middleware.
623
- * Extends CacheWorker to include caching logic automatically.
624
- */
598
+ declare abstract class Middleware {
599
+ abstract handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
600
+ }
601
+
625
602
  declare abstract class MiddlewareWorker extends BaseWorker {
626
603
  private readonly middlewares;
627
604
  /**
@@ -724,18 +701,17 @@ declare abstract class RouteWorker extends BasicWorker {
724
701
  protected delete(): Promise<Response>;
725
702
  }
726
703
 
704
+ declare class CorsHandler extends Middleware {
705
+ private readonly provider;
706
+ constructor(init?: CorsProvider | CorsConfig);
707
+ handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
708
+ }
709
+
727
710
  declare class CacheHandler extends Middleware {
711
+ protected readonly cacheName?: string | undefined;
712
+ protected readonly getKey?: ((request: Request) => URL | RequestInfo) | undefined;
713
+ constructor(cacheName?: string | undefined, getKey?: ((request: Request) => URL | RequestInfo) | undefined);
728
714
  handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
729
- /**
730
- * Returns the cache key for the request.
731
- *
732
- * Behavior:
733
- * - By default, returns the normalized request URL.
734
- * - Query parameters are normalized so that the order does not affect the cache key.
735
- * For example, `?a=1&b=2` and `?b=2&a=1` produce the same cache key.
736
- *
737
- * @returns {URL | RequestInfo} The URL or RequestInfo used as the cache key.
738
- */
739
715
  getCacheKey(request: Request): URL | RequestInfo;
740
716
  }
741
717
 
package/dist/index.js CHANGED
@@ -467,27 +467,6 @@ var Routes = class {
467
467
  }
468
468
  };
469
469
 
470
- // src/middleware.ts
471
- var Middleware = class {
472
- };
473
-
474
- // src/cors-handler.ts
475
- var CorsHandler = class extends Middleware {
476
- constructor(provider = new CorsProvider(DEFAULT_CORS_CONFIG)) {
477
- super();
478
- this.provider = provider;
479
- }
480
- async handle(worker, next) {
481
- const response = await next();
482
- const mutable = new Response(response.body, response);
483
- addCorsHeaders(worker, this.provider, mutable.headers);
484
- if (!allowAnyOrigin(this.provider)) {
485
- mergeHeader(mutable.headers, "Vary", "Origin");
486
- }
487
- return mutable;
488
- }
489
- };
490
-
491
470
  // src/base-worker.ts
492
471
  var BaseWorker = class {
493
472
  constructor(_request, _env, _ctx) {
@@ -708,33 +687,53 @@ var RouteWorker = class extends BasicWorker {
708
687
  }
709
688
  };
710
689
 
711
- // src/cache-handler.ts
690
+ // src/middleware/middleware.ts
691
+ var Middleware = class {
692
+ };
693
+
694
+ // src/middleware/cors-handler.ts
695
+ var CorsHandler = class extends Middleware {
696
+ provider;
697
+ constructor(init) {
698
+ super();
699
+ if (init) {
700
+ this.provider = init instanceof CorsProvider ? init : new CorsProvider(init);
701
+ } else {
702
+ this.provider = new CorsProvider();
703
+ }
704
+ }
705
+ async handle(worker, next) {
706
+ const response = await next();
707
+ const mutable = new Response(response.body, response);
708
+ addCorsHeaders(worker, this.provider, mutable.headers);
709
+ if (!allowAnyOrigin(this.provider)) {
710
+ mergeHeader(mutable.headers, "Vary", "Origin");
711
+ }
712
+ return mutable;
713
+ }
714
+ };
715
+
716
+ // src/middleware/cache-handler.ts
712
717
  var CacheHandler = class extends Middleware {
718
+ constructor(cacheName, getKey) {
719
+ super();
720
+ this.cacheName = cacheName;
721
+ this.getKey = getKey;
722
+ }
713
723
  async handle(worker, next) {
724
+ const cache = this.cacheName ? await caches.open(this.cacheName) : caches.default;
714
725
  if (worker.request.method === "GET" /* GET */) {
715
- const cached = await caches.default.match(this.getCacheKey(worker.request));
726
+ const cached = await cache.match(this.getCacheKey(worker.request));
716
727
  if (cached) return cached;
717
728
  }
718
729
  const response = await next();
719
730
  if (response.ok && worker.request.method === "GET" /* GET */) {
720
- worker.ctx.waitUntil(
721
- caches.default.put(this.getCacheKey(worker.request), response.clone())
722
- );
731
+ worker.ctx.waitUntil(cache.put(this.getCacheKey(worker.request), response.clone()));
723
732
  }
724
733
  return response;
725
734
  }
726
- /**
727
- * Returns the cache key for the request.
728
- *
729
- * Behavior:
730
- * - By default, returns the normalized request URL.
731
- * - Query parameters are normalized so that the order does not affect the cache key.
732
- * For example, `?a=1&b=2` and `?b=2&a=1` produce the same cache key.
733
- *
734
- * @returns {URL | RequestInfo} The URL or RequestInfo used as the cache key.
735
- */
736
735
  getCacheKey(request) {
737
- return normalizeUrl(request.url);
736
+ return this.getKey ? this.getKey(request) : normalizeUrl(request.url);
738
737
  }
739
738
  };
740
739
  export {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/common.ts","../src/cors.ts","../src/errors.ts","../src/response.ts","../src/routes.ts","../src/middleware.ts","../src/cors-handler.ts","../src/base-worker.ts","../src/middleware-worker.ts","../src/basic-worker.ts","../src/route-worker.ts","../src/cache-handler.ts"],"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 Cache-Control 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/**\n * https://github.com/prettymuchbryce/http-status-codes\n */\nexport { StatusCodes } from \"http-status-codes\";\n\n/**\n * Standard HTTP header names and common values.\n */\nexport namespace HttpHeader {\n export const VARY = \"Vary\";\n export const ALLOW = \"Allow\";\n export const CONTENT_TYPE = \"Content-Type\";\n export const CACHE_CONTROL = \"Cache-Control\";\n\n // Security Headers\n export const X_FRAME_OPTIONS = \"X-Frame-Options\"; // e.g. \"DENY\" or \"SAMEORIGIN\"\n export const X_CONTENT_TYPE_OPTIONS = \"X-Content-Type-Options\"; // usually \"nosniff\"\n export const REFERRER_POLICY = \"Referrer-Policy\"; // e.g. \"no-referrer\", \"strict-origin-when-cross-origin\"\n export const PERMISSIONS_POLICY = \"Permissions-Policy\"; // formerly Feature-Policy, controls APIs like geolocation/camera\n export const CONTENT_SECURITY_POLICY = \"Content-Security-Policy\"; // fine-grained script/style/image restrictions\n export const STRICT_TRANSPORT_SECURITY = \"Strict-Transport-Security\"; // e.g. \"max-age=63072000; includeSubDomains; preload\"\n\n // Values\n export const NOSNIFF = \"nosniff\";\n export const ORIGIN = \"Origin\";\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/**\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}\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: string): value is Method {\n return METHOD_SET.has(value);\n}\n\n/**\n * Returns the proper Content-Type string for a given media type.\n * Appends `charset=utf-8` for text-based types that require it.\n *\n * @param type - The media type.\n * @returns A string suitable for the `Content-Type` header.\n */\nexport function getContentType(type: MediaType): string {\n if (ADD_CHARSET.has(type)) {\n return `${type}; charset=utf-8`;\n }\n return type;\n}\n\n/**\n * Common media types types used for HTTP headers.\n */\nexport enum MediaType {\n PLAIN_TEXT = \"text/plain\",\n HTML = \"text/html\",\n CSS = \"text/css\",\n CSV = \"text/csv\",\n XML = \"text/xml\",\n MARKDOWN = \"text/markdown\",\n RICH_TEXT = \"text/richtext\",\n JSON = \"application/json\",\n XML_APP = \"application/xml\",\n YAML = \"application/x-yaml\",\n FORM_URLENCODED = \"application/x-www-form-urlencoded\",\n NDJSON = \"application/x-ndjson\",\n MSGPACK = \"application/x-msgpack\",\n PROTOBUF = \"application/x-protobuf\",\n MULTIPART_FORM_DATA = \"multipart/form-data\",\n MULTIPART_MIXED = \"multipart/mixed\",\n MULTIPART_ALTERNATIVE = \"multipart/alternative\",\n MULTIPART_DIGEST = \"multipart/digest\",\n MULTIPART_RELATED = \"multipart/related\",\n MULTIPART_SIGNED = \"multipart/signed\",\n MULTIPART_ENCRYPTED = \"multipart/encrypted\",\n OCTET_STREAM = \"application/octet-stream\",\n PDF = \"application/pdf\",\n ZIP = \"application/zip\",\n GZIP = \"application/gzip\",\n MSWORD = \"application/msword\",\n DOCX = \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n EXCEL = \"application/vnd.ms-excel\",\n XLSX = \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n POWERPOINT = \"application/vnd.ms-powerpoint\",\n PPTX = \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n ICO = \"image/x-icon\",\n ICO_MS = \"image/vnd.microsoft.icon\",\n GIF = \"image/gif\",\n PNG = \"image/png\",\n JPEG = \"image/jpeg\",\n WEBP = \"image/webp\",\n SVG = \"image/svg+xml\",\n HEIF = \"image/heif\",\n AVIF = \"image/avif\",\n EVENT_STREAM = \"text/event-stream\",\n TAR = \"application/x-tar\",\n BZIP2 = \"application/x-bzip2\",\n}\n\n/**\n * A set of media types that require a `charset` parameter when setting\n * the `Content-Type` header.\n *\n * This includes common text-based media types such as HTML, CSS, JSON,\n * XML, CSV, Markdown, and others.\n */\nconst ADD_CHARSET: Set<MediaType> = new Set([\n MediaType.CSS,\n MediaType.CSV,\n MediaType.XML,\n MediaType.SVG,\n MediaType.HTML,\n MediaType.JSON,\n MediaType.NDJSON,\n MediaType.XML_APP,\n MediaType.MARKDOWN,\n MediaType.RICH_TEXT,\n MediaType.PLAIN_TEXT,\n MediaType.FORM_URLENCODED,\n]);\n\n/**\n * Sets a header on the given Headers object.\n *\n * - If `value` is an array, duplicates and empty strings are removed.\n * - If the resulting value array 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 *\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) return;\n\n const existing = headers.get(key);\n if (existing) {\n const merged = existing.split(\",\").map((v) => v.trim());\n values.forEach((v) => merged.push(v.trim()));\n setHeader(headers, key, merged);\n } else {\n setHeader(headers, key, values);\n }\n}\n\n/**\n * Normalizes a URL string for use as a consistent cache key.\n *\n * - Sorts query parameters alphabetically so `?b=2&a=1` and `?a=1&b=2` are treated the same.\n * - Strips fragment identifiers (`#...`) since they are not sent in HTTP requests.\n * - Leaves protocol, host, path, and query values intact.\n *\n * @param url The original URL string to normalize.\n * @returns A normalized URL string suitable for hashing or direct cache key use.\n */\nexport function normalizeUrl(url: string): URL {\n const u = new URL(url);\n\n const params = [...u.searchParams.entries()];\n params.sort(([a], [b]) => lexCompare(a, b));\n\n u.search = params\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n u.hash = \"\";\n\n return u;\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/**\n * Extracts the `Origin` header value from a request.\n *\n * The `Origin` header identifies the origin (scheme, host, and port)\n * of the request initiator. It is commonly used for CORS checks.\n *\n * @param request - The incoming {@link Request} object.\n * @returns The origin string if present, otherwise `null`.\n */\nexport function getOrigin(request: Request): string | null {\n return request.headers.get(HttpHeader.ORIGIN);\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 { getOrigin, mergeHeader, setHeader, Time } from \"./common\";\nimport { Worker } from \"./worker\";\n\n/**\n * Default CORS configuration used by `CorsProvider`.\n *\n * By default, all origins are allowed, only `Content-Type` is allowed as a header,\n * no headers are exposed, and preflight caching is 1 week.\n *\n * @see {@link CorsConfig}\n */\nexport const DEFAULT_CORS_CONFIG: Required<CorsConfig> = {\n /** Origins allowed by default. Default: all (`*`). */\n allowedOrigins: [\"*\"],\n\n /** Allowed headers for CORS requests. Default: `Content-Type`. */\n allowedHeaders: [\"Content-Type\"],\n\n /** Headers exposed to the client. Default: none. */\n exposedHeaders: [],\n\n /** Max age (in seconds) for preflight caching. Default: 1 week. */\n maxAge: Time.Week,\n} as const;\n\n/**\n * Configuration options for `CorsProvider`.\n *\n * @see {@link DEFAULT_CORS_CONFIG}\n */\nexport interface CorsConfig {\n /** Origins allowed for CORS requests. */\n allowedOrigins?: string[];\n\n /** Allowed HTTP headers for CORS requests. */\n allowedHeaders?: string[];\n\n /** HTTP headers exposed to the client. */\n exposedHeaders?: string[];\n\n /** Max age in seconds for CORS preflight caching. */\n maxAge?: number;\n}\n\n/**\n * Provides CORS settings for a worker.\n *\n * Combines a user-supplied `CorsConfig` with defaults. Used by\n * `CorsHandler` to automatically set the appropriate headers.\n */\nexport class CorsProvider {\n private readonly config: Required<CorsConfig>;\n\n /**\n * Create a new `CorsProvider`.\n *\n * @param config - Optional configuration to override defaults.\n */\n constructor(config: CorsConfig = {}) {\n this.config = { ...DEFAULT_CORS_CONFIG, ...config };\n }\n\n /** Returns the allowed origins. Default: all (`*`). */\n public getAllowedOrigins(): string[] {\n return this.config.allowedOrigins;\n }\n\n /** Returns the allowed HTTP headers. Default: `[\"Content-Type\"]`. */\n public getAllowedHeaders(): string[] {\n return this.config.allowedHeaders;\n }\n\n /** Returns headers exposed to the client. Default: `[]`. */\n public getExposedHeaders(): string[] {\n return this.config.exposedHeaders;\n }\n\n /** Returns the max age in seconds for preflight requests. Default: 1 week. */\n public getMaxAge(): number {\n return this.config.maxAge;\n }\n}\n\n/**\n * Constants for common CORS headers.\n */\nexport namespace Cors {\n export const MAX_AGE = \"Access-Control-Max-Age\";\n export const ALLOW_ORIGIN = \"Access-Control-Allow-Origin\";\n export const ALLOW_HEADERS = \"Access-Control-Allow-Headers\";\n export const ALLOW_METHODS = \"Access-Control-Allow-Methods\";\n export const EXPOSE_HEADERS = \"Access-Control-Expose-Headers\";\n export const ALLOW_CREDENTIALS = \"Access-Control-Allow-Credentials\";\n export const ALLOW_ALL_ORIGINS = \"*\";\n}\n\n/**\n * Adds or updates CORS headers on a Headers object according to the provided policy.\n *\n * Behavior:\n * - Removes any existing CORS headers to avoid stale values.\n * - If the request has no origin, the function exits early.\n * - If wildcard `*` is allowed, sets Access-Control-Allow-Origin to `*`.\n * - If the origin is explicitly allowed, sets the correct headers including credentials.\n * - Optional headers (Expose-Headers, Allow-Headers, Allow-Methods, Max-Age) are always applied.\n *\n * @param cors The CorsProvider instance that determines allowed origins and headers\n * @param headers The Headers object to update\n */\nexport function addCorsHeaders(worker: Worker, cors: CorsProvider, headers: Headers): void {\n deleteCorsHeaders(headers);\n\n const origin = getOrigin(worker.request);\n\n // CORS is not required.\n if (!origin || origin.trim() === \"\") return;\n\n if (allowAnyOrigin(cors)) {\n setHeader(headers, Cors.ALLOW_ORIGIN, Cors.ALLOW_ALL_ORIGINS);\n } else if (cors.getAllowedOrigins().includes(origin)) {\n setHeader(headers, Cors.ALLOW_ORIGIN, origin);\n setHeader(headers, Cors.ALLOW_CREDENTIALS, \"true\");\n }\n\n // Optional headers always applied if CORS.\n setHeader(headers, Cors.MAX_AGE, String(cors.getMaxAge()));\n setHeader(headers, Cors.ALLOW_METHODS, worker.getAllowedMethods());\n setHeader(headers, Cors.ALLOW_HEADERS, cors.getAllowedHeaders());\n mergeHeader(headers, Cors.EXPOSE_HEADERS, cors.getExposedHeaders());\n}\n\n/**\n * Determines if a CORS policy allows any origin (`*`).\n *\n * @param cors - The `CorsProvider` instance to check.\n * @returns `true` if the allowed origins include `\"*\"`, otherwise `false`.\n */\nexport function allowAnyOrigin(cors: CorsProvider): boolean {\n return cors.getAllowedOrigins().includes(\"*\");\n}\n\n/**\n * Deletes all standard CORS headers from the given Headers object.\n * Useful for cleaning cached responses or resetting headers before reapplying CORS.\n *\n * @param headers The Headers object to clean\n */\nfunction deleteCorsHeaders(headers: Headers): void {\n headers.delete(Cors.MAX_AGE);\n headers.delete(Cors.ALLOW_ORIGIN);\n headers.delete(Cors.ALLOW_HEADERS);\n headers.delete(Cors.ALLOW_METHODS);\n headers.delete(Cors.EXPOSE_HEADERS);\n headers.delete(Cors.ALLOW_CREDENTIALS);\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\";\nimport { CacheControl, HttpHeader, StatusCodes } from \"./common\";\nimport { JsonResponse } from \"./response\";\nimport { Worker } from \"./worker\";\n\n/** Structure for JSON error responses. */\nexport interface ErrorJson {\n /** HTTP status code. */\n status: number;\n /** Standard HTTP reason phrase. */\n error: string;\n /** Optional detailed message about the error. */\n details: string;\n}\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(worker: Worker, status: StatusCodes, protected readonly details?: string) {\n const json: ErrorJson = {\n status,\n error: getReasonPhrase(status),\n details: details ?? \"\",\n };\n super(worker, json, CacheControl.DISABLE, status);\n }\n}\n\n/** 400 Bad Request error response. */\nexport class BadRequest extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.BAD_REQUEST, details);\n }\n}\n\n/** 401 Unauthorized error response. */\nexport class Unauthorized extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.UNAUTHORIZED, details);\n }\n}\n\n/** 403 Forbidden error response. */\nexport class Forbidden extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.FORBIDDEN, details);\n }\n}\n\n/** 404 Not Found error response. */\nexport class NotFound extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.NOT_FOUND, details);\n }\n}\n\n/** 405 Method Not Allowed error response. */\nexport class MethodNotAllowed extends HttpError {\n constructor(worker: Worker) {\n super(\n worker,\n StatusCodes.METHOD_NOT_ALLOWED,\n `${worker.request.method} method not allowed.`\n );\n this.setHeader(HttpHeader.ALLOW, this.worker.getAllowedMethods());\n }\n}\n\n/** 500 Internal Server Error response. */\nexport class InternalServerError extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.INTERNAL_SERVER_ERROR, details);\n }\n}\n\n/** 501 Not Implemented error response. */\nexport class NotImplemented extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, 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, `${worker.request.method} method not implemented.`);\n }\n}\n\n/** 503 Service Unavailable error response. */\nexport class ServiceUnavailable extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, 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 { getReasonPhrase, StatusCodes } from \"http-status-codes\";\nimport {\n CacheControl,\n getContentType,\n HttpHeader,\n mergeHeader,\n MediaType,\n setHeader,\n} from \"./common\";\nimport { Worker } from \"./worker\";\n\n/**\n * Base class for building HTTP responses.\n * Manages headers, status, and media type.\n */\nabstract class BaseResponse {\n constructor(public readonly worker: Worker) {}\n\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 media type of the response body. */\n public mediaType?: MediaType;\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 };\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 based on the media type if set. */\n public addContentType() {\n if (this.mediaType) {\n this.headers.set(HttpHeader.CONTENT_TYPE, getContentType(this.mediaType));\n }\n }\n}\n\n/**\n * Base response class that adds caching headers.\n */\nabstract class CacheResponse extends BaseResponse {\n constructor(worker: Worker, public cache?: CacheControl) {\n super(worker);\n }\n\n /** Adds Cache-Control header if caching is configured. */\n protected addCacheHeader(): void {\n if (this.cache) {\n this.headers.set(HttpHeader.CACHE_CONTROL, CacheControl.stringify(this.cache));\n }\n }\n}\n\n/**\n * Core worker response. Combines caching, and security headers.\n */\nexport abstract class WorkerResponse extends CacheResponse {\n constructor(\n worker: Worker,\n private readonly body: BodyInit | null = null,\n cache?: CacheControl\n ) {\n super(worker, cache);\n }\n\n /** Builds the Response object with body, headers, and status. */\n public async getResponse(): Promise<Response> {\n this.addCacheHeader();\n this.addSecurityHeaders();\n\n const body = this.status === StatusCodes.NO_CONTENT ? null : this.body;\n\n if (body) this.addContentType();\n return new Response(body, this.responseInit);\n }\n\n /** Adds default security headers. */\n protected addSecurityHeaders(): void {\n this.setHeader(HttpHeader.X_CONTENT_TYPE_OPTIONS, HttpHeader.NOSNIFF);\n }\n}\n\n/**\n * Wraps an existing Response and clones its body, headers, and status.\n */\nexport class ClonedResponse extends WorkerResponse {\n constructor(worker: Worker, response: Response, cache?: CacheControl) {\n const clone = response.clone();\n super(worker, clone.body, cache);\n this.headers = new Headers(clone.headers);\n this.status = clone.status;\n this.statusText = clone.statusText;\n }\n}\n\n/**\n * Represents a successful response with customizable body and status.\n */\nexport class SuccessResponse extends WorkerResponse {\n constructor(\n worker: Worker,\n body: BodyInit | null = null,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(worker, 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(\n worker: Worker,\n json: unknown = {},\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(worker, JSON.stringify(json), cache, status);\n this.mediaType = MediaType.JSON;\n }\n}\n\n/**\n * HTML response. Automatically sets Content-Type to text/html.\n */\nexport class HtmlResponse extends SuccessResponse {\n constructor(\n worker: Worker,\n body: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(worker, body, cache, status);\n this.mediaType = MediaType.HTML;\n }\n}\n\n/**\n * Plain text response. Automatically sets Content-Type to text/plain.\n */\nexport class TextResponse extends SuccessResponse {\n constructor(\n worker: Worker,\n content: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(worker, content, cache, status);\n this.mediaType = MediaType.PLAIN_TEXT;\n }\n}\n\n/**\n * Response for HEAD requests. Clones headers but has no body.\n */\nexport class Head extends WorkerResponse {\n constructor(worker: Worker, get: Response) {\n super(worker);\n this.headers = new Headers(get.headers);\n }\n}\n\n/**\n * Response for OPTIONS requests. Sets allowed methods and returns 204 No Content.\n */\nexport class Options extends SuccessResponse {\n constructor(worker: Worker) {\n super(worker, null, undefined, StatusCodes.NO_CONTENT);\n this.setHeader(HttpHeader.ALLOW, this.worker.getAllowedMethods());\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, MatchFunction } from \"path-to-regexp\";\nimport { Method } from \"./common\";\n\n/** Parameters extracted from a matched route */\nexport type RouteParams = Record<string, string>;\n\n/**\n * Type for a route callback function.\n * @param params - Named parameters extracted from the URL path.\n * @returns A Response object or a Promise resolving to a Response.\n */\nexport type RouteCallback = (params: RouteParams) => Promise<Response> | Response;\n\n/**\n * Represents a single route.\n */\nexport interface Route {\n /** HTTP method for the route */\n method: Method;\n /** Path-to-regexp matcher function for this route */\n matcher: MatchFunction<RouteParams>;\n /** Callback to execute when the route is matched */\n callback: RouteCallback;\n}\n\n/**\n * Result of a route match.\n */\nexport interface MatchedRoute {\n /** The route that matched */\n route: Route;\n /** Parameters extracted from the URL path */\n params: RouteParams;\n}\n\n/** Tuple type representing a single route: [method, path, callback] */\nexport type RouteTuple = [Method, string, RouteCallback];\n\n/** Array of route tuples, used to initialize Routes */\nexport type RouteTable = RouteTuple[];\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 * Registers all routes from the given table, replacing any existing routes.\n *\n * @param table The list of routes to register, in the form [method, path, callback].\n */\n public load(table: RouteTable): void {\n this.routes.length = 0;\n table.forEach(([method, path, callback]) => this.add(method, path, callback));\n }\n\n /**\n * Add a single route to the container.\n * @param method - HTTP method (GET, POST, etc.)\n * @param path - URL path pattern (Express-style, e.g., \"/users/:id\")\n * @param callback - Function to execute when this route matches\n */\n public add(method: Method, path: string, callback: RouteCallback) {\n const matcher = match<RouteParams>(path, {\n decode: decodeURIComponent,\n });\n this.routes.push({ method, matcher, callback });\n }\n\n /**\n * Attempt to match a URL against the registered routes.\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 { Worker } from \"./worker\";\n\n/**\n * Abstract base class for Worker middleware.\n * Provides a structured pre/post pattern around the next middleware or final handler,\n * with optional short-circuit support.\n */\nexport abstract class Middleware {\n public abstract handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;\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 { mergeHeader } from \"./common\";\nimport { addCorsHeaders, allowAnyOrigin, CorsProvider, DEFAULT_CORS_CONFIG } from \"./cors\";\nimport { Middleware } from \"./middleware\";\nimport { Worker } from \"./worker\";\n\n/**\n * Middleware that automatically applies CORS headers to responses.\n *\n * Uses a `CorsProvider` to determine the allowed origins, allowed headers,\n * exposed headers, and max age for preflight caching.\n *\n * Can be registered with a `MiddlewareWorker` or any worker that supports middleware.\n */\nexport class CorsHandler extends Middleware {\n constructor(private readonly provider: CorsProvider = new CorsProvider(DEFAULT_CORS_CONFIG)) {\n super();\n }\n\n public override async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {\n const response = await next();\n\n const mutable = new Response(response.body, response);\n\n addCorsHeaders(worker, this.provider, mutable.headers);\n if (!allowAnyOrigin(this.provider)) {\n mergeHeader(mutable.headers, \"Vary\", \"Origin\");\n }\n\n return mutable;\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 \"./common\";\nimport { Worker, WorkerConstructor } from \"./worker\";\n\n/**\n * A type-safe Cloudflare Worker handler.\n *\n * Extends `ExportedHandler` but guarantees that the `fetch` method exists\n * and has the correct signature for Cloudflare Worker invocation.\n *\n * @template E - The type of environment bindings passed to the worker. Defaults to `Env`.\n */\ninterface FetchHandler extends ExportedHandler<Env> {\n /**\n * Handles an incoming request and produces a response.\n *\n * @param request - The incoming `Request` object.\n * @param env - Environment bindings (e.g., KV namespaces, secrets, Durable Objects).\n * @param ctx - Execution context for background tasks (`waitUntil`).\n * @returns A `Promise` that resolves to the response.\n */\n fetch: (request: Request, env: Env, ctx: ExecutionContext) => Promise<Response>;\n}\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 * and where middleware chains, routing, or other custom behavior can be applied.\n *\n * @returns A Promise that resolves to the `Response` for the request.\n */\n protected abstract dispatch(): Promise<Response>;\n\n /**\n * The DEFAULT allowed HTTP methods for subclasses.\n */\n public getAllowedMethods(): Method[] {\n return [Method.GET, Method.HEAD, Method.OPTIONS];\n }\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 WorkerConstructor<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 * **Ignite** your `Worker` implementation into a Cloudflare handler.\n *\n * @returns A `FetchHandler` that launches a new worker instance for each request.\n *\n * @example\n * ```ts\n * export default MyWorker.ignite();\n * ```\n */\n public static ignite<W extends Worker>(this: WorkerConstructor<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 { BaseWorker } from \"./base-worker\";\nimport { Middleware } from \"./middleware\";\n\n/**\n * Worker that supports class-based middleware with optional always-run middleware.\n * Extends CacheWorker to include caching logic automatically.\n */\nexport abstract class MiddlewareWorker extends BaseWorker {\n private readonly middlewares: Middleware[] = [];\n\n /**\n * Register a middleware instance.\n * @param mw Middleware to register\n */\n public use(mw: Middleware): this {\n this.middlewares.push(mw);\n return this;\n }\n\n public async fetch(): Promise<Response> {\n const chain = this.middlewares.reduceRight(\n (next, mw) => () => mw.handle(this, next),\n () => this.dispatch()\n );\n return await 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 { isMethod, Method } from \"./common\";\nimport { MethodNotAllowed, InternalServerError, MethodNotImplemented } from \"./errors\";\nimport { MiddlewareWorker } from \"./middleware-worker\";\nimport { Head, Options, WorkerResponse } from \"./response\";\nimport { Worker } from \"./worker\";\n\n/**\n * Base worker class providing HTTP method dispatching, caching, and error handling.\n * Extends `CacheWorker` and defines default implementations for HTTP methods.\n */\nexport abstract class BasicWorker extends MiddlewareWorker {\n /**\n * Entry point to handle a fetch request.\n * Checks allowed methods, serves cached responses, or dispatches to the appropriate handler.\n */\n public async fetch(): Promise<Response> {\n if (!this.isAllowed(this.request.method)) {\n return this.getResponse(MethodNotAllowed);\n }\n\n try {\n this.init();\n return await super.fetch();\n } catch (error) {\n console.error(error);\n return this.getResponse(InternalServerError);\n }\n }\n\n /**\n * Dispatches the request to the method-specific handler.\n * Defaults to MethodNotAllowed if the HTTP method is not recognized.\n */\n protected async 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 return (handler[method] ?? (() => this.getResponse(MethodNotAllowed)))();\n }\n\n /**\n * Hook for subclasses to perform any initialization.\n */\n protected init(): void {\n return;\n }\n\n /**\n * Checks if the given HTTP method is allowed for this worker.\n * @param method HTTP method string\n * @returns true if the method is allowed\n */\n public isAllowed(method: string): boolean {\n return isMethod(method) && this.getAllowedMethods().includes(method);\n }\n\n /** Default handler for GET requests. Returns MethodNotImplemented unless overridden. */\n protected async get(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for PUT requests. Returns MethodNotImplemented unless overridden. */\n protected async put(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for POST requests. Returns MethodNotImplemented unless overridden. */\n protected async post(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for PATCH requests. Returns MethodNotImplemented unless overridden. */\n protected async patch(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for DELETE requests. Returns MethodNotImplemented unless overridden. */\n protected async delete(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /**\n * Default handler for OPTIONS requests.\n * Returns an Options response.\n *\n * Typically does not need to be overridden.\n */\n protected async options(): Promise<Response> {\n return this.getResponse(Options);\n }\n\n /**\n * Default handler for HEAD requests.\n * Performs a GET request internally and removes the body for HEAD semantics.\n *\n * Usually does not need to be overridden, as this behavior covers standard HEAD requirements.\n */\n protected async head(): Promise<Response> {\n const worker = this.create(new Request(this.request, { method: Method.GET }));\n return this.getResponse(Head, await worker.fetch());\n }\n\n /**\n * Helper to construct a WorkerResponse of the given class with arguments.\n * @param ResponseClass The response class to instantiate\n * @param args Additional constructor arguments\n * @returns The final Response object\n */\n protected async getResponse<\n T extends WorkerResponse,\n Ctor extends new (worker: Worker, ...args: any[]) => T\n >(\n ResponseClass: Ctor,\n ...args: ConstructorParameters<Ctor> extends [Worker, ...infer R] ? R : never\n ): Promise<Response> {\n return new ResponseClass(this, ...args).getResponse();\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 { BasicWorker } from \"./basic-worker\";\nimport { Method } from \"./common\";\nimport { NotFound } from \"./errors\";\nimport { Routes, RouteCallback, RouteTable } from \"./routes\";\n\n/**\n * Abstract worker that provides routing capabilities.\n * Extends `BasicWorker` and uses a `Routes` table to map HTTP methods and paths\n * to handler callbacks.\n */\nexport abstract class RouteWorker extends BasicWorker {\n /** Routing table used for registering and matching routes. */\n protected readonly routes: Routes = new Routes();\n\n /**\n * Loads routes from a `RouteTable` into this worker's route table.\n * @param table The table of routes to load.\n */\n protected load(table: RouteTable): void {\n this.routes.load(table);\n }\n\n /**\n * Adds a single route to this worker.\n * @param method HTTP method (GET, POST, etc.)\n * @param path Route path\n * @param callback Function to handle requests matching this route\n * @returns The worker instance (for chaining)\n */\n protected add(method: Method, path: string, callback: RouteCallback): this {\n this.routes.add(method, path, callback);\n return this;\n }\n\n /**\n * Matches the incoming request against registered routes and executes\n * the corresponding callback. Falls back to `BasicWorker.dispatch()` if no match.\n * @returns The response from the matched route or the default handler.\n */\n protected 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 return found.route.callback.call(this, found.params);\n }\n\n protected override async get(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async put(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async post(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async patch(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async delete(): Promise<Response> {\n return this.getResponse(NotFound);\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, normalizeUrl } from \"./common\";\nimport { Middleware } from \"./middleware\";\nimport { Worker } from \"./worker\";\n\nexport class CacheHandler extends Middleware {\n public override async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {\n if (worker.request.method === Method.GET) {\n const cached = await caches.default.match(this.getCacheKey(worker.request));\n if (cached) return cached; // short-circuit if cached\n }\n\n const response = await next();\n\n if (response.ok && worker.request.method === Method.GET) {\n worker.ctx.waitUntil(\n caches.default.put(this.getCacheKey(worker.request), response.clone())\n );\n }\n return response;\n }\n\n /**\n * Returns the cache key for the request.\n *\n * Behavior:\n * - By default, returns the normalized request URL.\n * - Query parameters are normalized so that the order does not affect the cache key.\n * For example, `?a=1&b=2` and `?b=2&a=1` produce the same cache key.\n *\n * @returns {URL | RequestInfo} The URL or RequestInfo used as the cache key.\n */\n public getCacheKey(request: Request): URL | RequestInfo {\n return normalizeUrl(request.url);\n }\n}\n"],"mappings":"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","names":["HttpHeader","Method","MediaType","Cors","getReasonPhrase","StatusCodes","StatusCodes","getReasonPhrase"]}
1
+ {"version":3,"sources":["../src/common.ts","../src/cors.ts","../src/errors.ts","../src/response.ts","../src/routes.ts","../src/base-worker.ts","../src/middleware-worker.ts","../src/basic-worker.ts","../src/route-worker.ts","../src/middleware/middleware.ts","../src/middleware/cors-handler.ts","../src/middleware/cache-handler.ts"],"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 Cache-Control 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/**\n * https://github.com/prettymuchbryce/http-status-codes\n */\nexport { StatusCodes } from \"http-status-codes\";\n\n/**\n * Standard HTTP header names and common values.\n */\nexport namespace HttpHeader {\n export const VARY = \"Vary\";\n export const ALLOW = \"Allow\";\n export const CONTENT_TYPE = \"Content-Type\";\n export const CACHE_CONTROL = \"Cache-Control\";\n\n // Security Headers\n export const X_FRAME_OPTIONS = \"X-Frame-Options\"; // e.g. \"DENY\" or \"SAMEORIGIN\"\n export const X_CONTENT_TYPE_OPTIONS = \"X-Content-Type-Options\"; // usually \"nosniff\"\n export const REFERRER_POLICY = \"Referrer-Policy\"; // e.g. \"no-referrer\", \"strict-origin-when-cross-origin\"\n export const PERMISSIONS_POLICY = \"Permissions-Policy\"; // formerly Feature-Policy, controls APIs like geolocation/camera\n export const CONTENT_SECURITY_POLICY = \"Content-Security-Policy\"; // fine-grained script/style/image restrictions\n export const STRICT_TRANSPORT_SECURITY = \"Strict-Transport-Security\"; // e.g. \"max-age=63072000; includeSubDomains; preload\"\n\n // Values\n export const NOSNIFF = \"nosniff\";\n export const ORIGIN = \"Origin\";\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/**\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}\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: string): value is Method {\n return METHOD_SET.has(value);\n}\n\n/**\n * Returns the proper Content-Type string for a given media type.\n * Appends `charset=utf-8` for text-based types that require it.\n *\n * @param type - The media type.\n * @returns A string suitable for the `Content-Type` header.\n */\nexport function getContentType(type: MediaType): string {\n if (ADD_CHARSET.has(type)) {\n return `${type}; charset=utf-8`;\n }\n return type;\n}\n\n/**\n * Common media types types used for HTTP headers.\n */\nexport enum MediaType {\n PLAIN_TEXT = \"text/plain\",\n HTML = \"text/html\",\n CSS = \"text/css\",\n CSV = \"text/csv\",\n XML = \"text/xml\",\n MARKDOWN = \"text/markdown\",\n RICH_TEXT = \"text/richtext\",\n JSON = \"application/json\",\n XML_APP = \"application/xml\",\n YAML = \"application/x-yaml\",\n FORM_URLENCODED = \"application/x-www-form-urlencoded\",\n NDJSON = \"application/x-ndjson\",\n MSGPACK = \"application/x-msgpack\",\n PROTOBUF = \"application/x-protobuf\",\n MULTIPART_FORM_DATA = \"multipart/form-data\",\n MULTIPART_MIXED = \"multipart/mixed\",\n MULTIPART_ALTERNATIVE = \"multipart/alternative\",\n MULTIPART_DIGEST = \"multipart/digest\",\n MULTIPART_RELATED = \"multipart/related\",\n MULTIPART_SIGNED = \"multipart/signed\",\n MULTIPART_ENCRYPTED = \"multipart/encrypted\",\n OCTET_STREAM = \"application/octet-stream\",\n PDF = \"application/pdf\",\n ZIP = \"application/zip\",\n GZIP = \"application/gzip\",\n MSWORD = \"application/msword\",\n DOCX = \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n EXCEL = \"application/vnd.ms-excel\",\n XLSX = \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n POWERPOINT = \"application/vnd.ms-powerpoint\",\n PPTX = \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n ICO = \"image/x-icon\",\n ICO_MS = \"image/vnd.microsoft.icon\",\n GIF = \"image/gif\",\n PNG = \"image/png\",\n JPEG = \"image/jpeg\",\n WEBP = \"image/webp\",\n SVG = \"image/svg+xml\",\n HEIF = \"image/heif\",\n AVIF = \"image/avif\",\n EVENT_STREAM = \"text/event-stream\",\n TAR = \"application/x-tar\",\n BZIP2 = \"application/x-bzip2\",\n}\n\n/**\n * A set of media types that require a `charset` parameter when setting\n * the `Content-Type` header.\n *\n * This includes common text-based media types such as HTML, CSS, JSON,\n * XML, CSV, Markdown, and others.\n */\nconst ADD_CHARSET: Set<MediaType> = new Set([\n MediaType.CSS,\n MediaType.CSV,\n MediaType.XML,\n MediaType.SVG,\n MediaType.HTML,\n MediaType.JSON,\n MediaType.NDJSON,\n MediaType.XML_APP,\n MediaType.MARKDOWN,\n MediaType.RICH_TEXT,\n MediaType.PLAIN_TEXT,\n MediaType.FORM_URLENCODED,\n]);\n\n/**\n * Sets a header on the given Headers object.\n *\n * - If `value` is an array, duplicates and empty strings are removed.\n * - If the resulting value array 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 *\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) return;\n\n const existing = headers.get(key);\n if (existing) {\n const merged = existing.split(\",\").map((v) => v.trim());\n values.forEach((v) => merged.push(v.trim()));\n setHeader(headers, key, merged);\n } else {\n setHeader(headers, key, values);\n }\n}\n\n/**\n * Normalizes a URL string for use as a consistent cache key.\n *\n * - Sorts query parameters alphabetically so `?b=2&a=1` and `?a=1&b=2` are treated the same.\n * - Strips fragment identifiers (`#...`) since they are not sent in HTTP requests.\n * - Leaves protocol, host, path, and query values intact.\n *\n * @param url The original URL string to normalize.\n * @returns A normalized URL string suitable for hashing or direct cache key use.\n */\nexport function normalizeUrl(url: string): URL {\n const u = new URL(url);\n\n const params = [...u.searchParams.entries()];\n params.sort(([a], [b]) => lexCompare(a, b));\n\n u.search = params\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n u.hash = \"\";\n\n return u;\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/**\n * Extracts the `Origin` header value from a request.\n *\n * The `Origin` header identifies the origin (scheme, host, and port)\n * of the request initiator. It is commonly used for CORS checks.\n *\n * @param request - The incoming {@link Request} object.\n * @returns The origin string if present, otherwise `null`.\n */\nexport function getOrigin(request: Request): string | null {\n return request.headers.get(HttpHeader.ORIGIN);\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 { getOrigin, mergeHeader, setHeader, Time } from \"./common\";\nimport { Worker } from \"./worker\";\n\n/**\n * Default CORS configuration used by `CorsProvider`.\n *\n * By default, all origins are allowed, only `Content-Type` is allowed as a header,\n * no headers are exposed, and preflight caching is 1 week.\n *\n * @see {@link CorsConfig}\n */\nexport const DEFAULT_CORS_CONFIG: Required<CorsConfig> = {\n /** Origins allowed by default. Default: all (`*`). */\n allowedOrigins: [\"*\"],\n\n /** Allowed headers for CORS requests. Default: `Content-Type`. */\n allowedHeaders: [\"Content-Type\"],\n\n /** Headers exposed to the client. Default: none. */\n exposedHeaders: [],\n\n /** Max age (in seconds) for preflight caching. Default: 1 week. */\n maxAge: Time.Week,\n} as const;\n\n/**\n * Configuration options for `CorsProvider`.\n *\n * @see {@link DEFAULT_CORS_CONFIG}\n */\nexport interface CorsConfig {\n /** Origins allowed for CORS requests. */\n allowedOrigins?: string[];\n\n /** Allowed HTTP headers for CORS requests. */\n allowedHeaders?: string[];\n\n /** HTTP headers exposed to the client. */\n exposedHeaders?: string[];\n\n /** Max age in seconds for CORS preflight caching. */\n maxAge?: number;\n}\n\n/**\n * Provides CORS settings for a worker.\n *\n * Combines a user-supplied `CorsConfig` with defaults. Used by\n * `CorsHandler` to automatically set the appropriate headers.\n */\nexport class CorsProvider {\n private readonly config: Required<CorsConfig>;\n\n /**\n * Create a new `CorsProvider`.\n *\n * @param config - Optional configuration to override defaults.\n */\n constructor(config: CorsConfig = {}) {\n this.config = { ...DEFAULT_CORS_CONFIG, ...config };\n }\n\n /** Returns the allowed origins. Default: all (`*`). */\n public getAllowedOrigins(): string[] {\n return this.config.allowedOrigins;\n }\n\n /** Returns the allowed HTTP headers. Default: `[\"Content-Type\"]`. */\n public getAllowedHeaders(): string[] {\n return this.config.allowedHeaders;\n }\n\n /** Returns headers exposed to the client. Default: `[]`. */\n public getExposedHeaders(): string[] {\n return this.config.exposedHeaders;\n }\n\n /** Returns the max age in seconds for preflight requests. Default: 1 week. */\n public getMaxAge(): number {\n return this.config.maxAge;\n }\n}\n\n/**\n * Constants for common CORS headers.\n */\nexport namespace Cors {\n export const MAX_AGE = \"Access-Control-Max-Age\";\n export const ALLOW_ORIGIN = \"Access-Control-Allow-Origin\";\n export const ALLOW_HEADERS = \"Access-Control-Allow-Headers\";\n export const ALLOW_METHODS = \"Access-Control-Allow-Methods\";\n export const EXPOSE_HEADERS = \"Access-Control-Expose-Headers\";\n export const ALLOW_CREDENTIALS = \"Access-Control-Allow-Credentials\";\n export const ALLOW_ALL_ORIGINS = \"*\";\n}\n\n/**\n * Adds or updates CORS headers on a Headers object according to the provided policy.\n *\n * Behavior:\n * - Removes any existing CORS headers to avoid stale values.\n * - If the request has no origin, the function exits early.\n * - If wildcard `*` is allowed, sets Access-Control-Allow-Origin to `*`.\n * - If the origin is explicitly allowed, sets the correct headers including credentials.\n * - Optional headers (Expose-Headers, Allow-Headers, Allow-Methods, Max-Age) are always applied.\n *\n * @param cors The CorsProvider instance that determines allowed origins and headers\n * @param headers The Headers object to update\n */\nexport function addCorsHeaders(worker: Worker, cors: CorsProvider, headers: Headers): void {\n deleteCorsHeaders(headers);\n\n const origin = getOrigin(worker.request);\n\n // CORS is not required.\n if (!origin || origin.trim() === \"\") return;\n\n if (allowAnyOrigin(cors)) {\n setHeader(headers, Cors.ALLOW_ORIGIN, Cors.ALLOW_ALL_ORIGINS);\n } else if (cors.getAllowedOrigins().includes(origin)) {\n setHeader(headers, Cors.ALLOW_ORIGIN, origin);\n setHeader(headers, Cors.ALLOW_CREDENTIALS, \"true\");\n }\n\n // Optional headers always applied if CORS.\n setHeader(headers, Cors.MAX_AGE, String(cors.getMaxAge()));\n setHeader(headers, Cors.ALLOW_METHODS, worker.getAllowedMethods());\n setHeader(headers, Cors.ALLOW_HEADERS, cors.getAllowedHeaders());\n mergeHeader(headers, Cors.EXPOSE_HEADERS, cors.getExposedHeaders());\n}\n\n/**\n * Determines if a CORS policy allows any origin (`*`).\n *\n * @param cors - The `CorsProvider` instance to check.\n * @returns `true` if the allowed origins include `\"*\"`, otherwise `false`.\n */\nexport function allowAnyOrigin(cors: CorsProvider): boolean {\n return cors.getAllowedOrigins().includes(\"*\");\n}\n\n/**\n * Deletes all standard CORS headers from the given Headers object.\n *\n * @param headers The Headers object to clean\n */\nfunction deleteCorsHeaders(headers: Headers): void {\n headers.delete(Cors.MAX_AGE);\n headers.delete(Cors.ALLOW_ORIGIN);\n headers.delete(Cors.ALLOW_HEADERS);\n headers.delete(Cors.ALLOW_METHODS);\n headers.delete(Cors.EXPOSE_HEADERS);\n headers.delete(Cors.ALLOW_CREDENTIALS);\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\";\nimport { CacheControl, HttpHeader, StatusCodes } from \"./common\";\nimport { JsonResponse } from \"./response\";\nimport { Worker } from \"./worker\";\n\n/** Structure for JSON error responses. */\nexport interface ErrorJson {\n /** HTTP status code. */\n status: number;\n /** Standard HTTP reason phrase. */\n error: string;\n /** Optional detailed message about the error. */\n details: string;\n}\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(worker: Worker, status: StatusCodes, protected readonly details?: string) {\n const json: ErrorJson = {\n status,\n error: getReasonPhrase(status),\n details: details ?? \"\",\n };\n super(worker, json, CacheControl.DISABLE, status);\n }\n}\n\n/** 400 Bad Request error response. */\nexport class BadRequest extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.BAD_REQUEST, details);\n }\n}\n\n/** 401 Unauthorized error response. */\nexport class Unauthorized extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.UNAUTHORIZED, details);\n }\n}\n\n/** 403 Forbidden error response. */\nexport class Forbidden extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.FORBIDDEN, details);\n }\n}\n\n/** 404 Not Found error response. */\nexport class NotFound extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.NOT_FOUND, details);\n }\n}\n\n/** 405 Method Not Allowed error response. */\nexport class MethodNotAllowed extends HttpError {\n constructor(worker: Worker) {\n super(\n worker,\n StatusCodes.METHOD_NOT_ALLOWED,\n `${worker.request.method} method not allowed.`\n );\n this.setHeader(HttpHeader.ALLOW, this.worker.getAllowedMethods());\n }\n}\n\n/** 500 Internal Server Error response. */\nexport class InternalServerError extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.INTERNAL_SERVER_ERROR, details);\n }\n}\n\n/** 501 Not Implemented error response. */\nexport class NotImplemented extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, 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, `${worker.request.method} method not implemented.`);\n }\n}\n\n/** 503 Service Unavailable error response. */\nexport class ServiceUnavailable extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, 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 { getReasonPhrase, StatusCodes } from \"http-status-codes\";\nimport {\n CacheControl,\n getContentType,\n HttpHeader,\n mergeHeader,\n MediaType,\n setHeader,\n} from \"./common\";\nimport { Worker } from \"./worker\";\n\n/**\n * Base class for building HTTP responses.\n * Manages headers, status, and media type.\n */\nabstract class BaseResponse {\n constructor(public readonly worker: Worker) {}\n\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 media type of the response body. */\n public mediaType?: MediaType;\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 };\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 based on the media type if set. */\n public addContentType() {\n if (this.mediaType) {\n this.headers.set(HttpHeader.CONTENT_TYPE, getContentType(this.mediaType));\n }\n }\n}\n\n/**\n * Base response class that adds caching headers.\n */\nabstract class CacheResponse extends BaseResponse {\n constructor(worker: Worker, public cache?: CacheControl) {\n super(worker);\n }\n\n /** Adds Cache-Control header if caching is configured. */\n protected addCacheHeader(): void {\n if (this.cache) {\n this.headers.set(HttpHeader.CACHE_CONTROL, CacheControl.stringify(this.cache));\n }\n }\n}\n\n/**\n * Core worker response. Combines caching, and security headers.\n */\nexport abstract class WorkerResponse extends CacheResponse {\n constructor(\n worker: Worker,\n private readonly body: BodyInit | null = null,\n cache?: CacheControl\n ) {\n super(worker, cache);\n }\n\n /** Builds the Response object with body, headers, and status. */\n public async getResponse(): Promise<Response> {\n this.addCacheHeader();\n this.addSecurityHeaders();\n\n const body = this.status === StatusCodes.NO_CONTENT ? null : this.body;\n\n if (body) this.addContentType();\n return new Response(body, this.responseInit);\n }\n\n /** Adds default security headers. */\n protected addSecurityHeaders(): void {\n this.setHeader(HttpHeader.X_CONTENT_TYPE_OPTIONS, HttpHeader.NOSNIFF);\n }\n}\n\n/**\n * Wraps an existing Response and clones its body, headers, and status.\n */\nexport class ClonedResponse extends WorkerResponse {\n constructor(worker: Worker, response: Response, cache?: CacheControl) {\n const clone = response.clone();\n super(worker, clone.body, cache);\n this.headers = new Headers(clone.headers);\n this.status = clone.status;\n this.statusText = clone.statusText;\n }\n}\n\n/**\n * Represents a successful response with customizable body and status.\n */\nexport class SuccessResponse extends WorkerResponse {\n constructor(\n worker: Worker,\n body: BodyInit | null = null,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(worker, 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(\n worker: Worker,\n json: unknown = {},\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(worker, JSON.stringify(json), cache, status);\n this.mediaType = MediaType.JSON;\n }\n}\n\n/**\n * HTML response. Automatically sets Content-Type to text/html.\n */\nexport class HtmlResponse extends SuccessResponse {\n constructor(\n worker: Worker,\n body: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(worker, body, cache, status);\n this.mediaType = MediaType.HTML;\n }\n}\n\n/**\n * Plain text response. Automatically sets Content-Type to text/plain.\n */\nexport class TextResponse extends SuccessResponse {\n constructor(\n worker: Worker,\n content: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(worker, content, cache, status);\n this.mediaType = MediaType.PLAIN_TEXT;\n }\n}\n\n/**\n * Response for HEAD requests. Clones headers but has no body.\n */\nexport class Head extends WorkerResponse {\n constructor(worker: Worker, get: Response) {\n super(worker);\n this.headers = new Headers(get.headers);\n }\n}\n\n/**\n * Response for OPTIONS requests. Sets allowed methods and returns 204 No Content.\n */\nexport class Options extends SuccessResponse {\n constructor(worker: Worker) {\n super(worker, null, undefined, StatusCodes.NO_CONTENT);\n this.setHeader(HttpHeader.ALLOW, this.worker.getAllowedMethods());\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, MatchFunction } from \"path-to-regexp\";\nimport { Method } from \"./common\";\n\n/** Parameters extracted from a matched route */\nexport type RouteParams = Record<string, string>;\n\n/**\n * Type for a route callback function.\n * @param params - Named parameters extracted from the URL path.\n * @returns A Response object or a Promise resolving to a Response.\n */\nexport type RouteCallback = (params: RouteParams) => Promise<Response> | Response;\n\n/**\n * Represents a single route.\n */\nexport interface Route {\n /** HTTP method for the route */\n method: Method;\n /** Path-to-regexp matcher function for this route */\n matcher: MatchFunction<RouteParams>;\n /** Callback to execute when the route is matched */\n callback: RouteCallback;\n}\n\n/**\n * Result of a route match.\n */\nexport interface MatchedRoute {\n /** The route that matched */\n route: Route;\n /** Parameters extracted from the URL path */\n params: RouteParams;\n}\n\n/** Tuple type representing a single route: [method, path, callback] */\nexport type RouteTuple = [Method, string, RouteCallback];\n\n/** Array of route tuples, used to initialize Routes */\nexport type RouteTable = RouteTuple[];\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 * Registers all routes from the given table, replacing any existing routes.\n *\n * @param table The list of routes to register, in the form [method, path, callback].\n */\n public load(table: RouteTable): void {\n this.routes.length = 0;\n table.forEach(([method, path, callback]) => this.add(method, path, callback));\n }\n\n /**\n * Add a single route to the container.\n * @param method - HTTP method (GET, POST, etc.)\n * @param path - URL path pattern (Express-style, e.g., \"/users/:id\")\n * @param callback - Function to execute when this route matches\n */\n public add(method: Method, path: string, callback: RouteCallback) {\n const matcher = match<RouteParams>(path, {\n decode: decodeURIComponent,\n });\n this.routes.push({ method, matcher, callback });\n }\n\n /**\n * Attempt to match a URL against the registered routes.\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 \"./common\";\nimport { Worker, WorkerConstructor } from \"./worker\";\n\n/**\n * A type-safe Cloudflare Worker handler.\n *\n * Extends `ExportedHandler` but guarantees that the `fetch` method exists\n * and has the correct signature for Cloudflare Worker invocation.\n *\n * @template E - The type of environment bindings passed to the worker. Defaults to `Env`.\n */\ninterface FetchHandler extends ExportedHandler<Env> {\n /**\n * Handles an incoming request and produces a response.\n *\n * @param request - The incoming `Request` object.\n * @param env - Environment bindings (e.g., KV namespaces, secrets, Durable Objects).\n * @param ctx - Execution context for background tasks (`waitUntil`).\n * @returns A `Promise` that resolves to the response.\n */\n fetch: (request: Request, env: Env, ctx: ExecutionContext) => Promise<Response>;\n}\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 * and where middleware chains, routing, or other custom behavior can be applied.\n *\n * @returns A Promise that resolves to the `Response` for the request.\n */\n protected abstract dispatch(): Promise<Response>;\n\n /**\n * The DEFAULT allowed HTTP methods for subclasses.\n */\n public getAllowedMethods(): Method[] {\n return [Method.GET, Method.HEAD, Method.OPTIONS];\n }\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 WorkerConstructor<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 * **Ignite** your `Worker` implementation into a Cloudflare handler.\n *\n * @returns A `FetchHandler` that launches a new worker instance for each request.\n *\n * @example\n * ```ts\n * export default MyWorker.ignite();\n * ```\n */\n public static ignite<W extends Worker>(this: WorkerConstructor<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 { BaseWorker } from \"./base-worker\";\nimport { Middleware } from \"./middleware/middleware\";\n\nexport abstract class MiddlewareWorker extends BaseWorker {\n private readonly middlewares: Middleware[] = [];\n\n /**\n * Register a middleware instance.\n * @param mw Middleware to register\n */\n public use(mw: Middleware): this {\n this.middlewares.push(mw);\n return this;\n }\n\n public async fetch(): Promise<Response> {\n const chain = this.middlewares.reduceRight(\n (next, mw) => () => mw.handle(this, next),\n () => this.dispatch()\n );\n return await 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 { isMethod, Method } from \"./common\";\nimport { MethodNotAllowed, InternalServerError, MethodNotImplemented } from \"./errors\";\nimport { MiddlewareWorker } from \"./middleware-worker\";\nimport { Head, Options, WorkerResponse } from \"./response\";\nimport { Worker } from \"./worker\";\n\n/**\n * Base worker class providing HTTP method dispatching, caching, and error handling.\n * Extends `CacheWorker` and defines default implementations for HTTP methods.\n */\nexport abstract class BasicWorker extends MiddlewareWorker {\n /**\n * Entry point to handle a fetch request.\n * Checks allowed methods, serves cached responses, or dispatches to the appropriate handler.\n */\n public async fetch(): Promise<Response> {\n if (!this.isAllowed(this.request.method)) {\n return this.getResponse(MethodNotAllowed);\n }\n\n try {\n this.init();\n return await super.fetch();\n } catch (error) {\n console.error(error);\n return this.getResponse(InternalServerError);\n }\n }\n\n /**\n * Dispatches the request to the method-specific handler.\n * Defaults to MethodNotAllowed if the HTTP method is not recognized.\n */\n protected async 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 return (handler[method] ?? (() => this.getResponse(MethodNotAllowed)))();\n }\n\n /**\n * Hook for subclasses to perform any initialization.\n */\n protected init(): void {\n return;\n }\n\n /**\n * Checks if the given HTTP method is allowed for this worker.\n * @param method HTTP method string\n * @returns true if the method is allowed\n */\n public isAllowed(method: string): boolean {\n return isMethod(method) && this.getAllowedMethods().includes(method);\n }\n\n /** Default handler for GET requests. Returns MethodNotImplemented unless overridden. */\n protected async get(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for PUT requests. Returns MethodNotImplemented unless overridden. */\n protected async put(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for POST requests. Returns MethodNotImplemented unless overridden. */\n protected async post(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for PATCH requests. Returns MethodNotImplemented unless overridden. */\n protected async patch(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for DELETE requests. Returns MethodNotImplemented unless overridden. */\n protected async delete(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /**\n * Default handler for OPTIONS requests.\n * Returns an Options response.\n *\n * Typically does not need to be overridden.\n */\n protected async options(): Promise<Response> {\n return this.getResponse(Options);\n }\n\n /**\n * Default handler for HEAD requests.\n * Performs a GET request internally and removes the body for HEAD semantics.\n *\n * Usually does not need to be overridden, as this behavior covers standard HEAD requirements.\n */\n protected async head(): Promise<Response> {\n const worker = this.create(new Request(this.request, { method: Method.GET }));\n return this.getResponse(Head, await worker.fetch());\n }\n\n /**\n * Helper to construct a WorkerResponse of the given class with arguments.\n * @param ResponseClass The response class to instantiate\n * @param args Additional constructor arguments\n * @returns The final Response object\n */\n protected async getResponse<\n T extends WorkerResponse,\n Ctor extends new (worker: Worker, ...args: any[]) => T\n >(\n ResponseClass: Ctor,\n ...args: ConstructorParameters<Ctor> extends [Worker, ...infer R] ? R : never\n ): Promise<Response> {\n return new ResponseClass(this, ...args).getResponse();\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 { BasicWorker } from \"./basic-worker\";\nimport { Method } from \"./common\";\nimport { NotFound } from \"./errors\";\nimport { Routes, RouteCallback, RouteTable } from \"./routes\";\n\n/**\n * Abstract worker that provides routing capabilities.\n * Extends `BasicWorker` and uses a `Routes` table to map HTTP methods and paths\n * to handler callbacks.\n */\nexport abstract class RouteWorker extends BasicWorker {\n /** Routing table used for registering and matching routes. */\n protected readonly routes: Routes = new Routes();\n\n /**\n * Loads routes from a `RouteTable` into this worker's route table.\n * @param table The table of routes to load.\n */\n protected load(table: RouteTable): void {\n this.routes.load(table);\n }\n\n /**\n * Adds a single route to this worker.\n * @param method HTTP method (GET, POST, etc.)\n * @param path Route path\n * @param callback Function to handle requests matching this route\n * @returns The worker instance (for chaining)\n */\n protected add(method: Method, path: string, callback: RouteCallback): this {\n this.routes.add(method, path, callback);\n return this;\n }\n\n /**\n * Matches the incoming request against registered routes and executes\n * the corresponding callback. Falls back to `BasicWorker.dispatch()` if no match.\n * @returns The response from the matched route or the default handler.\n */\n protected 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 return found.route.callback.call(this, found.params);\n }\n\n protected override async get(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async put(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async post(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async patch(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async delete(): Promise<Response> {\n return this.getResponse(NotFound);\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 { Worker } from \"../worker\";\n\nexport abstract class Middleware {\n public abstract handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;\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 { mergeHeader } from \"../common\";\nimport { addCorsHeaders, allowAnyOrigin, CorsConfig, CorsProvider } from \"../cors\";\nimport { Worker } from \"../worker\";\nimport { Middleware } from \"./middleware\";\n\n\nexport class CorsHandler extends Middleware {\n private readonly provider: CorsProvider;\n\n constructor(init?: CorsProvider | CorsConfig) {\n super();\n if (init) {\n this.provider = init instanceof CorsProvider ? init : new CorsProvider(init);\n } else {\n this.provider = new CorsProvider();\n }\n }\n\n public override async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {\n const response = await next();\n\n const mutable = new Response(response.body, response);\n\n addCorsHeaders(worker, this.provider, mutable.headers);\n if (!allowAnyOrigin(this.provider)) {\n mergeHeader(mutable.headers, \"Vary\", \"Origin\");\n }\n\n return mutable;\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, normalizeUrl } from \"../common\";\nimport { Middleware } from \"./middleware\";\nimport { Worker } from \"../worker\";\n\nexport class CacheHandler extends Middleware {\n constructor(\n protected readonly cacheName?: string,\n protected readonly getKey?: (request: Request) => URL | RequestInfo\n ) {\n super();\n }\n\n public override async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {\n const cache = this.cacheName ? await caches.open(this.cacheName) : caches.default;\n\n if (worker.request.method === Method.GET) {\n const cached = await cache.match(this.getCacheKey(worker.request));\n if (cached) return cached;\n }\n\n const response = await next();\n\n if (response.ok && worker.request.method === Method.GET) {\n worker.ctx.waitUntil(cache.put(this.getCacheKey(worker.request), response.clone()));\n }\n return response;\n }\n\n public getCacheKey(request: Request): URL | RequestInfo {\n return this.getKey ? this.getKey(request) : normalizeUrl(request.url);\n }\n}\n"],"mappings":"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","names":["HttpHeader","Method","MediaType","Cors","getReasonPhrase","StatusCodes","StatusCodes","getReasonPhrase"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adonix.org/cloud-spark",
3
- "version": "0.0.113",
3
+ "version": "0.0.115",
4
4
  "description": "Ignite your Cloudflare Workers with a type-safe library for rapid development.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",