@sourceregistry/node-webserver 1.2.1 → 1.2.3
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 +25 -0
- package/dist/helpers/sse.d.ts +12 -0
- package/dist/{static.d.ts → helpers/static.d.ts} +3 -1
- package/dist/index.cjs.js +4 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.es.js +335 -276
- package/dist/index.es.js.map +1 -1
- package/dist/types/router.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/static.ts","../src/utils.ts","../src/middlewares/ratelimiter/InMemory.ts","../src/middlewares/ratelimiter/index.ts","../src/middlewares/cros/index.ts","../src/types/RequestMethod.ts","../src/types/router.ts","../src/types/Cookies.ts","../src/types/server.ts","../src/index.ts"],"sourcesContent":["import { createReadStream } from \"node:fs\";\nimport { lstat, realpath, stat } from \"node:fs/promises\";\nimport { extname, isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { Readable } from \"node:stream\";\n\nimport type { RequestEvent } from \"./types\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".avif\": \"image/avif\",\n \".css\": \"text/css; charset=utf-8\",\n \".gif\": \"image/gif\",\n \".html\": \"text/html; charset=utf-8\",\n \".ico\": \"image/x-icon\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".mjs\": \"text/javascript; charset=utf-8\",\n \".pdf\": \"application/pdf\",\n \".png\": \"image/png\",\n \".svg\": \"image/svg+xml; charset=utf-8\",\n \".txt\": \"text/plain; charset=utf-8\",\n \".wasm\": \"application/wasm\",\n \".webp\": \"image/webp\",\n \".xml\": \"application/xml; charset=utf-8\"\n};\n\nexport type StaticOptions = {\n index?: string;\n cacheControl?: string;\n dotFiles?: \"allow\" | \"deny\" | \"ignore\";\n headers?: HeadersInit | ((filePath: string, stats: Awaited<ReturnType<typeof stat>>) => HeadersInit);\n};\n\nconst DEFAULT_STATIC_OPTIONS: Required<Omit<StaticOptions, \"headers\">> = {\n index: \"index.html\",\n cacheControl: \"public, max-age=0\",\n dotFiles: \"ignore\"\n};\n\nexport async function serveStatic(root: string, event: RequestEvent, options: StaticOptions = {}): Promise<Response> {\n const requestPath = getStaticRequestPath(event);\n const resolvedOptions = {\n ...DEFAULT_STATIC_OPTIONS,\n ...options\n };\n\n const rootPath = await resolveStaticRoot(root);\n const normalizedPath = normalizeStaticRequestPath(requestPath, resolvedOptions.dotFiles);\n if (normalizedPath instanceof Response) {\n return normalizedPath;\n }\n\n const targetPath = normalizedPath.length > 0 ? normalizedPath.join(sep) : \"\";\n const candidatePath = resolve(rootPath, targetPath);\n\n if (!isPathInside(rootPath, candidatePath)) {\n return new Response(\"Forbidden\", { status: 403 });\n }\n\n const filePath = await resolveStaticFile(candidatePath, rootPath, resolvedOptions.index);\n if (filePath instanceof Response) {\n return filePath;\n }\n\n const fileStats = await stat(filePath);\n const headers = new Headers({\n \"content-length\": String(fileStats.size),\n \"content-type\": getMimeType(filePath),\n \"cache-control\": resolvedOptions.cacheControl,\n \"last-modified\": fileStats.mtime.toUTCString(),\n \"x-content-type-options\": \"nosniff\"\n });\n\n if (options.headers) {\n const extraHeaders = typeof options.headers === \"function\"\n ? options.headers(filePath, fileStats)\n : options.headers;\n new Headers(extraHeaders).forEach((value, key) => {\n headers.set(key, value);\n });\n }\n\n return new Response(Readable.toWeb(createReadStream(filePath)) as ReadableStream<Uint8Array>, {\n status: 200,\n headers\n });\n}\n\nasync function resolveStaticRoot(root: string): Promise<string> {\n return realpath(root);\n}\n\nfunction normalizeStaticRequestPath(requestPath: string, dotFiles: StaticOptions[\"dotFiles\"]): string[] | Response {\n if (requestPath.includes(\"\\0\")) {\n return new Response(\"Bad Request\", { status: 400 });\n }\n\n const segments = requestPath\n .replace(/\\\\/g, \"/\")\n .split(\"/\")\n .filter(Boolean);\n\n const normalizedSegments: string[] = [];\n\n for (const segment of segments) {\n let decoded: string;\n try {\n decoded = decodeURIComponent(segment);\n } catch {\n return new Response(\"Bad Request\", { status: 400 });\n }\n\n if (!decoded || decoded === \".\") {\n continue;\n }\n\n if (decoded === \"..\" || decoded.includes(\"/\") || decoded.includes(\"\\\\\") || decoded.includes(\"\\0\")) {\n return new Response(\"Forbidden\", { status: 403 });\n }\n\n if (decoded.startsWith(\".\")) {\n if (dotFiles === \"deny\") {\n return new Response(\"Forbidden\", { status: 403 });\n }\n if (dotFiles !== \"allow\") {\n return new Response(\"Not Found\", { status: 404 });\n }\n }\n\n normalizedSegments.push(decoded);\n }\n\n return normalizedSegments;\n}\n\nasync function resolveStaticFile(candidatePath: string, rootPath: string, indexFile: string): Promise<string | Response> {\n try {\n const candidateStats = await lstat(candidatePath);\n\n if (candidateStats.isDirectory()) {\n const indexPath = resolve(candidatePath, indexFile);\n return ensureResolvedFile(indexPath, rootPath);\n }\n\n return ensureResolvedFile(candidatePath, rootPath);\n } catch {\n return new Response(\"Not Found\", { status: 404 });\n }\n}\n\nasync function ensureResolvedFile(candidatePath: string, rootPath: string): Promise<string | Response> {\n try {\n const resolvedPath = await realpath(candidatePath);\n if (!isPathInside(rootPath, resolvedPath)) {\n return new Response(\"Forbidden\", { status: 403 });\n }\n\n const resolvedStats = await stat(resolvedPath);\n if (!resolvedStats.isFile()) {\n return new Response(\"Not Found\", { status: 404 });\n }\n\n return resolvedPath;\n } catch {\n return new Response(\"Not Found\", { status: 404 });\n }\n}\n\nfunction isPathInside(rootPath: string, targetPath: string): boolean {\n const relativePath = relative(rootPath, targetPath);\n return relativePath === \"\" || (!relativePath.startsWith(\"..\") && !isAbsolute(relativePath));\n}\n\nfunction getMimeType(filePath: string): string {\n return MIME_TYPES[extname(filePath).toLowerCase()] ?? \"application/octet-stream\";\n}\n\nfunction getStaticRequestPath(event: RequestEvent): string {\n if (typeof event.params.path === \"string\") {\n return event.params.path;\n }\n\n return event.url.pathname.replace(/^\\/+/, \"\");\n}\n","export function isHttpError(err: unknown): err is Response {\n return isResponse(err) && err.status >= 400 && err.status < 600;\n}\n\nexport function isRedirect(err: unknown): err is Response {\n return isResponse(err) && err.status >= 300 && err.status < 400;\n}\n\nexport function isResponse(err: unknown): err is Response {\n return err instanceof Response;\n}\n","import type {RateLimitStore} from \"./storage\";\n\nexport class MemoryStore implements RateLimitStore {\n private readonly windowMs: number;\n private data = new Map<string, { count: number; reset: number }>();\n private cleanupInterval?: NodeJS.Timeout;\n\n constructor(opts: { windowMs: number }) {\n this.windowMs = opts.windowMs;\n this.startCleanup();\n }\n\n async incr(key: string): Promise<{ current: number; reset: number }> {\n const now = Date.now();\n let record = this.data.get(key);\n\n if (!record || now >= record.reset) {\n const reset = now + this.windowMs;\n record = {count: 1, reset};\n this.data.set(key, record);\n } else {\n record.count++;\n }\n\n return {current: record.count, reset: record.reset};\n }\n\n private startCleanup() {\n this.cleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [key, {reset}] of this.data) {\n if (now >= reset) {\n this.data.delete(key);\n }\n }\n }, Math.min(this.windowMs, 300_000)); // Max 5 min interval\n }\n\n stop() {\n if (this.cleanupInterval) clearInterval(this.cleanupInterval);\n }\n\n async resetAll() {\n this.data.clear();\n }\n}\n","import type { RateLimitStore } from './storage';\nimport type {Middleware, RequestEvent} from \"../../types\";\nimport {MemoryStore} from \"./InMemory\";\n\nexport type Options = {\n /**\n * Window duration in milliseconds\n * @default 60_000 (1 minute)\n */\n windowMs?: number;\n\n /**\n * Max number of requests per window\n */\n max: number;\n\n /**\n * Function to generate key for rate limiting\n * @default IP address\n */\n key?: (event: RequestEvent) => string;\n\n /**\n * Custom error message (string or JSON)\n * @default \"Too many requests, please try again later.\"\n */\n message?: string | Record<string, any>;\n\n /**\n * HTTP status code to return\n * @default 429\n */\n statusCode?: number;\n\n /**\n * Whether to add rate limit headers\n * @default 'include'\n */\n headers?: 'include' | 'remove';\n\n /**\n * Called when rate limit is hit\n */\n onRateLimit?: (event: RequestEvent, info: { current: number; max: number; key: string }) => void;\n\n /**\n * Storage backend\n * @default MemoryStore\n */\n store?: RateLimitStore;\n};\n\n/**\n * Fixed window rate limiter middleware\n */\nexport function fixedWindowLimit(options: Options): Middleware {\n const {\n windowMs = 60_000,\n max,\n key = (event) => event.getClientAddress(),\n message = 'Too many requests, please try again later.',\n statusCode = 429,\n headers = 'include',\n onRateLimit,\n store = new MemoryStore({ windowMs })\n } = options;\n\n return async (event, next) => {\n const rateLimitKey = `rl:${key(event)}`;\n const { current, reset } = await store.incr(rateLimitKey);\n\n const retryAfter = Math.ceil((reset - Date.now()) / 1000);\n\n if (current > max) {\n if (onRateLimit) {\n onRateLimit(event, { current, max, key: rateLimitKey });\n }\n\n const responseInit: ResponseInit = {\n status: statusCode,\n headers: new Headers()\n };\n\n const header = responseInit.headers! as Headers;\n\n if (headers === 'include') {\n header.set('X-RateLimit-Limit', String(max));\n header.set('X-RateLimit-Remaining', '0');\n header.set('X-RateLimit-Reset', String(Math.floor(reset / 1000)));\n header.set('Retry-After', String(retryAfter));\n }\n\n let body: string;\n if (typeof message === 'string') {\n body = message;\n header.set('Content-Type', 'text/plain');\n } else {\n body = JSON.stringify(message);\n header.set('Content-Type', 'application/json');\n }\n\n return new Response(body, responseInit);\n }\n\n // Add info to event for debugging\n (event as any).rateLimit = {\n current,\n limit: max,\n reset: new Date(reset),\n remaining: max - current\n };\n\n // Add headers to response if enabled\n if (headers === 'include') {\n const rateLimitHeaders = {\n 'X-RateLimit-Limit': String(max),\n 'X-RateLimit-Remaining': String(max - current),\n 'X-RateLimit-Reset': String(Math.floor(reset / 1000))\n };\n const originalSetHeaders = event.setHeaders;\n event.setHeaders = (newHeaders) => {\n originalSetHeaders({\n ...rateLimitHeaders,\n ...newHeaders\n });\n };\n originalSetHeaders(rateLimitHeaders);\n }\n\n return next();\n };\n}\n","import {Middleware} from \"../../types\";\n\n/**\n * Configuration for CORS middleware\n */\nexport interface Options {\n /**\n * Allowed origins (strings or regex)\n * @default '*' (allow all)\n */\n origin?: string | string[] | RegExp | RegExp[] | ((origin: string) => boolean);\n\n /**\n * Allowed methods\n * @default ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']\n */\n methods?: string[];\n\n /**\n * Allowed request headers\n * @default 'Content-Type,X-Auth-Token,Authorization' (plus simple headers)\n */\n allowedHeaders?: string[];\n\n /**\n * Exposed headers in response\n */\n exposedHeaders?: string[];\n\n /**\n * Whether to include credentials (cookies, authorization)\n * @default false\n */\n credentials?: boolean;\n\n /**\n * Max age of preflight result (in seconds)\n * @default 86400 (24h)\n */\n maxAge?: number;\n\n /**\n * Optional callback to modify response before sending\n */\n onResponse?: (response: Response) => void | Response;\n}\n\n/**\n * Default allowed methods\n */\nconst DEFAULT_METHODS = [\n 'GET',\n 'POST',\n 'PUT',\n 'DELETE',\n 'PATCH',\n 'HEAD',\n 'OPTIONS'\n];\n\n/**\n * Default simple headers (always allowed by browsers)\n */\nconst SIMPLE_HEADERS = [\n 'Accept',\n 'Accept-Language',\n 'Content-Language',\n 'Content-Type',\n 'Range'\n];\n\n/**\n * Default allowed headers beyond simple headers\n */\nconst DEFAULT_ALLOWED_HEADERS = [\n 'Authorization',\n 'X-Auth-Token',\n 'X-Requested-With',\n 'X-CSRF-Token',\n 'X-HTTP-Method-Override',\n 'X-Forwarded-For',\n 'X-Real-IP',\n 'X-Custom-Header'\n];\n\n/**\n * Check if origin is allowed\n */\nfunction isOriginAllowed(origin: string, option: Options['origin']): boolean {\n if (!origin || !option) return false;\n\n if (option === '*') return true;\n if (option === 'null') return origin === 'null';\n\n if (Array.isArray(option)) {\n return option.some(o => isOriginAllowed(origin, o));\n }\n\n if (typeof option === 'function') {\n return option(origin);\n }\n\n if (option instanceof RegExp) {\n return option.test(origin);\n }\n\n return origin === option;\n}\n\n/**\n * Get allowed origin header value\n */\nfunction getAllowedOrigin(requestOrigin: string | null, options: Options): string | null {\n const { origin = '*' } = options;\n\n if (!requestOrigin) return origin === '*' ? '*' : null;\n\n if (origin === '*') {\n // If wildcard, reflect the origin (but not for credentials)\n return options.credentials ? requestOrigin : '*';\n }\n\n if (isOriginAllowed(requestOrigin, origin)) {\n return requestOrigin; // Reflect allowed origin\n }\n\n return null;\n}\n\n/**\n * CORS Middleware Factory\n *\n * @example\n * // Allow all (default)\n * cors()\n *\n * @example\n * // Allow specific origin\n * cors({ origin: 'https://myapp.com' })\n *\n * @example\n * // Allow multiple origins\n * cors({ origin: ['https://myapp.com', 'https://admin.com'] })\n *\n * @example\n * // Allow with regex\n * cors({ origin: /^https:\\/\\/.*\\.mycompany\\.com$/ })\n *\n * @example\n * // Allow with credentials\n * cors({\n * origin: 'https://myapp.com',\n * credentials: true\n * })\n */\nexport function policy(options: Options = {}): Middleware {\n const {\n methods = DEFAULT_METHODS,\n allowedHeaders = DEFAULT_ALLOWED_HEADERS,\n exposedHeaders,\n credentials = false,\n maxAge = 86400,\n onResponse\n } = options;\n\n const varyHeader = 'Origin,Access-Control-Request-Method,Access-Control-Request-Headers';\n const methodsHeader = methods.join(',');\n const allowedHeadersHeader = [...SIMPLE_HEADERS, ...allowedHeaders].join(',');\n\n const headersToSet: [string, string][] = [\n ['Vary', varyHeader],\n ['Access-Control-Allow-Methods', methodsHeader],\n ['Access-Control-Allow-Headers', allowedHeadersHeader],\n ];\n\n if (exposedHeaders) {\n headersToSet.push(['Access-Control-Expose-Headers', exposedHeaders.join(',')])\n }\n\n if (credentials) {\n headersToSet.push(['Access-Control-Allow-Credentials', 'true']);\n }\n\n if (maxAge) {\n headersToSet.push(['Access-Control-Max-Age', maxAge.toString()]);\n }\n\n return async (event, next) => {\n const request = event.request;\n const origin = request.headers.get('Origin');\n const isPreflight = request.method === 'OPTIONS'\n && origin !== null\n && request.headers.has('Access-Control-Request-Method');\n\n const allowedOrigin = getAllowedOrigin(origin, options);\n if (isPreflight) {\n if (!allowedOrigin) {\n return new Response(null, {status: 403});\n }\n\n const preflightResponse = new Response(null, {status: 204});\n for (const [key, value] of headersToSet) {\n preflightResponse.headers.set(key, value);\n }\n preflightResponse.headers.set('Access-Control-Allow-Origin', allowedOrigin);\n return preflightResponse;\n }\n\n // Always set Vary and other base headers\n const response = await next();\n\n if (!response) return;\n\n // Check if origin is allowed\n if (!allowedOrigin) return response;\n\n // Clone response so we can modify headers\n const modifiedResponse = new Response(response.body, response);\n\n // Set CORS headers\n for (const [key, value] of headersToSet) {\n modifiedResponse.headers.set(key, value);\n }\n modifiedResponse.headers.set('Access-Control-Allow-Origin', allowedOrigin);\n\n // Allow response to be modified\n let finalResponse = modifiedResponse;\n if (onResponse) {\n const override = onResponse(finalResponse);\n if (override) finalResponse = override;\n }\n\n return finalResponse;\n };\n}\n","export const RequestMethods = ['GET', 'PUT', 'POST', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'] as const;\nexport type RequestMethod = typeof RequestMethods[number];\n","import type {RequestEvent} from \"./RequestEvent\";\nimport {RequestMethod, RequestMethods} from \"./RequestMethod\";\nimport {isHttpError, isRedirect, isResponse} from \"../utils\";\nimport {WebSocket} from \"ws\";\nimport type {MaybePromise} from \"./MaybePromise\";\n\n/**\n * Extracts path parameters from route pattern\n * - [param] → string\n * - [...param] → string (full path segment, e.g. \"a/b/c\")\n * - [[param]] → string | '' (optional segment)\n */\nexport type ExtractPathParams<T extends string> =\n T extends `/${infer Segment}/${infer Rest}`\n ? MergeParams<ExtractSegmentParam<Segment>, ExtractPathParams<`/${Rest}`>>\n : T extends `/${infer Segment}`\n ? ExtractSegmentParam<Segment>\n : {};\n\nexport type ExtractSegmentParam<S extends string> =\n S extends `[...${infer Param}]` ? { [K in Param]: string } :\n S extends `[[${infer Param}]]` ? { [K in Param]?: string } :\n S extends `[${infer Param}]` ? { [K in Param]: string } :\n {};\n\nexport type MergeParams<A, B> = A & B;\n\n// Add Locals generic\nexport type RouteHandler<Path extends string, Locals extends Record<string, any> = {}> = (\n event: RequestEvent<\n ExtractPathParams<Path> & RequestEvent['params'],\n Path,\n Locals\n >\n) => MaybePromise<Response>;\n\nexport type ActionHandler<Path extends string, OutputData extends Record<string, any> = Record<string, any>> = Action<ExtractPathParams<Path>, OutputData>;\n\nexport type Action<\n Params extends Partial<Record<string, string>> = Partial<Record<string, string>>,\n OutputData extends Record<string, any> | void = Record<string, any> | void,\n> = (event: RequestEvent<Params>) => MaybePromise<OutputData>;\n\n// Middleware with locals support\nexport type Middleware<\n Path extends string = string,\n AddedLocals extends Record<string, any> = {}\n> = (\n event: RequestEvent<any, Path, any> & { locals: Record<string, any> & AddedLocals },\n next: () => MaybePromise<Response | undefined>\n) => MaybePromise<Response | undefined>;\n\nexport type PreHandler<Locals extends Record<string, any> = {}> = (\n event: RequestEvent<any, string, Locals>\n) => MaybePromise<Response | void>;\n\nexport type PostHandler<Locals extends Record<string, any> = {}> = (\n event: RequestEvent<any, string, Locals>,\n response: Response\n) => MaybePromise<Response | void>;\n\n// WebSocket Handler\nexport type WebSocketHandler<Path extends string, Locals extends Record<string, any> = {}> = (\n event: RequestEvent<\n ExtractPathParams<Path> & RequestEvent['params'],\n Path,\n Locals\n > & { websocket: WebSocket }\n) => MaybePromise<any>;\n\n// Route definition\nexport interface Route<Path extends string> {\n readonly path: Path;\n readonly method: RequestMethod;\n readonly regex: RegExp;\n readonly paramNames: readonly string[];\n readonly isCatchAll: boolean;\n readonly priority: number;\n readonly handler: RouteHandler<Path, any>;\n readonly middlewares: Middleware<Path>[];\n}\n\ntype WebSocketRoute<Path extends string> = {\n readonly path: Path;\n readonly regex: RegExp;\n readonly paramNames: readonly string[];\n readonly isCatchAll: boolean;\n readonly priority: number;\n readonly handler: WebSocketHandler<Path, any>;\n readonly middlewares: Middleware<Path>[];\n};\n\n// Nested router\ninterface NestedRouter {\n readonly prefix: string;\n readonly router: Router<any>;\n readonly regex: RegExp;\n readonly paramNames: readonly string[];\n readonly isCatchAll: boolean;\n readonly priority: number;\n readonly middlewares: Middleware<any>[];\n}\n\n// Cache for regex creation\nclass PathRegexCache {\n private static cache = new Map<string, {\n regex: RegExp;\n paramNames: string[];\n isCatchAll: boolean;\n priority: number;\n }>();\n\n static get(path: string) {\n return this.cache.get(path);\n }\n\n static set(path: string, value: {\n regex: RegExp;\n paramNames: string[];\n isCatchAll: boolean;\n priority: number;\n }) {\n this.cache.set(path, value);\n }\n}\n\nexport class Router<Locals extends Record<string, any> = {}> {\n private _routes: Route<any>[] = [];\n private _wsRoutes: WebSocketRoute<any>[] = [];\n private _nestedRouters: NestedRouter[] = [];\n private _middlewares: Middleware<string, any>[] = [];\n private _preHandlers: PreHandler<Locals>[] = [];\n private _postHandlers: PostHandler<Locals>[] = [];\n private routesSorted = false;\n private wsRoutesSorted = false;\n\n get routes(): readonly Route<any>[] {\n return this._routes;\n }\n\n get nestedRouters(): readonly NestedRouter[] {\n return this._nestedRouters;\n }\n\n // HTTP method handlers\n GET<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('GET', path, handler, middlewares);\n }\n\n POST<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('POST', path, handler, middlewares);\n }\n\n PUT<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('PUT', path, handler, middlewares);\n }\n\n PATCH<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('PATCH', path, handler, middlewares);\n }\n\n DELETE<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('DELETE', path, handler, middlewares);\n }\n\n HEAD<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('HEAD', path, handler, middlewares);\n }\n\n OPTIONS<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('OPTIONS', path, handler, middlewares);\n }\n\n // Universal method\n USE<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n RequestMethods.forEach(method => this.addHandler(method, path, handler, middlewares));\n return this;\n }\n\n // Action handler (POST only)\n action<Path extends string, OutputData extends Record<string, any> = Record<string, any>>(\n path: Path,\n handler: ActionHandler<Path, OutputData>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n const wrapped: RouteHandler<Path, Locals> = async (event) => {\n try {\n const result = await handler(event as RequestEvent<ExtractPathParams<Path>, Path, Locals>);\n return this.formatActionResult(result);\n } catch (error) {\n return this.handleActionError(error);\n }\n };\n\n return this.addHandler('POST', path, wrapped, middlewares);\n }\n\n // Nested routing\n use<Prefix extends string, InnerLocals extends Record<string, any>>(input: readonly [Prefix, Router<InnerLocals>, ...Middleware<Prefix>[]]): Router<Locals & InnerLocals>;\n use<Prefix extends string, InnerLocals extends Record<string, any>>(prefix: Prefix, router: Router<InnerLocals>, ...middlewares: Middleware<Prefix>[]): Router<Locals & InnerLocals>;\n use<Prefix extends string, InnerLocals extends Record<string, any>>(arg1: string | readonly [Prefix, Router<InnerLocals>, ...Middleware<Prefix>[]], arg2?: Router<InnerLocals>, ...middlewares: Middleware<Prefix>[]): Router<Locals & InnerLocals> {\n let prefix: Prefix;\n let router: Router<InnerLocals>;\n let finalMiddlewares: Middleware<Prefix>[] = middlewares;\n\n if (Array.isArray(arg1)) {\n [prefix, router] = arg1;\n finalMiddlewares = arg1.length > 2 ? arg1.slice(2) as Middleware<Prefix>[] : [];\n } else {\n prefix = arg1 as Prefix;\n router = arg2!;\n }\n\n const normalizedPrefix = this.normalizePrefix(prefix);\n const {regex, paramNames, isCatchAll, priority} = this.createPrefixRegex(normalizedPrefix);\n\n this._nestedRouters.push({\n prefix: normalizedPrefix,\n router,\n regex,\n paramNames,\n isCatchAll,\n priority,\n middlewares: finalMiddlewares\n });\n\n return this as unknown as Router<Locals & InnerLocals>;\n }\n\n // Global middleware\n useMiddleware<NewLocals extends Record<string, any>>(\n ...mw: Middleware<string, NewLocals>[]\n ): Router<Locals & NewLocals> {\n this._middlewares.push(...mw);\n return this as unknown as Router<Locals & NewLocals>;\n }\n\n pre(...handlers: PreHandler<Locals>[]): Router<Locals> {\n this._preHandlers.push(...handlers);\n return this;\n }\n\n post(...handlers: PostHandler<Locals>[]): Router<Locals> {\n this._postHandlers.push(...handlers);\n return this;\n }\n\n // Discard routes or nested routers\n discard(path_or_prefix: string, method?: RequestMethod): this {\n this._nestedRouters = this._nestedRouters.filter(r => r.prefix !== path_or_prefix);\n this._routes = this._routes.filter(route =>\n route.path !== path_or_prefix || (method && route.method !== method)\n );\n return this;\n }\n\n // WebSocket route\n WS<Path extends string>(\n path: Path,\n handler: WebSocketHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n const {regex, paramNames, isCatchAll, priority} = this.createPathRegex(path);\n\n this._wsRoutes.push({\n path,\n regex,\n paramNames,\n isCatchAll,\n priority,\n handler,\n middlewares\n });\n\n this.wsRoutesSorted = false;\n return this;\n }\n\n // Add this method to your Router class\n\n /**\n * Check if the router can handle a WebSocket connection for the given path\n * This is used during the upgrade process to validate routes before attempting connection\n */\n public async canHandleWebSocket(event: RequestEvent): Promise<boolean> {\n return this.canHandleWebSocketAtPath(event, event.url.pathname);\n }\n\n private async canHandleWebSocketAtPath(event: RequestEvent, pathname: string): Promise<boolean> {\n if (!this.wsRoutesSorted) this.sortWsRoutes();\n\n // 1. Check nested routers first\n for (const nested of [...this._nestedRouters].sort((a, b) => b.priority - a.priority)) {\n const match = pathname.match(nested.regex);\n if (!match || match.index !== 0) continue;\n\n const matched = match[0];\n const remaining = pathname.slice(matched.length) || '/';\n\n const nestedEvent: RequestEvent = {\n ...event,\n params: {...event.params, ...this.extractPrefixParams(nested, matched)}\n };\n\n // Recursively check if nested router can handle the WebSocket\n if (await nested.router.canHandleWebSocketAtPath(nestedEvent, remaining)) {\n return true;\n }\n }\n\n // 2. Check local WebSocket routes\n for (const route of this._wsRoutes) {\n if (route.regex.test(pathname)) {\n return true;\n }\n }\n\n return false;\n }\n\n // Handle WebSocket upgrade\n public async handleWebSocket(\n event: RequestEvent,\n websocket: WebSocket\n ): Promise<boolean> {\n return this.handleWebSocketAtPath(event, websocket, event.url.pathname);\n }\n\n private async handleWebSocketAtPath(\n event: RequestEvent,\n websocket: WebSocket,\n pathname: string\n ): Promise<boolean> {\n if (!this.wsRoutesSorted) this.sortWsRoutes();\n\n // 1. Try nested routers\n for (const nested of [...this._nestedRouters].sort((a, b) => b.priority - a.priority)) {\n const match = pathname.match(nested.regex);\n if (!match || match.index !== 0) continue;\n\n const matched = match[0];\n const remaining = pathname.slice(matched.length) || '/';\n const prefixParams = this.extractPrefixParams(nested, matched);\n\n const nestedEvent: RequestEvent = {\n ...event,\n params: {...event.params, ...prefixParams}\n };\n\n const effectiveMiddlewares = [...this._middlewares, ...nested.middlewares];\n const handler = () => nested.router.handleWebSocketAtPath(nestedEvent, websocket, remaining);\n\n const result = await this.applyMiddlewaresWithList(nestedEvent, effectiveMiddlewares, handler as any);\n if (!result) continue;\n else return true;\n }\n\n // 2. Try local WebSocket routes\n for (const route of this._wsRoutes) {\n if (!route.regex.test(pathname)) continue;\n\n const match = pathname.match(route.regex);\n if (!match) continue;\n\n const params = Object.fromEntries(\n route.paramNames.map((name, i) => [name, match[i + 1] || ''])\n );\n\n const enhancedEvent = {\n ...event,\n params: {...event.params, ...params},\n route: {...event.route, id: route.path},\n websocket,\n }\n\n const allMiddlewares = [...this._middlewares, ...route.middlewares];\n\n\n const result = await this.applyMiddlewaresWithList(enhancedEvent, allMiddlewares, () => route.handler(enhancedEvent));\n if (result === undefined) {\n return true;\n }\n }\n\n return false;\n }\n\n // Handle HTTP request - FIXED: Single middleware application\n protected async handle(event: RequestEvent): Promise<Response> {\n return this.handleAtPath(event, event.url.pathname);\n }\n\n private async handleAtPath(event: RequestEvent, path: string): Promise<Response> {\n try {\n const method = event.request.method as RequestMethod;\n let response = await this.runPreHandlers(event);\n if (!response) {\n // Apply global middlewares once at the top level\n const handler = async () => {\n // Try nested routers first\n const nestedResponse = await this.handleNestedRouters(event, path);\n if (nestedResponse) return nestedResponse;\n\n // Then try local routes\n if (!this.routesSorted) this.sortRoutes();\n return this.handleLocalRoutes(event, method, path);\n };\n\n response = await this.applyMiddlewaresWithList(event, this._middlewares, handler);\n }\n\n const finalResponse = response || new Response(\"No Content\", {status: 204});\n return await this.runPostHandlers(event, finalResponse);\n } catch (err) {\n if (isResponse(err)) return err;\n throw err;\n }\n }\n\n // Apply middlewares utility\n private async applyMiddlewaresWithList(\n event: RequestEvent,\n mws: Middleware<string, any>[],\n next: () => MaybePromise<Response | undefined>\n ) {\n const chain = [...mws];\n const run = async (index: number): Promise<Response | undefined> => {\n if (index >= chain.length) return next();\n return chain[index](event, () => run(index + 1));\n };\n return run(0);\n }\n\n private async runPreHandlers(event: RequestEvent): Promise<Response | undefined> {\n for (const handler of this._preHandlers) {\n const response = await handler(event as RequestEvent<any, string, Locals>);\n if (response instanceof Response) {\n return response;\n }\n }\n\n return undefined;\n }\n\n private async runPostHandlers(event: RequestEvent, response: Response): Promise<Response> {\n let currentResponse = response;\n\n for (const handler of this._postHandlers) {\n const nextResponse = await handler(event as RequestEvent<any, string, Locals>, currentResponse);\n if (nextResponse instanceof Response) {\n currentResponse = nextResponse;\n }\n }\n\n return currentResponse;\n }\n\n // Add route handler\n private addHandler<Path extends string>(\n method: RequestMethod,\n path: Path,\n handler: RouteHandler<Path, Locals>,\n middlewares: Middleware<Path, any>[] = []\n ): Router<Locals> {\n const {regex, paramNames, isCatchAll, priority} = this.createPathRegex(path);\n\n this._routes.push({\n method,\n path,\n regex,\n paramNames,\n isCatchAll,\n priority,\n handler,\n middlewares\n });\n\n this.routesSorted = false;\n return this;\n }\n\n // Create regex for route path\n private createPathRegex(path: string) {\n const cached = PathRegexCache.get(path);\n if (cached) return cached;\n\n const paramNames: string[] = [];\n let isCatchAll = false;\n let priority: number;\n\n const segments = path.split('/').filter(Boolean);\n priority = segments.reduce((acc, segment) => {\n if (segment.startsWith('[...')) return acc - 10;\n if (segment.startsWith('[[')) return acc - 5;\n if (segment.startsWith('[')) return acc - 1;\n return acc + 1;\n }, 0);\n\n let regexString = '^';\n for (const part of segments) {\n if (part.startsWith('[...') && part.endsWith(']')) {\n isCatchAll = true;\n const paramName = part.slice(4, -1);\n paramNames.push(paramName);\n regexString += '/(.+)';\n } else if (part.startsWith('[[') && part.endsWith(']]')) {\n const paramName = part.slice(2, -2);\n paramNames.push(paramName);\n regexString += '(?:/([^/]+))?';\n } else if (part.startsWith('[') && part.endsWith(']')) {\n const paramName = part.slice(1, -1);\n paramNames.push(paramName);\n regexString += '/([^/]+)';\n } else {\n regexString += '/' + part.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n }\n }\n regexString += '/?$';\n\n const result = {regex: new RegExp(regexString), paramNames, isCatchAll, priority};\n PathRegexCache.set(path, result);\n return result;\n }\n\n // Create regex for prefix\n private createPrefixRegex(prefix: string) {\n const paramNames: string[] = [];\n let isCatchAll = false;\n let priority: number;\n\n const segments = prefix.split('/').filter(Boolean);\n priority = segments.reduce((acc, segment) => {\n if (segment.startsWith('[...')) return acc - 10;\n if (segment.startsWith('[[')) return acc - 5;\n if (segment.startsWith('[')) return acc - 1;\n return acc + 1;\n }, 0);\n\n let regexString = '^';\n for (const part of segments) {\n if (part.startsWith('[...') && part.endsWith(']')) {\n isCatchAll = true;\n const paramName = part.slice(4, -1);\n paramNames.push(paramName);\n regexString += '/(.+)';\n } else if (part.startsWith('[[') && part.endsWith(']]')) {\n const paramName = part.slice(2, -2);\n paramNames.push(paramName);\n regexString += '(?:/([^/]+))?';\n } else if (part.startsWith('[') && part.endsWith(']')) {\n const paramName = part.slice(1, -1);\n paramNames.push(paramName);\n regexString += '/([^/]+)';\n } else {\n regexString += '/' + part.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n }\n }\n regexString += '(?=/|$)';\n\n return {regex: new RegExp(regexString), paramNames, isCatchAll, priority};\n }\n\n private normalizePrefix(prefix: string): string {\n return prefix.startsWith('/') ? prefix.replace(/\\/$/, '') : `/${prefix.replace(/\\/$/, '')}`;\n }\n\n private extractPrefixParams(nested: NestedRouter, matchedPath: string): Record<string, string> {\n const match = matchedPath.match(nested.regex);\n if (!match) return {};\n\n const params: Record<string, string> = {};\n if (nested.isCatchAll && nested.paramNames.length === 1) {\n params[nested.paramNames[0]] = match[1]?.replace(/^\\//, '') || '';\n } else {\n nested.paramNames.forEach((name, i) => {\n params[name] = match[i + 1] || '';\n });\n }\n return params;\n }\n\n // FIXED: Nested router handling without duplicate middleware application\n private async handleNestedRouters(event: RequestEvent, path: string): Promise<Response | null> {\n const sorted = [...this._nestedRouters].sort((a, b) => b.priority - a.priority);\n\n for (const nested of sorted) {\n const match = path.match(nested.regex);\n if (!match || match.index !== 0) continue;\n\n const matched = match[0];\n const remaining = path.slice(matched.length) || '/';\n const prefixParams = this.extractPrefixParams(nested, matched);\n\n const nestedEvent: RequestEvent = {\n ...event,\n params: {...event.params, ...prefixParams}\n };\n\n // Apply nested middlewares and handle nested router\n // Note: nested.router.handle() will apply its own global middlewares\n const handler = async () => await nested.router.handleAtPath(nestedEvent, remaining);\n const response = await this.applyMiddlewaresWithList(nestedEvent, nested.middlewares, handler);\n if (response) return response;\n }\n\n return null;\n }\n\n // FIXED: Local route handling without duplicate middleware application\n private async handleLocalRoutes(event: RequestEvent, method: RequestMethod, path: string) {\n const allowed = new Set<RequestMethod>();\n let getRouteForHead = false;\n\n for (const route of this._routes) {\n if (!route.regex.test(path)) continue;\n allowed.add(route.method);\n if (route.method === 'GET') {\n getRouteForHead = true;\n allowed.add('HEAD');\n }\n\n const matchesMethod = route.method === method || (method === 'HEAD' && route.method === 'GET');\n if (!matchesMethod) continue;\n\n const match = path.match(route.regex);\n if (!match) continue;\n\n const params = Object.fromEntries(\n route.paramNames.map((name, i) => [name, match[i + 1] || ''])\n );\n\n event.params = {...event.params, ...params};\n event.route = {...event.route, id: route.path};\n\n // Only apply route-specific middlewares here\n // Global middlewares were already applied in handle()\n const finalHandler = () => route.handler(event);\n return await this.applyMiddlewaresWithList(event, route.middlewares, finalHandler);\n }\n\n if (allowed.size > 0 || (method === 'HEAD' && getRouteForHead)) {\n const allowHeader = [...allowed].join(', ');\n if (method === 'OPTIONS') {\n return new Response(null, {\n status: 200,\n headers: {'Allow': allowHeader}\n });\n }\n return new Response('Method Not Allowed', {\n status: 405,\n headers: {'Allow': allowHeader}\n });\n }\n\n return new Response('Not Found', {status: 404});\n }\n\n private sortRoutes(): void {\n this._routes.sort((a, b) => b.priority - a.priority);\n this.routesSorted = true;\n }\n\n private sortWsRoutes(): void {\n this._wsRoutes.sort((a, b) => b.priority - a.priority);\n this.wsRoutesSorted = true;\n }\n\n private formatActionResult(result: any): Response {\n if (result instanceof Response) return result;\n if (result?.type === 'failure' && 'status' in result) {\n return Action.fail(result.status, result.data);\n }\n return Action.success(200, result ?? undefined);\n }\n\n private handleActionError(err: unknown): Response {\n if (isHttpError(err)) {\n return Action.error(err.status, {message: err.statusText || 'Error'});\n }\n if (isRedirect(err)) {\n const url = err.headers.get('Location') || '/';\n return Action.redirect(err.status, url);\n }\n console.error(err);\n return Action.error(500, {message: 'Internal Server Error'});\n }\n\n static New(): Router {\n return new Router();\n }\n}\n\n// Action utilities\nexport const Action = {\n success: (code: number = 200, data?: Record<string, any>): Response =>\n new Response(JSON.stringify({data, type: 'success', status: code}), {\n status: code,\n headers: {'Content-Type': 'application/json'}\n }),\n\n redirect: (code: number = 302, location: string): Response =>\n new Response(JSON.stringify({location, type: 'redirect', status: code}), {\n status: code,\n headers: {'Content-Type': 'application/json'}\n }),\n\n error: (code: number = 500, error: App.Error): Response =>\n new Response(JSON.stringify({error, type: 'error', status: code}), {\n status: code,\n headers: {'Content-Type': 'application/json'}\n }),\n\n fail: (code: number = 400, data: Record<string, any>): Response =>\n new Response(JSON.stringify({data, type: 'failure', status: code}), {\n status: code,\n headers: {'Content-Type': 'application/json'}\n })\n} as const;\n","import {type ParseOptions, parse, serialize, type SerializeOptions} from \"cookie\";\n\nexport class Cookies {\n private readonly setCookieHeader: (serialized: string) => void;\n private readonly raw: string;\n\n constructor(request: Request, setCookieHeader: (serialized: string) => void) {\n this.raw = request.headers.get('cookie') ?? '';\n this.setCookieHeader = setCookieHeader;\n }\n\n get(name: string, opts?: ParseOptions): string | undefined {\n return parse(this.raw, opts)[name];\n }\n\n getAll(opts?: ParseOptions): { name: string; value: string }[] {\n return Object.entries(parse(this.raw, opts))\n .filter(([, v]) => v !== undefined)\n .map(([name, value]) => ({name, value})) as {name: string, value: string}[];\n }\n\n set(name: string, value: string, opts: SerializeOptions & { path: string }): void {\n this.setCookieHeader(serialize(name, value, opts));\n }\n\n delete(name: string, opts: SerializeOptions & { path: string }): void {\n this.set(name, '', {...opts, maxAge: 0});\n }\n}\n","import {\n createServer as createHttpServer,\n type Server as HttpServer,\n IncomingMessage,\n type ServerOptions,\n ServerResponse\n} from 'http';\nimport {\n createServer as createHttpsServer,\n type Server as HttpsServer,\n type ServerOptions as HttpsServerOptions\n} from 'https';\nimport {TLSSocket} from 'tls';\nimport {Readable, Transform, Writable} from 'stream';\nimport {\n type RequestEvent,\n Router\n} from './';\nimport {isHttpError, isRedirect} from \"../utils\";\nimport {WebSocketServer, WebSocket} from \"ws\";\nimport {Cookies} from \"./Cookies\";\nimport {ListenOptions} from \"net\";\n\ntype HostMatcher = string | RegExp | ((host: string) => boolean);\ntype InferServerLocals<TServerConfig extends ServerConfig> =\n Extract<TServerConfig['locals'], (event: RequestEvent) => any> extends (event: RequestEvent) => infer TLocals\n ? TLocals extends Record<string, any>\n ? TLocals\n : App.Locals\n : App.Locals;\ntype ListenArgs =\n | [port?: number, hostname?: string, backlog?: number, listeningListener?: () => void]\n | [port?: number, hostname?: string, listeningListener?: () => void]\n | [port?: number, backlog?: number, listeningListener?: () => void]\n | [port?: number, listeningListener?: () => void]\n | [path: string, backlog?: number, listeningListener?: () => void]\n | [path: string, listeningListener?: () => void]\n | [options: ListenOptions, listeningListener?: () => void]\n | [handle: any, backlog?: number, listeningListener?: () => void]\n | [handle: any, listeningListener?: () => void];\n\nclass PayloadTooLargeError extends Error {\n readonly status = 413;\n\n constructor(message = 'Payload Too Large') {\n super(message);\n this.name = 'PayloadTooLargeError';\n }\n}\n\nexport type SecurityConfig = {\n /**\n * Trust the incoming Host header when constructing event.url/request.url.\n * Disabled by default to avoid host header poisoning in absolute URL generation.\n */\n trustHostHeader?: boolean;\n\n /**\n * Restrict trusted Host values when trustHostHeader is enabled.\n */\n allowedHosts?: HostMatcher | HostMatcher[];\n\n /**\n * Restrict accepted WebSocket Origin values.\n * When omitted, Origin is not enforced by default.\n */\n allowedWebSocketOrigins?: HostMatcher | HostMatcher[];\n\n /**\n * Maximum accepted request body size based on Content-Length.\n * Requests above the limit are rejected before the body is read.\n */\n maxRequestBodySize?: number;\n\n /**\n * Maximum accepted WebSocket message size in bytes.\n * Passed to ws as maxPayload.\n */\n maxWebSocketPayload?: number;\n};\n\nexport type HttpServerConfig = {\n type: 'http';\n options?: ServerOptions;\n security?: SecurityConfig;\n};\n\nexport type HttpsServerConfig = {\n type: 'https';\n options: HttpsServerOptions;\n security?: SecurityConfig;\n};\n\nexport type ServerConfig = {\n locals?: (event: RequestEvent) => App.Locals;\n platform?: (event: RequestEvent) => App.Platform;\n} & (HttpServerConfig | HttpsServerConfig);\n\nexport class WebServer<TServerConfig extends ServerConfig = ServerConfig> extends Router<InferServerLocals<TServerConfig>> {\n private _server!: TServerConfig['type'] extends 'https' ? HttpsServer : HttpServer;\n private readonly config: TServerConfig;\n private upgradeHandlerInstalled = false;\n\n // Single WebSocket server instance\n private readonly wss: WebSocketServer;\n\n constructor(config?: TServerConfig) {\n super();\n this.config = (config ?? {type: 'http', options: {}}) as TServerConfig;\n this.wss = new WebSocketServer({\n noServer: true,\n maxPayload: this.config.security?.maxWebSocketPayload ?? 1024 * 1024\n });\n }\n\n private get server(): TServerConfig['type'] extends 'https' ? HttpsServer : HttpServer {\n if (!this._server) {\n const requestListener = (req: IncomingMessage, res: ServerResponse) => {\n this.handleRequest(req, res).catch(err => {\n console.error('Unhandled request error:', err);\n res.statusCode = 500;\n res.end('Internal Server Error');\n });\n };\n\n // @ts-ignore\n this._server = this.config.type === 'https'\n ? createHttpsServer(this.config.options as HttpsServerOptions, requestListener)\n : createHttpServer(this.config.options as ServerOptions, requestListener);\n }\n return this._server;\n }\n\n listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): this;\n listen(port?: number, hostname?: string, listeningListener?: () => void): this;\n listen(port?: number, backlog?: number, listeningListener?: () => void): this;\n listen(port?: number, listeningListener?: () => void): this;\n listen(path: string, backlog?: number, listeningListener?: () => void): this;\n listen(path: string, listeningListener?: () => void): this;\n listen(options: ListenOptions, listeningListener?: () => void): this;\n listen(handle: any, backlog?: number, listeningListener?: () => void): this;\n listen(handle: any, listeningListener?: () => void): this;\n listen(...args: ListenArgs): this {\n if (!this.upgradeHandlerInstalled) {\n this.installUpgradeHandler();\n this.upgradeHandlerInstalled = true;\n }\n\n this.server.listen(...args);\n return this;\n }\n\n private installUpgradeHandler(): void {\n this.server.on('upgrade', (req, socket, head) => {\n if (req.headers.upgrade?.toLowerCase() !== 'websocket') {\n socket.destroy();\n return;\n }\n\n let url: URL;\n let request: Request;\n try {\n url = this.toURL(req, true);\n request = this.toRequest(req, url, true);\n } catch {\n socket.destroy();\n return;\n }\n\n const event = this.toRequestEvent(request, url, {\n getClientAddress: () => req.socket.remoteAddress ?? '127.0.0.1',\n setHeader: () => {\n },\n pushSetCookie: () => {\n }\n });\n\n this.canHandleWebSocket(event)\n .then((canHandle) => {\n if (!canHandle || !this.isAllowedWebSocketOrigin(req)) {\n socket.destroy();\n return;\n }\n\n this.wss.handleUpgrade(req, socket, head, (ws: WebSocket) => {\n this.handleWebSocket(event, ws).then((handled) => {\n if (!handled && ws.readyState === WebSocket.OPEN) {\n ws.close(1008, 'Route not found');\n }\n }).catch(err => {\n console.error('WebSocket routing error:', err);\n if (ws.readyState === WebSocket.OPEN) {\n ws.close(1011, 'Internal error');\n }\n });\n });\n })\n .catch(() => socket.destroy());\n });\n }\n\n close(callback?: (err?: Error) => void): void {\n this.wss.close(() => {\n this.server.close(callback);\n });\n }\n\n address(): string | import('net').AddressInfo | null {\n return this.server.address();\n }\n\n get listening(): boolean {\n return this.server.listening;\n }\n\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n if (!this.isRequestBodyAllowed(req)) {\n res.statusCode = 413;\n res.end('Payload Too Large');\n return;\n }\n\n const request = this.toWebRequest(req);\n const url = new URL(request.url);\n\n const setHeaders: Record<string, string> = {};\n const setCookies: string[] = [];\n\n const event = this.toRequestEvent(request, url, {\n getClientAddress: () => req.socket.remoteAddress ?? '127.0.0.1',\n setHeader: (name: string, value: string) => {\n setHeaders[name.toLowerCase()] = value;\n },\n pushSetCookie: (serialized: string) => {\n setCookies.push(serialized);\n }\n });\n\n let response: Response;\n try {\n response = await this.handle(event);\n } catch (err) {\n response = this.handleError(err);\n }\n\n for (const [name, value] of Object.entries(setHeaders)) {\n res.setHeader(name, value);\n }\n\n if (setCookies.length > 0) {\n res.setHeader('Set-Cookie', setCookies);\n }\n\n await this.sendWebResponse(res, response);\n }\n\n private toWebRequest(req: IncomingMessage): Request {\n const url = this.toURL(req, false);\n return this.toRequest(req, url, false);\n }\n\n private toRequest(req: IncomingMessage, url: URL, isWebSocket: boolean): Request {\n const init: RequestInit = {\n method: isWebSocket ? 'GET' : req.method,\n headers: this.toHeaders(req.headers),\n // @ts-ignore\n duplex: 'half'\n };\n\n if (!isWebSocket && req.method !== 'GET' && req.method !== 'HEAD') {\n init.body = Readable.toWeb(this.wrapRequestBody(req)) as unknown as ReadableStream<Uint8Array>;\n }\n\n return new Request(url, init);\n }\n\n private wrapRequestBody(req: IncomingMessage): Readable {\n const limit = this.config.security?.maxRequestBodySize;\n if (!limit) {\n return req;\n }\n\n let total = 0;\n const limiter = new Transform({\n transform(chunk, _encoding, callback) {\n total += Buffer.byteLength(chunk);\n if (total > limit) {\n callback(new PayloadTooLargeError());\n return;\n }\n\n callback(null, chunk);\n }\n });\n\n req.on('aborted', () => limiter.destroy(new Error('Request aborted')));\n req.on('error', (error) => limiter.destroy(error));\n req.pipe(limiter);\n return limiter;\n }\n\n private toURL(req: IncomingMessage, isWebSocket: boolean): URL {\n const protocol = req.socket instanceof TLSSocket ? (isWebSocket ? 'wss' : 'https') : (isWebSocket ? 'ws' : 'http');\n const authority = this.resolveAuthority(req);\n return new URL(req.url ?? '/', `${protocol}://${authority}`);\n }\n\n private resolveAuthority(req: IncomingMessage): string {\n const trustedAuthority = this.config.security?.trustHostHeader ? this.normalizeTrustedHost(req.headers.host) : null;\n if (trustedAuthority) {\n return trustedAuthority;\n }\n\n const address = this.server.address();\n if (address && typeof address === 'object') {\n const host = address.address.includes(':') ? `[${address.address}]` : address.address;\n return `${host}:${address.port}`;\n }\n\n return req.socket.localPort ? `127.0.0.1:${req.socket.localPort}` : 'localhost';\n }\n\n private normalizeTrustedHost(hostHeader: string | undefined): string | null {\n if (!hostHeader) return null;\n\n let url: URL;\n try {\n url = new URL(`http://${hostHeader}`);\n } catch {\n return null;\n }\n\n if (url.username || url.password || url.pathname !== '/' || url.search || url.hash) {\n return null;\n }\n\n const authority = url.port ? `${url.hostname}:${url.port}` : url.hostname;\n const allowedHosts = this.config.security?.allowedHosts;\n if (!allowedHosts || this.matchesValue(authority, allowedHosts)) {\n return authority;\n }\n\n return null;\n }\n\n private matchesValue(value: string, matcher: HostMatcher | HostMatcher[]): boolean {\n const matchers = Array.isArray(matcher) ? matcher : [matcher];\n return matchers.some((entry) => {\n if (typeof entry === 'string') return entry === value;\n if (entry instanceof RegExp) return entry.test(value);\n return entry(value);\n });\n }\n\n private toHeaders(headers: IncomingMessage['headers']): Headers {\n const normalized = new Headers();\n for (const [name, value] of Object.entries(headers)) {\n if (value === undefined) continue;\n\n if (Array.isArray(value)) {\n const joined = name.toLowerCase() === 'cookie' ? value.join('; ') : value.join(', ');\n normalized.set(name, joined);\n continue;\n }\n\n normalized.set(name, value);\n }\n\n return normalized;\n }\n\n private isRequestBodyAllowed(req: IncomingMessage): boolean {\n const limit = this.config.security?.maxRequestBodySize;\n if (!limit) return true;\n\n const contentLength = req.headers['content-length'];\n if (!contentLength) return true;\n\n const parsed = Number.parseInt(Array.isArray(contentLength) ? contentLength[0] : contentLength, 10);\n return Number.isFinite(parsed) && parsed <= limit;\n }\n\n private handleError(err: unknown): Response {\n if (err instanceof PayloadTooLargeError) {\n return new Response(err.message, {status: err.status});\n }\n\n if (isHttpError(err)) {\n return new Response(JSON.stringify({\n error: err.statusText || 'Error',\n status: err.status\n }), {\n status: err.status,\n headers: {'Content-Type': 'application/json'}\n });\n }\n\n if (isRedirect(err)) {\n const location = err.headers.get('Location') || '/';\n return new Response(null, {\n status: err.status,\n headers: {'Location': location}\n });\n }\n\n console.error('Unhandled error:', err);\n return new Response('Internal Server Error', {status: 500});\n }\n\n private async sendWebResponse(res: ServerResponse, response: Response): Promise<void> {\n res.statusCode = response.status;\n response.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n\n if (!res.hasHeader('Server')) {\n res.setHeader('Server', 'WebHTTPServer');\n }\n\n if (!response.body || this.shouldOmitResponseBody(response, res.req?.method)) {\n res.end();\n return;\n }\n\n const reader = response.body.getReader();\n const writer = Writable.toWeb(res).getWriter();\n\n try {\n while (true) {\n const {done, value} = await reader.read();\n if (done) break;\n await writer.write(value);\n }\n } finally {\n await writer.close().catch(() => {\n });\n }\n }\n\n private shouldOmitResponseBody(response: Response, method?: string): boolean {\n if (method === 'HEAD') return true;\n return response.status === 204 || response.status === 205 || response.status === 304;\n }\n\n private isAllowedWebSocketOrigin(req: IncomingMessage): boolean {\n const origin = req.headers.origin;\n if (!origin) return true;\n\n const allowedOrigins = this.config.security?.allowedWebSocketOrigins;\n if (!allowedOrigins) return true;\n\n return this.matchesValue(origin, allowedOrigins);\n }\n\n private toRequestEvent(\n request: Request,\n url: URL,\n utils: {\n getClientAddress: () => string;\n setHeader: (name: string, value: string) => void;\n pushSetCookie: (serialized: string) => void;\n }\n ): RequestEvent<{}> {\n const cookies = new Cookies(request, utils.pushSetCookie);\n const handlers = this.config;\n const locals: App.Locals | Record<string, any> = {};\n const platform: App.Platform | Record<string, any> = {name: 'WebHTTPServer'};\n const setHeadersState = new Set<string>();\n\n const event: RequestEvent<{}> = {\n request,\n url,\n cookies,\n getClientAddress: utils.getClientAddress,\n get locals(): App.Locals {\n return locals;\n },\n get platform(): App.Platform | undefined {\n return platform;\n },\n params: {},\n route: {id: ''},\n setHeaders: (headers: Record<string, string>) => {\n for (const [name, value] of Object.entries(headers)) {\n const normalizedName = name.toLowerCase();\n if (normalizedName === 'set-cookie') {\n throw new TypeError('Use event.cookies for Set-Cookie headers');\n }\n if (setHeadersState.has(normalizedName)) {\n throw new TypeError(`Header \"${name}\" has already been set`);\n }\n setHeadersState.add(normalizedName);\n utils.setHeader(name, value);\n }\n }\n };\n\n if (handlers.locals) {\n Object.assign(locals, handlers.locals(event));\n }\n if (handlers.platform) {\n Object.assign(platform as Record<string, any>, handlers.platform(event));\n }\n\n return event;\n }\n}\n","import type {MaybePromise} from \"./types/MaybePromise\";\nimport {serveStatic, StaticOptions} from \"./static\";\nimport {RouteHandler} from \"./types\";\n\nexport * from './app'\nexport * from './utils'\nexport * from './middlewares'\nexport * from './types'\nexport * from './static'\n\nexport const json = async (data: MaybePromise<any>, init?: ResponseInit) => {\n const content = JSON.stringify(await data);\n return new Response(content, {\n ...init,\n headers: {\n 'content-type': 'application/json',\n 'content-length': Buffer.byteLength(content).toString(),\n ...init?.headers\n }\n })\n}\n\nexport function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never{\n throw new Response(null, {\n status,\n headers: {\n location: location.toString()\n }\n })\n}\n\nexport function error(status: number, body: App.Error | string): never{\n throw new Response(JSON.stringify(typeof body === \"string\" ? {message: body} : body), {\n status,\n headers: {\n 'content-type': 'application/json'\n }\n })\n}\n\nexport const text = async (body: MaybePromise<string>, init?: ResponseInit) => {\n const content = await body\n return new Response(content, {\n ...init,\n headers: {\n 'content-type': 'text/plain',\n 'content-length': Buffer.byteLength(content).toString(),\n ...init?.headers\n }\n })\n}\n\nexport const html = async (html: MaybePromise<string>, init?: ResponseInit) => {\n const content = await html\n return new Response(content, {\n ...init,\n headers: {\n 'content-type': 'text/html',\n 'content-length': Buffer.byteLength(content).toString(),\n ...init?.headers\n }\n })\n}\n\nexport const dir = <Path extends string>(root: string, options: StaticOptions = {}): RouteHandler<Path> =>\n (event) => serveStatic(root, event, options);\n"],"names":["MIME_TYPES","DEFAULT_STATIC_OPTIONS","serveStatic","root","event","options","requestPath","getStaticRequestPath","resolvedOptions","rootPath","resolveStaticRoot","normalizedPath","normalizeStaticRequestPath","targetPath","sep","candidatePath","resolve","isPathInside","filePath","resolveStaticFile","fileStats","stat","headers","getMimeType","extraHeaders","value","key","Readable","createReadStream","realpath","dotFiles","segments","normalizedSegments","segment","decoded","indexFile","lstat","indexPath","ensureResolvedFile","resolvedPath","relativePath","relative","isAbsolute","extname","isHttpError","err","isResponse","isRedirect","MemoryStore","opts","now","record","reset","fixedWindowLimit","windowMs","max","message","statusCode","onRateLimit","store","next","rateLimitKey","current","retryAfter","responseInit","header","body","rateLimitHeaders","originalSetHeaders","newHeaders","DEFAULT_METHODS","SIMPLE_HEADERS","DEFAULT_ALLOWED_HEADERS","isOriginAllowed","origin","option","o","getAllowedOrigin","requestOrigin","policy","methods","allowedHeaders","exposedHeaders","credentials","maxAge","onResponse","varyHeader","methodsHeader","allowedHeadersHeader","headersToSet","request","isPreflight","allowedOrigin","preflightResponse","response","modifiedResponse","finalResponse","override","RequestMethods","PathRegexCache","path","Router","handler","middlewares","method","wrapped","result","error","arg1","arg2","prefix","router","finalMiddlewares","normalizedPrefix","regex","paramNames","isCatchAll","priority","mw","handlers","path_or_prefix","r","route","pathname","nested","a","b","match","matched","remaining","nestedEvent","websocket","prefixParams","effectiveMiddlewares","params","name","i","enhancedEvent","allMiddlewares","nestedResponse","mws","chain","run","index","currentResponse","nextResponse","cached","acc","regexString","part","paramName","matchedPath","sorted","allowed","getRouteForHead","finalHandler","allowHeader","Action","url","code","data","location","Cookies","setCookieHeader","parse","v","serialize","PayloadTooLargeError","WebServer","config","WebSocketServer","requestListener","req","res","createHttpsServer","createHttpServer","args","socket","head","canHandle","ws","handled","WebSocket","callback","setHeaders","setCookies","serialized","isWebSocket","init","limit","total","limiter","Transform","chunk","_encoding","protocol","TLSSocket","authority","trustedAuthority","address","hostHeader","allowedHosts","matcher","entry","normalized","joined","contentLength","parsed","reader","writer","Writable","done","allowedOrigins","utils","cookies","locals","platform","setHeadersState","normalizedName","json","content","redirect","status","text","html","dir"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/utils.ts","../src/middlewares/ratelimiter/InMemory.ts","../src/middlewares/ratelimiter/index.ts","../src/middlewares/cros/index.ts","../src/types/RequestMethod.ts","../src/types/router.ts","../src/types/Cookies.ts","../src/types/server.ts","../src/helpers/static.ts","../src/helpers/sse.ts","../src/index.ts"],"sourcesContent":["export function isHttpError(err: unknown): err is Response {\n return isResponse(err) && err.status >= 400 && err.status < 600;\n}\n\nexport function isRedirect(err: unknown): err is Response {\n return isResponse(err) && err.status >= 300 && err.status < 400;\n}\n\nexport function isResponse(err: unknown): err is Response {\n return err instanceof Response;\n}\n","import type {RateLimitStore} from \"./storage\";\n\nexport class MemoryStore implements RateLimitStore {\n private readonly windowMs: number;\n private data = new Map<string, { count: number; reset: number }>();\n private cleanupInterval?: NodeJS.Timeout;\n\n constructor(opts: { windowMs: number }) {\n this.windowMs = opts.windowMs;\n this.startCleanup();\n }\n\n async incr(key: string): Promise<{ current: number; reset: number }> {\n const now = Date.now();\n let record = this.data.get(key);\n\n if (!record || now >= record.reset) {\n const reset = now + this.windowMs;\n record = {count: 1, reset};\n this.data.set(key, record);\n } else {\n record.count++;\n }\n\n return {current: record.count, reset: record.reset};\n }\n\n private startCleanup() {\n this.cleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [key, {reset}] of this.data) {\n if (now >= reset) {\n this.data.delete(key);\n }\n }\n }, Math.min(this.windowMs, 300_000)); // Max 5 min interval\n }\n\n stop() {\n if (this.cleanupInterval) clearInterval(this.cleanupInterval);\n }\n\n async resetAll() {\n this.data.clear();\n }\n}\n","import type { RateLimitStore } from './storage';\nimport type {Middleware, RequestEvent} from \"../../types\";\nimport {MemoryStore} from \"./InMemory\";\n\nexport type Options = {\n /**\n * Window duration in milliseconds\n * @default 60_000 (1 minute)\n */\n windowMs?: number;\n\n /**\n * Max number of requests per window\n */\n max: number;\n\n /**\n * Function to generate key for rate limiting\n * @default IP address\n */\n key?: (event: RequestEvent) => string;\n\n /**\n * Custom error message (string or JSON)\n * @default \"Too many requests, please try again later.\"\n */\n message?: string | Record<string, any>;\n\n /**\n * HTTP status code to return\n * @default 429\n */\n statusCode?: number;\n\n /**\n * Whether to add rate limit headers\n * @default 'include'\n */\n headers?: 'include' | 'remove';\n\n /**\n * Called when rate limit is hit\n */\n onRateLimit?: (event: RequestEvent, info: { current: number; max: number; key: string }) => void;\n\n /**\n * Storage backend\n * @default MemoryStore\n */\n store?: RateLimitStore;\n};\n\n/**\n * Fixed window rate limiter middleware\n */\nexport function fixedWindowLimit(options: Options): Middleware {\n const {\n windowMs = 60_000,\n max,\n key = (event) => event.getClientAddress(),\n message = 'Too many requests, please try again later.',\n statusCode = 429,\n headers = 'include',\n onRateLimit,\n store = new MemoryStore({ windowMs })\n } = options;\n\n return async (event, next) => {\n const rateLimitKey = `rl:${key(event)}`;\n const { current, reset } = await store.incr(rateLimitKey);\n\n const retryAfter = Math.ceil((reset - Date.now()) / 1000);\n\n if (current > max) {\n if (onRateLimit) {\n onRateLimit(event, { current, max, key: rateLimitKey });\n }\n\n const responseInit: ResponseInit = {\n status: statusCode,\n headers: new Headers()\n };\n\n const header = responseInit.headers! as Headers;\n\n if (headers === 'include') {\n header.set('X-RateLimit-Limit', String(max));\n header.set('X-RateLimit-Remaining', '0');\n header.set('X-RateLimit-Reset', String(Math.floor(reset / 1000)));\n header.set('Retry-After', String(retryAfter));\n }\n\n let body: string;\n if (typeof message === 'string') {\n body = message;\n header.set('Content-Type', 'text/plain');\n } else {\n body = JSON.stringify(message);\n header.set('Content-Type', 'application/json');\n }\n\n return new Response(body, responseInit);\n }\n\n // Add info to event for debugging\n (event as any).rateLimit = {\n current,\n limit: max,\n reset: new Date(reset),\n remaining: max - current\n };\n\n // Add headers to response if enabled\n if (headers === 'include') {\n const rateLimitHeaders = {\n 'X-RateLimit-Limit': String(max),\n 'X-RateLimit-Remaining': String(max - current),\n 'X-RateLimit-Reset': String(Math.floor(reset / 1000))\n };\n const originalSetHeaders = event.setHeaders;\n event.setHeaders = (newHeaders) => {\n originalSetHeaders({\n ...rateLimitHeaders,\n ...newHeaders\n });\n };\n originalSetHeaders(rateLimitHeaders);\n }\n\n return next();\n };\n}\n","import {Middleware} from \"../../types\";\n\n/**\n * Configuration for CORS middleware\n */\nexport interface Options {\n /**\n * Allowed origins (strings or regex)\n * @default '*' (allow all)\n */\n origin?: string | string[] | RegExp | RegExp[] | ((origin: string) => boolean);\n\n /**\n * Allowed methods\n * @default ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']\n */\n methods?: string[];\n\n /**\n * Allowed request headers\n * @default 'Content-Type,X-Auth-Token,Authorization' (plus simple headers)\n */\n allowedHeaders?: string[];\n\n /**\n * Exposed headers in response\n */\n exposedHeaders?: string[];\n\n /**\n * Whether to include credentials (cookies, authorization)\n * @default false\n */\n credentials?: boolean;\n\n /**\n * Max age of preflight result (in seconds)\n * @default 86400 (24h)\n */\n maxAge?: number;\n\n /**\n * Optional callback to modify response before sending\n */\n onResponse?: (response: Response) => void | Response;\n}\n\n/**\n * Default allowed methods\n */\nconst DEFAULT_METHODS = [\n 'GET',\n 'POST',\n 'PUT',\n 'DELETE',\n 'PATCH',\n 'HEAD',\n 'OPTIONS'\n];\n\n/**\n * Default simple headers (always allowed by browsers)\n */\nconst SIMPLE_HEADERS = [\n 'Accept',\n 'Accept-Language',\n 'Content-Language',\n 'Content-Type',\n 'Range'\n];\n\n/**\n * Default allowed headers beyond simple headers\n */\nconst DEFAULT_ALLOWED_HEADERS = [\n 'Authorization',\n 'X-Auth-Token',\n 'X-Requested-With',\n 'X-CSRF-Token',\n 'X-HTTP-Method-Override',\n 'X-Forwarded-For',\n 'X-Real-IP',\n 'X-Custom-Header'\n];\n\n/**\n * Check if origin is allowed\n */\nfunction isOriginAllowed(origin: string, option: Options['origin']): boolean {\n if (!origin || !option) return false;\n\n if (option === '*') return true;\n if (option === 'null') return origin === 'null';\n\n if (Array.isArray(option)) {\n return option.some(o => isOriginAllowed(origin, o));\n }\n\n if (typeof option === 'function') {\n return option(origin);\n }\n\n if (option instanceof RegExp) {\n return option.test(origin);\n }\n\n return origin === option;\n}\n\n/**\n * Get allowed origin header value\n */\nfunction getAllowedOrigin(requestOrigin: string | null, options: Options): string | null {\n const { origin = '*' } = options;\n\n if (!requestOrigin) return origin === '*' ? '*' : null;\n\n if (origin === '*') {\n // If wildcard, reflect the origin (but not for credentials)\n return options.credentials ? requestOrigin : '*';\n }\n\n if (isOriginAllowed(requestOrigin, origin)) {\n return requestOrigin; // Reflect allowed origin\n }\n\n return null;\n}\n\n/**\n * CORS Middleware Factory\n *\n * @example\n * // Allow all (default)\n * cors()\n *\n * @example\n * // Allow specific origin\n * cors({ origin: 'https://myapp.com' })\n *\n * @example\n * // Allow multiple origins\n * cors({ origin: ['https://myapp.com', 'https://admin.com'] })\n *\n * @example\n * // Allow with regex\n * cors({ origin: /^https:\\/\\/.*\\.mycompany\\.com$/ })\n *\n * @example\n * // Allow with credentials\n * cors({\n * origin: 'https://myapp.com',\n * credentials: true\n * })\n */\nexport function policy(options: Options = {}): Middleware {\n const {\n methods = DEFAULT_METHODS,\n allowedHeaders = DEFAULT_ALLOWED_HEADERS,\n exposedHeaders,\n credentials = false,\n maxAge = 86400,\n onResponse\n } = options;\n\n const varyHeader = 'Origin,Access-Control-Request-Method,Access-Control-Request-Headers';\n const methodsHeader = methods.join(',');\n const allowedHeadersHeader = [...SIMPLE_HEADERS, ...allowedHeaders].join(',');\n\n const headersToSet: [string, string][] = [\n ['Vary', varyHeader],\n ['Access-Control-Allow-Methods', methodsHeader],\n ['Access-Control-Allow-Headers', allowedHeadersHeader],\n ];\n\n if (exposedHeaders) {\n headersToSet.push(['Access-Control-Expose-Headers', exposedHeaders.join(',')])\n }\n\n if (credentials) {\n headersToSet.push(['Access-Control-Allow-Credentials', 'true']);\n }\n\n if (maxAge) {\n headersToSet.push(['Access-Control-Max-Age', maxAge.toString()]);\n }\n\n return async (event, next) => {\n const request = event.request;\n const origin = request.headers.get('Origin');\n const isPreflight = request.method === 'OPTIONS'\n && origin !== null\n && request.headers.has('Access-Control-Request-Method');\n\n const allowedOrigin = getAllowedOrigin(origin, options);\n if (isPreflight) {\n if (!allowedOrigin) {\n return new Response(null, {status: 403});\n }\n\n const preflightResponse = new Response(null, {status: 204});\n for (const [key, value] of headersToSet) {\n preflightResponse.headers.set(key, value);\n }\n preflightResponse.headers.set('Access-Control-Allow-Origin', allowedOrigin);\n return preflightResponse;\n }\n\n // Always set Vary and other base headers\n const response = await next();\n\n if (!response) return;\n\n // Check if origin is allowed\n if (!allowedOrigin) return response;\n\n // Clone response so we can modify headers\n const modifiedResponse = new Response(response.body, response);\n\n // Set CORS headers\n for (const [key, value] of headersToSet) {\n modifiedResponse.headers.set(key, value);\n }\n modifiedResponse.headers.set('Access-Control-Allow-Origin', allowedOrigin);\n\n // Allow response to be modified\n let finalResponse = modifiedResponse;\n if (onResponse) {\n const override = onResponse(finalResponse);\n if (override) finalResponse = override;\n }\n\n return finalResponse;\n };\n}\n","export const RequestMethods = ['GET', 'PUT', 'POST', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'] as const;\nexport type RequestMethod = typeof RequestMethods[number];\n","import type {RequestEvent} from \"./RequestEvent\";\nimport {RequestMethod, RequestMethods} from \"./RequestMethod\";\nimport {isHttpError, isRedirect, isResponse} from \"../utils\";\nimport {WebSocket} from \"ws\";\nimport type {MaybePromise} from \"./MaybePromise\";\n\n/**\n * Extracts path parameters from route pattern\n * - [param] → string\n * - [...param] → string (full path segment, e.g. \"a/b/c\")\n * - [[param]] → string | '' (optional segment)\n */\nexport type ExtractPathParams<T extends string> =\n T extends `/${infer Segment}/${infer Rest}`\n ? MergeParams<ExtractSegmentParam<Segment>, ExtractPathParams<`/${Rest}`>>\n : T extends `/${infer Segment}`\n ? ExtractSegmentParam<Segment>\n : {};\n\nexport type ExtractSegmentParam<S extends string> =\n S extends `[...${infer Param}]` ? { [K in Param]: string } :\n S extends `[[${infer Param}]]` ? { [K in Param]?: string } :\n S extends `[${infer Param}]` ? { [K in Param]: string } :\n {};\n\nexport type MergeParams<A, B> = A & B;\n\n// Add Locals generic\nexport type RouteHandler<Path extends string, Locals extends Record<string, any> = {}> = (\n event: RequestEvent<\n ExtractPathParams<Path> & RequestEvent['params'],\n Path,\n Locals\n >\n) => MaybePromise<Response>;\n\nexport type ActionHandler<Path extends string, OutputData extends Record<string, any> = Record<string, any>> = Action<ExtractPathParams<Path>, OutputData>;\n\nexport type Action<\n Params extends Partial<Record<string, string>> = Partial<Record<string, string>>,\n OutputData extends Record<string, any> | void = Record<string, any> | void,\n> = (event: RequestEvent<Params>) => MaybePromise<OutputData>;\n\n// Middleware with locals support\nexport type Middleware<\n Path extends string = string,\n AddedLocals extends Record<string, any> = {}\n> = (\n event: RequestEvent<any, Path, any> & { locals: Record<string, any> & AddedLocals },\n next: () => MaybePromise<Response | undefined>\n) => MaybePromise<Response | undefined>;\n\nexport type PreHandler<Locals extends Record<string, any> = {}> = (\n event: RequestEvent<any, string, Locals>\n) => MaybePromise<Response | void>;\n\nexport type PostHandler<Locals extends Record<string, any> = {}> = (\n event: RequestEvent<any, string, Locals>,\n response: Response\n) => MaybePromise<Response | void>;\n\n// WebSocket Handler\nexport type WebSocketHandler<Path extends string, Locals extends Record<string, any> = {}> = (\n event: RequestEvent<\n ExtractPathParams<Path> & RequestEvent['params'],\n Path,\n Locals\n > & { websocket: WebSocket }\n) => MaybePromise<any>;\n\n// Route definition\nexport interface Route<Path extends string> {\n readonly path: Path;\n readonly method: RequestMethod;\n readonly regex: RegExp;\n readonly paramNames: readonly string[];\n readonly isCatchAll: boolean;\n readonly priority: number;\n readonly handler: RouteHandler<Path, any>;\n readonly middlewares: Middleware<Path>[];\n}\n\ntype WebSocketRoute<Path extends string> = {\n readonly path: Path;\n readonly regex: RegExp;\n readonly paramNames: readonly string[];\n readonly isCatchAll: boolean;\n readonly priority: number;\n readonly handler: WebSocketHandler<Path, any>;\n readonly middlewares: Middleware<Path>[];\n};\n\n// Nested router\ninterface NestedRouter {\n readonly prefix: string;\n readonly router: Router<any>;\n readonly regex: RegExp;\n readonly paramNames: readonly string[];\n readonly isCatchAll: boolean;\n readonly priority: number;\n readonly middlewares: Middleware<any>[];\n}\n\n// Cache for regex creation\nclass PathRegexCache {\n private static cache = new Map<string, {\n regex: RegExp;\n paramNames: string[];\n isCatchAll: boolean;\n priority: number;\n }>();\n\n static get(path: string) {\n return this.cache.get(path);\n }\n\n static set(path: string, value: {\n regex: RegExp;\n paramNames: string[];\n isCatchAll: boolean;\n priority: number;\n }) {\n this.cache.set(path, value);\n }\n}\n\nexport class Router<Locals extends App.Locals = App.Locals> {\n private _routes: Route<any>[] = [];\n private _wsRoutes: WebSocketRoute<any>[] = [];\n private _nestedRouters: NestedRouter[] = [];\n private _middlewares: Middleware<string, any>[] = [];\n private _preHandlers: PreHandler<Locals>[] = [];\n private _postHandlers: PostHandler<Locals>[] = [];\n private routesSorted = false;\n private wsRoutesSorted = false;\n\n get routes(): readonly Route<any>[] {\n return this._routes;\n }\n\n get nestedRouters(): readonly NestedRouter[] {\n return this._nestedRouters;\n }\n\n // HTTP method handlers\n GET<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('GET', path, handler, middlewares);\n }\n\n POST<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('POST', path, handler, middlewares);\n }\n\n PUT<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('PUT', path, handler, middlewares);\n }\n\n PATCH<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('PATCH', path, handler, middlewares);\n }\n\n DELETE<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('DELETE', path, handler, middlewares);\n }\n\n HEAD<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('HEAD', path, handler, middlewares);\n }\n\n OPTIONS<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n return this.addHandler('OPTIONS', path, handler, middlewares);\n }\n\n // Universal method\n USE<Path extends string>(\n path: Path,\n handler: RouteHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n RequestMethods.forEach(method => this.addHandler(method, path, handler, middlewares));\n return this;\n }\n\n // Action handler (POST only)\n action<Path extends string, OutputData extends Record<string, any> = Record<string, any>>(\n path: Path,\n handler: ActionHandler<Path, OutputData>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n const wrapped: RouteHandler<Path, Locals> = async (event) => {\n try {\n const result = await handler(event as RequestEvent<ExtractPathParams<Path>, Path, Locals>);\n return this.formatActionResult(result);\n } catch (error) {\n return this.handleActionError(error);\n }\n };\n\n return this.addHandler('POST', path, wrapped, middlewares);\n }\n\n // Nested routing\n use<Prefix extends string, InnerLocals extends Record<string, any>>(input: readonly [Prefix, Router<InnerLocals>, ...Middleware<Prefix>[]]): Router<Locals & InnerLocals>;\n use<Prefix extends string, InnerLocals extends Record<string, any>>(prefix: Prefix, router: Router<InnerLocals>, ...middlewares: Middleware<Prefix>[]): Router<Locals & InnerLocals>;\n use<Prefix extends string, InnerLocals extends Record<string, any>>(arg1: string | readonly [Prefix, Router<InnerLocals>, ...Middleware<Prefix>[]], arg2?: Router<InnerLocals>, ...middlewares: Middleware<Prefix>[]): Router<Locals & InnerLocals> {\n let prefix: Prefix;\n let router: Router<InnerLocals>;\n let finalMiddlewares: Middleware<Prefix>[] = middlewares;\n\n if (Array.isArray(arg1)) {\n [prefix, router] = arg1;\n finalMiddlewares = arg1.length > 2 ? arg1.slice(2) as Middleware<Prefix>[] : [];\n } else {\n prefix = arg1 as Prefix;\n router = arg2!;\n }\n\n const normalizedPrefix = this.normalizePrefix(prefix);\n const {regex, paramNames, isCatchAll, priority} = this.createPrefixRegex(normalizedPrefix);\n\n this._nestedRouters.push({\n prefix: normalizedPrefix,\n router,\n regex,\n paramNames,\n isCatchAll,\n priority,\n middlewares: finalMiddlewares\n });\n\n return this as unknown as Router<Locals & InnerLocals>;\n }\n\n // Global middleware\n useMiddleware<NewLocals extends Record<string, any>>(\n ...mw: Middleware<string, NewLocals>[]\n ): Router<Locals & NewLocals> {\n this._middlewares.push(...mw);\n return this as unknown as Router<Locals & NewLocals>;\n }\n\n pre(...handlers: PreHandler<Locals>[]): Router<Locals> {\n this._preHandlers.push(...handlers);\n return this;\n }\n\n post(...handlers: PostHandler<Locals>[]): Router<Locals> {\n this._postHandlers.push(...handlers);\n return this;\n }\n\n // Discard routes or nested routers\n discard(path_or_prefix: string, method?: RequestMethod): this {\n this._nestedRouters = this._nestedRouters.filter(r => r.prefix !== path_or_prefix);\n this._routes = this._routes.filter(route =>\n route.path !== path_or_prefix || (method && route.method !== method)\n );\n return this;\n }\n\n // WebSocket route\n WS<Path extends string>(\n path: Path,\n handler: WebSocketHandler<Path, Locals>,\n ...middlewares: Middleware<Path, any>[]\n ): Router<Locals> {\n const {regex, paramNames, isCatchAll, priority} = this.createPathRegex(path);\n\n this._wsRoutes.push({\n path,\n regex,\n paramNames,\n isCatchAll,\n priority,\n handler,\n middlewares\n });\n\n this.wsRoutesSorted = false;\n return this;\n }\n\n // Add this method to your Router class\n\n /**\n * Check if the router can handle a WebSocket connection for the given path\n * This is used during the upgrade process to validate routes before attempting connection\n */\n public async canHandleWebSocket(event: RequestEvent): Promise<boolean> {\n return this.canHandleWebSocketAtPath(event, event.url.pathname);\n }\n\n private async canHandleWebSocketAtPath(event: RequestEvent, pathname: string): Promise<boolean> {\n if (!this.wsRoutesSorted) this.sortWsRoutes();\n\n // 1. Check nested routers first\n for (const nested of [...this._nestedRouters].sort((a, b) => b.priority - a.priority)) {\n const match = pathname.match(nested.regex);\n if (!match || match.index !== 0) continue;\n\n const matched = match[0];\n const remaining = pathname.slice(matched.length) || '/';\n\n const nestedEvent: RequestEvent = {\n ...event,\n params: {...event.params, ...this.extractPrefixParams(nested, matched)}\n };\n\n // Recursively check if nested router can handle the WebSocket\n if (await nested.router.canHandleWebSocketAtPath(nestedEvent, remaining)) {\n return true;\n }\n }\n\n // 2. Check local WebSocket routes\n for (const route of this._wsRoutes) {\n if (route.regex.test(pathname)) {\n return true;\n }\n }\n\n return false;\n }\n\n // Handle WebSocket upgrade\n public async handleWebSocket(\n event: RequestEvent,\n websocket: WebSocket\n ): Promise<boolean> {\n return this.handleWebSocketAtPath(event, websocket, event.url.pathname);\n }\n\n private async handleWebSocketAtPath(\n event: RequestEvent,\n websocket: WebSocket,\n pathname: string\n ): Promise<boolean> {\n if (!this.wsRoutesSorted) this.sortWsRoutes();\n\n // 1. Try nested routers\n for (const nested of [...this._nestedRouters].sort((a, b) => b.priority - a.priority)) {\n const match = pathname.match(nested.regex);\n if (!match || match.index !== 0) continue;\n\n const matched = match[0];\n const remaining = pathname.slice(matched.length) || '/';\n const prefixParams = this.extractPrefixParams(nested, matched);\n\n const nestedEvent: RequestEvent = {\n ...event,\n params: {...event.params, ...prefixParams}\n };\n\n const effectiveMiddlewares = [...this._middlewares, ...nested.middlewares];\n const handler = () => nested.router.handleWebSocketAtPath(nestedEvent, websocket, remaining);\n\n const result = await this.applyMiddlewaresWithList(nestedEvent, effectiveMiddlewares, handler as any);\n if (!result) continue;\n else return true;\n }\n\n // 2. Try local WebSocket routes\n for (const route of this._wsRoutes) {\n if (!route.regex.test(pathname)) continue;\n\n const match = pathname.match(route.regex);\n if (!match) continue;\n\n const params = Object.fromEntries(\n route.paramNames.map((name, i) => [name, match[i + 1] || ''])\n );\n\n const enhancedEvent = {\n ...event,\n params: {...event.params, ...params},\n route: {...event.route, id: route.path},\n websocket,\n }\n\n const allMiddlewares = [...this._middlewares, ...route.middlewares];\n\n\n const result = await this.applyMiddlewaresWithList(enhancedEvent, allMiddlewares, () => route.handler(enhancedEvent));\n if (result === undefined) {\n return true;\n }\n }\n\n return false;\n }\n\n // Handle HTTP request - FIXED: Single middleware application\n protected async handle(event: RequestEvent): Promise<Response> {\n return this.handleAtPath(event, event.url.pathname);\n }\n\n private async handleAtPath(event: RequestEvent, path: string): Promise<Response> {\n try {\n const method = event.request.method as RequestMethod;\n let response = await this.runPreHandlers(event);\n if (!response) {\n // Apply global middlewares once at the top level\n const handler = async () => {\n // Try nested routers first\n const nestedResponse = await this.handleNestedRouters(event, path);\n if (nestedResponse) return nestedResponse;\n\n // Then try local routes\n if (!this.routesSorted) this.sortRoutes();\n return this.handleLocalRoutes(event, method, path);\n };\n\n response = await this.applyMiddlewaresWithList(event, this._middlewares, handler);\n }\n\n const finalResponse = response || new Response(\"No Content\", {status: 204});\n return await this.runPostHandlers(event, finalResponse);\n } catch (err) {\n if (isResponse(err)) return err;\n throw err;\n }\n }\n\n // Apply middlewares utility\n private async applyMiddlewaresWithList(\n event: RequestEvent,\n mws: Middleware<string, any>[],\n next: () => MaybePromise<Response | undefined>\n ) {\n const chain = [...mws];\n const run = async (index: number): Promise<Response | undefined> => {\n if (index >= chain.length) return next();\n return chain[index](event, () => run(index + 1));\n };\n return run(0);\n }\n\n private async runPreHandlers(event: RequestEvent): Promise<Response | undefined> {\n for (const handler of this._preHandlers) {\n const response = await handler(event as RequestEvent<any, string, Locals>);\n if (response instanceof Response) {\n return response;\n }\n }\n\n return undefined;\n }\n\n private async runPostHandlers(event: RequestEvent, response: Response): Promise<Response> {\n let currentResponse = response;\n\n for (const handler of this._postHandlers) {\n const nextResponse = await handler(event as RequestEvent<any, string, Locals>, currentResponse);\n if (nextResponse instanceof Response) {\n currentResponse = nextResponse;\n }\n }\n\n return currentResponse;\n }\n\n // Add route handler\n private addHandler<Path extends string>(\n method: RequestMethod,\n path: Path,\n handler: RouteHandler<Path, Locals>,\n middlewares: Middleware<Path, any>[] = []\n ): Router<Locals> {\n const {regex, paramNames, isCatchAll, priority} = this.createPathRegex(path);\n\n this._routes.push({\n method,\n path,\n regex,\n paramNames,\n isCatchAll,\n priority,\n handler,\n middlewares\n });\n\n this.routesSorted = false;\n return this;\n }\n\n // Create regex for route path\n private createPathRegex(path: string) {\n const cached = PathRegexCache.get(path);\n if (cached) return cached;\n\n const paramNames: string[] = [];\n let isCatchAll = false;\n let priority: number;\n\n const segments = path.split('/').filter(Boolean);\n priority = segments.reduce((acc, segment) => {\n if (segment.startsWith('[...')) return acc - 10;\n if (segment.startsWith('[[')) return acc - 5;\n if (segment.startsWith('[')) return acc - 1;\n return acc + 1;\n }, 0);\n\n let regexString = '^';\n for (const part of segments) {\n if (part.startsWith('[...') && part.endsWith(']')) {\n isCatchAll = true;\n const paramName = part.slice(4, -1);\n paramNames.push(paramName);\n regexString += '/(.+)';\n } else if (part.startsWith('[[') && part.endsWith(']]')) {\n const paramName = part.slice(2, -2);\n paramNames.push(paramName);\n regexString += '(?:/([^/]+))?';\n } else if (part.startsWith('[') && part.endsWith(']')) {\n const paramName = part.slice(1, -1);\n paramNames.push(paramName);\n regexString += '/([^/]+)';\n } else {\n regexString += '/' + part.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n }\n }\n regexString += '/?$';\n\n const result = {regex: new RegExp(regexString), paramNames, isCatchAll, priority};\n PathRegexCache.set(path, result);\n return result;\n }\n\n // Create regex for prefix\n private createPrefixRegex(prefix: string) {\n const paramNames: string[] = [];\n let isCatchAll = false;\n let priority: number;\n\n const segments = prefix.split('/').filter(Boolean);\n priority = segments.reduce((acc, segment) => {\n if (segment.startsWith('[...')) return acc - 10;\n if (segment.startsWith('[[')) return acc - 5;\n if (segment.startsWith('[')) return acc - 1;\n return acc + 1;\n }, 0);\n\n let regexString = '^';\n for (const part of segments) {\n if (part.startsWith('[...') && part.endsWith(']')) {\n isCatchAll = true;\n const paramName = part.slice(4, -1);\n paramNames.push(paramName);\n regexString += '/(.+)';\n } else if (part.startsWith('[[') && part.endsWith(']]')) {\n const paramName = part.slice(2, -2);\n paramNames.push(paramName);\n regexString += '(?:/([^/]+))?';\n } else if (part.startsWith('[') && part.endsWith(']')) {\n const paramName = part.slice(1, -1);\n paramNames.push(paramName);\n regexString += '/([^/]+)';\n } else {\n regexString += '/' + part.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n }\n }\n regexString += '(?=/|$)';\n\n return {regex: new RegExp(regexString), paramNames, isCatchAll, priority};\n }\n\n private normalizePrefix(prefix: string): string {\n return prefix.startsWith('/') ? prefix.replace(/\\/$/, '') : `/${prefix.replace(/\\/$/, '')}`;\n }\n\n private extractPrefixParams(nested: NestedRouter, matchedPath: string): Record<string, string> {\n const match = matchedPath.match(nested.regex);\n if (!match) return {};\n\n const params: Record<string, string> = {};\n if (nested.isCatchAll && nested.paramNames.length === 1) {\n params[nested.paramNames[0]] = match[1]?.replace(/^\\//, '') || '';\n } else {\n nested.paramNames.forEach((name, i) => {\n params[name] = match[i + 1] || '';\n });\n }\n return params;\n }\n\n // FIXED: Nested router handling without duplicate middleware application\n private async handleNestedRouters(event: RequestEvent, path: string): Promise<Response | null> {\n const sorted = [...this._nestedRouters].sort((a, b) => b.priority - a.priority);\n\n for (const nested of sorted) {\n const match = path.match(nested.regex);\n if (!match || match.index !== 0) continue;\n\n const matched = match[0];\n const remaining = path.slice(matched.length) || '/';\n const prefixParams = this.extractPrefixParams(nested, matched);\n\n const nestedEvent: RequestEvent = {\n ...event,\n params: {...event.params, ...prefixParams}\n };\n\n // Apply nested middlewares and handle nested router\n // Note: nested.router.handle() will apply its own global middlewares\n const handler = async () => await nested.router.handleAtPath(nestedEvent, remaining);\n const response = await this.applyMiddlewaresWithList(nestedEvent, nested.middlewares, handler);\n if (response) return response;\n }\n\n return null;\n }\n\n // FIXED: Local route handling without duplicate middleware application\n private async handleLocalRoutes(event: RequestEvent, method: RequestMethod, path: string) {\n const allowed = new Set<RequestMethod>();\n let getRouteForHead = false;\n\n for (const route of this._routes) {\n if (!route.regex.test(path)) continue;\n allowed.add(route.method);\n if (route.method === 'GET') {\n getRouteForHead = true;\n allowed.add('HEAD');\n }\n\n const matchesMethod = route.method === method || (method === 'HEAD' && route.method === 'GET');\n if (!matchesMethod) continue;\n\n const match = path.match(route.regex);\n if (!match) continue;\n\n const params = Object.fromEntries(\n route.paramNames.map((name, i) => [name, match[i + 1] || ''])\n );\n\n event.params = {...event.params, ...params};\n event.route = {...event.route, id: route.path};\n\n // Only apply route-specific middlewares here\n // Global middlewares were already applied in handle()\n const finalHandler = () => route.handler(event);\n return await this.applyMiddlewaresWithList(event, route.middlewares, finalHandler);\n }\n\n if (allowed.size > 0 || (method === 'HEAD' && getRouteForHead)) {\n const allowHeader = [...allowed].join(', ');\n if (method === 'OPTIONS') {\n return new Response(null, {\n status: 200,\n headers: {'Allow': allowHeader}\n });\n }\n return new Response('Method Not Allowed', {\n status: 405,\n headers: {'Allow': allowHeader}\n });\n }\n\n return new Response('Not Found', {status: 404});\n }\n\n private sortRoutes(): void {\n this._routes.sort((a, b) => b.priority - a.priority);\n this.routesSorted = true;\n }\n\n private sortWsRoutes(): void {\n this._wsRoutes.sort((a, b) => b.priority - a.priority);\n this.wsRoutesSorted = true;\n }\n\n private formatActionResult(result: any): Response {\n if (result instanceof Response) return result;\n if (result?.type === 'failure' && 'status' in result) {\n return Action.fail(result.status, result.data);\n }\n return Action.success(200, result ?? undefined);\n }\n\n private handleActionError(err: unknown): Response {\n if (isHttpError(err)) {\n return Action.error(err.status, {message: err.statusText || 'Error'});\n }\n if (isRedirect(err)) {\n const url = err.headers.get('Location') || '/';\n return Action.redirect(err.status, url);\n }\n console.error(err);\n return Action.error(500, {message: 'Internal Server Error'});\n }\n\n static New(): Router {\n return new Router();\n }\n}\n\n// Action utilities\nexport const Action = {\n success: (code: number = 200, data?: Record<string, any>): Response =>\n new Response(JSON.stringify({data, type: 'success', status: code}), {\n status: code,\n headers: {'Content-Type': 'application/json'}\n }),\n\n redirect: (code: number = 302, location: string): Response =>\n new Response(JSON.stringify({location, type: 'redirect', status: code}), {\n status: code,\n headers: {'Content-Type': 'application/json'}\n }),\n\n error: (code: number = 500, error: App.Error): Response =>\n new Response(JSON.stringify({error, type: 'error', status: code}), {\n status: code,\n headers: {'Content-Type': 'application/json'}\n }),\n\n fail: (code: number = 400, data: Record<string, any>): Response =>\n new Response(JSON.stringify({data, type: 'failure', status: code}), {\n status: code,\n headers: {'Content-Type': 'application/json'}\n })\n} as const;\n","import {type ParseOptions, parse, serialize, type SerializeOptions} from \"cookie\";\n\nexport class Cookies {\n private readonly setCookieHeader: (serialized: string) => void;\n private readonly raw: string;\n\n constructor(request: Request, setCookieHeader: (serialized: string) => void) {\n this.raw = request.headers.get('cookie') ?? '';\n this.setCookieHeader = setCookieHeader;\n }\n\n get(name: string, opts?: ParseOptions): string | undefined {\n return parse(this.raw, opts)[name];\n }\n\n getAll(opts?: ParseOptions): { name: string; value: string }[] {\n return Object.entries(parse(this.raw, opts))\n .filter(([, v]) => v !== undefined)\n .map(([name, value]) => ({name, value})) as {name: string, value: string}[];\n }\n\n set(name: string, value: string, opts: SerializeOptions & { path: string }): void {\n this.setCookieHeader(serialize(name, value, opts));\n }\n\n delete(name: string, opts: SerializeOptions & { path: string }): void {\n this.set(name, '', {...opts, maxAge: 0});\n }\n}\n","import {\n createServer as createHttpServer,\n type Server as HttpServer,\n IncomingMessage,\n type ServerOptions,\n ServerResponse\n} from 'http';\nimport {\n createServer as createHttpsServer,\n type Server as HttpsServer,\n type ServerOptions as HttpsServerOptions\n} from 'https';\nimport {TLSSocket} from 'tls';\nimport {Readable, Transform, Writable} from 'stream';\nimport {\n type RequestEvent,\n Router\n} from './';\nimport {isHttpError, isRedirect} from \"../utils\";\nimport {WebSocketServer, WebSocket} from \"ws\";\nimport {Cookies} from \"./Cookies\";\nimport {ListenOptions} from \"net\";\n\ntype HostMatcher = string | RegExp | ((host: string) => boolean);\ntype InferServerLocals<TServerConfig extends ServerConfig> =\n Extract<TServerConfig['locals'], (event: RequestEvent) => any> extends (event: RequestEvent) => infer TLocals\n ? TLocals extends Record<string, any>\n ? TLocals\n : App.Locals\n : App.Locals;\ntype ListenArgs =\n | [port?: number, hostname?: string, backlog?: number, listeningListener?: () => void]\n | [port?: number, hostname?: string, listeningListener?: () => void]\n | [port?: number, backlog?: number, listeningListener?: () => void]\n | [port?: number, listeningListener?: () => void]\n | [path: string, backlog?: number, listeningListener?: () => void]\n | [path: string, listeningListener?: () => void]\n | [options: ListenOptions, listeningListener?: () => void]\n | [handle: any, backlog?: number, listeningListener?: () => void]\n | [handle: any, listeningListener?: () => void];\n\nclass PayloadTooLargeError extends Error {\n readonly status = 413;\n\n constructor(message = 'Payload Too Large') {\n super(message);\n this.name = 'PayloadTooLargeError';\n }\n}\n\nexport type SecurityConfig = {\n /**\n * Trust the incoming Host header when constructing event.url/request.url.\n * Disabled by default to avoid host header poisoning in absolute URL generation.\n */\n trustHostHeader?: boolean;\n\n /**\n * Restrict trusted Host values when trustHostHeader is enabled.\n */\n allowedHosts?: HostMatcher | HostMatcher[];\n\n /**\n * Restrict accepted WebSocket Origin values.\n * When omitted, Origin is not enforced by default.\n */\n allowedWebSocketOrigins?: HostMatcher | HostMatcher[];\n\n /**\n * Maximum accepted request body size based on Content-Length.\n * Requests above the limit are rejected before the body is read.\n */\n maxRequestBodySize?: number;\n\n /**\n * Maximum accepted WebSocket message size in bytes.\n * Passed to ws as maxPayload.\n */\n maxWebSocketPayload?: number;\n};\n\nexport type HttpServerConfig = {\n type: 'http';\n options?: ServerOptions;\n security?: SecurityConfig;\n};\n\nexport type HttpsServerConfig = {\n type: 'https';\n options: HttpsServerOptions;\n security?: SecurityConfig;\n};\n\nexport type ServerConfig = {\n locals?: (event: RequestEvent) => App.Locals;\n platform?: (event: RequestEvent) => App.Platform;\n} & (HttpServerConfig | HttpsServerConfig);\n\nexport class WebServer<TServerConfig extends ServerConfig = ServerConfig> extends Router<InferServerLocals<TServerConfig>> {\n private _server!: TServerConfig['type'] extends 'https' ? HttpsServer : HttpServer;\n private readonly config: TServerConfig;\n private upgradeHandlerInstalled = false;\n\n // Single WebSocket server instance\n private readonly wss: WebSocketServer;\n\n constructor(config?: TServerConfig) {\n super();\n this.config = (config ?? {type: 'http', options: {}}) as TServerConfig;\n this.wss = new WebSocketServer({\n noServer: true,\n maxPayload: this.config.security?.maxWebSocketPayload ?? 1024 * 1024\n });\n }\n\n private get server(): TServerConfig['type'] extends 'https' ? HttpsServer : HttpServer {\n if (!this._server) {\n const requestListener = (req: IncomingMessage, res: ServerResponse) => {\n this.handleRequest(req, res).catch(err => {\n console.error('Unhandled request error:', err);\n res.statusCode = 500;\n res.end('Internal Server Error');\n });\n };\n\n // @ts-ignore\n this._server = this.config.type === 'https'\n ? createHttpsServer(this.config.options as HttpsServerOptions, requestListener)\n : createHttpServer(this.config.options as ServerOptions, requestListener);\n }\n return this._server;\n }\n\n listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): this;\n listen(port?: number, hostname?: string, listeningListener?: () => void): this;\n listen(port?: number, backlog?: number, listeningListener?: () => void): this;\n listen(port?: number, listeningListener?: () => void): this;\n listen(path: string, backlog?: number, listeningListener?: () => void): this;\n listen(path: string, listeningListener?: () => void): this;\n listen(options: ListenOptions, listeningListener?: () => void): this;\n listen(handle: any, backlog?: number, listeningListener?: () => void): this;\n listen(handle: any, listeningListener?: () => void): this;\n listen(...args: ListenArgs): this {\n if (!this.upgradeHandlerInstalled) {\n this.installUpgradeHandler();\n this.upgradeHandlerInstalled = true;\n }\n\n this.server.listen(...args);\n return this;\n }\n\n private installUpgradeHandler(): void {\n this.server.on('upgrade', (req, socket, head) => {\n if (req.headers.upgrade?.toLowerCase() !== 'websocket') {\n socket.destroy();\n return;\n }\n\n let url: URL;\n let request: Request;\n try {\n url = this.toURL(req, true);\n request = this.toRequest(req, url, true);\n } catch {\n socket.destroy();\n return;\n }\n\n const event = this.toRequestEvent(request, url, {\n getClientAddress: () => req.socket.remoteAddress ?? '127.0.0.1',\n setHeader: () => {\n },\n pushSetCookie: () => {\n }\n });\n\n this.canHandleWebSocket(event)\n .then((canHandle) => {\n if (!canHandle || !this.isAllowedWebSocketOrigin(req)) {\n socket.destroy();\n return;\n }\n\n this.wss.handleUpgrade(req, socket, head, (ws: WebSocket) => {\n this.handleWebSocket(event, ws).then((handled) => {\n if (!handled && ws.readyState === WebSocket.OPEN) {\n ws.close(1008, 'Route not found');\n }\n }).catch(err => {\n console.error('WebSocket routing error:', err);\n if (ws.readyState === WebSocket.OPEN) {\n ws.close(1011, 'Internal error');\n }\n });\n });\n })\n .catch(() => socket.destroy());\n });\n }\n\n close(callback?: (err?: Error) => void): void {\n this.wss.close(() => {\n this.server.close(callback);\n });\n }\n\n address(): string | import('net').AddressInfo | null {\n return this.server.address();\n }\n\n get listening(): boolean {\n return this.server.listening;\n }\n\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n if (!this.isRequestBodyAllowed(req)) {\n res.statusCode = 413;\n res.end('Payload Too Large');\n return;\n }\n\n const request = this.toWebRequest(req);\n const url = new URL(request.url);\n\n const setHeaders: Record<string, string> = {};\n const setCookies: string[] = [];\n\n const event = this.toRequestEvent(request, url, {\n getClientAddress: () => req.socket.remoteAddress ?? '127.0.0.1',\n setHeader: (name: string, value: string) => {\n setHeaders[name.toLowerCase()] = value;\n },\n pushSetCookie: (serialized: string) => {\n setCookies.push(serialized);\n }\n });\n\n let response: Response;\n try {\n response = await this.handle(event);\n } catch (err) {\n response = this.handleError(err);\n }\n\n for (const [name, value] of Object.entries(setHeaders)) {\n res.setHeader(name, value);\n }\n\n if (setCookies.length > 0) {\n res.setHeader('Set-Cookie', setCookies);\n }\n\n await this.sendWebResponse(res, response);\n }\n\n private toWebRequest(req: IncomingMessage): Request {\n const url = this.toURL(req, false);\n return this.toRequest(req, url, false);\n }\n\n private toRequest(req: IncomingMessage, url: URL, isWebSocket: boolean): Request {\n const init: RequestInit = {\n method: isWebSocket ? 'GET' : req.method,\n headers: this.toHeaders(req.headers),\n // @ts-ignore\n duplex: 'half'\n };\n\n if (!isWebSocket && req.method !== 'GET' && req.method !== 'HEAD') {\n init.body = Readable.toWeb(this.wrapRequestBody(req)) as unknown as ReadableStream<Uint8Array>;\n }\n\n return new Request(url, init);\n }\n\n private wrapRequestBody(req: IncomingMessage): Readable {\n const limit = this.config.security?.maxRequestBodySize;\n if (!limit) {\n return req;\n }\n\n let total = 0;\n const limiter = new Transform({\n transform(chunk, _encoding, callback) {\n total += Buffer.byteLength(chunk);\n if (total > limit) {\n callback(new PayloadTooLargeError());\n return;\n }\n\n callback(null, chunk);\n }\n });\n\n req.on('aborted', () => limiter.destroy(new Error('Request aborted')));\n req.on('error', (error) => limiter.destroy(error));\n req.pipe(limiter);\n return limiter;\n }\n\n private toURL(req: IncomingMessage, isWebSocket: boolean): URL {\n const protocol = req.socket instanceof TLSSocket ? (isWebSocket ? 'wss' : 'https') : (isWebSocket ? 'ws' : 'http');\n const authority = this.resolveAuthority(req);\n return new URL(req.url ?? '/', `${protocol}://${authority}`);\n }\n\n private resolveAuthority(req: IncomingMessage): string {\n const trustedAuthority = this.config.security?.trustHostHeader ? this.normalizeTrustedHost(req.headers.host) : null;\n if (trustedAuthority) {\n return trustedAuthority;\n }\n\n const address = this.server.address();\n if (address && typeof address === 'object') {\n const host = address.address.includes(':') ? `[${address.address}]` : address.address;\n return `${host}:${address.port}`;\n }\n\n return req.socket.localPort ? `127.0.0.1:${req.socket.localPort}` : 'localhost';\n }\n\n private normalizeTrustedHost(hostHeader: string | undefined): string | null {\n if (!hostHeader) return null;\n\n let url: URL;\n try {\n url = new URL(`http://${hostHeader}`);\n } catch {\n return null;\n }\n\n if (url.username || url.password || url.pathname !== '/' || url.search || url.hash) {\n return null;\n }\n\n const authority = url.port ? `${url.hostname}:${url.port}` : url.hostname;\n const allowedHosts = this.config.security?.allowedHosts;\n if (!allowedHosts || this.matchesValue(authority, allowedHosts)) {\n return authority;\n }\n\n return null;\n }\n\n private matchesValue(value: string, matcher: HostMatcher | HostMatcher[]): boolean {\n const matchers = Array.isArray(matcher) ? matcher : [matcher];\n return matchers.some((entry) => {\n if (typeof entry === 'string') return entry === value;\n if (entry instanceof RegExp) return entry.test(value);\n return entry(value);\n });\n }\n\n private toHeaders(headers: IncomingMessage['headers']): Headers {\n const normalized = new Headers();\n for (const [name, value] of Object.entries(headers)) {\n if (value === undefined) continue;\n\n if (Array.isArray(value)) {\n const joined = name.toLowerCase() === 'cookie' ? value.join('; ') : value.join(', ');\n normalized.set(name, joined);\n continue;\n }\n\n normalized.set(name, value);\n }\n\n return normalized;\n }\n\n private isRequestBodyAllowed(req: IncomingMessage): boolean {\n const limit = this.config.security?.maxRequestBodySize;\n if (!limit) return true;\n\n const contentLength = req.headers['content-length'];\n if (!contentLength) return true;\n\n const parsed = Number.parseInt(Array.isArray(contentLength) ? contentLength[0] : contentLength, 10);\n return Number.isFinite(parsed) && parsed <= limit;\n }\n\n private handleError(err: unknown): Response {\n if (err instanceof PayloadTooLargeError) {\n return new Response(err.message, {status: err.status});\n }\n\n if (isHttpError(err)) {\n return new Response(JSON.stringify({\n error: err.statusText || 'Error',\n status: err.status\n }), {\n status: err.status,\n headers: {'Content-Type': 'application/json'}\n });\n }\n\n if (isRedirect(err)) {\n const location = err.headers.get('Location') || '/';\n return new Response(null, {\n status: err.status,\n headers: {'Location': location}\n });\n }\n\n console.error('Unhandled error:', err);\n return new Response('Internal Server Error', {status: 500});\n }\n\n private async sendWebResponse(res: ServerResponse, response: Response): Promise<void> {\n res.statusCode = response.status;\n response.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n\n if (!res.hasHeader('Server')) {\n res.setHeader('Server', 'WebHTTPServer');\n }\n\n if (!response.body || this.shouldOmitResponseBody(response, res.req?.method)) {\n res.end();\n return;\n }\n\n const reader = response.body.getReader();\n const writer = Writable.toWeb(res).getWriter();\n\n try {\n while (true) {\n const {done, value} = await reader.read();\n if (done) break;\n await writer.write(value);\n }\n } finally {\n await writer.close().catch(() => {\n });\n }\n }\n\n private shouldOmitResponseBody(response: Response, method?: string): boolean {\n if (method === 'HEAD') return true;\n return response.status === 204 || response.status === 205 || response.status === 304;\n }\n\n private isAllowedWebSocketOrigin(req: IncomingMessage): boolean {\n const origin = req.headers.origin;\n if (!origin) return true;\n\n const allowedOrigins = this.config.security?.allowedWebSocketOrigins;\n if (!allowedOrigins) return true;\n\n return this.matchesValue(origin, allowedOrigins);\n }\n\n private toRequestEvent(\n request: Request,\n url: URL,\n utils: {\n getClientAddress: () => string;\n setHeader: (name: string, value: string) => void;\n pushSetCookie: (serialized: string) => void;\n }\n ): RequestEvent<{}> {\n const cookies = new Cookies(request, utils.pushSetCookie);\n const handlers = this.config;\n const locals: App.Locals | Record<string, any> = {};\n const platform: App.Platform | Record<string, any> = {name: 'WebHTTPServer'};\n const setHeadersState = new Set<string>();\n\n const event: RequestEvent<{}> = {\n request,\n url,\n cookies,\n getClientAddress: utils.getClientAddress,\n get locals(): App.Locals {\n return locals;\n },\n get platform(): App.Platform | undefined {\n return platform;\n },\n params: {},\n route: {id: ''},\n setHeaders: (headers: Record<string, string>) => {\n for (const [name, value] of Object.entries(headers)) {\n const normalizedName = name.toLowerCase();\n if (normalizedName === 'set-cookie') {\n throw new TypeError('Use event.cookies for Set-Cookie headers');\n }\n if (setHeadersState.has(normalizedName)) {\n throw new TypeError(`Header \"${name}\" has already been set`);\n }\n setHeadersState.add(normalizedName);\n utils.setHeader(name, value);\n }\n }\n };\n\n if (handlers.locals) {\n Object.assign(locals, handlers.locals(event));\n }\n if (handlers.platform) {\n Object.assign(platform as Record<string, any>, handlers.platform(event));\n }\n\n return event;\n }\n}\n","import { createReadStream } from \"node:fs\";\nimport { lstat, realpath, stat } from \"node:fs/promises\";\nimport { extname, isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { Readable } from \"node:stream\";\n\nimport type {RequestEvent, RouteHandler} from \"../types\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".avif\": \"image/avif\",\n \".css\": \"text/css; charset=utf-8\",\n \".gif\": \"image/gif\",\n \".html\": \"text/html; charset=utf-8\",\n \".ico\": \"image/x-icon\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".mjs\": \"text/javascript; charset=utf-8\",\n \".pdf\": \"application/pdf\",\n \".png\": \"image/png\",\n \".svg\": \"image/svg+xml; charset=utf-8\",\n \".txt\": \"text/plain; charset=utf-8\",\n \".wasm\": \"application/wasm\",\n \".webp\": \"image/webp\",\n \".xml\": \"application/xml; charset=utf-8\"\n};\n\nexport type StaticOptions = {\n index?: string;\n cacheControl?: string;\n dotFiles?: \"allow\" | \"deny\" | \"ignore\";\n headers?: HeadersInit | ((filePath: string, stats: Awaited<ReturnType<typeof stat>>) => HeadersInit);\n};\n\nconst DEFAULT_STATIC_OPTIONS: Required<Omit<StaticOptions, \"headers\">> = {\n index: \"index.html\",\n cacheControl: \"public, max-age=0\",\n dotFiles: \"ignore\"\n};\n\nexport async function serveStatic(root: string, event: RequestEvent, options: StaticOptions = {}): Promise<Response> {\n const requestPath = getStaticRequestPath(event);\n const resolvedOptions = {\n ...DEFAULT_STATIC_OPTIONS,\n ...options\n };\n\n const rootPath = await resolveStaticRoot(root);\n const normalizedPath = normalizeStaticRequestPath(requestPath, resolvedOptions.dotFiles);\n if (normalizedPath instanceof Response) {\n return normalizedPath;\n }\n\n const targetPath = normalizedPath.length > 0 ? normalizedPath.join(sep) : \"\";\n const candidatePath = resolve(rootPath, targetPath);\n\n if (!isPathInside(rootPath, candidatePath)) {\n return new Response(\"Forbidden\", { status: 403 });\n }\n\n const filePath = await resolveStaticFile(candidatePath, rootPath, resolvedOptions.index);\n if (filePath instanceof Response) {\n return filePath;\n }\n\n const fileStats = await stat(filePath);\n const headers = new Headers({\n \"content-length\": String(fileStats.size),\n \"content-type\": getMimeType(filePath),\n \"cache-control\": resolvedOptions.cacheControl,\n \"last-modified\": fileStats.mtime.toUTCString(),\n \"x-content-type-options\": \"nosniff\"\n });\n\n if (options.headers) {\n const extraHeaders = typeof options.headers === \"function\"\n ? options.headers(filePath, fileStats)\n : options.headers;\n new Headers(extraHeaders).forEach((value, key) => {\n headers.set(key, value);\n });\n }\n\n return new Response(Readable.toWeb(createReadStream(filePath)) as ReadableStream<Uint8Array>, {\n status: 200,\n headers\n });\n}\n\nasync function resolveStaticRoot(root: string): Promise<string> {\n return realpath(root);\n}\n\nfunction normalizeStaticRequestPath(requestPath: string, dotFiles: StaticOptions[\"dotFiles\"]): string[] | Response {\n if (requestPath.includes(\"\\0\")) {\n return new Response(\"Bad Request\", { status: 400 });\n }\n\n const segments = requestPath\n .replace(/\\\\/g, \"/\")\n .split(\"/\")\n .filter(Boolean);\n\n const normalizedSegments: string[] = [];\n\n for (const segment of segments) {\n let decoded: string;\n try {\n decoded = decodeURIComponent(segment);\n } catch {\n return new Response(\"Bad Request\", { status: 400 });\n }\n\n if (!decoded || decoded === \".\") {\n continue;\n }\n\n if (decoded === \"..\" || decoded.includes(\"/\") || decoded.includes(\"\\\\\") || decoded.includes(\"\\0\")) {\n return new Response(\"Forbidden\", { status: 403 });\n }\n\n if (decoded.startsWith(\".\")) {\n if (dotFiles === \"deny\") {\n return new Response(\"Forbidden\", { status: 403 });\n }\n if (dotFiles !== \"allow\") {\n return new Response(\"Not Found\", { status: 404 });\n }\n }\n\n normalizedSegments.push(decoded);\n }\n\n return normalizedSegments;\n}\n\nasync function resolveStaticFile(candidatePath: string, rootPath: string, indexFile: string): Promise<string | Response> {\n try {\n const candidateStats = await lstat(candidatePath);\n\n if (candidateStats.isDirectory()) {\n const indexPath = resolve(candidatePath, indexFile);\n return ensureResolvedFile(indexPath, rootPath);\n }\n\n return ensureResolvedFile(candidatePath, rootPath);\n } catch {\n return new Response(\"Not Found\", { status: 404 });\n }\n}\n\nasync function ensureResolvedFile(candidatePath: string, rootPath: string): Promise<string | Response> {\n try {\n const resolvedPath = await realpath(candidatePath);\n if (!isPathInside(rootPath, resolvedPath)) {\n return new Response(\"Forbidden\", { status: 403 });\n }\n\n const resolvedStats = await stat(resolvedPath);\n if (!resolvedStats.isFile()) {\n return new Response(\"Not Found\", { status: 404 });\n }\n\n return resolvedPath;\n } catch {\n return new Response(\"Not Found\", { status: 404 });\n }\n}\n\nfunction isPathInside(rootPath: string, targetPath: string): boolean {\n const relativePath = relative(rootPath, targetPath);\n return relativePath === \"\" || (!relativePath.startsWith(\"..\") && !isAbsolute(relativePath));\n}\n\nfunction getMimeType(filePath: string): string {\n return MIME_TYPES[extname(filePath).toLowerCase()] ?? \"application/octet-stream\";\n}\n\nfunction getStaticRequestPath(event: RequestEvent): string {\n if (typeof event.params.path === \"string\") {\n return event.params.path;\n }\n\n return event.url.pathname.replace(/^\\/+/, \"\");\n}\n\n\nexport default <Path extends string>(root: string, options: StaticOptions = {}): RouteHandler<Path> =>\n (event) => serveStatic(root, event, options);\n","import {MaybePromise} from \"../types/MaybePromise\";\nimport {RouteHandler} from \"../types\";\n\nexport type SSEEmitOptions = {\n event?: string;\n id?: string;\n retry?: number;\n comment?: string;\n};\n\nexport type SSEEmit = (data?: unknown, options?: SSEEmitOptions) => void;\n\nexport type SSEHandler<Path extends string> = (\n event: Parameters<RouteHandler<Path>>[0],\n emit: SSEEmit\n) => MaybePromise<void | (() => MaybePromise<void>)>;\n\nfunction createSSEChunk(data?: unknown, options: SSEEmitOptions = {}): string {\n const lines: string[] = [];\n\n if (options.comment) {\n for (const line of options.comment.split(/\\r?\\n/)) {\n lines.push(`: ${line}`);\n }\n }\n if (options.event) lines.push(`event: ${options.event}`);\n if (options.id) lines.push(`id: ${options.id}`);\n if (options.retry !== undefined) lines.push(`retry: ${options.retry}`);\n\n if (data !== undefined) {\n const content = typeof data === \"string\" ? data : JSON.stringify(data);\n for (const line of content.split(/\\r?\\n/)) {\n lines.push(`data: ${line}`);\n }\n }\n\n return `${lines.join('\\n')}\\n\\n`;\n}\n\nexport default <Path extends string>(emitter: SSEHandler<Path>, init: ResponseInit = {}): RouteHandler<Path> => {\n return (event) => {\n const encoder = new TextEncoder();\n let controllerRef: ReadableStreamDefaultController<Uint8Array> | null = null;\n let closed = false;\n let cleanup: void | (() => MaybePromise<void>);\n\n const closeStream = async () => {\n if (closed) return;\n closed = true;\n\n try {\n await cleanup?.();\n } finally {\n controllerRef?.close();\n }\n };\n\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n controllerRef = controller;\n\n const emit: SSEEmit = (data, options = {}) => {\n if (closed) return;\n controller.enqueue(encoder.encode(createSSEChunk(data, options)));\n };\n\n event.request.signal.addEventListener(\"abort\", () => {\n void closeStream();\n }, {once: true});\n\n try {\n cleanup = await emitter(event, emit);\n if (!event.request.signal.aborted && cleanup === undefined) {\n return;\n }\n if (event.request.signal.aborted) {\n await closeStream();\n }\n } catch (err) {\n if (!closed) controller.error(err);\n }\n },\n async cancel() {\n await closeStream();\n }\n });\n\n return new Response(stream, {\n ...init,\n headers: {\n 'content-type': 'text/event-stream',\n 'cache-control': 'no-cache',\n 'connection': 'keep-alive',\n ...init.headers\n }\n });\n }\n}\n","import type {MaybePromise} from \"./types/MaybePromise\";\n\nexport * from './app'\nexport * from './utils'\nexport * from './middlewares'\nexport * from './types'\nexport * from './helpers/static'\n\nexport const json = async (data: MaybePromise<any>, init?: ResponseInit) => {\n const content = JSON.stringify(await data);\n return new Response(content, {\n ...init,\n headers: {\n 'content-type': 'application/json',\n 'content-length': Buffer.byteLength(content).toString(),\n ...init?.headers\n }\n })\n}\n\nexport function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never {\n throw new Response(null, {\n status,\n headers: {\n location: location.toString()\n }\n })\n}\n\nexport function error(status: number, body: App.Error | string): never {\n throw new Response(JSON.stringify(typeof body === \"string\" ? {message: body} : body), {\n status,\n headers: {\n 'content-type': 'application/json'\n }\n })\n}\n\nexport const text = async (body: MaybePromise<string>, init?: ResponseInit) => {\n const content = await body\n return new Response(content, {\n ...init,\n headers: {\n 'content-type': 'text/plain',\n 'content-length': Buffer.byteLength(content).toString(),\n ...init?.headers\n }\n })\n}\n\nexport const html = async (html: MaybePromise<string>, init?: ResponseInit) => {\n const content = await html\n return new Response(content, {\n ...init,\n headers: {\n 'content-type': 'text/html',\n 'content-length': Buffer.byteLength(content).toString(),\n ...init?.headers\n }\n })\n}\n\nexport {default as dir} from \"./helpers/static\"\n\nexport {default as sse} from \"./helpers/sse\"\n"],"names":["isHttpError","err","isResponse","isRedirect","MemoryStore","opts","key","now","record","reset","fixedWindowLimit","options","windowMs","max","event","message","statusCode","headers","onRateLimit","store","next","rateLimitKey","current","retryAfter","responseInit","header","body","rateLimitHeaders","originalSetHeaders","newHeaders","DEFAULT_METHODS","SIMPLE_HEADERS","DEFAULT_ALLOWED_HEADERS","isOriginAllowed","origin","option","o","getAllowedOrigin","requestOrigin","policy","methods","allowedHeaders","exposedHeaders","credentials","maxAge","onResponse","varyHeader","methodsHeader","allowedHeadersHeader","headersToSet","request","isPreflight","allowedOrigin","preflightResponse","value","response","modifiedResponse","finalResponse","override","RequestMethods","PathRegexCache","path","Router","handler","middlewares","method","wrapped","result","error","arg1","arg2","prefix","router","finalMiddlewares","normalizedPrefix","regex","paramNames","isCatchAll","priority","mw","handlers","path_or_prefix","r","route","pathname","nested","a","b","match","matched","remaining","nestedEvent","websocket","prefixParams","effectiveMiddlewares","params","name","i","enhancedEvent","allMiddlewares","nestedResponse","mws","chain","run","index","currentResponse","nextResponse","cached","segments","acc","segment","regexString","part","paramName","matchedPath","sorted","allowed","getRouteForHead","finalHandler","allowHeader","Action","url","code","data","location","Cookies","setCookieHeader","parse","v","serialize","PayloadTooLargeError","WebServer","config","WebSocketServer","requestListener","req","res","createHttpsServer","createHttpServer","args","socket","head","canHandle","ws","handled","WebSocket","callback","setHeaders","setCookies","serialized","isWebSocket","init","Readable","limit","total","limiter","Transform","chunk","_encoding","protocol","TLSSocket","authority","trustedAuthority","address","hostHeader","allowedHosts","matcher","entry","normalized","joined","contentLength","parsed","reader","writer","Writable","done","allowedOrigins","utils","cookies","locals","platform","setHeadersState","normalizedName","MIME_TYPES","DEFAULT_STATIC_OPTIONS","serveStatic","root","requestPath","getStaticRequestPath","resolvedOptions","rootPath","resolveStaticRoot","normalizedPath","normalizeStaticRequestPath","targetPath","sep","candidatePath","resolve","isPathInside","filePath","resolveStaticFile","fileStats","stat","getMimeType","extraHeaders","createReadStream","realpath","dotFiles","normalizedSegments","decoded","indexFile","lstat","indexPath","ensureResolvedFile","resolvedPath","relativePath","relative","isAbsolute","extname","_static","createSSEChunk","lines","line","content","sse","emitter","encoder","controllerRef","closed","cleanup","closeStream","stream","controller","emit","json","redirect","status","text","html"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { MaybePromise } from './types/MaybePromise';
|
|
2
|
-
import { StaticOptions } from './static';
|
|
3
|
-
import { RouteHandler } from './types';
|
|
4
2
|
export * from './app';
|
|
5
3
|
export * from './utils';
|
|
6
4
|
export * from './middlewares';
|
|
7
5
|
export * from './types';
|
|
8
|
-
export * from './static';
|
|
6
|
+
export * from './helpers/static';
|
|
9
7
|
export declare const json: (data: MaybePromise<any>, init?: ResponseInit) => Promise<Response>;
|
|
10
8
|
export declare function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never;
|
|
11
9
|
export declare function error(status: number, body: App.Error | string): never;
|
|
12
10
|
export declare const text: (body: MaybePromise<string>, init?: ResponseInit) => Promise<Response>;
|
|
13
11
|
export declare const html: (html: MaybePromise<string>, init?: ResponseInit) => Promise<Response>;
|
|
14
|
-
export
|
|
12
|
+
export { default as dir } from './helpers/static';
|
|
13
|
+
export { default as sse } from './helpers/sse';
|