@sourceregistry/node-webserver 1.3.0 → 1.4.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.
- package/README.md +111 -60
- package/dist/app.d.ts +1 -0
- package/dist/index.cjs.js +3 -5
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +1143 -1045
- package/dist/index.es.js.map +1 -1
- package/dist/middlewares/index.d.ts +3 -0
- package/dist/middlewares/requestid/index.d.ts +16 -0
- package/dist/middlewares/security/index.d.ts +39 -0
- package/dist/middlewares/timeout/index.d.ts +22 -0
- package/dist/types/router.d.ts +0 -1
- package/dist/types/server.d.ts +31 -3
- package/examples/public-baseline.ts +75 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ It provides:
|
|
|
14
14
|
- Router lifecycle hooks with `pre()` and `post()`
|
|
15
15
|
- WebSocket routing
|
|
16
16
|
- Cookie helpers
|
|
17
|
-
- Built-in CORS
|
|
17
|
+
- Built-in middleware for CORS, rate limiting, security headers, request IDs, and timeouts
|
|
18
18
|
- Safer defaults for host handling and WebSocket upgrade validation
|
|
19
19
|
|
|
20
20
|
## Installation
|
|
@@ -176,6 +176,8 @@ app.GET("/events", sse((event, emit) => {
|
|
|
176
176
|
|
|
177
177
|
Objects are serialized as JSON automatically. Strings are sent as plain `data:` lines.
|
|
178
178
|
|
|
179
|
+
If the callback finishes without returning cleanup, the SSE stream closes automatically. If it returns a cleanup function, the stream stays open until the client disconnects or the stream is canceled.
|
|
180
|
+
|
|
179
181
|
## Request Handling
|
|
180
182
|
|
|
181
183
|
Route handlers receive a web-standard `Request` plus extra routing data:
|
|
@@ -269,6 +271,89 @@ app.useMiddleware(async (event, next) => {
|
|
|
269
271
|
});
|
|
270
272
|
```
|
|
271
273
|
|
|
274
|
+
## Built-in Middleware
|
|
275
|
+
|
|
276
|
+
The library exports built-in middleware namespaces from `@sourceregistry/node-webserver`:
|
|
277
|
+
|
|
278
|
+
- `CORS`
|
|
279
|
+
- `RateLimiter`
|
|
280
|
+
- `RequestId`
|
|
281
|
+
- `Security`
|
|
282
|
+
- `Timeout`
|
|
283
|
+
|
|
284
|
+
### Security headers
|
|
285
|
+
|
|
286
|
+
Use `Security.headers()` to apply a small set of secure defaults without overwriting headers your route already sets.
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
import { Security } from "@sourceregistry/node-webserver";
|
|
290
|
+
|
|
291
|
+
app.useMiddleware(Security.headers());
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
By default it adds:
|
|
295
|
+
|
|
296
|
+
- `Content-Security-Policy`
|
|
297
|
+
- `X-Frame-Options`
|
|
298
|
+
- `Referrer-Policy`
|
|
299
|
+
- `Permissions-Policy`
|
|
300
|
+
- `Cross-Origin-Opener-Policy`
|
|
301
|
+
- `Cross-Origin-Resource-Policy`
|
|
302
|
+
|
|
303
|
+
You can disable or override individual headers:
|
|
304
|
+
|
|
305
|
+
```ts
|
|
306
|
+
app.useMiddleware(Security.headers({
|
|
307
|
+
contentSecurityPolicy: false,
|
|
308
|
+
frameOptions: "SAMEORIGIN",
|
|
309
|
+
strictTransportSecurity: "max-age=31536000; includeSubDomains"
|
|
310
|
+
}));
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Request IDs
|
|
314
|
+
|
|
315
|
+
Use `RequestId.assign()` to accept or generate a request ID, expose it through `event.locals.requestId`, and add it to the response.
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
import { RequestId } from "@sourceregistry/node-webserver";
|
|
319
|
+
|
|
320
|
+
app.useMiddleware(RequestId.assign());
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
You can customize the header name or generator:
|
|
324
|
+
|
|
325
|
+
```ts
|
|
326
|
+
app.useMiddleware(RequestId.assign({
|
|
327
|
+
headerName: "x-correlation-id",
|
|
328
|
+
generate: () => crypto.randomUUID()
|
|
329
|
+
}));
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Timeouts
|
|
333
|
+
|
|
334
|
+
Use `Timeout.deadline()` to return a fallback response when a route takes too long.
|
|
335
|
+
|
|
336
|
+
```ts
|
|
337
|
+
import { Timeout } from "@sourceregistry/node-webserver";
|
|
338
|
+
|
|
339
|
+
app.useMiddleware(Timeout.deadline({
|
|
340
|
+
ms: 5000
|
|
341
|
+
}));
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
You can customize the response and add a timeout hook:
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
app.useMiddleware(Timeout.deadline({
|
|
348
|
+
ms: 2000,
|
|
349
|
+
status: 503,
|
|
350
|
+
body: "Request timed out",
|
|
351
|
+
onTimeout: () => {
|
|
352
|
+
console.warn("request exceeded deadline");
|
|
353
|
+
}
|
|
354
|
+
}));
|
|
355
|
+
```
|
|
356
|
+
|
|
272
357
|
Route-specific middleware:
|
|
273
358
|
|
|
274
359
|
```ts
|
|
@@ -434,7 +519,12 @@ const app = new WebServer({
|
|
|
434
519
|
options: {},
|
|
435
520
|
security: {
|
|
436
521
|
maxRequestBodySize: 1024 * 1024,
|
|
522
|
+
headersTimeoutMs: 30_000,
|
|
523
|
+
requestTimeoutMs: 60_000,
|
|
524
|
+
keepAliveTimeoutMs: 5_000,
|
|
437
525
|
maxWebSocketPayload: 64 * 1024,
|
|
526
|
+
trustedProxies: ["127.0.0.1"],
|
|
527
|
+
trustHostHeader: true,
|
|
438
528
|
allowedWebSocketOrigins: [
|
|
439
529
|
"https://app.example.com",
|
|
440
530
|
"https://admin.example.com"
|
|
@@ -447,13 +537,25 @@ Available options:
|
|
|
447
537
|
|
|
448
538
|
- `trustHostHeader`
|
|
449
539
|
- `allowedHosts`
|
|
540
|
+
- `trustedProxies`
|
|
450
541
|
- `allowedWebSocketOrigins`
|
|
451
542
|
- `maxRequestBodySize`
|
|
543
|
+
- `headersTimeoutMs`
|
|
544
|
+
- `requestTimeoutMs`
|
|
545
|
+
- `keepAliveTimeoutMs`
|
|
452
546
|
- `maxWebSocketPayload`
|
|
453
547
|
|
|
454
548
|
`trustHostHeader` defaults to `false`. That is the safer default for public-facing services unless you are explicitly validating proxy behavior.
|
|
455
549
|
|
|
456
|
-
|
|
550
|
+
`trustedProxies` is also disabled by default. When configured, the server will trust `X-Forwarded-For`, `X-Forwarded-Proto`, and `X-Forwarded-Host` only when the direct peer matches one of the configured values.
|
|
551
|
+
|
|
552
|
+
For public-facing services, the server now also applies conservative timeout defaults unless you override them:
|
|
553
|
+
|
|
554
|
+
- `headersTimeoutMs`: `30000`
|
|
555
|
+
- `requestTimeoutMs`: `60000`
|
|
556
|
+
- `keepAliveTimeoutMs`: `5000`
|
|
557
|
+
|
|
558
|
+
### Middleware examples
|
|
457
559
|
|
|
458
560
|
### CORS
|
|
459
561
|
|
|
@@ -498,66 +600,15 @@ app.listen(3443);
|
|
|
498
600
|
|
|
499
601
|
## Full Example
|
|
500
602
|
|
|
501
|
-
|
|
502
|
-
import {
|
|
503
|
-
CORS,
|
|
504
|
-
RateLimiter,
|
|
505
|
-
WebServer,
|
|
506
|
-
json,
|
|
507
|
-
text
|
|
508
|
-
} from "@sourceregistry/node-webserver";
|
|
509
|
-
|
|
510
|
-
const app = new WebServer({
|
|
511
|
-
type: "http",
|
|
512
|
-
options: {},
|
|
513
|
-
locals: () => ({
|
|
514
|
-
startedAt: Date.now()
|
|
515
|
-
}),
|
|
516
|
-
security: {
|
|
517
|
-
maxRequestBodySize: 1024 * 1024,
|
|
518
|
-
allowedWebSocketOrigins: "https://app.example.com"
|
|
519
|
-
}
|
|
520
|
-
});
|
|
521
|
-
|
|
522
|
-
app.pre(async (event) => {
|
|
523
|
-
if (event.url.pathname.startsWith("/private")) {
|
|
524
|
-
const auth = event.request.headers.get("authorization");
|
|
525
|
-
if (!auth) {
|
|
526
|
-
return new Response("Unauthorized", { status: 401 });
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
app.useMiddleware(
|
|
532
|
-
CORS.policy({
|
|
533
|
-
origin: "https://app.example.com",
|
|
534
|
-
credentials: true
|
|
535
|
-
}),
|
|
536
|
-
RateLimiter.fixedWindowLimit({
|
|
537
|
-
max: 60,
|
|
538
|
-
windowMs: 60_000
|
|
539
|
-
})
|
|
540
|
-
);
|
|
603
|
+
For a production-oriented baseline with:
|
|
541
604
|
|
|
542
|
-
|
|
605
|
+
- trusted proxy handling
|
|
606
|
+
- security headers
|
|
607
|
+
- request IDs
|
|
608
|
+
- route deadlines
|
|
609
|
+
- CORS and rate limiting
|
|
543
610
|
|
|
544
|
-
|
|
545
|
-
return json({
|
|
546
|
-
id: event.params.id,
|
|
547
|
-
requestId: event.locals.startedAt
|
|
548
|
-
});
|
|
549
|
-
});
|
|
550
|
-
|
|
551
|
-
app.post(async (_event, response) => {
|
|
552
|
-
const nextResponse = new Response(response.body, response);
|
|
553
|
-
nextResponse.headers.set("x-server", "node-webserver");
|
|
554
|
-
return nextResponse;
|
|
555
|
-
});
|
|
556
|
-
|
|
557
|
-
app.listen(3000, () => {
|
|
558
|
-
console.log("server listening on port 3000");
|
|
559
|
-
});
|
|
560
|
-
```
|
|
611
|
+
see [examples/public-baseline.ts](./examples/public-baseline.ts).
|
|
561
612
|
|
|
562
613
|
## Development
|
|
563
614
|
|
package/dist/app.d.ts
CHANGED
package/dist/index.cjs.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const F=require("http"),D=require("https"),U=require("tls"),T=require("stream"),C=require("ws"),v=require("cookie"),$=require("node:fs"),H=require("node:fs/promises"),S=require("node:path"),z=require("node:stream");function L(a){return A(a)&&a.status>=400&&a.status<600}function W(a){return A(a)&&a.status>=300&&a.status<400}function A(a){return a instanceof Response}class B{constructor(e){this.data=new Map,this.windowMs=e.windowMs,this.startCleanup()}async incr(e){const t=Date.now();let s=this.data.get(e);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}}startCleanup(){this.cleanupInterval=setInterval(()=>{const e=Date.now();for(const[t,{reset:s}]of this.data)e>=s&&this.data.delete(t)},Math.min(this.windowMs,3e5))}stop(){this.cleanupInterval&&clearInterval(this.cleanupInterval)}async resetAll(){this.data.clear()}}function X(a){const{windowMs:e=6e4,max:t,key:s=c=>c.getClientAddress(),message:r="Too many requests, please try again later.",statusCode:n=429,headers:o="include",onRateLimit:i,store:u=new B({windowMs:e})}=a;return async(c,l)=>{const d=`rl:${s(c)}`,{current:h,reset:p}=await u.incr(d),m=Math.ceil((p-Date.now())/1e3);if(h>t){i&&i(c,{current:h,max:t,key:d});const y={status:n,headers:new Headers},f=y.headers;o==="include"&&(f.set("X-RateLimit-Limit",String(t)),f.set("X-RateLimit-Remaining","0"),f.set("X-RateLimit-Reset",String(Math.floor(p/1e3))),f.set("Retry-After",String(m)));let w;return typeof r=="string"?(w=r,f.set("Content-Type","text/plain")):(w=JSON.stringify(r),f.set("Content-Type","application/json")),new Response(w,y)}if(c.rateLimit={current:h,limit:t,reset:new Date(p),remaining:t-h},o==="include"){const y={"X-RateLimit-Limit":String(t),"X-RateLimit-Remaining":String(t-h),"X-RateLimit-Reset":String(Math.floor(p/1e3))},f=c.setHeaders;c.setHeaders=w=>{f({...y,...w})},f(y)}return l()}}const J=Object.freeze(Object.defineProperty({__proto__:null,fixedWindowLimit:X},Symbol.toStringTag,{value:"Module"})),G=["GET","POST","PUT","DELETE","PATCH","HEAD","OPTIONS"],V=["Accept","Accept-Language","Content-Language","Content-Type","Range"],K=["Authorization","X-Auth-Token","X-Requested-With","X-CSRF-Token","X-HTTP-Method-Override","X-Forwarded-For","X-Real-IP","X-Custom-Header"];function N(a,e){return!a||!e?!1:e==="*"?!0:e==="null"?a==="null":Array.isArray(e)?e.some(t=>N(a,t)):typeof e=="function"?e(a):e instanceof RegExp?e.test(a):a===e}function Y(a,e){const{origin:t="*"}=e;return a?t==="*"?e.credentials?a:"*":N(a,t)?a:null:t==="*"?"*":null}function Q(a={}){const{methods:e=G,allowedHeaders:t=K,exposedHeaders:s,credentials:r=!1,maxAge:n=86400,onResponse:o}=a,i="Origin,Access-Control-Request-Method,Access-Control-Request-Headers",u=e.join(","),c=[...V,...t].join(","),l=[["Vary",i],["Access-Control-Allow-Methods",u],["Access-Control-Allow-Headers",c]];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)=>{const p=d.request,m=p.headers.get("Origin"),y=p.method==="OPTIONS"&&m!==null&&p.headers.has("Access-Control-Request-Method"),f=Y(m,a);if(y){if(!f)return new Response(null,{status:403});const g=new Response(null,{status:204});for(const[b,I]of l)g.headers.set(b,I);return g.headers.set("Access-Control-Allow-Origin",f),g}const w=await h();if(!w)return;if(!f)return w;const E=new Response(w.body,w);for(const[g,b]of l)E.headers.set(g,b);E.headers.set("Access-Control-Allow-Origin",f);let P=E;if(o){const g=o(P);g&&(P=g)}return P}}const Z=Object.freeze(Object.defineProperty({__proto__:null,policy:Q},Symbol.toStringTag,{value:"Module"})),j=["GET","PUT","POST","DELETE","PATCH","HEAD","OPTIONS"];class O{static{this.cache=new Map}static get(e){return this.cache.get(e)}static set(e,t){this.cache.set(e,t)}}class x{constructor(){this._routes=[],this._wsRoutes=[],this._nestedRouters=[],this._middlewares=[],this._preHandlers=[],this._postHandlers=[],this.routesSorted=!1,this.wsRoutesSorted=!1}get routes(){return this._routes}get nestedRouters(){return this._nestedRouters}GET(e,t,...s){return this.addHandler("GET",e,t,s)}POST(e,t,...s){return this.addHandler("POST",e,t,s)}PUT(e,t,...s){return this.addHandler("PUT",e,t,s)}PATCH(e,t,...s){return this.addHandler("PATCH",e,t,s)}DELETE(e,t,...s){return this.addHandler("DELETE",e,t,s)}HEAD(e,t,...s){return this.addHandler("HEAD",e,t,s)}OPTIONS(e,t,...s){return this.addHandler("OPTIONS",e,t,s)}USE(e,t,...s){return j.forEach(r=>this.addHandler(r,e,t,s)),this}action(e,t,...s){const r=async n=>{try{const o=await t(n);return this.formatActionResult(o)}catch(o){return this.handleActionError(o)}};return this.addHandler("POST",e,r,s)}use(e,t,...s){let r,n,o=s;Array.isArray(e)?([r,n]=e,o=e.length>2?e.slice(2):[]):(r=e,n=t);const i=this.normalizePrefix(r),{regex:u,paramNames:c,isCatchAll:l,priority:d}=this.createPrefixRegex(i);return this._nestedRouters.push({prefix:i,router:n,regex:u,paramNames:c,isCatchAll:l,priority:d,middlewares:o}),this}useMiddleware(...e){return this._middlewares.push(...e),this}pre(...e){return this._preHandlers.push(...e),this}post(...e){return this._postHandlers.push(...e),this}discard(e,t){return this._nestedRouters=this._nestedRouters.filter(s=>s.prefix!==e),this._routes=this._routes.filter(s=>s.path!==e||t&&s.method!==t),this}WS(e,t,...s){const{regex:r,paramNames:n,isCatchAll:o,priority:i}=this.createPathRegex(e);return this._wsRoutes.push({path:e,regex:r,paramNames:n,isCatchAll:o,priority:i,handler:t,middlewares:s}),this.wsRoutesSorted=!1,this}async canHandleWebSocket(e){return this.canHandleWebSocketAtPath(e,e.url.pathname)}async canHandleWebSocketAtPath(e,t){this.wsRoutesSorted||this.sortWsRoutes();for(const s of[...this._nestedRouters].sort((r,n)=>n.priority-r.priority)){const r=t.match(s.regex);if(!r||r.index!==0)continue;const n=r[0],o=t.slice(n.length)||"/",i={...e,params:{...e.params,...this.extractPrefixParams(s,n)}};if(await s.router.canHandleWebSocketAtPath(i,o))return!0}for(const s of this._wsRoutes)if(s.regex.test(t))return!0;return!1}async handleWebSocket(e,t){return this.handleWebSocketAtPath(e,t,e.url.pathname)}async handleWebSocketAtPath(e,t,s){this.wsRoutesSorted||this.sortWsRoutes();for(const r of[...this._nestedRouters].sort((n,o)=>o.priority-n.priority)){const n=s.match(r.regex);if(!n||n.index!==0)continue;const o=n[0],i=s.slice(o.length)||"/",u=this.extractPrefixParams(r,o),c={...e,params:{...e.params,...u}},l=[...this._middlewares,...r.middlewares],d=()=>r.router.handleWebSocketAtPath(c,t,i);if(await this.applyMiddlewaresWithList(c,l,d))return!0}for(const r of this._wsRoutes){if(!r.regex.test(s))continue;const n=s.match(r.regex);if(!n)continue;const o=Object.fromEntries(r.paramNames.map((l,d)=>[l,n[d+1]||""])),i={...e,params:{...e.params,...o},route:{...e.route,id:r.path},websocket:t},u=[...this._middlewares,...r.middlewares];if(await this.applyMiddlewaresWithList(i,u,()=>r.handler(i))===void 0)return!0}return!1}async handle(e){return this.handleAtPath(e,e.url.pathname)}async handleAtPath(e,t){try{const s=e.request.method;let r=await this.runPreHandlers(e);if(!r){const o=async()=>{const i=await this.handleNestedRouters(e,t);return i||(this.routesSorted||this.sortRoutes(),this.handleLocalRoutes(e,s,t))};r=await this.applyMiddlewaresWithList(e,this._middlewares,o)}const n=r||new Response("No Content",{status:204});return await this.runPostHandlers(e,n)}catch(s){if(A(s))return s;throw s}}async applyMiddlewaresWithList(e,t,s){const r=[...t],n=async o=>o>=r.length?s():r[o](e,()=>n(o+1));return n(0)}async runPreHandlers(e){for(const t of this._preHandlers){const s=await t(e);if(s instanceof Response)return s}}async runPostHandlers(e,t){let s=t;for(const r of this._postHandlers){const n=await r(e,s);n instanceof Response&&(s=n)}return s}addHandler(e,t,s,r=[]){const{regex:n,paramNames:o,isCatchAll:i,priority:u}=this.createPathRegex(t);return this._routes.push({method:e,path:t,regex:n,paramNames:o,isCatchAll:i,priority:u,handler:s,middlewares:r}),this.routesSorted=!1,this}createPathRegex(e){const t=O.get(e);if(t)return t;const s=[];let r=!1,n;const o=e.split("/").filter(Boolean);n=o.reduce((c,l)=>l.startsWith("[...")?c-10:l.startsWith("[[")?c-5:l.startsWith("[")?c-1:c+1,0);let i="^";for(const c of o)if(c.startsWith("[...")&&c.endsWith("]")){r=!0;const l=c.slice(4,-1);s.push(l),i+="/(.+)"}else if(c.startsWith("[[")&&c.endsWith("]]")){const l=c.slice(2,-2);s.push(l),i+="(?:/([^/]+))?"}else if(c.startsWith("[")&&c.endsWith("]")){const l=c.slice(1,-1);s.push(l),i+="/([^/]+)"}else i+="/"+c.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&");i+="/?$";const u={regex:new RegExp(i),paramNames:s,isCatchAll:r,priority:n};return O.set(e,u),u}createPrefixRegex(e){const t=[];let s=!1,r;const n=e.split("/").filter(Boolean);r=n.reduce((i,u)=>u.startsWith("[...")?i-10:u.startsWith("[[")?i-5:u.startsWith("[")?i-1:i+1,0);let o="^";for(const i of n)if(i.startsWith("[...")&&i.endsWith("]")){s=!0;const u=i.slice(4,-1);t.push(u),o+="/(.+)"}else if(i.startsWith("[[")&&i.endsWith("]]")){const u=i.slice(2,-2);t.push(u),o+="(?:/([^/]+))?"}else if(i.startsWith("[")&&i.endsWith("]")){const u=i.slice(1,-1);t.push(u),o+="/([^/]+)"}else o+="/"+i.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&");return o+="(?=/|$)",{regex:new RegExp(o),paramNames:t,isCatchAll:s,priority:r}}normalizePrefix(e){return e.startsWith("/")?e.replace(/\/$/,""):`/${e.replace(/\/$/,"")}`}extractPrefixParams(e,t){const s=t.match(e.regex);if(!s)return{};const r={};return e.isCatchAll&&e.paramNames.length===1?r[e.paramNames[0]]=s[1]?.replace(/^\//,"")||"":e.paramNames.forEach((n,o)=>{r[n]=s[o+1]||""}),r}async handleNestedRouters(e,t){const s=[...this._nestedRouters].sort((r,n)=>n.priority-r.priority);for(const r of s){const n=t.match(r.regex);if(!n||n.index!==0)continue;const o=n[0],i=t.slice(o.length)||"/",u=this.extractPrefixParams(r,o),c={...e,params:{...e.params,...u}},l=async()=>await r.router.handleAtPath(c,i),d=await this.applyMiddlewaresWithList(c,r.middlewares,l);if(d)return d}return null}async handleLocalRoutes(e,t,s){const r=new Set;let n=!1;for(const o of this._routes){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;const u=s.match(o.regex);if(!u)continue;const c=Object.fromEntries(o.paramNames.map((d,h)=>[d,u[h+1]||""]));e.params={...e.params,...c},e.route={...e.route,id:o.path};const l=()=>o.handler(e);return await this.applyMiddlewaresWithList(e,o.middlewares,l)}if(r.size>0||t==="HEAD"&&n){const o=[...r].join(", ");return t==="OPTIONS"?new Response(null,{status:200,headers:{Allow:o}}):new Response("Method Not Allowed",{status:405,headers:{Allow:o}})}return new Response("Not Found",{status:404})}sortRoutes(){this._routes.sort((e,t)=>t.priority-e.priority),this.routesSorted=!0}sortWsRoutes(){this._wsRoutes.sort((e,t)=>t.priority-e.priority),this.wsRoutesSorted=!0}formatActionResult(e){return e instanceof Response?e:e?.type==="failure"&&"status"in e?R.fail(e.status,e.data):R.success(200,e??void 0)}handleActionError(e){if(L(e))return R.error(e.status,{message:e.statusText||"Error"});if(W(e)){const t=e.headers.get("Location")||"/";return R.redirect(e.status,t)}return console.error(e),R.error(500,{message:"Internal Server Error"})}static New(){return new x}}const R={success:(a=200,e)=>new Response(JSON.stringify({data:e,type:"success",status:a}),{status:a,headers:{"Content-Type":"application/json"}}),redirect:(a=302,e)=>new Response(JSON.stringify({location:e,type:"redirect",status:a}),{status:a,headers:{"Content-Type":"application/json"}}),error:(a=500,e)=>new Response(JSON.stringify({error:e,type:"error",status:a}),{status:a,headers:{"Content-Type":"application/json"}}),fail:(a=400,e)=>new Response(JSON.stringify({data:e,type:"failure",status:a}),{status:a,headers:{"Content-Type":"application/json"}})};class ee{constructor(e,t){this.raw=e.headers.get("cookie")??"",this.setCookieHeader=t}get(e,t){return v.parse(this.raw,t)[e]}getAll(e){return Object.entries(v.parse(this.raw,e)).filter(([,t])=>t!==void 0).map(([t,s])=>({name:t,value:s}))}set(e,t,s){this.setCookieHeader(v.serialize(e,t,s))}delete(e,t){this.set(e,"",{...t,maxAge:0})}}class q extends Error{constructor(e="Payload Too Large"){super(e),this.status=413,this.name="PayloadTooLargeError"}}class te extends x{constructor(e){super(),this.upgradeHandlerInstalled=!1,this.config=e??{type:"http",options:{}},this.wss=new C.WebSocketServer({noServer:!0,maxPayload:this.config.security?.maxWebSocketPayload??1024*1024})}get server(){if(!this._server){const e=(t,s)=>{this.handleRequest(t,s).catch(r=>{console.error("Unhandled request error:",r),s.statusCode=500,s.end("Internal Server Error")})};this._server=this.config.type==="https"?D.createServer(this.config.options,e):F.createServer(this.config.options,e)}return this._server}listen(...e){return this.upgradeHandlerInstalled||(this.installUpgradeHandler(),this.upgradeHandlerInstalled=!0),this.server.listen(...e),this}installUpgradeHandler(){this.server.on("upgrade",(e,t,s)=>{if(e.headers.upgrade?.toLowerCase()!=="websocket"){t.destroy();return}let r,n;try{r=this.toURL(e,!0),n=this.toRequest(e,r,!0)}catch{t.destroy();return}const o=this.toRequestEvent(n,r,{getClientAddress:()=>e.socket.remoteAddress??"127.0.0.1",setHeader:()=>{},pushSetCookie:()=>{}});this.canHandleWebSocket(o).then(i=>{if(!i||!this.isAllowedWebSocketOrigin(e)){t.destroy();return}this.wss.handleUpgrade(e,t,s,u=>{this.handleWebSocket(o,u).then(c=>{!c&&u.readyState===C.WebSocket.OPEN&&u.close(1008,"Route not found")}).catch(c=>{console.error("WebSocket routing error:",c),u.readyState===C.WebSocket.OPEN&&u.close(1011,"Internal error")})})}).catch(()=>t.destroy())})}close(e){this.wss.close(()=>{this.server.close(e)})}address(){return this.server.address()}get listening(){return this.server.listening}async handleRequest(e,t){if(!this.isRequestBodyAllowed(e)){t.statusCode=413,t.end("Payload Too Large");return}const s=this.toWebRequest(e),r=new URL(s.url),n={},o=[],i=this.toRequestEvent(s,r,{getClientAddress:()=>e.socket.remoteAddress??"127.0.0.1",setHeader:(c,l)=>{n[c.toLowerCase()]=l},pushSetCookie:c=>{o.push(c)}});let u;try{u=await this.handle(i)}catch(c){u=this.handleError(c)}for(const[c,l]of Object.entries(n))t.setHeader(c,l);o.length>0&&t.setHeader("Set-Cookie",o),await this.sendWebResponse(t,u)}toWebRequest(e){const t=this.toURL(e,!1);return this.toRequest(e,t,!1)}toRequest(e,t,s){const r={method:s?"GET":e.method,headers:this.toHeaders(e.headers),duplex:"half"};return!s&&e.method!=="GET"&&e.method!=="HEAD"&&(r.body=T.Readable.toWeb(this.wrapRequestBody(e))),new Request(t,r)}wrapRequestBody(e){const t=this.config.security?.maxRequestBodySize;if(!t)return e;let s=0;const r=new T.Transform({transform(n,o,i){if(s+=Buffer.byteLength(n),s>t){i(new q);return}i(null,n)}});return e.on("aborted",()=>r.destroy(new Error("Request aborted"))),e.on("error",n=>r.destroy(n)),e.pipe(r),r}toURL(e,t){const s=e.socket instanceof U.TLSSocket?t?"wss":"https":t?"ws":"http",r=this.resolveAuthority(e);return new URL(e.url??"/",`${s}://${r}`)}resolveAuthority(e){const t=this.config.security?.trustHostHeader?this.normalizeTrustedHost(e.headers.host):null;if(t)return t;const s=this.server.address();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"}normalizeTrustedHost(e){if(!e)return null;let t;try{t=new URL(`http://${e}`)}catch{return null}if(t.username||t.password||t.pathname!=="/"||t.search||t.hash)return null;const s=t.port?`${t.hostname}:${t.port}`:t.hostname,r=this.config.security?.allowedHosts;return!r||this.matchesValue(s,r)?s:null}matchesValue(e,t){return(Array.isArray(t)?t:[t]).some(r=>typeof r=="string"?r===e:r instanceof RegExp?r.test(e):r(e))}toHeaders(e){const t=new Headers;for(const[s,r]of Object.entries(e))if(r!==void 0){if(Array.isArray(r)){const n=s.toLowerCase()==="cookie"?r.join("; "):r.join(", ");t.set(s,n);continue}t.set(s,r)}return t}isRequestBodyAllowed(e){const t=this.config.security?.maxRequestBodySize;if(!t)return!0;const s=e.headers["content-length"];if(!s)return!0;const r=Number.parseInt(Array.isArray(s)?s[0]:s,10);return Number.isFinite(r)&&r<=t}handleError(e){if(e instanceof q)return new Response(e.message,{status:e.status});if(L(e))return new Response(JSON.stringify({error:e.statusText||"Error",status:e.status}),{status:e.status,headers:{"Content-Type":"application/json"}});if(W(e)){const t=e.headers.get("Location")||"/";return new Response(null,{status:e.status,headers:{Location:t}})}return console.error("Unhandled error:",e),new Response("Internal Server Error",{status:500})}async sendWebResponse(e,t){if(e.statusCode=t.status,t.headers.forEach((n,o)=>{e.setHeader(o,n)}),e.hasHeader("Server")||e.setHeader("Server","WebHTTPServer"),!t.body||this.shouldOmitResponseBody(t,e.req?.method)){e.end();return}const s=t.body.getReader(),r=T.Writable.toWeb(e).getWriter();try{for(;;){const{done:n,value:o}=await s.read();if(n)break;await r.write(o)}}finally{await r.close().catch(()=>{})}}shouldOmitResponseBody(e,t){return t==="HEAD"?!0:e.status===204||e.status===205||e.status===304}isAllowedWebSocketOrigin(e){const t=e.headers.origin;if(!t)return!0;const s=this.config.security?.allowedWebSocketOrigins;return s?this.matchesValue(t,s):!0}createEventFetch(e,t){return async(s,r)=>{const n=this.toEventFetchRequest(e,s,r);if(n.url.startsWith(`${e.url.origin}/`)){const o=this.toRequestEvent(n,new URL(n.url),t);try{return await this.handle(o)}catch(i){return this.handleError(i)}}return fetch(n)}}toEventFetchRequest(e,t,s){const r=t instanceof URL?t.toString():t,n=r instanceof Request?r:new Request(new URL(String(r),e.url),s);if(r instanceof Request&&!s)return this.withInheritedRequestHeaders(e,r);const o=new Headers(r instanceof Request?r.headers:s?.headers),i=s?.method??(r instanceof Request?r.method:void 0),u=s?.body??(r instanceof Request?r.body:void 0),c=u?"half":void 0;return this.inheritRequestHeader(e.request.headers,o,"cookie"),this.inheritRequestHeader(e.request.headers,o,"authorization"),new Request(n.url,{...s,method:i,headers:o,body:u,duplex:c})}withInheritedRequestHeaders(e,t){const s=new Headers(t.headers);return this.inheritRequestHeader(e.request.headers,s,"cookie"),this.inheritRequestHeader(e.request.headers,s,"authorization"),new Request(t,{headers:s,duplex:t.body?"half":void 0})}inheritRequestHeader(e,t,s){if(t.has(s))return;const r=e.get(s);r&&t.set(s,r)}toRequestEvent(e,t,s){const r=new ee(e,s.pushSetCookie),n=this.config,o={},i={name:"WebHTTPServer"},u=new Set,c={request:e,url:t,cookies:r,getClientAddress:s.getClientAddress,get locals(){return o},get platform(){return i},fetch:async(d,h)=>l(d,h),params:{},route:{id:null},setHeaders:d=>{for(const[h,p]of Object.entries(d)){const m=h.toLowerCase();if(m==="set-cookie")throw new TypeError("Use event.cookies for Set-Cookie headers");if(u.has(m))throw new TypeError(`Header "${h}" has already been set`);u.add(m),s.setHeader(h,p)}}},l=this.createEventFetch(c,s);return n.locals&&Object.assign(o,n.locals(c)),n.platform&&Object.assign(i,n.platform(c)),c}}const se={".avif":"image/avif",".css":"text/css; charset=utf-8",".gif":"image/gif",".html":"text/html; charset=utf-8",".ico":"image/x-icon",".jpg":"image/jpeg",".jpeg":"image/jpeg",".js":"text/javascript; charset=utf-8",".json":"application/json; charset=utf-8",".mjs":"text/javascript; charset=utf-8",".pdf":"application/pdf",".png":"image/png",".svg":"image/svg+xml; charset=utf-8",".txt":"text/plain; charset=utf-8",".wasm":"application/wasm",".webp":"image/webp",".xml":"application/xml; charset=utf-8"},re={index:"index.html",cacheControl:"public, max-age=0",dotFiles:"ignore"};async function k(a,e,t={}){const s=ce(e),r={...re,...t},n=await ne(a),o=oe(s,r.dotFiles);if(o instanceof Response)return o;const i=o.length>0?o.join(S.sep):"",u=S.resolve(n,i);if(!M(n,u))return new Response("Forbidden",{status:403});const c=await ae(u,n,r.index);if(c instanceof Response)return c;const l=await H.stat(c),d=new Headers({"content-length":String(l.size),"content-type":ie(c),"cache-control":r.cacheControl,"last-modified":l.mtime.toUTCString(),"x-content-type-options":"nosniff"});if(t.headers){const h=typeof t.headers=="function"?t.headers(c,l):t.headers;new Headers(h).forEach((p,m)=>{d.set(m,p)})}return new Response(z.Readable.toWeb($.createReadStream(c)),{status:200,headers:d})}async function ne(a){return H.realpath(a)}function oe(a,e){if(a.includes("\0"))return new Response("Bad Request",{status:400});const t=a.replace(/\\/g,"/").split("/").filter(Boolean),s=[];for(const r of t){let n;try{n=decodeURIComponent(r)}catch{return new Response("Bad Request",{status:400})}if(!(!n||n===".")){if(n===".."||n.includes("/")||n.includes("\\")||n.includes("\0"))return new Response("Forbidden",{status:403});if(n.startsWith(".")){if(e==="deny")return new Response("Forbidden",{status:403});if(e!=="allow")return new Response("Not Found",{status:404})}s.push(n)}}return s}async function ae(a,e,t){try{if((await H.lstat(a)).isDirectory()){const r=S.resolve(a,t);return _(r,e)}return _(a,e)}catch{return new Response("Not Found",{status:404})}}async function _(a,e){try{const t=await H.realpath(a);return M(e,t)?(await H.stat(t)).isFile()?t:new Response("Not Found",{status:404}):new Response("Forbidden",{status:403})}catch{return new Response("Not Found",{status:404})}}function M(a,e){const t=S.relative(a,e);return t===""||!t.startsWith("..")&&!S.isAbsolute(t)}function ie(a){return se[S.extname(a).toLowerCase()]??"application/octet-stream"}function ce(a){return typeof a.params.path=="string"?a.params.path:a.url.pathname.replace(/^\/+/,"")}const ue=(a,e={})=>t=>k(a,t,e),le=(a,...e)=>async t=>{const s={};for(const r of e){const n=await r(t);if(A(n))return n;n&&typeof n=="object"&&Object.assign(s,n)}return a(Object.assign(t,{context:s}))};function de(a,e={}){const t=[];if(e.comment)for(const s of e.comment.split(/\r?\n/))t.push(`: ${s}`);if(e.event&&t.push(`event: ${e.event}`),e.id&&t.push(`id: ${e.id}`),e.retry!==void 0&&t.push(`retry: ${e.retry}`),a!==void 0){const s=typeof a=="string"?a:JSON.stringify(a);for(const r of s.split(/\r?\n/))t.push(`data: ${r}`)}return`${t.join(`
|
|
2
|
-
`)}
|
|
3
|
-
|
|
4
|
-
`}const he=(a,e={})=>t=>{const s=new TextEncoder;let r=null,n=!1,o;const i=async()=>{if(!n){n=!0;try{await o?.()}finally{r?.close()}}},u=new ReadableStream({async start(c){r=c;const l=(d,h={})=>{n||c.enqueue(s.encode(de(d,h)))};t.request.signal.addEventListener("abort",()=>{i()},{once:!0});try{if(o=await a(t,l),!t.request.signal.aborted&&o===void 0)return;t.request.signal.aborted&&await i()}catch(d){n||c.error(d)}},async cancel(){await i()}});return new Response(u,{...e,headers:{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive",...e.headers}})},fe=async(a,e)=>{const t=JSON.stringify(await a);return new Response(t,{...e,headers:{"content-type":"application/json","content-length":Buffer.byteLength(t).toString(),...e?.headers}})};function pe(a,e){throw new Response(null,{status:a,headers:{location:e.toString()}})}function me(a,e){throw new Response(JSON.stringify(typeof e=="string"?{message:e}:e),{status:a,headers:{"content-type":"application/json"}})}const we=async(a,e)=>{const t=await a;return new Response(t,{...e,headers:{"content-type":"text/plain","content-length":Buffer.byteLength(t).toString(),...e?.headers}})},ge=async(a,e)=>{const t=await a;return new Response(t,{...e,headers:{"content-type":"text/html","content-length":Buffer.byteLength(t).toString(),...e?.headers}})};exports.Action=R;exports.CORS=Z;exports.RateLimiter=J;exports.RequestMethods=j;exports.Router=x;exports.WebServer=te;exports.dir=ue;exports.enhance=le;exports.error=me;exports.html=ge;exports.isHttpError=L;exports.isRedirect=W;exports.isResponse=A;exports.json=fe;exports.redirect=pe;exports.serveStatic=k;exports.sse=he;exports.text=we;
|
|
5
|
-
//# sourceMappingURL=index.cjs.js.map
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],enumerable:!0});return n||e(r,Symbol.toStringTag,{value:`Module`}),r};let n=require(`node:crypto`),r=require(`http`),i=require(`https`),a=require(`tls`),o=require(`stream`),s=require(`ws`),c=require(`cookie`),l=require(`node:fs`),u=require(`node:fs/promises`),d=require(`node:path`),f=require(`node:stream`);function p(e){return h(e)&&e.status>=400&&e.status<600}function m(e){return h(e)&&e.status>=300&&e.status<400}function h(e){return e instanceof Response}var ee=class{constructor(e){this.data=new Map,this.windowMs=e.windowMs,this.startCleanup()}async incr(e){let t=Date.now(),n=this.data.get(e);return!n||t>=n.reset?(n={count:1,reset:t+this.windowMs},this.data.set(e,n)):n.count++,{current:n.count,reset:n.reset}}startCleanup(){this.cleanupInterval=setInterval(()=>{let e=Date.now();for(let[t,{reset:n}]of this.data)e>=n&&this.data.delete(t)},Math.min(this.windowMs,3e5))}stop(){this.cleanupInterval&&clearInterval(this.cleanupInterval)}async resetAll(){this.data.clear()}},g=t({fixedWindowLimit:()=>_});function _(e){let{windowMs:t=6e4,max:n,key:r=e=>e.getClientAddress(),message:i=`Too many requests, please try again later.`,statusCode:a=429,headers:o=`include`,onRateLimit:s,store:c=new ee({windowMs:t})}=e;return async(e,t)=>{let l=`rl:${r(e)}`,{current:u,reset:d}=await c.incr(l),f=Math.ceil((d-Date.now())/1e3);if(u>n){s&&s(e,{current:u,max:n,key:l});let t={status:a,headers:new Headers},r=t.headers;o===`include`&&(r.set(`X-RateLimit-Limit`,String(n)),r.set(`X-RateLimit-Remaining`,`0`),r.set(`X-RateLimit-Reset`,String(Math.floor(d/1e3))),r.set(`Retry-After`,String(f)));let c;return typeof i==`string`?(c=i,r.set(`Content-Type`,`text/plain`)):(c=JSON.stringify(i),r.set(`Content-Type`,`application/json`)),new Response(c,t)}if(e.rateLimit={current:u,limit:n,reset:new Date(d),remaining:n-u},o===`include`){let t={"X-RateLimit-Limit":String(n),"X-RateLimit-Remaining":String(n-u),"X-RateLimit-Reset":String(Math.floor(d/1e3))},r=e.setHeaders;e.setHeaders=e=>{r({...t,...e})},r(t)}return t()}}var v=t({policy:()=>w}),y=[`GET`,`POST`,`PUT`,`DELETE`,`PATCH`,`HEAD`,`OPTIONS`],b=[`Accept`,`Accept-Language`,`Content-Language`,`Content-Type`,`Range`],x=[`Authorization`,`X-Auth-Token`,`X-Requested-With`,`X-CSRF-Token`,`X-HTTP-Method-Override`,`X-Forwarded-For`,`X-Real-IP`,`X-Custom-Header`];function S(e,t){return!e||!t?!1:t===`*`?!0:t===`null`?e===`null`:Array.isArray(t)?t.some(t=>S(e,t)):typeof t==`function`?t(e):t instanceof RegExp?t.test(e):e===t}function C(e,t){let{origin:n=`*`}=t;return e?n===`*`?t.credentials?e:`*`:S(e,n)?e:null:n===`*`?`*`:null}function w(e={}){let{methods:t=y,allowedHeaders:n=x,exposedHeaders:r,credentials:i=!1,maxAge:a=86400,onResponse:o}=e,s=t.join(`,`),c=[...b,...n].join(`,`),l=[[`Vary`,`Origin,Access-Control-Request-Method,Access-Control-Request-Headers`],[`Access-Control-Allow-Methods`,s],[`Access-Control-Allow-Headers`,c]];return r&&l.push([`Access-Control-Expose-Headers`,r.join(`,`)]),i&&l.push([`Access-Control-Allow-Credentials`,`true`]),a&&l.push([`Access-Control-Max-Age`,a.toString()]),async(t,n)=>{let r=t.request,i=r.headers.get(`Origin`),a=r.method===`OPTIONS`&&i!==null&&r.headers.has(`Access-Control-Request-Method`),s=C(i,e);if(a){if(!s)return new Response(null,{status:403});let e=new Response(null,{status:204});for(let[t,n]of l)e.headers.set(t,n);return e.headers.set(`Access-Control-Allow-Origin`,s),e}let c=await n();if(!c)return;if(!s)return c;let u=new Response(c.body,c);for(let[e,t]of l)u.headers.set(e,t);u.headers.set(`Access-Control-Allow-Origin`,s);let d=u;if(o){let e=o(d);e&&(d=e)}return d}}var T=t({headers:()=>D}),E={contentSecurityPolicy:`default-src 'self'; base-uri 'self'; frame-ancestors 'none'; object-src 'none'`,frameOptions:`DENY`,referrerPolicy:`no-referrer`,permissionsPolicy:`geolocation=(), microphone=(), camera=()`,crossOriginOpenerPolicy:`same-origin`,crossOriginResourcePolicy:`same-origin`,strictTransportSecurity:!1};function D(e={}){let t={...E,...e};return async(e,n)=>{let r=await n();if(!r)return;let i=new Headers(r.headers);return O(i,`content-security-policy`,t.contentSecurityPolicy),O(i,`x-frame-options`,t.frameOptions),O(i,`referrer-policy`,t.referrerPolicy),O(i,`permissions-policy`,t.permissionsPolicy),O(i,`cross-origin-opener-policy`,t.crossOriginOpenerPolicy),O(i,`cross-origin-resource-policy`,t.crossOriginResourcePolicy),O(i,`strict-transport-security`,t.strictTransportSecurity),new Response(r.body,{status:r.status,statusText:r.statusText,headers:i})}}function O(e,t,n){!n||e.has(t)||e.set(t,n)}var k=t({assign:()=>A});function A(e={}){let t=e.headerName?.toLowerCase()??`x-request-id`,r=e.generate??n.randomUUID;return async(e,n)=>{let i=e.request.headers.get(t)??r();Object.assign(e.locals,{requestId:i});let a=await n();if(!a)return;if(a.headers.has(t))return a;let o=new Headers(a.headers);return o.set(t,i),new Response(a.body,{status:a.status,statusText:a.statusText,headers:o})}}var j=t({deadline:()=>M});function M(e){let{ms:t,status:n=504,body:r=`Gateway Timeout`,onTimeout:i}=e;if(!Number.isFinite(t)||t<=0)throw TypeError(`Timeout.deadline requires a positive ms value`);return async(e,a)=>{let o=e.request,s=new AbortController,c=()=>s.abort();o.signal.addEventListener(`abort`,c,{once:!0});let l=AbortSignal.any([o.signal,s.signal]);e.request=new Request(o,{signal:l,duplex:o.body?`half`:void 0});let u;try{return await Promise.race([a(),new Promise(e=>{u=setTimeout(()=>{s.abort(),i?.(),e(new Response(r,{status:n}))},t)})])}finally{o.signal.removeEventListener(`abort`,c),u&&clearTimeout(u)}}}var N=[`GET`,`PUT`,`POST`,`DELETE`,`PATCH`,`HEAD`,`OPTIONS`],P=class{static{this.cache=new Map}static get(e){return this.cache.get(e)}static set(e,t){this.cache.set(e,t)}},F=class{constructor(){this._routes=[],this._wsRoutes=[],this._nestedRouters=[],this._middlewares=[],this._preHandlers=[],this._postHandlers=[],this.routesSorted=!1,this.wsRoutesSorted=!1}get routes(){return this._routes}get nestedRouters(){return this._nestedRouters}GET(e,t,...n){return this.addHandler(`GET`,e,t,n)}POST(e,t,...n){return this.addHandler(`POST`,e,t,n)}PUT(e,t,...n){return this.addHandler(`PUT`,e,t,n)}PATCH(e,t,...n){return this.addHandler(`PATCH`,e,t,n)}DELETE(e,t,...n){return this.addHandler(`DELETE`,e,t,n)}HEAD(e,t,...n){return this.addHandler(`HEAD`,e,t,n)}OPTIONS(e,t,...n){return this.addHandler(`OPTIONS`,e,t,n)}USE(e,t,...n){return N.forEach(r=>this.addHandler(r,e,t,n)),this}action(e,t,...n){return this.addHandler(`POST`,e,async e=>{try{let n=await t(e);return this.formatActionResult(n)}catch(e){return this.handleActionError(e)}},n)}use(e,t,...n){let r,i,a=n;Array.isArray(e)?([r,i]=e,a=e.length>2?e.slice(2):[]):(r=e,i=t);let o=this.normalizePrefix(r),{regex:s,paramNames:c,isCatchAll:l,priority:u}=this.createPrefixRegex(o);return this._nestedRouters.push({prefix:o,router:i,regex:s,paramNames:c,isCatchAll:l,priority:u,middlewares:a}),this}useMiddleware(...e){return this._middlewares.push(...e),this}pre(...e){return this._preHandlers.push(...e),this}post(...e){return this._postHandlers.push(...e),this}discard(e,t){return this._nestedRouters=this._nestedRouters.filter(t=>t.prefix!==e),this._routes=this._routes.filter(n=>n.path!==e||t&&n.method!==t),this}WS(e,t,...n){let{regex:r,paramNames:i,isCatchAll:a,priority:o}=this.createPathRegex(e);return this._wsRoutes.push({path:e,regex:r,paramNames:i,isCatchAll:a,priority:o,handler:t,middlewares:n}),this.wsRoutesSorted=!1,this}async canHandleWebSocket(e){return this.canHandleWebSocketAtPath(e,e.url.pathname)}async canHandleWebSocketAtPath(e,t){this.wsRoutesSorted||this.sortWsRoutes();for(let n of[...this._nestedRouters].sort((e,t)=>t.priority-e.priority)){let r=t.match(n.regex);if(!r||r.index!==0)continue;let i=r[0],a=t.slice(i.length)||`/`,o={...e,params:{...e.params,...this.extractPrefixParams(n,i)}};if(await n.router.canHandleWebSocketAtPath(o,a))return!0}for(let e of this._wsRoutes)if(e.regex.test(t))return!0;return!1}async handleWebSocket(e,t){return this.handleWebSocketAtPath(e,t,e.url.pathname)}async handleWebSocketAtPath(e,t,n){this.wsRoutesSorted||this.sortWsRoutes();for(let r of[...this._nestedRouters].sort((e,t)=>t.priority-e.priority)){let i=n.match(r.regex);if(!i||i.index!==0)continue;let a=i[0],o=n.slice(a.length)||`/`,s=this.extractPrefixParams(r,a),c={...e,params:{...e.params,...s}},l=[...this._middlewares,...r.middlewares];if(await this.applyMiddlewaresWithList(c,l,()=>r.router.handleWebSocketAtPath(c,t,o)))return!0}for(let r of this._wsRoutes){if(!r.regex.test(n))continue;let i=n.match(r.regex);if(!i)continue;let a=Object.fromEntries(r.paramNames.map((e,t)=>{let n=i[t+1];return n===void 0?void 0:[e,decodeURIComponent(n)]}).filter(e=>e!==void 0)),o={...e,params:{...e.params,...a},route:{...e.route,id:r.path},websocket:t},s=[...this._middlewares,...r.middlewares];if(await this.applyMiddlewaresWithList(o,s,()=>r.handler(o))!==void 0)return!0}return!1}async handle(e){return this.handleAtPath(e,e.url.pathname)}async handleAtPath(e,t){try{let n=e.request.method,r=await this.runPreHandlers(e);r||=await this.applyMiddlewaresWithList(e,this._middlewares,async()=>await this.handleNestedRouters(e,t)||(this.routesSorted||this.sortRoutes(),this.handleLocalRoutes(e,n,t)));let i=r||new Response(`No Content`,{status:204});return await this.runPostHandlers(e,i)}catch(e){if(h(e))return e;throw e}}async applyMiddlewaresWithList(e,t,n){let r=[...t],i=async t=>t>=r.length?n():r[t](e,()=>i(t+1));return i(0)}async runPreHandlers(e){for(let t of this._preHandlers){let n=await t(e);if(n instanceof Response)return n}}async runPostHandlers(e,t){let n=t;for(let t of this._postHandlers){let r=await t(e,n);r instanceof Response&&(n=r)}return n}addHandler(e,t,n,r=[]){let{regex:i,paramNames:a,isCatchAll:o,priority:s}=this.createPathRegex(t);return this._routes.push({method:e,path:t,regex:i,paramNames:a,isCatchAll:o,priority:s,handler:n,middlewares:r}),this.routesSorted=!1,this}createPathRegex(e){let t=P.get(e);if(t)return t;let n=[],r=!1,i,a=e.split(`/`).filter(Boolean);i=a.reduce((e,t)=>t.startsWith(`[...`)?e-10:t.startsWith(`[[`)?e-5:t.startsWith(`[`)?e-1:e+1,0);let o=`^`;for(let e of a)if(e.startsWith(`[...`)&&e.endsWith(`]`)){r=!0;let t=e.slice(4,-1);n.push(t),o+=`/(.+)`}else if(e.startsWith(`[[`)&&e.endsWith(`]]`)){let t=e.slice(2,-2);n.push(t),o+=`(?:/([^/]+))?`}else if(e.startsWith(`[`)&&e.endsWith(`]`)){let t=e.slice(1,-1);n.push(t),o+=`/([^/]+)`}else o+=`/`+e.replace(/[-/\\^$*+?.()|[\]{}]/g,`\\$&`);o+=`/?$`;let s={regex:new RegExp(o),paramNames:n,isCatchAll:r,priority:i};return P.set(e,s),s}createPrefixRegex(e){let t=[],n=!1,r,i=e.split(`/`).filter(Boolean);r=i.reduce((e,t)=>t.startsWith(`[...`)?e-10:t.startsWith(`[[`)?e-5:t.startsWith(`[`)?e-1:e+1,0);let a=`^`;for(let e of i)if(e.startsWith(`[...`)&&e.endsWith(`]`)){n=!0;let r=e.slice(4,-1);t.push(r),a+=`/(.+)`}else if(e.startsWith(`[[`)&&e.endsWith(`]]`)){let n=e.slice(2,-2);t.push(n),a+=`(?:/([^/]+))?`}else if(e.startsWith(`[`)&&e.endsWith(`]`)){let n=e.slice(1,-1);t.push(n),a+=`/([^/]+)`}else a+=`/`+e.replace(/[-/\\^$*+?.()|[\]{}]/g,`\\$&`);return a+=`(?=/|$)`,{regex:new RegExp(a),paramNames:t,isCatchAll:n,priority:r}}normalizePrefix(e){return e.startsWith(`/`)?e.replace(/\/$/,``):`/${e.replace(/\/$/,``)}`}extractPrefixParams(e,t){let n=t.match(e.regex);if(!n)return{};let r={};if(e.isCatchAll&&e.paramNames.length===1){let t=n[1]?.replace(/^\//,``);t!==void 0&&(r[e.paramNames[0]]=decodeURIComponent(t))}else e.paramNames.forEach((e,t)=>{let i=n[t+1];i!==void 0&&(r[e]=decodeURIComponent(i))});return r}async handleNestedRouters(e,t){let n=[...this._nestedRouters].sort((e,t)=>t.priority-e.priority);for(let r of n){let n=t.match(r.regex);if(!n||n.index!==0)continue;let i=n[0],a=t.slice(i.length)||`/`,o=this.extractPrefixParams(r,i),s={...e,params:{...e.params,...o}},c=await this.applyMiddlewaresWithList(s,r.middlewares,async()=>await r.router.handleAtPath(s,a));if(c)return c}return null}async handleLocalRoutes(e,t,n){let r=new Set,i=!1;for(let a of this._routes){if(!a.regex.test(n)||(r.add(a.method),a.method===`GET`&&(i=!0,r.add(`HEAD`)),!(a.method===t||t===`HEAD`&&a.method===`GET`)))continue;let o=n.match(a.regex);if(!o)continue;let s=Object.fromEntries(a.paramNames.map((e,t)=>{let n=o[t+1];return n===void 0?void 0:[e,decodeURIComponent(n)]}).filter(e=>e!==void 0));return e.params={...e.params,...s},e.route={...e.route,id:a.path},await this.applyMiddlewaresWithList(e,a.middlewares,()=>a.handler(e))}if(r.size>0||t===`HEAD`&&i){let e=[...r].join(`, `);return t===`OPTIONS`?new Response(null,{status:200,headers:{Allow:e}}):new Response(`Method Not Allowed`,{status:405,headers:{Allow:e}})}return new Response(`Not Found`,{status:404})}sortRoutes(){this._routes.sort((e,t)=>t.priority-e.priority),this.routesSorted=!0}sortWsRoutes(){this._wsRoutes.sort((e,t)=>t.priority-e.priority),this.wsRoutesSorted=!0}formatActionResult(e){return e instanceof Response?e:e?.type===`failure`&&`status`in e?I.fail(e.status,e.data):I.success(200,e??void 0)}handleActionError(e){if(p(e))return I.error(e.status,{message:e.statusText||`Error`});if(m(e)){let t=e.headers.get(`Location`)||`/`;return I.redirect(e.status,t)}return console.error(e),I.error(500,{message:`Internal Server Error`})}},I={success:(e=200,t)=>new Response(JSON.stringify({data:t,type:`success`,status:e}),{status:e,headers:{"Content-Type":`application/json`}}),redirect:(e=302,t)=>new Response(JSON.stringify({location:t,type:`redirect`,status:e}),{status:e,headers:{"Content-Type":`application/json`}}),error:(e=500,t)=>new Response(JSON.stringify({error:t,type:`error`,status:e}),{status:e,headers:{"Content-Type":`application/json`}}),fail:(e=400,t)=>new Response(JSON.stringify({data:t,type:`failure`,status:e}),{status:e,headers:{"Content-Type":`application/json`}})},L=class{constructor(e,t){this.raw=e.headers.get(`cookie`)??``,this.setCookieHeader=t}get(e,t){return(0,c.parse)(this.raw,t)[e]}getAll(e){return Object.entries((0,c.parse)(this.raw,e)).filter(([,e])=>e!==void 0).map(([e,t])=>({name:e,value:t}))}set(e,t,n){this.setCookieHeader((0,c.serialize)(e,t,n))}delete(e,t){this.set(e,``,{...t,maxAge:0})}},R=class extends Error{constructor(e=`Payload Too Large`){super(e),this.status=413,this.name=`PayloadTooLargeError`}},z=class extends F{constructor(e){super(),this.upgradeHandlerInstalled=!1,this.config=e??{type:`http`,options:{}},this.wss=new s.WebSocketServer({noServer:!0,maxPayload:this.config.security?.maxWebSocketPayload??1024*1024})}get server(){if(!this._server){let e=(e,t)=>{this.handleRequest(e,t).catch(e=>{console.error(`Unhandled request error:`,e),t.statusCode=500,t.end(`Internal Server Error`)})};this._server=this.config.type===`https`?(0,i.createServer)(this.config.options,e):(0,r.createServer)(this.config.options,e),this.configureServerTimeouts(this._server)}return this._server}listen(...e){return this.upgradeHandlerInstalled||=(this.installUpgradeHandler(),!0),this.server.listen(...e),this}installUpgradeHandler(){this.server.on(`upgrade`,(e,t,n)=>{if(e.headers.upgrade?.toLowerCase()!==`websocket`){t.destroy();return}let r,i;try{r=this.toURL(e,!0),i=this.toRequest(e,r,!0)}catch{t.destroy();return}let a=this.toRequestEvent(i,r,{getClientAddress:()=>this.getClientAddress(e),setHeader:()=>{},pushSetCookie:()=>{}});this.canHandleWebSocket(a).then(r=>{if(!r||!this.isAllowedWebSocketOrigin(e)){t.destroy();return}this.wss.handleUpgrade(e,t,n,e=>{this.handleWebSocket(a,e).then(t=>{!t&&e.readyState===s.WebSocket.OPEN&&e.close(1008,`Route not found`)}).catch(t=>{console.error(`WebSocket routing error:`,t),e.readyState===s.WebSocket.OPEN&&e.close(1011,`Internal error`)})})}).catch(()=>t.destroy())})}close(e){this.wss.close(()=>{this.server.close(e)})}address(){return this.server.address()}get listening(){return this.server.listening}async handleRequest(e,t){if(!this.isRequestBodyAllowed(e)){t.statusCode=413,t.end(`Payload Too Large`);return}let n=new AbortController,r=()=>n.abort();e.once(`aborted`,r),e.once(`close`,r),t.once(`close`,r);let i=this.toWebRequest(e,n.signal),a=new URL(i.url),o={},s=[],c=this.toRequestEvent(i,a,{getClientAddress:()=>this.getClientAddress(e),setHeader:(e,t)=>{o[e.toLowerCase()]=t},pushSetCookie:e=>{s.push(e)}}),l;try{l=await this.handle(c)}catch(e){l=this.handleError(e)}for(let[e,n]of Object.entries(o))t.setHeader(e,n);s.length>0&&t.setHeader(`Set-Cookie`,s),await this.sendWebResponse(t,l)}toWebRequest(e,t){let n=this.toURL(e,!1);return this.toRequest(e,n,!1,t)}toRequest(e,t,n,r){let i={method:n?`GET`:e.method,headers:this.toHeaders(e.headers),signal:r,duplex:`half`};return!n&&e.method!==`GET`&&e.method!==`HEAD`&&(i.body=o.Readable.toWeb(this.wrapRequestBody(e))),new Request(t,i)}wrapRequestBody(e){let t=this.config.security?.maxRequestBodySize;if(!t)return e;let n=0,r=new o.Transform({transform(e,r,i){if(n+=Buffer.byteLength(e),n>t){i(new R);return}i(null,e)}});return e.on(`aborted`,()=>r.destroy(Error(`Request aborted`))),e.on(`error`,e=>r.destroy(e)),e.pipe(r),r}toURL(e,t){let n=this.resolveProtocol(e,t),r=this.resolveAuthority(e);return new URL(e.url??`/`,`${n}://${r}`)}resolveProtocol(e,t){let n=this.getTrustedForwardedHeader(e,`x-forwarded-proto`)?.split(`,`)[0]?.trim().toLowerCase();return n===`http`||n===`https`?t?n===`https`?`wss`:`ws`:n:e.socket instanceof a.TLSSocket?t?`wss`:`https`:t?`ws`:`http`}resolveAuthority(e){let t=this.getTrustedForwardedHeader(e,`x-forwarded-host`)??e.headers.host,n=this.config.security?.trustHostHeader?this.normalizeTrustedHost(t):null;if(n)return n;let r=this.server.address();return r&&typeof r==`object`?`${r.address.includes(`:`)?`[${r.address}]`:r.address}:${r.port}`:e.socket.localPort?`127.0.0.1:${e.socket.localPort}`:`localhost`}getClientAddress(e){let t=e.socket.remoteAddress??`127.0.0.1`;if(!this.isTrustedProxy(t))return this.normalizeAddress(t);let n=e.headers[`x-forwarded-for`];if(!n)return this.normalizeAddress(t);let r=this.parseForwardedHeader(n);r.push(t);for(let e=r.length-1;e>=0;--e){let t=r[e];if(!this.isTrustedProxy(t))return this.normalizeAddress(t)}return this.normalizeAddress(r[0]??t)}normalizeTrustedHost(e){if(!e)return null;let t;try{t=new URL(`http://${e}`)}catch{return null}if(t.username||t.password||t.pathname!==`/`||t.search||t.hash)return null;let n=t.port?`${t.hostname}:${t.port}`:t.hostname,r=this.config.security?.allowedHosts;return!r||this.matchesValue(n,r)?n:null}matchesValue(e,t){return(Array.isArray(t)?t:[t]).some(t=>typeof t==`string`?t===e:t instanceof RegExp?t.test(e):t(e))}configureServerTimeouts(e){let t=this.config.security,n=this.isDevelopment();e.headersTimeout=t?.headersTimeoutMs??3e4,e.requestTimeout=t?.requestTimeoutMs??(n?0:6e4),e.keepAliveTimeout=t?.keepAliveTimeoutMs??5e3}isDevelopment(){return process.env.NODE_ENV!==`production`}getTrustedForwardedHeader(e,t){if(!this.isTrustedProxy(e.socket.remoteAddress??``))return;let n=e.headers[t];return Array.isArray(n)?n[0]:n}isTrustedProxy(e){let t=this.config.security?.trustedProxies;if(!t)return!1;let n=this.normalizeAddress(e);return n!==e&&this.matchesValue(n,t)?!0:this.matchesValue(e,t)}normalizeAddress(e){return e.startsWith(`::ffff:`)?e.slice(7):e}parseForwardedHeader(e){return(Array.isArray(e)?e.join(`,`):e).split(`,`).map(e=>this.normalizeAddress(e.trim())).filter(Boolean)}toHeaders(e){let t=new Headers;for(let[n,r]of Object.entries(e))if(r!==void 0){if(Array.isArray(r)){let e=n.toLowerCase()===`cookie`?r.join(`; `):r.join(`, `);t.set(n,e);continue}t.set(n,r)}return t}isRequestBodyAllowed(e){let t=this.config.security?.maxRequestBodySize;if(!t)return!0;let n=e.headers[`content-length`];if(!n)return!0;let r=Number.parseInt(Array.isArray(n)?n[0]:n,10);return Number.isFinite(r)&&r<=t}handleError(e){if(e instanceof R)return new Response(e.message,{status:e.status});if(p(e))return new Response(JSON.stringify({error:e.statusText||`Error`,status:e.status}),{status:e.status,headers:{"Content-Type":`application/json`}});if(m(e)){let t=e.headers.get(`Location`)||`/`;return new Response(null,{status:e.status,headers:{Location:t}})}return console.error(`Unhandled error:`,e),new Response(`Internal Server Error`,{status:500})}async sendWebResponse(e,t){if(e.statusCode=t.status,t.headers.forEach((t,n)=>{e.setHeader(n,t)}),e.hasHeader(`Server`)||e.setHeader(`Server`,`WebHTTPServer`),!t.body||this.shouldOmitResponseBody(t,e.req?.method)){e.end();return}let n=t.body.getReader(),r=o.Writable.toWeb(e).getWriter(),i=!1,a=async()=>{i||(i=!0,await n.cancel().catch(()=>{}))},s=()=>{a()};e.once(`close`,s);try{for(;;){let{done:e,value:t}=await n.read();if(e)break;await r.write(t)}i=!0}catch(e){if(await a(),!this.isPrematureCloseError(e))throw e}finally{e.off(`close`,s),await r.close().catch(()=>{})}}isPrematureCloseError(e){if(!(e instanceof Error))return!1;let t=`code`in e?e.code:void 0;return t===`ABORT_ERR`||t===`ERR_STREAM_PREMATURE_CLOSE`?!0:e.name===`AbortError`}shouldOmitResponseBody(e,t){return t===`HEAD`?!0:e.status===204||e.status===205||e.status===304}isAllowedWebSocketOrigin(e){let t=e.headers.origin;if(!t)return!0;let n=this.config.security?.allowedWebSocketOrigins;return n?this.matchesValue(t,n):!0}createEventFetch(e,t){return async(n,r)=>{let i=this.toEventFetchRequest(e,n,r);if(i.url.startsWith(`${e.url.origin}/`)){let e=this.toRequestEvent(i,new URL(i.url),t);try{return await this.handle(e)}catch(e){return this.handleError(e)}}return fetch(i)}}toEventFetchRequest(e,t,n){let r=t instanceof URL?t.toString():t,i=r instanceof Request?r:new Request(new URL(String(r),e.url),n);if(r instanceof Request&&!n)return this.withInheritedRequestHeaders(e,r);let a=new Headers(r instanceof Request?r.headers:n?.headers),o=n?.method??(r instanceof Request?r.method:void 0),s=n?.body??(r instanceof Request?r.body:void 0),c=s?`half`:void 0;return this.inheritRequestHeader(e.request.headers,a,`cookie`),this.inheritRequestHeader(e.request.headers,a,`authorization`),new Request(i.url,{...n,method:o,headers:a,body:s,signal:n?.signal??e.request.signal,duplex:c})}withInheritedRequestHeaders(e,t){let n=new Headers(t.headers);return this.inheritRequestHeader(e.request.headers,n,`cookie`),this.inheritRequestHeader(e.request.headers,n,`authorization`),new Request(t,{headers:n,signal:e.request.signal,duplex:t.body?`half`:void 0})}inheritRequestHeader(e,t,n){if(t.has(n))return;let r=e.get(n);r&&t.set(n,r)}toRequestEvent(e,t,n){let r=new L(e,n.pushSetCookie),i=this.config,a={},o={name:`node-webserver`,dev:this.isDevelopment()},s=new Set,c={request:e,url:t,cookies:r,getClientAddress:n.getClientAddress,get locals(){return a},get platform(){return o},fetch:async(e,t)=>l(e,t),params:{},route:{id:null},setHeaders:e=>{for(let[t,r]of Object.entries(e)){let e=t.toLowerCase();if(e===`set-cookie`)throw TypeError(`Use event.cookies for Set-Cookie headers`);if(s.has(e))throw TypeError(`Header "${t}" has already been set`);s.add(e),n.setHeader(t,r)}}},l=this.createEventFetch(c,n);return i.locals&&Object.assign(a,i.locals(c)),i.platform&&Object.assign(o,i.platform(c)),c}},B={".avif":`image/avif`,".css":`text/css; charset=utf-8`,".gif":`image/gif`,".html":`text/html; charset=utf-8`,".ico":`image/x-icon`,".jpg":`image/jpeg`,".jpeg":`image/jpeg`,".js":`text/javascript; charset=utf-8`,".json":`application/json; charset=utf-8`,".mjs":`text/javascript; charset=utf-8`,".pdf":`application/pdf`,".png":`image/png`,".svg":`image/svg+xml; charset=utf-8`,".txt":`text/plain; charset=utf-8`,".wasm":`application/wasm`,".webp":`image/webp`,".xml":`application/xml; charset=utf-8`},V={index:`index.html`,cacheControl:`public, max-age=0`,dotFiles:`ignore`};async function H(e,t,n={}){let r=Y(t),i={...V,...n},a=await U(e),o=W(r,i.dotFiles);if(o instanceof Response)return o;let s=(0,d.resolve)(a,o.length>0?o.join(d.sep):``);if(!q(a,s))return new Response(`Forbidden`,{status:403});let c=await G(s,a,i.index);if(c instanceof Response)return c;let p=await(0,u.stat)(c),m=new Headers({"content-length":String(p.size),"content-type":J(c),"cache-control":i.cacheControl,"last-modified":p.mtime.toUTCString(),"x-content-type-options":`nosniff`});if(n.headers){let e=typeof n.headers==`function`?n.headers(c,p):n.headers;new Headers(e).forEach((e,t)=>{m.set(t,e)})}return new Response(f.Readable.toWeb((0,l.createReadStream)(c)),{status:200,headers:m})}async function U(e){return(0,u.realpath)(e)}function W(e,t){if(e.includes(`\0`))return new Response(`Bad Request`,{status:400});let n=e.replace(/\\/g,`/`).split(`/`).filter(Boolean),r=[];for(let e of n){let n;try{n=decodeURIComponent(e)}catch{return new Response(`Bad Request`,{status:400})}if(!(!n||n===`.`)){if(n===`..`||n.includes(`/`)||n.includes(`\\`)||n.includes(`\0`))return new Response(`Forbidden`,{status:403});if(n.startsWith(`.`)){if(t===`deny`)return new Response(`Forbidden`,{status:403});if(t!==`allow`)return new Response(`Not Found`,{status:404})}r.push(n)}}return r}async function G(e,t,n){try{return(await(0,u.lstat)(e)).isDirectory()?K((0,d.resolve)(e,n),t):K(e,t)}catch{return new Response(`Not Found`,{status:404})}}async function K(e,t){try{let n=await(0,u.realpath)(e);return q(t,n)?(await(0,u.stat)(n)).isFile()?n:new Response(`Not Found`,{status:404}):new Response(`Forbidden`,{status:403})}catch{return new Response(`Not Found`,{status:404})}}function q(e,t){let n=(0,d.relative)(e,t);return n===``||!n.startsWith(`..`)&&!(0,d.isAbsolute)(n)}function J(e){return B[(0,d.extname)(e).toLowerCase()]??`application/octet-stream`}function Y(e){return typeof e.params.path==`string`?e.params.path:e.url.pathname.replace(/^\/+/,``)}var X=(e,t={})=>n=>H(e,n,t),Z=(e,...t)=>async n=>{let r={};for(let e of t){let t=await e(n);if(h(t))return t;t&&typeof t==`object`&&Object.assign(r,t)}return e(Object.assign(n,{context:r}))};function Q(e,t={}){let n=[];if(t.comment)for(let e of t.comment.split(/\r?\n/))n.push(`: ${e}`);if(t.event&&n.push(`event: ${t.event}`),t.id&&n.push(`id: ${t.id}`),t.retry!==void 0&&n.push(`retry: ${t.retry}`),e!==void 0){let t=typeof e==`string`?e:JSON.stringify(e);for(let e of t.split(/\r?\n/))n.push(`data: ${e}`)}return`${n.join(`
|
|
2
|
+
`)}\n\n`}var $=(e,t={})=>n=>{let r=new TextEncoder,i=null,a=!1,o,s=async()=>{if(!a){a=!0;try{await o?.()}finally{try{i?.close()}catch{}}}},c=new ReadableStream({async start(t){i=t;let c=(e,n={})=>{a||t.enqueue(r.encode(Q(e,n)))};n.request.signal.addEventListener(`abort`,()=>{s()},{once:!0});try{if(o=await e(n,c),n.request.signal.aborted){await s();return}o===void 0&&await s()}catch(e){a||t.error(e)}},async cancel(){await s()}});return new Response(c,{...t,headers:{"content-type":`text/event-stream`,"cache-control":`no-cache`,connection:`keep-alive`,...t.headers}})},te=async(e,t)=>{let n=JSON.stringify(await e);return new Response(n,{...t,headers:{"content-type":`application/json`,"content-length":Buffer.byteLength(n).toString(),...t?.headers}})};function ne(e,t){throw new Response(null,{status:e,headers:{location:t.toString()}})}function re(e,t){throw new Response(JSON.stringify(typeof t==`string`?{message:t}:t),{status:e,headers:{"content-type":`application/json`}})}var ie=async(e,t)=>{let n=await e;return new Response(n,{...t,headers:{"content-type":`text/plain`,"content-length":Buffer.byteLength(n).toString(),...t?.headers}})},ae=async(e,t)=>{let n=await e;return new Response(n,{...t,headers:{"content-type":`text/html`,"content-length":Buffer.byteLength(n).toString(),...t?.headers}})};exports.Action=I,Object.defineProperty(exports,`CORS`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`RateLimiter`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`RequestId`,{enumerable:!0,get:function(){return k}}),exports.RequestMethods=N,exports.Router=F,Object.defineProperty(exports,`Security`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`Timeout`,{enumerable:!0,get:function(){return j}}),exports.WebServer=z,exports.dir=X,exports.enhance=Z,exports.error=re,exports.html=ae,exports.isHttpError=p,exports.isRedirect=m,exports.isResponse=h,exports.json=te,exports.redirect=ne,exports.serveStatic=H,exports.sse=$,exports.text=ie;
|
|
3
|
+
//# sourceMappingURL=index.cjs.js.map
|