@adonix.org/cloud-spark 0.0.89 → 0.0.91
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 +62 -55
- package/dist/index.js +97 -54
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -79,7 +79,7 @@ declare abstract class BaseWorker implements Worker {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
|
-
*
|
|
82
|
+
* @see {@link https://github.com/etienne-martin/cache-control-parser | cache-control-parser}
|
|
83
83
|
*/
|
|
84
84
|
type CacheControl = CacheLib.CacheControl;
|
|
85
85
|
declare const CacheControl: {
|
|
@@ -225,15 +225,6 @@ declare function mergeHeader(headers: Headers, key: string, value: string | stri
|
|
|
225
225
|
* @returns A normalized URL string suitable for hashing or direct cache key use.
|
|
226
226
|
*/
|
|
227
227
|
declare function normalizeUrl(url: string): URL;
|
|
228
|
-
/**
|
|
229
|
-
* Encodes a given string into Base64 using UTF-8 encoding.
|
|
230
|
-
*
|
|
231
|
-
* This function correctly handles any Unicode characters.
|
|
232
|
-
*
|
|
233
|
-
* @param raw - The input string to encode.
|
|
234
|
-
* @returns The Base64-encoded string.
|
|
235
|
-
*/
|
|
236
|
-
declare function toBase64(raw: string): string;
|
|
237
228
|
|
|
238
229
|
/**
|
|
239
230
|
* Provides information about the CORS policy for the current request.
|
|
@@ -280,30 +271,6 @@ declare namespace Cors {
|
|
|
280
271
|
* @param headers The Headers object to update
|
|
281
272
|
*/
|
|
282
273
|
declare function addCorsHeaders(cors: CorsProvider, headers: Headers): void;
|
|
283
|
-
/**
|
|
284
|
-
* Deletes all standard CORS headers from the given Headers object.
|
|
285
|
-
* Useful for cleaning cached responses or resetting headers before reapplying CORS.
|
|
286
|
-
*
|
|
287
|
-
* @param headers The Headers object to clean
|
|
288
|
-
*/
|
|
289
|
-
declare function deleteCorsHeaders(headers: Headers): void;
|
|
290
|
-
/**
|
|
291
|
-
* Returns a new Response with CORS headers applied according to the policy.
|
|
292
|
-
* Original response is not mutated.
|
|
293
|
-
*
|
|
294
|
-
* @param cors The CorsProvider instance for policy
|
|
295
|
-
* @param res The original Response object
|
|
296
|
-
* @returns A new Response with updated CORS headers
|
|
297
|
-
*/
|
|
298
|
-
declare function withCorsHeaders(cors: CorsProvider, res: Response): Response;
|
|
299
|
-
/**
|
|
300
|
-
* Returns a new Response with all standard CORS headers removed.
|
|
301
|
-
* Useful for storing responses in a cache without per-request CORS headers.
|
|
302
|
-
*
|
|
303
|
-
* @param res The original Response object
|
|
304
|
-
* @returns A new Response without CORS headers
|
|
305
|
-
*/
|
|
306
|
-
declare function withoutCorsHeaders(res: Response): Response;
|
|
307
274
|
|
|
308
275
|
/**
|
|
309
276
|
* Abstract base class for Workers to provide a default CORS policy.
|
|
@@ -328,33 +295,43 @@ declare abstract class CorsWorker extends BaseWorker implements CorsProvider {
|
|
|
328
295
|
}
|
|
329
296
|
|
|
330
297
|
/**
|
|
331
|
-
* Abstract
|
|
298
|
+
* Abstract worker class that adds caching support for GET requests.
|
|
332
299
|
*
|
|
333
|
-
*
|
|
334
|
-
* -
|
|
335
|
-
* -
|
|
336
|
-
* - Dynamically
|
|
337
|
-
*
|
|
300
|
+
* Behavior:
|
|
301
|
+
* - Caches successful GET responses (`response.ok === true`) in the selected cache.
|
|
302
|
+
* - Strips CORS headers from cached responses; all other origin headers are preserved.
|
|
303
|
+
* - Dynamically adds CORS headers to cached responses when returned to the client.
|
|
304
|
+
*
|
|
305
|
+
* Subclasses should override `getCacheKey()` to customize cache key generation if needed.
|
|
338
306
|
*/
|
|
339
307
|
declare abstract class CacheWorker extends CorsWorker {
|
|
340
308
|
/**
|
|
341
309
|
* Returns the cache key for the current request.
|
|
342
|
-
* By default, this is the normalized request URL.
|
|
343
310
|
*
|
|
344
|
-
*
|
|
311
|
+
* Behavior:
|
|
312
|
+
* - By default, returns the normalized request URL.
|
|
313
|
+
* - Query parameters are normalized so that the order does not affect the cache key.
|
|
314
|
+
* For example, `?a=1&b=2` and `?b=2&a=1` produce the same cache key.
|
|
315
|
+
*
|
|
316
|
+
* Subclasses may override this method to implement custom cache key strategies.
|
|
317
|
+
*
|
|
318
|
+
* @returns {URL | RequestInfo} The URL or RequestInfo used as the cache key.
|
|
345
319
|
*/
|
|
346
320
|
protected getCacheKey(): URL | RequestInfo;
|
|
347
321
|
/**
|
|
348
322
|
* Retrieves a cached Response for the current request, if one exists.
|
|
349
323
|
*
|
|
350
324
|
* Behavior:
|
|
351
|
-
* - Only GET requests are
|
|
352
|
-
* -
|
|
353
|
-
*
|
|
354
|
-
* -
|
|
325
|
+
* - Only GET requests are considered.
|
|
326
|
+
* - Returns a new Response with dynamic CORS headers applied via `addCacheHeaders`.
|
|
327
|
+
* - Returns `undefined` if no cached response is found.
|
|
328
|
+
* - Cloudflare dynamic headers (`CF-Cache-Status`, `Age`, `Connection`, etc.) will
|
|
329
|
+
* always be present on the returned response, even though they are not stored in the cache.
|
|
355
330
|
*
|
|
356
|
-
* @param cacheName Optional
|
|
357
|
-
* @returns
|
|
331
|
+
* @param {string} [cacheName] Optional named cache; defaults to `caches.default`.
|
|
332
|
+
* @returns {Promise<Response | undefined>} A Response with CORS headers, or undefined.
|
|
333
|
+
* @see {@link setCachedResponse}
|
|
334
|
+
* @see {@link getCacheKey}
|
|
358
335
|
*/
|
|
359
336
|
protected getCachedResponse(cacheName?: string): Promise<Response | undefined>;
|
|
360
337
|
/**
|
|
@@ -362,13 +339,40 @@ declare abstract class CacheWorker extends CorsWorker {
|
|
|
362
339
|
*
|
|
363
340
|
* Behavior:
|
|
364
341
|
* - Only caches successful GET responses (`response.ok === true`).
|
|
365
|
-
* -
|
|
366
|
-
* - Uses `ctx.waitUntil` to
|
|
342
|
+
* - Strips headers via `removeCacheHeaders` before storing.
|
|
343
|
+
* - Uses `ctx.waitUntil` to perform caching asynchronously without blocking the response.
|
|
344
|
+
* - All other origin headers (e.g., Cache-Control, Expires) are preserved.
|
|
367
345
|
*
|
|
368
|
-
* @param response The Response to cache
|
|
369
|
-
* @param cacheName Optional
|
|
346
|
+
* @param {Response} response The Response to cache.
|
|
347
|
+
* @param {string} [cacheName] Optional named cache; defaults to `caches.default`.
|
|
348
|
+
* @see {@link getCachedResponse}
|
|
349
|
+
* @see {@link getCacheKey}
|
|
370
350
|
*/
|
|
371
351
|
protected setCachedResponse(response: Response, cacheName?: string): Promise<void>;
|
|
352
|
+
/**
|
|
353
|
+
* Adds headers to a cached response.
|
|
354
|
+
*
|
|
355
|
+
* @param {Response} cached The cached Response.
|
|
356
|
+
* @returns {Response} A new Response with dynamic CORS headers applied.
|
|
357
|
+
* @see {@link removeCacheHeaders}
|
|
358
|
+
*/
|
|
359
|
+
private addCacheHeaders;
|
|
360
|
+
/**
|
|
361
|
+
* Removes headers that should not be stored in the cache (currently only CORS headers).
|
|
362
|
+
*
|
|
363
|
+
* @param {Response} response The Response to clean before caching.
|
|
364
|
+
* @returns {Response} A new Response with excluded headers removed.
|
|
365
|
+
* @see {@link addCacheHeaders}
|
|
366
|
+
*/
|
|
367
|
+
private removeCacheHeaders;
|
|
368
|
+
/**
|
|
369
|
+
* Returns the list of headers to exclude from the cached response.
|
|
370
|
+
* By default, excludes only dynamic CORS headers.
|
|
371
|
+
*
|
|
372
|
+
* @returns {string[]} Array of header names to exclude.
|
|
373
|
+
* @see {@link removeCacheHeaders}
|
|
374
|
+
*/
|
|
375
|
+
protected excludeCacheHeaders(): string[];
|
|
372
376
|
}
|
|
373
377
|
|
|
374
378
|
interface ErrorJson {
|
|
@@ -396,7 +400,7 @@ declare abstract class CorsResponse extends BaseResponse {
|
|
|
396
400
|
declare abstract class CacheResponse extends CorsResponse {
|
|
397
401
|
cache?: CacheControl | undefined;
|
|
398
402
|
constructor(cors: CorsProvider, body?: BodyInit | null, cache?: CacheControl | undefined);
|
|
399
|
-
protected
|
|
403
|
+
protected addCacheHeaders(): void;
|
|
400
404
|
}
|
|
401
405
|
declare abstract class WorkerResponse extends CacheResponse {
|
|
402
406
|
createResponse(): Response;
|
|
@@ -454,7 +458,10 @@ declare class InternalServerError extends HttpError {
|
|
|
454
458
|
constructor(cors: CorsProvider, details?: string);
|
|
455
459
|
}
|
|
456
460
|
declare class NotImplemented extends HttpError {
|
|
457
|
-
constructor(cors: CorsProvider);
|
|
461
|
+
constructor(cors: CorsProvider, details?: string);
|
|
462
|
+
}
|
|
463
|
+
declare class MethodNotImplemented extends NotImplemented {
|
|
464
|
+
constructor(cors: CorsProvider, method: Method);
|
|
458
465
|
}
|
|
459
466
|
declare class ServiceUnavailable extends HttpError {
|
|
460
467
|
constructor(cors: CorsProvider, details?: string);
|
|
@@ -536,4 +543,4 @@ declare abstract class RoutedWorker extends BasicWorker {
|
|
|
536
543
|
protected delete(): Promise<Response>;
|
|
537
544
|
}
|
|
538
545
|
|
|
539
|
-
export { BadRequest, BasicWorker, CacheControl, ClonedResponse, Cors, type CorsProvider, type ErrorJson, Forbidden, Head, HtmlResponse, HttpError, HttpHeader, InternalServerError, JsonResponse, MediaType, Method, MethodNotAllowed, NotFound, NotImplemented, Options, Route, type RouteCallback, type RouteInit, RoutedWorker, Routes, ServiceUnavailable, SuccessResponse, TextResponse, Time, Unauthorized, type Worker, WorkerResponse, addCorsHeaders,
|
|
546
|
+
export { BadRequest, BasicWorker, CacheControl, ClonedResponse, Cors, type CorsProvider, type ErrorJson, Forbidden, Head, HtmlResponse, HttpError, HttpHeader, InternalServerError, JsonResponse, MediaType, Method, MethodNotAllowed, MethodNotImplemented, NotFound, NotImplemented, Options, Route, type RouteCallback, type RouteInit, RoutedWorker, Routes, ServiceUnavailable, SuccessResponse, TextResponse, Time, Unauthorized, type Worker, WorkerResponse, addCorsHeaders, getContentType, isMethod, mergeHeader, normalizeUrl, setHeader };
|
package/dist/index.js
CHANGED
|
@@ -142,14 +142,6 @@ function normalizeUrl(url) {
|
|
|
142
142
|
u.hash = "";
|
|
143
143
|
return u;
|
|
144
144
|
}
|
|
145
|
-
function toBase64(raw) {
|
|
146
|
-
const bytes = new TextEncoder().encode(raw);
|
|
147
|
-
let binary = "";
|
|
148
|
-
for (const b of bytes) {
|
|
149
|
-
binary += String.fromCharCode(b);
|
|
150
|
-
}
|
|
151
|
-
return btoa(binary);
|
|
152
|
-
}
|
|
153
145
|
|
|
154
146
|
// src/cors.ts
|
|
155
147
|
var Cors;
|
|
@@ -185,24 +177,6 @@ function deleteCorsHeaders(headers) {
|
|
|
185
177
|
headers.delete(Cors.ALLOW_METHODS);
|
|
186
178
|
headers.delete(Cors.MAX_AGE);
|
|
187
179
|
}
|
|
188
|
-
function withCorsHeaders(cors, res) {
|
|
189
|
-
const headers = new Headers(res.headers);
|
|
190
|
-
addCorsHeaders(cors, headers);
|
|
191
|
-
return new Response(res.body, {
|
|
192
|
-
status: res.status,
|
|
193
|
-
statusText: res.statusText,
|
|
194
|
-
headers
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
function withoutCorsHeaders(res) {
|
|
198
|
-
const headers = new Headers(res.headers);
|
|
199
|
-
deleteCorsHeaders(headers);
|
|
200
|
-
return new Response(res.body, {
|
|
201
|
-
status: res.status,
|
|
202
|
-
statusText: res.statusText,
|
|
203
|
-
headers
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
180
|
|
|
207
181
|
// src/base-worker.ts
|
|
208
182
|
var BaseWorker = class {
|
|
@@ -269,9 +243,15 @@ var CorsWorker = class extends BaseWorker {
|
|
|
269
243
|
var CacheWorker = class extends CorsWorker {
|
|
270
244
|
/**
|
|
271
245
|
* Returns the cache key for the current request.
|
|
272
|
-
* By default, this is the normalized request URL.
|
|
273
246
|
*
|
|
274
|
-
*
|
|
247
|
+
* Behavior:
|
|
248
|
+
* - By default, returns the normalized request URL.
|
|
249
|
+
* - Query parameters are normalized so that the order does not affect the cache key.
|
|
250
|
+
* For example, `?a=1&b=2` and `?b=2&a=1` produce the same cache key.
|
|
251
|
+
*
|
|
252
|
+
* Subclasses may override this method to implement custom cache key strategies.
|
|
253
|
+
*
|
|
254
|
+
* @returns {URL | RequestInfo} The URL or RequestInfo used as the cache key.
|
|
275
255
|
*/
|
|
276
256
|
getCacheKey() {
|
|
277
257
|
return normalizeUrl(this.request.url);
|
|
@@ -280,36 +260,97 @@ var CacheWorker = class extends CorsWorker {
|
|
|
280
260
|
* Retrieves a cached Response for the current request, if one exists.
|
|
281
261
|
*
|
|
282
262
|
* Behavior:
|
|
283
|
-
* - Only GET requests are
|
|
284
|
-
* -
|
|
285
|
-
*
|
|
286
|
-
* -
|
|
263
|
+
* - Only GET requests are considered.
|
|
264
|
+
* - Returns a new Response with dynamic CORS headers applied via `addCacheHeaders`.
|
|
265
|
+
* - Returns `undefined` if no cached response is found.
|
|
266
|
+
* - Cloudflare dynamic headers (`CF-Cache-Status`, `Age`, `Connection`, etc.) will
|
|
267
|
+
* always be present on the returned response, even though they are not stored in the cache.
|
|
287
268
|
*
|
|
288
|
-
* @param cacheName Optional
|
|
289
|
-
* @returns
|
|
269
|
+
* @param {string} [cacheName] Optional named cache; defaults to `caches.default`.
|
|
270
|
+
* @returns {Promise<Response | undefined>} A Response with CORS headers, or undefined.
|
|
271
|
+
* @see {@link setCachedResponse}
|
|
272
|
+
* @see {@link getCacheKey}
|
|
290
273
|
*/
|
|
291
274
|
async getCachedResponse(cacheName) {
|
|
292
275
|
if (this.request.method !== "GET" /* GET */) return;
|
|
293
276
|
const cache = cacheName ? await caches.open(cacheName) : caches.default;
|
|
294
277
|
const response = await cache.match(this.getCacheKey());
|
|
295
|
-
return response ?
|
|
278
|
+
return response ? this.addCacheHeaders(response) : void 0;
|
|
296
279
|
}
|
|
297
280
|
/**
|
|
298
281
|
* Stores a Response in the cache for the current request.
|
|
299
282
|
*
|
|
300
283
|
* Behavior:
|
|
301
284
|
* - Only caches successful GET responses (`response.ok === true`).
|
|
302
|
-
* -
|
|
303
|
-
* - Uses `ctx.waitUntil` to
|
|
285
|
+
* - Strips headers via `removeCacheHeaders` before storing.
|
|
286
|
+
* - Uses `ctx.waitUntil` to perform caching asynchronously without blocking the response.
|
|
287
|
+
* - All other origin headers (e.g., Cache-Control, Expires) are preserved.
|
|
304
288
|
*
|
|
305
|
-
* @param response The Response to cache
|
|
306
|
-
* @param cacheName Optional
|
|
289
|
+
* @param {Response} response The Response to cache.
|
|
290
|
+
* @param {string} [cacheName] Optional named cache; defaults to `caches.default`.
|
|
291
|
+
* @see {@link getCachedResponse}
|
|
292
|
+
* @see {@link getCacheKey}
|
|
307
293
|
*/
|
|
308
294
|
async setCachedResponse(response, cacheName) {
|
|
309
295
|
if (!response.ok) return;
|
|
310
296
|
if (this.request.method !== "GET" /* GET */) return;
|
|
311
297
|
const cache = cacheName ? await caches.open(cacheName) : caches.default;
|
|
312
|
-
this.ctx?.waitUntil(
|
|
298
|
+
this.ctx?.waitUntil(
|
|
299
|
+
cache.put(this.getCacheKey(), this.removeCacheHeaders(response.clone()))
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Adds headers to a cached response.
|
|
304
|
+
*
|
|
305
|
+
* @param {Response} cached The cached Response.
|
|
306
|
+
* @returns {Response} A new Response with dynamic CORS headers applied.
|
|
307
|
+
* @see {@link removeCacheHeaders}
|
|
308
|
+
*/
|
|
309
|
+
addCacheHeaders(cached) {
|
|
310
|
+
const headers = new Headers(cached.headers);
|
|
311
|
+
addCorsHeaders(this, headers);
|
|
312
|
+
return new Response(cached.body, {
|
|
313
|
+
status: cached.status,
|
|
314
|
+
statusText: cached.statusText,
|
|
315
|
+
headers
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Removes headers that should not be stored in the cache (currently only CORS headers).
|
|
320
|
+
*
|
|
321
|
+
* @param {Response} response The Response to clean before caching.
|
|
322
|
+
* @returns {Response} A new Response with excluded headers removed.
|
|
323
|
+
* @see {@link addCacheHeaders}
|
|
324
|
+
*/
|
|
325
|
+
removeCacheHeaders(response) {
|
|
326
|
+
const excludeSet = new Set(this.excludeCacheHeaders().map((h) => h.toLowerCase()));
|
|
327
|
+
const headers = new Headers();
|
|
328
|
+
for (const [key, value] of response.headers) {
|
|
329
|
+
if (!excludeSet.has(key)) {
|
|
330
|
+
headers.set(key, value);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return new Response(response.body, {
|
|
334
|
+
status: response.status,
|
|
335
|
+
statusText: response.statusText,
|
|
336
|
+
headers
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Returns the list of headers to exclude from the cached response.
|
|
341
|
+
* By default, excludes only dynamic CORS headers.
|
|
342
|
+
*
|
|
343
|
+
* @returns {string[]} Array of header names to exclude.
|
|
344
|
+
* @see {@link removeCacheHeaders}
|
|
345
|
+
*/
|
|
346
|
+
excludeCacheHeaders() {
|
|
347
|
+
return [
|
|
348
|
+
Cors.ALLOW_ORIGIN,
|
|
349
|
+
Cors.ALLOW_CREDENTIALS,
|
|
350
|
+
Cors.EXPOSE_HEADERS,
|
|
351
|
+
Cors.ALLOW_METHODS,
|
|
352
|
+
Cors.MAX_AGE
|
|
353
|
+
];
|
|
313
354
|
}
|
|
314
355
|
};
|
|
315
356
|
|
|
@@ -357,7 +398,7 @@ var CacheResponse = class extends CorsResponse {
|
|
|
357
398
|
super(cors, body);
|
|
358
399
|
this.cache = cache;
|
|
359
400
|
}
|
|
360
|
-
|
|
401
|
+
addCacheHeaders() {
|
|
361
402
|
if (this.cache) {
|
|
362
403
|
this.headers.set(HttpHeader.CACHE_CONTROL, CacheControl.stringify(this.cache));
|
|
363
404
|
}
|
|
@@ -366,7 +407,7 @@ var CacheResponse = class extends CorsResponse {
|
|
|
366
407
|
var WorkerResponse = class extends CacheResponse {
|
|
367
408
|
createResponse() {
|
|
368
409
|
this.addCorsHeaders();
|
|
369
|
-
this.
|
|
410
|
+
this.addCacheHeaders();
|
|
370
411
|
this.addSecurityHeaders();
|
|
371
412
|
const body = this.status === StatusCodes2.NO_CONTENT ? null : this.body;
|
|
372
413
|
if (body) this.addContentType();
|
|
@@ -482,8 +523,13 @@ var InternalServerError = class extends HttpError {
|
|
|
482
523
|
}
|
|
483
524
|
};
|
|
484
525
|
var NotImplemented = class extends HttpError {
|
|
485
|
-
constructor(cors) {
|
|
486
|
-
super(cors, StatusCodes2.NOT_IMPLEMENTED);
|
|
526
|
+
constructor(cors, details) {
|
|
527
|
+
super(cors, StatusCodes2.NOT_IMPLEMENTED, details);
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
var MethodNotImplemented = class extends NotImplemented {
|
|
531
|
+
constructor(cors, method) {
|
|
532
|
+
super(cors, `${method} method not implemented.`);
|
|
487
533
|
}
|
|
488
534
|
};
|
|
489
535
|
var ServiceUnavailable = class extends HttpError {
|
|
@@ -518,19 +564,19 @@ var BasicWorker = class extends CacheWorker {
|
|
|
518
564
|
return (handler[method] ?? (() => this.getResponse(MethodNotAllowed, method)))();
|
|
519
565
|
}
|
|
520
566
|
async get() {
|
|
521
|
-
return this.getResponse(
|
|
567
|
+
return this.getResponse(MethodNotImplemented, "GET" /* GET */);
|
|
522
568
|
}
|
|
523
569
|
async put() {
|
|
524
|
-
return this.getResponse(
|
|
570
|
+
return this.getResponse(MethodNotImplemented, "PUT" /* PUT */);
|
|
525
571
|
}
|
|
526
572
|
async post() {
|
|
527
|
-
return this.getResponse(
|
|
573
|
+
return this.getResponse(MethodNotImplemented, "POST" /* POST */);
|
|
528
574
|
}
|
|
529
575
|
async patch() {
|
|
530
|
-
return this.getResponse(
|
|
576
|
+
return this.getResponse(MethodNotImplemented, "PATCH" /* PATCH */);
|
|
531
577
|
}
|
|
532
578
|
async delete() {
|
|
533
|
-
return this.getResponse(
|
|
579
|
+
return this.getResponse(MethodNotImplemented, "DELETE" /* DELETE */);
|
|
534
580
|
}
|
|
535
581
|
async options() {
|
|
536
582
|
return this.getResponse(Options);
|
|
@@ -646,6 +692,7 @@ export {
|
|
|
646
692
|
MediaType,
|
|
647
693
|
Method,
|
|
648
694
|
MethodNotAllowed,
|
|
695
|
+
MethodNotImplemented,
|
|
649
696
|
NotFound,
|
|
650
697
|
NotImplemented,
|
|
651
698
|
Options,
|
|
@@ -660,14 +707,10 @@ export {
|
|
|
660
707
|
Unauthorized,
|
|
661
708
|
WorkerResponse,
|
|
662
709
|
addCorsHeaders,
|
|
663
|
-
deleteCorsHeaders,
|
|
664
710
|
getContentType,
|
|
665
711
|
isMethod,
|
|
666
712
|
mergeHeader,
|
|
667
713
|
normalizeUrl,
|
|
668
|
-
setHeader
|
|
669
|
-
toBase64,
|
|
670
|
-
withCorsHeaders,
|
|
671
|
-
withoutCorsHeaders
|
|
714
|
+
setHeader
|
|
672
715
|
};
|
|
673
716
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/common.ts","../src/cors.ts","../src/base-worker.ts","../src/cors-worker.ts","../src/cache-worker.ts","../src/response.ts","../src/basic-worker.ts","../src/routes.ts","../src/routed-worker.ts"],"sourcesContent":["/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport CacheLib from \"cache-control-parser\";\n\n/**\n * - See https://github.com/etienne-martin/cache-control-parser\n */\nexport type CacheControl = CacheLib.CacheControl;\nexport const CacheControl = {\n parse: CacheLib.parse,\n stringify: CacheLib.stringify,\n};\n\n/**\n * - See https://github.com/prettymuchbryce/http-status-codes\n */\nexport { StatusCodes } from \"http-status-codes\";\n\n/**\n * Standard HTTP header names and common values.\n */\nexport namespace HttpHeader {\n export const VARY = \"Vary\";\n export const CONTENT_TYPE = \"Content-Type\";\n export const CACHE_CONTROL = \"Cache-Control\";\n\n // Security Headers\n export const X_CONTENT_TYPE_OPTIONS = \"X-Content-Type-Options\"; // usually \"nosniff\"\n export const X_FRAME_OPTIONS = \"X-Frame-Options\"; // e.g. \"DENY\" or \"SAMEORIGIN\"\n export const STRICT_TRANSPORT_SECURITY = \"Strict-Transport-Security\"; // e.g. \"max-age=63072000; includeSubDomains; preload\"\n export const CONTENT_SECURITY_POLICY = \"Content-Security-Policy\"; // fine-grained script/style/image restrictions\n export const REFERRER_POLICY = \"Referrer-Policy\"; // e.g. \"no-referrer\", \"strict-origin-when-cross-origin\"\n export const PERMISSIONS_POLICY = \"Permissions-Policy\"; // formerly Feature-Policy, controls APIs like geolocation/camera\n\n // Values\n export const NOSNIFF = \"nosniff\";\n export const ORIGIN = \"Origin\";\n}\n\n/**\n * Time constants in seconds. Month is approximated as 30 days.\n */\nexport const Time = {\n Second: 1,\n Minute: 60,\n Hour: 3600, // 60 * 60\n Day: 86400, // 60 * 60 * 24\n Week: 604800, // 60 * 60 * 24 * 7\n Month: 2592000, // 60 * 60 * 24 * 30\n Year: 31536000, // 60 * 60 * 24 * 365\n} as const;\n\n/**\n * Standard HTTP request methods.\n */\nexport enum Method {\n GET = \"GET\",\n PUT = \"PUT\",\n POST = \"POST\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n HEAD = \"HEAD\",\n OPTIONS = \"OPTIONS\",\n}\nconst METHOD_SET: Set<string> = new Set(Object.values(Method));\n\n/**\n * Type guard that checks if a string is a valid HTTP method.\n *\n * @param value - The string to test.\n * @returns True if `value` is a recognized HTTP method.\n */\nexport function isMethod(value: string): value is Method {\n return METHOD_SET.has(value);\n}\n\n/**\n * Returns the proper Content-Type string for a given media type.\n * Appends `charset=utf-8` for text-based types that require it.\n *\n * @param type - The media type.\n * @returns A string suitable for the `Content-Type` header.\n */\nexport function getContentType(type: MediaType): string {\n if (ADD_CHARSET.has(type)) {\n return `${type}; charset=utf-8`;\n }\n return type;\n}\n\n/**\n * Common media types types used for HTTP headers.\n */\nexport enum MediaType {\n PLAIN_TEXT = \"text/plain\",\n HTML = \"text/html\",\n CSS = \"text/css\",\n CSV = \"text/csv\",\n XML = \"text/xml\",\n MARKDOWN = \"text/markdown\",\n RICH_TEXT = \"text/richtext\",\n JSON = \"application/json\",\n XML_APP = \"application/xml\",\n YAML = \"application/x-yaml\",\n FORM_URLENCODED = \"application/x-www-form-urlencoded\",\n NDJSON = \"application/x-ndjson\",\n MSGPACK = \"application/x-msgpack\",\n PROTOBUF = \"application/x-protobuf\",\n MULTIPART_FORM_DATA = \"multipart/form-data\",\n MULTIPART_MIXED = \"multipart/mixed\",\n MULTIPART_ALTERNATIVE = \"multipart/alternative\",\n MULTIPART_DIGEST = \"multipart/digest\",\n MULTIPART_RELATED = \"multipart/related\",\n MULTIPART_SIGNED = \"multipart/signed\",\n MULTIPART_ENCRYPTED = \"multipart/encrypted\",\n OCTET_STREAM = \"application/octet-stream\",\n PDF = \"application/pdf\",\n ZIP = \"application/zip\",\n GZIP = \"application/gzip\",\n MSWORD = \"application/msword\",\n DOCX = \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n EXCEL = \"application/vnd.ms-excel\",\n XLSX = \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n POWERPOINT = \"application/vnd.ms-powerpoint\",\n PPTX = \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n ICO = \"image/x-icon\",\n ICO_MS = \"image/vnd.microsoft.icon\",\n GIF = \"image/gif\",\n PNG = \"image/png\",\n JPEG = \"image/jpeg\",\n WEBP = \"image/webp\",\n SVG = \"image/svg+xml\",\n HEIF = \"image/heif\",\n AVIF = \"image/avif\",\n EVENT_STREAM = \"text/event-stream\",\n TAR = \"application/x-tar\",\n BZIP2 = \"application/x-bzip2\",\n}\n\n/**\n * A set of media types that require a `charset` parameter when setting\n * the `Content-Type` header.\n *\n * This includes common text-based media types such as HTML, CSS, JSON,\n * XML, CSV, Markdown, and others.\n */\nconst ADD_CHARSET: Set<MediaType> = new Set([\n MediaType.PLAIN_TEXT,\n MediaType.HTML,\n MediaType.CSS,\n MediaType.CSV,\n MediaType.MARKDOWN,\n MediaType.XML,\n MediaType.JSON,\n MediaType.XML_APP,\n MediaType.FORM_URLENCODED,\n MediaType.NDJSON,\n MediaType.RICH_TEXT,\n MediaType.SVG,\n]);\n\n/**\n * Sets a header on the given Headers object.\n *\n * - If `value` is an array, duplicates and empty strings are removed.\n * - If the resulting value array is empty, the header is deleted.\n * - Otherwise, values are joined with `\", \"` and set as the header value.\n *\n * @param headers - The Headers object to modify.\n * @param key - The header name to set.\n * @param value - The header value(s) to set. Can be a string or array of strings.\n */\nexport function setHeader(headers: Headers, key: string, value: string | string[]): void {\n const raw = Array.isArray(value) ? value : [value];\n const values = Array.from(new Set(raw.map((v) => v.trim()))).filter((v) => v.length);\n\n if (!values.length) {\n headers.delete(key);\n return;\n }\n\n headers.set(key, values.join(\", \"));\n}\n\n/**\n * Merges new value(s) into an existing header on the given Headers object.\n *\n * - Preserves any existing values and adds new ones.\n * - Removes duplicates and trims all values.\n * - If the header does not exist, it is created.\n *\n * @param headers - The Headers object to modify.\n * @param key - The header name to merge into.\n * @param value - The new header value(s) to add. Can be a string or array of strings.\n */\nexport function mergeHeader(headers: Headers, key: string, value: string | string[]): void {\n const values = Array.isArray(value) ? value : [value];\n if (!values.length) return;\n\n const existing = headers.get(key);\n if (existing) {\n const merged = existing.split(\",\").map((v) => v.trim());\n values.forEach((v) => merged.push(v.trim()));\n setHeader(headers, key, merged);\n } else {\n setHeader(headers, key, values);\n }\n}\n\n/**\n * Normalizes a URL string for use as a consistent cache key.\n *\n * - Sorts query parameters alphabetically so `?b=2&a=1` and `?a=1&b=2` are treated the same.\n * - Strips fragment identifiers (`#...`) since they are not sent in HTTP requests.\n * - Leaves protocol, host, path, and query values intact.\n *\n * @param url The original URL string to normalize.\n * @returns A normalized URL string suitable for hashing or direct cache key use.\n */\nexport function normalizeUrl(url: string): URL {\n const u = new URL(url);\n\n const params = [...u.searchParams.entries()];\n params.sort(([a], [b]) => a.localeCompare(b));\n\n u.search = params\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n u.hash = \"\";\n\n return u;\n}\n\n/**\n * Encodes a given string into Base64 using UTF-8 encoding.\n *\n * This function correctly handles any Unicode characters.\n *\n * @param raw - The input string to encode.\n * @returns The Base64-encoded string.\n */\nexport function toBase64(raw: string): string {\n const bytes = new TextEncoder().encode(raw);\n let binary = \"\";\n for (const b of bytes) {\n binary += String.fromCharCode(b);\n }\n return btoa(binary);\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { HttpHeader, mergeHeader, Method, setHeader } from \"./common\";\n\n/**\n * Provides information about the CORS policy for the current request.\n */\nexport interface CorsProvider {\n /** Returns the origin of the request, or null if none is provided. */\n getOrigin(): string | null;\n\n /** Returns a list of allowed origins. */\n getAllowOrigins(): string[];\n\n /** Returns true if any origin is allowed (`*`). */\n allowAnyOrigin(): boolean;\n\n /** Returns the HTTP methods allowed by CORS. */\n getAllowMethods(): Method[];\n\n /** Returns the HTTP headers allowed by CORS. */\n getAllowHeaders(): string[];\n\n /** Returns the HTTP headers that should be exposed to the browser. */\n getExposeHeaders(): string[];\n\n /** Returns the max age (in seconds) for CORS preflight caching. */\n getMaxAge(): number;\n}\n\n/**\n * Constants for common CORS headers.\n */\nexport namespace Cors {\n export const ALLOW_ORIGIN = \"Access-Control-Allow-Origin\";\n export const ALLOW_CREDENTIALS = \"Access-Control-Allow-Credentials\";\n export const EXPOSE_HEADERS = \"Access-Control-Expose-Headers\";\n export const ALLOW_HEADERS = \"Access-Control-Allow-Headers\";\n export const ALLOW_METHODS = \"Access-Control-Allow-Methods\";\n export const MAX_AGE = \"Access-Control-Max-Age\";\n export const ALLOW_ALL_ORIGINS = \"*\";\n}\n\n/**\n * Adds or updates CORS headers on a Headers object according to the provided policy.\n *\n * Behavior:\n * - Removes any existing CORS headers to avoid stale values.\n * - If the request has no origin, the function exits early.\n * - If wildcard `*` is allowed, sets Access-Control-Allow-Origin to `*`.\n * - If the origin is explicitly allowed, sets the correct headers including credentials and Vary: Origin.\n * - Optional headers (Expose-Headers, Allow-Headers, Allow-Methods, Max-Age) are always applied.\n *\n * @param cors The CorsProvider instance that determines allowed origins and headers\n * @param headers The Headers object to update\n */\nexport function addCorsHeaders(cors: CorsProvider, headers: Headers): void {\n // Remove stale headers if from cache\n deleteCorsHeaders(headers);\n\n const origin = cors.getOrigin();\n if (!origin) return;\n\n if (cors.allowAnyOrigin()) {\n setHeader(headers, Cors.ALLOW_ORIGIN, Cors.ALLOW_ALL_ORIGINS);\n } else if (cors.getAllowOrigins().includes(origin)) {\n setHeader(headers, Cors.ALLOW_ORIGIN, origin);\n setHeader(headers, Cors.ALLOW_CREDENTIALS, \"true\");\n mergeHeader(headers, HttpHeader.VARY, HttpHeader.ORIGIN);\n }\n\n // Optional headers always applied\n mergeHeader(headers, Cors.EXPOSE_HEADERS, cors.getExposeHeaders());\n setHeader(headers, Cors.ALLOW_HEADERS, cors.getAllowHeaders());\n setHeader(headers, Cors.ALLOW_METHODS, cors.getAllowMethods());\n setHeader(headers, Cors.MAX_AGE, String(cors.getMaxAge()));\n}\n\n/**\n * Deletes all standard CORS headers from the given Headers object.\n * Useful for cleaning cached responses or resetting headers before reapplying CORS.\n *\n * @param headers The Headers object to clean\n */\nexport function deleteCorsHeaders(headers: Headers) {\n headers.delete(Cors.ALLOW_ORIGIN);\n headers.delete(Cors.ALLOW_CREDENTIALS);\n headers.delete(Cors.EXPOSE_HEADERS);\n headers.delete(Cors.ALLOW_METHODS);\n headers.delete(Cors.MAX_AGE);\n}\n\n/**\n * Returns a new Response with CORS headers applied according to the policy.\n * Original response is not mutated.\n *\n * @param cors The CorsProvider instance for policy\n * @param res The original Response object\n * @returns A new Response with updated CORS headers\n */\nexport function withCorsHeaders(cors: CorsProvider, res: Response): Response {\n const headers = new Headers(res.headers);\n addCorsHeaders(cors, headers);\n return new Response(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers,\n });\n}\n\n/**\n * Returns a new Response with all standard CORS headers removed.\n * Useful for storing responses in a cache without per-request CORS headers.\n *\n * @param res The original Response object\n * @returns A new Response without CORS headers\n */\nexport function withoutCorsHeaders(res: Response): Response {\n const headers = new Headers(res.headers);\n deleteCorsHeaders(headers);\n return new Response(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers,\n });\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Worker } from \"./worker\";\n\n/**\n * A type-safe Cloudflare Worker handler where `fetch` is required.\n *\n * Extends `ExportedHandler` but guarantees that the `fetch` method exists\n * and has the correct signature for Cloudflare Worker invocation.\n *\n * @template E - The type of environment bindings passed to the worker. Defaults to `Env`.\n */\ninterface FetchHandler<E = Env> extends ExportedHandler<E> {\n /**\n * Handles an incoming request and produces a response.\n *\n * @param request - The incoming `Request` object.\n * @param env - Environment bindings (e.g., KV namespaces, secrets, Durable Objects).\n * @param ctx - Optional execution context for background tasks (`waitUntil`).\n * @returns A `Promise` that resolves to the response.\n */\n fetch: (request: Request, env: E, ctx: ExecutionContext) => Promise<Response>;\n}\n\n/**\n * Provides the foundational structure for handling requests, environment bindings,\n * and the worker execution context. Subclasses are expected to implement the\n * `fetch` method to handle the request and return a Response.\n *\n * Features:\n * - Holds the current `Request` object (`request` getter).\n * - Provides access to environment bindings (`env` getter).\n * - Provides access to the worker execution context (`ctx` getter), if available.\n * - Subclasses must implement `fetch()` to process the request.\n */\nexport abstract class BaseWorker implements Worker {\n constructor(\n private readonly _request: Request,\n private readonly _env: Env = {},\n private readonly _ctx?: ExecutionContext\n ) {}\n\n /** The Request object associated with this worker invocation */\n protected get request(): Request {\n return this._request;\n }\n\n /** Environment bindings (e.g., KV, secrets, or other globals) */\n protected get env(): Env {\n return this._env;\n }\n\n /** Optional execution context for background tasks or `waitUntil` */\n protected get ctx(): ExecutionContext | undefined {\n return this._ctx;\n }\n\n /**\n * Process the request and produce a Response.\n * Subclasses must implement this method.\n *\n * @returns A Promise resolving to the Response for the request\n */\n public abstract fetch(): Promise<Response>;\n\n /**\n * Ignite your `Worker` implementation into a Cloudflare-compatible handler.\n *\n * @returns A `FetchHandler` that launches a new worker instance for each request.\n *\n * @example\n * ```ts\n * export default MyWorker.ignite();\n * ```\n */\n public static ignite<T extends new (...args: any) => BaseWorker>(this: T): FetchHandler {\n return {\n fetch: (req: Request, env: Env, ctx: ExecutionContext) =>\n new this(req, env, ctx).fetch(),\n };\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BaseWorker } from \"./base-worker\";\nimport { Method, Time } from \"./common\";\nimport { CorsProvider } from \"./cors\";\n\n/**\n * Abstract base class for Workers to provide a default CORS policy.\n *\n * Implements the `CorsProvider` interface and provides a standard policy:\n * - Allows all origins (`*`) by default.\n * - Allows GET, OPTIONS, and HEAD methods.\n * - Allows the `Content-Type` header.\n * - Exposes no additional headers.\n * - Sets CORS preflight max-age to one week.\n *\n * Subclasses can override any of the methods to customize the CORS behavior.\n */\nexport abstract class CorsWorker extends BaseWorker implements CorsProvider {\n public getAllowOrigins(): string[] {\n return [\"*\"];\n }\n\n public allowAnyOrigin(): boolean {\n return this.getAllowOrigins().includes(\"*\");\n }\n\n public getAllowMethods(): Method[] {\n return [Method.GET, Method.OPTIONS, Method.HEAD];\n }\n\n public getAllowHeaders(): string[] {\n return [\"Content-Type\"];\n }\n\n public getExposeHeaders(): string[] {\n return [];\n }\n\n public getMaxAge(): number {\n return Time.Week;\n }\n\n public getOrigin(): string | null {\n return this.request.headers.get(\"Origin\");\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Method, normalizeUrl } from \"./common\";\nimport { withCorsHeaders, withoutCorsHeaders } from \"./cors\";\nimport { CorsWorker } from \"./cors-worker\";\n\n/**\n * Abstract base class for Workers that support caching of GET responses.\n *\n * Features:\n * - URL-based caching using `Request.url`.\n * - Removes per-request CORS headers before storing in cache.\n * - Dynamically applies correct CORS headers when retrieving cached responses.\n * - Only caches successful GET requests.\n */\nexport abstract class CacheWorker extends CorsWorker {\n /**\n * Returns the cache key for the current request.\n * By default, this is the normalized request URL.\n *\n * @returns A URL or RequestInfo to use as the cache key\n */\n protected getCacheKey(): URL | RequestInfo {\n return normalizeUrl(this.request.url);\n }\n\n /**\n * Retrieves a cached Response for the current request, if one exists.\n *\n * Behavior:\n * - Only GET requests are cached.\n * - If a cached response is found, CORS headers are applied dynamically\n * using `withCorsHeaders` before returning.\n * - Returns undefined if no cached response is found or if request is not GET.\n *\n * @param cacheName Optional name of the cache to use; defaults to `caches.default`.\n * @returns A Promise resolving to a Response with correct CORS headers, or undefined.\n */\n protected async getCachedResponse(cacheName?: string): Promise<Response | undefined> {\n if (this.request.method !== Method.GET) return;\n\n const cache = cacheName ? await caches.open(cacheName) : caches.default;\n\n const response = await cache.match(this.getCacheKey());\n return response ? withCorsHeaders(this, response) : undefined;\n }\n\n /**\n * Stores a Response in the cache for the current request.\n *\n * Behavior:\n * - Only caches successful GET responses (`response.ok === true`).\n * - Removes all CORS headers before storing using `withoutCorsHeaders`.\n * - Uses `ctx.waitUntil` to store asynchronously without blocking the worker.\n *\n * @param response The Response to cache\n * @param cacheName Optional name of the cache to use; defaults to `caches.default`.\n */\n protected async setCachedResponse(response: Response, cacheName?: string): Promise<void> {\n if (!response.ok) return;\n if (this.request.method !== Method.GET) return;\n\n const cache = cacheName ? await caches.open(cacheName) : caches.default;\n this.ctx?.waitUntil(cache.put(this.getCacheKey(), withoutCorsHeaders(response.clone())));\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getReasonPhrase, StatusCodes } from \"http-status-codes\";\nimport {\n CacheControl,\n getContentType,\n HttpHeader,\n mergeHeader,\n Method,\n MediaType,\n setHeader,\n} from \"./common\";\nimport { addCorsHeaders, CorsProvider } from \"./cors\";\n\nexport interface ErrorJson {\n status: number;\n error: string;\n details: string;\n}\n\nabstract class BaseResponse {\n public headers: Headers = new Headers();\n public body: BodyInit | null;\n public status: StatusCodes = StatusCodes.OK;\n public statusText?: string;\n public mediaType?: MediaType;\n\n constructor(content: BodyInit | null = null) {\n this.body = this.status === StatusCodes.NO_CONTENT ? null : content;\n }\n\n protected get responseInit(): ResponseInit {\n return {\n headers: this.headers,\n status: this.status,\n statusText: this.statusText ?? getReasonPhrase(this.status),\n };\n }\n\n public setHeader(key: string, value: string | string[]): void {\n setHeader(this.headers, key, value);\n }\n\n public mergeHeader(key: string, value: string | string[]): void {\n mergeHeader(this.headers, key, value);\n }\n\n public addContentType() {\n if (this.mediaType) {\n this.headers.set(HttpHeader.CONTENT_TYPE, getContentType(this.mediaType));\n }\n }\n}\n\nabstract class CorsResponse extends BaseResponse {\n constructor(public readonly cors: CorsProvider, content: BodyInit | null = null) {\n super(content);\n }\n\n protected addCorsHeaders(): void {\n addCorsHeaders(this.cors, this.headers);\n }\n}\n\nabstract class CacheResponse extends CorsResponse {\n constructor(cors: CorsProvider, body: BodyInit | null = null, public cache?: CacheControl) {\n super(cors, body);\n }\n\n protected addCacheHeader(): void {\n if (this.cache) {\n this.headers.set(HttpHeader.CACHE_CONTROL, CacheControl.stringify(this.cache));\n }\n }\n}\n\nexport abstract class WorkerResponse extends CacheResponse {\n public createResponse(): Response {\n this.addCorsHeaders();\n this.addCacheHeader();\n this.addSecurityHeaders();\n\n const body = this.status === StatusCodes.NO_CONTENT ? null : this.body;\n if (body) this.addContentType();\n return new Response(body, this.responseInit);\n }\n\n protected addSecurityHeaders(): void {\n this.setHeader(HttpHeader.X_CONTENT_TYPE_OPTIONS, HttpHeader.NOSNIFF);\n }\n}\n\nexport class ClonedResponse extends WorkerResponse {\n constructor(cors: CorsProvider, response: Response, cache?: CacheControl) {\n const clone = response.clone();\n super(cors, clone.body, cache);\n this.headers = new Headers(clone.headers);\n this.status = clone.status;\n this.statusText = clone.statusText;\n }\n}\n\nexport class SuccessResponse extends WorkerResponse {\n constructor(\n cors: CorsProvider,\n body: BodyInit | null = null,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(cors, body, cache);\n this.status = status;\n }\n}\n\nexport class JsonResponse extends SuccessResponse {\n constructor(\n cors: CorsProvider,\n json: unknown = {},\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(cors, JSON.stringify(json), cache, status);\n this.mediaType = MediaType.JSON;\n }\n}\n\nexport class HtmlResponse extends SuccessResponse {\n constructor(\n cors: CorsProvider,\n body: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(cors, body, cache, status);\n this.mediaType = MediaType.HTML;\n }\n}\n\nexport class TextResponse extends SuccessResponse {\n constructor(\n cors: CorsProvider,\n content: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(cors, content, cache, status);\n this.mediaType = MediaType.PLAIN_TEXT;\n }\n}\n\n/**\n * Removes the body from a GET response.\n */\nexport class Head extends WorkerResponse {\n constructor(cors: CorsProvider, get: Response) {\n super(cors);\n this.headers = new Headers(get.headers);\n }\n}\n\nexport class Options extends SuccessResponse {\n constructor(cors: CorsProvider) {\n super(cors, null, undefined, StatusCodes.NO_CONTENT);\n this.setHeader(\"Allow\", this.cors.getAllowMethods());\n }\n}\n\nexport class HttpError extends JsonResponse {\n constructor(cors: CorsProvider, status: StatusCodes, protected readonly details?: string) {\n const cache: CacheControl = {\n \"no-cache\": true,\n \"no-store\": true,\n \"must-revalidate\": true,\n \"max-age\": 0,\n };\n super(cors, undefined, cache, status);\n }\n\n public get json(): ErrorJson {\n return {\n status: this.status,\n error: getReasonPhrase(this.status),\n details: this.details ?? getReasonPhrase(this.status),\n };\n }\n\n public override createResponse(): Response {\n this.body = JSON.stringify(this.json);\n return super.createResponse();\n }\n}\n\nexport class BadRequest extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.BAD_REQUEST, details);\n }\n}\n\nexport class Unauthorized extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.UNAUTHORIZED, details);\n }\n}\n\nexport class Forbidden extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.FORBIDDEN, details);\n }\n}\n\nexport class NotFound extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.NOT_FOUND, details);\n }\n}\n\nexport class MethodNotAllowed extends HttpError {\n constructor(cors: CorsProvider, method: string) {\n super(cors, StatusCodes.METHOD_NOT_ALLOWED, `${method} method not allowed.`);\n this.setHeader(\"Allow\", this.cors.getAllowMethods());\n }\n\n public override get json(): ErrorJson & { allowed: Method[] } {\n return {\n ...super.json,\n allowed: this.cors.getAllowMethods(),\n };\n }\n}\n\nexport class InternalServerError extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.INTERNAL_SERVER_ERROR, details);\n }\n}\n\nexport class NotImplemented extends HttpError {\n constructor(cors: CorsProvider) {\n super(cors, StatusCodes.NOT_IMPLEMENTED);\n }\n}\n\nexport class ServiceUnavailable extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.SERVICE_UNAVAILABLE, details);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CacheWorker } from \"./cache-worker\";\nimport { isMethod, Method } from \"./common\";\nimport { CorsProvider } from \"./cors\";\nimport {\n Head,\n InternalServerError,\n MethodNotAllowed,\n NotImplemented,\n Options,\n WorkerResponse,\n} from \"./response\";\n\nexport abstract class BasicWorker extends CacheWorker {\n public async fetch(): Promise<Response> {\n if (!this.isAllowed(this.request.method)) {\n return this.getResponse(MethodNotAllowed, this.request.method);\n }\n\n try {\n return await this.dispatch();\n } catch (error) {\n return this.getResponse(InternalServerError, String(error));\n }\n }\n\n protected async dispatch(request: Request = this.request): Promise<Response> {\n const method = request.method as Method;\n const handler: Record<Method, () => Promise<Response>> = {\n GET: () => this.get(),\n PUT: () => this.put(),\n POST: () => this.post(),\n PATCH: () => this.patch(),\n DELETE: () => this.delete(),\n HEAD: () => this.head(),\n OPTIONS: () => this.options(),\n };\n return (handler[method] ?? (() => this.getResponse(MethodNotAllowed, method)))();\n }\n\n protected async get(): Promise<Response> {\n return this.getResponse(NotImplemented);\n }\n\n protected async put(): Promise<Response> {\n return this.getResponse(NotImplemented);\n }\n\n protected async post(): Promise<Response> {\n return this.getResponse(NotImplemented);\n }\n\n protected async patch(): Promise<Response> {\n return this.getResponse(NotImplemented);\n }\n\n protected async delete(): Promise<Response> {\n return this.getResponse(NotImplemented);\n }\n\n protected async options(): Promise<Response> {\n return this.getResponse(Options);\n }\n\n protected async head(): Promise<Response> {\n // Dispatch a new GET request created from the HEAD request\n // and return the GET response with the body removed.\n return this.getResponse(\n Head,\n await this.dispatch(new Request(this.request, { method: Method.GET }))\n );\n }\n\n protected async getResponse<\n T extends WorkerResponse,\n Ctor extends new (cors: CorsProvider, ...args: any[]) => T\n >(\n ResponseClass: Ctor,\n ...args: ConstructorParameters<Ctor> extends [CorsProvider, ...infer R] ? R : never\n ): Promise<Response> {\n const response = new ResponseClass(this, ...args).createResponse();\n this.setCachedResponse(response);\n return response;\n }\n\n public isAllowed(method: string): boolean {\n return isMethod(method) && this.getAllowMethods().includes(method);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Method } from \"./common\";\n\n/**\n * A callback function for a route.\n *\n * @param matches - Captured groups from the route RegExp, or the full match at index 0\n * @returns A Response object or a Promise that resolves to a Response\n */\nexport type RouteCallback = (...matches: string[]) => Response | Promise<Response>;\n\n/**\n * Tuple used to initialize a route.\n *\n * [HTTP method, path pattern (string or RegExp), callback function]\n */\nexport type RouteInit = [Method, RegExp | string, RouteCallback];\n\n/**\n * Represents a single route with a pattern and a callback.\n */\nexport class Route {\n public readonly pattern: RegExp;\n\n /**\n * @param pattern - A RegExp or string used to match the request path\n * @param callback - Function to handle requests matching the pattern\n */\n constructor(pattern: RegExp | string, public readonly callback: RouteCallback) {\n this.pattern = new RegExp(pattern);\n }\n}\n\n/**\n * A collection of routes grouped by HTTP method.\n *\n * Supports adding routes and retrieving the first matching route for a given method and URL.\n */\nexport class Routes {\n private readonly map = new Map<Method, Route[]>();\n\n /**\n * Adds a route to the collection under the given HTTP method.\n *\n * @param method - HTTP method (GET, POST, etc.)\n * @param route - Route instance to add\n * @returns The Routes instance (for chaining)\n */\n public add(method: Method, route: Route): this {\n const existing = this.map.get(method);\n if (existing) {\n existing.push(route);\n } else {\n this.map.set(method, [route]);\n }\n return this;\n }\n\n /**\n * Finds the first route that matches the given method and URL.\n *\n * @param method - HTTP method of the request\n * @param url - Full URL string of the request\n * @returns The first matching Route, or undefined if none match\n */\n public get(method: Method, url: string): Route | undefined {\n const routes = this.map.get(method);\n if (!routes) return undefined;\n\n const pathname = new URL(url).pathname;\n return routes.find(({ pattern }) => pattern.test(pathname));\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BasicWorker } from \"./basic-worker\";\nimport { Method } from \"./common\";\nimport { NotFound } from \"./response\";\nimport { Route, Routes, RouteInit, RouteCallback } from \"./routes\";\n\nexport abstract class RoutedWorker extends BasicWorker {\n private readonly routes: Routes = new Routes();\n\n protected initialize(routes: RouteInit[]) {\n routes.forEach(([method, pattern, callback]) => {\n this.add(method, pattern, callback);\n });\n }\n\n protected add(method: Method, pattern: RegExp | string, callback: RouteCallback) {\n this.routes.add(method, new Route(pattern, callback));\n return this;\n }\n\n protected async dispatch(request: Request = this.request): Promise<Response> {\n const route = this.routes.get(request.method as Method, request.url);\n if (!route) return super.dispatch(request);\n\n const match = new URL(request.url).pathname.match(route.pattern) ?? [];\n return route.callback.call(this, ...match);\n }\n\n protected override async get(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async put(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async post(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async patch(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async delete(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n}\n"],"mappings":"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","names":["HttpHeader","Method","MediaType","Cors","StatusCodes","StatusCodes"]}
|
|
1
|
+
{"version":3,"sources":["../src/common.ts","../src/cors.ts","../src/base-worker.ts","../src/cors-worker.ts","../src/cache-worker.ts","../src/response.ts","../src/basic-worker.ts","../src/routes.ts","../src/routed-worker.ts"],"sourcesContent":["/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport CacheLib from \"cache-control-parser\";\n\n/**\n * @see {@link https://github.com/etienne-martin/cache-control-parser | cache-control-parser}\n */\nexport type CacheControl = CacheLib.CacheControl;\nexport const CacheControl = {\n parse: CacheLib.parse,\n stringify: CacheLib.stringify,\n};\n\n/**\n * https://github.com/prettymuchbryce/http-status-codes\n */\nexport { StatusCodes } from \"http-status-codes\";\n\n/**\n * Standard HTTP header names and common values.\n */\nexport namespace HttpHeader {\n export const VARY = \"Vary\";\n export const CONTENT_TYPE = \"Content-Type\";\n export const CACHE_CONTROL = \"Cache-Control\";\n\n // Security Headers\n export const X_CONTENT_TYPE_OPTIONS = \"X-Content-Type-Options\"; // usually \"nosniff\"\n export const X_FRAME_OPTIONS = \"X-Frame-Options\"; // e.g. \"DENY\" or \"SAMEORIGIN\"\n export const STRICT_TRANSPORT_SECURITY = \"Strict-Transport-Security\"; // e.g. \"max-age=63072000; includeSubDomains; preload\"\n export const CONTENT_SECURITY_POLICY = \"Content-Security-Policy\"; // fine-grained script/style/image restrictions\n export const REFERRER_POLICY = \"Referrer-Policy\"; // e.g. \"no-referrer\", \"strict-origin-when-cross-origin\"\n export const PERMISSIONS_POLICY = \"Permissions-Policy\"; // formerly Feature-Policy, controls APIs like geolocation/camera\n\n // Values\n export const NOSNIFF = \"nosniff\";\n export const ORIGIN = \"Origin\";\n}\n\n/**\n * Time constants in seconds. Month is approximated as 30 days.\n */\nexport const Time = {\n Second: 1,\n Minute: 60,\n Hour: 3600, // 60 * 60\n Day: 86400, // 60 * 60 * 24\n Week: 604800, // 60 * 60 * 24 * 7\n Month: 2592000, // 60 * 60 * 24 * 30\n Year: 31536000, // 60 * 60 * 24 * 365\n} as const;\n\n/**\n * Standard HTTP request methods.\n */\nexport enum Method {\n GET = \"GET\",\n PUT = \"PUT\",\n POST = \"POST\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n HEAD = \"HEAD\",\n OPTIONS = \"OPTIONS\",\n}\nconst METHOD_SET: Set<string> = new Set(Object.values(Method));\n\n/**\n * Type guard that checks if a string is a valid HTTP method.\n *\n * @param value - The string to test.\n * @returns True if `value` is a recognized HTTP method.\n */\nexport function isMethod(value: string): value is Method {\n return METHOD_SET.has(value);\n}\n\n/**\n * Returns the proper Content-Type string for a given media type.\n * Appends `charset=utf-8` for text-based types that require it.\n *\n * @param type - The media type.\n * @returns A string suitable for the `Content-Type` header.\n */\nexport function getContentType(type: MediaType): string {\n if (ADD_CHARSET.has(type)) {\n return `${type}; charset=utf-8`;\n }\n return type;\n}\n\n/**\n * Common media types types used for HTTP headers.\n */\nexport enum MediaType {\n PLAIN_TEXT = \"text/plain\",\n HTML = \"text/html\",\n CSS = \"text/css\",\n CSV = \"text/csv\",\n XML = \"text/xml\",\n MARKDOWN = \"text/markdown\",\n RICH_TEXT = \"text/richtext\",\n JSON = \"application/json\",\n XML_APP = \"application/xml\",\n YAML = \"application/x-yaml\",\n FORM_URLENCODED = \"application/x-www-form-urlencoded\",\n NDJSON = \"application/x-ndjson\",\n MSGPACK = \"application/x-msgpack\",\n PROTOBUF = \"application/x-protobuf\",\n MULTIPART_FORM_DATA = \"multipart/form-data\",\n MULTIPART_MIXED = \"multipart/mixed\",\n MULTIPART_ALTERNATIVE = \"multipart/alternative\",\n MULTIPART_DIGEST = \"multipart/digest\",\n MULTIPART_RELATED = \"multipart/related\",\n MULTIPART_SIGNED = \"multipart/signed\",\n MULTIPART_ENCRYPTED = \"multipart/encrypted\",\n OCTET_STREAM = \"application/octet-stream\",\n PDF = \"application/pdf\",\n ZIP = \"application/zip\",\n GZIP = \"application/gzip\",\n MSWORD = \"application/msword\",\n DOCX = \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n EXCEL = \"application/vnd.ms-excel\",\n XLSX = \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n POWERPOINT = \"application/vnd.ms-powerpoint\",\n PPTX = \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n ICO = \"image/x-icon\",\n ICO_MS = \"image/vnd.microsoft.icon\",\n GIF = \"image/gif\",\n PNG = \"image/png\",\n JPEG = \"image/jpeg\",\n WEBP = \"image/webp\",\n SVG = \"image/svg+xml\",\n HEIF = \"image/heif\",\n AVIF = \"image/avif\",\n EVENT_STREAM = \"text/event-stream\",\n TAR = \"application/x-tar\",\n BZIP2 = \"application/x-bzip2\",\n}\n\n/**\n * A set of media types that require a `charset` parameter when setting\n * the `Content-Type` header.\n *\n * This includes common text-based media types such as HTML, CSS, JSON,\n * XML, CSV, Markdown, and others.\n */\nconst ADD_CHARSET: Set<MediaType> = new Set([\n MediaType.PLAIN_TEXT,\n MediaType.HTML,\n MediaType.CSS,\n MediaType.CSV,\n MediaType.MARKDOWN,\n MediaType.XML,\n MediaType.JSON,\n MediaType.XML_APP,\n MediaType.FORM_URLENCODED,\n MediaType.NDJSON,\n MediaType.RICH_TEXT,\n MediaType.SVG,\n]);\n\n/**\n * Sets a header on the given Headers object.\n *\n * - If `value` is an array, duplicates and empty strings are removed.\n * - If the resulting value array is empty, the header is deleted.\n * - Otherwise, values are joined with `\", \"` and set as the header value.\n *\n * @param headers - The Headers object to modify.\n * @param key - The header name to set.\n * @param value - The header value(s) to set. Can be a string or array of strings.\n */\nexport function setHeader(headers: Headers, key: string, value: string | string[]): void {\n const raw = Array.isArray(value) ? value : [value];\n const values = Array.from(new Set(raw.map((v) => v.trim()))).filter((v) => v.length);\n\n if (!values.length) {\n headers.delete(key);\n return;\n }\n\n headers.set(key, values.join(\", \"));\n}\n\n/**\n * Merges new value(s) into an existing header on the given Headers object.\n *\n * - Preserves any existing values and adds new ones.\n * - Removes duplicates and trims all values.\n * - If the header does not exist, it is created.\n *\n * @param headers - The Headers object to modify.\n * @param key - The header name to merge into.\n * @param value - The new header value(s) to add. Can be a string or array of strings.\n */\nexport function mergeHeader(headers: Headers, key: string, value: string | string[]): void {\n const values = Array.isArray(value) ? value : [value];\n if (!values.length) return;\n\n const existing = headers.get(key);\n if (existing) {\n const merged = existing.split(\",\").map((v) => v.trim());\n values.forEach((v) => merged.push(v.trim()));\n setHeader(headers, key, merged);\n } else {\n setHeader(headers, key, values);\n }\n}\n\n/**\n * Normalizes a URL string for use as a consistent cache key.\n *\n * - Sorts query parameters alphabetically so `?b=2&a=1` and `?a=1&b=2` are treated the same.\n * - Strips fragment identifiers (`#...`) since they are not sent in HTTP requests.\n * - Leaves protocol, host, path, and query values intact.\n *\n * @param url The original URL string to normalize.\n * @returns A normalized URL string suitable for hashing or direct cache key use.\n */\nexport function normalizeUrl(url: string): URL {\n const u = new URL(url);\n\n const params = [...u.searchParams.entries()];\n params.sort(([a], [b]) => a.localeCompare(b));\n\n u.search = params\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join(\"&\");\n u.hash = \"\";\n\n return u;\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { HttpHeader, mergeHeader, Method, setHeader } from \"./common\";\n\n/**\n * Provides information about the CORS policy for the current request.\n */\nexport interface CorsProvider {\n /** Returns the origin of the request, or null if none is provided. */\n getOrigin(): string | null;\n\n /** Returns a list of allowed origins. */\n getAllowOrigins(): string[];\n\n /** Returns true if any origin is allowed (`*`). */\n allowAnyOrigin(): boolean;\n\n /** Returns the HTTP methods allowed by CORS. */\n getAllowMethods(): Method[];\n\n /** Returns the HTTP headers allowed by CORS. */\n getAllowHeaders(): string[];\n\n /** Returns the HTTP headers that should be exposed to the browser. */\n getExposeHeaders(): string[];\n\n /** Returns the max age (in seconds) for CORS preflight caching. */\n getMaxAge(): number;\n}\n\n/**\n * Constants for common CORS headers.\n */\nexport namespace Cors {\n export const ALLOW_ORIGIN = \"Access-Control-Allow-Origin\";\n export const ALLOW_CREDENTIALS = \"Access-Control-Allow-Credentials\";\n export const EXPOSE_HEADERS = \"Access-Control-Expose-Headers\";\n export const ALLOW_HEADERS = \"Access-Control-Allow-Headers\";\n export const ALLOW_METHODS = \"Access-Control-Allow-Methods\";\n export const MAX_AGE = \"Access-Control-Max-Age\";\n export const ALLOW_ALL_ORIGINS = \"*\";\n}\n\n/**\n * Adds or updates CORS headers on a Headers object according to the provided policy.\n *\n * Behavior:\n * - Removes any existing CORS headers to avoid stale values.\n * - If the request has no origin, the function exits early.\n * - If wildcard `*` is allowed, sets Access-Control-Allow-Origin to `*`.\n * - If the origin is explicitly allowed, sets the correct headers including credentials and Vary: Origin.\n * - Optional headers (Expose-Headers, Allow-Headers, Allow-Methods, Max-Age) are always applied.\n *\n * @param cors The CorsProvider instance that determines allowed origins and headers\n * @param headers The Headers object to update\n */\nexport function addCorsHeaders(cors: CorsProvider, headers: Headers): void {\n deleteCorsHeaders(headers);\n\n const origin = cors.getOrigin();\n if (!origin) return;\n\n if (cors.allowAnyOrigin()) {\n setHeader(headers, Cors.ALLOW_ORIGIN, Cors.ALLOW_ALL_ORIGINS);\n } else if (cors.getAllowOrigins().includes(origin)) {\n setHeader(headers, Cors.ALLOW_ORIGIN, origin);\n setHeader(headers, Cors.ALLOW_CREDENTIALS, \"true\");\n mergeHeader(headers, HttpHeader.VARY, HttpHeader.ORIGIN);\n }\n\n // Optional headers always applied\n mergeHeader(headers, Cors.EXPOSE_HEADERS, cors.getExposeHeaders());\n setHeader(headers, Cors.ALLOW_HEADERS, cors.getAllowHeaders());\n setHeader(headers, Cors.ALLOW_METHODS, cors.getAllowMethods());\n setHeader(headers, Cors.MAX_AGE, String(cors.getMaxAge()));\n}\n\n/**\n * Deletes all standard CORS headers from the given Headers object.\n * Useful for cleaning cached responses or resetting headers before reapplying CORS.\n *\n * @param headers The Headers object to clean\n */\nfunction deleteCorsHeaders(headers: Headers) {\n headers.delete(Cors.ALLOW_ORIGIN);\n headers.delete(Cors.ALLOW_CREDENTIALS);\n headers.delete(Cors.EXPOSE_HEADERS);\n headers.delete(Cors.ALLOW_METHODS);\n headers.delete(Cors.MAX_AGE);\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Worker } from \"./worker\";\n\n/**\n * A type-safe Cloudflare Worker handler where `fetch` is required.\n *\n * Extends `ExportedHandler` but guarantees that the `fetch` method exists\n * and has the correct signature for Cloudflare Worker invocation.\n *\n * @template E - The type of environment bindings passed to the worker. Defaults to `Env`.\n */\ninterface FetchHandler<E = Env> extends ExportedHandler<E> {\n /**\n * Handles an incoming request and produces a response.\n *\n * @param request - The incoming `Request` object.\n * @param env - Environment bindings (e.g., KV namespaces, secrets, Durable Objects).\n * @param ctx - Optional execution context for background tasks (`waitUntil`).\n * @returns A `Promise` that resolves to the response.\n */\n fetch: (request: Request, env: E, ctx: ExecutionContext) => Promise<Response>;\n}\n\n/**\n * Provides the foundational structure for handling requests, environment bindings,\n * and the worker execution context. Subclasses are expected to implement the\n * `fetch` method to handle the request and return a Response.\n *\n * Features:\n * - Holds the current `Request` object (`request` getter).\n * - Provides access to environment bindings (`env` getter).\n * - Provides access to the worker execution context (`ctx` getter), if available.\n * - Subclasses must implement `fetch()` to process the request.\n */\nexport abstract class BaseWorker implements Worker {\n constructor(\n private readonly _request: Request,\n private readonly _env: Env = {},\n private readonly _ctx?: ExecutionContext\n ) {}\n\n /** The Request object associated with this worker invocation */\n protected get request(): Request {\n return this._request;\n }\n\n /** Environment bindings (e.g., KV, secrets, or other globals) */\n protected get env(): Env {\n return this._env;\n }\n\n /** Optional execution context for background tasks or `waitUntil` */\n protected get ctx(): ExecutionContext | undefined {\n return this._ctx;\n }\n\n /**\n * Process the request and produce a Response.\n * Subclasses must implement this method.\n *\n * @returns A Promise resolving to the Response for the request\n */\n public abstract fetch(): Promise<Response>;\n\n /**\n * Ignite your `Worker` implementation into a Cloudflare-compatible handler.\n *\n * @returns A `FetchHandler` that launches a new worker instance for each request.\n *\n * @example\n * ```ts\n * export default MyWorker.ignite();\n * ```\n */\n public static ignite<T extends new (...args: any) => BaseWorker>(this: T): FetchHandler {\n return {\n fetch: (req: Request, env: Env, ctx: ExecutionContext) =>\n new this(req, env, ctx).fetch(),\n };\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BaseWorker } from \"./base-worker\";\nimport { Method, Time } from \"./common\";\nimport { CorsProvider } from \"./cors\";\n\n/**\n * Abstract base class for Workers to provide a default CORS policy.\n *\n * Implements the `CorsProvider` interface and provides a standard policy:\n * - Allows all origins (`*`) by default.\n * - Allows GET, OPTIONS, and HEAD methods.\n * - Allows the `Content-Type` header.\n * - Exposes no additional headers.\n * - Sets CORS preflight max-age to one week.\n *\n * Subclasses can override any of the methods to customize the CORS behavior.\n */\nexport abstract class CorsWorker extends BaseWorker implements CorsProvider {\n public getAllowOrigins(): string[] {\n return [\"*\"];\n }\n\n public allowAnyOrigin(): boolean {\n return this.getAllowOrigins().includes(\"*\");\n }\n\n public getAllowMethods(): Method[] {\n return [Method.GET, Method.OPTIONS, Method.HEAD];\n }\n\n public getAllowHeaders(): string[] {\n return [\"Content-Type\"];\n }\n\n public getExposeHeaders(): string[] {\n return [];\n }\n\n public getMaxAge(): number {\n return Time.Week;\n }\n\n public getOrigin(): string | null {\n return this.request.headers.get(\"Origin\");\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Method, normalizeUrl } from \"./common\";\nimport { addCorsHeaders, Cors } from \"./cors\";\nimport { CorsWorker } from \"./cors-worker\";\n\n/**\n * Abstract worker class that adds caching support for GET requests.\n *\n * Behavior:\n * - Caches successful GET responses (`response.ok === true`) in the selected cache.\n * - Strips CORS headers from cached responses; all other origin headers are preserved.\n * - Dynamically adds CORS headers to cached responses when returned to the client.\n *\n * Subclasses should override `getCacheKey()` to customize cache key generation if needed.\n */\nexport abstract class CacheWorker extends CorsWorker {\n /**\n * Returns the cache key for the current request.\n *\n * Behavior:\n * - By default, returns the normalized request URL.\n * - Query parameters are normalized so that the order does not affect the cache key.\n * For example, `?a=1&b=2` and `?b=2&a=1` produce the same cache key.\n *\n * Subclasses may override this method to implement custom cache key strategies.\n *\n * @returns {URL | RequestInfo} The URL or RequestInfo used as the cache key.\n */\n protected getCacheKey(): URL | RequestInfo {\n return normalizeUrl(this.request.url);\n }\n\n /**\n * Retrieves a cached Response for the current request, if one exists.\n *\n * Behavior:\n * - Only GET requests are considered.\n * - Returns a new Response with dynamic CORS headers applied via `addCacheHeaders`.\n * - Returns `undefined` if no cached response is found.\n * - Cloudflare dynamic headers (`CF-Cache-Status`, `Age`, `Connection`, etc.) will\n * always be present on the returned response, even though they are not stored in the cache.\n *\n * @param {string} [cacheName] Optional named cache; defaults to `caches.default`.\n * @returns {Promise<Response | undefined>} A Response with CORS headers, or undefined.\n * @see {@link setCachedResponse}\n * @see {@link getCacheKey}\n */\n protected async getCachedResponse(cacheName?: string): Promise<Response | undefined> {\n if (this.request.method !== Method.GET) return;\n\n const cache = cacheName ? await caches.open(cacheName) : caches.default;\n const response = await cache.match(this.getCacheKey());\n return response ? this.addCacheHeaders(response) : undefined;\n }\n\n /**\n * Stores a Response in the cache for the current request.\n *\n * Behavior:\n * - Only caches successful GET responses (`response.ok === true`).\n * - Strips headers via `removeCacheHeaders` before storing.\n * - Uses `ctx.waitUntil` to perform caching asynchronously without blocking the response.\n * - All other origin headers (e.g., Cache-Control, Expires) are preserved.\n *\n * @param {Response} response The Response to cache.\n * @param {string} [cacheName] Optional named cache; defaults to `caches.default`.\n * @see {@link getCachedResponse}\n * @see {@link getCacheKey}\n */\n protected async setCachedResponse(response: Response, cacheName?: string): Promise<void> {\n if (!response.ok) return;\n if (this.request.method !== Method.GET) return;\n\n const cache = cacheName ? await caches.open(cacheName) : caches.default;\n this.ctx?.waitUntil(\n cache.put(this.getCacheKey(), this.removeCacheHeaders(response.clone()))\n );\n }\n\n /**\n * Adds headers to a cached response.\n *\n * @param {Response} cached The cached Response.\n * @returns {Response} A new Response with dynamic CORS headers applied.\n * @see {@link removeCacheHeaders}\n */\n private addCacheHeaders(cached: Response): Response {\n const headers = new Headers(cached.headers);\n addCorsHeaders(this, headers);\n\n return new Response(cached.body, {\n status: cached.status,\n statusText: cached.statusText,\n headers,\n });\n }\n\n /**\n * Removes headers that should not be stored in the cache (currently only CORS headers).\n *\n * @param {Response} response The Response to clean before caching.\n * @returns {Response} A new Response with excluded headers removed.\n * @see {@link addCacheHeaders}\n */\n private removeCacheHeaders(response: Response): Response {\n const excludeSet = new Set(this.excludeCacheHeaders().map((h) => h.toLowerCase()));\n const headers = new Headers();\n\n for (const [key, value] of response.headers) {\n if (!excludeSet.has(key)) {\n headers.set(key, value);\n }\n }\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n\n /**\n * Returns the list of headers to exclude from the cached response.\n * By default, excludes only dynamic CORS headers.\n *\n * @returns {string[]} Array of header names to exclude.\n * @see {@link removeCacheHeaders}\n */\n protected excludeCacheHeaders(): string[] {\n return [\n Cors.ALLOW_ORIGIN,\n Cors.ALLOW_CREDENTIALS,\n Cors.EXPOSE_HEADERS,\n Cors.ALLOW_METHODS,\n Cors.MAX_AGE,\n ];\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getReasonPhrase, StatusCodes } from \"http-status-codes\";\nimport {\n CacheControl,\n getContentType,\n HttpHeader,\n mergeHeader,\n Method,\n MediaType,\n setHeader,\n} from \"./common\";\nimport { addCorsHeaders, CorsProvider } from \"./cors\";\n\nexport interface ErrorJson {\n status: number;\n error: string;\n details: string;\n}\n\nabstract class BaseResponse {\n public headers: Headers = new Headers();\n public body: BodyInit | null;\n public status: StatusCodes = StatusCodes.OK;\n public statusText?: string;\n public mediaType?: MediaType;\n\n constructor(content: BodyInit | null = null) {\n this.body = this.status === StatusCodes.NO_CONTENT ? null : content;\n }\n\n protected get responseInit(): ResponseInit {\n return {\n headers: this.headers,\n status: this.status,\n statusText: this.statusText ?? getReasonPhrase(this.status),\n };\n }\n\n public setHeader(key: string, value: string | string[]): void {\n setHeader(this.headers, key, value);\n }\n\n public mergeHeader(key: string, value: string | string[]): void {\n mergeHeader(this.headers, key, value);\n }\n\n public addContentType() {\n if (this.mediaType) {\n this.headers.set(HttpHeader.CONTENT_TYPE, getContentType(this.mediaType));\n }\n }\n}\n\nabstract class CorsResponse extends BaseResponse {\n constructor(public readonly cors: CorsProvider, content: BodyInit | null = null) {\n super(content);\n }\n\n protected addCorsHeaders(): void {\n addCorsHeaders(this.cors, this.headers);\n }\n}\n\nabstract class CacheResponse extends CorsResponse {\n constructor(cors: CorsProvider, body: BodyInit | null = null, public cache?: CacheControl) {\n super(cors, body);\n }\n\n protected addCacheHeaders(): void {\n if (this.cache) {\n this.headers.set(HttpHeader.CACHE_CONTROL, CacheControl.stringify(this.cache));\n }\n }\n}\n\nexport abstract class WorkerResponse extends CacheResponse {\n public createResponse(): Response {\n this.addCorsHeaders();\n this.addCacheHeaders();\n this.addSecurityHeaders();\n\n const body = this.status === StatusCodes.NO_CONTENT ? null : this.body;\n if (body) this.addContentType();\n return new Response(body, this.responseInit);\n }\n\n protected addSecurityHeaders(): void {\n this.setHeader(HttpHeader.X_CONTENT_TYPE_OPTIONS, HttpHeader.NOSNIFF);\n }\n}\n\nexport class ClonedResponse extends WorkerResponse {\n constructor(cors: CorsProvider, response: Response, cache?: CacheControl) {\n const clone = response.clone();\n super(cors, clone.body, cache);\n this.headers = new Headers(clone.headers);\n this.status = clone.status;\n this.statusText = clone.statusText;\n }\n}\n\nexport class SuccessResponse extends WorkerResponse {\n constructor(\n cors: CorsProvider,\n body: BodyInit | null = null,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(cors, body, cache);\n this.status = status;\n }\n}\n\nexport class JsonResponse extends SuccessResponse {\n constructor(\n cors: CorsProvider,\n json: unknown = {},\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(cors, JSON.stringify(json), cache, status);\n this.mediaType = MediaType.JSON;\n }\n}\n\nexport class HtmlResponse extends SuccessResponse {\n constructor(\n cors: CorsProvider,\n body: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(cors, body, cache, status);\n this.mediaType = MediaType.HTML;\n }\n}\n\nexport class TextResponse extends SuccessResponse {\n constructor(\n cors: CorsProvider,\n content: string,\n cache?: CacheControl,\n status: StatusCodes = StatusCodes.OK\n ) {\n super(cors, content, cache, status);\n this.mediaType = MediaType.PLAIN_TEXT;\n }\n}\n\n/**\n * Removes the body from a GET response.\n */\nexport class Head extends WorkerResponse {\n constructor(cors: CorsProvider, get: Response) {\n super(cors);\n this.headers = new Headers(get.headers);\n }\n}\n\nexport class Options extends SuccessResponse {\n constructor(cors: CorsProvider) {\n super(cors, null, undefined, StatusCodes.NO_CONTENT);\n this.setHeader(\"Allow\", this.cors.getAllowMethods());\n }\n}\n\nexport class HttpError extends JsonResponse {\n constructor(cors: CorsProvider, status: StatusCodes, protected readonly details?: string) {\n const cache: CacheControl = {\n \"no-cache\": true,\n \"no-store\": true,\n \"must-revalidate\": true,\n \"max-age\": 0,\n };\n super(cors, undefined, cache, status);\n }\n\n public get json(): ErrorJson {\n return {\n status: this.status,\n error: getReasonPhrase(this.status),\n details: this.details ?? getReasonPhrase(this.status),\n };\n }\n\n public override createResponse(): Response {\n this.body = JSON.stringify(this.json);\n return super.createResponse();\n }\n}\n\nexport class BadRequest extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.BAD_REQUEST, details);\n }\n}\n\nexport class Unauthorized extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.UNAUTHORIZED, details);\n }\n}\n\nexport class Forbidden extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.FORBIDDEN, details);\n }\n}\n\nexport class NotFound extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.NOT_FOUND, details);\n }\n}\n\nexport class MethodNotAllowed extends HttpError {\n constructor(cors: CorsProvider, method: string) {\n super(cors, StatusCodes.METHOD_NOT_ALLOWED, `${method} method not allowed.`);\n this.setHeader(\"Allow\", this.cors.getAllowMethods());\n }\n\n public override get json(): ErrorJson & { allowed: Method[] } {\n return {\n ...super.json,\n allowed: this.cors.getAllowMethods(),\n };\n }\n}\n\nexport class InternalServerError extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.INTERNAL_SERVER_ERROR, details);\n }\n}\n\nexport class NotImplemented extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.NOT_IMPLEMENTED, details);\n }\n}\n\nexport class MethodNotImplemented extends NotImplemented {\n constructor(cors: CorsProvider, method: Method) {\n super(cors, `${method} method not implemented.`);\n }\n}\n\nexport class ServiceUnavailable extends HttpError {\n constructor(cors: CorsProvider, details?: string) {\n super(cors, StatusCodes.SERVICE_UNAVAILABLE, details);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CacheWorker } from \"./cache-worker\";\nimport { isMethod, Method } from \"./common\";\nimport { CorsProvider } from \"./cors\";\nimport {\n Head,\n InternalServerError,\n MethodNotAllowed,\n MethodNotImplemented,\n Options,\n WorkerResponse,\n} from \"./response\";\n\nexport abstract class BasicWorker extends CacheWorker {\n public async fetch(): Promise<Response> {\n if (!this.isAllowed(this.request.method)) {\n return this.getResponse(MethodNotAllowed, this.request.method);\n }\n\n try {\n return await this.dispatch();\n } catch (error) {\n return this.getResponse(InternalServerError, String(error));\n }\n }\n\n protected async dispatch(request: Request = this.request): Promise<Response> {\n const method = request.method as Method;\n const handler: Record<Method, () => Promise<Response>> = {\n GET: () => this.get(),\n PUT: () => this.put(),\n POST: () => this.post(),\n PATCH: () => this.patch(),\n DELETE: () => this.delete(),\n HEAD: () => this.head(),\n OPTIONS: () => this.options(),\n };\n return (handler[method] ?? (() => this.getResponse(MethodNotAllowed, method)))();\n }\n\n protected async get(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.GET);\n }\n\n protected async put(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.PUT);\n }\n\n protected async post(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.POST);\n }\n\n protected async patch(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.PATCH);\n }\n\n protected async delete(): Promise<Response> {\n return this.getResponse(MethodNotImplemented, Method.DELETE);\n }\n\n protected async options(): Promise<Response> {\n return this.getResponse(Options);\n }\n\n protected async head(): Promise<Response> {\n // Dispatch a new GET request created from the HEAD request\n // and return the GET response with the body removed.\n return this.getResponse(\n Head,\n await this.dispatch(new Request(this.request, { method: Method.GET }))\n );\n }\n\n protected async getResponse<\n T extends WorkerResponse,\n Ctor extends new (cors: CorsProvider, ...args: any[]) => T\n >(\n ResponseClass: Ctor,\n ...args: ConstructorParameters<Ctor> extends [CorsProvider, ...infer R] ? R : never\n ): Promise<Response> {\n const response = new ResponseClass(this, ...args).createResponse();\n this.setCachedResponse(response);\n return response;\n }\n\n public isAllowed(method: string): boolean {\n return isMethod(method) && this.getAllowMethods().includes(method);\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Method } from \"./common\";\n\n/**\n * A callback function for a route.\n *\n * @param matches - Captured groups from the route RegExp, or the full match at index 0\n * @returns A Response object or a Promise that resolves to a Response\n */\nexport type RouteCallback = (...matches: string[]) => Response | Promise<Response>;\n\n/**\n * Tuple used to initialize a route.\n *\n * [HTTP method, path pattern (string or RegExp), callback function]\n */\nexport type RouteInit = [Method, RegExp | string, RouteCallback];\n\n/**\n * Represents a single route with a pattern and a callback.\n */\nexport class Route {\n public readonly pattern: RegExp;\n\n /**\n * @param pattern - A RegExp or string used to match the request path\n * @param callback - Function to handle requests matching the pattern\n */\n constructor(pattern: RegExp | string, public readonly callback: RouteCallback) {\n this.pattern = new RegExp(pattern);\n }\n}\n\n/**\n * A collection of routes grouped by HTTP method.\n *\n * Supports adding routes and retrieving the first matching route for a given method and URL.\n */\nexport class Routes {\n private readonly map = new Map<Method, Route[]>();\n\n /**\n * Adds a route to the collection under the given HTTP method.\n *\n * @param method - HTTP method (GET, POST, etc.)\n * @param route - Route instance to add\n * @returns The Routes instance (for chaining)\n */\n public add(method: Method, route: Route): this {\n const existing = this.map.get(method);\n if (existing) {\n existing.push(route);\n } else {\n this.map.set(method, [route]);\n }\n return this;\n }\n\n /**\n * Finds the first route that matches the given method and URL.\n *\n * @param method - HTTP method of the request\n * @param url - Full URL string of the request\n * @returns The first matching Route, or undefined if none match\n */\n public get(method: Method, url: string): Route | undefined {\n const routes = this.map.get(method);\n if (!routes) return undefined;\n\n const pathname = new URL(url).pathname;\n return routes.find(({ pattern }) => pattern.test(pathname));\n }\n}\n","/*\n * Copyright (C) 2025 Ty Busby\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BasicWorker } from \"./basic-worker\";\nimport { Method } from \"./common\";\nimport { NotFound } from \"./response\";\nimport { Route, Routes, RouteInit, RouteCallback } from \"./routes\";\n\nexport abstract class RoutedWorker extends BasicWorker {\n private readonly routes: Routes = new Routes();\n\n protected initialize(routes: RouteInit[]) {\n routes.forEach(([method, pattern, callback]) => {\n this.add(method, pattern, callback);\n });\n }\n\n protected add(method: Method, pattern: RegExp | string, callback: RouteCallback) {\n this.routes.add(method, new Route(pattern, callback));\n return this;\n }\n\n protected async dispatch(request: Request = this.request): Promise<Response> {\n const route = this.routes.get(request.method as Method, request.url);\n if (!route) return super.dispatch(request);\n\n const match = new URL(request.url).pathname.match(route.pattern) ?? [];\n return route.callback.call(this, ...match);\n }\n\n protected override async get(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async put(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async post(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async patch(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n\n protected override async delete(): Promise<Response> {\n return this.getResponse(NotFound);\n }\n}\n"],"mappings":"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","names":["HttpHeader","Method","MediaType","Cors","StatusCodes","StatusCodes"]}
|