@adonix.org/cloud-spark 0.0.92 → 0.0.94

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
@@ -13,18 +13,32 @@ export { StatusCodes } from 'http-status-codes';
13
13
  */
14
14
  type WorkerConstructor<T extends Worker = Worker> = new (req: Request, env: Env, ctx: ExecutionContext) => T;
15
15
  /**
16
- * Minimal interface representing a Worker.
16
+ * Defines the contract for a Cloudflare-compatible Worker.
17
17
  *
18
- * Any class implementing this interface must provide a `fetch` method
19
- * that handles a request and returns a Response (or a Promise resolving to a Response).
18
+ * Implementations are responsible for handling incoming requests,
19
+ * providing access to the request, environment bindings, and
20
+ * execution context.
20
21
  */
21
22
  interface Worker {
22
23
  /**
23
- * Processes a request and returns a Response.
24
+ * Processes the incoming {@link Request} and produces a {@link Response}.
24
25
  *
25
- * @returns A Promise resolving to the Response
26
+ * @returns A Promise that resolves to the HTTP {@link Response}.
26
27
  */
27
28
  fetch(): Promise<Response>;
29
+ /**
30
+ * The original {@link Request} being processed by this worker instance.
31
+ */
32
+ get request(): Request;
33
+ /**
34
+ * The environment bindings provided at runtime (e.g., KV, R2, secrets).
35
+ */
36
+ get env(): Env;
37
+ /**
38
+ * The {@link ExecutionContext} associated with the current request,
39
+ * used to manage background tasks and request lifecycle.
40
+ */
41
+ get ctx(): ExecutionContext;
28
42
  }
29
43
 
30
44
  /**
@@ -63,11 +77,11 @@ declare abstract class BaseWorker implements Worker {
63
77
  private readonly _ctx;
64
78
  constructor(_request: Request, _env: Env, _ctx: ExecutionContext);
65
79
  /** The Request object associated with this worker invocation */
66
- protected get request(): Request;
80
+ get request(): Request;
67
81
  /** Environment bindings (e.g., KV, secrets, or other globals) */
68
- protected get env(): Env;
82
+ get env(): Env;
69
83
  /** Optional execution context for background tasks or `waitUntil` */
70
- protected get ctx(): ExecutionContext;
84
+ get ctx(): ExecutionContext;
71
85
  /**
72
86
  * Creates a new instance of the current Worker subclass.
73
87
  *
@@ -102,6 +116,13 @@ type CacheControl = CacheLib.CacheControl;
102
116
  declare const CacheControl: {
103
117
  parse: (cacheControlHeader: string) => CacheLib.CacheControl;
104
118
  stringify: (cacheControl: CacheLib.CacheControl) => string;
119
+ /** A Cache-Control directive that disables all caching. */
120
+ DISABLE: Readonly<{
121
+ "no-cache": true;
122
+ "no-store": true;
123
+ "must-revalidate": true;
124
+ "max-age": 0;
125
+ }>;
105
126
  };
106
127
 
107
128
  /**
@@ -242,13 +263,21 @@ declare function mergeHeader(headers: Headers, key: string, value: string | stri
242
263
  * @returns A normalized URL string suitable for hashing or direct cache key use.
243
264
  */
244
265
  declare function normalizeUrl(url: string): URL;
266
+ /**
267
+ * Extracts the `Origin` header value from a request.
268
+ *
269
+ * The `Origin` header identifies the origin (scheme, host, and port)
270
+ * of the request initiator. It is commonly used for CORS checks.
271
+ *
272
+ * @param request - The incoming {@link Request} object.
273
+ * @returns The origin string if present, otherwise `null`.
274
+ */
275
+ declare function getOrigin(request: Request): string | null;
245
276
 
246
277
  /**
247
278
  * Provides information about the CORS policy for the current request.
248
279
  */
249
280
  interface CorsProvider {
250
- /** Returns the origin of the request, or null if none is provided. */
251
- getOrigin(): string | null;
252
281
  /** Returns a list of allowed origins. */
253
282
  getAllowOrigins(): string[];
254
283
  /** Returns true if any origin is allowed (`*`). */
@@ -287,7 +316,7 @@ declare namespace Cors {
287
316
  * @param cors The CorsProvider instance that determines allowed origins and headers
288
317
  * @param headers The Headers object to update
289
318
  */
290
- declare function addCorsHeaders(cors: CorsProvider, headers: Headers): void;
319
+ declare function addCorsHeaders(origin: string | null, cors: CorsProvider, headers: Headers): void;
291
320
 
292
321
  /**
293
322
  * Abstract base class for Workers to provide a default CORS policy.
@@ -301,14 +330,13 @@ declare function addCorsHeaders(cors: CorsProvider, headers: Headers): void;
301
330
  *
302
331
  * Subclasses can override any of the methods to customize the CORS behavior.
303
332
  */
304
- declare abstract class CorsWorker extends BaseWorker implements CorsProvider {
333
+ declare abstract class CorsWorker$1 extends BaseWorker implements CorsProvider {
305
334
  getAllowOrigins(): string[];
306
335
  allowAnyOrigin(): boolean;
307
336
  getAllowMethods(): Method[];
308
337
  getAllowHeaders(): string[];
309
338
  getExposeHeaders(): string[];
310
339
  getMaxAge(): number;
311
- getOrigin(): string | null;
312
340
  }
313
341
 
314
342
  /**
@@ -321,7 +349,7 @@ declare abstract class CorsWorker extends BaseWorker implements CorsProvider {
321
349
  *
322
350
  * Subclasses should override `getCacheKey()` to customize cache key generation if needed.
323
351
  */
324
- declare abstract class CacheWorker extends CorsWorker {
352
+ declare abstract class CacheWorker extends CorsWorker$1 {
325
353
  /**
326
354
  * Returns the cache key for the current request.
327
355
  *
@@ -397,26 +425,34 @@ interface ErrorJson {
397
425
  error: string;
398
426
  details: string;
399
427
  }
428
+ /**
429
+ * A {@link Worker} that also implements {@link CorsProvider}.
430
+ *
431
+ * Used by response builders that require both Worker
432
+ * and CORS functionality.
433
+ */
434
+ type CorsWorker = Worker & CorsProvider;
400
435
  declare abstract class BaseResponse {
436
+ readonly worker: CorsWorker;
401
437
  headers: Headers;
402
438
  body: BodyInit | null;
403
439
  status: StatusCodes;
404
440
  statusText?: string;
405
441
  mediaType?: MediaType;
406
- constructor(content?: BodyInit | null);
442
+ constructor(worker: CorsWorker, content?: BodyInit | null);
407
443
  protected get responseInit(): ResponseInit;
408
444
  setHeader(key: string, value: string | string[]): void;
409
445
  mergeHeader(key: string, value: string | string[]): void;
410
446
  addContentType(): void;
411
447
  }
412
448
  declare abstract class CorsResponse extends BaseResponse {
413
- readonly cors: CorsProvider;
414
- constructor(cors: CorsProvider, content?: BodyInit | null);
449
+ constructor(worker: CorsWorker, content?: BodyInit | null);
415
450
  protected addCorsHeaders(): void;
451
+ protected getOrigin(): string | null;
416
452
  }
417
453
  declare abstract class CacheResponse extends CorsResponse {
418
454
  cache?: CacheControl | undefined;
419
- constructor(cors: CorsProvider, body?: BodyInit | null, cache?: CacheControl | undefined);
455
+ constructor(worker: CorsWorker, body?: BodyInit | null, cache?: CacheControl | undefined);
420
456
  protected addCacheHeaders(): void;
421
457
  }
422
458
  declare abstract class WorkerResponse extends CacheResponse {
@@ -424,64 +460,64 @@ declare abstract class WorkerResponse extends CacheResponse {
424
460
  protected addSecurityHeaders(): void;
425
461
  }
426
462
  declare class ClonedResponse extends WorkerResponse {
427
- constructor(cors: CorsProvider, response: Response, cache?: CacheControl);
463
+ constructor(worker: CorsWorker, response: Response, cache?: CacheControl);
428
464
  }
429
465
  declare class SuccessResponse extends WorkerResponse {
430
- constructor(cors: CorsProvider, body?: BodyInit | null, cache?: CacheControl, status?: StatusCodes);
466
+ constructor(worker: CorsWorker, body?: BodyInit | null, cache?: CacheControl, status?: StatusCodes);
431
467
  }
432
468
  declare class JsonResponse extends SuccessResponse {
433
- constructor(cors: CorsProvider, json?: unknown, cache?: CacheControl, status?: StatusCodes);
469
+ constructor(worker: CorsWorker, json?: unknown, cache?: CacheControl, status?: StatusCodes);
434
470
  }
435
471
  declare class HtmlResponse extends SuccessResponse {
436
- constructor(cors: CorsProvider, body: string, cache?: CacheControl, status?: StatusCodes);
472
+ constructor(worker: CorsWorker, body: string, cache?: CacheControl, status?: StatusCodes);
437
473
  }
438
474
  declare class TextResponse extends SuccessResponse {
439
- constructor(cors: CorsProvider, content: string, cache?: CacheControl, status?: StatusCodes);
475
+ constructor(worker: CorsWorker, content: string, cache?: CacheControl, status?: StatusCodes);
440
476
  }
441
477
  /**
442
478
  * Removes the body from a GET response.
443
479
  */
444
480
  declare class Head extends WorkerResponse {
445
- constructor(cors: CorsProvider, get: Response);
481
+ constructor(worker: CorsWorker, get: Response);
446
482
  }
447
483
  declare class Options extends SuccessResponse {
448
- constructor(cors: CorsProvider);
484
+ constructor(worker: CorsWorker);
449
485
  }
450
486
  declare class HttpError extends JsonResponse {
451
487
  protected readonly details?: string | undefined;
452
- constructor(cors: CorsProvider, status: StatusCodes, details?: string | undefined);
488
+ constructor(worker: CorsWorker, status: StatusCodes, details?: string | undefined);
453
489
  get json(): ErrorJson;
454
490
  createResponse(): Response;
455
491
  }
456
492
  declare class BadRequest extends HttpError {
457
- constructor(cors: CorsProvider, details?: string);
493
+ constructor(worker: CorsWorker, details?: string);
458
494
  }
459
495
  declare class Unauthorized extends HttpError {
460
- constructor(cors: CorsProvider, details?: string);
496
+ constructor(worker: CorsWorker, details?: string);
461
497
  }
462
498
  declare class Forbidden extends HttpError {
463
- constructor(cors: CorsProvider, details?: string);
499
+ constructor(worker: CorsWorker, details?: string);
464
500
  }
465
501
  declare class NotFound extends HttpError {
466
- constructor(cors: CorsProvider, details?: string);
502
+ constructor(worker: CorsWorker, details?: string);
467
503
  }
468
504
  declare class MethodNotAllowed extends HttpError {
469
- constructor(cors: CorsProvider, method: string);
505
+ constructor(worker: CorsWorker, method: string);
470
506
  get json(): ErrorJson & {
471
507
  allowed: Method[];
472
508
  };
473
509
  }
474
510
  declare class InternalServerError extends HttpError {
475
- constructor(cors: CorsProvider, details?: string);
511
+ constructor(worker: CorsWorker, details?: string);
476
512
  }
477
513
  declare class NotImplemented extends HttpError {
478
- constructor(cors: CorsProvider, details?: string);
514
+ constructor(worker: CorsWorker, details?: string);
479
515
  }
480
516
  declare class MethodNotImplemented extends NotImplemented {
481
- constructor(cors: CorsProvider, method: Method);
517
+ constructor(worker: CorsWorker, method: Method);
482
518
  }
483
519
  declare class ServiceUnavailable extends HttpError {
484
- constructor(cors: CorsProvider, details?: string);
520
+ constructor(worker: CorsWorker, details?: string);
485
521
  }
486
522
 
487
523
  declare abstract class BasicWorker extends CacheWorker {
@@ -494,7 +530,7 @@ declare abstract class BasicWorker extends CacheWorker {
494
530
  protected delete(): Promise<Response>;
495
531
  protected options(): Promise<Response>;
496
532
  protected head(): Promise<Response>;
497
- protected getResponse<T extends WorkerResponse, Ctor extends new (cors: CorsProvider, ...args: any[]) => T>(ResponseClass: Ctor, ...args: ConstructorParameters<Ctor> extends [CorsProvider, ...infer R] ? R : never): Promise<Response>;
533
+ protected getResponse<T extends WorkerResponse, Ctor extends new (worker: CorsWorker, ...args: any[]) => T>(ResponseClass: Ctor, ...args: ConstructorParameters<Ctor> extends [CorsWorker, ...infer R] ? R : never): Promise<Response>;
498
534
  isAllowed(method: string): boolean;
499
535
  }
500
536
 
@@ -560,4 +596,4 @@ declare abstract class RoutedWorker extends BasicWorker {
560
596
  protected delete(): Promise<Response>;
561
597
  }
562
598
 
563
- export { BadRequest, BasicWorker, CacheControl, ClonedResponse, Cors, type CorsProvider, type ErrorJson, Forbidden, Head, HtmlResponse, HttpError, HttpHeader, InternalServerError, JsonResponse, MediaType, Method, MethodNotAllowed, MethodNotImplemented, NotFound, NotImplemented, Options, Route, type RouteCallback, type RouteInit, RoutedWorker, Routes, ServiceUnavailable, SuccessResponse, TextResponse, Time, Unauthorized, type Worker, type WorkerConstructor, WorkerResponse, addCorsHeaders, getContentType, isMethod, mergeHeader, normalizeUrl, setHeader };
599
+ export { BadRequest, BasicWorker, CacheControl, ClonedResponse, Cors, type CorsProvider, type CorsWorker, type ErrorJson, Forbidden, Head, HtmlResponse, HttpError, HttpHeader, InternalServerError, JsonResponse, MediaType, Method, MethodNotAllowed, MethodNotImplemented, NotFound, NotImplemented, Options, Route, type RouteCallback, type RouteInit, RoutedWorker, Routes, ServiceUnavailable, SuccessResponse, TextResponse, Time, Unauthorized, type Worker, type WorkerConstructor, WorkerResponse, addCorsHeaders, getContentType, getOrigin, isMethod, mergeHeader, normalizeUrl, setHeader };
package/dist/index.js CHANGED
@@ -3,7 +3,14 @@ import CacheLib from "cache-control-parser";
3
3
  import { StatusCodes } from "http-status-codes";
4
4
  var CacheControl = {
5
5
  parse: CacheLib.parse,
6
- stringify: CacheLib.stringify
6
+ stringify: CacheLib.stringify,
7
+ /** A Cache-Control directive that disables all caching. */
8
+ DISABLE: Object.freeze({
9
+ "no-cache": true,
10
+ "no-store": true,
11
+ "must-revalidate": true,
12
+ "max-age": 0
13
+ })
7
14
  };
8
15
  var HttpHeader;
9
16
  ((HttpHeader2) => {
@@ -142,6 +149,9 @@ function normalizeUrl(url) {
142
149
  u.hash = "";
143
150
  return u;
144
151
  }
152
+ function getOrigin(request) {
153
+ return request.headers.get(HttpHeader.ORIGIN);
154
+ }
145
155
 
146
156
  // src/cors.ts
147
157
  var Cors;
@@ -154,9 +164,8 @@ var Cors;
154
164
  Cors2.MAX_AGE = "Access-Control-Max-Age";
155
165
  Cors2.ALLOW_ALL_ORIGINS = "*";
156
166
  })(Cors || (Cors = {}));
157
- function addCorsHeaders(cors, headers) {
167
+ function addCorsHeaders(origin, cors, headers) {
158
168
  deleteCorsHeaders(headers);
159
- const origin = cors.getOrigin();
160
169
  if (!origin) return;
161
170
  if (cors.allowAnyOrigin()) {
162
171
  setHeader(headers, Cors.ALLOW_ORIGIN, Cors.ALLOW_ALL_ORIGINS);
@@ -244,9 +253,6 @@ var CorsWorker = class extends BaseWorker {
244
253
  getMaxAge() {
245
254
  return Time.Week;
246
255
  }
247
- getOrigin() {
248
- return this.request.headers.get("Origin");
249
- }
250
256
  };
251
257
 
252
258
  // src/cache-worker.ts
@@ -318,7 +324,7 @@ var CacheWorker = class extends CorsWorker {
318
324
  */
319
325
  addCacheHeaders(cached) {
320
326
  const headers = new Headers(cached.headers);
321
- addCorsHeaders(this, headers);
327
+ addCorsHeaders(getOrigin(this.request), this, headers);
322
328
  return new Response(cached.body, {
323
329
  status: cached.status,
324
330
  statusText: cached.statusText,
@@ -367,14 +373,15 @@ var CacheWorker = class extends CorsWorker {
367
373
  // src/response.ts
368
374
  import { getReasonPhrase, StatusCodes as StatusCodes2 } from "http-status-codes";
369
375
  var BaseResponse = class {
376
+ constructor(worker, content = null) {
377
+ this.worker = worker;
378
+ this.body = this.status === StatusCodes2.NO_CONTENT ? null : content;
379
+ }
370
380
  headers = new Headers();
371
381
  body;
372
382
  status = StatusCodes2.OK;
373
383
  statusText;
374
384
  mediaType;
375
- constructor(content = null) {
376
- this.body = this.status === StatusCodes2.NO_CONTENT ? null : content;
377
- }
378
385
  get responseInit() {
379
386
  return {
380
387
  headers: this.headers,
@@ -395,17 +402,19 @@ var BaseResponse = class {
395
402
  }
396
403
  };
397
404
  var CorsResponse = class extends BaseResponse {
398
- constructor(cors, content = null) {
399
- super(content);
400
- this.cors = cors;
405
+ constructor(worker, content = null) {
406
+ super(worker, content);
401
407
  }
402
408
  addCorsHeaders() {
403
- addCorsHeaders(this.cors, this.headers);
409
+ addCorsHeaders(this.getOrigin(), this.worker, this.headers);
410
+ }
411
+ getOrigin() {
412
+ return getOrigin(this.worker.request);
404
413
  }
405
414
  };
406
415
  var CacheResponse = class extends CorsResponse {
407
- constructor(cors, body = null, cache) {
408
- super(cors, body);
416
+ constructor(worker, body = null, cache) {
417
+ super(worker, body);
409
418
  this.cache = cache;
410
419
  }
411
420
  addCacheHeaders() {
@@ -428,59 +437,53 @@ var WorkerResponse = class extends CacheResponse {
428
437
  }
429
438
  };
430
439
  var ClonedResponse = class extends WorkerResponse {
431
- constructor(cors, response, cache) {
440
+ constructor(worker, response, cache) {
432
441
  const clone = response.clone();
433
- super(cors, clone.body, cache);
442
+ super(worker, clone.body, cache);
434
443
  this.headers = new Headers(clone.headers);
435
444
  this.status = clone.status;
436
445
  this.statusText = clone.statusText;
437
446
  }
438
447
  };
439
448
  var SuccessResponse = class extends WorkerResponse {
440
- constructor(cors, body = null, cache, status = StatusCodes2.OK) {
441
- super(cors, body, cache);
449
+ constructor(worker, body = null, cache, status = StatusCodes2.OK) {
450
+ super(worker, body, cache);
442
451
  this.status = status;
443
452
  }
444
453
  };
445
454
  var JsonResponse = class extends SuccessResponse {
446
- constructor(cors, json = {}, cache, status = StatusCodes2.OK) {
447
- super(cors, JSON.stringify(json), cache, status);
455
+ constructor(worker, json = {}, cache, status = StatusCodes2.OK) {
456
+ super(worker, JSON.stringify(json), cache, status);
448
457
  this.mediaType = "application/json" /* JSON */;
449
458
  }
450
459
  };
451
460
  var HtmlResponse = class extends SuccessResponse {
452
- constructor(cors, body, cache, status = StatusCodes2.OK) {
453
- super(cors, body, cache, status);
461
+ constructor(worker, body, cache, status = StatusCodes2.OK) {
462
+ super(worker, body, cache, status);
454
463
  this.mediaType = "text/html" /* HTML */;
455
464
  }
456
465
  };
457
466
  var TextResponse = class extends SuccessResponse {
458
- constructor(cors, content, cache, status = StatusCodes2.OK) {
459
- super(cors, content, cache, status);
467
+ constructor(worker, content, cache, status = StatusCodes2.OK) {
468
+ super(worker, content, cache, status);
460
469
  this.mediaType = "text/plain" /* PLAIN_TEXT */;
461
470
  }
462
471
  };
463
472
  var Head = class extends WorkerResponse {
464
- constructor(cors, get) {
465
- super(cors);
473
+ constructor(worker, get) {
474
+ super(worker);
466
475
  this.headers = new Headers(get.headers);
467
476
  }
468
477
  };
469
478
  var Options = class extends SuccessResponse {
470
- constructor(cors) {
471
- super(cors, null, void 0, StatusCodes2.NO_CONTENT);
472
- this.setHeader("Allow", this.cors.getAllowMethods());
479
+ constructor(worker) {
480
+ super(worker, null, void 0, StatusCodes2.NO_CONTENT);
481
+ this.setHeader("Allow", this.worker.getAllowMethods());
473
482
  }
474
483
  };
475
484
  var HttpError = class extends JsonResponse {
476
- constructor(cors, status, details) {
477
- const cache = {
478
- "no-cache": true,
479
- "no-store": true,
480
- "must-revalidate": true,
481
- "max-age": 0
482
- };
483
- super(cors, void 0, cache, status);
485
+ constructor(worker, status, details) {
486
+ super(worker, void 0, CacheControl.DISABLE, status);
484
487
  this.details = details;
485
488
  }
486
489
  get json() {
@@ -496,55 +499,55 @@ var HttpError = class extends JsonResponse {
496
499
  }
497
500
  };
498
501
  var BadRequest = class extends HttpError {
499
- constructor(cors, details) {
500
- super(cors, StatusCodes2.BAD_REQUEST, details);
502
+ constructor(worker, details) {
503
+ super(worker, StatusCodes2.BAD_REQUEST, details);
501
504
  }
502
505
  };
503
506
  var Unauthorized = class extends HttpError {
504
- constructor(cors, details) {
505
- super(cors, StatusCodes2.UNAUTHORIZED, details);
507
+ constructor(worker, details) {
508
+ super(worker, StatusCodes2.UNAUTHORIZED, details);
506
509
  }
507
510
  };
508
511
  var Forbidden = class extends HttpError {
509
- constructor(cors, details) {
510
- super(cors, StatusCodes2.FORBIDDEN, details);
512
+ constructor(worker, details) {
513
+ super(worker, StatusCodes2.FORBIDDEN, details);
511
514
  }
512
515
  };
513
516
  var NotFound = class extends HttpError {
514
- constructor(cors, details) {
515
- super(cors, StatusCodes2.NOT_FOUND, details);
517
+ constructor(worker, details) {
518
+ super(worker, StatusCodes2.NOT_FOUND, details);
516
519
  }
517
520
  };
518
521
  var MethodNotAllowed = class extends HttpError {
519
- constructor(cors, method) {
520
- super(cors, StatusCodes2.METHOD_NOT_ALLOWED, `${method} method not allowed.`);
521
- this.setHeader("Allow", this.cors.getAllowMethods());
522
+ constructor(worker, method) {
523
+ super(worker, StatusCodes2.METHOD_NOT_ALLOWED, `${method} method not allowed.`);
524
+ this.setHeader("Allow", this.worker.getAllowMethods());
522
525
  }
523
526
  get json() {
524
527
  return {
525
528
  ...super.json,
526
- allowed: this.cors.getAllowMethods()
529
+ allowed: this.worker.getAllowMethods()
527
530
  };
528
531
  }
529
532
  };
530
533
  var InternalServerError = class extends HttpError {
531
- constructor(cors, details) {
532
- super(cors, StatusCodes2.INTERNAL_SERVER_ERROR, details);
534
+ constructor(worker, details) {
535
+ super(worker, StatusCodes2.INTERNAL_SERVER_ERROR, details);
533
536
  }
534
537
  };
535
538
  var NotImplemented = class extends HttpError {
536
- constructor(cors, details) {
537
- super(cors, StatusCodes2.NOT_IMPLEMENTED, details);
539
+ constructor(worker, details) {
540
+ super(worker, StatusCodes2.NOT_IMPLEMENTED, details);
538
541
  }
539
542
  };
540
543
  var MethodNotImplemented = class extends NotImplemented {
541
- constructor(cors, method) {
542
- super(cors, `${method} method not implemented.`);
544
+ constructor(worker, method) {
545
+ super(worker, `${method} method not implemented.`);
543
546
  }
544
547
  };
545
548
  var ServiceUnavailable = class extends HttpError {
546
- constructor(cors, details) {
547
- super(cors, StatusCodes2.SERVICE_UNAVAILABLE, details);
549
+ constructor(worker, details) {
550
+ super(worker, StatusCodes2.SERVICE_UNAVAILABLE, details);
548
551
  }
549
552
  };
550
553
 
@@ -716,6 +719,7 @@ export {
716
719
  WorkerResponse,
717
720
  addCorsHeaders,
718
721
  getContentType,
722
+ getOrigin,
719
723
  isMethod,
720
724
  mergeHeader,
721
725
  normalizeUrl,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/common.ts","../src/cors.ts","../src/base-worker.ts","../src/cors-worker.ts","../src/cache-worker.ts","../src/response.ts","../src/basic-worker.ts","../src/routes.ts","../src/routed-worker.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\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 CONTENT_TYPE = \"Content-Type\";\n export const CACHE_CONTROL = \"Cache-Control\";\n\n // Security Headers\n export const X_CONTENT_TYPE_OPTIONS = \"X-Content-Type-Options\"; // usually \"nosniff\"\n export const X_FRAME_OPTIONS = \"X-Frame-Options\"; // e.g. \"DENY\" or \"SAMEORIGIN\"\n export const STRICT_TRANSPORT_SECURITY = \"Strict-Transport-Security\"; // e.g. \"max-age=63072000; includeSubDomains; preload\"\n export const CONTENT_SECURITY_POLICY = \"Content-Security-Policy\"; // fine-grained script/style/image restrictions\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\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 POST = \"POST\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n HEAD = \"HEAD\",\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.PLAIN_TEXT,\n MediaType.HTML,\n MediaType.CSS,\n MediaType.CSV,\n MediaType.MARKDOWN,\n MediaType.XML,\n MediaType.JSON,\n MediaType.XML_APP,\n MediaType.FORM_URLENCODED,\n MediaType.NDJSON,\n MediaType.RICH_TEXT,\n MediaType.SVG,\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()))).filter((v) => v.length);\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]) => a.localeCompare(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 * 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 { HttpHeader, mergeHeader, Method, setHeader } from \"./common\";\n\n/**\n * Provides information about the CORS policy for the current request.\n */\nexport interface CorsProvider {\n /** Returns the origin of the request, or null if none is provided. */\n getOrigin(): string | null;\n\n /** Returns a list of allowed origins. */\n getAllowOrigins(): string[];\n\n /** Returns true if any origin is allowed (`*`). */\n allowAnyOrigin(): boolean;\n\n /** Returns the HTTP methods allowed by CORS. */\n getAllowMethods(): Method[];\n\n /** Returns the HTTP headers allowed by CORS. */\n getAllowHeaders(): string[];\n\n /** Returns the HTTP headers that should be exposed to the browser. */\n getExposeHeaders(): string[];\n\n /** Returns the max age (in seconds) for CORS preflight caching. */\n getMaxAge(): number;\n}\n\n/**\n * Constants for common CORS headers.\n */\nexport namespace Cors {\n export const ALLOW_ORIGIN = \"Access-Control-Allow-Origin\";\n export const ALLOW_CREDENTIALS = \"Access-Control-Allow-Credentials\";\n export const EXPOSE_HEADERS = \"Access-Control-Expose-Headers\";\n export const ALLOW_HEADERS = \"Access-Control-Allow-Headers\";\n export const ALLOW_METHODS = \"Access-Control-Allow-Methods\";\n export const MAX_AGE = \"Access-Control-Max-Age\";\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 and Vary: Origin.\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(cors: CorsProvider, headers: Headers): void {\n deleteCorsHeaders(headers);\n\n const origin = cors.getOrigin();\n if (!origin) return;\n\n if (cors.allowAnyOrigin()) {\n setHeader(headers, Cors.ALLOW_ORIGIN, Cors.ALLOW_ALL_ORIGINS);\n } else if (cors.getAllowOrigins().includes(origin)) {\n setHeader(headers, Cors.ALLOW_ORIGIN, origin);\n setHeader(headers, Cors.ALLOW_CREDENTIALS, \"true\");\n mergeHeader(headers, HttpHeader.VARY, HttpHeader.ORIGIN);\n }\n\n // Optional headers always applied\n mergeHeader(headers, Cors.EXPOSE_HEADERS, cors.getExposeHeaders());\n setHeader(headers, Cors.ALLOW_HEADERS, cors.getAllowHeaders());\n setHeader(headers, Cors.ALLOW_METHODS, cors.getAllowMethods());\n setHeader(headers, Cors.MAX_AGE, String(cors.getMaxAge()));\n}\n\n/**\n * Deletes all standard CORS headers from the given Headers object.\n * Useful for cleaning cached responses or resetting headers before reapplying CORS.\n *\n * @param headers The Headers object to clean\n */\nfunction deleteCorsHeaders(headers: Headers) {\n headers.delete(Cors.ALLOW_ORIGIN);\n headers.delete(Cors.ALLOW_CREDENTIALS);\n headers.delete(Cors.EXPOSE_HEADERS);\n headers.delete(Cors.ALLOW_METHODS);\n headers.delete(Cors.MAX_AGE);\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, WorkerConstructor } from \"./worker\";\n\n/**\n * A type-safe Cloudflare Worker handler where `fetch` is required.\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<E = Env> extends ExportedHandler<E> {\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 - Optional execution context for background tasks (`waitUntil`).\n * @returns A `Promise` that resolves to the response.\n */\n fetch: (request: Request, env: E, ctx: ExecutionContext) => Promise<Response>;\n}\n\n/**\n * Provides the foundational structure for handling requests, environment bindings,\n * and the worker execution context. Subclasses are expected to implement the\n * `fetch` method to handle the request and return a Response.\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), if available.\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 protected get request(): Request {\n return this._request;\n }\n\n /** Environment bindings (e.g., KV, secrets, or other globals) */\n protected get env(): Env {\n return this._env;\n }\n\n /** Optional execution context for background tasks or `waitUntil` */\n protected get ctx(): ExecutionContext {\n return this._ctx;\n }\n\n /**\n * Creates a new instance of the current Worker subclass.\n *\n * @param request - The request to pass to the new worker instance.\n * @returns A new worker instance of the same subclass as `this`.\n */\n protected createWorker(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 request and produce a Response.\n * Subclasses must implement this method.\n *\n * @returns A Promise resolving to the Response for the request\n */\n public abstract fetch(): Promise<Response>;\n\n /**\n * **Ignite** your `Worker` implementation into a Cloudflare-compatible 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: (req: Request, env: Env, ctx: ExecutionContext) =>\n new this(req, 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 { Method, Time } from \"./common\";\nimport { CorsProvider } from \"./cors\";\n\n/**\n * Abstract base class for Workers to provide a default CORS policy.\n *\n * Implements the `CorsProvider` interface and provides a standard policy:\n * - Allows all origins (`*`) by default.\n * - Allows GET, OPTIONS, and HEAD methods.\n * - Allows the `Content-Type` header.\n * - Exposes no additional headers.\n * - Sets CORS preflight max-age to one week.\n *\n * Subclasses can override any of the methods to customize the CORS behavior.\n */\nexport abstract class CorsWorker extends BaseWorker implements CorsProvider {\n public getAllowOrigins(): string[] {\n return [\"*\"];\n }\n\n public allowAnyOrigin(): boolean {\n return this.getAllowOrigins().includes(\"*\");\n }\n\n public getAllowMethods(): Method[] {\n return [Method.GET, Method.OPTIONS, Method.HEAD];\n }\n\n public getAllowHeaders(): string[] {\n return [\"Content-Type\"];\n }\n\n public getExposeHeaders(): string[] {\n return [];\n }\n\n public getMaxAge(): number {\n return Time.Week;\n }\n\n public getOrigin(): string | null {\n return this.request.headers.get(\"Origin\");\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 { addCorsHeaders, Cors } from \"./cors\";\nimport { CorsWorker } from \"./cors-worker\";\n\n/**\n * Abstract worker class that adds caching support for GET requests.\n *\n * Behavior:\n * - Caches successful GET responses (`response.ok === true`) in the selected cache.\n * - Strips CORS headers from cached responses; all other origin headers are preserved.\n * - Dynamically adds CORS headers to cached responses when returned to the client.\n *\n * Subclasses should override `getCacheKey()` to customize cache key generation if needed.\n */\nexport abstract class CacheWorker extends CorsWorker {\n /**\n * Returns the cache key for the current request.\n *\n * Behavior:\n * - By default, returns the normalized request URL.\n * - Query parameters are normalized so that the order does not affect the cache key.\n * For example, `?a=1&b=2` and `?b=2&a=1` produce the same cache key.\n *\n * Subclasses may override this method to implement custom cache key strategies.\n *\n * @returns {URL | RequestInfo} The URL or RequestInfo used as the cache key.\n */\n protected getCacheKey(): URL | RequestInfo {\n return normalizeUrl(this.request.url);\n }\n\n /**\n * Retrieves a cached Response for the current request, if one exists.\n *\n * Behavior:\n * - Only GET requests are considered.\n * - Returns a new Response with dynamic CORS headers applied via `addCacheHeaders`.\n * - Returns `undefined` if no cached response is found.\n * - Cloudflare dynamic headers (`CF-Cache-Status`, `Age`, `Connection`, etc.) will\n * always be present on the returned response, even though they are not stored in the cache.\n *\n * @param {string} [cacheName] Optional named cache; defaults to `caches.default`.\n * @returns {Promise<Response | undefined>} A Response with CORS headers, or undefined.\n * @see {@link setCachedResponse}\n * @see {@link getCacheKey}\n */\n protected async getCachedResponse(cacheName?: string): Promise<Response | undefined> {\n if (this.request.method !== Method.GET) return;\n\n const cache = cacheName ? await caches.open(cacheName) : caches.default;\n const response = await cache.match(this.getCacheKey());\n return response ? this.addCacheHeaders(response) : undefined;\n }\n\n /**\n * Stores a Response in the cache for the current request.\n *\n * Behavior:\n * - Only caches successful GET responses (`response.ok === true`).\n * - Strips headers via `removeCacheHeaders` before storing.\n * - Uses `ctx.waitUntil` to perform caching asynchronously without blocking the response.\n * - All other origin headers (e.g., Cache-Control, Expires) are preserved.\n *\n * @param {Response} response The Response to cache.\n * @param {string} [cacheName] Optional named cache; defaults to `caches.default`.\n * @see {@link getCachedResponse}\n * @see {@link getCacheKey}\n */\n protected async setCachedResponse(response: Response, cacheName?: string): Promise<void> {\n if (!response.ok) return;\n if (this.request.method !== Method.GET) return;\n\n const cache = cacheName ? await caches.open(cacheName) : caches.default;\n this.ctx.waitUntil(\n cache.put(this.getCacheKey(), this.removeCacheHeaders(response.clone()))\n );\n }\n\n /**\n * Adds headers to a cached response.\n *\n * @param {Response} cached The cached Response.\n * @returns {Response} A new Response with dynamic CORS headers applied.\n * @see {@link removeCacheHeaders}\n */\n private addCacheHeaders(cached: Response): Response {\n const headers = new Headers(cached.headers);\n addCorsHeaders(this, headers);\n\n return new Response(cached.body, {\n status: cached.status,\n statusText: cached.statusText,\n headers,\n });\n }\n\n /**\n * Removes headers that should not be stored in the cache (currently only CORS headers).\n *\n * @param {Response} response The Response to clean before caching.\n * @returns {Response} A new Response with excluded headers removed.\n * @see {@link addCacheHeaders}\n */\n private removeCacheHeaders(response: Response): Response {\n const excludeSet = new Set(this.excludeCacheHeaders().map((h) => h.toLowerCase()));\n const headers = new Headers();\n\n for (const [key, value] of response.headers) {\n if (!excludeSet.has(key)) {\n headers.set(key, value);\n }\n }\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n\n /**\n * Returns the list of headers to exclude from the cached response.\n * By default, excludes only dynamic CORS headers.\n *\n * @returns {string[]} Array of header names to exclude.\n * @see {@link removeCacheHeaders}\n */\n protected excludeCacheHeaders(): string[] {\n return [\n Cors.ALLOW_ORIGIN,\n Cors.ALLOW_CREDENTIALS,\n Cors.EXPOSE_HEADERS,\n Cors.ALLOW_METHODS,\n Cors.MAX_AGE,\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 { getReasonPhrase, StatusCodes } from \"http-status-codes\";\nimport {\n CacheControl,\n getContentType,\n HttpHeader,\n mergeHeader,\n Method,\n MediaType,\n setHeader,\n} from \"./common\";\nimport { addCorsHeaders, CorsProvider } from \"./cors\";\n\nexport interface ErrorJson {\n status: number;\n error: string;\n details: string;\n}\n\nabstract class BaseResponse {\n public headers: Headers = new Headers();\n public body: BodyInit | null;\n public status: StatusCodes = StatusCodes.OK;\n public statusText?: string;\n public mediaType?: MediaType;\n\n constructor(content: BodyInit | null = null) {\n this.body = this.status === StatusCodes.NO_CONTENT ? null : content;\n }\n\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 public setHeader(key: string, value: string | string[]): void {\n setHeader(this.headers, key, value);\n }\n\n public mergeHeader(key: string, value: string | string[]): void {\n mergeHeader(this.headers, key, value);\n }\n\n public addContentType() {\n if (this.mediaType) {\n this.headers.set(HttpHeader.CONTENT_TYPE, getContentType(this.mediaType));\n }\n }\n}\n\nabstract class CorsResponse extends BaseResponse {\n constructor(public readonly cors: CorsProvider, content: BodyInit | null = null) {\n super(content);\n }\n\n protected addCorsHeaders(): void {\n addCorsHeaders(this.cors, this.headers);\n }\n}\n\nabstract class CacheResponse extends CorsResponse {\n constructor(cors: CorsProvider, body: BodyInit | null = null, public cache?: CacheControl) {\n super(cors, body);\n }\n\n protected addCacheHeaders(): void {\n if (this.cache) {\n this.headers.set(HttpHeader.CACHE_CONTROL, CacheControl.stringify(this.cache));\n }\n }\n}\n\nexport abstract class WorkerResponse extends CacheResponse {\n public createResponse(): Response {\n this.addCorsHeaders();\n this.addCacheHeaders();\n this.addSecurityHeaders();\n\n const body = this.status === StatusCodes.NO_CONTENT ? null : this.body;\n if (body) this.addContentType();\n return new Response(body, this.responseInit);\n }\n\n protected addSecurityHeaders(): void {\n this.setHeader(HttpHeader.X_CONTENT_TYPE_OPTIONS, HttpHeader.NOSNIFF);\n }\n}\n\nexport class ClonedResponse extends WorkerResponse {\n constructor(cors: CorsProvider, response: Response, cache?: CacheControl) {\n const clone = response.clone();\n super(cors, clone.body, cache);\n this.headers = new Headers(clone.headers);\n this.status = clone.status;\n this.statusText = clone.statusText;\n }\n}\n\nexport class SuccessResponse extends WorkerResponse {\n constructor(\n cors: CorsProvider,\n body: BodyInit | null = null,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(cors, body, cache);\n this.status = status;\n }\n}\n\nexport class JsonResponse extends SuccessResponse {\n constructor(\n cors: CorsProvider,\n json: unknown = {},\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(cors, JSON.stringify(json), cache, status);\n this.mediaType = MediaType.JSON;\n }\n}\n\nexport class HtmlResponse extends SuccessResponse {\n constructor(\n cors: CorsProvider,\n body: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(cors, body, cache, status);\n this.mediaType = MediaType.HTML;\n }\n}\n\nexport class TextResponse extends SuccessResponse {\n constructor(\n cors: CorsProvider,\n content: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(cors, content, cache, status);\n this.mediaType = MediaType.PLAIN_TEXT;\n }\n}\n\n/**\n * Removes the body from a GET response.\n */\nexport class Head extends WorkerResponse {\n constructor(cors: CorsProvider, get: Response) {\n super(cors);\n this.headers = new Headers(get.headers);\n }\n}\n\nexport class Options extends SuccessResponse {\n constructor(cors: CorsProvider) {\n super(cors, null, undefined, StatusCodes.NO_CONTENT);\n this.setHeader(\"Allow\", this.cors.getAllowMethods());\n }\n}\n\nexport class HttpError extends JsonResponse {\n constructor(cors: CorsProvider, status: StatusCodes, protected readonly details?: string) {\n const cache: CacheControl = {\n \"no-cache\": true,\n \"no-store\": true,\n \"must-revalidate\": true,\n \"max-age\": 0,\n };\n super(cors, undefined, cache, status);\n }\n\n public get json(): ErrorJson {\n return {\n status: this.status,\n error: getReasonPhrase(this.status),\n details: this.details ?? getReasonPhrase(this.status),\n };\n }\n\n public override createResponse(): Response {\n this.body = JSON.stringify(this.json);\n return super.createResponse();\n }\n}\n\nexport class BadRequest extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.BAD_REQUEST, details);\n }\n}\n\nexport class Unauthorized extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.UNAUTHORIZED, details);\n }\n}\n\nexport class Forbidden extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.FORBIDDEN, details);\n }\n}\n\nexport class NotFound extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.NOT_FOUND, details);\n }\n}\n\nexport class MethodNotAllowed extends HttpError {\n constructor(cors: CorsProvider, method: string) {\n super(cors, StatusCodes.METHOD_NOT_ALLOWED, `${method} method not allowed.`);\n this.setHeader(\"Allow\", this.cors.getAllowMethods());\n }\n\n public override get json(): ErrorJson & { allowed: Method[] } {\n return {\n ...super.json,\n allowed: this.cors.getAllowMethods(),\n };\n }\n}\n\nexport class InternalServerError extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.INTERNAL_SERVER_ERROR, details);\n }\n}\n\nexport class NotImplemented extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.NOT_IMPLEMENTED, details);\n }\n}\n\nexport class MethodNotImplemented extends NotImplemented {\n constructor(cors: CorsProvider, method: Method) {\n super(cors, `${method} method not implemented.`);\n }\n}\n\nexport class ServiceUnavailable extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, 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 { CacheWorker } from \"./cache-worker\";\nimport { isMethod, Method } from \"./common\";\nimport { CorsProvider } from \"./cors\";\nimport {\n Head,\n InternalServerError,\n MethodNotAllowed,\n MethodNotImplemented,\n Options,\n WorkerResponse,\n} from \"./response\";\n\nexport abstract class BasicWorker extends CacheWorker {\n public async fetch(): Promise<Response> {\n if (!this.isAllowed(this.request.method)) {\n return this.getResponse(MethodNotAllowed, this.request.method);\n }\n\n try {\n return await this.dispatch();\n } catch (error) {\n return this.getResponse(InternalServerError, String(error));\n }\n }\n\n protected async dispatch(): Promise<Response> {\n const method = this.request.method as Method;\n const handler: Record<Method, () => Promise<Response>> = {\n GET: () => this.get(),\n PUT: () => this.put(),\n POST: () => this.post(),\n PATCH: () => this.patch(),\n DELETE: () => this.delete(),\n HEAD: () => this.head(),\n OPTIONS: () => this.options(),\n };\n return (handler[method] ?? (() => this.getResponse(MethodNotAllowed, method)))();\n }\n\n protected async get(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.GET);\n }\n\n protected async put(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.PUT);\n }\n\n protected async post(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.POST);\n }\n\n protected async patch(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.PATCH);\n }\n\n protected async delete(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.DELETE);\n }\n\n protected async options(): Promise<Response> {\n return this.getResponse(Options);\n }\n\n protected async head(): Promise<Response> {\n const worker = this.createWorker(new Request(this.request, { method: \"GET\" }));\n return this.getResponse(Head, await worker.fetch());\n }\n\n protected async getResponse<\n T extends WorkerResponse,\n Ctor extends new (cors: CorsProvider, ...args: any[]) => T\n >(\n ResponseClass: Ctor,\n ...args: ConstructorParameters<Ctor> extends [CorsProvider, ...infer R] ? R : never\n ): Promise<Response> {\n const response = new ResponseClass(this, ...args).createResponse();\n this.setCachedResponse(response);\n return response;\n }\n\n public isAllowed(method: string): boolean {\n return isMethod(method) && this.getAllowMethods().includes(method);\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\";\n\n/**\n * A callback function for a route.\n *\n * @param matches - Captured groups from the route RegExp, or the full match at index 0\n * @returns A Response object or a Promise that resolves to a Response\n */\nexport type RouteCallback = (...matches: string[]) => Response | Promise<Response>;\n\n/**\n * Tuple used to initialize a route.\n *\n * [HTTP method, path pattern (string or RegExp), callback function]\n */\nexport type RouteInit = [Method, RegExp | string, RouteCallback];\n\n/**\n * Represents a single route with a pattern and a callback.\n */\nexport class Route {\n public readonly pattern: RegExp;\n\n /**\n * @param pattern - A RegExp or string used to match the request path\n * @param callback - Function to handle requests matching the pattern\n */\n constructor(pattern: RegExp | string, public readonly callback: RouteCallback) {\n this.pattern = new RegExp(pattern);\n }\n}\n\n/**\n * A collection of routes grouped by HTTP method.\n *\n * Supports adding routes and retrieving the first matching route for a given method and URL.\n */\nexport class Routes {\n private readonly map = new Map<Method, Route[]>();\n\n /**\n * Adds a route to the collection under the given HTTP method.\n *\n * @param method - HTTP method (GET, POST, etc.)\n * @param route - Route instance to add\n * @returns The Routes instance (for chaining)\n */\n public add(method: Method, route: Route): this {\n const existing = this.map.get(method);\n if (existing) {\n existing.push(route);\n } else {\n this.map.set(method, [route]);\n }\n return this;\n }\n\n /**\n * Finds the first route that matches the given method and URL.\n *\n * @param method - HTTP method of the request\n * @param url - Full URL string of the request\n * @returns The first matching Route, or undefined if none match\n */\n public get(method: Method, url: string): Route | undefined {\n const routes = this.map.get(method);\n if (!routes) return undefined;\n\n const pathname = new URL(url).pathname;\n return routes.find(({ pattern }) => pattern.test(pathname));\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 \"./response\";\nimport { Route, Routes, RouteInit, RouteCallback } from \"./routes\";\n\nexport abstract class RoutedWorker extends BasicWorker {\n private readonly routes: Routes = new Routes();\n\n protected initialize(routes: RouteInit[]) {\n routes.forEach(([method, pattern, callback]) => {\n this.add(method, pattern, callback);\n });\n }\n\n protected add(method: Method, pattern: RegExp | string, callback: RouteCallback) {\n this.routes.add(method, new Route(pattern, callback));\n return this;\n }\n\n protected async dispatch(request: Request = this.request): Promise<Response> {\n const route = this.routes.get(request.method as Method, request.url);\n if (!route) return super.dispatch();\n\n const match = new URL(request.url).pathname.match(route.pattern) ?? [];\n return route.callback.call(this, ...match);\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"],"mappings":"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","names":["HttpHeader","Method","MediaType","Cors","StatusCodes","StatusCodes"]}
1
+ {"version":3,"sources":["../src/common.ts","../src/cors.ts","../src/base-worker.ts","../src/cors-worker.ts","../src/cache-worker.ts","../src/response.ts","../src/basic-worker.ts","../src/routes.ts","../src/routed-worker.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 CONTENT_TYPE = \"Content-Type\";\n export const CACHE_CONTROL = \"Cache-Control\";\n\n // Security Headers\n export const X_CONTENT_TYPE_OPTIONS = \"X-Content-Type-Options\"; // usually \"nosniff\"\n export const X_FRAME_OPTIONS = \"X-Frame-Options\"; // e.g. \"DENY\" or \"SAMEORIGIN\"\n export const STRICT_TRANSPORT_SECURITY = \"Strict-Transport-Security\"; // e.g. \"max-age=63072000; includeSubDomains; preload\"\n export const CONTENT_SECURITY_POLICY = \"Content-Security-Policy\"; // fine-grained script/style/image restrictions\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\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 POST = \"POST\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n HEAD = \"HEAD\",\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.PLAIN_TEXT,\n MediaType.HTML,\n MediaType.CSS,\n MediaType.CSV,\n MediaType.MARKDOWN,\n MediaType.XML,\n MediaType.JSON,\n MediaType.XML_APP,\n MediaType.FORM_URLENCODED,\n MediaType.NDJSON,\n MediaType.RICH_TEXT,\n MediaType.SVG,\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()))).filter((v) => v.length);\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]) => a.localeCompare(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 * 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 { HttpHeader, mergeHeader, Method, setHeader } from \"./common\";\n\n/**\n * Provides information about the CORS policy for the current request.\n */\nexport interface CorsProvider {\n /** Returns a list of allowed origins. */\n getAllowOrigins(): string[];\n\n /** Returns true if any origin is allowed (`*`). */\n allowAnyOrigin(): boolean;\n\n /** Returns the HTTP methods allowed by CORS. */\n getAllowMethods(): Method[];\n\n /** Returns the HTTP headers allowed by CORS. */\n getAllowHeaders(): string[];\n\n /** Returns the HTTP headers that should be exposed to the browser. */\n getExposeHeaders(): string[];\n\n /** Returns the max age (in seconds) for CORS preflight caching. */\n getMaxAge(): number;\n}\n\n/**\n * Constants for common CORS headers.\n */\nexport namespace Cors {\n export const ALLOW_ORIGIN = \"Access-Control-Allow-Origin\";\n export const ALLOW_CREDENTIALS = \"Access-Control-Allow-Credentials\";\n export const EXPOSE_HEADERS = \"Access-Control-Expose-Headers\";\n export const ALLOW_HEADERS = \"Access-Control-Allow-Headers\";\n export const ALLOW_METHODS = \"Access-Control-Allow-Methods\";\n export const MAX_AGE = \"Access-Control-Max-Age\";\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 and Vary: Origin.\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(origin: string | null, cors: CorsProvider, headers: Headers): void {\n deleteCorsHeaders(headers);\n\n // CORS is not required.\n if (!origin) return;\n\n if (cors.allowAnyOrigin()) {\n setHeader(headers, Cors.ALLOW_ORIGIN, Cors.ALLOW_ALL_ORIGINS);\n } else if (cors.getAllowOrigins().includes(origin)) {\n setHeader(headers, Cors.ALLOW_ORIGIN, origin);\n setHeader(headers, Cors.ALLOW_CREDENTIALS, \"true\");\n mergeHeader(headers, HttpHeader.VARY, HttpHeader.ORIGIN);\n }\n\n // Optional headers always applied if CORS.\n mergeHeader(headers, Cors.EXPOSE_HEADERS, cors.getExposeHeaders());\n setHeader(headers, Cors.ALLOW_HEADERS, cors.getAllowHeaders());\n setHeader(headers, Cors.ALLOW_METHODS, cors.getAllowMethods());\n setHeader(headers, Cors.MAX_AGE, String(cors.getMaxAge()));\n}\n\n/**\n * Deletes all standard CORS headers from the given Headers object.\n * Useful for cleaning cached responses or resetting headers before reapplying CORS.\n *\n * @param headers The Headers object to clean\n */\nfunction deleteCorsHeaders(headers: Headers) {\n headers.delete(Cors.ALLOW_ORIGIN);\n headers.delete(Cors.ALLOW_CREDENTIALS);\n headers.delete(Cors.EXPOSE_HEADERS);\n headers.delete(Cors.ALLOW_METHODS);\n headers.delete(Cors.MAX_AGE);\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, WorkerConstructor } from \"./worker\";\n\n/**\n * A type-safe Cloudflare Worker handler where `fetch` is required.\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<E = Env> extends ExportedHandler<E> {\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 - Optional execution context for background tasks (`waitUntil`).\n * @returns A `Promise` that resolves to the response.\n */\n fetch: (request: Request, env: E, ctx: ExecutionContext) => Promise<Response>;\n}\n\n/**\n * Provides the foundational structure for handling requests, environment bindings,\n * and the worker execution context. Subclasses are expected to implement the\n * `fetch` method to handle the request and return a Response.\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), if available.\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 /** Optional execution context for background tasks or `waitUntil` */\n public get ctx(): ExecutionContext {\n return this._ctx;\n }\n\n /**\n * Creates a new instance of the current Worker subclass.\n *\n * @param request - The request to pass to the new worker instance.\n * @returns A new worker instance of the same subclass as `this`.\n */\n protected createWorker(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 request and produce a Response.\n * Subclasses must implement this method.\n *\n * @returns A Promise resolving to the Response for the request\n */\n public abstract fetch(): Promise<Response>;\n\n /**\n * **Ignite** your `Worker` implementation into a Cloudflare-compatible 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: (req: Request, env: Env, ctx: ExecutionContext) =>\n new this(req, 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 { Method, Time } from \"./common\";\nimport { CorsProvider } from \"./cors\";\n\n/**\n * Abstract base class for Workers to provide a default CORS policy.\n *\n * Implements the `CorsProvider` interface and provides a standard policy:\n * - Allows all origins (`*`) by default.\n * - Allows GET, OPTIONS, and HEAD methods.\n * - Allows the `Content-Type` header.\n * - Exposes no additional headers.\n * - Sets CORS preflight max-age to one week.\n *\n * Subclasses can override any of the methods to customize the CORS behavior.\n */\nexport abstract class CorsWorker extends BaseWorker implements CorsProvider {\n public getAllowOrigins(): string[] {\n return [\"*\"];\n }\n\n public allowAnyOrigin(): boolean {\n return this.getAllowOrigins().includes(\"*\");\n }\n\n public getAllowMethods(): Method[] {\n return [Method.GET, Method.OPTIONS, Method.HEAD];\n }\n\n public getAllowHeaders(): string[] {\n return [\"Content-Type\"];\n }\n\n public getExposeHeaders(): string[] {\n return [];\n }\n\n public getMaxAge(): number {\n return Time.Week;\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, Method, normalizeUrl } from \"./common\";\nimport { addCorsHeaders, Cors } from \"./cors\";\nimport { CorsWorker } from \"./cors-worker\";\n\n/**\n * Abstract worker class that adds caching support for GET requests.\n *\n * Behavior:\n * - Caches successful GET responses (`response.ok === true`) in the selected cache.\n * - Strips CORS headers from cached responses; all other origin headers are preserved.\n * - Dynamically adds CORS headers to cached responses when returned to the client.\n *\n * Subclasses should override `getCacheKey()` to customize cache key generation if needed.\n */\nexport abstract class CacheWorker extends CorsWorker {\n /**\n * Returns the cache key for the current request.\n *\n * Behavior:\n * - By default, returns the normalized request URL.\n * - Query parameters are normalized so that the order does not affect the cache key.\n * For example, `?a=1&b=2` and `?b=2&a=1` produce the same cache key.\n *\n * Subclasses may override this method to implement custom cache key strategies.\n *\n * @returns {URL | RequestInfo} The URL or RequestInfo used as the cache key.\n */\n protected getCacheKey(): URL | RequestInfo {\n return normalizeUrl(this.request.url);\n }\n\n /**\n * Retrieves a cached Response for the current request, if one exists.\n *\n * Behavior:\n * - Only GET requests are considered.\n * - Returns a new Response with dynamic CORS headers applied via `addCacheHeaders`.\n * - Returns `undefined` if no cached response is found.\n * - Cloudflare dynamic headers (`CF-Cache-Status`, `Age`, `Connection`, etc.) will\n * always be present on the returned response, even though they are not stored in the cache.\n *\n * @param {string} [cacheName] Optional named cache; defaults to `caches.default`.\n * @returns {Promise<Response | undefined>} A Response with CORS headers, or undefined.\n * @see {@link setCachedResponse}\n * @see {@link getCacheKey}\n */\n protected async getCachedResponse(cacheName?: string): Promise<Response | undefined> {\n if (this.request.method !== Method.GET) return;\n\n const cache = cacheName ? await caches.open(cacheName) : caches.default;\n const response = await cache.match(this.getCacheKey());\n return response ? this.addCacheHeaders(response) : undefined;\n }\n\n /**\n * Stores a Response in the cache for the current request.\n *\n * Behavior:\n * - Only caches successful GET responses (`response.ok === true`).\n * - Strips headers via `removeCacheHeaders` before storing.\n * - Uses `ctx.waitUntil` to perform caching asynchronously without blocking the response.\n * - All other origin headers (e.g., Cache-Control, Expires) are preserved.\n *\n * @param {Response} response The Response to cache.\n * @param {string} [cacheName] Optional named cache; defaults to `caches.default`.\n * @see {@link getCachedResponse}\n * @see {@link getCacheKey}\n */\n protected async setCachedResponse(response: Response, cacheName?: string): Promise<void> {\n if (!response.ok) return;\n if (this.request.method !== Method.GET) return;\n\n const cache = cacheName ? await caches.open(cacheName) : caches.default;\n this.ctx.waitUntil(\n cache.put(this.getCacheKey(), this.removeCacheHeaders(response.clone()))\n );\n }\n\n /**\n * Adds headers to a cached response.\n *\n * @param {Response} cached The cached Response.\n * @returns {Response} A new Response with dynamic CORS headers applied.\n * @see {@link removeCacheHeaders}\n */\n private addCacheHeaders(cached: Response): Response {\n const headers = new Headers(cached.headers);\n addCorsHeaders(getOrigin(this.request), this, headers);\n\n return new Response(cached.body, {\n status: cached.status,\n statusText: cached.statusText,\n headers,\n });\n }\n\n /**\n * Removes headers that should not be stored in the cache (currently only CORS headers).\n *\n * @param {Response} response The Response to clean before caching.\n * @returns {Response} A new Response with excluded headers removed.\n * @see {@link addCacheHeaders}\n */\n private removeCacheHeaders(response: Response): Response {\n const excludeSet = new Set(this.excludeCacheHeaders().map((h) => h.toLowerCase()));\n const headers = new Headers();\n\n for (const [key, value] of response.headers) {\n if (!excludeSet.has(key)) {\n headers.set(key, value);\n }\n }\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n\n /**\n * Returns the list of headers to exclude from the cached response.\n * By default, excludes only dynamic CORS headers.\n *\n * @returns {string[]} Array of header names to exclude.\n * @see {@link removeCacheHeaders}\n */\n protected excludeCacheHeaders(): string[] {\n return [\n Cors.ALLOW_ORIGIN,\n Cors.ALLOW_CREDENTIALS,\n Cors.EXPOSE_HEADERS,\n Cors.ALLOW_METHODS,\n Cors.MAX_AGE,\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 { getReasonPhrase, StatusCodes } from \"http-status-codes\";\nimport {\n CacheControl,\n getContentType,\n HttpHeader,\n mergeHeader,\n Method,\n MediaType,\n setHeader,\n getOrigin,\n} from \"./common\";\nimport { addCorsHeaders, CorsProvider } from \"./cors\";\nimport { Worker } from \"./worker\";\n\nexport interface ErrorJson {\n status: number;\n error: string;\n details: string;\n}\n\n/**\n * A {@link Worker} that also implements {@link CorsProvider}.\n *\n * Used by response builders that require both Worker\n * and CORS functionality.\n */\nexport type CorsWorker = Worker & CorsProvider;\n\nabstract class BaseResponse {\n public headers: Headers = new Headers();\n public body: BodyInit | null;\n public status: StatusCodes = StatusCodes.OK;\n public statusText?: string;\n public mediaType?: MediaType;\n\n constructor(public readonly worker: CorsWorker, content: BodyInit | null = null) {\n this.body = this.status === StatusCodes.NO_CONTENT ? null : content;\n }\n\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 public setHeader(key: string, value: string | string[]): void {\n setHeader(this.headers, key, value);\n }\n\n public mergeHeader(key: string, value: string | string[]): void {\n mergeHeader(this.headers, key, value);\n }\n\n public addContentType() {\n if (this.mediaType) {\n this.headers.set(HttpHeader.CONTENT_TYPE, getContentType(this.mediaType));\n }\n }\n}\n\nabstract class CorsResponse extends BaseResponse {\n constructor(worker: CorsWorker, content: BodyInit | null = null) {\n super(worker, content);\n }\n\n protected addCorsHeaders(): void {\n addCorsHeaders(this.getOrigin(), this.worker, this.headers);\n }\n\n protected getOrigin() {\n return getOrigin(this.worker.request);\n }\n}\n\nabstract class CacheResponse extends CorsResponse {\n constructor(worker: CorsWorker, body: BodyInit | null = null, public cache?: CacheControl) {\n super(worker, body);\n }\n\n protected addCacheHeaders(): void {\n if (this.cache) {\n this.headers.set(HttpHeader.CACHE_CONTROL, CacheControl.stringify(this.cache));\n }\n }\n}\n\nexport abstract class WorkerResponse extends CacheResponse {\n public createResponse(): Response {\n this.addCorsHeaders();\n this.addCacheHeaders();\n this.addSecurityHeaders();\n\n const body = this.status === StatusCodes.NO_CONTENT ? null : this.body;\n if (body) this.addContentType();\n return new Response(body, this.responseInit);\n }\n\n protected addSecurityHeaders(): void {\n this.setHeader(HttpHeader.X_CONTENT_TYPE_OPTIONS, HttpHeader.NOSNIFF);\n }\n}\n\nexport class ClonedResponse extends WorkerResponse {\n constructor(worker: CorsWorker, 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\nexport class SuccessResponse extends WorkerResponse {\n constructor(\n worker: CorsWorker,\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\nexport class JsonResponse extends SuccessResponse {\n constructor(\n worker: CorsWorker,\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\nexport class HtmlResponse extends SuccessResponse {\n constructor(\n worker: CorsWorker,\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\nexport class TextResponse extends SuccessResponse {\n constructor(\n worker: CorsWorker,\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 * Removes the body from a GET response.\n */\nexport class Head extends WorkerResponse {\n constructor(worker: CorsWorker, get: Response) {\n super(worker);\n this.headers = new Headers(get.headers);\n }\n}\n\nexport class Options extends SuccessResponse {\n constructor(worker: CorsWorker) {\n super(worker, null, undefined, StatusCodes.NO_CONTENT);\n this.setHeader(\"Allow\", this.worker.getAllowMethods());\n }\n}\n\nexport class HttpError extends JsonResponse {\n constructor(worker: CorsWorker, status: StatusCodes, protected readonly details?: string) {\n super(worker, undefined, CacheControl.DISABLE, status);\n }\n\n public get json(): ErrorJson {\n return {\n status: this.status,\n error: getReasonPhrase(this.status),\n details: this.details ?? getReasonPhrase(this.status),\n };\n }\n\n public override createResponse(): Response {\n this.body = JSON.stringify(this.json);\n return super.createResponse();\n }\n}\n\nexport class BadRequest extends HttpError {\n constructor(worker: CorsWorker, details?: string) {\n super(worker, StatusCodes.BAD_REQUEST, details);\n }\n}\n\nexport class Unauthorized extends HttpError {\n constructor(worker: CorsWorker, details?: string) {\n super(worker, StatusCodes.UNAUTHORIZED, details);\n }\n}\n\nexport class Forbidden extends HttpError {\n constructor(worker: CorsWorker, details?: string) {\n super(worker, StatusCodes.FORBIDDEN, details);\n }\n}\n\nexport class NotFound extends HttpError {\n constructor(worker: CorsWorker, details?: string) {\n super(worker, StatusCodes.NOT_FOUND, details);\n }\n}\n\nexport class MethodNotAllowed extends HttpError {\n constructor(worker: CorsWorker, method: string) {\n super(worker, StatusCodes.METHOD_NOT_ALLOWED, `${method} method not allowed.`);\n this.setHeader(\"Allow\", this.worker.getAllowMethods());\n }\n\n public override get json(): ErrorJson & { allowed: Method[] } {\n return {\n ...super.json,\n allowed: this.worker.getAllowMethods(),\n };\n }\n}\n\nexport class InternalServerError extends HttpError {\n constructor(worker: CorsWorker, details?: string) {\n super(worker, StatusCodes.INTERNAL_SERVER_ERROR, details);\n }\n}\n\nexport class NotImplemented extends HttpError {\n constructor(worker: CorsWorker, details?: string) {\n super(worker, StatusCodes.NOT_IMPLEMENTED, details);\n }\n}\n\nexport class MethodNotImplemented extends NotImplemented {\n constructor(worker: CorsWorker, method: Method) {\n super(worker, `${method} method not implemented.`);\n }\n}\n\nexport class ServiceUnavailable extends HttpError {\n constructor(worker: CorsWorker, 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 { CacheWorker } from \"./cache-worker\";\nimport { isMethod, Method } from \"./common\";\nimport {\n CorsWorker,\n Head,\n InternalServerError,\n MethodNotAllowed,\n MethodNotImplemented,\n Options,\n WorkerResponse,\n} from \"./response\";\n\nexport abstract class BasicWorker extends CacheWorker {\n public async fetch(): Promise<Response> {\n if (!this.isAllowed(this.request.method)) {\n return this.getResponse(MethodNotAllowed, this.request.method);\n }\n\n try {\n return await this.dispatch();\n } catch (error) {\n return this.getResponse(InternalServerError, String(error));\n }\n }\n\n protected async dispatch(): Promise<Response> {\n const method = this.request.method as Method;\n const handler: Record<Method, () => Promise<Response>> = {\n GET: () => this.get(),\n PUT: () => this.put(),\n POST: () => this.post(),\n PATCH: () => this.patch(),\n DELETE: () => this.delete(),\n HEAD: () => this.head(),\n OPTIONS: () => this.options(),\n };\n return (handler[method] ?? (() => this.getResponse(MethodNotAllowed, method)))();\n }\n\n protected async get(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.GET);\n }\n\n protected async put(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.PUT);\n }\n\n protected async post(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.POST);\n }\n\n protected async patch(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.PATCH);\n }\n\n protected async delete(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.DELETE);\n }\n\n protected async options(): Promise<Response> {\n return this.getResponse(Options);\n }\n\n protected async head(): Promise<Response> {\n const worker = this.createWorker(new Request(this.request, { method: \"GET\" }));\n return this.getResponse(Head, await worker.fetch());\n }\n\n protected async getResponse<\n T extends WorkerResponse,\n Ctor extends new (worker: CorsWorker, ...args: any[]) => T\n >(\n ResponseClass: Ctor,\n ...args: ConstructorParameters<Ctor> extends [CorsWorker, ...infer R] ? R : never\n ): Promise<Response> {\n const response = new ResponseClass(this, ...args).createResponse();\n this.setCachedResponse(response);\n return response;\n }\n\n public isAllowed(method: string): boolean {\n return isMethod(method) && this.getAllowMethods().includes(method);\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\";\n\n/**\n * A callback function for a route.\n *\n * @param matches - Captured groups from the route RegExp, or the full match at index 0\n * @returns A Response object or a Promise that resolves to a Response\n */\nexport type RouteCallback = (...matches: string[]) => Response | Promise<Response>;\n\n/**\n * Tuple used to initialize a route.\n *\n * [HTTP method, path pattern (string or RegExp), callback function]\n */\nexport type RouteInit = [Method, RegExp | string, RouteCallback];\n\n/**\n * Represents a single route with a pattern and a callback.\n */\nexport class Route {\n public readonly pattern: RegExp;\n\n /**\n * @param pattern - A RegExp or string used to match the request path\n * @param callback - Function to handle requests matching the pattern\n */\n constructor(pattern: RegExp | string, public readonly callback: RouteCallback) {\n this.pattern = new RegExp(pattern);\n }\n}\n\n/**\n * A collection of routes grouped by HTTP method.\n *\n * Supports adding routes and retrieving the first matching route for a given method and URL.\n */\nexport class Routes {\n private readonly map = new Map<Method, Route[]>();\n\n /**\n * Adds a route to the collection under the given HTTP method.\n *\n * @param method - HTTP method (GET, POST, etc.)\n * @param route - Route instance to add\n * @returns The Routes instance (for chaining)\n */\n public add(method: Method, route: Route): this {\n const existing = this.map.get(method);\n if (existing) {\n existing.push(route);\n } else {\n this.map.set(method, [route]);\n }\n return this;\n }\n\n /**\n * Finds the first route that matches the given method and URL.\n *\n * @param method - HTTP method of the request\n * @param url - Full URL string of the request\n * @returns The first matching Route, or undefined if none match\n */\n public get(method: Method, url: string): Route | undefined {\n const routes = this.map.get(method);\n if (!routes) return undefined;\n\n const pathname = new URL(url).pathname;\n return routes.find(({ pattern }) => pattern.test(pathname));\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 \"./response\";\nimport { Route, Routes, RouteInit, RouteCallback } from \"./routes\";\n\nexport abstract class RoutedWorker extends BasicWorker {\n private readonly routes: Routes = new Routes();\n\n protected initialize(routes: RouteInit[]) {\n routes.forEach(([method, pattern, callback]) => {\n this.add(method, pattern, callback);\n });\n }\n\n protected add(method: Method, pattern: RegExp | string, callback: RouteCallback) {\n this.routes.add(method, new Route(pattern, callback));\n return this;\n }\n\n protected async dispatch(request: Request = this.request): Promise<Response> {\n const route = this.routes.get(request.method as Method, request.url);\n if (!route) return super.dispatch();\n\n const match = new URL(request.url).pathname.match(route.pattern) ?? [];\n return route.callback.call(this, ...match);\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"],"mappings":"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","names":["HttpHeader","Method","MediaType","Cors","StatusCodes","StatusCodes"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adonix.org/cloud-spark",
3
- "version": "0.0.92",
3
+ "version": "0.0.94",
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",