@adonix.org/cloud-spark 0.0.160 → 0.0.162

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.js CHANGED
@@ -1,1452 +1,2 @@
1
- // src/constants/cache.ts
2
- import CacheLib from "cache-control-parser";
3
- var CacheControl = {
4
- parse: CacheLib.parse,
5
- stringify: CacheLib.stringify,
6
- /** A CacheControl directive that disables all caching. */
7
- DISABLE: Object.freeze({
8
- "no-cache": true,
9
- "no-store": true,
10
- "must-revalidate": true,
11
- "max-age": 0
12
- })
13
- };
14
-
15
- // src/constants/http.ts
16
- import { StatusCodes } from "http-status-codes";
17
- var HttpHeader;
18
- ((HttpHeader2) => {
19
- HttpHeader2.ALLOW = "Allow";
20
- HttpHeader2.ACCEPT_ENCODING = "Accept-Encoding";
21
- HttpHeader2.ORIGIN = "Origin";
22
- HttpHeader2.CONTENT_TYPE = "Content-Type";
23
- HttpHeader2.CACHE_CONTROL = "Cache-Control";
24
- HttpHeader2.USER_AGENT = "User-Agent";
25
- HttpHeader2.VARY = "Vary";
26
- HttpHeader2.CONTENT_SECURITY_POLICY = "Content-Security-Policy";
27
- HttpHeader2.PERMISSIONS_POLICY = "Permissions-Policy";
28
- HttpHeader2.STRICT_TRANSPORT_SECURITY = "Strict-Transport-Security";
29
- HttpHeader2.REFERRER_POLICY = "Referrer-Policy";
30
- HttpHeader2.X_CONTENT_TYPE_OPTIONS = "X-Content-Type-Options";
31
- HttpHeader2.X_FRAME_OPTIONS = "X-Frame-Options";
32
- HttpHeader2.ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
33
- HttpHeader2.ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
34
- HttpHeader2.ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
35
- HttpHeader2.ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
36
- HttpHeader2.ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
37
- HttpHeader2.ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
38
- HttpHeader2.ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";
39
- HttpHeader2.SEC_WEBSOCKET_VERSION = "Sec-WebSocket-Version";
40
- HttpHeader2.CONNECTION = "Connection";
41
- HttpHeader2.UPGRADE = "Upgrade";
42
- })(HttpHeader || (HttpHeader = {}));
43
- var Method = /* @__PURE__ */ ((Method4) => {
44
- Method4["GET"] = "GET";
45
- Method4["PUT"] = "PUT";
46
- Method4["HEAD"] = "HEAD";
47
- Method4["POST"] = "POST";
48
- Method4["PATCH"] = "PATCH";
49
- Method4["DELETE"] = "DELETE";
50
- Method4["OPTIONS"] = "OPTIONS";
51
- return Method4;
52
- })(Method || {});
53
- var { GET, PUT, HEAD, POST, PATCH, DELETE, OPTIONS } = Method;
54
-
55
- // src/constants/media-types.ts
56
- var MediaType = /* @__PURE__ */ ((MediaType2) => {
57
- MediaType2["PLAIN_TEXT"] = "text/plain";
58
- MediaType2["HTML"] = "text/html";
59
- MediaType2["CSS"] = "text/css";
60
- MediaType2["CSV"] = "text/csv";
61
- MediaType2["XML"] = "text/xml";
62
- MediaType2["MARKDOWN"] = "text/markdown";
63
- MediaType2["RICH_TEXT"] = "text/richtext";
64
- MediaType2["JSON"] = "application/json";
65
- MediaType2["XML_APP"] = "application/xml";
66
- MediaType2["YAML"] = "application/x-yaml";
67
- MediaType2["FORM_URLENCODED"] = "application/x-www-form-urlencoded";
68
- MediaType2["NDJSON"] = "application/x-ndjson";
69
- MediaType2["MSGPACK"] = "application/x-msgpack";
70
- MediaType2["PROTOBUF"] = "application/x-protobuf";
71
- MediaType2["MULTIPART_FORM_DATA"] = "multipart/form-data";
72
- MediaType2["MULTIPART_MIXED"] = "multipart/mixed";
73
- MediaType2["MULTIPART_ALTERNATIVE"] = "multipart/alternative";
74
- MediaType2["MULTIPART_DIGEST"] = "multipart/digest";
75
- MediaType2["MULTIPART_RELATED"] = "multipart/related";
76
- MediaType2["MULTIPART_SIGNED"] = "multipart/signed";
77
- MediaType2["MULTIPART_ENCRYPTED"] = "multipart/encrypted";
78
- MediaType2["OCTET_STREAM"] = "application/octet-stream";
79
- MediaType2["PDF"] = "application/pdf";
80
- MediaType2["ZIP"] = "application/zip";
81
- MediaType2["GZIP"] = "application/gzip";
82
- MediaType2["MSWORD"] = "application/msword";
83
- MediaType2["DOCX"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
84
- MediaType2["EXCEL"] = "application/vnd.ms-excel";
85
- MediaType2["XLSX"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
86
- MediaType2["POWERPOINT"] = "application/vnd.ms-powerpoint";
87
- MediaType2["PPTX"] = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
88
- MediaType2["ICO"] = "image/x-icon";
89
- MediaType2["ICO_MS"] = "image/vnd.microsoft.icon";
90
- MediaType2["GIF"] = "image/gif";
91
- MediaType2["PNG"] = "image/png";
92
- MediaType2["JPEG"] = "image/jpeg";
93
- MediaType2["WEBP"] = "image/webp";
94
- MediaType2["SVG"] = "image/svg+xml";
95
- MediaType2["HEIF"] = "image/heif";
96
- MediaType2["AVIF"] = "image/avif";
97
- MediaType2["EVENT_STREAM"] = "text/event-stream";
98
- MediaType2["TAR"] = "application/x-tar";
99
- MediaType2["BZIP2"] = "application/x-bzip2";
100
- return MediaType2;
101
- })(MediaType || {});
102
-
103
- // src/constants/time.ts
104
- var Time = {
105
- Second: 1,
106
- Minute: 60,
107
- Hour: 3600,
108
- // 60 * 60
109
- Day: 86400,
110
- // 60 * 60 * 24
111
- Week: 604800,
112
- // 60 * 60 * 24 * 7
113
- Month: 2592e3,
114
- // 60 * 60 * 24 * 30
115
- Year: 31536e3
116
- // 60 * 60 * 24 * 365
117
- };
118
-
119
- // src/constants/websocket.ts
120
- var WS_UPGRADE = "upgrade";
121
- var WS_WEBSOCKET = "websocket";
122
- var WS_VERSION = "13";
123
- var WS_MAX_CLOSE_CODE = 4999;
124
- var WS_MAX_REASON_CHARS = 123;
125
- var CloseCode = {
126
- NORMAL: 1e3,
127
- GOING_AWAY: 1001,
128
- PROTOCOL_ERROR: 1002,
129
- UNSUPPORTED_DATA: 1003,
130
- NO_STATUS: 1005,
131
- ABNORMAL: 1006,
132
- INVALID_PAYLOAD: 1007,
133
- POLICY_VIOLATION: 1008,
134
- MESSAGE_TOO_BIG: 1009,
135
- MISSING_EXTENSION: 1010,
136
- INTERNAL_ERROR: 1011,
137
- TLS_HANDSHAKE: 1015
138
- };
139
- var WS_RESERVED_CODES = /* @__PURE__ */ new Set([
140
- CloseCode.NO_STATUS,
141
- CloseCode.ABNORMAL,
142
- CloseCode.TLS_HANDSHAKE
143
- ]);
144
-
145
- // src/guards/basic.ts
146
- function isStringArray(value) {
147
- return Array.isArray(value) && value.every((item) => typeof item === "string");
148
- }
149
- function isString(value) {
150
- return typeof value === "string";
151
- }
152
- function isFunction(value) {
153
- return typeof value === "function";
154
- }
155
- function isNumber(value) {
156
- return typeof value === "number" && !Number.isNaN(value);
157
- }
158
- function isBoolean(value) {
159
- return typeof value === "boolean";
160
- }
161
-
162
- // src/guards/methods.ts
163
- var METHOD_SET = new Set(Object.values(Method));
164
- function isMethod(value) {
165
- return isString(value) && METHOD_SET.has(value);
166
- }
167
- function isMethodArray(value) {
168
- return Array.isArray(value) && value.every(isMethod);
169
- }
170
- function assertMethods(value) {
171
- if (!isMethodArray(value)) {
172
- const desc = Array.isArray(value) ? JSON.stringify(value) : String(value);
173
- throw new TypeError(`Invalid method array: ${desc}`);
174
- }
175
- }
176
-
177
- // src/middleware/middleware.ts
178
- var Middleware = class {
179
- };
180
-
181
- // src/guards/cache.ts
182
- function assertCacheName(value) {
183
- if (value === void 0) return;
184
- if (!isString(value)) {
185
- throw new TypeError("Cache name must be a string.");
186
- }
187
- }
188
- function assertGetKey(value) {
189
- if (value === void 0) return;
190
- if (!isFunction(value)) {
191
- throw new TypeError("getKey must be a function.");
192
- }
193
- }
194
- function assertKey(value) {
195
- if (!(value instanceof URL)) {
196
- throw new TypeError("getKey must return a URL.");
197
- }
198
- }
199
-
200
- // src/utils/compare.ts
201
- function lexCompare(a, b) {
202
- if (a < b) return -1;
203
- if (a > b) return 1;
204
- return 0;
205
- }
206
-
207
- // src/utils/header.ts
208
- function setHeader(headers, key, value) {
209
- const raw = Array.isArray(value) ? value : [value];
210
- const values = Array.from(new Set(raw.map((v) => v.trim()))).filter((v) => v.length).sort(lexCompare);
211
- if (!values.length) {
212
- headers.delete(key);
213
- return;
214
- }
215
- headers.set(key, values.join(", "));
216
- }
217
- function mergeHeader(headers, key, value) {
218
- const values = Array.isArray(value) ? value : [value];
219
- if (values.length === 0) return;
220
- const existing = getHeaderValues(headers, key);
221
- const merged = existing.concat(values.map((v) => v.trim()));
222
- setHeader(headers, key, merged);
223
- }
224
- function getHeaderValues(headers, key) {
225
- const values = headers.get(key)?.split(",").map((v) => v.trim()).filter((v) => v.length > 0) ?? [];
226
- return Array.from(new Set(values)).sort(lexCompare);
227
- }
228
-
229
- // src/utils/request.ts
230
- function getOrigin(request) {
231
- const origin = request.headers.get(HttpHeader.ORIGIN)?.trim();
232
- if (!origin || origin === "null") return null;
233
- try {
234
- return new URL(origin).origin;
235
- } catch {
236
- return null;
237
- }
238
- }
239
- function sortSearchParams(request) {
240
- const url = new URL(request.url);
241
- const sorted = new URLSearchParams(
242
- [...url.searchParams.entries()].sort(([a], [b]) => lexCompare(a, b))
243
- );
244
- url.search = sorted.toString();
245
- url.hash = "";
246
- return url;
247
- }
248
- function stripSearchParams(request) {
249
- const url = new URL(request.url);
250
- url.search = "";
251
- url.hash = "";
252
- return url;
253
- }
254
-
255
- // src/utils/response.ts
256
- var ADD_CHARSET = /* @__PURE__ */ new Set([
257
- "text/css" /* CSS */,
258
- "text/csv" /* CSV */,
259
- "text/xml" /* XML */,
260
- "image/svg+xml" /* SVG */,
261
- "text/html" /* HTML */,
262
- "application/json" /* JSON */,
263
- "application/x-ndjson" /* NDJSON */,
264
- "application/xml" /* XML_APP */,
265
- "text/markdown" /* MARKDOWN */,
266
- "text/richtext" /* RICH_TEXT */,
267
- "text/plain" /* PLAIN_TEXT */,
268
- "application/x-www-form-urlencoded" /* FORM_URLENCODED */
269
- ]);
270
- function getContentType(type) {
271
- if (ADD_CHARSET.has(type)) {
272
- return `${type}; charset=utf-8`;
273
- }
274
- return type;
275
- }
276
-
277
- // src/middleware/cache/constants.ts
278
- var VARY_WILDCARD = "*";
279
-
280
- // src/middleware/cache/utils.ts
281
- var VARY_CACHE_URL = "https://vary";
282
- function isCacheable(response) {
283
- if (!response.ok) return false;
284
- if (getVaryHeader(response).includes(VARY_WILDCARD)) return false;
285
- return true;
286
- }
287
- function getVaryHeader(response) {
288
- const values = getHeaderValues(response.headers, HttpHeader.VARY);
289
- return Array.from(new Set(values.map((v) => v.toLowerCase()))).sort(lexCompare);
290
- }
291
- function filterVaryHeader(vary) {
292
- return vary.map((h) => h.toLowerCase()).filter((value) => value !== HttpHeader.ACCEPT_ENCODING.toLowerCase());
293
- }
294
- function getVaryKey(request, vary, key) {
295
- const varyPairs = [];
296
- const filtered = filterVaryHeader(vary);
297
- filtered.sort(lexCompare);
298
- filtered.forEach((header) => {
299
- const value = request.headers.get(header);
300
- if (value !== null) {
301
- varyPairs.push([header, value]);
302
- }
303
- });
304
- const encoded = base64UrlEncode(JSON.stringify([key.toString(), varyPairs]));
305
- return new URL(encoded, VARY_CACHE_URL).href;
306
- }
307
- function base64UrlEncode(str) {
308
- const utf8 = new TextEncoder().encode(str);
309
- let base64 = btoa(String.fromCharCode(...utf8));
310
- while (base64.endsWith("=")) {
311
- base64 = base64.slice(0, -1);
312
- }
313
- return base64.replace(/\+/g, "-").replace(/\//g, "_");
314
- }
315
-
316
- // src/middleware/cache/handler.ts
317
- function cache(cacheName, getKey) {
318
- assertCacheName(cacheName);
319
- assertGetKey(getKey);
320
- return new CacheHandler(cacheName, getKey);
321
- }
322
- var CacheHandler = class extends Middleware {
323
- constructor(cacheName, getKey) {
324
- super();
325
- this.cacheName = cacheName;
326
- this.getKey = getKey;
327
- this.cacheName = cacheName?.trim() || void 0;
328
- }
329
- /**
330
- * Handles an incoming request.
331
- * - Bypasses caching for non-GET requests.
332
- * - Checks the cache for a stored response.
333
- * - Calls next if no cached response exists.
334
- * - Caches the response if it is cacheable.
335
- *
336
- * @param worker The Worker instance containing the request and context.
337
- * @param next Function to call the next middleware or origin fetch.
338
- * @returns A cached or freshly fetched Response.
339
- */
340
- async handle(worker, next) {
341
- if (worker.request.method !== GET) {
342
- return next();
343
- }
344
- const cache2 = this.cacheName ? await caches.open(this.cacheName) : caches.default;
345
- const cached = await this.getCached(cache2, worker.request);
346
- if (cached) return cached;
347
- const response = await next();
348
- this.setCached(cache2, worker, response);
349
- return response;
350
- }
351
- /**
352
- * Retrieves a cached response for a given request.
353
- * - Checks both the base cache key and any Vary-specific keys.
354
- *
355
- * @param cache The Cache object to check.
356
- * @param request The request to retrieve a cached response for.
357
- * @returns A cached Response if available, otherwise `undefined`.
358
- */
359
- async getCached(cache2, request) {
360
- const url = this.getCacheKey(request);
361
- const response = await cache2.match(url);
362
- if (!response) return;
363
- const vary = this.getFilteredVary(response);
364
- if (vary.length === 0) return response;
365
- const key = getVaryKey(request, vary, url);
366
- return cache2.match(key);
367
- }
368
- /**
369
- * Caches a response if it is cacheable.
370
- *
371
- * Behavior:
372
- * - Always stores the response under the main cache key. This ensures that
373
- * the response’s Vary headers are available for later cache lookups.
374
- * - If the response varies based on certain request headers (per the Vary header),
375
- * also stores a copy under a Vary-specific cache key so future requests
376
- * with matching headers can retrieve the correct response.
377
- *
378
- * @param cache The Cache object to store the response in.
379
- * @param worker The Worker instance containing the request and context.
380
- * @param response The Response to cache.
381
- */
382
- async setCached(cache2, worker, response) {
383
- if (!isCacheable(response)) return;
384
- const url = this.getCacheKey(worker.request);
385
- worker.ctx.waitUntil(cache2.put(url, response.clone()));
386
- const vary = this.getFilteredVary(response);
387
- if (vary.length > 0) {
388
- worker.ctx.waitUntil(
389
- cache2.put(getVaryKey(worker.request, vary, url), response.clone())
390
- );
391
- }
392
- }
393
- /**
394
- * Extracts and filters the `Vary` header from a response.
395
- *
396
- * @param response - The HTTP response to inspect.
397
- * @returns An array of filtered header names from the `Vary` header.
398
- */
399
- getFilteredVary(response) {
400
- return filterVaryHeader(getVaryHeader(response));
401
- }
402
- /**
403
- * Returns the cache key for a request.
404
- *
405
- * By default, this is a normalized URL including the path and query string.
406
- * However, users can provide a custom `getKey` function when creating the
407
- * `cache` middleware to fully control how the cache keys are generated.
408
- *
409
- * For example, a custom function could:
410
- * - Sort or remove query parameters
411
- * - Exclude the search/query string entirely
412
- * - Modify the path or host
413
- *
414
- * This allows complete flexibility over cache key generation.
415
- *
416
- * @param request The Request object to generate a cache key for.
417
- * @returns A URL representing the main cache key for this request.
418
- */
419
- getCacheKey(request) {
420
- const key = this.getKey ? this.getKey(request) : sortSearchParams(request);
421
- assertKey(key);
422
- key.hash = "";
423
- return key;
424
- }
425
- };
426
-
427
- // src/responses.ts
428
- import { getReasonPhrase, StatusCodes as StatusCodes2 } from "http-status-codes";
429
- var BaseResponse = class {
430
- /** HTTP headers for the response. */
431
- headers = new Headers();
432
- /** HTTP status code (default 200 OK). */
433
- status = StatusCodes2.OK;
434
- /** Optional status text. Defaults to standard reason phrase. */
435
- statusText;
436
- /** Enable websocket responses. */
437
- webSocket = null;
438
- /** Default media type of the response body. */
439
- mediaType = "text/plain" /* PLAIN_TEXT */;
440
- /** Converts current state to ResponseInit for constructing a Response. */
441
- get responseInit() {
442
- return {
443
- headers: this.headers,
444
- status: this.status,
445
- statusText: this.statusText ?? getReasonPhrase(this.status),
446
- webSocket: this.webSocket,
447
- encodeBody: "automatic"
448
- };
449
- }
450
- /** Sets a header, overwriting any existing value. */
451
- setHeader(key, value) {
452
- setHeader(this.headers, key, value);
453
- }
454
- /** Merges a header with existing values (does not overwrite). */
455
- mergeHeader(key, value) {
456
- mergeHeader(this.headers, key, value);
457
- }
458
- /** Adds a Content-Type header if not already existing (does not overwrite). */
459
- addContentType() {
460
- if (!this.headers.get(HttpHeader.CONTENT_TYPE)) {
461
- this.headers.set(HttpHeader.CONTENT_TYPE, getContentType(this.mediaType));
462
- }
463
- }
464
- };
465
- var CacheResponse = class extends BaseResponse {
466
- constructor(cache2) {
467
- super();
468
- this.cache = cache2;
469
- }
470
- /** Adds Cache-Control header if caching is configured. */
471
- addCacheHeader() {
472
- if (this.cache) {
473
- this.headers.set(HttpHeader.CACHE_CONTROL, CacheControl.stringify(this.cache));
474
- }
475
- }
476
- };
477
- var WorkerResponse = class extends CacheResponse {
478
- constructor(body = null, cache2) {
479
- super(cache2);
480
- this.body = body;
481
- }
482
- /** Builds the Response with body, headers, and status. */
483
- async response() {
484
- this.addCacheHeader();
485
- const body = this.status === StatusCodes2.NO_CONTENT ? null : this.body;
486
- if (body) this.addContentType();
487
- return new Response(body, this.responseInit);
488
- }
489
- };
490
- var ClonedResponse = class extends WorkerResponse {
491
- constructor(response, cache2) {
492
- const clone = response.clone();
493
- super(clone.body, cache2);
494
- this.headers = new Headers(clone.headers);
495
- this.status = clone.status;
496
- this.statusText = clone.statusText;
497
- }
498
- };
499
- var SuccessResponse = class extends WorkerResponse {
500
- constructor(body = null, cache2, status = StatusCodes2.OK) {
501
- super(body, cache2);
502
- this.status = status;
503
- }
504
- };
505
- var JsonResponse = class extends SuccessResponse {
506
- constructor(json = {}, cache2, status = StatusCodes2.OK) {
507
- super(JSON.stringify(json), cache2, status);
508
- this.mediaType = "application/json" /* JSON */;
509
- }
510
- };
511
- var HtmlResponse = class extends SuccessResponse {
512
- constructor(body, cache2, status = StatusCodes2.OK) {
513
- super(body, cache2, status);
514
- this.mediaType = "text/html" /* HTML */;
515
- }
516
- };
517
- var TextResponse = class extends SuccessResponse {
518
- constructor(content, cache2, status = StatusCodes2.OK) {
519
- super(content, cache2, status);
520
- this.mediaType = "text/plain" /* PLAIN_TEXT */;
521
- }
522
- };
523
- var WebSocketUpgrade = class extends WorkerResponse {
524
- constructor(client) {
525
- super(null);
526
- this.status = StatusCodes2.SWITCHING_PROTOCOLS;
527
- this.webSocket = client;
528
- }
529
- };
530
- var Head = class extends WorkerResponse {
531
- constructor(get) {
532
- super();
533
- this.status = get.status;
534
- this.statusText = get.statusText;
535
- this.headers = new Headers(get.headers);
536
- }
537
- };
538
- var Options = class extends SuccessResponse {
539
- constructor() {
540
- super(null, void 0, StatusCodes2.NO_CONTENT);
541
- }
542
- };
543
-
544
- // src/middleware/cors/constants.ts
545
- var ALLOW_ALL_ORIGINS = "*";
546
- var SIMPLE_METHODS = /* @__PURE__ */ new Set([GET, HEAD, OPTIONS]);
547
- var SKIP_CORS_STATUSES = [
548
- StatusCodes.SWITCHING_PROTOCOLS,
549
- StatusCodes.CONTINUE,
550
- StatusCodes.PROCESSING,
551
- StatusCodes.EARLY_HINTS,
552
- StatusCodes.MOVED_PERMANENTLY,
553
- StatusCodes.MOVED_TEMPORARILY,
554
- StatusCodes.SEE_OTHER,
555
- StatusCodes.TEMPORARY_REDIRECT,
556
- StatusCodes.PERMANENT_REDIRECT
557
- ];
558
- var defaultCorsConfig = {
559
- allowedOrigins: [ALLOW_ALL_ORIGINS],
560
- allowedHeaders: [HttpHeader.CONTENT_TYPE],
561
- exposedHeaders: [],
562
- allowCredentials: false,
563
- maxAge: 5 * Time.Minute
564
- };
565
-
566
- // src/middleware/cors/utils.ts
567
- async function options(worker, cors2) {
568
- const options2 = new Options();
569
- const origin = getOrigin(worker.request);
570
- if (origin) {
571
- setAllowOrigin(options2.headers, cors2, origin);
572
- setAllowCredentials(options2.headers, cors2, origin);
573
- }
574
- setAllowMethods(options2.headers, worker);
575
- setAllowHeaders(options2.headers, cors2);
576
- setMaxAge(options2.headers, cors2);
577
- return options2.response();
578
- }
579
- async function apply(response, worker, cors2) {
580
- const clone = new ClonedResponse(response);
581
- const origin = getOrigin(worker.request);
582
- deleteCorsHeaders(clone.headers);
583
- if (origin) {
584
- setAllowOrigin(clone.headers, cors2, origin);
585
- setAllowCredentials(clone.headers, cors2, origin);
586
- setExposedHeaders(clone.headers, cors2);
587
- }
588
- return clone.response();
589
- }
590
- function setAllowOrigin(headers, cors2, origin) {
591
- if (allowAllOrigins(cors2)) {
592
- setHeader(headers, HttpHeader.ACCESS_CONTROL_ALLOW_ORIGIN, ALLOW_ALL_ORIGINS);
593
- } else {
594
- if (cors2.allowedOrigins.includes(origin)) {
595
- setHeader(headers, HttpHeader.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
596
- }
597
- mergeHeader(headers, HttpHeader.VARY, HttpHeader.ORIGIN);
598
- }
599
- }
600
- function setAllowCredentials(headers, cors2, origin) {
601
- if (!cors2.allowCredentials) return;
602
- if (allowAllOrigins(cors2)) return;
603
- if (!cors2.allowedOrigins.includes(origin)) return;
604
- setHeader(headers, HttpHeader.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
605
- }
606
- function setAllowMethods(headers, worker) {
607
- const methods = worker.getAllowedMethods();
608
- assertMethods(methods);
609
- const allowed = methods.filter((method) => !SIMPLE_METHODS.has(method));
610
- if (allowed.length > 0) {
611
- setHeader(headers, HttpHeader.ACCESS_CONTROL_ALLOW_METHODS, allowed);
612
- }
613
- }
614
- function setMaxAge(headers, cors2) {
615
- const maxAge = Math.max(0, Math.floor(cors2.maxAge));
616
- setHeader(headers, HttpHeader.ACCESS_CONTROL_MAX_AGE, String(maxAge));
617
- }
618
- function setAllowHeaders(headers, cors2) {
619
- if (cors2.allowedHeaders.length > 0) {
620
- setHeader(headers, HttpHeader.ACCESS_CONTROL_ALLOW_HEADERS, cors2.allowedHeaders);
621
- }
622
- }
623
- function setExposedHeaders(headers, cors2) {
624
- setHeader(headers, HttpHeader.ACCESS_CONTROL_EXPOSE_HEADERS, cors2.exposedHeaders);
625
- }
626
- function allowAllOrigins(cors2) {
627
- return cors2.allowedOrigins.includes(ALLOW_ALL_ORIGINS);
628
- }
629
- function deleteCorsHeaders(headers) {
630
- headers.delete(HttpHeader.ACCESS_CONTROL_MAX_AGE);
631
- headers.delete(HttpHeader.ACCESS_CONTROL_ALLOW_ORIGIN);
632
- headers.delete(HttpHeader.ACCESS_CONTROL_ALLOW_HEADERS);
633
- headers.delete(HttpHeader.ACCESS_CONTROL_ALLOW_METHODS);
634
- headers.delete(HttpHeader.ACCESS_CONTROL_EXPOSE_HEADERS);
635
- headers.delete(HttpHeader.ACCESS_CONTROL_ALLOW_CREDENTIALS);
636
- }
637
- function skipCors(response) {
638
- const { status, headers } = response;
639
- if (SKIP_CORS_STATUSES.includes(status)) return true;
640
- if (headers.has(HttpHeader.UPGRADE)) return true;
641
- return false;
642
- }
643
-
644
- // src/guards/cors.ts
645
- function assertCorsInit(value) {
646
- if (value === void 0) return;
647
- if (typeof value !== "object" || value === null) {
648
- throw new TypeError("CorsInit must be an object.");
649
- }
650
- const obj = value;
651
- if (obj["allowedOrigins"] !== void 0 && !isStringArray(obj["allowedOrigins"])) {
652
- throw new TypeError("CorsInit.allowedOrigins must be a string array.");
653
- }
654
- if (obj["allowedHeaders"] !== void 0 && !isStringArray(obj["allowedHeaders"])) {
655
- throw new TypeError("CorsInit.allowedHeaders must be a string array.");
656
- }
657
- if (obj["exposedHeaders"] !== void 0 && !isStringArray(obj["exposedHeaders"])) {
658
- throw new TypeError("CorsInit.exposedHeaders must be a string array.");
659
- }
660
- if (obj["allowCredentials"] !== void 0 && !isBoolean(obj["allowCredentials"])) {
661
- throw new TypeError("CorsInit.allowCredentials must be a boolean.");
662
- }
663
- if (obj["maxAge"] !== void 0 && !isNumber(obj["maxAge"])) {
664
- throw new TypeError("CorsInit.maxAge must be a number.");
665
- }
666
- }
667
-
668
- // src/middleware/cors/handler.ts
669
- function cors(init) {
670
- assertCorsInit(init);
671
- return new CorsHandler(init);
672
- }
673
- var CorsHandler = class extends Middleware {
674
- /** The configuration used for this instance, with all defaults applied. */
675
- config;
676
- /**
677
- * Create a new CORS middleware instance.
678
- *
679
- * @param init - Partial configuration to override the defaults. Any values
680
- * not provided will use `defaultCorsConfig`.
681
- */
682
- constructor(init) {
683
- super();
684
- this.config = { ...defaultCorsConfig, ...init };
685
- }
686
- /**
687
- * Applies CORS headers to a request.
688
- *
689
- * - Returns a preflight response for `OPTIONS` requests.
690
- * - For other methods, calls `next()` and applies CORS headers to the result.
691
- *
692
- * @param worker - The Worker handling the request.
693
- * @param next - Function to invoke the next middleware.
694
- * @returns Response with CORS headers applied.
695
- */
696
- async handle(worker, next) {
697
- if (worker.request.method === OPTIONS) {
698
- return options(worker, this.config);
699
- }
700
- const response = await next();
701
- if (skipCors(response)) return response;
702
- return apply(response, worker, this.config);
703
- }
704
- };
705
-
706
- // src/errors.ts
707
- import { getReasonPhrase as getReasonPhrase2, StatusCodes as StatusCodes3 } from "http-status-codes";
708
- var HttpError = class extends JsonResponse {
709
- /**
710
- * @param worker The worker handling the request.
711
- * @param status HTTP status code.
712
- * @param details Optional detailed error message.
713
- */
714
- constructor(status, details) {
715
- const json = {
716
- status,
717
- error: getReasonPhrase2(status),
718
- details: details ?? ""
719
- };
720
- super(json, CacheControl.DISABLE, status);
721
- this.details = details;
722
- }
723
- };
724
- var BadRequest = class extends HttpError {
725
- constructor(details) {
726
- super(StatusCodes3.BAD_REQUEST, details);
727
- }
728
- };
729
- var Unauthorized = class extends HttpError {
730
- constructor(details) {
731
- super(StatusCodes3.UNAUTHORIZED, details);
732
- }
733
- };
734
- var Forbidden = class extends HttpError {
735
- constructor(details) {
736
- super(StatusCodes3.FORBIDDEN, details);
737
- }
738
- };
739
- var NotFound = class extends HttpError {
740
- constructor(details) {
741
- super(StatusCodes3.NOT_FOUND, details);
742
- }
743
- };
744
- var MethodNotAllowed = class extends HttpError {
745
- constructor(worker) {
746
- const methods = worker.getAllowedMethods();
747
- assertMethods(methods);
748
- super(StatusCodes3.METHOD_NOT_ALLOWED, `${worker.request.method} method not allowed.`);
749
- this.setHeader(HttpHeader.ALLOW, methods);
750
- }
751
- };
752
- var UpgradeRequired = class extends HttpError {
753
- constructor() {
754
- super(StatusCodes3.UPGRADE_REQUIRED);
755
- this.headers.set(HttpHeader.SEC_WEBSOCKET_VERSION, WS_VERSION);
756
- }
757
- };
758
- var InternalServerError = class extends HttpError {
759
- constructor(details) {
760
- super(StatusCodes3.INTERNAL_SERVER_ERROR, details);
761
- }
762
- };
763
- var NotImplemented = class extends HttpError {
764
- constructor(details) {
765
- super(StatusCodes3.NOT_IMPLEMENTED, details);
766
- }
767
- };
768
- var MethodNotImplemented = class extends NotImplemented {
769
- constructor(worker) {
770
- super(`${worker.request.method} method not implemented.`);
771
- }
772
- };
773
- var ServiceUnavailable = class extends HttpError {
774
- constructor(details) {
775
- super(StatusCodes3.SERVICE_UNAVAILABLE, details);
776
- }
777
- };
778
-
779
- // src/middleware/websocket/utils.ts
780
- function hasConnectionHeader(headers) {
781
- return getHeaderValues(headers, HttpHeader.CONNECTION).some(
782
- (value) => value.toLowerCase() === WS_UPGRADE
783
- );
784
- }
785
- function hasUpgradeHeader(headers) {
786
- return getHeaderValues(headers, HttpHeader.UPGRADE).some(
787
- (value) => value.toLowerCase() === WS_WEBSOCKET
788
- );
789
- }
790
- function hasWebSocketVersion(headers) {
791
- return headers.get(HttpHeader.SEC_WEBSOCKET_VERSION)?.trim() === WS_VERSION;
792
- }
793
-
794
- // src/middleware/websocket/handler.ts
795
- function websocket(path = "/") {
796
- return new WebSocketHandler(path);
797
- }
798
- var WebSocketHandler = class extends Middleware {
799
- constructor(path) {
800
- super();
801
- this.path = path;
802
- }
803
- handle(worker, next) {
804
- if (worker.request.method !== GET) {
805
- return next();
806
- }
807
- if (this.getPath(worker.request) !== this.path) {
808
- return next();
809
- }
810
- const headers = worker.request.headers;
811
- if (!hasConnectionHeader(headers)) {
812
- return new BadRequest("Missing or invalid Connection header").response();
813
- }
814
- if (!hasUpgradeHeader(headers)) {
815
- return new BadRequest("Missing or invalid Upgrade header").response();
816
- }
817
- if (!hasWebSocketVersion(headers)) {
818
- return new UpgradeRequired().response();
819
- }
820
- return next();
821
- }
822
- getPath(request) {
823
- return new URL(request.url).pathname;
824
- }
825
- };
826
-
827
- // src/guards/websocket.ts
828
- function isBinary(value) {
829
- return value instanceof ArrayBuffer || ArrayBuffer.isView(value);
830
- }
831
- function isSendable(value) {
832
- if (isString(value)) return value.length > 0;
833
- if (isBinary(value)) return value.byteLength > 0;
834
- return false;
835
- }
836
- function safeCloseCode(code) {
837
- if (!isNumber(code)) return CloseCode.NORMAL;
838
- if (isCodeInRange(code) && !isReservedCode(code)) return code;
839
- return CloseCode.NORMAL;
840
- }
841
- function isCodeInRange(code) {
842
- return code >= CloseCode.NORMAL && code <= WS_MAX_CLOSE_CODE;
843
- }
844
- function isReservedCode(code) {
845
- return WS_RESERVED_CODES.has(code);
846
- }
847
- function safeReason(reason) {
848
- if (!isString(reason)) return;
849
- return reason.replace(/[^\x20-\x7E]/g, "").slice(0, WS_MAX_REASON_CHARS);
850
- }
851
- function assertSerializable(value) {
852
- if (value === null || typeof value !== "object") {
853
- throw new TypeError("WebSocket attachment must be a non-null object");
854
- }
855
- try {
856
- JSON.stringify(value);
857
- } catch {
858
- throw new TypeError("WebSocket attachment is non-serializable");
859
- }
860
- }
861
-
862
- // src/websocket/events.ts
863
- var WebSocketEvents = class _WebSocketEvents {
864
- server;
865
- static isCustomEvent(type) {
866
- return ["open", "warn"].includes(type);
867
- }
868
- customListeners = {};
869
- constructor(server) {
870
- this.server = server;
871
- }
872
- addEventListener(type, listener, options2) {
873
- if (_WebSocketEvents.isCustomEvent(type)) {
874
- let arr = this.customListeners[type];
875
- if (!arr) {
876
- arr = [];
877
- this.customListeners[type] = arr;
878
- }
879
- arr.push(listener);
880
- } else {
881
- const finalOptions = type === "close" ? { ...options2, once: true } : options2;
882
- this.server.addEventListener(
883
- type,
884
- listener,
885
- finalOptions
886
- );
887
- }
888
- }
889
- removeEventListener(type, listener) {
890
- if (_WebSocketEvents.isCustomEvent(type)) {
891
- const arr = this.customListeners[type];
892
- if (arr) {
893
- const index = arr.indexOf(listener);
894
- if (index !== -1) arr.splice(index, 1);
895
- }
896
- } else {
897
- this.server.removeEventListener(
898
- type,
899
- listener
900
- );
901
- }
902
- }
903
- dispatch(type, ev, once = false) {
904
- const listeners = this.customListeners[type]?.slice() ?? [];
905
- if (once) {
906
- this.customListeners[type] = [];
907
- }
908
- listeners.forEach((listener) => listener(ev));
909
- }
910
- warn(msg) {
911
- this.dispatch("warn", { type: "warn", message: msg });
912
- }
913
- open() {
914
- this.dispatch("open", new Event("open"), true);
915
- }
916
- };
917
-
918
- // src/websocket/base.ts
919
- var BaseWebSocket = class extends WebSocketEvents {
920
- accepted = false;
921
- server;
922
- constructor(server) {
923
- super(server);
924
- this.server = server;
925
- this.server.addEventListener("close", this.onclose);
926
- }
927
- send(data) {
928
- if (this.isState(WebSocket.CONNECTING, WebSocket.CLOSED)) {
929
- this.warn("Cannot send: WebSocket not open");
930
- return;
931
- }
932
- if (!isSendable(data)) {
933
- this.warn("Cannot send: empty or invalid data");
934
- return;
935
- }
936
- this.server.send(data);
937
- }
938
- get attachment() {
939
- return this.server.deserializeAttachment() ?? {};
940
- }
941
- attach(attachment) {
942
- if (attachment === void 0) return;
943
- if (attachment === null) {
944
- this.server.serializeAttachment({});
945
- } else {
946
- assertSerializable(attachment);
947
- this.server.serializeAttachment(attachment);
948
- }
949
- }
950
- get readyState() {
951
- if (!this.accepted) return WebSocket.CONNECTING;
952
- return this.server.readyState;
953
- }
954
- isState(...states) {
955
- return states.includes(this.readyState);
956
- }
957
- close(code, reason) {
958
- this.server.removeEventListener("close", this.onclose);
959
- this.server.close(safeCloseCode(code), safeReason(reason));
960
- }
961
- onclose = (event) => {
962
- this.close(event.code, event.reason);
963
- };
964
- };
965
-
966
- // src/websocket/new.ts
967
- var NewConnectionBase = class extends BaseWebSocket {
968
- client;
969
- constructor() {
970
- const pair = new WebSocketPair();
971
- const [client, server] = [pair[0], pair[1]];
972
- super(server);
973
- this.client = client;
974
- }
975
- acceptWebSocket(ctx, tags) {
976
- ctx.acceptWebSocket(this.server, tags);
977
- return this.ready();
978
- }
979
- accept() {
980
- this.server.accept();
981
- return this.ready();
982
- }
983
- ready() {
984
- this.accepted = true;
985
- this.open();
986
- return this.client;
987
- }
988
- };
989
-
990
- // src/websocket/restore.ts
991
- var RestoredConnectionBase = class extends BaseWebSocket {
992
- constructor(ws) {
993
- super(ws);
994
- this.accepted = true;
995
- }
996
- accept() {
997
- throw new Error("Do not call accept() on restore");
998
- }
999
- acceptWebSocket() {
1000
- throw new Error("Do not call acceptWebSocket() on restore");
1001
- }
1002
- };
1003
-
1004
- // src/websocket/sessions.ts
1005
- var WebSocketSessions = class {
1006
- map = /* @__PURE__ */ new Map();
1007
- create(attachment) {
1008
- class NewConnection extends NewConnectionBase {
1009
- constructor(sessions) {
1010
- super();
1011
- this.sessions = sessions;
1012
- }
1013
- accept() {
1014
- this.addEventListener("close", () => this.sessions.unregister(this.server));
1015
- this.sessions.register(this.server, this);
1016
- return super.accept();
1017
- }
1018
- acceptWebSocket(ctx, tags) {
1019
- this.sessions.register(this.server, this);
1020
- return super.acceptWebSocket(ctx, tags);
1021
- }
1022
- }
1023
- const connection = new NewConnection(this);
1024
- connection.attach(attachment);
1025
- return connection;
1026
- }
1027
- restore(ws) {
1028
- class RestoredConnection extends RestoredConnectionBase {
1029
- constructor(sessions, restore) {
1030
- super(restore);
1031
- sessions.register(this.server, this);
1032
- }
1033
- }
1034
- return new RestoredConnection(this, ws);
1035
- }
1036
- restoreAll(all) {
1037
- const restored = [];
1038
- for (const ws of all) {
1039
- restored.push(this.restore(ws));
1040
- }
1041
- return restored;
1042
- }
1043
- get(ws) {
1044
- return this.map.get(ws);
1045
- }
1046
- values() {
1047
- return this.map.values();
1048
- }
1049
- keys() {
1050
- return this.map.keys();
1051
- }
1052
- close(ws, code, reason) {
1053
- const con = this.get(ws);
1054
- if (con) con.close(code, reason);
1055
- return this.unregister(ws);
1056
- }
1057
- *[Symbol.iterator]() {
1058
- yield* this.values();
1059
- }
1060
- register(ws, con) {
1061
- this.map.set(ws, con);
1062
- }
1063
- unregister(ws) {
1064
- return this.map.delete(ws);
1065
- }
1066
- };
1067
-
1068
- // src/workers/base.ts
1069
- var BaseWorker = class {
1070
- constructor(_request, _env, _ctx) {
1071
- this._request = _request;
1072
- this._env = _env;
1073
- this._ctx = _ctx;
1074
- }
1075
- /** The Request object associated with this worker invocation */
1076
- get request() {
1077
- return this._request;
1078
- }
1079
- /** Environment bindings (e.g., KV, secrets, or other globals) */
1080
- get env() {
1081
- return this._env;
1082
- }
1083
- /** Execution context for background tasks or `waitUntil` */
1084
- get ctx() {
1085
- return this._ctx;
1086
- }
1087
- /**
1088
- * Checks if the given HTTP method is allowed for this worker.
1089
- * @param method HTTP method string
1090
- * @returns true if the method is allowed
1091
- */
1092
- isAllowed(method) {
1093
- const methods = this.getAllowedMethods();
1094
- assertMethods(methods);
1095
- return isMethod(method) && methods.includes(method);
1096
- }
1097
- /**
1098
- * Creates a new instance of the current Worker subclass.
1099
- *
1100
- * @param request - The {@link Request} to pass to the new worker instance.
1101
- * @returns A new worker instance of the same subclass as `this`.
1102
- */
1103
- create(request) {
1104
- const ctor = this.constructor;
1105
- return new ctor(request, this.env, this.ctx);
1106
- }
1107
- /**
1108
- * Simplify and standardize {@link Response} creation by extending {@link WorkerResponse}
1109
- * or any of its subclasses and passing to this method.
1110
- *
1111
- * Or directly use any of the built-in classes.
1112
- *
1113
- * ```ts
1114
- * this.response(TextResponse, "Hello World!")
1115
- * ```
1116
- *
1117
- * @param ResponseClass The response class to instantiate
1118
- * @param args Additional constructor arguments
1119
- * @returns A Promise resolving to the {@link Response} object
1120
- */
1121
- async response(ResponseClass, ...args) {
1122
- return new ResponseClass(...args).response();
1123
- }
1124
- /**
1125
- * **Ignite** your `Worker` implementation into a Cloudflare handler.
1126
- *
1127
- * @returns A `FetchHandler` that launches a new worker instance for each request.
1128
- *
1129
- * ```ts
1130
- * export default MyWorker.ignite();
1131
- * ```
1132
- */
1133
- static ignite() {
1134
- return {
1135
- fetch: (request, env, ctx) => new this(request, env, ctx).fetch()
1136
- };
1137
- }
1138
- };
1139
-
1140
- // src/guards/middleware.ts
1141
- function assertMiddleware(handler) {
1142
- if (!(handler instanceof Middleware)) {
1143
- throw new TypeError("Handler must be a subclass of Middleware.");
1144
- }
1145
- }
1146
-
1147
- // src/workers/middleware.ts
1148
- var MiddlewareWorker = class extends BaseWorker {
1149
- /** Middleware handlers registered for this worker. */
1150
- middlewares = [];
1151
- /**
1152
- * Hook for subclasses to perform any initialization.
1153
- */
1154
- init() {
1155
- return;
1156
- }
1157
- /**
1158
- * Add a middleware instance to this worker.
1159
- *
1160
- * The middleware will run for every request handled by this worker,
1161
- * in the order they are added.
1162
- *
1163
- * @param handler - The middleware to run.
1164
- * @returns `this` to allow chaining multiple `.use()` calls.
1165
- */
1166
- use(handler) {
1167
- assertMiddleware(handler);
1168
- this.middlewares.push(handler);
1169
- return this;
1170
- }
1171
- /**
1172
- * Executes the middleware chain and dispatches the request.
1173
- *
1174
- * @returns The Response produced by the last middleware or `dispatch()`.
1175
- */
1176
- async fetch() {
1177
- const chain = this.middlewares.reduceRight(
1178
- (next, handler) => () => handler.handle(this, next),
1179
- () => this.dispatch()
1180
- );
1181
- return await chain();
1182
- }
1183
- };
1184
-
1185
- // src/workers/basic.ts
1186
- var BasicWorker = class extends MiddlewareWorker {
1187
- /**
1188
- * Entry point to handle a fetch request.
1189
- */
1190
- async fetch() {
1191
- if (!this.isAllowed(this.request.method)) {
1192
- return this.response(MethodNotAllowed, this);
1193
- }
1194
- try {
1195
- await this.init();
1196
- return await super.fetch();
1197
- } catch (error) {
1198
- console.error(error);
1199
- return this.response(InternalServerError);
1200
- }
1201
- }
1202
- /**
1203
- * Dispatches the request to the method-specific handler.
1204
- */
1205
- async dispatch() {
1206
- const method = this.request.method;
1207
- const handler = {
1208
- GET: () => this.get(),
1209
- PUT: () => this.put(),
1210
- HEAD: () => this.head(),
1211
- POST: () => this.post(),
1212
- PATCH: () => this.patch(),
1213
- DELETE: () => this.delete(),
1214
- OPTIONS: () => this.options()
1215
- };
1216
- return (handler[method] ?? (() => this.response(MethodNotAllowed, this)))();
1217
- }
1218
- /** Override and implement this method for GET requests. */
1219
- async get() {
1220
- return this.response(MethodNotImplemented, this);
1221
- }
1222
- /** Override and implement this method for PUT requests. */
1223
- async put() {
1224
- return this.response(MethodNotImplemented, this);
1225
- }
1226
- /** Override and implement this method for POST requests. */
1227
- async post() {
1228
- return this.response(MethodNotImplemented, this);
1229
- }
1230
- /** Override and implement this method for PATCH requests. */
1231
- async patch() {
1232
- return this.response(MethodNotImplemented, this);
1233
- }
1234
- /** Override and implement this method for DELETE requests. */
1235
- async delete() {
1236
- return this.response(MethodNotImplemented, this);
1237
- }
1238
- /** Returns a default empty OPTIONS response. */
1239
- async options() {
1240
- return this.response(Options);
1241
- }
1242
- /**
1243
- * Default handler for HEAD requests.
1244
- * Performs a GET request and removes the body for HEAD semantics.
1245
- *
1246
- * Usually does not need to be overridden as this behavior covers
1247
- * standard HEAD requirements.
1248
- */
1249
- async head() {
1250
- const worker = this.create(
1251
- new Request(this.request.url, { method: GET, headers: this.request.headers })
1252
- );
1253
- return this.response(Head, await worker.fetch());
1254
- }
1255
- /**
1256
- * DEFAULT allowed HTTP methods for subclasses.
1257
- *
1258
- * These defaults were selected for getting started quickly and should be
1259
- * overridden for each specific worker.
1260
- */
1261
- getAllowedMethods() {
1262
- return [GET, HEAD, OPTIONS];
1263
- }
1264
- };
1265
-
1266
- // src/routes.ts
1267
- import { match } from "path-to-regexp";
1268
- var Routes = class {
1269
- /** Internal array of registered routes */
1270
- routes = [];
1271
- /**
1272
- * Add routes to the router.
1273
- *
1274
- * Accepts any iterable of [method, path, handler] tuples.
1275
- * This includes arrays, Sets, or generators.
1276
- *
1277
- * @param routes - Iterable of route tuples to add.
1278
- */
1279
- add(routes) {
1280
- for (const [method, path, handler] of routes) {
1281
- const matcher = match(path);
1282
- this.routes.push({ method, matcher, handler });
1283
- }
1284
- }
1285
- /**
1286
- * Attempt to match a URL against the registered routes.
1287
- *
1288
- * @param method - HTTP method of the request
1289
- * @param url - Full URL string to match against
1290
- * @returns A MatchedRoute object if a route matches, otherwise null
1291
- */
1292
- match(method, url) {
1293
- const pathname = new URL(url).pathname;
1294
- for (const route of this) {
1295
- if (route.method !== method) continue;
1296
- const found = route.matcher(pathname);
1297
- if (found) return { route, params: found.params };
1298
- }
1299
- return null;
1300
- }
1301
- /**
1302
- * Iterate over all registered routes.
1303
- */
1304
- *[Symbol.iterator]() {
1305
- yield* this.routes;
1306
- }
1307
- };
1308
-
1309
- // src/workers/route.ts
1310
- var RouteWorker = class _RouteWorker extends BasicWorker {
1311
- /** Internal table of registered routes. */
1312
- _routes = new Routes();
1313
- /**
1314
- * Registers a single new route in the worker.
1315
- *
1316
- * When a request matches the specified method and path, the provided handler
1317
- * will be executed. The handler can be either:
1318
- * - A function that receives URL parameters, or
1319
- * - A Worker subclass that will handle the request.
1320
- *
1321
- * @param method - HTTP method for the route (GET, POST, etc.).
1322
- * @param path - URL path pattern (Express-style, e.g., "/users/:id").
1323
- * @param handler - The function or Worker class to run when the route matches.
1324
- * @returns The current worker instance, allowing method chaining.
1325
- */
1326
- route(method, path, handler) {
1327
- this.routes([[method, path, handler]]);
1328
- return this;
1329
- }
1330
- /**
1331
- * Registers multiple routes at once in the worker.
1332
- *
1333
- * Each route should be a tuple `[method, path, handler]` where:
1334
- * - `method` - HTTP method for the route (GET, POST, etc.).
1335
- * - `path` - URL path pattern (Express-style, e.g., "/users/:id").
1336
- * - `handler` - A function that receives URL parameters or a Worker subclass
1337
- * that will handle the request.
1338
- *
1339
- * @param routes - An iterable of routes to register. Each item is a `[method, path, handler]` tuple.
1340
- * @returns The current worker instance, allowing method chaining.
1341
- */
1342
- routes(routes) {
1343
- this._routes.add(routes);
1344
- return this;
1345
- }
1346
- /**
1347
- * Matches the incoming request against registered routes and dispatches it.
1348
- *
1349
- * If a route is found:
1350
- * - If the handler is a Worker class, a new instance is created and its `fetch()` is called.
1351
- * - If the handler is a callback function, it is invoked with the extracted path parameters.
1352
- *
1353
- * If no route matches, the request is passed to the parent `dispatch()` handler.
1354
- *
1355
- * @returns A `Promise<Response>` from the matched handler or parent dispatch.
1356
- */
1357
- async dispatch() {
1358
- const found = this._routes.match(this.request.method, this.request.url);
1359
- if (!found) return super.dispatch();
1360
- const { handler } = found.route;
1361
- if (_RouteWorker.isWorkerClass(handler)) {
1362
- return new handler(this.request, this.env, this.ctx).fetch();
1363
- }
1364
- return handler.call(this, found.params);
1365
- }
1366
- /**
1367
- * Runtime type guard to check if a given handler is a Worker class.
1368
- *
1369
- * A Worker class is any class that extends `BaseWorker`.
1370
- *
1371
- * @param handler - The constructor function to test.
1372
- * @returns `true` if `handler` is a subclass of `BaseWorker` at runtime, `false` otherwise.
1373
- */
1374
- static isWorkerClass(handler) {
1375
- return BaseWorker.prototype.isPrototypeOf(handler.prototype);
1376
- }
1377
- async get() {
1378
- return this.response(NotFound);
1379
- }
1380
- async put() {
1381
- return this.response(NotFound);
1382
- }
1383
- async post() {
1384
- return this.response(NotFound);
1385
- }
1386
- async patch() {
1387
- return this.response(NotFound);
1388
- }
1389
- async delete() {
1390
- return this.response(NotFound);
1391
- }
1392
- };
1393
- export {
1394
- BadRequest,
1395
- BasicWorker,
1396
- CacheControl,
1397
- ClonedResponse,
1398
- CloseCode,
1399
- DELETE,
1400
- Forbidden,
1401
- GET,
1402
- HEAD,
1403
- Head,
1404
- HtmlResponse,
1405
- HttpError,
1406
- HttpHeader,
1407
- InternalServerError,
1408
- JsonResponse,
1409
- MediaType,
1410
- Method,
1411
- MethodNotAllowed,
1412
- MethodNotImplemented,
1413
- NotFound,
1414
- NotImplemented,
1415
- OPTIONS,
1416
- Options,
1417
- PATCH,
1418
- POST,
1419
- PUT,
1420
- RouteWorker,
1421
- ServiceUnavailable,
1422
- StatusCodes,
1423
- SuccessResponse,
1424
- TextResponse,
1425
- Time,
1426
- Unauthorized,
1427
- UpgradeRequired,
1428
- WS_MAX_CLOSE_CODE,
1429
- WS_MAX_REASON_CHARS,
1430
- WS_RESERVED_CODES,
1431
- WS_UPGRADE,
1432
- WS_VERSION,
1433
- WS_WEBSOCKET,
1434
- WebSocketSessions,
1435
- WebSocketUpgrade,
1436
- WorkerResponse,
1437
- assertMethods,
1438
- cache,
1439
- cors,
1440
- getContentType,
1441
- getHeaderValues,
1442
- getOrigin,
1443
- isMethod,
1444
- isMethodArray,
1445
- lexCompare,
1446
- mergeHeader,
1447
- setHeader,
1448
- sortSearchParams,
1449
- stripSearchParams,
1450
- websocket
1451
- };
1
+ import pe from"cache-control-parser";var I={parse:pe.parse,stringify:pe.stringify,DISABLE:Object.freeze({"no-cache":!0,"no-store":!0,"must-revalidate":!0,"max-age":0})};import{StatusCodes as m}from"http-status-codes";var i;(c=>(c.ALLOW="Allow",c.ACCEPT_ENCODING="Accept-Encoding",c.ORIGIN="Origin",c.CONTENT_TYPE="Content-Type",c.CACHE_CONTROL="Cache-Control",c.USER_AGENT="User-Agent",c.VARY="Vary",c.CONTENT_SECURITY_POLICY="Content-Security-Policy",c.PERMISSIONS_POLICY="Permissions-Policy",c.STRICT_TRANSPORT_SECURITY="Strict-Transport-Security",c.REFERRER_POLICY="Referrer-Policy",c.X_CONTENT_TYPE_OPTIONS="X-Content-Type-Options",c.X_FRAME_OPTIONS="X-Frame-Options",c.ACCESS_CONTROL_ALLOW_CREDENTIALS="Access-Control-Allow-Credentials",c.ACCESS_CONTROL_ALLOW_HEADERS="Access-Control-Allow-Headers",c.ACCESS_CONTROL_ALLOW_METHODS="Access-Control-Allow-Methods",c.ACCESS_CONTROL_ALLOW_ORIGIN="Access-Control-Allow-Origin",c.ACCESS_CONTROL_EXPOSE_HEADERS="Access-Control-Expose-Headers",c.ACCESS_CONTROL_MAX_AGE="Access-Control-Max-Age",c.ACCESS_CONTROL_REQUEST_HEADERS="Access-Control-Request-Headers",c.SEC_WEBSOCKET_VERSION="Sec-WebSocket-Version",c.CONNECTION="Connection",c.UPGRADE="Upgrade"))(i||={});var W=(u=>(u.GET="GET",u.PUT="PUT",u.HEAD="HEAD",u.POST="POST",u.PATCH="PATCH",u.DELETE="DELETE",u.OPTIONS="OPTIONS",u))(W||{}),{GET:f,PUT:vt,HEAD:k,POST:Pt,PATCH:yt,DELETE:It,OPTIONS:g}=W;var ze=(n=>(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))(ze||{});var ue={Second:1,Minute:60,Hour:3600,Day:86400,Week:604800,Month:2592e3,Year:31536e3};var le="upgrade",de="websocket",$="13",me=4999,he=123,O={NORMAL:1e3,GOING_AWAY:1001,PROTOCOL_ERROR:1002,UNSUPPORTED_DATA:1003,NO_STATUS:1005,ABNORMAL:1006,INVALID_PAYLOAD:1007,POLICY_VIOLATION:1008,MESSAGE_TOO_BIG:1009,MISSING_EXTENSION:1010,INTERNAL_ERROR:1011,TLS_HANDSHAKE:1015},fe=new Set([O.NO_STATUS,O.ABNORMAL,O.TLS_HANDSHAKE]);function D(t){return Array.isArray(t)&&t.every(e=>typeof e=="string")}function R(t){return typeof t=="string"}function Ce(t){return typeof t=="function"}function M(t){return typeof t=="number"&&!Number.isNaN(t)}function Ee(t){return typeof t=="boolean"}var $e=new Set(Object.values(W));function Z(t){return R(t)&&$e.has(t)}function Ze(t){return Array.isArray(t)&&t.every(Z)}function b(t){if(!Ze(t)){let e=Array.isArray(t)?JSON.stringify(t):String(t);throw new TypeError(`Invalid method array: ${e}`)}}var h=class{};function Se(t){if(t!==void 0&&!R(t))throw new TypeError("Cache name must be a string.")}function Ae(t){if(t!==void 0&&!Ce(t))throw new TypeError("getKey must be a function.")}function xe(t){if(!(t instanceof URL))throw new TypeError("getKey must return a URL.")}function E(t,e){return t<e?-1:t>e?1:0}function l(t,e,r){let s=Array.isArray(r)?r:[r],o=Array.from(new Set(s.map(a=>a.trim()))).filter(a=>a.length).sort(E);if(!o.length){t.delete(e);return}t.set(e,o.join(", "))}function H(t,e,r){let s=Array.isArray(r)?r:[r];if(s.length===0)return;let a=T(t,e).concat(s.map(p=>p.trim()));l(t,e,a)}function T(t,e){let r=t.get(e)?.split(",").map(s=>s.trim()).filter(s=>s.length>0)??[];return Array.from(new Set(r)).sort(E)}function Q(t){let e=t.headers.get(i.ORIGIN)?.trim();if(!e||e==="null")return null;try{return new URL(e).origin}catch{return null}}function Oe(t){let e=new URL(t.url),r=new URLSearchParams([...e.searchParams.entries()].sort(([s],[o])=>E(s,o)));return e.search=r.toString(),e.hash="",e}function $t(t){let e=new URL(t.url);return e.search="",e.hash="",e}var Qe=new Set(["text/css","text/csv","text/xml","image/svg+xml","text/html","application/json","application/x-ndjson","application/xml","text/markdown","text/richtext","text/plain","application/x-www-form-urlencoded"]);function Re(t){return Qe.has(t)?`${t}; charset=utf-8`:t}var et="https://vary";function ge(t){return!(!t.ok||ee(t).includes("*"))}function ee(t){let e=T(t.headers,i.VARY);return Array.from(new Set(e.map(r=>r.toLowerCase()))).sort(E)}function te(t){return t.map(e=>e.toLowerCase()).filter(e=>e!==i.ACCEPT_ENCODING.toLowerCase())}function re(t,e,r){let s=[],o=te(e);o.sort(E);for(let p of o){let u=t.headers.get(p);u!==null&&s.push([p,u])}let a=tt(JSON.stringify([r.toString(),s]));return new URL(a,et).href}function tt(t){let e=new TextEncoder().encode(t),r="";for(let s of e)r+=String.fromCodePoint(s);return btoa(r).replaceAll("+","-").replaceAll("/","_").replace(/={1,2}$/,"")}function pr(t,e){return Se(t),Ae(e),new se(t,e)}var se=class extends h{constructor(r,s){super();this.cacheName=r;this.getKey=s;this.cacheName=r?.trim()||void 0}async handle(r,s){if(r.request.method!==f)return s();let o=this.cacheName?await caches.open(this.cacheName):caches.default,a=await this.getCached(o,r.request);if(a)return a;let p=await s();return this.setCached(o,r,p),p}async getCached(r,s){let o=this.getCacheKey(s),a=await r.match(o);if(!a)return;let p=this.getFilteredVary(a);if(p.length===0)return a;let u=re(s,p,o);return r.match(u)}async setCached(r,s,o){if(!ge(o))return;let a=this.getCacheKey(s.request);s.ctx.waitUntil(r.put(a,o.clone()));let p=this.getFilteredVary(o);p.length>0&&s.ctx.waitUntil(r.put(re(s.request,p,a),o.clone()))}getFilteredVary(r){return te(ee(r))}getCacheKey(r){let s=this.getKey?this.getKey(r):Oe(r);return xe(s),s.hash="",s}};import{getReasonPhrase as rt,StatusCodes as S}from"http-status-codes";var oe=class{headers=new Headers;status=S.OK;statusText;webSocket=null;mediaType="text/plain";get responseInit(){return{headers:this.headers,status:this.status,statusText:this.statusText??rt(this.status),webSocket:this.webSocket,encodeBody:"automatic"}}setHeader(e,r){l(this.headers,e,r)}mergeHeader(e,r){H(this.headers,e,r)}addContentType(){this.headers.get(i.CONTENT_TYPE)||this.headers.set(i.CONTENT_TYPE,Re(this.mediaType))}},ne=class extends oe{constructor(r){super();this.cache=r}addCacheHeader(){this.cache&&this.headers.set(i.CACHE_CONTROL,I.stringify(this.cache))}},_=class extends ne{constructor(r=null,s){super(s);this.body=r}async response(){this.addCacheHeader();let r=this.status===S.NO_CONTENT?null:this.body;return r&&this.addContentType(),new Response(r,this.responseInit)}},U=class extends _{constructor(e,r){let s=e.clone();super(s.body,r),this.headers=new Headers(s.headers),this.status=s.status,this.statusText=s.statusText}},w=class extends _{constructor(e=null,r,s=S.OK){super(e,r),this.status=s}},G=class extends w{constructor(e={},r,s=S.OK){super(JSON.stringify(e),r,s),this.mediaType="application/json"}},be=class extends w{constructor(e,r,s=S.OK){super(e,r,s),this.mediaType="text/html"}},Te=class extends w{constructor(e,r,s=S.OK){super(e,r,s),this.mediaType="text/plain"}},_e=class extends _{constructor(e){super(null),this.status=S.SWITCHING_PROTOCOLS,this.webSocket=e}},V=class extends _{constructor(e){super(),this.status=e.status,this.statusText=e.statusText,this.headers=new Headers(e.headers)}},L=class extends w{constructor(){super(null,void 0,S.NO_CONTENT)}};var K="*",we=new Set([f,k,g]),Le=[m.SWITCHING_PROTOCOLS,m.CONTINUE,m.PROCESSING,m.EARLY_HINTS,m.MOVED_PERMANENTLY,m.MOVED_TEMPORARILY,m.SEE_OTHER,m.TEMPORARY_REDIRECT,m.PERMANENT_REDIRECT],Ne={allowedOrigins:[K],allowedHeaders:[i.CONTENT_TYPE],exposedHeaders:[],allowCredentials:!1,maxAge:5*ue.Minute};async function ve(t,e){let r=new L,s=Q(t.request);return s&&(ye(r.headers,e,s),Ie(r.headers,e,s)),st(r.headers,t),nt(r.headers,e),ot(r.headers,e),r.response()}async function Pe(t,e,r){let s=new U(t),o=Q(e.request);return at(s.headers),o&&(ye(s.headers,r,o),Ie(s.headers,r,o),it(s.headers,r)),s.response()}function ye(t,e,r){We(e)?l(t,i.ACCESS_CONTROL_ALLOW_ORIGIN,K):(e.allowedOrigins.includes(r)&&l(t,i.ACCESS_CONTROL_ALLOW_ORIGIN,r),H(t,i.VARY,i.ORIGIN))}function Ie(t,e,r){e.allowCredentials&&(We(e)||e.allowedOrigins.includes(r)&&l(t,i.ACCESS_CONTROL_ALLOW_CREDENTIALS,"true"))}function st(t,e){let r=e.getAllowedMethods();b(r);let s=r.filter(o=>!we.has(o));s.length>0&&l(t,i.ACCESS_CONTROL_ALLOW_METHODS,s)}function ot(t,e){let r=Math.max(0,Math.floor(e.maxAge));l(t,i.ACCESS_CONTROL_MAX_AGE,String(r))}function nt(t,e){e.allowedHeaders.length>0&&l(t,i.ACCESS_CONTROL_ALLOW_HEADERS,e.allowedHeaders)}function it(t,e){l(t,i.ACCESS_CONTROL_EXPOSE_HEADERS,e.exposedHeaders)}function We(t){return t.allowedOrigins.includes(K)}function at(t){t.delete(i.ACCESS_CONTROL_MAX_AGE),t.delete(i.ACCESS_CONTROL_ALLOW_ORIGIN),t.delete(i.ACCESS_CONTROL_ALLOW_HEADERS),t.delete(i.ACCESS_CONTROL_ALLOW_METHODS),t.delete(i.ACCESS_CONTROL_EXPOSE_HEADERS),t.delete(i.ACCESS_CONTROL_ALLOW_CREDENTIALS)}function ke(t){let{status:e,headers:r}=t;return!!(Le.includes(e)||r.has(i.UPGRADE))}function De(t){if(t===void 0)return;if(typeof t!="object"||t===null)throw new TypeError("CorsInit must be an object.");let e=t;if(e.allowedOrigins!==void 0&&!D(e.allowedOrigins))throw new TypeError("CorsInit.allowedOrigins must be a string array.");if(e.allowedHeaders!==void 0&&!D(e.allowedHeaders))throw new TypeError("CorsInit.allowedHeaders must be a string array.");if(e.exposedHeaders!==void 0&&!D(e.exposedHeaders))throw new TypeError("CorsInit.exposedHeaders must be a string array.");if(e.allowCredentials!==void 0&&!Ee(e.allowCredentials))throw new TypeError("CorsInit.allowCredentials must be a boolean.");if(e.maxAge!==void 0&&!M(e.maxAge))throw new TypeError("CorsInit.maxAge must be a number.")}function kr(t){return De(t),new ie(t)}var ie=class extends h{config;constructor(e){super(),this.config={...Ne,...e}}async handle(e,r){if(e.request.method===g)return ve(e,this.config);let s=await r();return ke(s)?s:Pe(s,e,this.config)}};import{getReasonPhrase as ct,StatusCodes as C}from"http-status-codes";var d=class extends G{constructor(r,s){let o={status:r,error:ct(r),details:s??""};super(o,I.DISABLE,r);this.details=s}},P=class extends d{constructor(e){super(C.BAD_REQUEST,e)}},Me=class extends d{constructor(e){super(C.UNAUTHORIZED,e)}},He=class extends d{constructor(e){super(C.FORBIDDEN,e)}},A=class extends d{constructor(e){super(C.NOT_FOUND,e)}},y=class extends d{constructor(e){let r=e.getAllowedMethods();b(r),super(C.METHOD_NOT_ALLOWED,`${e.request.method} method not allowed.`),this.setHeader(i.ALLOW,r)}},q=class extends d{constructor(){super(C.UPGRADE_REQUIRED),this.headers.set(i.SEC_WEBSOCKET_VERSION,"13")}},B=class extends d{constructor(e){super(C.INTERNAL_SERVER_ERROR,e)}},ae=class extends d{constructor(e){super(C.NOT_IMPLEMENTED,e)}},x=class extends ae{constructor(e){super(`${e.request.method} method not implemented.`)}},Ue=class extends d{constructor(e){super(C.SERVICE_UNAVAILABLE,e)}};function Ge(t){return T(t,i.CONNECTION).some(e=>e.toLowerCase()===le)}function Ve(t){return T(t,i.UPGRADE).some(e=>e.toLowerCase()===de)}function Ke(t){return t.get(i.SEC_WEBSOCKET_VERSION)?.trim()==="13"}function $r(t="/"){return new ce(t)}var ce=class extends h{constructor(r){super();this.path=r}handle(r,s){if(r.request.method!==f||this.getPath(r.request)!==this.path)return s();let o=r.request.headers;return Ge(o)?Ve(o)?Ke(o)?s():new q().response():new P("Missing or invalid Upgrade header").response():new P("Missing or invalid Connection header").response()}getPath(r){return new URL(r.url).pathname}};function pt(t){return t instanceof ArrayBuffer||ArrayBuffer.isView(t)}function qe(t){return R(t)?t.length>0:pt(t)?t.byteLength>0:!1}function Be(t){return M(t)?ut(t)&&!lt(t)?t:O.NORMAL:O.NORMAL}function ut(t){return t>=O.NORMAL&&t<=4999}function lt(t){return fe.has(t)}function Xe(t){if(R(t))return t.replaceAll(/[^\x20-\x7E]/g,"").slice(0,123)}function Ye(t){if(t===null||typeof t!="object")throw new TypeError("WebSocket attachment must be a non-null object");try{JSON.stringify(t)}catch{throw new TypeError("WebSocket attachment is non-serializable")}}var X=class t{server;static isCustomEvent(e){return["open","warn"].includes(e)}customListeners={};constructor(e){this.server=e}addEventListener(e,r,s){if(t.isCustomEvent(e)){let o=this.customListeners[e];o||(o=[],this.customListeners[e]=o),o.push(r)}else{let o=e==="close"?{...s,once:!0}:s;this.server.addEventListener(e,r,o)}}removeEventListener(e,r){if(t.isCustomEvent(e)){let s=this.customListeners[e];if(s){let o=s.indexOf(r);o!==-1&&s.splice(o,1)}}else this.server.removeEventListener(e,r)}dispatch(e,r,s=!1){let o=this.customListeners[e]?.slice()??[];s&&(this.customListeners[e]=[]);for(let a of o)a(r)}warn(e){this.dispatch("warn",{type:"warn",message:e})}open(){this.dispatch("open",new Event("open"),!0)}};var N=class extends X{accepted=!1;server;constructor(e){super(e),this.server=e,this.server.addEventListener("close",this.onclose)}send(e){if(this.isState(WebSocket.CONNECTING,WebSocket.CLOSED)){this.warn("Cannot send: WebSocket not open");return}if(!qe(e)){this.warn("Cannot send: empty or invalid data");return}this.server.send(e)}get attachment(){return this.server.deserializeAttachment()??{}}attach(e){e!==void 0&&(e===null?this.server.serializeAttachment({}):(Ye(e),this.server.serializeAttachment(e)))}get readyState(){return this.accepted?this.server.readyState:WebSocket.CONNECTING}isState(...e){return e.includes(this.readyState)}close(e,r){this.server.removeEventListener("close",this.onclose),this.server.close(Be(e),Xe(r))}onclose=e=>{this.close(e.code,e.reason)}};var Y=class extends N{client;constructor(){let e=new WebSocketPair,[r,s]=[e[0],e[1]];super(s),this.client=r}acceptWebSocket(e,r){return e.acceptWebSocket(this.server,r),this.ready()}accept(){return this.server.accept(),this.ready()}ready(){return this.accepted=!0,this.open(),this.client}};var F=class extends N{constructor(e){super(e),this.accepted=!0}accept(){throw new Error("Do not call accept() on restore")}acceptWebSocket(){throw new Error("Do not call acceptWebSocket() on restore")}};var Fe=class{map=new Map;create(e){class r extends Y{constructor(p){super();this.sessions=p}accept(){return this.addEventListener("close",()=>this.sessions.unregister(this.server)),this.sessions.register(this.server,this),super.accept()}acceptWebSocket(p,u){return this.sessions.register(this.server,this),super.acceptWebSocket(p,u)}}let s=new r(this);return s.attach(e),s}restore(e){class r extends F{constructor(o,a){super(a),o.register(this.server,this)}}return new r(this,e)}restoreAll(e){let r=[];for(let s of e)r.push(this.restore(s));return r}get(e){return this.map.get(e)}values(){return this.map.values()}keys(){return this.map.keys()}close(e,r,s){let o=this.get(e);return o&&o.close(r,s),this.unregister(e)}*[Symbol.iterator](){yield*this.values()}register(e,r){this.map.set(e,r)}unregister(e){return this.map.delete(e)}};var v=class{constructor(e,r,s){this._request=e;this._env=r;this._ctx=s}get request(){return this._request}get env(){return this._env}get ctx(){return this._ctx}isAllowed(e){let r=this.getAllowedMethods();return b(r),Z(e)&&r.includes(e)}create(e){let r=this.constructor;return new r(e,this.env,this.ctx)}async response(e,...r){return new e(...r).response()}static ignite(){return{fetch:(e,r,s)=>new this(e,r,s).fetch()}}};function je(t){if(!(t instanceof h))throw new TypeError("Handler must be a subclass of Middleware.")}var j=class extends v{middlewares=[];init(){}use(e){return je(e),this.middlewares.push(e),this}async fetch(){return await this.middlewares.reduceRight((r,s)=>()=>s.handle(this,r),()=>this.dispatch())()}};var J=class extends j{async fetch(){if(!this.isAllowed(this.request.method))return this.response(y,this);try{return await this.init(),await super.fetch()}catch(e){return console.error(e),this.response(B)}}async dispatch(){let e=this.request.method;return({GET:()=>this.get(),PUT:()=>this.put(),HEAD:()=>this.head(),POST:()=>this.post(),PATCH:()=>this.patch(),DELETE:()=>this.delete(),OPTIONS:()=>this.options()}[e]??(()=>this.response(y,this)))()}async get(){return this.response(x,this)}async put(){return this.response(x,this)}async post(){return this.response(x,this)}async patch(){return this.response(x,this)}async delete(){return this.response(x,this)}async options(){return this.response(L)}async head(){let e=this.create(new Request(this.request.url,{method:f,headers:this.request.headers}));return this.response(V,await e.fetch())}getAllowedMethods(){return[f,k,g]}};import{match as dt}from"path-to-regexp";var z=class{routes=[];add(e){for(let[r,s,o]of e){let a=dt(s);this.routes.push({method:r,matcher:a,handler:o})}}match(e,r){let s=new URL(r).pathname;for(let o of this){if(o.method!==e)continue;let a=o.matcher(s);if(a)return{route:o,params:a.params}}return null}*[Symbol.iterator](){yield*this.routes}};var Je=class t extends J{_routes=new z;route(e,r,s){return this.routes([[e,r,s]]),this}routes(e){return this._routes.add(e),this}async dispatch(){let e=this._routes.match(this.request.method,this.request.url);if(!e)return super.dispatch();let{handler:r}=e.route;return t.isWorkerClass(r)?new r(this.request,this.env,this.ctx).fetch():r.call(this,e.params)}static isWorkerClass(e){return v.prototype.isPrototypeOf(e.prototype)}async get(){return this.response(A)}async put(){return this.response(A)}async post(){return this.response(A)}async patch(){return this.response(A)}async delete(){return this.response(A)}};export{P as BadRequest,J as BasicWorker,I as CacheControl,U as ClonedResponse,O as CloseCode,It as DELETE,He as Forbidden,f as GET,k as HEAD,V as Head,be as HtmlResponse,d as HttpError,i as HttpHeader,B as InternalServerError,G as JsonResponse,ze as MediaType,W as Method,y as MethodNotAllowed,x as MethodNotImplemented,A as NotFound,ae as NotImplemented,g as OPTIONS,L as Options,yt as PATCH,Pt as POST,vt as PUT,Je as RouteWorker,Ue as ServiceUnavailable,m as StatusCodes,w as SuccessResponse,Te as TextResponse,ue as Time,Me as Unauthorized,q as UpgradeRequired,me as WS_MAX_CLOSE_CODE,he as WS_MAX_REASON_CHARS,fe as WS_RESERVED_CODES,le as WS_UPGRADE,$ as WS_VERSION,de as WS_WEBSOCKET,Fe as WebSocketSessions,_e as WebSocketUpgrade,_ as WorkerResponse,b as assertMethods,pr as cache,kr as cors,Re as getContentType,T as getHeaderValues,Q as getOrigin,Z as isMethod,Ze as isMethodArray,E as lexCompare,H as mergeHeader,l as setHeader,Oe as sortSearchParams,$t as stripSearchParams,$r as websocket};
1452
2
  //# sourceMappingURL=index.js.map