@adonix.org/cloud-spark 0.0.118 → 0.0.121

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
@@ -33,8 +33,15 @@ declare namespace HttpHeader {
33
33
  const PERMISSIONS_POLICY = "Permissions-Policy";
34
34
  const CONTENT_SECURITY_POLICY = "Content-Security-Policy";
35
35
  const STRICT_TRANSPORT_SECURITY = "Strict-Transport-Security";
36
+ const MAX_AGE = "Access-Control-Max-Age";
37
+ const ALLOW_ORIGIN = "Access-Control-Allow-Origin";
38
+ const ALLOW_HEADERS = "Access-Control-Allow-Headers";
39
+ const ALLOW_METHODS = "Access-Control-Allow-Methods";
40
+ const EXPOSE_HEADERS = "Access-Control-Expose-Headers";
41
+ const ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
36
42
  const NOSNIFF = "nosniff";
37
43
  const ORIGIN = "Origin";
44
+ const ALLOW_ALL_ORIGINS = "*";
38
45
  }
39
46
  /**
40
47
  * Time constants in seconds. Month is approximated as 30 days.
@@ -180,16 +187,6 @@ declare function lexCompare(a: string, b: string): number;
180
187
  */
181
188
  declare function getOrigin(request: Request): string | null;
182
189
 
183
- /**
184
- * Represents the constructor of a Worker or a subclass of Worker.
185
- *
186
- * @template T - The specific type of Worker being constructed. Defaults to `Worker`.
187
- * @param req - The `Request` object to be handled by the worker instance.
188
- * @param env - The environment bindings available to the worker.
189
- * @param ctx - The `ExecutionContext` for the worker invocation.
190
- * @returns An instance of the worker type `T`.
191
- */
192
- type WorkerConstructor<T extends Worker = Worker> = new (request: Request, env: Env, ctx: ExecutionContext) => T;
193
190
  /**
194
191
  * Defines the contract for a Cloudflare-compatible Worker.
195
192
  *
@@ -435,30 +432,15 @@ declare class Routes implements Iterable<Route> {
435
432
  }
436
433
 
437
434
  /**
438
- * Default CORS configuration used by `CorsProvider`.
435
+ * Represents the constructor of a Worker subclass.
439
436
  *
440
- * By default, all origins are allowed, only `Content-Type` is allowed as a header,
441
- * no headers are exposed, and preflight caching is 1 week.
442
- *
443
- * @see {@link CorsConfig}
444
- */
445
- declare const DEFAULT_CORS_CONFIG: Required<CorsConfig>;
446
- /**
447
- * Configuration options for `CorsProvider`.
448
- *
449
- * @see {@link DEFAULT_CORS_CONFIG}
437
+ * @template T - The specific type of Worker being constructed. Defaults to `Worker`.
438
+ * @param req - The `Request` object to be handled by the worker instance.
439
+ * @param env - The environment bindings available to the worker.
440
+ * @param ctx - The `ExecutionContext` for the worker invocation.
441
+ * @returns An instance of the worker type `T`.
450
442
  */
451
- interface CorsConfig {
452
- /** Origins allowed for CORS requests. */
453
- allowedOrigins?: string[];
454
- /** Allowed HTTP headers for CORS requests. */
455
- allowedHeaders?: string[];
456
- /** HTTP headers exposed to the client. */
457
- exposedHeaders?: string[];
458
- /** Max age in seconds for CORS preflight caching. */
459
- maxAge?: number;
460
- }
461
-
443
+ type WorkerConstructor<T extends Worker = Worker> = new (request: Request, env: Env, ctx: ExecutionContext) => T;
462
444
  /**
463
445
  * A type-safe Cloudflare Worker handler.
464
446
  *
@@ -645,9 +627,21 @@ declare abstract class RouteWorker extends BasicWorker {
645
627
  protected delete(): Promise<Response>;
646
628
  }
647
629
 
630
+ declare const DEFAULT_CORS_CONFIG: CorsConfig;
631
+ interface CorsConfig {
632
+ /** Origins allowed for CORS requests. */
633
+ allowedOrigins: string[];
634
+ /** Allowed HTTP headers for CORS requests. */
635
+ allowedHeaders: string[];
636
+ /** HTTP headers exposed to the client. */
637
+ exposedHeaders: string[];
638
+ /** Max age in seconds for CORS preflight caching. */
639
+ maxAge: number;
640
+ }
641
+
648
642
  declare class CorsHandler extends Middleware {
649
- private readonly provider;
650
- constructor(init?: CorsConfig);
643
+ private readonly config;
644
+ constructor(init?: Partial<CorsConfig>);
651
645
  handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
652
646
  }
653
647
 
@@ -659,4 +653,4 @@ declare class CacheHandler extends Middleware {
659
653
  getCacheKey(request: Request): URL | RequestInfo;
660
654
  }
661
655
 
662
- export { BadRequest, BasicWorker, CacheControl, CacheHandler, ClonedResponse, type CorsConfig, CorsHandler, DEFAULT_CORS_CONFIG, type ErrorJson, Forbidden, Head, HtmlResponse, HttpError, HttpHeader, InternalServerError, JsonResponse, type MatchedRoute, MediaType, Method, MethodNotAllowed, MethodNotImplemented, Middleware, NotFound, NotImplemented, Options, type Route, type RouteCallback, type RouteParams, type RouteTable, type RouteTuple, RouteWorker, Routes, ServiceUnavailable, SuccessResponse, TextResponse, Time, Unauthorized, type Worker, type WorkerConstructor, WorkerResponse, getContentType, getOrigin, isMethod, lexCompare, mergeHeader, normalizeUrl, setHeader };
656
+ export { BadRequest, BasicWorker, CacheControl, CacheHandler, ClonedResponse, type CorsConfig, CorsHandler, DEFAULT_CORS_CONFIG, type ErrorJson, Forbidden, Head, HtmlResponse, HttpError, HttpHeader, InternalServerError, JsonResponse, type MatchedRoute, MediaType, Method, MethodNotAllowed, MethodNotImplemented, NotFound, NotImplemented, Options, type Route, type RouteCallback, type RouteParams, type RouteTable, type RouteTuple, RouteWorker, Routes, ServiceUnavailable, SuccessResponse, TextResponse, Time, Unauthorized, type Worker, WorkerResponse, getContentType, getOrigin, isMethod, lexCompare, mergeHeader, normalizeUrl, setHeader };
package/dist/index.js CHANGED
@@ -24,8 +24,15 @@ var HttpHeader;
24
24
  HttpHeader2.PERMISSIONS_POLICY = "Permissions-Policy";
25
25
  HttpHeader2.CONTENT_SECURITY_POLICY = "Content-Security-Policy";
26
26
  HttpHeader2.STRICT_TRANSPORT_SECURITY = "Strict-Transport-Security";
27
+ HttpHeader2.MAX_AGE = "Access-Control-Max-Age";
28
+ HttpHeader2.ALLOW_ORIGIN = "Access-Control-Allow-Origin";
29
+ HttpHeader2.ALLOW_HEADERS = "Access-Control-Allow-Headers";
30
+ HttpHeader2.ALLOW_METHODS = "Access-Control-Allow-Methods";
31
+ HttpHeader2.EXPOSE_HEADERS = "Access-Control-Expose-Headers";
32
+ HttpHeader2.ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
27
33
  HttpHeader2.NOSNIFF = "nosniff";
28
34
  HttpHeader2.ORIGIN = "Origin";
35
+ HttpHeader2.ALLOW_ALL_ORIGINS = "*";
29
36
  })(HttpHeader || (HttpHeader = {}));
30
37
  var Time = {
31
38
  Second: 1,
@@ -390,19 +397,7 @@ var Routes = class {
390
397
  }
391
398
  };
392
399
 
393
- // src/cors-config.ts
394
- var DEFAULT_CORS_CONFIG = {
395
- /** Origins allowed by default. Default: all (`*`). */
396
- allowedOrigins: ["*"],
397
- /** Allowed headers for CORS requests. Default: `Content-Type`. */
398
- allowedHeaders: ["Content-Type"],
399
- /** Headers exposed to the client. Default: none. */
400
- exposedHeaders: [],
401
- /** Max age (in seconds) for preflight caching. Default: 1 week. */
402
- maxAge: Time.Week
403
- };
404
-
405
- // src/base-worker.ts
400
+ // src/workers/base-worker.ts
406
401
  var BaseWorker = class {
407
402
  constructor(_request, _env, _ctx) {
408
403
  this._request = _request;
@@ -454,7 +449,7 @@ var BaseWorker = class {
454
449
  }
455
450
  };
456
451
 
457
- // src/middleware-worker.ts
452
+ // src/workers/middleware-worker.ts
458
453
  var MiddlewareWorker = class extends BaseWorker {
459
454
  middlewares = [];
460
455
  /**
@@ -474,7 +469,7 @@ var MiddlewareWorker = class extends BaseWorker {
474
469
  }
475
470
  };
476
471
 
477
- // src/basic-worker.ts
472
+ // src/workers/basic-worker.ts
478
473
  var BasicWorker = class extends MiddlewareWorker {
479
474
  /**
480
475
  * Entry point to handle a fetch request.
@@ -573,7 +568,7 @@ var BasicWorker = class extends MiddlewareWorker {
573
568
  }
574
569
  };
575
570
 
576
- // src/route-worker.ts
571
+ // src/workers/route-worker.ts
577
572
  var RouteWorker = class extends BasicWorker {
578
573
  /** Routing table used for registering and matching routes. */
579
574
  routes = new Routes();
@@ -622,94 +617,69 @@ var RouteWorker = class extends BasicWorker {
622
617
  }
623
618
  };
624
619
 
625
- // src/middleware/middleware.ts
626
- var Middleware = class {
627
- };
628
-
629
- // src/cors.ts
630
- var CorsProvider = class {
631
- config;
632
- /**
633
- * Create a new `CorsProvider`.
634
- *
635
- * @param config - Optional configuration to override defaults.
636
- */
637
- constructor(config = {}) {
638
- this.config = { ...DEFAULT_CORS_CONFIG, ...config };
639
- }
640
- /** Returns the allowed origins. Default: all (`*`). */
641
- getAllowedOrigins() {
642
- return this.config.allowedOrigins;
643
- }
644
- /** Returns the allowed HTTP headers. Default: `["Content-Type"]`. */
645
- getAllowedHeaders() {
646
- return this.config.allowedHeaders;
647
- }
648
- /** Returns headers exposed to the client. Default: `[]`. */
649
- getExposedHeaders() {
650
- return this.config.exposedHeaders;
651
- }
652
- /** Returns the max age in seconds for preflight requests. Default: 1 week. */
653
- getMaxAge() {
654
- return this.config.maxAge;
655
- }
656
- };
657
- var Cors;
658
- ((Cors2) => {
659
- Cors2.MAX_AGE = "Access-Control-Max-Age";
660
- Cors2.ALLOW_ORIGIN = "Access-Control-Allow-Origin";
661
- Cors2.ALLOW_HEADERS = "Access-Control-Allow-Headers";
662
- Cors2.ALLOW_METHODS = "Access-Control-Allow-Methods";
663
- Cors2.EXPOSE_HEADERS = "Access-Control-Expose-Headers";
664
- Cors2.ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
665
- Cors2.ALLOW_ALL_ORIGINS = "*";
666
- })(Cors || (Cors = {}));
620
+ // src/middleware/cors/cors.ts
667
621
  function addCorsHeaders(worker, cors, headers) {
668
622
  deleteCorsHeaders(headers);
669
623
  const origin = getOrigin(worker.request);
670
624
  if (!origin || origin.trim() === "") return;
671
625
  if (allowAnyOrigin(cors)) {
672
- setHeader(headers, Cors.ALLOW_ORIGIN, Cors.ALLOW_ALL_ORIGINS);
673
- } else if (cors.getAllowedOrigins().includes(origin)) {
674
- setHeader(headers, Cors.ALLOW_ORIGIN, origin);
675
- setHeader(headers, Cors.ALLOW_CREDENTIALS, "true");
676
- }
677
- setHeader(headers, Cors.MAX_AGE, String(cors.getMaxAge()));
678
- setHeader(headers, Cors.ALLOW_METHODS, worker.getAllowedMethods());
679
- setHeader(headers, Cors.ALLOW_HEADERS, cors.getAllowedHeaders());
680
- mergeHeader(headers, Cors.EXPOSE_HEADERS, cors.getExposedHeaders());
626
+ setHeader(headers, HttpHeader.ALLOW_ORIGIN, HttpHeader.ALLOW_ALL_ORIGINS);
627
+ } else if (cors.allowedOrigins.includes(origin)) {
628
+ setHeader(headers, HttpHeader.ALLOW_ORIGIN, origin);
629
+ setHeader(headers, HttpHeader.ALLOW_CREDENTIALS, "true");
630
+ }
631
+ setHeader(headers, HttpHeader.MAX_AGE, String(cors.maxAge));
632
+ setHeader(headers, HttpHeader.ALLOW_METHODS, worker.getAllowedMethods());
633
+ setHeader(headers, HttpHeader.ALLOW_HEADERS, cors.allowedHeaders);
634
+ mergeHeader(headers, HttpHeader.EXPOSE_HEADERS, cors.exposedHeaders);
681
635
  }
682
636
  function allowAnyOrigin(cors) {
683
- return cors.getAllowedOrigins().includes("*");
637
+ return cors.allowedOrigins.includes("*");
684
638
  }
685
639
  function deleteCorsHeaders(headers) {
686
- headers.delete(Cors.MAX_AGE);
687
- headers.delete(Cors.ALLOW_ORIGIN);
688
- headers.delete(Cors.ALLOW_HEADERS);
689
- headers.delete(Cors.ALLOW_METHODS);
690
- headers.delete(Cors.EXPOSE_HEADERS);
691
- headers.delete(Cors.ALLOW_CREDENTIALS);
640
+ headers.delete(HttpHeader.MAX_AGE);
641
+ headers.delete(HttpHeader.ALLOW_ORIGIN);
642
+ headers.delete(HttpHeader.ALLOW_HEADERS);
643
+ headers.delete(HttpHeader.ALLOW_METHODS);
644
+ headers.delete(HttpHeader.EXPOSE_HEADERS);
645
+ headers.delete(HttpHeader.ALLOW_CREDENTIALS);
692
646
  }
693
647
 
694
- // src/middleware/cors-handler.ts
648
+ // src/middleware/cors/cors-config.ts
649
+ var DEFAULT_CORS_CONFIG = {
650
+ /** Origins allowed by default. Default: all (`*`). */
651
+ allowedOrigins: ["*"],
652
+ /** Allowed headers for CORS requests. Default: `Content-Type`. */
653
+ allowedHeaders: ["Content-Type"],
654
+ /** Headers exposed to the client. Default: none. */
655
+ exposedHeaders: [],
656
+ /** Max age (in seconds) for preflight caching. Default: 1 week. */
657
+ maxAge: Time.Week
658
+ };
659
+
660
+ // src/middleware/base.ts
661
+ var Middleware = class {
662
+ };
663
+
664
+ // src/middleware/cors/handler.ts
695
665
  var CorsHandler = class extends Middleware {
696
- provider;
666
+ config;
697
667
  constructor(init) {
698
668
  super();
699
- this.provider = new CorsProvider(init);
669
+ this.config = { ...DEFAULT_CORS_CONFIG, ...init };
700
670
  }
701
671
  async handle(worker, next) {
702
672
  const response = await next();
703
673
  const mutable = new Response(response.body, response);
704
- addCorsHeaders(worker, this.provider, mutable.headers);
705
- if (!allowAnyOrigin(this.provider)) {
674
+ addCorsHeaders(worker, this.config, mutable.headers);
675
+ if (!allowAnyOrigin(this.config)) {
706
676
  mergeHeader(mutable.headers, "Vary", "Origin");
707
677
  }
708
678
  return mutable;
709
679
  }
710
680
  };
711
681
 
712
- // src/middleware/cache-handler.ts
682
+ // src/middleware/cache/handler.ts
713
683
  var CacheHandler = class extends Middleware {
714
684
  constructor(cacheName, getKey) {
715
685
  super();
@@ -723,7 +693,7 @@ var CacheHandler = class extends Middleware {
723
693
  if (cached) return cached;
724
694
  }
725
695
  const response = await next();
726
- if (response.ok && worker.request.method === "GET" /* GET */) {
696
+ if (worker.request.method === "GET" /* GET */ && response.ok) {
727
697
  worker.ctx.waitUntil(cache.put(this.getCacheKey(worker.request), response.clone()));
728
698
  }
729
699
  return response;
@@ -751,7 +721,6 @@ export {
751
721
  Method,
752
722
  MethodNotAllowed,
753
723
  MethodNotImplemented,
754
- Middleware,
755
724
  NotFound,
756
725
  NotImplemented,
757
726
  Options,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/common.ts","../src/errors.ts","../src/response.ts","../src/routes.ts","../src/cors-config.ts","../src/base-worker.ts","../src/middleware-worker.ts","../src/basic-worker.ts","../src/route-worker.ts","../src/middleware/middleware.ts","../src/cors.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 { 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) => Response | Promise<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 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 { Time } from \"./common\";\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 * 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 protected 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 override 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 override 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 override 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 addRoute(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 override async dispatch(): Promise<Response> {\n const found = this.routes.match(this.request.method as Method, this.request.url);\n if (!found) return super.dispatch();\n\n 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 { getOrigin, mergeHeader, setHeader } from \"./common\";\nimport { CorsConfig, DEFAULT_CORS_CONFIG } from \"./cors-config\";\nimport { Worker } from \"./worker\";\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 { mergeHeader } from \"../common\";\nimport { addCorsHeaders, allowAnyOrigin, CorsProvider } from \"../cors\";\nimport { CorsConfig } from \"../cors-config\";\nimport { Worker } from \"../worker\";\nimport { Middleware } from \"./middleware\";\n\nexport class CorsHandler extends Middleware {\n private readonly provider: CorsProvider;\n\n constructor(init?: CorsConfig) {\n super();\n this.provider = new CorsProvider(init);\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","getReasonPhrase","StatusCodes","StatusCodes","getReasonPhrase","Cors"]}
1
+ {"version":3,"sources":["../src/common.ts","../src/errors.ts","../src/response.ts","../src/routes.ts","../src/workers/base-worker.ts","../src/workers/middleware-worker.ts","../src/workers/basic-worker.ts","../src/workers/route-worker.ts","../src/middleware/cors/cors.ts","../src/middleware/cors/cors-config.ts","../src/middleware/base.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 // Cors Headers\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\n // Values\n export const NOSNIFF = \"nosniff\";\n export const ORIGIN = \"Origin\";\n export const ALLOW_ALL_ORIGINS = \"*\";\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 { getReasonPhrase } from \"http-status-codes\";\nimport { CacheControl, HttpHeader, StatusCodes } from \"./common\";\nimport { JsonResponse } from \"./response\";\nimport { Worker } from \"./workers/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(\n worker: Worker,\n status: StatusCodes,\n protected readonly details?: string,\n ) {\n const json: ErrorJson = {\n status,\n error: getReasonPhrase(status),\n details: details ?? \"\",\n };\n super(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 \"./workers/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(\n worker: Worker,\n public cache?: CacheControl,\n ) {\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) => Response | Promise<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 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 } from \"./worker\";\n\n/**\n * Represents the constructor of a Worker subclass.\n *\n * @template T - The specific type of Worker being constructed. Defaults to `Worker`.\n * @param req - The `Request` object to be handled by the worker instance.\n * @param env - The environment bindings available to the worker.\n * @param ctx - The `ExecutionContext` for the worker invocation.\n * @returns An instance of the worker type `T`.\n */\ntype WorkerConstructor<T extends Worker = Worker> = new (\n request: Request,\n env: Env,\n ctx: ExecutionContext,\n) => T;\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/base\";\n\nexport abstract class MiddlewareWorker extends BaseWorker {\n protected 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 override 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 override 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 override 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 addRoute(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 override async dispatch(): Promise<Response> {\n const found = this.routes.match(this.request.method as Method, this.request.url);\n if (!found) return super.dispatch();\n\n 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 { getOrigin, HttpHeader, mergeHeader, setHeader } from \"../../common\";\nimport { CorsConfig } from \"./cors-config\";\nimport { Worker } from \"../../workers/worker\";\n\nexport function addCorsHeaders(worker: Worker, cors: CorsConfig, 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, HttpHeader.ALLOW_ORIGIN, HttpHeader.ALLOW_ALL_ORIGINS);\n } else if (cors.allowedOrigins.includes(origin)) {\n setHeader(headers, HttpHeader.ALLOW_ORIGIN, origin);\n setHeader(headers, HttpHeader.ALLOW_CREDENTIALS, \"true\");\n }\n\n // Optional headers always applied if HttpHeader.\n setHeader(headers, HttpHeader.MAX_AGE, String(cors.maxAge));\n setHeader(headers, HttpHeader.ALLOW_METHODS, worker.getAllowedMethods());\n setHeader(headers, HttpHeader.ALLOW_HEADERS, cors.allowedHeaders);\n mergeHeader(headers, HttpHeader.EXPOSE_HEADERS, cors.exposedHeaders);\n}\n\nexport function allowAnyOrigin(cors: CorsConfig): boolean {\n return cors.allowedOrigins.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(HttpHeader.MAX_AGE);\n headers.delete(HttpHeader.ALLOW_ORIGIN);\n headers.delete(HttpHeader.ALLOW_HEADERS);\n headers.delete(HttpHeader.ALLOW_METHODS);\n headers.delete(HttpHeader.EXPOSE_HEADERS);\n headers.delete(HttpHeader.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 { Time } from \"../../common\";\n\nexport const DEFAULT_CORS_CONFIG: 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\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 * 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 \"../workers/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 } from \"./cors\";\nimport { CorsConfig, DEFAULT_CORS_CONFIG } from \"./cors-config\";\nimport { Worker } from \"../../workers/worker\";\nimport { Middleware } from \"../base\";\n\nexport class CorsHandler extends Middleware {\n private readonly config: Required<CorsConfig>;\n\n constructor(init?: Partial<CorsConfig>) {\n super();\n this.config = { ...DEFAULT_CORS_CONFIG, ...init };\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.config, mutable.headers);\n if (!allowAnyOrigin(this.config)) {\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 \"../base\";\nimport { Worker } from \"../../workers/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 (worker.request.method === Method.GET && response.ok) {\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","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.118",
3
+ "version": "0.0.121",
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",