@sourceregistry/node-webserver 1.0.0

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.
@@ -0,0 +1,936 @@
1
+ import { createReadStream as k } from "node:fs";
2
+ import { stat as W, realpath as L, lstat as I } from "node:fs/promises";
3
+ import { sep as D, resolve as O, relative as $, isAbsolute as U, extname as F } from "node:path";
4
+ import { Readable as z } from "node:stream";
5
+ import { createServer as B } from "http";
6
+ import { createServer as q } from "https";
7
+ import { TLSSocket as X } from "tls";
8
+ import { Readable as G, Transform as J, Writable as V } from "stream";
9
+ import { WebSocketServer as K, WebSocket as P } from "ws";
10
+ import { parse as E, serialize as Y } from "cookie";
11
+ const Q = {
12
+ ".avif": "image/avif",
13
+ ".css": "text/css; charset=utf-8",
14
+ ".gif": "image/gif",
15
+ ".html": "text/html; charset=utf-8",
16
+ ".ico": "image/x-icon",
17
+ ".jpg": "image/jpeg",
18
+ ".jpeg": "image/jpeg",
19
+ ".js": "text/javascript; charset=utf-8",
20
+ ".json": "application/json; charset=utf-8",
21
+ ".mjs": "text/javascript; charset=utf-8",
22
+ ".pdf": "application/pdf",
23
+ ".png": "image/png",
24
+ ".svg": "image/svg+xml; charset=utf-8",
25
+ ".txt": "text/plain; charset=utf-8",
26
+ ".wasm": "application/wasm",
27
+ ".webp": "image/webp",
28
+ ".xml": "application/xml; charset=utf-8"
29
+ }, Z = {
30
+ index: "index.html",
31
+ cacheControl: "public, max-age=0",
32
+ dotFiles: "ignore"
33
+ };
34
+ async function ee(a, e, t = {}) {
35
+ const s = oe(e), r = {
36
+ ...Z,
37
+ ...t
38
+ }, n = await te(a), o = se(s, r.dotFiles);
39
+ if (o instanceof Response)
40
+ return o;
41
+ const i = o.length > 0 ? o.join(D) : "", u = O(n, i);
42
+ if (!v(n, u))
43
+ return new Response("Forbidden", { status: 403 });
44
+ const c = await re(u, n, r.index);
45
+ if (c instanceof Response)
46
+ return c;
47
+ const l = await W(c), d = new Headers({
48
+ "content-length": String(l.size),
49
+ "content-type": ne(c),
50
+ "cache-control": r.cacheControl,
51
+ "last-modified": l.mtime.toUTCString(),
52
+ "x-content-type-options": "nosniff"
53
+ });
54
+ if (t.headers) {
55
+ const h = typeof t.headers == "function" ? t.headers(c, l) : t.headers;
56
+ new Headers(h).forEach((f, y) => {
57
+ d.set(y, f);
58
+ });
59
+ }
60
+ return new Response(z.toWeb(k(c)), {
61
+ status: 200,
62
+ headers: d
63
+ });
64
+ }
65
+ async function te(a) {
66
+ return L(a);
67
+ }
68
+ function se(a, e) {
69
+ if (a.includes("\0"))
70
+ return new Response("Bad Request", { status: 400 });
71
+ const t = a.replace(/\\/g, "/").split("/").filter(Boolean), s = [];
72
+ for (const r of t) {
73
+ let n;
74
+ try {
75
+ n = decodeURIComponent(r);
76
+ } catch {
77
+ return new Response("Bad Request", { status: 400 });
78
+ }
79
+ if (!(!n || n === ".")) {
80
+ if (n === ".." || n.includes("/") || n.includes("\\") || n.includes("\0"))
81
+ return new Response("Forbidden", { status: 403 });
82
+ if (n.startsWith(".")) {
83
+ if (e === "deny")
84
+ return new Response("Forbidden", { status: 403 });
85
+ if (e !== "allow")
86
+ return new Response("Not Found", { status: 404 });
87
+ }
88
+ s.push(n);
89
+ }
90
+ }
91
+ return s;
92
+ }
93
+ async function re(a, e, t) {
94
+ try {
95
+ if ((await I(a)).isDirectory()) {
96
+ const r = O(a, t);
97
+ return T(r, e);
98
+ }
99
+ return T(a, e);
100
+ } catch {
101
+ return new Response("Not Found", { status: 404 });
102
+ }
103
+ }
104
+ async function T(a, e) {
105
+ try {
106
+ const t = await L(a);
107
+ return v(e, t) ? (await W(t)).isFile() ? t : new Response("Not Found", { status: 404 }) : new Response("Forbidden", { status: 403 });
108
+ } catch {
109
+ return new Response("Not Found", { status: 404 });
110
+ }
111
+ }
112
+ function v(a, e) {
113
+ const t = $(a, e);
114
+ return t === "" || !t.startsWith("..") && !U(t);
115
+ }
116
+ function ne(a) {
117
+ return Q[F(a).toLowerCase()] ?? "application/octet-stream";
118
+ }
119
+ function oe(a) {
120
+ return typeof a.params.path == "string" ? a.params.path : a.url.pathname.replace(/^\/+/, "");
121
+ }
122
+ function _(a) {
123
+ return a instanceof Response && a.status >= 400 && a.status < 600;
124
+ }
125
+ function N(a) {
126
+ return a instanceof Response && a.status >= 300 && a.status < 400;
127
+ }
128
+ class ae {
129
+ constructor(e) {
130
+ this.data = /* @__PURE__ */ new Map(), this.windowMs = e.windowMs, this.startCleanup();
131
+ }
132
+ async incr(e) {
133
+ const t = Date.now();
134
+ let s = this.data.get(e);
135
+ return !s || t >= s.reset ? (s = { count: 1, reset: t + this.windowMs }, this.data.set(e, s)) : s.count++, { current: s.count, reset: s.reset };
136
+ }
137
+ startCleanup() {
138
+ this.cleanupInterval = setInterval(() => {
139
+ const e = Date.now();
140
+ for (const [t, { reset: s }] of this.data)
141
+ e >= s && this.data.delete(t);
142
+ }, Math.min(this.windowMs, 3e5));
143
+ }
144
+ stop() {
145
+ this.cleanupInterval && clearInterval(this.cleanupInterval);
146
+ }
147
+ async resetAll() {
148
+ this.data.clear();
149
+ }
150
+ }
151
+ function ie(a) {
152
+ const {
153
+ windowMs: e = 6e4,
154
+ max: t,
155
+ key: s = (c) => c.getClientAddress(),
156
+ message: r = "Too many requests, please try again later.",
157
+ statusCode: n = 429,
158
+ headers: o = "include",
159
+ onRateLimit: i,
160
+ store: u = new ae({ windowMs: e })
161
+ } = a;
162
+ return async (c, l) => {
163
+ const d = `rl:${s(c)}`, { current: h, reset: f } = await u.incr(d), y = Math.ceil((f - Date.now()) / 1e3);
164
+ if (h > t) {
165
+ i && i(c, { current: h, max: t, key: d });
166
+ const w = {
167
+ status: n,
168
+ headers: new Headers()
169
+ }, p = w.headers;
170
+ o === "include" && (p.set("X-RateLimit-Limit", String(t)), p.set("X-RateLimit-Remaining", "0"), p.set("X-RateLimit-Reset", String(Math.floor(f / 1e3))), p.set("Retry-After", String(y)));
171
+ let m;
172
+ return typeof r == "string" ? (m = r, p.set("Content-Type", "text/plain")) : (m = JSON.stringify(r), p.set("Content-Type", "application/json")), new Response(m, w);
173
+ }
174
+ if (c.rateLimit = {
175
+ current: h,
176
+ limit: t,
177
+ reset: new Date(f),
178
+ remaining: t - h
179
+ }, o === "include") {
180
+ const w = {
181
+ "X-RateLimit-Limit": String(t),
182
+ "X-RateLimit-Remaining": String(t - h),
183
+ "X-RateLimit-Reset": String(Math.floor(f / 1e3))
184
+ }, p = c.setHeaders;
185
+ c.setHeaders = (m) => {
186
+ p({
187
+ ...w,
188
+ ...m
189
+ });
190
+ }, p(w);
191
+ }
192
+ return l();
193
+ };
194
+ }
195
+ const Ee = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
196
+ __proto__: null,
197
+ fixedWindowLimit: ie
198
+ }, Symbol.toStringTag, { value: "Module" })), ce = [
199
+ "GET",
200
+ "POST",
201
+ "PUT",
202
+ "DELETE",
203
+ "PATCH",
204
+ "HEAD",
205
+ "OPTIONS"
206
+ ], ue = [
207
+ "Accept",
208
+ "Accept-Language",
209
+ "Content-Language",
210
+ "Content-Type",
211
+ "Range"
212
+ ], le = [
213
+ "Authorization",
214
+ "X-Auth-Token",
215
+ "X-Requested-With",
216
+ "X-CSRF-Token",
217
+ "X-HTTP-Method-Override",
218
+ "X-Forwarded-For",
219
+ "X-Real-IP",
220
+ "X-Custom-Header"
221
+ ];
222
+ function j(a, e) {
223
+ return !a || !e ? !1 : e === "*" ? !0 : e === "null" ? a === "null" : Array.isArray(e) ? e.some((t) => j(a, t)) : typeof e == "function" ? e(a) : e instanceof RegExp ? e.test(a) : a === e;
224
+ }
225
+ function de(a, e) {
226
+ const { origin: t = "*" } = e;
227
+ return a ? t === "*" ? e.credentials ? a : "*" : j(a, t) ? a : null : t === "*" ? "*" : null;
228
+ }
229
+ function he(a = {}) {
230
+ const {
231
+ methods: e = ce,
232
+ allowedHeaders: t = le,
233
+ exposedHeaders: s,
234
+ credentials: r = !1,
235
+ maxAge: n = 86400,
236
+ onResponse: o
237
+ } = a, i = "Origin,Access-Control-Request-Method,Access-Control-Request-Headers", u = e.join(","), c = [...ue, ...t].join(","), l = [
238
+ ["Vary", i],
239
+ ["Access-Control-Allow-Methods", u],
240
+ ["Access-Control-Allow-Headers", c]
241
+ ];
242
+ return s && l.push(["Access-Control-Expose-Headers", s.join(",")]), r && l.push(["Access-Control-Allow-Credentials", "true"]), n && l.push(["Access-Control-Max-Age", n.toString()]), async (d, h) => {
243
+ const f = d.request, y = f.headers.get("Origin"), w = f.method === "OPTIONS" && y !== null && f.headers.has("Access-Control-Request-Method"), p = de(y, a);
244
+ if (w) {
245
+ if (!p)
246
+ return new Response(null, { status: 403 });
247
+ const g = new Response(null, { status: 204 });
248
+ for (const [H, M] of l)
249
+ g.headers.set(H, M);
250
+ return g.headers.set("Access-Control-Allow-Origin", p), g;
251
+ }
252
+ const m = await h();
253
+ if (!m) return;
254
+ if (!p) return m;
255
+ const S = new Response(m.body, m);
256
+ for (const [g, H] of l)
257
+ S.headers.set(g, H);
258
+ S.headers.set("Access-Control-Allow-Origin", p);
259
+ let A = S;
260
+ if (o) {
261
+ const g = o(A);
262
+ g && (A = g);
263
+ }
264
+ return A;
265
+ };
266
+ }
267
+ const Te = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
268
+ __proto__: null,
269
+ policy: he
270
+ }, Symbol.toStringTag, { value: "Module" })), fe = ["GET", "PUT", "POST", "DELETE", "PATCH", "HEAD", "OPTIONS"];
271
+ class b {
272
+ static {
273
+ this.cache = /* @__PURE__ */ new Map();
274
+ }
275
+ static get(e) {
276
+ return this.cache.get(e);
277
+ }
278
+ static set(e, t) {
279
+ this.cache.set(e, t);
280
+ }
281
+ }
282
+ class x {
283
+ constructor() {
284
+ this._routes = [], this._wsRoutes = [], this._nestedRouters = [], this._middlewares = [], this._preHandlers = [], this._postHandlers = [], this.routesSorted = !1, this.wsRoutesSorted = !1;
285
+ }
286
+ get routes() {
287
+ return this._routes;
288
+ }
289
+ get nestedRouters() {
290
+ return this._nestedRouters;
291
+ }
292
+ // HTTP method handlers
293
+ GET(e, t, ...s) {
294
+ return this.addHandler("GET", e, t, s);
295
+ }
296
+ POST(e, t, ...s) {
297
+ return this.addHandler("POST", e, t, s);
298
+ }
299
+ PUT(e, t, ...s) {
300
+ return this.addHandler("PUT", e, t, s);
301
+ }
302
+ PATCH(e, t, ...s) {
303
+ return this.addHandler("PATCH", e, t, s);
304
+ }
305
+ DELETE(e, t, ...s) {
306
+ return this.addHandler("DELETE", e, t, s);
307
+ }
308
+ HEAD(e, t, ...s) {
309
+ return this.addHandler("HEAD", e, t, s);
310
+ }
311
+ OPTIONS(e, t, ...s) {
312
+ return this.addHandler("OPTIONS", e, t, s);
313
+ }
314
+ // Universal method
315
+ USE(e, t, ...s) {
316
+ return fe.forEach((r) => this.addHandler(r, e, t, s)), this;
317
+ }
318
+ // Action handler (POST only)
319
+ action(e, t, ...s) {
320
+ const r = async (n) => {
321
+ try {
322
+ const o = await t(n);
323
+ return this.formatActionResult(o);
324
+ } catch (o) {
325
+ return this.handleActionError(o);
326
+ }
327
+ };
328
+ return this.addHandler("POST", e, r, s);
329
+ }
330
+ use(e, t, ...s) {
331
+ let r, n, o = s;
332
+ Array.isArray(e) ? ([r, n] = e, o = e.length > 2 ? e.slice(2) : []) : (r = e, n = t);
333
+ const i = this.normalizePrefix(r), { regex: u, paramNames: c, isCatchAll: l, priority: d } = this.createPrefixRegex(i);
334
+ return this._nestedRouters.push({
335
+ prefix: i,
336
+ router: n,
337
+ regex: u,
338
+ paramNames: c,
339
+ isCatchAll: l,
340
+ priority: d,
341
+ middlewares: o
342
+ }), this;
343
+ }
344
+ // Global middleware
345
+ useMiddleware(...e) {
346
+ return this._middlewares.push(...e), this;
347
+ }
348
+ pre(...e) {
349
+ return this._preHandlers.push(...e), this;
350
+ }
351
+ post(...e) {
352
+ return this._postHandlers.push(...e), this;
353
+ }
354
+ // Discard routes or nested routers
355
+ discard(e, t) {
356
+ return this._nestedRouters = this._nestedRouters.filter((s) => s.prefix !== e), this._routes = this._routes.filter(
357
+ (s) => s.path !== e || t && s.method !== t
358
+ ), this;
359
+ }
360
+ // WebSocket route
361
+ WS(e, t, ...s) {
362
+ const { regex: r, paramNames: n, isCatchAll: o, priority: i } = this.createPathRegex(e);
363
+ return this._wsRoutes.push({
364
+ path: e,
365
+ regex: r,
366
+ paramNames: n,
367
+ isCatchAll: o,
368
+ priority: i,
369
+ handler: t,
370
+ middlewares: s
371
+ }), this.wsRoutesSorted = !1, this;
372
+ }
373
+ // Add this method to your Router class
374
+ /**
375
+ * Check if the router can handle a WebSocket connection for the given path
376
+ * This is used during the upgrade process to validate routes before attempting connection
377
+ */
378
+ async canHandleWebSocket(e) {
379
+ return this.canHandleWebSocketAtPath(e, e.url.pathname);
380
+ }
381
+ async canHandleWebSocketAtPath(e, t) {
382
+ this.wsRoutesSorted || this.sortWsRoutes();
383
+ for (const s of [...this._nestedRouters].sort((r, n) => n.priority - r.priority)) {
384
+ const r = t.match(s.regex);
385
+ if (!r || r.index !== 0) continue;
386
+ const n = r[0], o = t.slice(n.length) || "/", i = {
387
+ ...e,
388
+ params: { ...e.params, ...this.extractPrefixParams(s, n) }
389
+ };
390
+ if (await s.router.canHandleWebSocketAtPath(i, o))
391
+ return !0;
392
+ }
393
+ for (const s of this._wsRoutes)
394
+ if (s.regex.test(t))
395
+ return !0;
396
+ return !1;
397
+ }
398
+ // Handle WebSocket upgrade
399
+ async handleWebSocket(e, t) {
400
+ return this.handleWebSocketAtPath(e, t, e.url.pathname);
401
+ }
402
+ async handleWebSocketAtPath(e, t, s) {
403
+ this.wsRoutesSorted || this.sortWsRoutes();
404
+ for (const r of [...this._nestedRouters].sort((n, o) => o.priority - n.priority)) {
405
+ const n = s.match(r.regex);
406
+ if (!n || n.index !== 0) continue;
407
+ const o = n[0], i = s.slice(o.length) || "/", u = this.extractPrefixParams(r, o), c = {
408
+ ...e,
409
+ params: { ...e.params, ...u }
410
+ }, l = [...this._middlewares, ...r.middlewares], d = () => r.router.handleWebSocketAtPath(c, t, i);
411
+ if (await this.applyMiddlewaresWithList(c, l, d)) return !0;
412
+ }
413
+ for (const r of this._wsRoutes) {
414
+ if (!r.regex.test(s)) continue;
415
+ const n = s.match(r.regex);
416
+ if (!n) continue;
417
+ const o = Object.fromEntries(
418
+ r.paramNames.map((l, d) => [l, n[d + 1] || ""])
419
+ ), i = {
420
+ ...e,
421
+ params: { ...e.params, ...o },
422
+ route: { ...e.route, id: r.path },
423
+ websocket: t
424
+ }, u = [...this._middlewares, ...r.middlewares];
425
+ if (await this.applyMiddlewaresWithList(i, u, () => r.handler(i)) === void 0)
426
+ return !0;
427
+ }
428
+ return !1;
429
+ }
430
+ // Handle HTTP request - FIXED: Single middleware application
431
+ async handle(e) {
432
+ return this.handleAtPath(e, e.url.pathname);
433
+ }
434
+ async handleAtPath(e, t) {
435
+ const s = e.request.method;
436
+ let r = await this.runPreHandlers(e);
437
+ if (!r) {
438
+ const o = async () => {
439
+ const i = await this.handleNestedRouters(e, t);
440
+ return i || (this.routesSorted || this.sortRoutes(), this.handleLocalRoutes(e, s, t));
441
+ };
442
+ r = await this.applyMiddlewaresWithList(e, this._middlewares, o);
443
+ }
444
+ const n = r || new Response("No Content", { status: 204 });
445
+ return this.runPostHandlers(e, n);
446
+ }
447
+ // Apply middlewares utility
448
+ async applyMiddlewaresWithList(e, t, s) {
449
+ const r = [...t], n = async (o) => o >= r.length ? s() : r[o](e, () => n(o + 1));
450
+ return n(0);
451
+ }
452
+ async runPreHandlers(e) {
453
+ for (const t of this._preHandlers) {
454
+ const s = await t(e);
455
+ if (s instanceof Response)
456
+ return s;
457
+ }
458
+ }
459
+ async runPostHandlers(e, t) {
460
+ let s = t;
461
+ for (const r of this._postHandlers) {
462
+ const n = await r(e, s);
463
+ n instanceof Response && (s = n);
464
+ }
465
+ return s;
466
+ }
467
+ // Add route handler
468
+ addHandler(e, t, s, r = []) {
469
+ const { regex: n, paramNames: o, isCatchAll: i, priority: u } = this.createPathRegex(t);
470
+ return this._routes.push({
471
+ method: e,
472
+ path: t,
473
+ regex: n,
474
+ paramNames: o,
475
+ isCatchAll: i,
476
+ priority: u,
477
+ handler: s,
478
+ middlewares: r
479
+ }), this.routesSorted = !1, this;
480
+ }
481
+ // Create regex for route path
482
+ createPathRegex(e) {
483
+ const t = b.get(e);
484
+ if (t) return t;
485
+ const s = [];
486
+ let r = !1, n;
487
+ const o = e.split("/").filter(Boolean);
488
+ n = o.reduce((c, l) => l.startsWith("[...") ? c - 10 : l.startsWith("[[") ? c - 5 : l.startsWith("[") ? c - 1 : c + 1, 0);
489
+ let i = "^";
490
+ for (const c of o)
491
+ if (c.startsWith("[...") && c.endsWith("]")) {
492
+ r = !0;
493
+ const l = c.slice(4, -1);
494
+ s.push(l), i += "/(.+)";
495
+ } else if (c.startsWith("[[") && c.endsWith("]]")) {
496
+ const l = c.slice(2, -2);
497
+ s.push(l), i += "(?:/([^/]+))?";
498
+ } else if (c.startsWith("[") && c.endsWith("]")) {
499
+ const l = c.slice(1, -1);
500
+ s.push(l), i += "/([^/]+)";
501
+ } else
502
+ i += "/" + c.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
503
+ i += "/?$";
504
+ const u = { regex: new RegExp(i), paramNames: s, isCatchAll: r, priority: n };
505
+ return b.set(e, u), u;
506
+ }
507
+ // Create regex for prefix
508
+ createPrefixRegex(e) {
509
+ const t = [];
510
+ let s = !1, r;
511
+ const n = e.split("/").filter(Boolean);
512
+ r = n.reduce((i, u) => u.startsWith("[...") ? i - 10 : u.startsWith("[[") ? i - 5 : u.startsWith("[") ? i - 1 : i + 1, 0);
513
+ let o = "^";
514
+ for (const i of n)
515
+ if (i.startsWith("[...") && i.endsWith("]")) {
516
+ s = !0;
517
+ const u = i.slice(4, -1);
518
+ t.push(u), o += "/(.+)";
519
+ } else if (i.startsWith("[[") && i.endsWith("]]")) {
520
+ const u = i.slice(2, -2);
521
+ t.push(u), o += "(?:/([^/]+))?";
522
+ } else if (i.startsWith("[") && i.endsWith("]")) {
523
+ const u = i.slice(1, -1);
524
+ t.push(u), o += "/([^/]+)";
525
+ } else
526
+ o += "/" + i.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
527
+ return o += "(?=/|$)", { regex: new RegExp(o), paramNames: t, isCatchAll: s, priority: r };
528
+ }
529
+ normalizePrefix(e) {
530
+ return e.startsWith("/") ? e.replace(/\/$/, "") : `/${e.replace(/\/$/, "")}`;
531
+ }
532
+ extractPrefixParams(e, t) {
533
+ const s = t.match(e.regex);
534
+ if (!s) return {};
535
+ const r = {};
536
+ return e.isCatchAll && e.paramNames.length === 1 ? r[e.paramNames[0]] = s[1]?.replace(/^\//, "") || "" : e.paramNames.forEach((n, o) => {
537
+ r[n] = s[o + 1] || "";
538
+ }), r;
539
+ }
540
+ // FIXED: Nested router handling without duplicate middleware application
541
+ async handleNestedRouters(e, t) {
542
+ const s = [...this._nestedRouters].sort((r, n) => n.priority - r.priority);
543
+ for (const r of s) {
544
+ const n = t.match(r.regex);
545
+ if (!n || n.index !== 0) continue;
546
+ const o = n[0], i = t.slice(o.length) || "/", u = this.extractPrefixParams(r, o), c = {
547
+ ...e,
548
+ params: { ...e.params, ...u }
549
+ }, l = async () => await r.router.handleAtPath(c, i), d = await this.applyMiddlewaresWithList(c, r.middlewares, l);
550
+ if (d) return d;
551
+ }
552
+ return null;
553
+ }
554
+ // FIXED: Local route handling without duplicate middleware application
555
+ async handleLocalRoutes(e, t, s) {
556
+ const r = /* @__PURE__ */ new Set();
557
+ let n = !1;
558
+ for (const o of this._routes) {
559
+ if (!o.regex.test(s) || (r.add(o.method), o.method === "GET" && (n = !0, r.add("HEAD")), !(o.method === t || t === "HEAD" && o.method === "GET"))) continue;
560
+ const u = s.match(o.regex);
561
+ if (!u) continue;
562
+ const c = Object.fromEntries(
563
+ o.paramNames.map((d, h) => [d, u[h + 1] || ""])
564
+ );
565
+ e.params = { ...e.params, ...c }, e.route = { ...e.route, id: o.path };
566
+ const l = () => o.handler(e);
567
+ return await this.applyMiddlewaresWithList(e, o.middlewares, l);
568
+ }
569
+ if (r.size > 0 || t === "HEAD" && n) {
570
+ const o = [...r].join(", ");
571
+ return t === "OPTIONS" ? new Response(null, {
572
+ status: 200,
573
+ headers: { Allow: o }
574
+ }) : new Response("Method Not Allowed", {
575
+ status: 405,
576
+ headers: { Allow: o }
577
+ });
578
+ }
579
+ return new Response("Not Found", { status: 404 });
580
+ }
581
+ sortRoutes() {
582
+ this._routes.sort((e, t) => t.priority - e.priority), this.routesSorted = !0;
583
+ }
584
+ sortWsRoutes() {
585
+ this._wsRoutes.sort((e, t) => t.priority - e.priority), this.wsRoutesSorted = !0;
586
+ }
587
+ formatActionResult(e) {
588
+ return e instanceof Response ? e : e?.type === "failure" && "status" in e ? R.fail(e.status, e.data) : R.success(200, e ?? void 0);
589
+ }
590
+ handleActionError(e) {
591
+ if (_(e))
592
+ return R.error(e.status, e);
593
+ if (N(e)) {
594
+ const t = e.headers.get("Location") || "/";
595
+ return R.redirect(e.status, t);
596
+ }
597
+ return console.error(e), R.error(500, { message: "Internal Server Error" });
598
+ }
599
+ static New() {
600
+ return new x();
601
+ }
602
+ }
603
+ const R = {
604
+ success: (a = 200, e) => new Response(JSON.stringify({ data: e, type: "success", status: a }), {
605
+ status: a,
606
+ headers: { "Content-Type": "application/json" }
607
+ }),
608
+ redirect: (a = 302, e) => new Response(JSON.stringify({ location: e, type: "redirect", status: a }), {
609
+ status: a,
610
+ headers: { "Content-Type": "application/json" }
611
+ }),
612
+ error: (a = 500, e) => new Response(JSON.stringify({ error: e, type: "error", status: a }), {
613
+ status: a,
614
+ headers: { "Content-Type": "application/json" }
615
+ }),
616
+ fail: (a = 400, e) => new Response(JSON.stringify({ data: e, type: "failure", status: a }), {
617
+ status: a,
618
+ headers: { "Content-Type": "application/json" }
619
+ })
620
+ };
621
+ class pe {
622
+ constructor(e, t) {
623
+ this.raw = e.headers.get("cookie") ?? "", this.setCookieHeader = t;
624
+ }
625
+ get(e, t) {
626
+ return E(this.raw, t)[e];
627
+ }
628
+ getAll(e) {
629
+ return Object.entries(E(this.raw, e)).filter(([, t]) => t !== void 0).map(([t, s]) => ({ name: t, value: s }));
630
+ }
631
+ set(e, t, s) {
632
+ this.setCookieHeader(Y(e, t, s));
633
+ }
634
+ delete(e, t) {
635
+ this.set(e, "", { ...t, maxAge: 0 });
636
+ }
637
+ }
638
+ class C extends Error {
639
+ constructor(e = "Payload Too Large") {
640
+ super(e), this.status = 413, this.name = "PayloadTooLargeError";
641
+ }
642
+ }
643
+ class be {
644
+ constructor(e) {
645
+ this.upgradeHandlerInstalled = !1, this.config = e ?? { type: "http", options: {} }, this.router = new x(), this.wss = new K({
646
+ noServer: !0,
647
+ maxPayload: this.config.security?.maxWebSocketPayload ?? 1024 * 1024
648
+ });
649
+ }
650
+ get server() {
651
+ if (!this._server) {
652
+ const e = (t, s) => {
653
+ this.handleRequest(t, s).catch((r) => {
654
+ console.error("Unhandled request error:", r), s.statusCode = 500, s.end("Internal Server Error");
655
+ });
656
+ };
657
+ this._server = this.config.type === "https" ? q(this.config.options, e) : B(this.config.options, e);
658
+ }
659
+ return this._server;
660
+ }
661
+ discard(e, t) {
662
+ return this.router.discard(e, t), this;
663
+ }
664
+ listen(...e) {
665
+ return this.upgradeHandlerInstalled || (this.installUpgradeHandler(), this.upgradeHandlerInstalled = !0), this.server.listen(...e), this;
666
+ }
667
+ installUpgradeHandler() {
668
+ this.server.on("upgrade", (e, t, s) => {
669
+ if (e.headers.upgrade?.toLowerCase() !== "websocket") {
670
+ t.destroy();
671
+ return;
672
+ }
673
+ let r, n;
674
+ try {
675
+ r = this.toURL(e, !0), n = this.toRequest(e, r, !0);
676
+ } catch {
677
+ t.destroy();
678
+ return;
679
+ }
680
+ const o = this.toRequestEvent(n, r, {
681
+ getClientAddress: () => e.socket.remoteAddress ?? "127.0.0.1",
682
+ setHeader: () => {
683
+ },
684
+ pushSetCookie: () => {
685
+ }
686
+ });
687
+ this.router.canHandleWebSocket(o).then((i) => {
688
+ if (!i || !this.isAllowedWebSocketOrigin(e)) {
689
+ t.destroy();
690
+ return;
691
+ }
692
+ this.wss.handleUpgrade(e, t, s, (u) => {
693
+ this.router.handleWebSocket(o, u).then((c) => {
694
+ !c && u.readyState === P.OPEN && u.close(1008, "Route not found");
695
+ }).catch((c) => {
696
+ console.error("WebSocket routing error:", c), u.readyState === P.OPEN && u.close(1011, "Internal error");
697
+ });
698
+ });
699
+ }).catch(() => t.destroy());
700
+ });
701
+ }
702
+ close(e) {
703
+ this.wss.close(() => {
704
+ this.server.close(e);
705
+ });
706
+ }
707
+ address() {
708
+ return this.server.address();
709
+ }
710
+ get listening() {
711
+ return this.server.listening;
712
+ }
713
+ async handleRequest(e, t) {
714
+ if (!this.isRequestBodyAllowed(e)) {
715
+ t.statusCode = 413, t.end("Payload Too Large");
716
+ return;
717
+ }
718
+ const s = this.toWebRequest(e), r = new URL(s.url), n = {}, o = [], i = this.toRequestEvent(s, r, {
719
+ getClientAddress: () => e.socket.remoteAddress ?? "127.0.0.1",
720
+ setHeader: (c, l) => {
721
+ n[c.toLowerCase()] = l;
722
+ },
723
+ pushSetCookie: (c) => {
724
+ o.push(c);
725
+ }
726
+ });
727
+ let u;
728
+ try {
729
+ u = await this.router.handle(i);
730
+ } catch (c) {
731
+ u = this.handleError(c);
732
+ }
733
+ for (const [c, l] of Object.entries(n))
734
+ t.setHeader(c, l);
735
+ o.length > 0 && t.setHeader("Set-Cookie", o), await this.sendWebResponse(t, u);
736
+ }
737
+ toWebRequest(e) {
738
+ const t = this.toURL(e, !1);
739
+ return this.toRequest(e, t, !1);
740
+ }
741
+ toRequest(e, t, s) {
742
+ const r = {
743
+ method: s ? "GET" : e.method,
744
+ headers: this.toHeaders(e.headers),
745
+ // @ts-ignore
746
+ duplex: "half"
747
+ };
748
+ return !s && e.method !== "GET" && e.method !== "HEAD" && (r.body = G.toWeb(this.wrapRequestBody(e))), new Request(t, r);
749
+ }
750
+ wrapRequestBody(e) {
751
+ const t = this.config.security?.maxRequestBodySize;
752
+ if (!t)
753
+ return e;
754
+ let s = 0;
755
+ const r = new J({
756
+ transform(n, o, i) {
757
+ if (s += Buffer.byteLength(n), s > t) {
758
+ i(new C());
759
+ return;
760
+ }
761
+ i(null, n);
762
+ }
763
+ });
764
+ return e.on("aborted", () => r.destroy(new Error("Request aborted"))), e.on("error", (n) => r.destroy(n)), e.pipe(r), r;
765
+ }
766
+ toURL(e, t) {
767
+ const s = e.socket instanceof X ? t ? "wss" : "https" : t ? "ws" : "http", r = this.resolveAuthority(e);
768
+ return new URL(e.url ?? "/", `${s}://${r}`);
769
+ }
770
+ resolveAuthority(e) {
771
+ const t = this.config.security?.trustHostHeader ? this.normalizeTrustedHost(e.headers.host) : null;
772
+ if (t)
773
+ return t;
774
+ const s = this.server.address();
775
+ return s && typeof s == "object" ? `${s.address.includes(":") ? `[${s.address}]` : s.address}:${s.port}` : e.socket.localPort ? `127.0.0.1:${e.socket.localPort}` : "localhost";
776
+ }
777
+ normalizeTrustedHost(e) {
778
+ if (!e) return null;
779
+ let t;
780
+ try {
781
+ t = new URL(`http://${e}`);
782
+ } catch {
783
+ return null;
784
+ }
785
+ if (t.username || t.password || t.pathname !== "/" || t.search || t.hash)
786
+ return null;
787
+ const s = t.port ? `${t.hostname}:${t.port}` : t.hostname, r = this.config.security?.allowedHosts;
788
+ return !r || this.matchesValue(s, r) ? s : null;
789
+ }
790
+ matchesValue(e, t) {
791
+ return (Array.isArray(t) ? t : [t]).some((r) => typeof r == "string" ? r === e : r instanceof RegExp ? r.test(e) : r(e));
792
+ }
793
+ toHeaders(e) {
794
+ const t = new Headers();
795
+ for (const [s, r] of Object.entries(e))
796
+ if (r !== void 0) {
797
+ if (Array.isArray(r)) {
798
+ const n = s.toLowerCase() === "cookie" ? r.join("; ") : r.join(", ");
799
+ t.set(s, n);
800
+ continue;
801
+ }
802
+ t.set(s, r);
803
+ }
804
+ return t;
805
+ }
806
+ isRequestBodyAllowed(e) {
807
+ const t = this.config.security?.maxRequestBodySize;
808
+ if (!t) return !0;
809
+ const s = e.headers["content-length"];
810
+ if (!s) return !0;
811
+ const r = Number.parseInt(Array.isArray(s) ? s[0] : s, 10);
812
+ return Number.isFinite(r) && r <= t;
813
+ }
814
+ handleError(e) {
815
+ if (e instanceof C)
816
+ return new Response(e.message, { status: e.status });
817
+ if (_(e))
818
+ return new Response(JSON.stringify({
819
+ error: e.statusText || "Error",
820
+ status: e.status
821
+ }), {
822
+ status: e.status,
823
+ headers: { "Content-Type": "application/json" }
824
+ });
825
+ if (N(e)) {
826
+ const t = e.headers.get("Location") || "/";
827
+ return new Response(null, {
828
+ status: e.status,
829
+ headers: { Location: t }
830
+ });
831
+ }
832
+ return console.error("Unhandled error:", e), new Response("Internal Server Error", { status: 500 });
833
+ }
834
+ async sendWebResponse(e, t) {
835
+ if (e.statusCode = t.status, t.headers.forEach((n, o) => {
836
+ e.setHeader(o, n);
837
+ }), e.hasHeader("Server") || e.setHeader("Server", "WebHTTPServer"), !t.body || this.shouldOmitResponseBody(t, e.req?.method)) {
838
+ e.end();
839
+ return;
840
+ }
841
+ const s = t.body.getReader(), r = V.toWeb(e).getWriter();
842
+ try {
843
+ for (; ; ) {
844
+ const { done: n, value: o } = await s.read();
845
+ if (n) break;
846
+ await r.write(o);
847
+ }
848
+ } finally {
849
+ await r.close().catch(() => {
850
+ });
851
+ }
852
+ }
853
+ shouldOmitResponseBody(e, t) {
854
+ return t === "HEAD" ? !0 : e.status === 204 || e.status === 205 || e.status === 304;
855
+ }
856
+ isAllowedWebSocketOrigin(e) {
857
+ const t = e.headers.origin;
858
+ if (!t) return !0;
859
+ const s = this.config.security?.allowedWebSocketOrigins;
860
+ return s ? this.matchesValue(t, s) : !0;
861
+ }
862
+ toRequestEvent(e, t, s) {
863
+ const r = new pe(e, s.pushSetCookie), n = this.config, o = {}, i = { name: "WebHTTPServer" }, u = /* @__PURE__ */ new Set(), c = {
864
+ request: e,
865
+ url: t,
866
+ cookies: r,
867
+ getClientAddress: s.getClientAddress,
868
+ get locals() {
869
+ return o;
870
+ },
871
+ get platform() {
872
+ return i;
873
+ },
874
+ params: {},
875
+ route: { id: "" },
876
+ setHeaders: (l) => {
877
+ for (const [d, h] of Object.entries(l)) {
878
+ const f = d.toLowerCase();
879
+ if (f === "set-cookie")
880
+ throw new TypeError("Use event.cookies for Set-Cookie headers");
881
+ if (u.has(f))
882
+ throw new TypeError(`Header "${d}" has already been set`);
883
+ u.add(f), s.setHeader(d, h);
884
+ }
885
+ }
886
+ };
887
+ return n.locals && Object.assign(o, n.locals(c)), n.platform && Object.assign(i, n.platform(c)), c;
888
+ }
889
+ }
890
+ const Ce = async (a, e) => {
891
+ const t = JSON.stringify(await a);
892
+ return new Response(t, {
893
+ ...e,
894
+ headers: {
895
+ "content-type": "application/json",
896
+ "content-length": Buffer.byteLength(t).toString(),
897
+ ...e?.headers
898
+ }
899
+ });
900
+ }, We = async (a, e) => {
901
+ const t = await a;
902
+ return new Response(t, {
903
+ ...e,
904
+ headers: {
905
+ "content-type": "text/plain",
906
+ "content-length": Buffer.byteLength(t).toString(),
907
+ ...e?.headers
908
+ }
909
+ });
910
+ }, Le = async (a, e) => {
911
+ const t = await a;
912
+ return new Response(t, {
913
+ ...e,
914
+ headers: {
915
+ "content-type": "text/html",
916
+ "content-length": Buffer.byteLength(t).toString(),
917
+ ...e?.headers
918
+ }
919
+ });
920
+ }, Oe = (a, e = {}) => (t) => ee(a, t, e);
921
+ export {
922
+ R as Action,
923
+ Te as CORS,
924
+ Ee as RateLimiter,
925
+ fe as RequestMethods,
926
+ x as Router,
927
+ be as WebServer,
928
+ Oe as dir,
929
+ Le as html,
930
+ _ as isHttpError,
931
+ N as isRedirect,
932
+ Ce as json,
933
+ ee as serveStatic,
934
+ We as text
935
+ };
936
+ //# sourceMappingURL=index.es.js.map