@adonix.org/cloud-spark 0.0.123 → 0.0.124

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
@@ -27,6 +27,7 @@ declare namespace HttpHeader {
27
27
  const ALLOW = "Allow";
28
28
  const CONTENT_TYPE = "Content-Type";
29
29
  const CACHE_CONTROL = "Cache-Control";
30
+ const USER_AGENT = "User-Agent";
30
31
  const X_FRAME_OPTIONS = "X-Frame-Options";
31
32
  const X_CONTENT_TYPE_OPTIONS = "X-Content-Type-Options";
32
33
  const REFERRER_POLICY = "Referrer-Policy";
@@ -441,6 +442,194 @@ declare class Routes implements Iterable<Route> {
441
442
  [Symbol.iterator](): Iterator<Route>;
442
443
  }
443
444
 
445
+ /**
446
+ * Configuration options for Cross-Origin Resource Sharing (CORS).
447
+ *
448
+ * Implementations of CORS middleware use this interface to determine
449
+ * how cross-origin requests are validated and which headers are sent
450
+ * in the response.
451
+ */
452
+ interface CorsConfig {
453
+ /**
454
+ * Origins allowed for CORS requests.
455
+ *
456
+ * Use `["*"]` to allow all origins, or provide a list of specific origins.
457
+ * Example: `["https://example.com", "https://api.example.com"]`
458
+ */
459
+ allowedOrigins: string[];
460
+ /**
461
+ * HTTP headers allowed in CORS requests.
462
+ *
463
+ * Requests that include headers not listed here will be blocked
464
+ * during the preflight check.
465
+ */
466
+ allowedHeaders: string[];
467
+ /**
468
+ * HTTP headers exposed to the client.
469
+ *
470
+ * By default, most headers are not accessible from client-side JavaScript.
471
+ * Use this option to explicitly allow certain response headers to be read.
472
+ */
473
+ exposedHeaders: string[];
474
+ /**
475
+ * Maximum age (in seconds) that the results of a preflight request
476
+ * can be cached by the client.
477
+ *
478
+ * Example: `60 * 60 * 24 * 7` (1 week).
479
+ */
480
+ maxAge: number;
481
+ }
482
+
483
+ /**
484
+ * Structure for JSON-formatted error responses.
485
+ *
486
+ * This interface defines the standard shape of error responses returned
487
+ * by middleware or workers when an operation fails. It ensures consistent
488
+ * error reporting and easy parsing by clients.
489
+ */
490
+ interface ErrorJson {
491
+ /**
492
+ * HTTP status code associated with the error.
493
+ *
494
+ * Example: `404` for Not Found, `500` for Internal Server Error.
495
+ */
496
+ status: number;
497
+ /**
498
+ * Standard HTTP reason phrase corresponding to the status code.
499
+ *
500
+ * Example: `"Not Found"` for 404, `"Internal Server Error"` for 500.
501
+ */
502
+ error: string;
503
+ /**
504
+ * Optional detailed message describing the error.
505
+ *
506
+ * This can include additional context, debugging hints, or
507
+ * information useful to the client. May be an empty string
508
+ * if no details are provided.
509
+ */
510
+ details: string;
511
+ }
512
+
513
+ /**
514
+ * Abstract base class for middleware.
515
+ *
516
+ * Middleware classes implement request/response processing logic in a
517
+ * chainable manner. Each middleware receives a `Worker` object and a
518
+ * `next` function that invokes the next middleware in the chain.
519
+ *
520
+ * Subclasses **must implement** the `handle` method.
521
+ *
522
+ * Example subclass:
523
+ * ```ts
524
+ * class LoggingMiddleware extends Middleware {
525
+ * public async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {
526
+ * console.log(`Processing request: ${worker.request.url}`);
527
+ * const response = await next();
528
+ * console.log(`Response status: ${response.status}`);
529
+ * return response;
530
+ * }
531
+ * }
532
+ * ```
533
+ */
534
+ declare abstract class Middleware {
535
+ /**
536
+ * Process a request in the middleware chain.
537
+ *
538
+ * @param worker - The `Worker` instance representing the request context.
539
+ * @param next - Function to invoke the next middleware in the chain.
540
+ * Must be called to continue the chain unless the middleware
541
+ * terminates early (e.g., returns a response directly).
542
+ * @returns A `Response` object, either returned directly or from `next()`.
543
+ */
544
+ abstract handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
545
+ }
546
+
547
+ /**
548
+ * Middleware that applies Cross-Origin Resource Sharing (CORS) headers to responses.
549
+ *
550
+ * This middleware reads the configuration provided (or uses `defaultCorsConfig`)
551
+ * and ensures that responses include the appropriate CORS headers. It also
552
+ * handles the `Vary: Origin` header when not allowing all origins.
553
+ *
554
+ * Example usage:
555
+ * ```ts
556
+ * const cors = new CorsHandler({ allowedOrigins: ["https://myapp.com"] });
557
+ * worker.use(cors);
558
+ * ```
559
+ */
560
+ declare class CorsHandler extends Middleware {
561
+ /** The configuration used for this instance, with all defaults applied. */
562
+ private readonly config;
563
+ /**
564
+ * Create a new CORS middleware instance.
565
+ *
566
+ * @param init - Partial configuration to override the defaults. Any values
567
+ * not provided will use `defaultCorsConfig`.
568
+ */
569
+ constructor(init?: Partial<CorsConfig>);
570
+ /**
571
+ * Handle a request by applying CORS headers to the response.
572
+ *
573
+ * @param worker - The Worker instance containing the request context.
574
+ * @param next - Function to invoke the next middleware in the chain.
575
+ * @returns A Response object with CORS headers applied.
576
+ *
577
+ * This middleware does not short-circuit the request; it always calls `next()`
578
+ * and modifies the resulting response.
579
+ */
580
+ handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
581
+ }
582
+
583
+ /**
584
+ * Middleware for caching GET requests.
585
+ *
586
+ * This middleware checks a cache (either a named cache or the default)
587
+ * before passing the request down the middleware chain. Responses for
588
+ * successful GET requests are automatically stored in the cache.
589
+ *
590
+ * Non-GET requests are never cached. The cache key can be customized
591
+ * via the `getKey` function; otherwise, the URL is normalized and used.
592
+ *
593
+ * Example usage:
594
+ * ```ts
595
+ * const cacheMiddleware = new CacheHandler("my-cache", (req) => new URL(req.url));
596
+ * worker.use(cacheMiddleware);
597
+ * ```
598
+ */
599
+ declare class CacheHandler extends Middleware {
600
+ protected readonly cacheName?: string | undefined;
601
+ protected readonly getKey?: ((request: Request) => URL | RequestInfo) | undefined;
602
+ /**
603
+ * @param cacheName - Optional name of the cache to use. If omitted,
604
+ * `caches.default` is used.
605
+ * @param getKey - Optional function to generate a cache key from a request.
606
+ * Defaults to using the normalized request URL.
607
+ */
608
+ constructor(cacheName?: string | undefined, getKey?: ((request: Request) => URL | RequestInfo) | undefined);
609
+ /**
610
+ * Handle a request in the caching middleware.
611
+ *
612
+ * Checks the cache for GET requests and returns the cached response if available.
613
+ * Otherwise, calls `next()` to continue the middleware chain and caches
614
+ * the response if successful.
615
+ *
616
+ * @param worker - The Worker instance containing the request context.
617
+ * @param next - Function to invoke the next middleware in the chain.
618
+ * @returns A Response object, either from cache or the next middleware.
619
+ */
620
+ handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
621
+ /**
622
+ * Generate the cache key for a request.
623
+ *
624
+ * @param request - The Request object to generate a cache key for.
625
+ * @returns A URL or RequestInfo used as the cache key.
626
+ *
627
+ * If a custom `getKey` function was provided in the constructor, it is used.
628
+ * Otherwise, the request URL is normalized.
629
+ */
630
+ getCacheKey(request: Request): URL | RequestInfo;
631
+ }
632
+
444
633
  /**
445
634
  * A type-safe Cloudflare Worker handler.
446
635
  *
@@ -532,40 +721,6 @@ declare abstract class BaseWorker implements Worker {
532
721
  static ignite<W extends Worker>(this: WorkerConstructor<W>): FetchHandler;
533
722
  }
534
723
 
535
- /**
536
- * Abstract base class for middleware.
537
- *
538
- * Middleware classes implement request/response processing logic in a
539
- * chainable manner. Each middleware receives a `Worker` object and a
540
- * `next` function that invokes the next middleware in the chain.
541
- *
542
- * Subclasses **must implement** the `handle` method.
543
- *
544
- * Example subclass:
545
- * ```ts
546
- * class LoggingMiddleware extends Middleware {
547
- * public async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {
548
- * console.log(`Processing request: ${worker.request.url}`);
549
- * const response = await next();
550
- * console.log(`Response status: ${response.status}`);
551
- * return response;
552
- * }
553
- * }
554
- * ```
555
- */
556
- declare abstract class Middleware {
557
- /**
558
- * Process a request in the middleware chain.
559
- *
560
- * @param worker - The `Worker` instance representing the request context.
561
- * @param next - Function to invoke the next middleware in the chain.
562
- * Must be called to continue the chain unless the middleware
563
- * terminates early (e.g., returns a response directly).
564
- * @returns A `Response` object, either returned directly or from `next()`.
565
- */
566
- abstract handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
567
- }
568
-
569
724
  /** Internal base worker for handling middleware chains. */
570
725
  declare abstract class MiddlewareWorker extends BaseWorker {
571
726
  /** Middleware handlers registered for this worker. */
@@ -684,158 +839,4 @@ declare abstract class RouteWorker extends BasicWorker {
684
839
  protected delete(): Promise<Response>;
685
840
  }
686
841
 
687
- /**
688
- * Configuration options for Cross-Origin Resource Sharing (CORS).
689
- *
690
- * Implementations of CORS middleware use this interface to determine
691
- * how cross-origin requests are validated and which headers are sent
692
- * in the response.
693
- */
694
- interface CorsConfig {
695
- /**
696
- * Origins allowed for CORS requests.
697
- *
698
- * Use `["*"]` to allow all origins, or provide a list of specific origins.
699
- * Example: `["https://example.com", "https://api.example.com"]`
700
- */
701
- allowedOrigins: string[];
702
- /**
703
- * HTTP headers allowed in CORS requests.
704
- *
705
- * Requests that include headers not listed here will be blocked
706
- * during the preflight check.
707
- */
708
- allowedHeaders: string[];
709
- /**
710
- * HTTP headers exposed to the client.
711
- *
712
- * By default, most headers are not accessible from client-side JavaScript.
713
- * Use this option to explicitly allow certain response headers to be read.
714
- */
715
- exposedHeaders: string[];
716
- /**
717
- * Maximum age (in seconds) that the results of a preflight request
718
- * can be cached by the client.
719
- *
720
- * Example: `60 * 60 * 24 * 7` (1 week).
721
- */
722
- maxAge: number;
723
- }
724
-
725
- /**
726
- * Structure for JSON-formatted error responses.
727
- *
728
- * This interface defines the standard shape of error responses returned
729
- * by middleware or workers when an operation fails. It ensures consistent
730
- * error reporting and easy parsing by clients.
731
- */
732
- interface ErrorJson {
733
- /**
734
- * HTTP status code associated with the error.
735
- *
736
- * Example: `404` for Not Found, `500` for Internal Server Error.
737
- */
738
- status: number;
739
- /**
740
- * Standard HTTP reason phrase corresponding to the status code.
741
- *
742
- * Example: `"Not Found"` for 404, `"Internal Server Error"` for 500.
743
- */
744
- error: string;
745
- /**
746
- * Optional detailed message describing the error.
747
- *
748
- * This can include additional context, debugging hints, or
749
- * information useful to the client. May be an empty string
750
- * if no details are provided.
751
- */
752
- details: string;
753
- }
754
-
755
- /**
756
- * Middleware that applies Cross-Origin Resource Sharing (CORS) headers to responses.
757
- *
758
- * This middleware reads the configuration provided (or uses `defaultCorsConfig`)
759
- * and ensures that responses include the appropriate CORS headers. It also
760
- * handles the `Vary: Origin` header when not allowing all origins.
761
- *
762
- * Example usage:
763
- * ```ts
764
- * const cors = new CorsHandler({ allowedOrigins: ["https://myapp.com"] });
765
- * worker.use(cors);
766
- * ```
767
- */
768
- declare class CorsHandler extends Middleware {
769
- /** The configuration used for this instance, with all defaults applied. */
770
- private readonly config;
771
- /**
772
- * Create a new CORS middleware instance.
773
- *
774
- * @param init - Partial configuration to override the defaults. Any values
775
- * not provided will use `defaultCorsConfig`.
776
- */
777
- constructor(init?: Partial<CorsConfig>);
778
- /**
779
- * Handle a request by applying CORS headers to the response.
780
- *
781
- * @param worker - The Worker instance containing the request context.
782
- * @param next - Function to invoke the next middleware in the chain.
783
- * @returns A Response object with CORS headers applied.
784
- *
785
- * This middleware does not short-circuit the request; it always calls `next()`
786
- * and modifies the resulting response.
787
- */
788
- handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
789
- }
790
-
791
- /**
792
- * Middleware for caching GET requests.
793
- *
794
- * This middleware checks a cache (either a named cache or the default)
795
- * before passing the request down the middleware chain. Responses for
796
- * successful GET requests are automatically stored in the cache.
797
- *
798
- * Non-GET requests are never cached. The cache key can be customized
799
- * via the `getKey` function; otherwise, the URL is normalized and used.
800
- *
801
- * Example usage:
802
- * ```ts
803
- * const cacheMiddleware = new CacheHandler("my-cache", (req) => new URL(req.url));
804
- * worker.use(cacheMiddleware);
805
- * ```
806
- */
807
- declare class CacheHandler extends Middleware {
808
- protected readonly cacheName?: string | undefined;
809
- protected readonly getKey?: ((request: Request) => URL | RequestInfo) | undefined;
810
- /**
811
- * @param cacheName - Optional name of the cache to use. If omitted,
812
- * `caches.default` is used.
813
- * @param getKey - Optional function to generate a cache key from a request.
814
- * Defaults to using the normalized request URL.
815
- */
816
- constructor(cacheName?: string | undefined, getKey?: ((request: Request) => URL | RequestInfo) | undefined);
817
- /**
818
- * Handle a request in the caching middleware.
819
- *
820
- * Checks the cache for GET requests and returns the cached response if available.
821
- * Otherwise, calls `next()` to continue the middleware chain and caches
822
- * the response if successful.
823
- *
824
- * @param worker - The Worker instance containing the request context.
825
- * @param next - Function to invoke the next middleware in the chain.
826
- * @returns A Response object, either from cache or the next middleware.
827
- */
828
- handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;
829
- /**
830
- * Generate the cache key for a request.
831
- *
832
- * @param request - The Request object to generate a cache key for.
833
- * @returns A URL or RequestInfo used as the cache key.
834
- *
835
- * If a custom `getKey` function was provided in the constructor, it is used.
836
- * Otherwise, the request URL is normalized.
837
- */
838
- getCacheKey(request: Request): URL | RequestInfo;
839
- }
840
-
841
842
  export { BadRequest, BasicWorker, CacheControl, CacheHandler, ClonedResponse, type CorsConfig, CorsHandler, type ErrorJson, Forbidden, Head, HtmlResponse, HttpError, HttpHeader, InternalServerError, JsonResponse, type MatchedRoute, MediaType, Method, MethodNotAllowed, MethodNotImplemented, NotFound, NotImplemented, Options, type Route, type RouteCallback, type RouteParams, type RouteTable, RouteWorker, Routes, ServiceUnavailable, SuccessResponse, TextResponse, Time, Unauthorized, type Worker, WorkerResponse, getContentType, getOrigin, isMethod, lexCompare, mergeHeader, normalizeUrl, setHeader };
package/dist/index.js CHANGED
@@ -18,6 +18,7 @@ var HttpHeader;
18
18
  HttpHeader2.ALLOW = "Allow";
19
19
  HttpHeader2.CONTENT_TYPE = "Content-Type";
20
20
  HttpHeader2.CACHE_CONTROL = "Cache-Control";
21
+ HttpHeader2.USER_AGENT = "User-Agent";
21
22
  HttpHeader2.X_FRAME_OPTIONS = "X-Frame-Options";
22
23
  HttpHeader2.X_CONTENT_TYPE_OPTIONS = "X-Content-Type-Options";
23
24
  HttpHeader2.REFERRER_POLICY = "Referrer-Policy";
@@ -397,6 +398,135 @@ var Routes = class {
397
398
  }
398
399
  };
399
400
 
401
+ // src/middleware/cors/utils.ts
402
+ function addCorsHeaders(worker, cors, headers) {
403
+ deleteCorsHeaders(headers);
404
+ const origin = getOrigin(worker.request);
405
+ if (!origin || origin.trim() === "") return;
406
+ if (allowAnyOrigin(cors)) {
407
+ setHeader(headers, HttpHeader.ALLOW_ORIGIN, HttpHeader.ALLOW_ALL_ORIGINS);
408
+ } else if (cors.allowedOrigins.includes(origin)) {
409
+ setHeader(headers, HttpHeader.ALLOW_ORIGIN, origin);
410
+ setHeader(headers, HttpHeader.ALLOW_CREDENTIALS, "true");
411
+ }
412
+ setHeader(headers, HttpHeader.MAX_AGE, String(cors.maxAge));
413
+ setHeader(headers, HttpHeader.ALLOW_METHODS, worker.getAllowedMethods());
414
+ setHeader(headers, HttpHeader.ALLOW_HEADERS, cors.allowedHeaders);
415
+ mergeHeader(headers, HttpHeader.EXPOSE_HEADERS, cors.exposedHeaders);
416
+ }
417
+ function allowAnyOrigin(cors) {
418
+ return cors.allowedOrigins.includes("*");
419
+ }
420
+ function deleteCorsHeaders(headers) {
421
+ headers.delete(HttpHeader.MAX_AGE);
422
+ headers.delete(HttpHeader.ALLOW_ORIGIN);
423
+ headers.delete(HttpHeader.ALLOW_HEADERS);
424
+ headers.delete(HttpHeader.ALLOW_METHODS);
425
+ headers.delete(HttpHeader.EXPOSE_HEADERS);
426
+ headers.delete(HttpHeader.ALLOW_CREDENTIALS);
427
+ }
428
+
429
+ // src/middleware/middleware.ts
430
+ var Middleware = class {
431
+ };
432
+
433
+ // src/middleware/cors/defaults.ts
434
+ var defaultCorsConfig = {
435
+ allowedOrigins: ["*"],
436
+ // Origins allowed for CORS requests
437
+ allowedHeaders: ["Content-Type"],
438
+ // HTTP headers allowed in requests
439
+ exposedHeaders: [],
440
+ // Headers exposed to the client
441
+ maxAge: Time.Week
442
+ // Max age in seconds for preflight caching
443
+ };
444
+
445
+ // src/middleware/cors/handler.ts
446
+ var CorsHandler = class extends Middleware {
447
+ /** The configuration used for this instance, with all defaults applied. */
448
+ config;
449
+ /**
450
+ * Create a new CORS middleware instance.
451
+ *
452
+ * @param init - Partial configuration to override the defaults. Any values
453
+ * not provided will use `defaultCorsConfig`.
454
+ */
455
+ constructor(init) {
456
+ super();
457
+ this.config = { ...defaultCorsConfig, ...init };
458
+ }
459
+ /**
460
+ * Handle a request by applying CORS headers to the response.
461
+ *
462
+ * @param worker - The Worker instance containing the request context.
463
+ * @param next - Function to invoke the next middleware in the chain.
464
+ * @returns A Response object with CORS headers applied.
465
+ *
466
+ * This middleware does not short-circuit the request; it always calls `next()`
467
+ * and modifies the resulting response.
468
+ */
469
+ async handle(worker, next) {
470
+ const response = await next();
471
+ const mutable = new Response(response.body, response);
472
+ addCorsHeaders(worker, this.config, mutable.headers);
473
+ if (!allowAnyOrigin(this.config)) {
474
+ mergeHeader(mutable.headers, "Vary", "Origin");
475
+ }
476
+ return mutable;
477
+ }
478
+ };
479
+
480
+ // src/middleware/cache/handler.ts
481
+ var CacheHandler = class extends Middleware {
482
+ /**
483
+ * @param cacheName - Optional name of the cache to use. If omitted,
484
+ * `caches.default` is used.
485
+ * @param getKey - Optional function to generate a cache key from a request.
486
+ * Defaults to using the normalized request URL.
487
+ */
488
+ constructor(cacheName, getKey) {
489
+ super();
490
+ this.cacheName = cacheName;
491
+ this.getKey = getKey;
492
+ }
493
+ /**
494
+ * Handle a request in the caching middleware.
495
+ *
496
+ * Checks the cache for GET requests and returns the cached response if available.
497
+ * Otherwise, calls `next()` to continue the middleware chain and caches
498
+ * the response if successful.
499
+ *
500
+ * @param worker - The Worker instance containing the request context.
501
+ * @param next - Function to invoke the next middleware in the chain.
502
+ * @returns A Response object, either from cache or the next middleware.
503
+ */
504
+ async handle(worker, next) {
505
+ const cache = this.cacheName ? await caches.open(this.cacheName) : caches.default;
506
+ if (worker.request.method === "GET" /* GET */) {
507
+ const cached = await cache.match(this.getCacheKey(worker.request));
508
+ if (cached) return cached;
509
+ }
510
+ const response = await next();
511
+ if (worker.request.method === "GET" /* GET */ && response.ok) {
512
+ worker.ctx.waitUntil(cache.put(this.getCacheKey(worker.request), response.clone()));
513
+ }
514
+ return response;
515
+ }
516
+ /**
517
+ * Generate the cache key for a request.
518
+ *
519
+ * @param request - The Request object to generate a cache key for.
520
+ * @returns A URL or RequestInfo used as the cache key.
521
+ *
522
+ * If a custom `getKey` function was provided in the constructor, it is used.
523
+ * Otherwise, the request URL is normalized.
524
+ */
525
+ getCacheKey(request) {
526
+ return this.getKey ? this.getKey(request) : normalizeUrl(request.url);
527
+ }
528
+ };
529
+
400
530
  // src/workers/base-worker.ts
401
531
  var BaseWorker = class {
402
532
  constructor(_request, _env, _ctx) {
@@ -627,135 +757,6 @@ var RouteWorker = class extends BasicWorker {
627
757
  return this.getResponse(NotFound);
628
758
  }
629
759
  };
630
-
631
- // src/middleware/cors/utils.ts
632
- function addCorsHeaders(worker, cors, headers) {
633
- deleteCorsHeaders(headers);
634
- const origin = getOrigin(worker.request);
635
- if (!origin || origin.trim() === "") return;
636
- if (allowAnyOrigin(cors)) {
637
- setHeader(headers, HttpHeader.ALLOW_ORIGIN, HttpHeader.ALLOW_ALL_ORIGINS);
638
- } else if (cors.allowedOrigins.includes(origin)) {
639
- setHeader(headers, HttpHeader.ALLOW_ORIGIN, origin);
640
- setHeader(headers, HttpHeader.ALLOW_CREDENTIALS, "true");
641
- }
642
- setHeader(headers, HttpHeader.MAX_AGE, String(cors.maxAge));
643
- setHeader(headers, HttpHeader.ALLOW_METHODS, worker.getAllowedMethods());
644
- setHeader(headers, HttpHeader.ALLOW_HEADERS, cors.allowedHeaders);
645
- mergeHeader(headers, HttpHeader.EXPOSE_HEADERS, cors.exposedHeaders);
646
- }
647
- function allowAnyOrigin(cors) {
648
- return cors.allowedOrigins.includes("*");
649
- }
650
- function deleteCorsHeaders(headers) {
651
- headers.delete(HttpHeader.MAX_AGE);
652
- headers.delete(HttpHeader.ALLOW_ORIGIN);
653
- headers.delete(HttpHeader.ALLOW_HEADERS);
654
- headers.delete(HttpHeader.ALLOW_METHODS);
655
- headers.delete(HttpHeader.EXPOSE_HEADERS);
656
- headers.delete(HttpHeader.ALLOW_CREDENTIALS);
657
- }
658
-
659
- // src/middleware/middleware.ts
660
- var Middleware = class {
661
- };
662
-
663
- // src/middleware/cors/defaults.ts
664
- var defaultCorsConfig = {
665
- allowedOrigins: ["*"],
666
- // Origins allowed for CORS requests
667
- allowedHeaders: ["Content-Type"],
668
- // HTTP headers allowed in requests
669
- exposedHeaders: [],
670
- // Headers exposed to the client
671
- maxAge: Time.Week
672
- // Max age in seconds for preflight caching
673
- };
674
-
675
- // src/middleware/cors/handler.ts
676
- var CorsHandler = class extends Middleware {
677
- /** The configuration used for this instance, with all defaults applied. */
678
- config;
679
- /**
680
- * Create a new CORS middleware instance.
681
- *
682
- * @param init - Partial configuration to override the defaults. Any values
683
- * not provided will use `defaultCorsConfig`.
684
- */
685
- constructor(init) {
686
- super();
687
- this.config = { ...defaultCorsConfig, ...init };
688
- }
689
- /**
690
- * Handle a request by applying CORS headers to the response.
691
- *
692
- * @param worker - The Worker instance containing the request context.
693
- * @param next - Function to invoke the next middleware in the chain.
694
- * @returns A Response object with CORS headers applied.
695
- *
696
- * This middleware does not short-circuit the request; it always calls `next()`
697
- * and modifies the resulting response.
698
- */
699
- async handle(worker, next) {
700
- const response = await next();
701
- const mutable = new Response(response.body, response);
702
- addCorsHeaders(worker, this.config, mutable.headers);
703
- if (!allowAnyOrigin(this.config)) {
704
- mergeHeader(mutable.headers, "Vary", "Origin");
705
- }
706
- return mutable;
707
- }
708
- };
709
-
710
- // src/middleware/cache/handler.ts
711
- var CacheHandler = class extends Middleware {
712
- /**
713
- * @param cacheName - Optional name of the cache to use. If omitted,
714
- * `caches.default` is used.
715
- * @param getKey - Optional function to generate a cache key from a request.
716
- * Defaults to using the normalized request URL.
717
- */
718
- constructor(cacheName, getKey) {
719
- super();
720
- this.cacheName = cacheName;
721
- this.getKey = getKey;
722
- }
723
- /**
724
- * Handle a request in the caching middleware.
725
- *
726
- * Checks the cache for GET requests and returns the cached response if available.
727
- * Otherwise, calls `next()` to continue the middleware chain and caches
728
- * the response if successful.
729
- *
730
- * @param worker - The Worker instance containing the request context.
731
- * @param next - Function to invoke the next middleware in the chain.
732
- * @returns A Response object, either from cache or the next middleware.
733
- */
734
- async handle(worker, next) {
735
- const cache = this.cacheName ? await caches.open(this.cacheName) : caches.default;
736
- if (worker.request.method === "GET" /* GET */) {
737
- const cached = await cache.match(this.getCacheKey(worker.request));
738
- if (cached) return cached;
739
- }
740
- const response = await next();
741
- if (worker.request.method === "GET" /* GET */ && response.ok) {
742
- worker.ctx.waitUntil(cache.put(this.getCacheKey(worker.request), response.clone()));
743
- }
744
- return response;
745
- }
746
- /**
747
- * Generate the cache key for a request.
748
- *
749
- * @param request - The Request object to generate a cache key for.
750
- * @returns A URL or RequestInfo used as the cache key.
751
- *
752
- * If a custom `getKey` function was provided in the constructor, it is used.
753
- * Otherwise, the request URL is normalized.
754
- */
755
- getCacheKey(request) {
756
- return this.getKey ? this.getKey(request) : normalizeUrl(request.url);
757
- }
758
- };
759
760
  export {
760
761
  BadRequest,
761
762
  BasicWorker,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/common.ts","../src/errors.ts","../src/responses.ts","../src/routes.ts","../src/workers/base-worker.ts","../src/workers/middleware-worker.ts","../src/workers/basic-worker.ts","../src/workers/route-worker.ts","../src/middleware/cors/utils.ts","../src/middleware/middleware.ts","../src/middleware/cors/defaults.ts","../src/middleware/cors/handler.ts","../src/middleware/cache/handler.ts"],"sourcesContent":["/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport CacheLib from \"cache-control-parser\";\n\n/**\n * @see {@link https://github.com/etienne-martin/cache-control-parser | cache-control-parser}\n */\nexport type CacheControl = CacheLib.CacheControl;\nexport const CacheControl = {\n parse: CacheLib.parse,\n stringify: CacheLib.stringify,\n\n /** A Cache-Control directive that disables all caching. */\n DISABLE: Object.freeze({\n \"no-cache\": true,\n \"no-store\": true,\n \"must-revalidate\": true,\n \"max-age\": 0,\n }) satisfies CacheControl,\n};\n\n/**\n * https://github.com/prettymuchbryce/http-status-codes\n */\nexport { StatusCodes } from \"http-status-codes\";\n\n/**\n * Standard HTTP header names and common values.\n */\nexport namespace HttpHeader {\n export const VARY = \"Vary\";\n export const ALLOW = \"Allow\";\n export const CONTENT_TYPE = \"Content-Type\";\n export const CACHE_CONTROL = \"Cache-Control\";\n\n // Security Headers\n export const X_FRAME_OPTIONS = \"X-Frame-Options\"; // e.g. \"DENY\" or \"SAMEORIGIN\"\n export const X_CONTENT_TYPE_OPTIONS = \"X-Content-Type-Options\"; // usually \"nosniff\"\n export const REFERRER_POLICY = \"Referrer-Policy\"; // e.g. \"no-referrer\", \"strict-origin-when-cross-origin\"\n export const PERMISSIONS_POLICY = \"Permissions-Policy\"; // formerly Feature-Policy, controls APIs like geolocation/camera\n export const CONTENT_SECURITY_POLICY = \"Content-Security-Policy\"; // fine-grained script/style/image restrictions\n export const STRICT_TRANSPORT_SECURITY = \"Strict-Transport-Security\"; // e.g. \"max-age=63072000; includeSubDomains; preload\"\n\n // Cors Headers\n export const MAX_AGE = \"Access-Control-Max-Age\";\n export const ALLOW_ORIGIN = \"Access-Control-Allow-Origin\";\n export const ALLOW_HEADERS = \"Access-Control-Allow-Headers\";\n export const ALLOW_METHODS = \"Access-Control-Allow-Methods\";\n export const EXPOSE_HEADERS = \"Access-Control-Expose-Headers\";\n export const ALLOW_CREDENTIALS = \"Access-Control-Allow-Credentials\";\n\n // Values\n export const NOSNIFF = \"nosniff\";\n export const ORIGIN = \"Origin\";\n export const ALLOW_ALL_ORIGINS = \"*\";\n}\n\n/**\n * Time constants in seconds. Month is approximated as 30 days.\n */\nexport const Time = {\n Second: 1,\n Minute: 60,\n Hour: 3600, // 60 * 60\n Day: 86400, // 60 * 60 * 24\n Week: 604800, // 60 * 60 * 24 * 7\n Month: 2592000, // 60 * 60 * 24 * 30\n Year: 31536000, // 60 * 60 * 24 * 365\n} as const;\n\n/**\n * Standard HTTP request methods.\n */\nexport enum Method {\n GET = \"GET\",\n PUT = \"PUT\",\n HEAD = \"HEAD\",\n POST = \"POST\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n OPTIONS = \"OPTIONS\",\n}\nconst METHOD_SET: Set<string> = new Set(Object.values(Method));\n\n/**\n * Type guard that checks if a string is a valid HTTP method.\n *\n * @param value - The string to test.\n * @returns True if `value` is a recognized HTTP method.\n */\nexport function isMethod(value: string): value is Method {\n return METHOD_SET.has(value);\n}\n\n/**\n * Returns the proper Content-Type string for a given media type.\n * Appends `charset=utf-8` for text-based types that require it.\n *\n * @param type - The media type.\n * @returns A string suitable for the `Content-Type` header.\n */\nexport function getContentType(type: MediaType): string {\n if (ADD_CHARSET.has(type)) {\n return `${type}; charset=utf-8`;\n }\n return type;\n}\n\n/**\n * Common media types types used for HTTP headers.\n */\nexport enum MediaType {\n PLAIN_TEXT = \"text/plain\",\n HTML = \"text/html\",\n CSS = \"text/css\",\n CSV = \"text/csv\",\n XML = \"text/xml\",\n MARKDOWN = \"text/markdown\",\n RICH_TEXT = \"text/richtext\",\n JSON = \"application/json\",\n XML_APP = \"application/xml\",\n YAML = \"application/x-yaml\",\n FORM_URLENCODED = \"application/x-www-form-urlencoded\",\n NDJSON = \"application/x-ndjson\",\n MSGPACK = \"application/x-msgpack\",\n PROTOBUF = \"application/x-protobuf\",\n MULTIPART_FORM_DATA = \"multipart/form-data\",\n MULTIPART_MIXED = \"multipart/mixed\",\n MULTIPART_ALTERNATIVE = \"multipart/alternative\",\n MULTIPART_DIGEST = \"multipart/digest\",\n MULTIPART_RELATED = \"multipart/related\",\n MULTIPART_SIGNED = \"multipart/signed\",\n MULTIPART_ENCRYPTED = \"multipart/encrypted\",\n OCTET_STREAM = \"application/octet-stream\",\n PDF = \"application/pdf\",\n ZIP = \"application/zip\",\n GZIP = \"application/gzip\",\n MSWORD = \"application/msword\",\n DOCX = \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n EXCEL = \"application/vnd.ms-excel\",\n XLSX = \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n POWERPOINT = \"application/vnd.ms-powerpoint\",\n PPTX = \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n ICO = \"image/x-icon\",\n ICO_MS = \"image/vnd.microsoft.icon\",\n GIF = \"image/gif\",\n PNG = \"image/png\",\n JPEG = \"image/jpeg\",\n WEBP = \"image/webp\",\n SVG = \"image/svg+xml\",\n HEIF = \"image/heif\",\n AVIF = \"image/avif\",\n EVENT_STREAM = \"text/event-stream\",\n TAR = \"application/x-tar\",\n BZIP2 = \"application/x-bzip2\",\n}\n\n/**\n * A set of media types that require a `charset` parameter when setting\n * the `Content-Type` header.\n *\n * This includes common text-based media types such as HTML, CSS, JSON,\n * XML, CSV, Markdown, and others.\n */\nconst ADD_CHARSET: Set<MediaType> = new Set([\n MediaType.CSS,\n MediaType.CSV,\n MediaType.XML,\n MediaType.SVG,\n MediaType.HTML,\n MediaType.JSON,\n MediaType.NDJSON,\n MediaType.XML_APP,\n MediaType.MARKDOWN,\n MediaType.RICH_TEXT,\n MediaType.PLAIN_TEXT,\n MediaType.FORM_URLENCODED,\n]);\n\n/**\n * Sets a header on the given Headers object.\n *\n * - If `value` is an array, duplicates and empty strings are removed.\n * - If the resulting value array is empty, the header is deleted.\n * - Otherwise, values are joined with `\", \"` and set as the header value.\n *\n * @param headers - The Headers object to modify.\n * @param key - The header name to set.\n * @param value - The header value(s) to set. Can be a string or array of strings.\n */\nexport function setHeader(headers: Headers, key: string, value: string | string[]): void {\n const raw = Array.isArray(value) ? value : [value];\n const values = Array.from(new Set(raw.map((v) => v.trim())))\n .filter((v) => v.length)\n .sort(lexCompare);\n\n if (!values.length) {\n headers.delete(key);\n return;\n }\n\n headers.set(key, values.join(\", \"));\n}\n\n/**\n * Merges new value(s) into an existing header on the given Headers object.\n *\n * - Preserves any existing values and adds new ones.\n * - Removes duplicates and trims all values.\n * - If the header does not exist, it is created.\n *\n * @param headers - The Headers object to modify.\n * @param key - The header name to merge into.\n * @param value - The new header value(s) to add. Can be a string or array of strings.\n */\nexport function mergeHeader(headers: Headers, key: string, value: string | string[]): void {\n const values = Array.isArray(value) ? value : [value];\n if (!values.length) return;\n\n const existing = headers.get(key);\n if (existing) {\n const merged = existing.split(\",\").map((v) => v.trim());\n values.forEach((v) => merged.push(v.trim()));\n setHeader(headers, key, merged);\n } else {\n setHeader(headers, key, values);\n }\n}\n\n/**\n * Normalizes a URL string for use as a consistent cache key.\n *\n * - Sorts query parameters alphabetically so `?b=2&a=1` and `?a=1&b=2` are treated the same.\n * - Strips fragment identifiers (`#...`) since they are not sent in HTTP requests.\n * - Leaves protocol, host, path, and query values intact.\n *\n * @param url The original URL string to normalize.\n * @returns A normalized URL string suitable for hashing or direct cache key use.\n */\nexport function normalizeUrl(url: string): URL {\n const u = new URL(url);\n\n const params = [...u.searchParams.entries()];\n params.sort(([a], [b]) => lexCompare(a, b));\n\n u.search = params\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n u.hash = \"\";\n\n return u;\n}\n\n/**\n * Lexicographically compares two strings.\n *\n * This comparator can be used in `Array.prototype.sort()` to produce a\n * consistent, stable ordering of string arrays.\n *\n * @param a - The first string to compare.\n * @param b - The second string to compare.\n * @returns A number indicating the relative order of `a` and `b`.\n */\nexport function lexCompare(a: string, b: string): number {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n}\n\n/**\n * Extracts the `Origin` header value from a request.\n *\n * The `Origin` header identifies the origin (scheme, host, and port)\n * of the request initiator. It is commonly used for CORS checks.\n *\n * @param request - The incoming {@link Request} object.\n * @returns The origin string if present, otherwise `null`.\n */\nexport function getOrigin(request: Request): string | null {\n return request.headers.get(HttpHeader.ORIGIN);\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getReasonPhrase } from \"http-status-codes\";\nimport { CacheControl, HttpHeader, StatusCodes } from \"./common\";\nimport { JsonResponse } from \"./responses\";\nimport { Worker } from \"./interfaces/worker\";\nimport { ErrorJson } from \"./interfaces/error-json\";\n\n/**\n * Generic HTTP error response.\n * Sends a JSON body with status, error message, and details.\n */\nexport class HttpError extends JsonResponse {\n /**\n * @param worker The worker handling the request.\n * @param status HTTP status code.\n * @param details Optional detailed error message.\n */\n constructor(\n worker: Worker,\n status: StatusCodes,\n protected readonly details?: string,\n ) {\n const json: ErrorJson = {\n status,\n error: getReasonPhrase(status),\n details: details ?? \"\",\n };\n super(worker, json, CacheControl.DISABLE, status);\n }\n}\n\n/** 400 Bad Request error response. */\nexport class BadRequest extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.BAD_REQUEST, details);\n }\n}\n\n/** 401 Unauthorized error response. */\nexport class Unauthorized extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.UNAUTHORIZED, details);\n }\n}\n\n/** 403 Forbidden error response. */\nexport class Forbidden extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.FORBIDDEN, details);\n }\n}\n\n/** 404 Not Found error response. */\nexport class NotFound extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.NOT_FOUND, details);\n }\n}\n\n/** 405 Method Not Allowed error response. */\nexport class MethodNotAllowed extends HttpError {\n constructor(worker: Worker) {\n super(\n worker,\n StatusCodes.METHOD_NOT_ALLOWED,\n `${worker.request.method} method not allowed.`,\n );\n this.setHeader(HttpHeader.ALLOW, this.worker.getAllowedMethods());\n }\n}\n\n/** 500 Internal Server Error response. */\nexport class InternalServerError extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.INTERNAL_SERVER_ERROR, details);\n }\n}\n\n/** 501 Not Implemented error response. */\nexport class NotImplemented extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.NOT_IMPLEMENTED, details);\n }\n}\n\n/** 501 Method Not Implemented error response for unsupported HTTP methods. */\nexport class MethodNotImplemented extends NotImplemented {\n constructor(worker: Worker) {\n super(worker, `${worker.request.method} method not implemented.`);\n }\n}\n\n/** 503 Service Unavailable error response. */\nexport class ServiceUnavailable extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.SERVICE_UNAVAILABLE, details);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getReasonPhrase, StatusCodes } from \"http-status-codes\";\nimport {\n CacheControl,\n getContentType,\n HttpHeader,\n mergeHeader,\n MediaType,\n setHeader,\n} from \"./common\";\nimport { Worker } from \"./interfaces/worker\";\n\n/**\n * Base class for building HTTP responses.\n * Manages headers, status, and media type.\n */\nabstract class BaseResponse {\n constructor(public readonly worker: Worker) {}\n\n /** HTTP headers for the response. */\n public headers: Headers = new Headers();\n\n /** HTTP status code (default 200 OK). */\n public status: StatusCodes = StatusCodes.OK;\n\n /** Optional status text. Defaults to standard reason phrase. */\n public statusText?: string;\n\n /** Optional media type of the response body. */\n public mediaType?: MediaType;\n\n /** Converts current state to ResponseInit for constructing a Response. */\n protected get responseInit(): ResponseInit {\n return {\n headers: this.headers,\n status: this.status,\n statusText: this.statusText ?? getReasonPhrase(this.status),\n };\n }\n\n /** Sets a header, overwriting any existing value. */\n public setHeader(key: string, value: string | string[]): void {\n setHeader(this.headers, key, value);\n }\n\n /** Merges a header with existing values (does not overwrite). */\n public mergeHeader(key: string, value: string | string[]): void {\n mergeHeader(this.headers, key, value);\n }\n\n /** Adds a Content-Type header based on the media type if set. */\n public addContentType() {\n if (this.mediaType) {\n this.headers.set(HttpHeader.CONTENT_TYPE, getContentType(this.mediaType));\n }\n }\n}\n\n/**\n * Base response class that adds caching headers.\n */\nabstract class CacheResponse extends BaseResponse {\n constructor(\n worker: Worker,\n public cache?: CacheControl,\n ) {\n super(worker);\n }\n\n /** Adds Cache-Control header if caching is configured. */\n protected addCacheHeader(): void {\n if (this.cache) {\n this.headers.set(HttpHeader.CACHE_CONTROL, CacheControl.stringify(this.cache));\n }\n }\n}\n\n/**\n * Core worker response. Combines caching, and security headers.\n */\nexport abstract class WorkerResponse extends CacheResponse {\n constructor(\n worker: Worker,\n private readonly body: BodyInit | null = null,\n cache?: CacheControl,\n ) {\n super(worker, cache);\n }\n\n /** Builds the Response object with body, headers, and status. */\n public async getResponse(): Promise<Response> {\n this.addCacheHeader();\n this.addSecurityHeaders();\n\n const body = this.status === StatusCodes.NO_CONTENT ? null : this.body;\n\n if (body) this.addContentType();\n return new Response(body, this.responseInit);\n }\n\n /** Adds default security headers. */\n protected addSecurityHeaders(): void {\n this.setHeader(HttpHeader.X_CONTENT_TYPE_OPTIONS, HttpHeader.NOSNIFF);\n }\n}\n\n/**\n * Wraps an existing Response and clones its body, headers, and status.\n */\nexport class ClonedResponse extends WorkerResponse {\n constructor(worker: Worker, response: Response, cache?: CacheControl) {\n const clone = response.clone();\n super(worker, clone.body, cache);\n this.headers = new Headers(clone.headers);\n this.status = clone.status;\n this.statusText = clone.statusText;\n }\n}\n\n/**\n * Represents a successful response with customizable body and status.\n */\nexport class SuccessResponse extends WorkerResponse {\n constructor(\n worker: Worker,\n body: BodyInit | null = null,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n ) {\n super(worker, body, cache);\n this.status = status;\n }\n}\n\n/**\n * JSON response. Automatically sets Content-Type to application/json.\n */\nexport class JsonResponse extends SuccessResponse {\n constructor(\n worker: Worker,\n json: unknown = {},\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n ) {\n super(worker, JSON.stringify(json), cache, status);\n this.mediaType = MediaType.JSON;\n }\n}\n\n/**\n * HTML response. Automatically sets Content-Type to text/html.\n */\nexport class HtmlResponse extends SuccessResponse {\n constructor(\n worker: Worker,\n body: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n ) {\n super(worker, body, cache, status);\n this.mediaType = MediaType.HTML;\n }\n}\n\n/**\n * Plain text response. Automatically sets Content-Type to text/plain.\n */\nexport class TextResponse extends SuccessResponse {\n constructor(\n worker: Worker,\n content: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n ) {\n super(worker, content, cache, status);\n this.mediaType = MediaType.PLAIN_TEXT;\n }\n}\n\n/**\n * Response for HEAD requests. Clones headers but has no body.\n */\nexport class Head extends WorkerResponse {\n constructor(worker: Worker, get: Response) {\n super(worker);\n this.headers = new Headers(get.headers);\n }\n}\n\n/**\n * Response for OPTIONS requests. Sets allowed methods and returns 204 No Content.\n */\nexport class Options extends SuccessResponse {\n constructor(worker: Worker) {\n super(worker, null, undefined, StatusCodes.NO_CONTENT);\n this.setHeader(HttpHeader.ALLOW, this.worker.getAllowedMethods());\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { match } from \"path-to-regexp\";\nimport { Method } from \"./common\";\nimport { MatchedRoute, Route, RouteCallback, RouteParams, RouteTable } from \"./interfaces/route\";\n\n/**\n * Container for route definitions and matching logic.\n * Implements Iterable to allow iteration over all routes.\n */\nexport class Routes implements Iterable<Route> {\n /** Internal array of registered routes */\n private readonly routes: Route[] = [];\n\n /**\n * Registers all routes from the given table, replacing any existing routes.\n *\n * @param table The list of routes to register, in the form [method, path, callback].\n */\n public load(table: RouteTable): void {\n this.routes.length = 0;\n table.forEach(([method, path, callback]) => this.add(method, path, callback));\n }\n\n /**\n * Add a single route to the container.\n * @param method - HTTP method (GET, POST, etc.)\n * @param path - URL path pattern (Express-style, e.g., \"/users/:id\")\n * @param callback - Function to execute when this route matches\n */\n public add(method: Method, path: string, callback: RouteCallback) {\n const matcher = match<RouteParams>(path);\n this.routes.push({ method, matcher, callback });\n }\n\n /**\n * Attempt to match a URL against the registered routes.\n * @param method - HTTP method of the request\n * @param url - Full URL string to match against\n * @returns A MatchedRoute object if a route matches, otherwise null\n */\n public match(method: Method, url: string): MatchedRoute | null {\n const pathname = new URL(url).pathname;\n\n for (const route of this) {\n if (route.method !== method) continue;\n\n const found = route.matcher(pathname);\n if (found) return { route, params: found.params };\n }\n\n return null;\n }\n\n /**\n * Iterate over all registered routes.\n */\n public *[Symbol.iterator](): Iterator<Route> {\n yield* this.routes;\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Method } from \"../common\";\nimport { FetchHandler } from \"../interfaces/fetch-handler\";\nimport { Worker } from \"../interfaces/worker\";\n\n/**\n * Represents the constructor of a Worker subclass.\n *\n * @template T - The specific type of Worker being constructed. Defaults to `Worker`.\n * @param req - The `Request` object to be handled by the worker instance.\n * @param env - The environment bindings available to the worker.\n * @param ctx - The `ExecutionContext` for the worker invocation.\n * @returns An instance of the worker type `T`.\n */\ntype WorkerConstructor<T extends Worker = Worker> = new (\n request: Request,\n env: Env,\n ctx: ExecutionContext,\n) => T;\n\n/**\n * Provides the foundational structure for handling requests,\n * environment bindings, and the worker execution context.\n *\n * Features:\n * - Holds the current `Request` object (`request` getter).\n * - Provides access to environment bindings (`env` getter).\n * - Provides access to the worker execution context (`ctx` getter).\n * - Subclasses must implement `fetch()` to process the request.\n */\nexport abstract class BaseWorker implements Worker {\n constructor(\n private readonly _request: Request,\n private readonly _env: Env,\n private readonly _ctx: ExecutionContext,\n ) {}\n\n /** The Request object associated with this worker invocation */\n public get request(): Request {\n return this._request;\n }\n\n /** Environment bindings (e.g., KV, secrets, or other globals) */\n public get env(): Env {\n return this._env;\n }\n\n /** Execution context for background tasks or `waitUntil` */\n public get ctx(): ExecutionContext {\n return this._ctx;\n }\n\n /**\n * Dispatches the incoming request to the appropriate handler and produces a response.\n *\n * Subclasses must implement this method to define how the worker generates a `Response`\n * for the current request. This is the central point where request processing occurs,\n * and where middleware chains, routing, or other custom behavior can be applied.\n *\n * @returns A Promise that resolves to the `Response` for the request.\n */\n protected abstract dispatch(): Promise<Response>;\n\n /**\n * The DEFAULT allowed HTTP methods for subclasses.\n */\n public getAllowedMethods(): Method[] {\n return [Method.GET, Method.HEAD, Method.OPTIONS];\n }\n\n /**\n * Creates a new instance of the current Worker subclass.\n *\n * @param request - The {@link Request} to pass to the new worker instance.\n * @returns A new worker instance of the same subclass as `this`.\n */\n protected create(request: Request): this {\n const ctor = this.constructor as WorkerConstructor<this>;\n return new ctor(request, this.env, this.ctx);\n }\n\n /**\n * Process the {@link Request} and produce a {@link Response}.\n *\n * @returns A {@link Response} promise for the {@link Request}.\n */\n public abstract fetch(): Promise<Response>;\n\n /**\n * **Ignite** your `Worker` implementation into a Cloudflare handler.\n *\n * @returns A `FetchHandler` that launches a new worker instance for each request.\n *\n * @example\n * ```ts\n * export default MyWorker.ignite();\n * ```\n */\n public static ignite<W extends Worker>(this: WorkerConstructor<W>): FetchHandler {\n return {\n fetch: (request: Request, env: Env, ctx: ExecutionContext) =>\n new this(request, env, ctx).fetch(),\n };\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BaseWorker } from \"./base-worker\";\nimport { Middleware } from \"../middleware/middleware\";\n/** Internal base worker for handling middleware chains. */\nexport abstract class MiddlewareWorker extends BaseWorker {\n /** Middleware handlers registered for this worker. */\n protected readonly middlewares: Middleware[] = [];\n\n /**\n * Add a middleware to this worker.\n *\n * The middleware will run for every request handled by this worker,\n * in the order they are added.\n *\n * @param handler - The middleware to run.\n * @returns `this` to allow chaining multiple `.use()` calls.\n */\n public use(handler: Middleware): this {\n this.middlewares.push(handler);\n return this;\n }\n\n /**\n * Executes the middleware chain and dispatches the request.\n *\n * @returns The Response produced by the last middleware or `dispatch()`.\n */\n public override async fetch(): Promise<Response> {\n const chain = this.middlewares.reduceRight(\n (next, handler) => () => handler.handle(this, next),\n () => this.dispatch(),\n );\n return await chain();\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { isMethod, Method } from \"../common\";\nimport { MethodNotAllowed, InternalServerError, MethodNotImplemented } from \"../errors\";\nimport { MiddlewareWorker } from \"./middleware-worker\";\nimport { Head, Options, WorkerResponse } from \"../responses\";\nimport { Worker } from \"../interfaces/worker\";\n\n/**\n * Base worker class providing HTTP method dispatching, caching, and error handling.\n * Extends `CacheWorker` and defines default implementations for HTTP methods.\n */\nexport abstract class BasicWorker extends MiddlewareWorker {\n /**\n * Entry point to handle a fetch request.\n * Checks allowed methods, serves cached responses, or dispatches to the appropriate handler.\n */\n public override async fetch(): Promise<Response> {\n if (!this.isAllowed(this.request.method)) {\n return this.getResponse(MethodNotAllowed);\n }\n\n try {\n this.init();\n return await super.fetch();\n } catch (error) {\n console.error(error);\n return this.getResponse(InternalServerError);\n }\n }\n\n /**\n * Dispatches the request to the method-specific handler.\n * Defaults to MethodNotAllowed if the HTTP method is not recognized.\n */\n protected override async dispatch(): Promise<Response> {\n const method = this.request.method as Method;\n const handler: Record<Method, () => Promise<Response>> = {\n GET: () => this.get(),\n PUT: () => this.put(),\n HEAD: () => this.head(),\n POST: () => this.post(),\n PATCH: () => this.patch(),\n DELETE: () => this.delete(),\n OPTIONS: () => this.options(),\n };\n return (handler[method] ?? (() => this.getResponse(MethodNotAllowed)))();\n }\n\n /**\n * Hook for subclasses to perform any initialization.\n */\n protected init(): void {\n return;\n }\n\n /**\n * Checks if the given HTTP method is allowed for this worker.\n * @param method HTTP method string\n * @returns true if the method is allowed\n */\n public isAllowed(method: string): boolean {\n return isMethod(method) && this.getAllowedMethods().includes(method);\n }\n\n /** Default handler for GET requests. Returns MethodNotImplemented unless overridden. */\n protected async get(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for PUT requests. Returns MethodNotImplemented unless overridden. */\n protected async put(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for POST requests. Returns MethodNotImplemented unless overridden. */\n protected async post(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for PATCH requests. Returns MethodNotImplemented unless overridden. */\n protected async patch(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for DELETE requests. Returns MethodNotImplemented unless overridden. */\n protected async delete(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /**\n * Default handler for OPTIONS requests.\n * Returns an Options response.\n *\n * Typically does not need to be overridden.\n */\n protected async options(): Promise<Response> {\n return this.getResponse(Options);\n }\n\n /**\n * Default handler for HEAD requests.\n * Performs a GET request internally and removes the body for HEAD semantics.\n *\n * Usually does not need to be overridden, as this behavior covers standard HEAD requirements.\n */\n protected async head(): Promise<Response> {\n const worker = this.create(new Request(this.request, { method: Method.GET }));\n return this.getResponse(Head, await worker.fetch());\n }\n\n /**\n * Helper to construct a WorkerResponse of the given class with arguments.\n * @param ResponseClass The response class to instantiate\n * @param args Additional constructor arguments\n * @returns The final Response object\n */\n protected async getResponse<\n T extends WorkerResponse,\n Ctor extends new (worker: Worker, ...args: any[]) => T,\n >(\n ResponseClass: Ctor,\n ...args: ConstructorParameters<Ctor> extends [Worker, ...infer R] ? R : never\n ): Promise<Response> {\n return new ResponseClass(this, ...args).getResponse();\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BasicWorker } from \"./basic-worker\";\nimport { Method } from \"../common\";\nimport { NotFound } from \"../errors\";\nimport { Routes } from \"../routes\";\nimport { RouteCallback, RouteTable } from \"../interfaces/route\";\n\n/**\n * Base worker supporting route-based request handling.\n *\n * Subclass `RouteWorker` to define a worker with multiple route handlers.\n *\n * Routes can be registered individually via `addRoute()` or in bulk via `load()`.\n * Middleware can be attached with `use()` to run for all requests.\n * ```\n */\nexport abstract class RouteWorker extends BasicWorker {\n /** Internal table of registered routes. */\n private readonly routes: Routes = new Routes();\n\n /**\n * Load multiple routes at once from a route table.\n * @param table - Array of routes to register.\n */\n protected load(table: RouteTable): void {\n this.routes.load(table);\n }\n\n /**\n * Add a single route.\n * @param method - HTTP method (GET, POST, etc.)\n * @param path - Route path, supports parameters like \"/users/:id\"\n * @param callback - Function to handle requests matching this route\n * @returns `this` for chaining multiple route additions\n */\n protected addRoute(method: Method, path: string, callback: RouteCallback): this {\n this.routes.add(method, path, callback);\n return this;\n }\n\n /**\n * Matches the incoming request against registered routes and executes the callback.\n * Falls back to the default handler if no match is found.\n * This is called automatically when the worker handles a request.\n */\n protected override async dispatch(): Promise<Response> {\n const found = this.routes.match(this.request.method as Method, this.request.url);\n if (!found) return super.dispatch();\n\n return found.route.callback.call(this, found.params);\n }\n\n protected override async get(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async put(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async post(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async patch(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async delete(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getOrigin, HttpHeader, mergeHeader, setHeader } from \"../../common\";\nimport { CorsConfig } from \"../../interfaces/cors-config\";\nimport { Worker } from \"../../interfaces/worker\";\n\n/**\n * Adds CORS headers to the given Headers object based on the request and config.\n */\nexport function addCorsHeaders(worker: Worker, cors: CorsConfig, headers: Headers): void {\n deleteCorsHeaders(headers);\n\n const origin = getOrigin(worker.request);\n if (!origin || origin.trim() === \"\") return;\n\n if (allowAnyOrigin(cors)) {\n setHeader(headers, HttpHeader.ALLOW_ORIGIN, HttpHeader.ALLOW_ALL_ORIGINS);\n } else if (cors.allowedOrigins.includes(origin)) {\n setHeader(headers, HttpHeader.ALLOW_ORIGIN, origin);\n setHeader(headers, HttpHeader.ALLOW_CREDENTIALS, \"true\");\n }\n\n setHeader(headers, HttpHeader.MAX_AGE, String(cors.maxAge));\n setHeader(headers, HttpHeader.ALLOW_METHODS, worker.getAllowedMethods());\n setHeader(headers, HttpHeader.ALLOW_HEADERS, cors.allowedHeaders);\n mergeHeader(headers, HttpHeader.EXPOSE_HEADERS, cors.exposedHeaders);\n}\n\n/** Returns true if the CORS config allows all origins (`*`). */\nexport function allowAnyOrigin(cors: CorsConfig): boolean {\n return cors.allowedOrigins.includes(\"*\");\n}\n\n/** Removes all standard CORS headers from a Headers object. */\nfunction deleteCorsHeaders(headers: Headers): void {\n headers.delete(HttpHeader.MAX_AGE);\n headers.delete(HttpHeader.ALLOW_ORIGIN);\n headers.delete(HttpHeader.ALLOW_HEADERS);\n headers.delete(HttpHeader.ALLOW_METHODS);\n headers.delete(HttpHeader.EXPOSE_HEADERS);\n headers.delete(HttpHeader.ALLOW_CREDENTIALS);\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Worker } from \"../interfaces/worker\";\n\n/**\n * Abstract base class for middleware.\n *\n * Middleware classes implement request/response processing logic in a\n * chainable manner. Each middleware receives a `Worker` object and a\n * `next` function that invokes the next middleware in the chain.\n *\n * Subclasses **must implement** the `handle` method.\n *\n * Example subclass:\n * ```ts\n * class LoggingMiddleware extends Middleware {\n * public async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {\n * console.log(`Processing request: ${worker.request.url}`);\n * const response = await next();\n * console.log(`Response status: ${response.status}`);\n * return response;\n * }\n * }\n * ```\n */\nexport abstract class Middleware {\n /**\n * Process a request in the middleware chain.\n *\n * @param worker - The `Worker` instance representing the request context.\n * @param next - Function to invoke the next middleware in the chain.\n * Must be called to continue the chain unless the middleware\n * terminates early (e.g., returns a response directly).\n * @returns A `Response` object, either returned directly or from `next()`.\n */\n public abstract handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Time } from \"../../common\";\nimport { CorsConfig } from \"../../interfaces/cors-config\";\n\n/**\n * Default configuration for CORS middleware.\n */\nexport const defaultCorsConfig: CorsConfig = {\n allowedOrigins: [\"*\"], // Origins allowed for CORS requests\n allowedHeaders: [\"Content-Type\"], // HTTP headers allowed in requests\n exposedHeaders: [], // Headers exposed to the client\n maxAge: Time.Week, // Max age in seconds for preflight caching\n} as const;\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { mergeHeader } from \"../../common\";\nimport { addCorsHeaders, allowAnyOrigin } from \"./utils\";\nimport { Worker } from \"../../interfaces/worker\";\nimport { Middleware } from \"../middleware\";\nimport { CorsConfig } from \"../../interfaces/cors-config\";\nimport { defaultCorsConfig } from \"./defaults\";\n\n/**\n * Middleware that applies Cross-Origin Resource Sharing (CORS) headers to responses.\n *\n * This middleware reads the configuration provided (or uses `defaultCorsConfig`)\n * and ensures that responses include the appropriate CORS headers. It also\n * handles the `Vary: Origin` header when not allowing all origins.\n *\n * Example usage:\n * ```ts\n * const cors = new CorsHandler({ allowedOrigins: [\"https://myapp.com\"] });\n * worker.use(cors);\n * ```\n */\nexport class CorsHandler extends Middleware {\n /** The configuration used for this instance, with all defaults applied. */\n private readonly config: Required<CorsConfig>;\n\n /**\n * Create a new CORS middleware instance.\n *\n * @param init - Partial configuration to override the defaults. Any values\n * not provided will use `defaultCorsConfig`.\n */\n constructor(init?: Partial<CorsConfig>) {\n super();\n this.config = { ...defaultCorsConfig, ...init };\n }\n\n /**\n * Handle a request by applying CORS headers to the response.\n *\n * @param worker - The Worker instance containing the request context.\n * @param next - Function to invoke the next middleware in the chain.\n * @returns A Response object with CORS headers applied.\n *\n * This middleware does not short-circuit the request; it always calls `next()`\n * and modifies the resulting response.\n */\n public override async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {\n const response = await next();\n\n const mutable = new Response(response.body, response);\n\n addCorsHeaders(worker, this.config, mutable.headers);\n if (!allowAnyOrigin(this.config)) {\n mergeHeader(mutable.headers, \"Vary\", \"Origin\");\n }\n\n return mutable;\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Method, normalizeUrl } from \"../../common\";\nimport { Middleware } from \"../middleware\";\nimport { Worker } from \"../../interfaces/worker\";\n\n/**\n * Middleware for caching GET requests.\n *\n * This middleware checks a cache (either a named cache or the default)\n * before passing the request down the middleware chain. Responses for\n * successful GET requests are automatically stored in the cache.\n *\n * Non-GET requests are never cached. The cache key can be customized\n * via the `getKey` function; otherwise, the URL is normalized and used.\n *\n * Example usage:\n * ```ts\n * const cacheMiddleware = new CacheHandler(\"my-cache\", (req) => new URL(req.url));\n * worker.use(cacheMiddleware);\n * ```\n */\nexport class CacheHandler extends Middleware {\n /**\n * @param cacheName - Optional name of the cache to use. If omitted,\n * `caches.default` is used.\n * @param getKey - Optional function to generate a cache key from a request.\n * Defaults to using the normalized request URL.\n */\n constructor(\n protected readonly cacheName?: string,\n protected readonly getKey?: (request: Request) => URL | RequestInfo,\n ) {\n super();\n }\n\n /**\n * Handle a request in the caching middleware.\n *\n * Checks the cache for GET requests and returns the cached response if available.\n * Otherwise, calls `next()` to continue the middleware chain and caches\n * the response if successful.\n *\n * @param worker - The Worker instance containing the request context.\n * @param next - Function to invoke the next middleware in the chain.\n * @returns A Response object, either from cache or the next middleware.\n */\n public override async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {\n const cache = this.cacheName ? await caches.open(this.cacheName) : caches.default;\n\n if (worker.request.method === Method.GET) {\n const cached = await cache.match(this.getCacheKey(worker.request));\n if (cached) return cached;\n }\n\n const response = await next();\n\n if (worker.request.method === Method.GET && response.ok) {\n worker.ctx.waitUntil(cache.put(this.getCacheKey(worker.request), response.clone()));\n }\n return response;\n }\n\n /**\n * Generate the cache key for a request.\n *\n * @param request - The Request object to generate a cache key for.\n * @returns A URL or RequestInfo used as the cache key.\n *\n * If a custom `getKey` function was provided in the constructor, it is used.\n * Otherwise, the request URL is normalized.\n */\n public getCacheKey(request: Request): URL | RequestInfo {\n return this.getKey ? this.getKey(request) : normalizeUrl(request.url);\n }\n}\n"],"mappings":"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","names":["HttpHeader","Method","MediaType","getReasonPhrase","StatusCodes","StatusCodes","getReasonPhrase"]}
1
+ {"version":3,"sources":["../src/common.ts","../src/errors.ts","../src/responses.ts","../src/routes.ts","../src/middleware/cors/utils.ts","../src/middleware/middleware.ts","../src/middleware/cors/defaults.ts","../src/middleware/cors/handler.ts","../src/middleware/cache/handler.ts","../src/workers/base-worker.ts","../src/workers/middleware-worker.ts","../src/workers/basic-worker.ts","../src/workers/route-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 ALLOW = \"Allow\";\n export const CONTENT_TYPE = \"Content-Type\";\n export const CACHE_CONTROL = \"Cache-Control\";\n export const USER_AGENT = \"User-Agent\";\n\n // Security Headers\n export const X_FRAME_OPTIONS = \"X-Frame-Options\"; // e.g. \"DENY\" or \"SAMEORIGIN\"\n export const X_CONTENT_TYPE_OPTIONS = \"X-Content-Type-Options\"; // usually \"nosniff\"\n export const REFERRER_POLICY = \"Referrer-Policy\"; // e.g. \"no-referrer\", \"strict-origin-when-cross-origin\"\n export const PERMISSIONS_POLICY = \"Permissions-Policy\"; // formerly Feature-Policy, controls APIs like geolocation/camera\n export const CONTENT_SECURITY_POLICY = \"Content-Security-Policy\"; // fine-grained script/style/image restrictions\n export const STRICT_TRANSPORT_SECURITY = \"Strict-Transport-Security\"; // e.g. \"max-age=63072000; includeSubDomains; preload\"\n\n // Cors Headers\n export const MAX_AGE = \"Access-Control-Max-Age\";\n export const ALLOW_ORIGIN = \"Access-Control-Allow-Origin\";\n export const ALLOW_HEADERS = \"Access-Control-Allow-Headers\";\n export const ALLOW_METHODS = \"Access-Control-Allow-Methods\";\n export const EXPOSE_HEADERS = \"Access-Control-Expose-Headers\";\n export const ALLOW_CREDENTIALS = \"Access-Control-Allow-Credentials\";\n\n // Values\n export const NOSNIFF = \"nosniff\";\n export const ORIGIN = \"Origin\";\n export const ALLOW_ALL_ORIGINS = \"*\";\n}\n\n/**\n * Time constants in seconds. Month is approximated as 30 days.\n */\nexport const Time = {\n Second: 1,\n Minute: 60,\n Hour: 3600, // 60 * 60\n Day: 86400, // 60 * 60 * 24\n Week: 604800, // 60 * 60 * 24 * 7\n Month: 2592000, // 60 * 60 * 24 * 30\n Year: 31536000, // 60 * 60 * 24 * 365\n} as const;\n\n/**\n * Standard HTTP request methods.\n */\nexport enum Method {\n GET = \"GET\",\n PUT = \"PUT\",\n HEAD = \"HEAD\",\n POST = \"POST\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n OPTIONS = \"OPTIONS\",\n}\nconst METHOD_SET: Set<string> = new Set(Object.values(Method));\n\n/**\n * Type guard that checks if a string is a valid HTTP method.\n *\n * @param value - The string to test.\n * @returns True if `value` is a recognized HTTP method.\n */\nexport function isMethod(value: string): value is Method {\n return METHOD_SET.has(value);\n}\n\n/**\n * Returns the proper Content-Type string for a given media type.\n * Appends `charset=utf-8` for text-based types that require it.\n *\n * @param type - The media type.\n * @returns A string suitable for the `Content-Type` header.\n */\nexport function getContentType(type: MediaType): string {\n if (ADD_CHARSET.has(type)) {\n return `${type}; charset=utf-8`;\n }\n return type;\n}\n\n/**\n * Common media types types used for HTTP headers.\n */\nexport enum MediaType {\n PLAIN_TEXT = \"text/plain\",\n HTML = \"text/html\",\n CSS = \"text/css\",\n CSV = \"text/csv\",\n XML = \"text/xml\",\n MARKDOWN = \"text/markdown\",\n RICH_TEXT = \"text/richtext\",\n JSON = \"application/json\",\n XML_APP = \"application/xml\",\n YAML = \"application/x-yaml\",\n FORM_URLENCODED = \"application/x-www-form-urlencoded\",\n NDJSON = \"application/x-ndjson\",\n MSGPACK = \"application/x-msgpack\",\n PROTOBUF = \"application/x-protobuf\",\n MULTIPART_FORM_DATA = \"multipart/form-data\",\n MULTIPART_MIXED = \"multipart/mixed\",\n MULTIPART_ALTERNATIVE = \"multipart/alternative\",\n MULTIPART_DIGEST = \"multipart/digest\",\n MULTIPART_RELATED = \"multipart/related\",\n MULTIPART_SIGNED = \"multipart/signed\",\n MULTIPART_ENCRYPTED = \"multipart/encrypted\",\n OCTET_STREAM = \"application/octet-stream\",\n PDF = \"application/pdf\",\n ZIP = \"application/zip\",\n GZIP = \"application/gzip\",\n MSWORD = \"application/msword\",\n DOCX = \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n EXCEL = \"application/vnd.ms-excel\",\n XLSX = \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n POWERPOINT = \"application/vnd.ms-powerpoint\",\n PPTX = \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n ICO = \"image/x-icon\",\n ICO_MS = \"image/vnd.microsoft.icon\",\n GIF = \"image/gif\",\n PNG = \"image/png\",\n JPEG = \"image/jpeg\",\n WEBP = \"image/webp\",\n SVG = \"image/svg+xml\",\n HEIF = \"image/heif\",\n AVIF = \"image/avif\",\n EVENT_STREAM = \"text/event-stream\",\n TAR = \"application/x-tar\",\n BZIP2 = \"application/x-bzip2\",\n}\n\n/**\n * A set of media types that require a `charset` parameter when setting\n * the `Content-Type` header.\n *\n * This includes common text-based media types such as HTML, CSS, JSON,\n * XML, CSV, Markdown, and others.\n */\nconst ADD_CHARSET: Set<MediaType> = new Set([\n MediaType.CSS,\n MediaType.CSV,\n MediaType.XML,\n MediaType.SVG,\n MediaType.HTML,\n MediaType.JSON,\n MediaType.NDJSON,\n MediaType.XML_APP,\n MediaType.MARKDOWN,\n MediaType.RICH_TEXT,\n MediaType.PLAIN_TEXT,\n MediaType.FORM_URLENCODED,\n]);\n\n/**\n * Sets a header on the given Headers object.\n *\n * - If `value` is an array, duplicates and empty strings are removed.\n * - If the resulting value array is empty, the header is deleted.\n * - Otherwise, values are joined with `\", \"` and set as the header value.\n *\n * @param headers - The Headers object to modify.\n * @param key - The header name to set.\n * @param value - The header value(s) to set. Can be a string or array of strings.\n */\nexport function setHeader(headers: Headers, key: string, value: string | string[]): void {\n const raw = Array.isArray(value) ? value : [value];\n const values = Array.from(new Set(raw.map((v) => v.trim())))\n .filter((v) => v.length)\n .sort(lexCompare);\n\n if (!values.length) {\n headers.delete(key);\n return;\n }\n\n headers.set(key, values.join(\", \"));\n}\n\n/**\n * Merges new value(s) into an existing header on the given Headers object.\n *\n * - Preserves any existing values and adds new ones.\n * - Removes duplicates and trims all values.\n * - If the header does not exist, it is created.\n *\n * @param headers - The Headers object to modify.\n * @param key - The header name to merge into.\n * @param value - The new header value(s) to add. Can be a string or array of strings.\n */\nexport function mergeHeader(headers: Headers, key: string, value: string | string[]): void {\n const values = Array.isArray(value) ? value : [value];\n if (!values.length) return;\n\n const existing = headers.get(key);\n if (existing) {\n const merged = existing.split(\",\").map((v) => v.trim());\n values.forEach((v) => merged.push(v.trim()));\n setHeader(headers, key, merged);\n } else {\n setHeader(headers, key, values);\n }\n}\n\n/**\n * Normalizes a URL string for use as a consistent cache key.\n *\n * - Sorts query parameters alphabetically so `?b=2&a=1` and `?a=1&b=2` are treated the same.\n * - Strips fragment identifiers (`#...`) since they are not sent in HTTP requests.\n * - Leaves protocol, host, path, and query values intact.\n *\n * @param url The original URL string to normalize.\n * @returns A normalized URL string suitable for hashing or direct cache key use.\n */\nexport function normalizeUrl(url: string): URL {\n const u = new URL(url);\n\n const params = [...u.searchParams.entries()];\n params.sort(([a], [b]) => lexCompare(a, b));\n\n u.search = params\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n u.hash = \"\";\n\n return u;\n}\n\n/**\n * Lexicographically compares two strings.\n *\n * This comparator can be used in `Array.prototype.sort()` to produce a\n * consistent, stable ordering of string arrays.\n *\n * @param a - The first string to compare.\n * @param b - The second string to compare.\n * @returns A number indicating the relative order of `a` and `b`.\n */\nexport function lexCompare(a: string, b: string): number {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n}\n\n/**\n * Extracts the `Origin` header value from a request.\n *\n * The `Origin` header identifies the origin (scheme, host, and port)\n * of the request initiator. It is commonly used for CORS checks.\n *\n * @param request - The incoming {@link Request} object.\n * @returns The origin string if present, otherwise `null`.\n */\nexport function getOrigin(request: Request): string | null {\n return request.headers.get(HttpHeader.ORIGIN);\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getReasonPhrase } from \"http-status-codes\";\nimport { CacheControl, HttpHeader, StatusCodes } from \"./common\";\nimport { JsonResponse } from \"./responses\";\nimport { Worker } from \"./interfaces/worker\";\nimport { ErrorJson } from \"./interfaces/error-json\";\n\n/**\n * Generic HTTP error response.\n * Sends a JSON body with status, error message, and details.\n */\nexport class HttpError extends JsonResponse {\n /**\n * @param worker The worker handling the request.\n * @param status HTTP status code.\n * @param details Optional detailed error message.\n */\n constructor(\n worker: Worker,\n status: StatusCodes,\n protected readonly details?: string,\n ) {\n const json: ErrorJson = {\n status,\n error: getReasonPhrase(status),\n details: details ?? \"\",\n };\n super(worker, json, CacheControl.DISABLE, status);\n }\n}\n\n/** 400 Bad Request error response. */\nexport class BadRequest extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.BAD_REQUEST, details);\n }\n}\n\n/** 401 Unauthorized error response. */\nexport class Unauthorized extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.UNAUTHORIZED, details);\n }\n}\n\n/** 403 Forbidden error response. */\nexport class Forbidden extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.FORBIDDEN, details);\n }\n}\n\n/** 404 Not Found error response. */\nexport class NotFound extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.NOT_FOUND, details);\n }\n}\n\n/** 405 Method Not Allowed error response. */\nexport class MethodNotAllowed extends HttpError {\n constructor(worker: Worker) {\n super(\n worker,\n StatusCodes.METHOD_NOT_ALLOWED,\n `${worker.request.method} method not allowed.`,\n );\n this.setHeader(HttpHeader.ALLOW, this.worker.getAllowedMethods());\n }\n}\n\n/** 500 Internal Server Error response. */\nexport class InternalServerError extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.INTERNAL_SERVER_ERROR, details);\n }\n}\n\n/** 501 Not Implemented error response. */\nexport class NotImplemented extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.NOT_IMPLEMENTED, details);\n }\n}\n\n/** 501 Method Not Implemented error response for unsupported HTTP methods. */\nexport class MethodNotImplemented extends NotImplemented {\n constructor(worker: Worker) {\n super(worker, `${worker.request.method} method not implemented.`);\n }\n}\n\n/** 503 Service Unavailable error response. */\nexport class ServiceUnavailable extends HttpError {\n constructor(worker: Worker, details?: string) {\n super(worker, StatusCodes.SERVICE_UNAVAILABLE, details);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getReasonPhrase, StatusCodes } from \"http-status-codes\";\nimport {\n CacheControl,\n getContentType,\n HttpHeader,\n mergeHeader,\n MediaType,\n setHeader,\n} from \"./common\";\nimport { Worker } from \"./interfaces/worker\";\n\n/**\n * Base class for building HTTP responses.\n * Manages headers, status, and media type.\n */\nabstract class BaseResponse {\n constructor(public readonly worker: Worker) {}\n\n /** HTTP headers for the response. */\n public headers: Headers = new Headers();\n\n /** HTTP status code (default 200 OK). */\n public status: StatusCodes = StatusCodes.OK;\n\n /** Optional status text. Defaults to standard reason phrase. */\n public statusText?: string;\n\n /** Optional media type of the response body. */\n public mediaType?: MediaType;\n\n /** Converts current state to ResponseInit for constructing a Response. */\n protected get responseInit(): ResponseInit {\n return {\n headers: this.headers,\n status: this.status,\n statusText: this.statusText ?? getReasonPhrase(this.status),\n };\n }\n\n /** Sets a header, overwriting any existing value. */\n public setHeader(key: string, value: string | string[]): void {\n setHeader(this.headers, key, value);\n }\n\n /** Merges a header with existing values (does not overwrite). */\n public mergeHeader(key: string, value: string | string[]): void {\n mergeHeader(this.headers, key, value);\n }\n\n /** Adds a Content-Type header based on the media type if set. */\n public addContentType() {\n if (this.mediaType) {\n this.headers.set(HttpHeader.CONTENT_TYPE, getContentType(this.mediaType));\n }\n }\n}\n\n/**\n * Base response class that adds caching headers.\n */\nabstract class CacheResponse extends BaseResponse {\n constructor(\n worker: Worker,\n public cache?: CacheControl,\n ) {\n super(worker);\n }\n\n /** Adds Cache-Control header if caching is configured. */\n protected addCacheHeader(): void {\n if (this.cache) {\n this.headers.set(HttpHeader.CACHE_CONTROL, CacheControl.stringify(this.cache));\n }\n }\n}\n\n/**\n * Core worker response. Combines caching, and security headers.\n */\nexport abstract class WorkerResponse extends CacheResponse {\n constructor(\n worker: Worker,\n private readonly body: BodyInit | null = null,\n cache?: CacheControl,\n ) {\n super(worker, cache);\n }\n\n /** Builds the Response object with body, headers, and status. */\n public async getResponse(): Promise<Response> {\n this.addCacheHeader();\n this.addSecurityHeaders();\n\n const body = this.status === StatusCodes.NO_CONTENT ? null : this.body;\n\n if (body) this.addContentType();\n return new Response(body, this.responseInit);\n }\n\n /** Adds default security headers. */\n protected addSecurityHeaders(): void {\n this.setHeader(HttpHeader.X_CONTENT_TYPE_OPTIONS, HttpHeader.NOSNIFF);\n }\n}\n\n/**\n * Wraps an existing Response and clones its body, headers, and status.\n */\nexport class ClonedResponse extends WorkerResponse {\n constructor(worker: Worker, response: Response, cache?: CacheControl) {\n const clone = response.clone();\n super(worker, clone.body, cache);\n this.headers = new Headers(clone.headers);\n this.status = clone.status;\n this.statusText = clone.statusText;\n }\n}\n\n/**\n * Represents a successful response with customizable body and status.\n */\nexport class SuccessResponse extends WorkerResponse {\n constructor(\n worker: Worker,\n body: BodyInit | null = null,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n ) {\n super(worker, body, cache);\n this.status = status;\n }\n}\n\n/**\n * JSON response. Automatically sets Content-Type to application/json.\n */\nexport class JsonResponse extends SuccessResponse {\n constructor(\n worker: Worker,\n json: unknown = {},\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n ) {\n super(worker, JSON.stringify(json), cache, status);\n this.mediaType = MediaType.JSON;\n }\n}\n\n/**\n * HTML response. Automatically sets Content-Type to text/html.\n */\nexport class HtmlResponse extends SuccessResponse {\n constructor(\n worker: Worker,\n body: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n ) {\n super(worker, body, cache, status);\n this.mediaType = MediaType.HTML;\n }\n}\n\n/**\n * Plain text response. Automatically sets Content-Type to text/plain.\n */\nexport class TextResponse extends SuccessResponse {\n constructor(\n worker: Worker,\n content: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK,\n ) {\n super(worker, content, cache, status);\n this.mediaType = MediaType.PLAIN_TEXT;\n }\n}\n\n/**\n * Response for HEAD requests. Clones headers but has no body.\n */\nexport class Head extends WorkerResponse {\n constructor(worker: Worker, get: Response) {\n super(worker);\n this.headers = new Headers(get.headers);\n }\n}\n\n/**\n * Response for OPTIONS requests. Sets allowed methods and returns 204 No Content.\n */\nexport class Options extends SuccessResponse {\n constructor(worker: Worker) {\n super(worker, null, undefined, StatusCodes.NO_CONTENT);\n this.setHeader(HttpHeader.ALLOW, this.worker.getAllowedMethods());\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { match } from \"path-to-regexp\";\nimport { Method } from \"./common\";\nimport { MatchedRoute, Route, RouteCallback, RouteParams, RouteTable } from \"./interfaces/route\";\n\n/**\n * Container for route definitions and matching logic.\n * Implements Iterable to allow iteration over all routes.\n */\nexport class Routes implements Iterable<Route> {\n /** Internal array of registered routes */\n private readonly routes: Route[] = [];\n\n /**\n * Registers all routes from the given table, replacing any existing routes.\n *\n * @param table The list of routes to register, in the form [method, path, callback].\n */\n public load(table: RouteTable): void {\n this.routes.length = 0;\n table.forEach(([method, path, callback]) => this.add(method, path, callback));\n }\n\n /**\n * Add a single route to the container.\n * @param method - HTTP method (GET, POST, etc.)\n * @param path - URL path pattern (Express-style, e.g., \"/users/:id\")\n * @param callback - Function to execute when this route matches\n */\n public add(method: Method, path: string, callback: RouteCallback) {\n const matcher = match<RouteParams>(path);\n this.routes.push({ method, matcher, callback });\n }\n\n /**\n * Attempt to match a URL against the registered routes.\n * @param method - HTTP method of the request\n * @param url - Full URL string to match against\n * @returns A MatchedRoute object if a route matches, otherwise null\n */\n public match(method: Method, url: string): MatchedRoute | null {\n const pathname = new URL(url).pathname;\n\n for (const route of this) {\n if (route.method !== method) continue;\n\n const found = route.matcher(pathname);\n if (found) return { route, params: found.params };\n }\n\n return null;\n }\n\n /**\n * Iterate over all registered routes.\n */\n public *[Symbol.iterator](): Iterator<Route> {\n yield* this.routes;\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getOrigin, HttpHeader, mergeHeader, setHeader } from \"../../common\";\nimport { CorsConfig } from \"../../interfaces/cors-config\";\nimport { Worker } from \"../../interfaces/worker\";\n\n/**\n * Adds CORS headers to the given Headers object based on the request and config.\n */\nexport function addCorsHeaders(worker: Worker, cors: CorsConfig, headers: Headers): void {\n deleteCorsHeaders(headers);\n\n const origin = getOrigin(worker.request);\n if (!origin || origin.trim() === \"\") return;\n\n if (allowAnyOrigin(cors)) {\n setHeader(headers, HttpHeader.ALLOW_ORIGIN, HttpHeader.ALLOW_ALL_ORIGINS);\n } else if (cors.allowedOrigins.includes(origin)) {\n setHeader(headers, HttpHeader.ALLOW_ORIGIN, origin);\n setHeader(headers, HttpHeader.ALLOW_CREDENTIALS, \"true\");\n }\n\n setHeader(headers, HttpHeader.MAX_AGE, String(cors.maxAge));\n setHeader(headers, HttpHeader.ALLOW_METHODS, worker.getAllowedMethods());\n setHeader(headers, HttpHeader.ALLOW_HEADERS, cors.allowedHeaders);\n mergeHeader(headers, HttpHeader.EXPOSE_HEADERS, cors.exposedHeaders);\n}\n\n/** Returns true if the CORS config allows all origins (`*`). */\nexport function allowAnyOrigin(cors: CorsConfig): boolean {\n return cors.allowedOrigins.includes(\"*\");\n}\n\n/** Removes all standard CORS headers from a Headers object. */\nfunction deleteCorsHeaders(headers: Headers): void {\n headers.delete(HttpHeader.MAX_AGE);\n headers.delete(HttpHeader.ALLOW_ORIGIN);\n headers.delete(HttpHeader.ALLOW_HEADERS);\n headers.delete(HttpHeader.ALLOW_METHODS);\n headers.delete(HttpHeader.EXPOSE_HEADERS);\n headers.delete(HttpHeader.ALLOW_CREDENTIALS);\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Worker } from \"../interfaces/worker\";\n\n/**\n * Abstract base class for middleware.\n *\n * Middleware classes implement request/response processing logic in a\n * chainable manner. Each middleware receives a `Worker` object and a\n * `next` function that invokes the next middleware in the chain.\n *\n * Subclasses **must implement** the `handle` method.\n *\n * Example subclass:\n * ```ts\n * class LoggingMiddleware extends Middleware {\n * public async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {\n * console.log(`Processing request: ${worker.request.url}`);\n * const response = await next();\n * console.log(`Response status: ${response.status}`);\n * return response;\n * }\n * }\n * ```\n */\nexport abstract class Middleware {\n /**\n * Process a request in the middleware chain.\n *\n * @param worker - The `Worker` instance representing the request context.\n * @param next - Function to invoke the next middleware in the chain.\n * Must be called to continue the chain unless the middleware\n * terminates early (e.g., returns a response directly).\n * @returns A `Response` object, either returned directly or from `next()`.\n */\n public abstract handle(worker: Worker, next: () => Promise<Response>): Promise<Response>;\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Time } from \"../../common\";\nimport { CorsConfig } from \"../../interfaces/cors-config\";\n\n/**\n * Default configuration for CORS middleware.\n */\nexport const defaultCorsConfig: CorsConfig = {\n allowedOrigins: [\"*\"], // Origins allowed for CORS requests\n allowedHeaders: [\"Content-Type\"], // HTTP headers allowed in requests\n exposedHeaders: [], // Headers exposed to the client\n maxAge: Time.Week, // Max age in seconds for preflight caching\n} as const;\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { mergeHeader } from \"../../common\";\nimport { addCorsHeaders, allowAnyOrigin } from \"./utils\";\nimport { Worker } from \"../../interfaces/worker\";\nimport { Middleware } from \"../middleware\";\nimport { CorsConfig } from \"../../interfaces/cors-config\";\nimport { defaultCorsConfig } from \"./defaults\";\n\n/**\n * Middleware that applies Cross-Origin Resource Sharing (CORS) headers to responses.\n *\n * This middleware reads the configuration provided (or uses `defaultCorsConfig`)\n * and ensures that responses include the appropriate CORS headers. It also\n * handles the `Vary: Origin` header when not allowing all origins.\n *\n * Example usage:\n * ```ts\n * const cors = new CorsHandler({ allowedOrigins: [\"https://myapp.com\"] });\n * worker.use(cors);\n * ```\n */\nexport class CorsHandler extends Middleware {\n /** The configuration used for this instance, with all defaults applied. */\n private readonly config: Required<CorsConfig>;\n\n /**\n * Create a new CORS middleware instance.\n *\n * @param init - Partial configuration to override the defaults. Any values\n * not provided will use `defaultCorsConfig`.\n */\n constructor(init?: Partial<CorsConfig>) {\n super();\n this.config = { ...defaultCorsConfig, ...init };\n }\n\n /**\n * Handle a request by applying CORS headers to the response.\n *\n * @param worker - The Worker instance containing the request context.\n * @param next - Function to invoke the next middleware in the chain.\n * @returns A Response object with CORS headers applied.\n *\n * This middleware does not short-circuit the request; it always calls `next()`\n * and modifies the resulting response.\n */\n public override async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {\n const response = await next();\n\n const mutable = new Response(response.body, response);\n\n addCorsHeaders(worker, this.config, mutable.headers);\n if (!allowAnyOrigin(this.config)) {\n mergeHeader(mutable.headers, \"Vary\", \"Origin\");\n }\n\n return mutable;\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Method, normalizeUrl } from \"../../common\";\nimport { Middleware } from \"../middleware\";\nimport { Worker } from \"../../interfaces/worker\";\n\n/**\n * Middleware for caching GET requests.\n *\n * This middleware checks a cache (either a named cache or the default)\n * before passing the request down the middleware chain. Responses for\n * successful GET requests are automatically stored in the cache.\n *\n * Non-GET requests are never cached. The cache key can be customized\n * via the `getKey` function; otherwise, the URL is normalized and used.\n *\n * Example usage:\n * ```ts\n * const cacheMiddleware = new CacheHandler(\"my-cache\", (req) => new URL(req.url));\n * worker.use(cacheMiddleware);\n * ```\n */\nexport class CacheHandler extends Middleware {\n /**\n * @param cacheName - Optional name of the cache to use. If omitted,\n * `caches.default` is used.\n * @param getKey - Optional function to generate a cache key from a request.\n * Defaults to using the normalized request URL.\n */\n constructor(\n protected readonly cacheName?: string,\n protected readonly getKey?: (request: Request) => URL | RequestInfo,\n ) {\n super();\n }\n\n /**\n * Handle a request in the caching middleware.\n *\n * Checks the cache for GET requests and returns the cached response if available.\n * Otherwise, calls `next()` to continue the middleware chain and caches\n * the response if successful.\n *\n * @param worker - The Worker instance containing the request context.\n * @param next - Function to invoke the next middleware in the chain.\n * @returns A Response object, either from cache or the next middleware.\n */\n public override async handle(worker: Worker, next: () => Promise<Response>): Promise<Response> {\n const cache = this.cacheName ? await caches.open(this.cacheName) : caches.default;\n\n if (worker.request.method === Method.GET) {\n const cached = await cache.match(this.getCacheKey(worker.request));\n if (cached) return cached;\n }\n\n const response = await next();\n\n if (worker.request.method === Method.GET && response.ok) {\n worker.ctx.waitUntil(cache.put(this.getCacheKey(worker.request), response.clone()));\n }\n return response;\n }\n\n /**\n * Generate the cache key for a request.\n *\n * @param request - The Request object to generate a cache key for.\n * @returns A URL or RequestInfo used as the cache key.\n *\n * If a custom `getKey` function was provided in the constructor, it is used.\n * Otherwise, the request URL is normalized.\n */\n public getCacheKey(request: Request): URL | RequestInfo {\n return this.getKey ? this.getKey(request) : normalizeUrl(request.url);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Method } from \"../common\";\nimport { FetchHandler } from \"../interfaces/fetch-handler\";\nimport { Worker } from \"../interfaces/worker\";\n\n/**\n * Represents the constructor of a Worker subclass.\n *\n * @template T - The specific type of Worker being constructed. Defaults to `Worker`.\n * @param req - The `Request` object to be handled by the worker instance.\n * @param env - The environment bindings available to the worker.\n * @param ctx - The `ExecutionContext` for the worker invocation.\n * @returns An instance of the worker type `T`.\n */\ntype WorkerConstructor<T extends Worker = Worker> = new (\n request: Request,\n env: Env,\n ctx: ExecutionContext,\n) => T;\n\n/**\n * Provides the foundational structure for handling requests,\n * environment bindings, and the worker execution context.\n *\n * Features:\n * - Holds the current `Request` object (`request` getter).\n * - Provides access to environment bindings (`env` getter).\n * - Provides access to the worker execution context (`ctx` getter).\n * - Subclasses must implement `fetch()` to process the request.\n */\nexport abstract class BaseWorker implements Worker {\n constructor(\n private readonly _request: Request,\n private readonly _env: Env,\n private readonly _ctx: ExecutionContext,\n ) {}\n\n /** The Request object associated with this worker invocation */\n public get request(): Request {\n return this._request;\n }\n\n /** Environment bindings (e.g., KV, secrets, or other globals) */\n public get env(): Env {\n return this._env;\n }\n\n /** Execution context for background tasks or `waitUntil` */\n public get ctx(): ExecutionContext {\n return this._ctx;\n }\n\n /**\n * Dispatches the incoming request to the appropriate handler and produces a response.\n *\n * Subclasses must implement this method to define how the worker generates a `Response`\n * for the current request. This is the central point where request processing occurs,\n * and where middleware chains, routing, or other custom behavior can be applied.\n *\n * @returns A Promise that resolves to the `Response` for the request.\n */\n protected abstract dispatch(): Promise<Response>;\n\n /**\n * The DEFAULT allowed HTTP methods for subclasses.\n */\n public getAllowedMethods(): Method[] {\n return [Method.GET, Method.HEAD, Method.OPTIONS];\n }\n\n /**\n * Creates a new instance of the current Worker subclass.\n *\n * @param request - The {@link Request} to pass to the new worker instance.\n * @returns A new worker instance of the same subclass as `this`.\n */\n protected create(request: Request): this {\n const ctor = this.constructor as WorkerConstructor<this>;\n return new ctor(request, this.env, this.ctx);\n }\n\n /**\n * Process the {@link Request} and produce a {@link Response}.\n *\n * @returns A {@link Response} promise for the {@link Request}.\n */\n public abstract fetch(): Promise<Response>;\n\n /**\n * **Ignite** your `Worker` implementation into a Cloudflare handler.\n *\n * @returns A `FetchHandler` that launches a new worker instance for each request.\n *\n * @example\n * ```ts\n * export default MyWorker.ignite();\n * ```\n */\n public static ignite<W extends Worker>(this: WorkerConstructor<W>): FetchHandler {\n return {\n fetch: (request: Request, env: Env, ctx: ExecutionContext) =>\n new this(request, env, ctx).fetch(),\n };\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BaseWorker } from \"./base-worker\";\nimport { Middleware } from \"../middleware/middleware\";\n/** Internal base worker for handling middleware chains. */\nexport abstract class MiddlewareWorker extends BaseWorker {\n /** Middleware handlers registered for this worker. */\n protected readonly middlewares: Middleware[] = [];\n\n /**\n * Add a middleware to this worker.\n *\n * The middleware will run for every request handled by this worker,\n * in the order they are added.\n *\n * @param handler - The middleware to run.\n * @returns `this` to allow chaining multiple `.use()` calls.\n */\n public use(handler: Middleware): this {\n this.middlewares.push(handler);\n return this;\n }\n\n /**\n * Executes the middleware chain and dispatches the request.\n *\n * @returns The Response produced by the last middleware or `dispatch()`.\n */\n public override async fetch(): Promise<Response> {\n const chain = this.middlewares.reduceRight(\n (next, handler) => () => handler.handle(this, next),\n () => this.dispatch(),\n );\n return await chain();\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { isMethod, Method } from \"../common\";\nimport { MethodNotAllowed, InternalServerError, MethodNotImplemented } from \"../errors\";\nimport { MiddlewareWorker } from \"./middleware-worker\";\nimport { Head, Options, WorkerResponse } from \"../responses\";\nimport { Worker } from \"../interfaces/worker\";\n\n/**\n * Base worker class providing HTTP method dispatching, caching, and error handling.\n * Extends `CacheWorker` and defines default implementations for HTTP methods.\n */\nexport abstract class BasicWorker extends MiddlewareWorker {\n /**\n * Entry point to handle a fetch request.\n * Checks allowed methods, serves cached responses, or dispatches to the appropriate handler.\n */\n public override async fetch(): Promise<Response> {\n if (!this.isAllowed(this.request.method)) {\n return this.getResponse(MethodNotAllowed);\n }\n\n try {\n this.init();\n return await super.fetch();\n } catch (error) {\n console.error(error);\n return this.getResponse(InternalServerError);\n }\n }\n\n /**\n * Dispatches the request to the method-specific handler.\n * Defaults to MethodNotAllowed if the HTTP method is not recognized.\n */\n protected override async dispatch(): Promise<Response> {\n const method = this.request.method as Method;\n const handler: Record<Method, () => Promise<Response>> = {\n GET: () => this.get(),\n PUT: () => this.put(),\n HEAD: () => this.head(),\n POST: () => this.post(),\n PATCH: () => this.patch(),\n DELETE: () => this.delete(),\n OPTIONS: () => this.options(),\n };\n return (handler[method] ?? (() => this.getResponse(MethodNotAllowed)))();\n }\n\n /**\n * Hook for subclasses to perform any initialization.\n */\n protected init(): void {\n return;\n }\n\n /**\n * Checks if the given HTTP method is allowed for this worker.\n * @param method HTTP method string\n * @returns true if the method is allowed\n */\n public isAllowed(method: string): boolean {\n return isMethod(method) && this.getAllowedMethods().includes(method);\n }\n\n /** Default handler for GET requests. Returns MethodNotImplemented unless overridden. */\n protected async get(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for PUT requests. Returns MethodNotImplemented unless overridden. */\n protected async put(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for POST requests. Returns MethodNotImplemented unless overridden. */\n protected async post(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for PATCH requests. Returns MethodNotImplemented unless overridden. */\n protected async patch(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /** Default handler for DELETE requests. Returns MethodNotImplemented unless overridden. */\n protected async delete(): Promise<Response> {\n return this.getResponse(MethodNotImplemented);\n }\n\n /**\n * Default handler for OPTIONS requests.\n * Returns an Options response.\n *\n * Typically does not need to be overridden.\n */\n protected async options(): Promise<Response> {\n return this.getResponse(Options);\n }\n\n /**\n * Default handler for HEAD requests.\n * Performs a GET request internally and removes the body for HEAD semantics.\n *\n * Usually does not need to be overridden, as this behavior covers standard HEAD requirements.\n */\n protected async head(): Promise<Response> {\n const worker = this.create(new Request(this.request, { method: Method.GET }));\n return this.getResponse(Head, await worker.fetch());\n }\n\n /**\n * Helper to construct a WorkerResponse of the given class with arguments.\n * @param ResponseClass The response class to instantiate\n * @param args Additional constructor arguments\n * @returns The final Response object\n */\n protected async getResponse<\n T extends WorkerResponse,\n Ctor extends new (worker: Worker, ...args: any[]) => T,\n >(\n ResponseClass: Ctor,\n ...args: ConstructorParameters<Ctor> extends [Worker, ...infer R] ? R : never\n ): Promise<Response> {\n return new ResponseClass(this, ...args).getResponse();\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BasicWorker } from \"./basic-worker\";\nimport { Method } from \"../common\";\nimport { NotFound } from \"../errors\";\nimport { Routes } from \"../routes\";\nimport { RouteCallback, RouteTable } from \"../interfaces/route\";\n\n/**\n * Base worker supporting route-based request handling.\n *\n * Subclass `RouteWorker` to define a worker with multiple route handlers.\n *\n * Routes can be registered individually via `addRoute()` or in bulk via `load()`.\n * Middleware can be attached with `use()` to run for all requests.\n * ```\n */\nexport abstract class RouteWorker extends BasicWorker {\n /** Internal table of registered routes. */\n private readonly routes: Routes = new Routes();\n\n /**\n * Load multiple routes at once from a route table.\n * @param table - Array of routes to register.\n */\n protected load(table: RouteTable): void {\n this.routes.load(table);\n }\n\n /**\n * Add a single route.\n * @param method - HTTP method (GET, POST, etc.)\n * @param path - Route path, supports parameters like \"/users/:id\"\n * @param callback - Function to handle requests matching this route\n * @returns `this` for chaining multiple route additions\n */\n protected addRoute(method: Method, path: string, callback: RouteCallback): this {\n this.routes.add(method, path, callback);\n return this;\n }\n\n /**\n * Matches the incoming request against registered routes and executes the callback.\n * Falls back to the default handler if no match is found.\n * This is called automatically when the worker handles a request.\n */\n protected override async dispatch(): Promise<Response> {\n const found = this.routes.match(this.request.method as Method, this.request.url);\n if (!found) return super.dispatch();\n\n return found.route.callback.call(this, found.params);\n }\n\n protected override async get(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async put(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async post(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async patch(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async delete(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n}\n"],"mappings":"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","names":["HttpHeader","Method","MediaType","getReasonPhrase","StatusCodes","StatusCodes","getReasonPhrase"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adonix.org/cloud-spark",
3
- "version": "0.0.123",
3
+ "version": "0.0.124",
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",