{"version":3,"sources":["/home/pitok/Projects/framework-bun/packages/buntok-core/dist/chunk-QUHLEKYY.cjs","../src/buntok.ts","../src/router/index.ts"],"names":["EMPTY_PARAMS","resolve"],"mappings":"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","file":"/home/pitok/Projects/framework-bun/packages/buntok-core/dist/chunk-QUHLEKYY.cjs","sourcesContent":[null,"import { join, sep, dirname, resolve } from \"node:path\";\nimport { mkdirSync, writeFileSync, existsSync } from \"node:fs\";\nimport type { Server, ServerWebSocket, BunFile } from \"bun\";\nimport type { z } from \"zod\";\nimport { Container } from \"./container\";\nimport { Context } from \"./context\";\nimport { getControllerMeta, type RouteMeta } from \"./decorators\";\nimport { HttpError } from \"./helpers/async-handler\";\nimport { BuntokFile } from \"./helpers/file\";\nimport { toResponse } from \"./helpers/response\";\nimport {\n\tanalyzeHandler,\n\textractConstResponseOp,\n\ttype ConstResponseOp,\n} from \"./aot/sucrose\";\nimport { logger } from \"./logger\";\nimport { getModel, registerModel } from \"./models\";\nimport { Router } from \"./router\";\nimport { VERSION } from \"./version\";\nimport type { Plugin } from \"./plugin\";\nimport type { CorsOptions } from \"./middlewares/cors\";\nimport { applyCorsHeaders, cors } from \"./middlewares/cors\";\nimport { getClientIP, type TrustedProxyOptions } from \"./helpers/network\";\n\nexport interface WSData<DI = Record<string, unknown>> {\n\tctx: Context<DI>;\n\thandler: WSHandler<DI>;\n}\n\nexport interface WSOptions {\n\t/** Per-message deflate - Bun native, default false */\n\tperMessageDeflate?: boolean | object;\n\t/** Max payload length bytes - default 16MB */\n\tmaxPayloadLength?: number;\n\t/** Idle timeout seconds before close - default 120, 30 for heartbeat */\n\tidleTimeout?: number;\n\t/** Backpressure highWaterMark */\n\tmaxBackpressure?: number;\n\t/** Publish to self? default false */\n\tpublishToSelf?: boolean;\n}\n\nexport interface WSHandler<DI = Record<string, unknown>> {\n\topen?: (ws: ServerWebSocket<WSData<DI>>) => void;\n\tmessage?: (ws: ServerWebSocket<WSData<DI>>, message: string | Buffer) => void;\n\tclose?: (\n\t\tws: ServerWebSocket<WSData<DI>>,\n\t\tcode: number,\n\t\treason: string,\n\t) => void;\n\tdrain?: (ws: ServerWebSocket<WSData<DI>>) => void;\n\tpong?: (ws: ServerWebSocket<WSData<DI>>) => void;\n\t/**\n\t * Optional authentication handler.\n\t * Called on connection open. Return null to reject the connection.\n\t * The returned data is stored in `ws.data.auth`.\n\t */\n\tauthenticate?: (ws: ServerWebSocket<WSData<DI>>) => Promise<unknown | null>;\n}\n\nexport type ExtractParams<Path extends string> =\n\tPath extends `${infer _Start}:${infer Param}/${infer Rest}`\n\t? { [K in Param]: string } & ExtractParams<`/${Rest}`>\n\t: Path extends `${infer _Start}:${infer Param}`\n\t? { [K in Param]: string }\n\t: Path extends `${infer _Start}*${infer Catchall}`\n\t? { [K in Catchall]: string } & { \"*\": string }\n\t: Record<string, never>;\n\n/**\n * @deprecated Use `ZodCtx<{ body: typeof schema; query: typeof schema }>` instead.\n * `RouteContext` has 5 generic parameters that are hard to remember.\n * `ZodCtx` only needs one and infers types automatically from your Zod schemas.\n */\nexport type RouteContext<\n\tPath extends string = string,\n\tBodyType = unknown,\n\tDI = Record<string, unknown>,\n\tQueryType = unknown,\n\tParamsType = ExtractParams<Path>,\n> = {\n\tbody(): Promise<BodyType>;\n\tvalid<T extends \"body\" | \"query\" | \"params\">(\n\t\ttarget: T,\n\t): T extends \"body\"\n\t\t? BodyType\n\t\t: T extends \"query\"\n\t\t? QueryType\n\t\t: T extends \"params\"\n\t\t? ParamsType\n\t\t: unknown;\n} & Context<DI, ParamsType>;\n\n/**\n * Helper to infer Context types from Zod schemas automatically.\n *\n * Just pass your Zod schemas - no need to remember generic parameter order.\n *\n * @example\n * const paginationSchema = z.object({ page: z.coerce.number(), limit: z.coerce.number() });\n *\n * @Controller(\"/users\")\n * export class UserController {\n *   @Get(\"/\")\n *   @Use(zValidator(\"query\", paginationSchema))\n *   async getAll(ctx: ZodCtx<{ query: typeof paginationSchema }>) {\n *     const { page, limit } = ctx.valid(\"query\"); // Fully typed!\n *   }\n * }\n */\nexport type ZodCtx<\n\t// biome-ignore lint/suspicious/noExplicitAny: Requires accessing Zod types\n\tT extends { query?: any; body?: any; params?: any },\n> = {\n\tbody(): Promise<T[\"body\"] extends { _type: infer U } ? U : T[\"body\"]>;\n\tvalid<Target extends \"body\" | \"query\" | \"params\">(\n\t\ttarget: Target,\n\t): Target extends \"body\"\n\t\t? T[\"body\"] extends { _type: infer U }\n\t\t? U\n\t\t: T[\"body\"]\n\t\t: Target extends \"query\"\n\t\t? T[\"query\"] extends { _type: infer U }\n\t\t? U\n\t\t: T[\"query\"]\n\t\t: Target extends \"params\"\n\t\t? T[\"params\"] extends { _type: infer U }\n\t\t? U\n\t\t: T[\"params\"]\n\t\t: unknown;\n} & Context<\n\tRecord<string, unknown>,\n\tT[\"params\"] extends { _type: infer U }\n\t? U\n\t: T[\"params\"] extends Record<string, string>\n\t? T[\"params\"]\n\t: Record<string, string>\n>;\n\nexport type HandlerReturn =\n\t| Response\n\t| BuntokFile\n\t| Blob\n\t| ArrayBuffer\n\t| Uint8Array\n\t| string\n\t| number\n\t| boolean\n\t| bigint\n\t| Record<string, unknown>\n\t| unknown[]\n\t| null\n\t| undefined\n\t| void\n\t| Promise<\n\t\t| Response\n\t\t| BuntokFile\n\t\t| Blob\n\t\t| ArrayBuffer\n\t\t| Uint8Array\n\t\t| string\n\t\t| number\n\t\t| boolean\n\t\t| bigint\n\t\t| Record<string, unknown>\n\t\t| unknown[]\n\t\t| null\n\t\t| undefined\n\t\t| void\n\t>;\n\nexport type Handler<\n\tDI = Record<string, unknown>,\n\tPath extends string = string,\n> = (ctx: Context<DI, ExtractParams<Path>>) => HandlerReturn;\nexport type Middleware<\n\tDI = Record<string, unknown>,\n\tPath extends string = string,\n> = (\n\tctx: Context<DI, ExtractParams<Path>>,\n\tnext: () => Promise<Response> | Response,\n) => HandlerReturn;\nexport type ErrorHandler<DI = Record<string, unknown>> = (\n\terr: Error,\n\t// biome-ignore lint/suspicious/noExplicitAny: generic\n\tctx: Context<DI, any>,\n) => HandlerReturn;\nexport type NotFoundHandler<DI = Record<string, unknown>> = (\n\t// biome-ignore lint/suspicious/noExplicitAny: generic\n\tctx: Context<DI, any>,\n) => HandlerReturn;\n\nexport type LifecycleHookResult =\n\t| Response\n\t| void\n\t| Promise<Response | void>;\nexport type RequestHook<DI = Record<string, unknown>> = (\n\t// biome-ignore lint/suspicious/noExplicitAny: generic\n\tctx: Context<DI, any>,\n) => LifecycleHookResult;\nexport type BeforeHandleHook<DI = Record<string, unknown>> = (\n\t// biome-ignore lint/suspicious/noExplicitAny: generic\n\tctx: Context<DI, any>,\n) => LifecycleHookResult;\nexport type AfterHandleHook<DI = Record<string, unknown>> = (\n\t// biome-ignore lint/suspicious/noExplicitAny: generic\n\tctx: Context<DI, any>,\n\tresponse: Response,\n) => Response | void | Promise<Response | void>;\nexport type DeriveHook<DI = Record<string, unknown>> = (\n\t// biome-ignore lint/suspicious/noExplicitAny: generic\n\tctx: Context<DI, any>,\n) => Record<string, unknown> | Promise<Record<string, unknown>>;\nexport type AppHook = () => void | Promise<void>;\n\nexport interface EnvValidationOptions {\n\t/**\n\t * Custom error handler called when env validation fails.\n\t * If provided, the default error printing and process.exit(1) are skipped.\n\t * Use this to send alerts to monitoring services or custom logging before exiting.\n\t *\n\t * @example\n\t * app.validateEnv(schema, {\n\t *   onError: (errors) => {\n\t *     // Send to monitoring service\n\t *     await sentry.captureException(new Error(\"Env validation failed\"));\n\t *     // Log to external service\n\t *     await logger.fatal(\"Missing env vars\", { errors });\n\t *     // Then exit manually\n\t *     process.exit(1);\n\t *   }\n\t * });\n\t */\n\tonError?: (errors: { field: string; message: string }[]) => void | never;\n}\n\nexport interface StaticOptions {\n\t/** Cache max-age in seconds (default: 3600) */\n\tmaxAge?: number;\n\t/** Override the full Cache-Control header value */\n\tcacheControl?: string;\n\t/** Enable ETag generation and conditional requests (default: true) */\n\tetag?: boolean;\n\t/**\n\t * Serve the directory through Bun's native `{ dir }` route - zero JS per\n\t * request (kernel-clamped path traversal, native mime/etag/range/index.html).\n\t * Falls back to the JS handler when the native gates are off (request\n\t * logging on, X-Powered-By enabled, global middleware). When active, Bun\n\t * controls the response: `maxAge`/`cacheControl`/`etag` options are not\n\t * applied and missing files return an empty-body 404 instead of the JSON\n\t * error body.\n\t */\n\tnative?: boolean;\n}\n\n/** Bun native `{ dir }` route value for `app.static({ native: true })`. */\ninterface DirRouteOptions {\n\tdir: string;\n\tstatCache?: boolean;\n}\n\n/** Values that can be handed to Bun.serve `routes` directly (baked at boot). */\ntype NativeRouteValue = Response | BunFile | DirRouteOptions;\n\n/**\n * Native Bun.serve route handler for `:param` paths - Bun's C++ router matches\n * the pattern, the closure runs the same JS as the fallback dispatch (params\n * re-extracted raw from the pathname for byte parity with the FFI trie).\n */\ntype NativeDynamicHandler = (request: Request) => Response | Promise<Response>;\n\n/** Everything collectNativeStaticRoutes can put into Bun.serve `routes`. */\ntype NativeRouteEntry = NativeRouteValue | NativeDynamicHandler;\n\nfunction isDirRouteValue(\n\tvalue: unknown,\n): value is DirRouteOptions {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t!(value instanceof Response) &&\n\t\t!(value instanceof Blob) &&\n\t\t\"dir\" in value &&\n\t\ttypeof (value as DirRouteOptions).dir === \"string\"\n\t);\n}\n\nexport interface ApiDocsOptions {\n\t/** URL path for the docs UI (default: \"/docs\") */\n\tpath?: string;\n\t/** API title displayed in the docs (default: \"API Documentation\") */\n\ttitle?: string;\n\t/** API version (default: \"1.0.0\") */\n\tversion?: string;\n\t/** API description */\n\tdescription?: string;\n\t/** Hide docs when NODE_ENV is \"production\" (default: false) */\n\tsafeOnProduction?: boolean;\n}\n\nexport interface RouteDebugInfo {\n\tmethod: string;\n\tpath: string;\n\tmiddlewares: string[];\n\thandler: string;\n\tsource: \"route\" | \"controller\" | \"group\";\n\tcontroller?: string;\n\tgroup?: string;\n}\n\nexport interface BuntokOptions {\n\t/** Register SIGINT and SIGTERM handlers when the app starts listening. */\n\thandleSignals?: boolean;\n\t/** Maximum time allowed for graceful shutdown. */\n\tshutdownTimeout?: number;\n}\n\nexport interface DisposableResource {\n\tname?: string;\n\tclose?: () => void | Promise<void>;\n\tdispose?: () => void | Promise<void>;\n}\n\n/**\n * Wrap a controller handler with the zero-cost response decorators\n * (@HttpCode / @SetHeader / @Redirect). Applied at boot time - no\n * per-request alloc beyond the wrapper closure. Returns the handler\n * unchanged when none of those decorators are present.\n *\n * Shared by `Buntok.registerController()` and `RouterGroup.registerController()`\n * so decorator behavior is identical on both registration paths.\n */\nfunction applyRouteResponseDecorators<DI extends Record<string, unknown>>(\n\thandler: Handler<DI>,\n\troute: RouteMeta,\n): Handler<DI> {\n\tconst hasStatus = route.statusCode !== undefined;\n\tconst hasHeaders = route.headers && route.headers.length > 0;\n\tconst hasRedirect = !!route.redirect;\n\tif (!hasStatus && !hasHeaders && !hasRedirect) return handler;\n\n\tconst original = handler;\n\tconst routeMeta = route;\n\tconst apply = (res: Response): Response => {\n\t\tlet r: Response = res;\n\t\tif (hasStatus && r.status === 200) {\n\t\t\t// Override status only if default 200 (preserve explicit ctx.status etc.)\n\t\t\tr = new Response(r.body, { status: routeMeta.statusCode!, headers: r.headers });\n\t\t} else if (hasStatus && r.status === 204 && routeMeta.statusCode !== 204) {\n\t\t\t// For void returns that became 204, respect HttpCode\n\t\t\tr = new Response(r.body, { status: routeMeta.statusCode!, headers: r.headers });\n\t\t}\n\t\tif (hasHeaders) {\n\t\t\tfor (const [k, v] of routeMeta.headers!) {\n\t\t\t\tr.headers.set(k, v);\n\t\t\t}\n\t\t}\n\t\treturn r;\n\t};\n\t// biome-ignore lint/suspicious/noExplicitAny: wrapper must accept any Context shape\n\tconst wrapped = ((ctx: any) => {\n\t\t// Redirect - static or dynamic override (Nest behavior)\n\t\tif (hasRedirect) {\n\t\t\tconst result: any = original(ctx);\n\t\t\t// If handler returns promise, handle async\n\t\t\tif (result instanceof Promise) {\n\t\t\t\treturn result.then((val: any) => {\n\t\t\t\t\tif (val instanceof Response) {\n\t\t\t\t\t\treturn new Response(val.body, {\n\t\t\t\t\t\t\tstatus: routeMeta.redirect!.statusCode,\n\t\t\t\t\t\t\theaders: { Location: routeMeta.redirect!.url, ...Object.fromEntries(val.headers) },\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (val && typeof val === \"object\" && \"url\" in val) {\n\t\t\t\t\t\tconst url = (val as any).url as string;\n\t\t\t\t\t\tconst sc = (val as any).statusCode ?? routeMeta.redirect!.statusCode;\n\t\t\t\t\t\treturn new Response(null, { status: sc, headers: { Location: url } });\n\t\t\t\t\t}\n\t\t\t\t\t// Also allow string return as url override\n\t\t\t\t\tif (typeof val === \"string\" && val.startsWith(\"/\")) {\n\t\t\t\t\t\treturn new Response(null, { status: routeMeta.redirect!.statusCode, headers: { Location: val } });\n\t\t\t\t\t}\n\t\t\t\t\t// Static redirect\n\t\t\t\t\treturn new Response(null, {\n\t\t\t\t\t\tstatus: routeMeta.redirect!.statusCode,\n\t\t\t\t\t\theaders: { Location: routeMeta.redirect!.url },\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (result instanceof Response) {\n\t\t\t\t// Handler returned a Response - apply redirect status + Location header\n\t\t\t\treturn new Response(result.body, {\n\t\t\t\t\tstatus: routeMeta.redirect!.statusCode,\n\t\t\t\t\theaders: { Location: routeMeta.redirect!.url, ...Object.fromEntries(result.headers) },\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (result && typeof result === \"object\" && \"url\" in result) {\n\t\t\t\tconst url = (result as any).url as string;\n\t\t\t\tconst sc = (result as any).statusCode ?? routeMeta.redirect!.statusCode;\n\t\t\t\treturn new Response(null, { status: sc, headers: { Location: url } });\n\t\t\t}\n\t\t\tif (typeof result === \"string\" && result.startsWith(\"/\")) {\n\t\t\t\treturn new Response(null, { status: routeMeta.redirect!.statusCode, headers: { Location: result } });\n\t\t\t}\n\t\t\treturn new Response(null, {\n\t\t\t\tstatus: routeMeta.redirect!.statusCode,\n\t\t\t\theaders: { Location: routeMeta.redirect!.url },\n\t\t\t});\n\t\t}\n\t\tconst raw: any = original(ctx);\n\t\tif (raw instanceof Promise) {\n\t\t\treturn raw.then((v: any) =>\n\t\t\t\ttypeof v === \"string\"\n\t\t\t\t\t? apply(new Response(v))\n\t\t\t\t\t: apply(v instanceof Response ? v : toResponse(v, ctx?.request)),\n\t\t\t);\n\t\t}\n\t\treturn typeof raw === \"string\"\n\t\t\t? apply(new Response(raw))\n\t\t\t: apply(raw instanceof Response ? raw : toResponse(raw, ctx?.request));\n\t}) as Handler<DI>;\n\t// Preserve sucrose target from original handler for AST analysis\n\t(wrapped as any)._sucroseTarget = (original as any)._sucroseTarget ?? original;\n\t// Mark: the wrapper adds status/headers/redirect - it must be executed,\n\t// never promote to native even when its _sucroseTarget is a constant literal.\n\t(wrapped as any)._buntokResponseDecorated = true;\n\treturn wrapped;\n}\n\nexport class Buntok<DI extends Record<string, unknown> = Record<string, unknown>> {\n\tprivate router: Router;\n\tprivate middlewares: Middleware<DI>[] = [];\n\tprivate requestHooks: RequestHook<DI>[] = [];\n\tprivate deriveHooks: DeriveHook<DI>[] = [];\n\tprivate beforeHandleHooks: BeforeHandleHook<DI>[] = [];\n\tprivate afterHandleHooks: AfterHandleHook<DI>[] = [];\n\tprivate startHooks: AppHook[] = [];\n\tprivate stopHooks: AppHook[] = [];\n\tprivate compiledGlobalPipeline?: (\n\t\tctx: Context<DI>,\n\t\tfinalHandler: Handler<DI>,\n\t) => HandlerReturn;\n\tprivate isListening: boolean = false;\n\tpublic di = {} as DI;\n\tprivate wsRoutes: Map<string, WSHandler<DI>> = new Map();\n\tprivate wsOpts: WSOptions = {};\n\tprivate poweredByHeaderEnabled: boolean = process.env.NODE_ENV !== \"production\";\n\tprivate _reusePort: boolean = false;\n\tprivate _skipLogResponse: boolean = false;\n\t// Cache sucrose analysis per handler to avoid AST analysis per request\n\tprivate _handlerNeedsFullContext = new WeakMap<Function, boolean>();\n\t// Track routes that have per-route middlewares (need full Context)\n\tprivate _routesWithMiddleware = new Set<string>();\n\t// Precomputed client IP resolver - avoid closure alloc per request\n\tprivate _clientIPResolver: (request: Request) => string = (req) => getClientIP(req);\n\t// Cache full needsFullContext per handler for AOT codegen (includes ctx.json detection)\n\tprivate _handlerFullContextCache = new WeakMap<Function, { needsFullContext: boolean; needsParams: boolean; needsSetHeaders: boolean }>();\n\t// Static handler values (string/Response/ConstResponseOp) per `METHOD:path`,\n\t// captured at registration for listen-time promotion to native Bun.serve routes.\n\tprivate _staticRouteValues = new Map<\n\t\tstring,\n\t\tstring | NativeRouteValue | ConstResponseOp\n\t>();\n\t// Map compiled pipeline → original handler for AOT sucrose analysis\n\tprivate _pipelineToHandler = new WeakMap<Function, Function>();\n\tpublic _apiDocsConfig: ApiDocsOptions | null = null;\n\t// biome-ignore lint/suspicious/noExplicitAny: Required for internal OpenAPI registry\n\tpublic openApiDocs: any[] = [];\n\tprivate container: Container | null = null;\n\tprivate installedPlugins = new Set<string>();\n\tprivate pluginDisposers = new Map<string, (app: Buntok<DI>) => void | Promise<void>>();\n\tprivate trustedProxy?: TrustedProxyOptions;\n\tprivate readonly handleSignals: boolean;\n\tprivate readonly shutdownTimeout: number;\n\tprivate shutdownPromise?: Promise<void>;\n\tprivate signalHandlers?: { signal: \"SIGTERM\" | \"SIGINT\"; handler: () => void }[];\n\tprivate resources = new Set<DisposableResource>();\n\tprivate corsConfig: CorsOptions | null = null;\n\t// biome-ignore lint/suspicious/noExplicitAny: OpenAPI document is dynamically generated\n\tprivate _swaggerDocument: any | null = null;\n\tpublic routeDebugInfo: RouteDebugInfo[] = [];\n\n\t/**\n\t * The underlying Bun Server instance. Only available after app.listen() is called.\n\t * Can be used for server.publish() to broadcast WebSocket messages.\n\t */\n\tpublic server?: Server<WSData<DI>>;\n\n\tprivate customErrorHandler: ErrorHandler<DI> = (err, ctx) => {\n\t\tlogger.error(\"Unhandled Exception\", {\n\t\t\terror: err.message,\n\t\t\tstack: err.stack,\n\t\t});\n\t\tconst status = err instanceof HttpError ? err.status : 500;\n\t\tconst errorName =\n\t\t\tstatus === 400\n\t\t\t\t? \"Bad Request\"\n\t\t\t\t: status === 401\n\t\t\t\t\t? \"Unauthorized\"\n\t\t\t\t\t: status === 403\n\t\t\t\t\t\t? \"Forbidden\"\n\t\t\t\t\t\t: status === 404\n\t\t\t\t\t\t\t? \"Not Found\"\n\t\t\t\t\t\t\t: status === 405\n\t\t\t\t\t\t\t\t? \"Method Not Allowed\"\n\t\t\t\t\t\t\t\t: status === 409\n\t\t\t\t\t\t\t\t\t? \"Conflict\"\n\t\t\t\t\t\t\t\t\t: status === 422\n\t\t\t\t\t\t\t\t\t\t? \"Unprocessable Entity\"\n\t\t\t\t\t\t\t\t\t\t: status === 429\n\t\t\t\t\t\t\t\t\t\t\t? \"Too Many Requests\"\n\t\t\t\t\t\t\t\t\t\t\t: status === 503\n\t\t\t\t\t\t\t\t\t\t\t\t? \"Service Unavailable\"\n\t\t\t\t\t\t\t\t\t\t\t\t: \"Internal Server Error\";\n\t\treturn ctx.json(\n\t\t\t{\n\t\t\t\tsuccess: false,\n\t\t\t\terror: errorName,\n\t\t\t\t// Buntok-thrown 4xx HttpErrors keep their message (also in\n\t\t\t\t// production); 5xx and unexpected errors are masked in production.\n\t\t\t\tmessage:\n\t\t\t\t\terr instanceof HttpError && err.status < 500\n\t\t\t\t\t\t? err.message\n\t\t\t\t\t\t: process.env.NODE_ENV === \"production\"\n\t\t\t\t\t\t\t? \"An unexpected error occurred\"\n\t\t\t\t\t\t\t: err.message,\n\t\t\t},\n\t\t\tstatus,\n\t\t);\n\t};\n\n\tprivate customNotFoundHandler: NotFoundHandler<DI> = (ctx) => {\n\t\treturn ctx.json(\n\t\t\t{\n\t\t\t\tsuccess: false,\n\t\t\t\terror: \"Not Found\",\n\t\t\t\tpath: new URL(ctx.request.url).pathname,\n\t\t\t},\n\t\t\t404,\n\t\t);\n\t};\n\n\tprivate iconPath: string = \"./public/favicon.ico\";\n\n\tconstructor(options: BuntokOptions = {}) {\n\t\tthis.handleSignals = options.handleSignals ?? true;\n\t\tthis.shutdownTimeout = options.shutdownTimeout ?? 30_000;\n\t\tthis.router = new Router();\n\t\t// Favicon served as static file from docs templates directory\n\t}\n\n\tpublic use(middleware: Middleware<DI>): this {\n\t\tthis.middlewares.push(middleware);\n\t\tthis._invalidateAOT(true);\n\t\treturn this;\n\t}\n\n\tprivate get hasPipelineHooks(): boolean {\n\t\treturn (\n\t\t\tthis.middlewares.length > 0 ||\n\t\t\tthis.requestHooks.length > 0 ||\n\t\t\tthis.deriveHooks.length > 0 ||\n\t\t\tthis.beforeHandleHooks.length > 0 ||\n\t\t\tthis.afterHandleHooks.length > 0\n\t\t);\n\t}\n\n\tpublic onRequest(hook: RequestHook<DI>): this {\n\t\tthis.requestHooks.push(hook);\n\t\tthis._invalidateAOT(true);\n\t\treturn this;\n\t}\n\n\tpublic onBeforeHandle(hook: BeforeHandleHook<DI>): this {\n\t\tthis.beforeHandleHooks.push(hook);\n\t\tthis._invalidateAOT(true);\n\t\treturn this;\n\t}\n\n\tpublic onAfterHandle(hook: AfterHandleHook<DI>): this {\n\t\tthis.afterHandleHooks.push(hook);\n\t\tthis._invalidateAOT(true);\n\t\treturn this;\n\t}\n\n\tpublic derive(hook: DeriveHook<DI>): this {\n\t\tthis.deriveHooks.push(hook);\n\t\tthis._invalidateAOT(true);\n\t\treturn this;\n\t}\n\n\tpublic onStart(hook: AppHook): this {\n\t\tthis.startHooks.push(hook);\n\t\treturn this;\n\t}\n\n\tpublic onStop(hook: AppHook): this {\n\t\tthis.stopHooks.push(hook);\n\t\treturn this;\n\t}\n\n\tpublic model(name: string, schema: unknown): this;\n\tpublic model(models: Record<string, unknown>): this;\n\tpublic model(\n\t\tnameOrModels: string | Record<string, unknown>,\n\t\tschema?: unknown,\n\t): this {\n\t\tif (typeof nameOrModels === \"string\") {\n\t\t\tregisterModel(nameOrModels, schema);\n\t\t\treturn this;\n\t\t}\n\t\tfor (const [name, model] of Object.entries(nameOrModels)) {\n\t\t\tregisterModel(name, model);\n\t\t}\n\t\treturn this;\n\t}\n\n\tpublic getModel<T = unknown>(name: string): T | undefined {\n\t\treturn getModel(name) as T | undefined;\n\t}\n\n\tpublic decorate<T extends Record<string, unknown>>(values: T): Buntok<DI & T>;\n\tpublic decorate<K extends string, V>(name: K, value: V): Buntok<DI & Record<K, V>>;\n\tpublic decorate(\n\t\tnameOrValues: string | Record<string, unknown>,\n\t\tvalue?: unknown,\n\t): Buntok<DI & Record<string, unknown>> {\n\t\tif (typeof nameOrValues === \"string\") {\n\t\t\t(this.di as Record<string, unknown>)[nameOrValues] = value;\n\t\t} else {\n\t\t\tObject.assign(this.di, nameOrValues);\n\t\t}\n\t\treturn this as unknown as Buntok<DI & Record<string, unknown>>;\n\t}\n\n\t/** Configure which proxy peers may supply forwarding headers. */\n\tpublic setTrustedProxy(options?: TrustedProxyOptions): this {\n\t\tthis.trustedProxy = options;\n\t\tthis._clientIPResolver = options\n\t\t\t? (req) => getClientIP(req, options)\n\t\t\t: (req) => getClientIP(req);\n\t\tthis._invalidateAOT();\n\t\treturn this;\n\t}\n\n\t/** Register an owned resource for graceful application shutdown. */\n\tpublic registerResource(resource: DisposableResource): this {\n\t\tthis.resources.add(resource);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Configure CORS for the application.\n\t * Unlike `app.use(cors(...))`, this method also ensures CORS headers\n\t * are applied to error responses (4xx, 5xx) generated by the framework.\n\t */\n\tpublic cors(options: CorsOptions = {}): this {\n\t\tthis.corsConfig = options;\n\t\tthis.middlewares.push(cors(options));\n\t\treturn this;\n\t}\n\n\t/**\n\t * Install a plugin. Plugins are deduplicated by name -\n\t * installing the same plugin twice is a no-op.\n\t */\n\tpublic async plugin(plugin: Plugin<DI>): Promise<this> {\n\t\tif (this.installedPlugins.has(plugin.name)) return this;\n\t\tthis.installedPlugins.add(plugin.name);\n\t\ttry {\n\t\t\tawait plugin.install(this);\n\t\t\tif (plugin.dispose) this.pluginDisposers.set(plugin.name, plugin.dispose);\n\t\t} catch (error) {\n\t\t\tthis.installedPlugins.delete(plugin.name);\n\t\t\tthrow error;\n\t\t}\n\t\treturn this;\n\t}\n\n\tpublic set<K extends keyof DI>(key: K, value: DI[K]): this {\n\t\tthis.di[key] = value;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Attach an IoC Container to the app. When set, `registerController()`\n\t * will resolve controllers via `container.resolve()` (use `FactoryProvider` for ctor deps).\n\t */\n\tpublic setContainer(container: Container): this {\n\t\tthis.container = container;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Get the attached IoC Container, or create an empty one if none was set.\n\t */\n\tpublic getContainer(): Container {\n\t\tif (!this.container) {\n\t\t\tthis.container = new Container();\n\t\t}\n\t\treturn this.container;\n\t}\n\n\tpublic group(prefix: string): RouterGroup<DI> {\n\t\treturn new RouterGroup<DI>(prefix, this);\n\t}\n\n\t/**\n\t * Register a WebSocket endpoint at an exact path (no params/wildcards).\n\t * Backed directly by Bun's native WebSocket server - no polyfill or\n\t * extra abstraction layer between your handler and `Bun.serve`.\n\t *\n\t * ```ts\n\t * app.ws(\"/chat\", {\n\t *   open: (ws) => ws.subscribe(\"room\"),\n\t *   message: (ws, msg) => ws.publish(\"room\", msg),\n\t * });\n\t * ```\n\t */\n\tpublic ws(path: string, handler: WSHandler<DI>): this {\n\t\tthis.wsRoutes.set(path, handler);\n\t\treturn this;\n\t}\n\n\t/** Configure Bun WebSocket options - Bun-only, zero-deps */\n\tpublic wsOptions(opts: WSOptions): this {\n\t\tthis.wsOpts = { ...this.wsOpts, ...opts };\n\t\treturn this;\n\t}\n\n\t/**\n\t * Type-safe Environment Variables Validator (static).\n\t * Validates `process.env` against a Zod schema object and returns the typed result.\n\t * If validation fails, it prints a beautiful error to the console and exits the process (stops booting).\n\t *\n\t * @example\n\t * // Static - no Buntok instance needed (ideal for src/env.ts)\n\t * const env = Buntok.validateEnv({\n\t *   DATABASE_URL: z.string().url(),\n\t *   PORT: z.coerce.number().default(3000),\n\t * });\n\t *\n\t * @example\n\t * // Custom error handler - send to monitoring before exiting\n\t * const env = Buntok.validateEnv({\n\t *   DATABASE_URL: z.string().url(),\n\t * }, {\n\t *   onError: (errors) => {\n\t *     // Send to monitoring service\n\t *     console.error(\"ENV ERROR:\", errors);\n\t *     // Exit manually after alerting\n\t *     process.exit(1);\n\t *   }\n\t * });\n\t */\n\tstatic validateEnv<T extends z.ZodRawShape>(\n\t\tschema: T,\n\t\toptions?: EnvValidationOptions,\n\t): z.infer<z.ZodObject<T>> {\n\t\t// biome-ignore lint/style/noNonNullAssertion: Lazy load zod on first use\n\t\tconst zod = (globalThis as Record<string, unknown>).__buntok_zod ??= require(\"zod\").z;\n\t\tconst envSchema = zod.object(schema);\n\t\tconst result = envSchema.safeParse(process.env);\n\n\t\tif (!result.success) {\n\t\t\tconst errors = result.error.issues.map((err: { path: { join: (s: string) => string }; message: string }) => ({\n\t\t\t\tfield: err.path.join(\".\"),\n\t\t\t\tmessage: err.message,\n\t\t\t}));\n\n\t\t\t// If custom handler provided, call it and skip default behavior\n\t\t\tif (options?.onError) {\n\t\t\t\toptions.onError(errors);\n\t\t\t\t// If onError didn't throw/exit, throw error for caller to handle\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Environment validation failed: ${errors.map((e: { field: string; message: string }) => `${e.field}: ${e.message}`).join(\", \")}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Default behavior: print error and exit\n\t\t\tconsole.error(\"\\n\\x1b[41m\\x1b[37m 🚨 Buntok Environment Error \\x1b[0m\\n\");\n\t\t\tconsole.error(\n\t\t\t\t\"\\x1b[31mMissing or invalid environment variables:\\x1b[0m\\n\",\n\t\t\t);\n\n\t\t\terrors.forEach((err: { field: string; message: string }) => {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`  \\x1b[33m❯\\x1b[0m \\x1b[36m${err.field}\\x1b[0m: \\x1b[90m${err.message}\\x1b[0m`,\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tconsole.error(\"\\n\\x1b[31mServer boot aborted.\\x1b[0m\\n\");\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\treturn result.data;\n\t}\n\n\t/**\n\t * Type-safe Environment Variables Validator (instance).\n\t * Delegates to the static method. Kept for backward compatibility.\n\t *\n\t * @example\n\t * const app = new Buntok();\n\t * const env = app.validateEnv({\n\t *   DATABASE_URL: z.string().url(),\n\t *   PORT: z.coerce.number().default(3000),\n\t * });\n\t */\n\tpublic validateEnv<T extends z.ZodRawShape>(\n\t\tschema: T,\n\t\toptions?: EnvValidationOptions,\n\t): z.infer<z.ZodObject<T>> {\n\t\treturn Buntok.validateEnv(schema, options);\n\t}\n\n\t/**\n\t * Register all `@Get`/`@Post`/etc. routes declared on a `@Controller`\n\t * class. This is sugar over `registerRoute()` - it instantiates the\n\t * class once (at boot time, not per request) and wires each decorated\n\t * method up exactly like a manual `app.get(path, handler)` call would.\n\t *\n\t * When a Container is attached via `app.setContainer()`, `@Inject`-\n\t * annotated properties on the controller are automatically resolved\n\t * from the container before routes are bound.\n\t *\n\t * ```ts\n\t * app.registerController(UserController);\n\t * app.registerController([UserController, PostController]);\n\t * ```\n\t */\n\t// biome-ignore lint/suspicious/noExplicitAny: Constructor args are unknowable\n\tpublic registerController<T extends object>(target: (new (...args: any[]) => T) | T): this;\n\t// biome-ignore lint/suspicious/noExplicitAny: Constructor args are unknowable\n\tpublic registerController<T extends object>(targets: Array<(new (...args: any[]) => T) | T>): this;\n\t// biome-ignore lint/suspicious/noExplicitAny: Constructor args are unknowable\n\tpublic registerController<T extends object>(\n\t\ttarget: (new (...args: any[]) => T) | T | Array<(new (...args: any[]) => T) | T>,\n\t): this {\n\t\tif (Array.isArray(target)) {\n\t\t\tfor (const t of target) {\n\t\t\t\tthis.registerController(t);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\t// Detect if target is a class (constructor) or an instance\n\t\tconst isInstance =\n\t\t\ttypeof target === \"object\" &&\n\t\t\ttarget !== null &&\n\t\t\ttypeof target === \"object\";\n\n\t\tconst ControllerClass = isInstance\n\t\t\t? // biome-ignore lint/suspicious/noExplicitAny: dynamic type narrowing\n\t\t\t(target as any).constructor\n\t\t\t: // biome-ignore lint/suspicious/noExplicitAny: dynamic type narrowing\n\t\t\t(target as new (\n\t\t\t\t...args: any[]\n\t\t\t) => T);\n\n\t\tconst meta = getControllerMeta(ControllerClass);\n\t\tif (!meta) {\n\t\t\tthrow new Error(\n\t\t\t\t`${ControllerClass.name} is not decorated with @Controller - did you forget to add it?`,\n\t\t\t);\n\t\t}\n\n\t\tlet instance: T;\n\n\t\tif (isInstance) {\n\t\t\t// Use the provided instance directly\n\t\t\tinstance = target as T;\n\t\t} else if (this.container?.has(ControllerClass)) {\n\t\t\t// Resolve from container if registered via scan()\n\t\t\tconst resolved = this.container.resolve<T>(ControllerClass);\n\t\t\tinstance = resolved;\n\t\t} else {\n\t\t\t// No container registration - create directly (no DI)\n\t\t\tinstance = new ControllerClass();\n\t\t}\n\n\t\tconst normalizedPrefix = meta.prefix.endsWith(\"/\")\n\t\t\t? meta.prefix.slice(0, -1)\n\t\t\t: meta.prefix;\n\n\t\tfor (const route of meta.routes) {\n\t\t\tconst cleanPath = route.path === \"/\" ? \"\" : route.path;\n\t\t\tconst fullPath = `${normalizedPrefix}${cleanPath}` || \"/\";\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: dynamic method dispatch by decorated property key\n\t\t\tconst originalMethod = (instance as any)[route.propertyKey];\n\t\t\tlet handler = ((...args: any[]) => originalMethod.apply(instance, args)) as Handler<DI>;\n\t\t\t// Attach original for sucrose analysis (bound/closure wrappers hide toString)\n\t\t\t(handler as any)._sucroseTarget = originalMethod;\n\n\t\t\t// Apply zero-cost wrappers for @HttpCode/@Header/@Redirect (boot-time, no per-request alloc beyond wrapper closure)\n\t\t\thandler = applyRouteResponseDecorators(handler, route);\n\n\t\t\tthis.registerRoute(route.method, fullPath, [\n\t\t\t\t...(route.middlewares as Middleware<DI>[]),\n\t\t\t\thandler,\n\t\t\t], { source: \"controller\", controller: ControllerClass.name });\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tpublic onError(handler: ErrorHandler<DI>): this {\n\t\tthis.customErrorHandler = handler;\n\t\treturn this;\n\t}\n\n\tpublic notFound(handler: NotFoundHandler<DI>): this {\n\t\tthis.customNotFoundHandler = handler;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Disable a built-in feature:\n\t *\n\t * - `\"x-powered-by\"` - turns off the `X-Powered-By: buntok` response\n\t *   header. The header's value itself is not configurable - this only\n\t *   controls whether it's sent.\n\t * - `\"logger\"` - silences the terminal logger entirely: request logs,\n\t *   error/warn logs, graceful-shutdown messages, and the startup banner\n\t *   (`Buntok vX ready in ...`). Also flags request logging as off so the\n\t *   AOT router compiles its log-free fast path. Useful when you don't\n\t *   want log noise during development.\n\t *\n\t * Both flags are read by the AOT codegen at compile time - toggling after\n\t * compile triggers a lazy recompile on the next request.\n\t */\n\tpublic disable(feature: \"x-powered-by\" | \"logger\"): this {\n\t\tif (feature === \"x-powered-by\") {\n\t\t\tthis.poweredByHeaderEnabled = false;\n\t\t}\n\t\tif (feature === \"logger\") {\n\t\t\tlogger.enabled = false;\n\t\t\tlogger.logRequests = false;\n\t\t}\n\t\tthis._invalidateAOT();\n\t\treturn this;\n\t}\n\n\t/**\n\t * Re-enable a feature previously turned off with `disable()`.\n\t */\n\tpublic enable(feature: \"x-powered-by\" | \"logger\"): this {\n\t\tif (feature === \"x-powered-by\") {\n\t\t\tthis.poweredByHeaderEnabled = true;\n\t\t}\n\t\tif (feature === \"logger\") {\n\t\t\tlogger.enabled = true;\n\t\t\tlogger.logRequests = true;\n\t\t}\n\t\tthis._invalidateAOT();\n\t\treturn this;\n\t}\n\n\t/**\n\t * Enable SO_REUSEPORT for multi-process load balancing (Linux only).\n\t * When enabled, multiple instances of the app can bind to the same port,\n\t * and incoming requests are load-balanced at the kernel level.\n\t *\n\t * ⚠️ On non-Linux platforms (macOS, Windows), this option is silently ignored.\n\t * A warning will be logged in development mode to help catch environment mismatches.\n\t */\n\tpublic enableReusePort(enabled = true): this {\n\t\tthis._reusePort = enabled;\n\n\t\t// Warn in development about platform limitation\n\t\tif (enabled && process.platform !== \"linux\") {\n\t\t\tconsole.warn(\n\t\t\t\t`\\x1b[33m⚠ Warning: enableReusePort() is only supported on Linux. ` +\n\t\t\t\t`Current platform: ${process.platform}. ` +\n\t\t\t\t`This option will be ignored in production.\\x1b[0m`,\n\t\t\t);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tpublic icon(path?: string): this {\n\t\tif (path) this.iconPath = path;\n\t\tthis.registerFaviconRoute();\n\t\treturn this;\n\t}\n\n\tprivate registerFaviconRoute(): void {\n\t\tthis.get(\"/favicon.ico\", async (_ctx) => {\n\t\t\t// Try custom path first\n\t\t\tconst customFile = Bun.file(this.iconPath);\n\t\t\tif (await customFile.exists()) {\n\t\t\t\treturn new Response(customFile);\n\t\t\t}\n\t\t\t// Fallback to built-in icon\n\t\t\tconst builtInFile = Bun.file(this.getBuiltInIconPath());\n\t\t\tif (await builtInFile.exists()) {\n\t\t\t\treturn new Response(builtInFile);\n\t\t\t}\n\t\t\t// No favicon found\n\t\t\treturn new Response(null, { status: 404 });\n\t\t});\n\t\t// Promote to a native Bun route value when the icon exists at boot -\n\t\t// registered after this.get() so registerRoute's static-value cleanup\n\t\t// doesn't wipe it. The async handler above stays as the JS fallback\n\t\t// (native gates off, or the file appears after registration).\n\t\tconst resolved = existsSync(this.iconPath)\n\t\t\t? this.iconPath\n\t\t\t: this.getBuiltInIconPath();\n\t\tif (existsSync(resolved)) {\n\t\t\tthis._staticRouteValues.set(\"GET:/favicon.ico\", Bun.file(resolved));\n\t\t}\n\t}\n\n\tprivate getBuiltInIconPath(): string {\n\t\treturn join(__dirname, \"..\", \"public\", \"favicon.ico\");\n\t}\n\n\tpublic get<Path extends string>(path: Path, handler: Handler<DI, Path> | string | Response): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.registerRoute(\"GET\", path, handlers, { source: \"route\" });\n\t\treturn this;\n\t}\n\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.registerRoute(\"POST\", path, handlers, { source: \"route\" });\n\t\treturn this;\n\t}\n\n\tpublic put<Path extends string>(path: Path, handler: Handler<DI, Path> | string | Response): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.registerRoute(\"PUT\", path, handlers, { source: \"route\" });\n\t\treturn this;\n\t}\n\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.registerRoute(\"DELETE\", path, handlers, { source: \"route\" });\n\t\treturn this;\n\t}\n\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.registerRoute(\"OPTIONS\", path, handlers, { source: \"route\" });\n\t\treturn this;\n\t}\n\n\tpublic query(path: string, handler: Handler<DI>): this;\n\tpublic query(\n\t\tpath: string,\n\t\tmiddleware: Middleware<DI>,\n\t\thandler: Handler<DI>,\n\t): this;\n\tpublic query(\n\t\tpath: string,\n\t\tm1: Middleware<DI>,\n\t\tm2: Middleware<DI>,\n\t\thandler: Handler<DI>,\n\t): this;\n\tpublic query(\n\t\tpath: string,\n\t\tm1: Middleware<DI>,\n\t\tm2: Middleware<DI>,\n\t\tm3: Middleware<DI>,\n\t\thandler: Handler<DI>,\n\t): this;\n\tpublic query(\n\t\tpath: string,\n\t\tm1: Middleware<DI>,\n\t\tm2: Middleware<DI>,\n\t\tm3: Middleware<DI>,\n\t\tm4: Middleware<DI>,\n\t\thandler: Handler<DI>,\n\t): this;\n\tpublic query(\n\t\tpath: string,\n\t\tm1: Middleware<DI>,\n\t\tm2: Middleware<DI>,\n\t\tm3: Middleware<DI>,\n\t\tm4: Middleware<DI>,\n\t\tm5: Middleware<DI>,\n\t\thandler: Handler<DI>,\n\t): this;\n\tpublic query(\n\t\tpath: string,\n\t\t...handlers: Array<Middleware<DI> | Handler<DI>>\n\t): this {\n\t\tthis.registerRoute(\"QUERY\", path, handlers, { source: \"route\" });\n\t\treturn this;\n\t}\n\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.registerRoute(\"PATCH\", path, handlers, { source: \"route\" });\n\t\treturn this;\n\t}\n\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.registerRoute(\"HEAD\", path, handlers, { source: \"route\" });\n\t\treturn this;\n\t}\n\n\t/**\n\t * Register a handler for all standard HTTP methods (GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS).\n\t */\n\tpublic all<Path extends string>(path: Path, handler: Handler<DI, Path> | string | Response): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tconst methods = [\n\t\t\t\"GET\",\n\t\t\t\"HEAD\",\n\t\t\t\"POST\",\n\t\t\t\"PUT\",\n\t\t\t\"PATCH\",\n\t\t\t\"DELETE\",\n\t\t\t\"OPTIONS\",\n\t\t];\n\t\tfor (const method of methods) {\n\t\t\tthis.registerRoute(method, path, handlers, { source: \"route\" });\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Serve static files from `directory` under `routePath`.\n\t *\n\t * Rejects any request whose resolved path escapes `directory` (e.g.\n\t * `/files/../../etc/passwd`) - without this check, static serving is a\n\t * directory-traversal vulnerability.\n\t *\n\t * Supports ETag-based conditional requests (If-None-Match → 304).\n\t * ETag is computed on every response and sent to the client, enabling\n\t * efficient caching on subsequent requests.\n\t */\n\tpublic static(routePath: string, directory: string, options?: StaticOptions): this {\n\t\tconst baseDir = resolve(directory);\n\t\tconst maxAge = options?.maxAge ?? 3600;\n\t\tconst cacheControl = options?.cacheControl ?? `public, max-age=${maxAge}`;\n\t\tconst enableEtag = options?.etag !== false;\n\n\t\tconst handler: Handler<DI> = async (ctx) => {\n\t\t\tconst requestedPath = ctx.params[\"*\"] || \"\";\n\t\t\tlet absolutePath = join(baseDir, requestedPath);\n\n\t\t\tif (absolutePath !== baseDir && !absolutePath.startsWith(baseDir + sep)) {\n\t\t\t\treturn ctx.json({ error: \"Forbidden\" }, 403);\n\t\t\t}\n\n\t\t\t// If file doesn't exist, check for directory with index.html\n\t\t\tif (!(await Bun.file(absolutePath).exists())) {\n\t\t\t\tconst indexPath = join(absolutePath, \"index.html\");\n\t\t\t\tif (await Bun.file(indexPath).exists()) {\n\t\t\t\t\tabsolutePath = indexPath;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst file = Bun.file(absolutePath);\n\n\t\t\tif (!(await file.exists())) {\n\t\t\t\treturn ctx.json({ error: \"File Not Found\" }, 404);\n\t\t\t}\n\n\t\t\tconst etag = enableEtag ? `\"${file.size}-${file.lastModified}\"` : null;\n\n\t\t\t// ETag-based conditional request (If-None-Match → 304)\n\t\t\tif (etag) {\n\t\t\t\tconst ifNoneMatch = ctx.request.headers.get(\"If-None-Match\");\n\t\t\t\tif (ifNoneMatch === etag) {\n\t\t\t\t\treturn new Response(null, {\n\t\t\t\t\t\tstatus: 304,\n\t\t\t\t\t\theaders: { ETag: etag },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t\"Cache-Control\": cacheControl,\n\t\t\t};\n\t\t\tif (etag) {\n\t\t\t\theaders.ETag = etag;\n\t\t\t}\n\n\t\t\treturn new Response(file, { headers });\n\t\t};\n\n\t\tconst wildcardPath = routePath.endsWith(\"/\")\n\t\t\t? `${routePath}*`\n\t\t\t: `${routePath}/*`;\n\t\tthis.get(wildcardPath, handler);\n\t\t// Opt-in native directory serving - Bun answers the route with its\n\t\t// `{ dir }` implementation (zero JS). Registered after this.get() for\n\t\t// the same reason as the favicon: registerRoute clears static values.\n\t\t// Gates (logger / X-Powered-By / global mw) still apply at listen();\n\t\t// when off, the JS handler above keeps serving with full options.\n\t\tif (\n\t\t\toptions?.native &&\n\t\t\twildcardPath.startsWith(\"/\") &&\n\t\t\twildcardPath.endsWith(\"/*\") &&\n\t\t\t!wildcardPath.includes(\"{\")\n\t\t) {\n\t\t\tthis._staticRouteValues.set(`GET:${wildcardPath}`, { dir: baseDir });\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Enable interactive API documentation at the specified path.\n\t *\n\t * Serves a built-in docs UI and the generated OpenAPI spec (swagger.json).\n\t * The docs routes are registered directly on the router and do NOT appear\n\t * in the generated swagger.json.\n\t *\n\t * @example\n\t * ```ts\n\t * app.apiDocs({ path: \"/docs\", title: \"My API\", version: \"1.0.0\" });\n\t * ```\n\t */\n\tpublic apiDocs(options?: ApiDocsOptions): this {\n\t\tthis._apiDocsConfig = {\n\t\t\tpath: options?.path ?? \"/docs\",\n\t\t\ttitle: options?.title ?? \"API Documentation\",\n\t\t\tversion: options?.version ?? \"1.0.0\",\n\t\t\tdescription: options?.description,\n\t\t\tsafeOnProduction: options?.safeOnProduction ?? false,\n\t\t};\n\t\treturn this;\n\t}\n\n\tpublic registerRoute(\n\t\tmethod: string,\n\t\tpath: string,\n\t\thandlers: Array<Middleware<DI> | Handler<DI> | string | Response>,\n\t\toptions?: { source?: \"route\" | \"controller\" | \"group\"; controller?: string; group?: string },\n\t): void {\n\t\tconst routeMiddlewares = handlers.slice(0, -1) as Middleware<DI>[];\n\t\tconst routeKey = `${method}:${path}`;\n\t\tlet mainHandler = handlers[handlers.length - 1] as Handler<DI>;\n\n\t\t// Static handler value (Elysia style: `app.get('/', 'Hi')`) - wrap it\n\t\t// in a function so every execution path (pipeline, AOT codegen,\n\t\t// fallback) keeps working, and keep the raw value so listen() can\n\t\t// promote the route to native Bun.serve `routes` (hot path without JS).\n\t\tthis._staticRouteValues.delete(routeKey);\n\t\tconst rawMain = handlers[handlers.length - 1];\n\t\tif (typeof rawMain === \"string\" || rawMain instanceof Response) {\n\t\t\tconst staticValue = rawMain;\n\t\t\tmainHandler = () => staticValue;\n\t\t\tif (routeMiddlewares.length === 0) {\n\t\t\t\tthis._staticRouteValues.set(routeKey, staticValue);\n\t\t\t}\n\t\t} else if (routeMiddlewares.length === 0) {\n\t\t\t// Handler with a provably constant expression - a pure literal\n\t\t\t// (`() => \"Hi\"`), `ctx.text(\"Hi\"[, 201])`, `ctx.html(...)` or\n\t\t\t// `ctx.json(<JSON-literal>[, 201])` - also promoted to native.\n\t\t\t// The original function stays on the JS path as a fallback when\n\t\t\t// a native gate is off (logging/global mw/etc.).\n\t\t\tconst constOp = extractConstResponseOp(rawMain);\n\t\t\tif (constOp !== undefined) {\n\t\t\t\tthis._staticRouteValues.set(routeKey, constOp);\n\t\t\t}\n\t\t}\n\n\t\t// Track routes with per-route middlewares for AOT Context optimization\n\t\tif (routeMiddlewares.length > 0) {\n\t\t\tthis._routesWithMiddleware.add(routeKey);\n\t\t}\n\n\t\t// Pre-compute sucrose analysis for fallback path and AOT codegen\n\t\tif (!this._handlerNeedsFullContext.has(mainHandler)) {\n\t\t\tconst a = analyzeHandler(mainHandler);\n\t\t\tthis._handlerNeedsFullContext.set(mainHandler, !!(a.needsBody || a.needsValidation ||\n\t\t\t\ta.needsFormData || a.needsQuery || a.needsText || a.needsBinary));\n\t\t}\n\t\t// Full context check for AOT: includes ctx.json, ctx.error, etc.\n\t\tif (!this._handlerFullContextCache.has(mainHandler)) {\n\t\t\tconst a = analyzeHandler(mainHandler);\n\t\t\tthis._handlerFullContextCache.set(mainHandler, {\n\t\t\t\tneedsFullContext: !!a.needsFullContext,\n\t\t\t\tneedsParams: !!a.needsParams,\n\t\t\t\tneedsSetHeaders: !!a.needsSetHeaders,\n\t\t\t});\n\t\t}\n\n\t\t// Capture debug info before compilation\n\t\tthis.routeDebugInfo.push({\n\t\t\tmethod,\n\t\t\tpath,\n\t\t\tmiddlewares: routeMiddlewares.map((mw) => mw.name || \"anonymous\"),\n\t\t\thandler: mainHandler.name || \"anonymous\",\n\t\t\tsource: options?.source || \"route\",\n\t\t\tcontroller: options?.controller,\n\t\t\tgroup: options?.group,\n\t\t});\n\n\t\t// Collect OpenAPI metadata\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Required for flexible schema representation\n\t\tconst openApiDoc: any = {\n\t\t\tmethod: method.toLowerCase(),\n\t\t\tpath,\n\t\t\trequest: { params: null, query: null, body: null },\n\t\t\tresponses: [],\n\t\t};\n\n\t\tfor (const handler of handlers) {\n\t\t\tconst h = handler as unknown as Record<string, unknown>;\n\t\t\tif (h._isBuntokValidator) {\n\t\t\t\tconst target = h._target as string;\n\t\t\t\tconst schema = h._schema;\n\t\t\t\topenApiDoc.request[target] = schema;\n\t\t\t\tif (target === \"body\") {\n\t\t\t\t\topenApiDoc.request.bodyContentType = h._contentType as string;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (h._isBuntokResponse) {\n\t\t\t\topenApiDoc.responses.push({\n\t\t\t\t\tstatus: h._status,\n\t\t\t\t\tschema: h._schema,\n\t\t\t\t\tdescription: h._description,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Always register the route in OpenAPI, even if it lacks explicit validation/responses\n\t\tthis.openApiDocs.push(openApiDoc);\n\n\t\t// AOT Compile route middlewares\n\t\tconst executionChain = this.compilePipeline(routeMiddlewares, mainHandler);\n\n\t\t// Map compiled pipeline → original handler for AOT sucrose analysis\n\t\tthis._pipelineToHandler.set(executionChain, mainHandler);\n\n\t\tthis.router.insert(method, path, executionChain);\n\t}\n\n\tprivate compilePipeline(\n\t\tmiddlewares: Middleware<DI>[],\n\t\tfinalHandler: Handler<DI>,\n\t): Handler<DI> {\n\t\tif (middlewares.length === 0) return finalHandler;\n\n\t\tconst fns = [...middlewares, finalHandler];\n\t\t// Normalize the innermost handler result BEFORE it flows back through\n\t\t// the middleware chain: built-ins (requestId, responseTime, rateLimiter,\n\t\t// compress, auditLog) guard mutations with `result instanceof Response`\n\t\t// and would silently skip raw string/object returns (e. `() => \"ok\"`).\n\t\tlet code = `const r = fns[${fns.length - 1}](ctx); return r instanceof Promise ? r.then((v) => normalize(v, ctx.request)) : normalize(r, ctx.request);`;\n\t\tfor (let i = fns.length - 2; i >= 0; i--) {\n\t\t\tcode = `return fns[${i}](ctx, () => { ${code} });`;\n\t\t}\n\n\t\tconst factory = new Function(\n\t\t\t\"fns\",\n\t\t\t\"normalize\",\n\t\t\t`return function(ctx) { ${code} }`,\n\t\t);\n\t\treturn factory(fns, this.normalizeReturn.bind(this)) as Handler<DI>;\n\t}\n\n\t/**\n\t * Register API docs routes directly on the router.\n\t * These routes do NOT go through registerRoute() and therefore\n\t * do NOT appear in openApiDocs / swagger.json.\n\t */\n\tprivate registerApiDocsRoutes(): void {\n\t\tconst config = this._apiDocsConfig!;\n\t\tconst basePath = (config.path ?? \"/docs\").replace(/\\/+$/, \"\");\n\n\t\t// Resolve template paths relative to this package's dist directory\n\t\tconst templatesDir = join(__dirname, \"cli\", \"templates\");\n\n\t\t// Handler for serving the HTML docs UI - safe injection via app.apiDocs()\n\t\tconst uiHandler: Handler<DI> = async () => {\n\t\t\tconst htmlPath = join(templatesDir, \"index.html\");\n\t\t\tconst file = Bun.file(htmlPath);\n\t\t\tif (await file.exists()) {\n\t\t\t\tlet html = await file.text();\n\t\t\t\t// Safe HTML escape for <title> (prevent </title> injection)\n\t\t\t\tconst rawTitle = config.title ?? \"API Reference\";\n\t\t\t\tconst escTitleHtml = String(rawTitle)\n\t\t\t\t\t.replace(/&/g, \"&amp;\")\n\t\t\t\t\t.replace(/</g, \"&lt;\")\n\t\t\t\t\t.replace(/>/g, \"&gt;\")\n\t\t\t\t\t.replace(/\"/g, \"&quot;\");\n\t\t\t\thtml = html.replace(\n\t\t\t\t\t/<title>.*?<\\/title>/,\n\t\t\t\t\t`<title>${escTitleHtml} - API Reference</title>`,\n\t\t\t\t);\n\t\t\t\t// Safe JSON injection via JSON.stringify (handles quotes, newlines, unicode)\n\t\t\t\thtml = html.replace(\n\t\t\t\t\t/\"title\":\\s*\"API Documentation\"/,\n\t\t\t\t\t`\"title\":${JSON.stringify(config.title ?? \"API Documentation\")}`,\n\t\t\t\t);\n\t\t\t\thtml = html.replace(\n\t\t\t\t\t/\"version\":\\s*\"1\\.0\\.0\"/,\n\t\t\t\t\t`\"version\":${JSON.stringify(config.version ?? \"1.0.0\")}`,\n\t\t\t\t);\n\t\t\t\tif (config.description) {\n\t\t\t\t\thtml = html.replace(\n\t\t\t\t\t\t/\"description\":\\s*\"Loading API specification\\.\\.\\.\"/,\n\t\t\t\t\t\t`\"description\":${JSON.stringify(config.description)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// Inject the swagger.json path based on the configured basePath\n\t\t\t\tconst swaggerPath = `${basePath}/swagger.json`;\n\t\t\t\thtml = html.replace(\n\t\t\t\t\t/const swaggerJsonPath = '.*?'/,\n\t\t\t\t\t`const swaggerJsonPath = ${JSON.stringify(swaggerPath)}`,\n\t\t\t\t);\n\t\t\t\t// Fix relative asset paths - browser resolves ./ against URL\n\t\t\t\t// which breaks when page is at /docs (no trailing slash)\n\t\t\t\thtml = html.replace(/\"\\.\\//g, `\"${basePath}/`);\n\t\t\t\treturn new Response(html, {\n\t\t\t\t\theaders: { \"Content-Type\": \"text/html; charset=utf-8\" },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn new Response(\"Docs UI not found. Run 'buntok make:docs' first.\", { status: 404 });\n\t\t};\n\n\t\t// Handler for serving swagger.json - memory first (instant), disk fallback\n\t\tconst swaggerHandler: Handler<DI> = async () => {\n\t\t\t// Serve from in-memory cache (generated at startup)\n\t\t\tif (this._swaggerDocument) {\n\t\t\t\treturn Response.json(this._swaggerDocument);\n\t\t\t}\n\t\t\t// Fallback to disk (for manual make:docs or if generation not done yet)\n\t\t\tconst swaggerPath = join(process.cwd(), \"public/docs/swagger.json\");\n\t\t\tconst file = Bun.file(swaggerPath);\n\t\t\tif (await file.exists()) {\n\t\t\t\treturn new Response(file, {\n\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn new Response(\n\t\t\t\tJSON.stringify({ error: \"swagger.json not found.\" }),\n\t\t\t\t{ status: 404, headers: { \"Content-Type\": \"application/json\" } },\n\t\t\t);\n\t\t};\n\n\t\t// Handler for serving static assets (tailwind.js, font-googles.css)\n\t\tconst assetsHandler: Handler<DI> = async (ctx) => {\n\t\t\tconst assetName = ctx.params[\"*\"] ?? \"\";\n\t\t\tconst assetPath = join(templatesDir, assetName);\n\t\t\tconst file = Bun.file(assetPath);\n\t\t\tif (await file.exists()) {\n\t\t\t\tconst ext = assetName.split(\".\").pop()?.toLowerCase() ?? \"\";\n\t\t\t\tconst contentTypes: Record<string, string> = {\n\t\t\t\t\tjs: \"application/javascript; charset=utf-8\",\n\t\t\t\t\tcss: \"text/css; charset=utf-8\",\n\t\t\t\t\tjson: \"application/json\",\n\t\t\t\t\tpng: \"image/png\",\n\t\t\t\t\tsvg: \"image/svg+xml\",\n\t\t\t\t\tico: \"image/x-icon\",\n\t\t\t\t};\n\t\t\t\treturn new Response(file, {\n\t\t\t\t\theaders: { \"Content-Type\": contentTypes[ext] || \"application/octet-stream\" },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn new Response(\"Not Found\", { status: 404 });\n\t\t};\n\n\t\t// Register routes directly on router (bypass openApiDocs)\n\t\tthis.router.insert(\"GET\", `${basePath}/swagger.json`, swaggerHandler);\n\t\tthis.router.insert(\"GET\", `${basePath}/index.html`, uiHandler);\n\t\tthis.router.insert(\"GET\", `${basePath}/*`, assetsHandler);\n\t\tthis.router.insert(\"GET\", `${basePath}`, uiHandler);\n\t\tthis.router.insert(\"GET\", `${basePath}/`, uiHandler);\n\n\t\t// Serve favicon.ico from templates directory (root path)\n\t\tconst faviconHandler: Handler<DI> = async () => {\n\t\t\tconst file = Bun.file(join(templatesDir, \"favicon.ico\"));\n\t\t\tif (await file.exists()) {\n\t\t\t\treturn new Response(file, { headers: { \"Content-Type\": \"image/x-icon\" } });\n\t\t\t}\n\t\t\treturn new Response(null, { status: 404 });\n\t\t};\n\t\tthis.router.insert(\"GET\", \"/favicon.ico\", faviconHandler);\n\t}\n\n\tprivate compileGlobalPipeline(): void {\n\t\tif (!this.hasPipelineHooks) {\n\t\t\tthis.compiledGlobalPipeline = (ctx, finalHandler) =>\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: compiled\n\t\t\t\tfinalHandler(ctx as any);\n\t\t\treturn;\n\t\t}\n\n\t\ttype Next = () => Promise<Response> | Response;\n\t\tconst preAdapter =\n\t\t\t(hook: RequestHook<DI> | BeforeHandleHook<DI>) =>\n\t\t\t(ctx: Context<DI>, next: Next): HandlerReturn => {\n\t\t\t\tconst result = hook(ctx);\n\t\t\t\tif (result instanceof Promise) {\n\t\t\t\t\treturn result.then((v) => (v instanceof Response ? v : next()));\n\t\t\t\t}\n\t\t\t\tif (result instanceof Response) return result;\n\t\t\t\treturn next();\n\t\t\t};\n\t\tconst deriveAdapter =\n\t\t\t(hook: DeriveHook<DI>) =>\n\t\t\t(ctx: Context<DI>, next: Next): HandlerReturn => {\n\t\t\t\tconst result = hook(ctx);\n\t\t\t\tif (result instanceof Promise) {\n\t\t\t\t\treturn result.then((v) => {\n\t\t\t\t\t\tif (v) Object.assign(ctx.store, v);\n\t\t\t\t\t\treturn next();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (result) Object.assign(ctx.store, result);\n\t\t\t\treturn next();\n\t\t\t};\n\t\tconst afterAdapter =\n\t\t\t(hook: AfterHandleHook<DI>) =>\n\t\t\t(ctx: Context<DI>, next: Next): HandlerReturn => {\n\t\t\t\tconst finish = (res: Response) => {\n\t\t\t\t\tconst out = hook(ctx, res);\n\t\t\t\t\treturn out instanceof Promise\n\t\t\t\t\t\t? out.then((v) => v ?? res)\n\t\t\t\t\t\t: (out ?? res);\n\t\t\t\t};\n\t\t\t\tconst result = next();\n\t\t\t\treturn result instanceof Promise ? result.then(finish) : finish(result);\n\t\t\t};\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: pipeline ctx params are normalized by codegen\n\t\tconst fns: Array<(ctx: Context<DI, any>, next: Next) => HandlerReturn> = [\n\t\t\t...this.requestHooks.map(preAdapter),\n\t\t\t...this.middlewares,\n\t\t\t...this.deriveHooks.map(deriveAdapter),\n\t\t\t...this.beforeHandleHooks.map(preAdapter),\n\t\t\t...this.afterHandleHooks.map(afterAdapter),\n\t\t];\n\t\t// Same contract as compilePipeline: the final handler result is\n\t\t// normalized to a Response before it reaches any middleware, so\n\t\t// `result instanceof Response` mutations work regardless of the\n\t\t// handler's return type and of the logging flag.\n\t\tlet code = `const r = finalHandler(ctx); return r instanceof Promise ? r.then((v) => normalize(v, ctx.request)) : normalize(r, ctx.request);`;\n\t\tfor (let i = fns.length - 1; i >= 0; i--) {\n\t\t\tcode = `return fns[${i}](ctx, () => { ${code} });`;\n\t\t}\n\n\t\tconst factory = new Function(\n\t\t\t\"fns\",\n\t\t\t\"normalize\",\n\t\t\t`return function(ctx, finalHandler) { ${code} }`,\n\t\t);\n\t\tthis.compiledGlobalPipeline = factory(\n\t\t\tfns,\n\t\t\tthis.normalizeReturn.bind(this),\n\t\t) as (\n\t\t\tctx: Context<DI>,\n\t\t\tfinalHandler: Handler<DI>,\n\t\t) => HandlerReturn;\n\t}\n\n\tprivate compileAOTRouter(): (\n\t\trequest: Request,\n\t\tserver?: Server<WSData<DI>>,\n\t) => Response | Promise<Response> {\n\t\t// Snapshotted at compile time (not just at listen) - fetch/serverless\n\t\t// paths without listen() still get codegen without logResponse().\n\t\tthis._skipLogResponse = !logger.logRequests;\n\t\tconst hasGlobalMiddleware = this.hasPipelineHooks;\n\t\tlet code =\n\t\t\t\"return function(request, server) {\\n\" +\n\t\t\t\"  const url = request.url;\\n\" +\n\t\t\t\"  let start = url.indexOf('/', url.indexOf('//') + 2);\\n\" +\n\t\t\t\"  if (start === -1) start = url.length;\\n\" +\n\t\t\t\"  let end = url.indexOf('?', start);\\n\" +\n\t\t\t\"  if (end === -1) end = url.length;\\n\" +\n\t\t\t\"  const pathname = start === url.length ? '/' : url.substring(start, end);\\n\";\n\n\t\tif (this.wsRoutes.size > 0) {\n\t\t\tcode +=\n\t\t\t\t\"  if (server && wsRoutes.has(pathname)) {\\n\" +\n\t\t\t\t\"    const wsHandler = wsRoutes.get(pathname);\\n\" +\n\t\t\t\t\"    const wsCtx = new Context(request, EMPTY_PARAMS, di, clientIPResolver);\\n\" +\n\t\t\t\t\"    const data = { ctx: wsCtx, handler: wsHandler };\\n\" +\n\t\t\t\t\"    const upgraded = server.upgrade(request, { data });\\n\" +\n\t\t\t\t\"    if (upgraded) return undefined;\\n\" +\n\t\t\t\t\"    return new Response('Upgrade Required', { status: 426, headers: { Connection: 'Upgrade', Upgrade: 'websocket' } });\\n\" +\n\t\t\t\t\"  }\\n\";\n\t\t}\n\n\t\tcode += \"  let ctx;\\n  const method = request.method;\\n\" + \"  try {\\n\" + \"  switch(method) {\\n\";\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: generic\n\t\tconst handlersList: any[] = [];\n\t\t// biome-ignore lint/suspicious/noExplicitAny: generic\n\t\tconst handlersMap = new Map<any, string>();\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: generic\n\t\tfunction getHandlerIndex(handler: any) {\n\t\t\tif (handlersMap.has(handler)) return handlersMap.get(handler);\n\t\t\tconst idx = handlersList.length;\n\t\t\thandlersList.push(handler);\n\t\t\thandlersMap.set(handler, `handlers[${idx}]`);\n\t\t\treturn `handlers[${idx}]`;\n\t\t}\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: generic\n\t\tconst methodPaths = new Map<string, { path: string; handler: any }[]>();\n\t\tfor (const [path, methodMap] of this.router.staticRoutes.entries()) {\n\t\t\tfor (const [method, handler] of methodMap.entries()) {\n\t\t\t\tif (!methodPaths.has(method)) methodPaths.set(method, []);\n\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: guaranteed\n\t\t\t\tmethodPaths.get(method)!.push({ path, handler });\n\t\t\t}\n\t\t}\n\n\t\tfor (const [method, routes] of methodPaths.entries()) {\n\t\t\tcode += `case \"${method}\": {\\n`;\n\t\t\tcode += \"  switch(pathname) {\\n\";\n\t\t\tfor (const route of routes) {\n\t\t\t\tconst handlerRef = getHandlerIndex(route.handler);\n\t\t\t\t// Resolve original handler from pipeline for sucrose analysis\n\t\t\t\tconst originalHandler = this._pipelineToHandler.get(route.handler) ?? route.handler;\n\t\t\t\t// Sucrose analysis via cached full-context check (detects ctx.json, ctx.error, etc.)\n\t\t\t\tconst cached = this._handlerFullContextCache.get(originalHandler) ?? { needsFullContext: true, needsParams: false, needsSetHeaders: true };\n\t\t\t\t// Global middleware or per-route middleware (e.g. requireAuth, zValidator)\n\t\t\t\t// may use ctx.error, ctx.json, etc. - must provide full Context\n\t\t\t\tconst routeKey = `${method}:${route.path}`;\n\t\t\t\tconst needsFullContext = hasGlobalMiddleware || this._routesWithMiddleware.has(routeKey) || cached.needsFullContext;\n\t\t\t\t// Sucrose-proven: when nothing can write ctx.set.headers (route\n\t\t\t\t// middleware and global middleware both can - forced true above),\n\t\t\t\t// the response tail skips the applyCtxHeaders merge entirely.\n\t\t\t\tconst needsSetHeaders =\n\t\t\t\t\thasGlobalMiddleware ||\n\t\t\t\t\tthis._routesWithMiddleware.has(routeKey) ||\n\t\t\t\t\tcached.needsSetHeaders;\n\t\t\t\t// Static-route codegen has no routeParams binding - and the\n\t\t\t\t// needsParams-only case is unreachable anyway (sucrose sets\n\t\t\t\t// needsFullContext whenever needsParams is true). Passing a\n\t\t\t\t// plain { request } here previously risked a ReferenceError.\n\t\t\t\tconst ctxArg = needsFullContext ? \"ctx\" : \"{ request }\";\n\t\t\t\t// Error handler always needs full Context, so we declare ctx for catch blocks\n\t\t\t\tconst ctxDecl = needsFullContext\n\t\t\t\t\t? \"      ctx = new Context(request, EMPTY_PARAMS, di, clientIPResolver);\\n\"\n\t\t\t\t\t: \"\";\n\n\t\t\t\tcode += `    case \"${route.path}\": {\\n`;\n\t\t\t\tcode += ctxDecl;\n\t\t\t\tcode += hasGlobalMiddleware\n\t\t\t\t\t? `      const raw = compiledGlobalPipeline(${ctxArg}, ${handlerRef});\\n`\n\t\t\t\t\t: `      const raw = ${handlerRef}(${ctxArg});\\n`;\n\t\t\t\tif (this._skipLogResponse) {\n\t\t\t\t\t// Normalization expressions - promise branch (v) and sync branch\n\t\t\t\t\t// (raw) - shared by the set-headers and no-set variants below.\n\t\t\t\t\tconst normV =\n\t\t\t\t\t\t'typeof v === \"string\" ? new Response(v) : v instanceof Response ? v : typeof v === \"object\" && v !== null ? (v instanceof BuntokFile ? v.toResponse(request) : Response.json(v)) : toResponse(v)';\n\t\t\t\t\tconst normRaw =\n\t\t\t\t\t\t'typeof raw === \"string\" ? new Response(raw) : raw instanceof Response ? raw : typeof raw === \"object\" && raw !== null ? (raw instanceof BuntokFile ? raw.toResponse(request) : Response.json(raw)) : toResponse(raw)';\n\t\t\t\t\tconst tailCatch =\n\t\t\t\t\t\t'.catch((e) => { if (!ctx) ctx = new Context(request, EMPTY_PARAMS, di, clientIPResolver); return handleError(request, pathname, ctx, e); });\\n';\n\t\t\t\t\tif (!this.poweredByHeaderEnabled) {\n\t\t\t\t\t\tif (needsSetHeaders) {\n\t\t\t\t\t\t\t// Fastest path: no logging, no powered-by - skip setPoweredBy entirely\n\t\t\t\t\t\t\tcode += \"      if (raw instanceof Promise) {\\n\";\n\t\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t\t'        return raw.then((v) => applyCtxHeaders(ctx, ' + normV + '))' + tailCatch;\n\t\t\t\t\t\t\tcode += \"      }\\n\";\n\t\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t\t'      if (typeof raw === \"string\") return applyCtxHeaders(ctx, new Response(raw));\\n';\n\t\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t\t\"      if (raw instanceof Response) return applyCtxHeaders(ctx, raw);\\n\" +\n\t\t\t\t\t\t\t\t'      if (typeof raw === \"object\" && raw !== null) return applyCtxHeaders(ctx, raw instanceof BuntokFile ? raw.toResponse(request) : Response.json(raw));\\n' +\n\t\t\t\t\t\t\t\t\"      return applyCtxHeaders(ctx, toResponse(raw));\\n\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// sucrose: handler can never write ctx.set.headers →\n\t\t\t\t\t\t\t// return the normalized response untouched.\n\t\t\t\t\t\t\tcode += \"      if (raw instanceof Promise) {\\n\";\n\t\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t\t'        return raw.then((v) => ' + normV + ')' + tailCatch;\n\t\t\t\t\t\t\tcode += \"      }\\n\";\n\t\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t\t'      if (typeof raw === \"string\") return new Response(raw);\\n';\n\t\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t\t\"      if (raw instanceof Response) return raw;\\n\" +\n\t\t\t\t\t\t\t\t'      if (typeof raw === \"object\" && raw !== null) return raw instanceof BuntokFile ? raw.toResponse(request) : Response.json(raw);\\n' +\n\t\t\t\t\t\t\t\t\"      return toResponse(raw);\\n\";\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (needsSetHeaders) {\n\t\t\t\t\t\tcode += \"      if (raw instanceof Promise) {\\n\";\n\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t'        return raw.then((v) => setPoweredBy(ctx, ' + normV + '))' + tailCatch;\n\t\t\t\t\t\tcode += \"      }\\n\";\n\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t'      if (typeof raw === \"string\") return setPoweredBy(ctx, new Response(raw));\\n';\n\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t\"      if (raw instanceof Response) return setPoweredBy(ctx, raw);\\n\" +\n\t\t\t\t\t\t\t'      if (typeof raw === \"object\" && raw !== null) return setPoweredBy(ctx, raw instanceof BuntokFile ? raw.toResponse(request) : Response.json(raw));\\n' +\n\t\t\t\t\t\t\t\"      return setPoweredBy(ctx, toResponse(raw));\\n\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// powered-by without the ctx.set merge (baked at compile -\n\t\t\t\t\t\t// flag toggles trigger _recompileAOT()).\n\t\t\t\t\t\tcode += \"      if (raw instanceof Promise) {\\n\";\n\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t'        return raw.then((v) => { const r = ' + normV + '; r.headers.set(\"X-Powered-By\", \"buntok\"); return r; })' + tailCatch;\n\t\t\t\t\t\tcode += \"      }\\n\";\n\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t'      const r = ' + normRaw + ';\\n' +\n\t\t\t\t\t\t\t'      r.headers.set(\"X-Powered-By\", \"buntok\");\\n' +\n\t\t\t\t\t\t\t\"      return r;\\n\";\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcode += \"      if (raw instanceof Promise) {\\n\";\n\t\t\t\t\tcode +=\n\t\t\t\t\t\t'        return raw.then((v) => typeof v === \"string\" ? logResponse(request, pathname, ctx, new Response(v)) : logResponse(request, pathname, ctx, v instanceof Response ? v : typeof v === \"object\" && v !== null ? (v instanceof BuntokFile ? v.toResponse(request) : Response.json(v)) : toResponse(v))).catch((e) => { if (!ctx) ctx = new Context(request, EMPTY_PARAMS, di, clientIPResolver); return handleError(request, pathname, ctx, e); });\\n';\n\t\t\t\t\tcode += \"      }\\n\";\n\t\t\t\t\tcode +=\n\t\t\t\t\t\t'      if (typeof raw === \"string\") return logResponse(request, pathname, ctx, new Response(raw));\\n';\n\t\t\t\t\tcode +=\n\t\t\t\t\t\t\"      if (raw instanceof Response) return logResponse(request, pathname, ctx, raw);\\n\" +\n\t\t\t\t\t\t'      if (typeof raw === \"object\" && raw !== null) return logResponse(request, pathname, ctx, raw instanceof BuntokFile ? raw.toResponse(request) : Response.json(raw));\\n' +\n\t\t\t\t\t\t\"      return logResponse(request, pathname, ctx, toResponse(raw));\\n\";\n\t\t\t\t}\n\t\t\t\tcode += \"    }\\n\";\n\t\t\t}\n\t\t\tcode += \"  }\\n\";\n\t\t\tcode += \"  break;\\n\";\n\t\t\tcode += \"}\\n\";\n\t\t}\n\n\t\tcode += \"  }\\n  } catch(err) { if (!ctx) ctx = new Context(request, EMPTY_PARAMS, di, clientIPResolver); return handleError(request, pathname, ctx, err); }\\n\" + \"  return fallback(request, server);\\n\" + \"};\\n\";\n\n\t\tconst factory = new Function(\n\t\t\t\"Context\",\n\t\t\t\"EMPTY_PARAMS\",\n\t\t\t\"di\",\n\t\t\t\"handlers\",\n\t\t\t\"compiledGlobalPipeline\",\n\t\t\t\"logResponse\",\n\t\t\t\"handleError\",\n\t\t\t\"fallback\",\n\t\t\t\"wsRoutes\",\n\t\t\t\"clientIPResolver\",\n\t\t\t\"toResponse\",\n\t\t\t\"BuntokFile\",\n\t\t\t\"setPoweredBy\",\n\t\t\t\"applyCtxHeaders\",\n\t\t\tcode,\n\t\t);\n\n\t\tconst EMPTY_PARAMS = Object.freeze({});\n\t\treturn factory(\n\t\t\tContext,\n\t\t\tEMPTY_PARAMS,\n\t\t\tthis.di,\n\t\t\thandlersList,\n\t\t\tthis.compiledGlobalPipeline,\n\t\t\tthis.logResponse,\n\t\t\tthis.handleError,\n\t\t\tthis.fallbackHandleRequest.bind(this),\n\t\t\tthis.wsRoutes,\n\t\t\tthis._clientIPResolver,\n\t\t\ttoResponse,\n\t\t\tBuntokFile,\n\t\t\tthis.setPoweredBy,\n\t\t\tthis.applyCtxHeaders,\n\t\t);\n\t}\n\n\tprivate extractPathname(url: string): string {\n\t\t// Skip protocol + authority (http://localhost:1212)\n\t\tconst start = url.indexOf(\"/\", url.indexOf(\"//\") + 2);\n\t\tif (start === -1) return \"/\";\n\t\tlet end = url.indexOf(\"?\", start);\n\t\tif (end === -1) end = url.length;\n\t\treturn url.substring(start, end);\n\t}\n\n\t// Bound once per Buntok instance instead of allocating a new closure per request\n\tprivate readonly logResponse = (\n\t\trequest: Request,\n\t\tpathname: string,\n\t\tctx: Context<DI> | undefined,\n\t\tresponse: Response,\n\t): Response => {\n\t\t// Guard against undefined response from middleware chain\n\t\tif (!response) {\n\t\t\treturn new Response(\"Internal Server Error\", { status: 500 });\n\t\t}\n\t\t// Read requestId only when logging is on (avoids Headers.get per-request in prod)\n\t\tconst requestId = logger.logRequests ? request.headers.get(\"x-request-id\") : null;\n\t\tif (logger.logRequests) {\n\t\t\tconst status = response.status;\n\t\t\tconst logData = requestId ? { status, requestId } : { status };\n\t\t\tif (status >= 500) {\n\t\t\t\tlogger.error(`${request.method} ${pathname}`, logData);\n\t\t\t} else if (status >= 400) {\n\t\t\t\tlogger.warn(`${request.method} ${pathname}`, logData);\n\t\t\t} else {\n\t\t\t\tlogger.info(`${request.method} ${pathname}`, logData);\n\t\t\t}\n\t\t}\n\t\tif (this.poweredByHeaderEnabled) {\n\t\t\tresponse.headers.set(\"X-Powered-By\", \"buntok\");\n\t\t}\n\t\tif (requestId) response.headers.set(\"x-request-id\", requestId);\n\t\t// ctx.set.headers applied last - user-set headers win over built-ins\n\t\treturn this.applyCtxHeaders(ctx, response);\n\t};\n\n\t/**\n\t * Merge `ctx.set.headers` (Elysia-style mutable response headers) into the\n\t * final response. Called from every response exit point - success, error,\n\t * not-found - with a cheap guard so routes that never touch `ctx.set`\n\t * pay only a property check.\n\t */\n\tprivate readonly applyCtxHeaders = (\n\t\tctx: Context<DI> | undefined,\n\t\tresponse: Response,\n\t): Response => {\n\t\tconst headers = ctx?._set?.headers;\n\t\tlet result = response;\n\t\tif (headers) {\n\t\t\tfor (const key in headers) {\n\t\t\t\tconst value = headers[key];\n\t\t\t\tif (value === undefined || value === null) continue;\n\t\t\t\tif (key.toLowerCase() === \"set-cookie\" && Array.isArray(value)) {\n\t\t\t\t\tfor (const cookie of value) {\n\t\t\t\t\t\tresult.headers.append(key, cookie);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tresult.headers.set(key, String(value));\n\t\t\t}\n\t\t}\n\t\tif (ctx?._afterHooks) {\n\t\t\tfor (const hook of ctx._afterHooks) {\n\t\t\t\tconst out = hook(result);\n\t\t\t\tif (out) result = out;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t};\n\n\t// Lightweight X-Powered-By setter for AOT skip-log path (no logging overhead)\n\tprivate readonly setPoweredBy = (\n\t\tctx: Context<DI> | undefined,\n\t\tresponse: Response,\n\t): Response => {\n\t\tif (this.poweredByHeaderEnabled) {\n\t\t\tresponse.headers.set(\"X-Powered-By\", \"buntok\");\n\t\t}\n\t\treturn this.applyCtxHeaders(ctx, response);\n\t};\n\n\t/**\n\t * Normalize flexible handler return (string | object | null etc.) to Response.\n\t * Used by both AOT and fallback paths.\n\t */\n\tprivate normalizeReturn(\n\t\tvalue: unknown,\n\t\trequest?: Request,\n\t): Response | Promise<Response> {\n\t\tif (value instanceof Promise) {\n\t\t\treturn value.then((v) =>\n\t\t\t\ttypeof v === \"string\"\n\t\t\t\t\t? new Response(v)\n\t\t\t\t\t: v instanceof Response\n\t\t\t\t\t\t? v\n\t\t\t\t\t\t: toResponse(v, request),\n\t\t\t);\n\t\t}\n\t\tif (typeof value === \"string\") return new Response(value);\n\t\treturn value instanceof Response ? value : toResponse(value, request);\n\t}\n\n\t/**\n\t * Normalize handler return then pass through logResponse.\n\t * Handles both sync and async flexible returns.\n\t */\n\tprivate readonly logNormalized = (\n\t\trequest: Request,\n\t\tpathname: string,\n\t\tvalue: unknown,\n\t\tctx?: Context<DI> | null,\n\t): Response | Promise<Response> => {\n\t\tconst normalized = this.normalizeReturn(value, request);\n\t\tif (normalized instanceof Promise) {\n\t\t\treturn normalized.then((res) =>\n\t\t\t\tthis.logResponse(request, pathname, ctx ?? undefined, res),\n\t\t\t);\n\t\t}\n\t\treturn this.logResponse(request, pathname, ctx ?? undefined, normalized);\n\t};\n\n\tprivate readonly handleError = (\n\t\trequest: Request,\n\t\tpathname: string,\n\t\tctx: Context<DI>,\n\t\terr: unknown,\n\t): Response | Promise<Response> => {\n\t\tconst errorObj = err instanceof Error ? err : new Error(String(err));\n\t\tlogger.error(`${request.method} ${pathname}`, {\n\t\t\terror: errorObj.message,\n\t\t});\n\t\tconst result = this.customErrorHandler(errorObj, ctx);\n\t\t// Normalize ErrorHandler flexible return as well\n\t\tconst normalized = this.normalizeReturn(result, request);\n\t\tif (normalized instanceof Promise) {\n\t\t\treturn normalized.then((response) => {\n\t\t\t\tif (this.corsConfig) {\n\t\t\t\t\tconst requestOrigin =\n\t\t\t\t\t\trequest.headers.get(\"Origin\") || \"*\";\n\t\t\t\t\tapplyCorsHeaders(response, requestOrigin, this.corsConfig);\n\t\t\t\t}\n\t\t\t\tif (this.poweredByHeaderEnabled) {\n\t\t\t\t\tresponse.headers.set(\"X-Powered-By\", \"buntok\");\n\t\t\t\t}\n\t\t\t\treturn this.applyCtxHeaders(ctx, response);\n\t\t\t});\n\t\t}\n\t\tif (this.corsConfig) {\n\t\t\tconst requestOrigin = request.headers.get(\"Origin\") || \"*\";\n\t\t\tapplyCorsHeaders(normalized, requestOrigin, this.corsConfig);\n\t\t}\n\t\tif (this.poweredByHeaderEnabled) {\n\t\t\tnormalized.headers.set(\"X-Powered-By\", \"buntok\");\n\t\t}\n\t\treturn this.applyCtxHeaders(ctx, normalized);\n\t};\n\n\t/**\n\t * Dispatch a request through the app without binding to a real port.\n\t * Meant for tests: `await app.request(\"/users/1\")` is much faster than\n\t * spinning up a server and making a real HTTP call.\n\t *\n\t * Accepts the same input as the global `fetch()` / `Request` constructor.\n\t */\n\tpublic async request(\n\t\tinput: string | Request | URL,\n\t\tinit?: RequestInit,\n\t): Promise<Response> {\n\t\tconst request =\n\t\t\tinput instanceof Request && !init\n\t\t\t\t? input\n\t\t\t\t: new Request(\n\t\t\t\t\ttypeof input === \"string\" && !/^https?:\\/\\//.test(input)\n\t\t\t\t\t\t? `http://localhost${input.startsWith(\"/\") ? \"\" : \"/\"}${input}`\n\t\t\t\t\t\t: // biome-ignore lint/suspicious/noExplicitAny: Standard fetch input overriding\n\t\t\t\t\t\t(input as any),\n\t\t\t\t\tinit,\n\t\t\t\t);\n\t\treturn this._dispatch(request);\n\t}\n\n\t/**\n\t * Standard fetch handler for serverless platforms (Vercel, Cloudflare Workers, etc.).\n\t * Compiles AOT once, then dispatches straight to the router - no\n\t * `request()` indirection (input normalization + `handleRequest`).\n\t *\n\t * Usage:\n\t * ```ts\n\t * const app = new Buntok();\n\t * export default app;\n\t * ```\n\t */\n\tpublic fetch(request: Request): Response | Promise<Response> {\n\t\treturn this._dispatch(request);\n\t}\n\n\t/**\n\t * Recompile the AOT router (+ global pipeline if empty) and refresh the\n\t * native static routes on the running server.\n\t */\n\tprivate _recompileAOT(): void {\n\t\tif (!this.compiledGlobalPipeline) this.compileGlobalPipeline();\n\t\tthis._compiledAOTRouter = this.compileAOTRouter();\n\t\tthis._aotReady = true;\n\t\tif (this.server && this._serveOptions && this.isListening) {\n\t\t\tthis._serveOptions.routes = this.collectNativeStaticRoutes() ?? {};\n\t\t\tthis.server.reload({\n\t\t\t\tfetch: this._serveOptions.fetch,\n\t\t\t\troutes: this._serveOptions.routes,\n\t\t\t\t...(this._serveOptions.websocket\n\t\t\t\t\t? { websocket: this._serveOptions.websocket }\n\t\t\t\t\t: {}),\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Invalidate the AOT after configuration changes (disable/enable logger|\n\t * powered-by, setTrustedProxy, use()). When the server is already running,\n\t * recompile + reload happen IMMEDIATELY - native static routes never touch\n\t * fetch(), so lazy invalidation would never be triggered by a request.\n\t * Without a server, marking is enough; the next dispatch/listen compiles.\n\t *\n\t * @param rebuildPipeline Force a recompile of the global pipeline\n\t * (middlewares changed - `use()`).\n\t */\n\tprivate _invalidateAOT(rebuildPipeline = false): void {\n\t\tif (rebuildPipeline) this.compiledGlobalPipeline = undefined;\n\t\tif (this.server && this._serveOptions && this.isListening) {\n\t\t\tthis._recompileAOT();\n\t\t} else {\n\t\t\tthis._aotReady = false;\n\t\t}\n\t}\n\n\tprivate _dispatch(\n\t\trequest: Request,\n\t\tserver?: Server<WSData<DI>>,\n\t): Response | Promise<Response> {\n\t\tif (!this.compiledGlobalPipeline) this.compileGlobalPipeline();\n\t\t// Lazy AOT - compile once; recompile when a codegen flag changes\n\t\t// (disable/enable logger|powered-by, setTrustedProxy, use()).\n\t\tif (!this._aotReady) this._recompileAOT();\n\t\treturn this._compiledAOTRouter(request, server);\n\t}\n\n\tprivate _aotReady = false;\n\t// biome-ignore lint/suspicious/noExplicitAny: mirror opsi bag Bun.serve\n\tprivate _serveOptions: any;\n\tprivate _compiledAOTRouter: (\n\t\trequest: Request,\n\t\tserver?: Server<WSData<DI>>,\n\t) => Response | Promise<Response> = this.fallbackHandleRequest.bind(this);\n\n\tpublic handleRequest(\n\t\trequest: Request,\n\t\tserver?: Server<WSData<DI>>,\n\t): Response | Promise<Response> {\n\t\treturn this._compiledAOTRouter(request, server);\n\t}\n\n\tpublic fallbackHandleRequest(\n\t\trequest: Request,\n\t\tserver?: Server<WSData<DI>>,\n\t): Response | Promise<Response> {\n\t\tconst pathname = this.extractPathname(request.url);\n\n\t\tif (server && this.wsRoutes.size > 0) {\n\t\t\tconst wsHandler = this.wsRoutes.get(pathname);\n\t\t\tif (wsHandler) {\n\t\t\t\tconst ctx = new Context(request, {}, this.di, this._clientIPResolver) as Context<DI>;\n\t\t\t\tconst data: WSData<DI> = { ctx, handler: wsHandler };\n\t\t\t\tconst upgraded = server.upgrade(request, { data });\n\t\t\t\tif (upgraded) {\n\t\t\t\t\treturn undefined as unknown as Response;\n\t\t\t\t}\n\t\t\t\treturn new Response(\"Upgrade Required\", {\n\t\t\t\t\tstatus: 426,\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tConnection: \"Upgrade\",\n\t\t\t\t\t\tUpgrade: \"websocket\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst route = this.router.find(request.method, pathname);\n\t\tconst routeParams = route.params;\n\n\t\tlet finalHandler = route.handler as Handler<DI>;\n\t\tif (!finalHandler) {\n\t\t\tfinalHandler = this.customNotFoundHandler;\n\t\t}\n\n\t\t// Sucrose: use cached analysis from compile time (includes ctx.json detection).\n\t\t// Global middleware must also get a full Context - mirrors the\n\t\t// hasGlobalMiddleware guard on the AOT codegen path.\n\t\tconst cached = this._handlerFullContextCache.get(finalHandler);\n\t\tconst needsFullContext =\n\t\t\tthis.hasPipelineHooks || (cached ? cached.needsFullContext : true);\n\t\tconst needsParams = cached ? cached.needsParams : false;\n\t\tconst fullCtx = needsFullContext\n\t\t\t? new Context(request, routeParams, this.di, this._clientIPResolver)\n\t\t\t: null;\n\t\tconst ctxArg = fullCtx ?? (needsParams ? { request, params: routeParams } : { request, params: routeParams });\n\n\t\ttry {\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: Guaranteed by compileGlobalPipeline\n\t\t\tconst result = this.compiledGlobalPipeline!(ctxArg as Context<DI>, finalHandler);\n\n\t\t\tif (result instanceof Promise) {\n\t\t\t\treturn result\n\t\t\t\t\t.then((value) => this.logNormalized(request, pathname, value, fullCtx))\n\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\t// Ensure full Context for error handler\n\t\t\t\t\t\tconst errCtx = fullCtx ?? new Context(request, routeParams, this.di, this._clientIPResolver);\n\t\t\t\t\t\treturn this.handleError(request, pathname, errCtx, err);\n\t\t\t\t\t});\n\t\t\t}\n\t\t\treturn this.logNormalized(request, pathname, result, fullCtx);\n\t\t} catch (err) {\n\t\t\tconst errCtx = fullCtx ?? new Context(request, routeParams, this.di, this._clientIPResolver);\n\t\t\treturn this.handleError(request, pathname, errCtx, err);\n\t\t}\n\t}\n\n\t/**\n\t * Promote static-value route handlers (Elysia style: `app.get('/', 'Hi')`)\n\t * to native Bun.serve `routes` responses - Bun answers them without\n\t * entering JS (no Context, no codegen, no per-request allocation).\n\t * Returns undefined if any gate disqualifies the promotion (global\n\t * middleware, request logging, dynamic/duplicate paths, etc.).\n\t */\n\tprivate collectNativeStaticRoutes():\n\t\t| Record<string, Record<string, NativeRouteEntry>>\n\t\t| undefined {\n\t\tif (\n\t\t\tthis.router.staticRoutes.size === 0 &&\n\t\t\tthis.router.dynamicRoutes.size === 0\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\t\t// Global middleware / CORS must still run per request - run them in JS.\n\t\tif (this.hasPipelineHooks) return undefined;\n\t\t// Native responses bypass logResponse - don't silently drop request logs.\n\t\tif (logger.logRequests) return undefined;\n\n\t\tconst methods = new Set([\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"HEAD\", \"OPTIONS\"]);\n\t\tconst ready: Record<string, Record<string, NativeRouteEntry>> = Object.create(null);\n\t\tfor (const [routeKey, value] of this._staticRouteValues) {\n\t\t\tconst sep = routeKey.indexOf(\":\");\n\t\t\tconst method = routeKey.slice(0, sep);\n\t\t\tconst path = routeKey.slice(sep + 1);\n\t\t\tif (!methods.has(method)) continue;\n\t\t\t// Bun.serve rejects route paths without a leading `/` (boot crash).\n\t\t\tif (!path.startsWith(\"/\")) continue;\n\t\t\t// Bun directory routes require a trailing `/*` splat - exempt them\n\t\t\t// from the splat skip below (the JS fallback handles `:`/`{` cases).\n\t\t\tconst isDir = isDirRouteValue(value);\n\t\t\tif (isDir) {\n\t\t\t\tif (!path.endsWith(\"/*\") || path.includes(\":\") || path.includes(\"{\")) continue;\n\t\t\t} else if (path.includes(\"*\") || path.includes(\"{\")) {\n\t\t\t\t// Splat & `{}` patterns stay on fetch() - Bun's match semantics\n\t\t\t\t// for them can differ segment-for-segment from the FFI trie.\n\t\t\t\t// `:param` paths ARE promoted for constant values: the response\n\t\t\t\t// never reads the param, so raw-vs-decoded can't diverge.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (this.wsRoutes.has(path)) continue;\n\t\t\t// BunFile / directory values can't carry X-Powered-By - keep the JS\n\t\t\t// handler so the wire stays identical when the flag is enabled.\n\t\t\tif (this.poweredByHeaderEnabled && (isDir || value instanceof Blob)) continue;\n\t\t\tconst response = this.materializeStatic(value);\n\t\t\t// Bake failed (e. status outside the Response range) → don't drop\n\t\t\t// the route: the JS path stays registered and handles the request.\n\t\t\tif (!response) continue;\n\t\t\t(ready[path] ??= Object.create(null))[method] = response;\n\t\t}\n\t\t// Param-dependent handlers: Bun matches `:segments` in C++, the closure\n\t\t// below runs the identical JS the fallback dispatch would run.\n\t\tfor (const [path, methodMap] of this.router.dynamicRoutes) {\n\t\t\tif (!path.startsWith(\"/\")) continue;\n\t\t\t// Splat/`{}` match semantics stay on fetch() (see above); ws paths\n\t\t\t// must reach the upgrade handshake in fetch().\n\t\t\tif (path.includes(\"*\") || path.includes(\"{\")) continue;\n\t\t\tif (this.wsRoutes.has(path)) continue;\n\t\t\tfor (const [method, handler] of methodMap) {\n\t\t\t\tif (!methods.has(method)) continue;\n\t\t\t\tconst key = `${method}:${path}`;\n\t\t\t\t// A constant value on this pattern (registered above) is cheaper\n\t\t\t\t// - zero JS. Also covers failed bakes: they stay on the JS path.\n\t\t\t\tif (this._staticRouteValues.has(key)) continue;\n\t\t\t\t(ready[path] ??= Object.create(null))[method] =\n\t\t\t\t\tthis.makeNativeDynamicHandler(path, handler);\n\t\t\t}\n\t\t}\n\t\t// Static function handlers (e.g. `app.post(\"/json\", async (c) => …)`):\n\t\t// Bun matches the exact path in C++ and the closure runs the same JS\n\t\t// the AOT codegen would run - minus the pathname parse and the\n\t\t// method/path switch. Constant values were handled by the first loop\n\t\t// (`_staticRouteValues` keys are skipped); `{}` patterns and splats\n\t\t// keep their fetch() semantics (see the static-value loop above).\n\t\tfor (const [path, methodMap] of this.router.staticRoutes) {\n\t\t\tif (!path.startsWith(\"/\")) continue;\n\t\t\tif (path.includes(\"*\") || path.includes(\"{\")) continue;\n\t\t\tif (this.wsRoutes.has(path)) continue;\n\t\t\tfor (const [method, handler] of methodMap) {\n\t\t\t\tif (!methods.has(method)) continue;\n\t\t\t\tconst key = `${method}:${path}`;\n\t\t\t\t// A constant value on this route (registered above) is cheaper -\n\t\t\t\t// zero JS. Also covers skipped bakes (BunFile + x-powered-by…).\n\t\t\t\tif (this._staticRouteValues.has(key)) continue;\n\t\t\t\t(ready[path] ??= Object.create(null))[method] =\n\t\t\t\t\tthis.makeNativeStaticHandler(handler);\n\t\t\t}\n\t\t}\n\t\treturn Object.keys(ready).length > 0 ? ready : undefined;\n\t}\n\n\t/**\n\t * Build the native route handler for a `:param` path. The response tail is\n\t * an inline mirror of `normalizeReturn` + `logResponse` with request\n\t * logging off (a collect gate), so the wire is byte-identical to the JS\n\t * fallback while skipping three call layers per request:\n\t *\n\t * - no `compiledGlobalPipeline` indirection (gates guarantee zero global\n\t *   middleware → the pipeline is identity; `use()` recompiles + reloads,\n\t *   which drops this route);\n\t * - no pathname parsing on the success path - Bun already split the path\n\t *   into `request.params`, and `decodeURIComponent` is the identity on\n\t *   percent-free URLs, so raw === decoded there. URLs containing `%` take\n\t *   the slow path (parse + split + raw capture - FFI-trie parity);\n\t * - inline normalize+tail instead of `normalizeReturn` → `logResponse` →\n\t *   `applyCtxHeaders` calls (same branches, same order, same output).\n\t *\n\t * Unmatched methods/paths fall through to `fetch()` → `_dispatch()`.\n\t */\n\tprivate makeNativeDynamicHandler(\n\t\tpath: string,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: same shape the router stores\n\t\thandler: (...args: any[]) => any,\n\t): NativeDynamicHandler {\n\t\t// Precompute raw-capture segments for percent-encoded URLs\n\t\t// (`/u/:uid/p/:pid` → [{2,\"uid\"},{4,\"pid\"}]; split indices align with\n\t\t// pathname.split(\"/\") because both include the leading \"\" element).\n\t\tconst patternSegments = path.split(\"/\");\n\t\tconst paramSpec: Array<{ seg: number; name: string }> = [];\n\t\tfor (let i = 0; i < patternSegments.length; i++) {\n\t\t\tconst seg = patternSegments[i];\n\t\t\tif (seg && seg.length > 1 && seg.charCodeAt(0) === 58 /* ':' */) {\n\t\t\t\tparamSpec.push({ seg: i, name: seg.slice(1) });\n\t\t\t}\n\t\t}\n\t\t// Sucrose decision - mirrors the fallback (`_dispatch`) exactly: cache\n\t\t// keyed by the object the router stores (mw chain or raw handler).\n\t\tconst cached = this._handlerFullContextCache.get(handler);\n\t\tconst needsFullContext = cached ? cached.needsFullContext : true;\n\t\tconst needsSetHeaders = cached ? cached.needsSetHeaders : true;\n\t\t// Baked like static values: flag toggles trigger _recompileAOT() →\n\t\t// collect() re-runs → this closure is rebuilt with the new flag.\n\t\tconst xpb = this.poweredByHeaderEnabled;\n\n\t\t// Raw pathname (error path only - success never logs when the gate is\n\t\t// off, so it does not need `pathname`).\n\t\tconst parsePathname = (request: Request): string => {\n\t\t\tconst url = request.url;\n\t\t\tlet start = url.indexOf(\"/\", url.indexOf(\"//\") + 2);\n\t\t\tif (start === -1) start = url.length;\n\t\t\tlet end = url.indexOf(\"?\", start);\n\t\t\tif (end === -1) end = url.length;\n\t\t\treturn start === url.length ? \"/\" : url.substring(start, end);\n\t\t};\n\n\t\tconst rawParams = (request: Request): Record<string, string> => {\n\t\t\t// Percent-free URLs: Bun's split == raw split (decode is identity).\n\t\t\tconst url = request.url;\n\t\t\tif (!url.includes(\"%\")) {\n\t\t\t\t// Bun attaches decoded params to the Request in route handlers.\n\t\t\t\tconst bunParams = (request as Request & {\n\t\t\t\t\tparams?: Record<string, string>;\n\t\t\t\t}).params;\n\t\t\t\treturn bunParams ? { ...bunParams } : {};\n\t\t\t}\n\t\t\t// Percent-encoded: re-split the raw pathname - the FFI trie\n\t\t\t// captures without decoding (unlike Bun's req.params).\n\t\t\tconst pathname = parsePathname(request);\n\t\t\tconst parts = pathname.split(\"/\");\n\t\t\tconst params: Record<string, string> = {};\n\t\t\tfor (let i = 0; i < paramSpec.length; i++) {\n\t\t\t\tconst spec = paramSpec[i];\n\t\t\t\tif (spec) params[spec.name] = parts[spec.seg] ?? \"\";\n\t\t\t}\n\t\t\treturn params;\n\t\t};\n\n\t\t// Inline mirror of normalizeReturn(v) + logResponse(...) with\n\t\t// logRequests=false: same string/Response/toResponse branches, then\n\t\t// X-Powered-By, then ctx.set.headers - nothing else runs with the\n\t\t// logging gate off (requestId reads and log lines are logRequests-only).\n\t\tconst finish = (\n\t\t\tv: unknown,\n\t\t\trequest: Request,\n\t\t\tfullCtx: Context<DI> | null,\n\t\t): Response => {\n\t\t\tconst res =\n\t\t\t\ttypeof v === \"string\"\n\t\t\t\t\t? new Response(v)\n\t\t\t\t\t: v instanceof Response\n\t\t\t\t\t\t? v\n\t\t\t\t\t\t: toResponse(v, request);\n\t\t\tif (xpb) res.headers.set(\"X-Powered-By\", \"buntok\");\n\t\t\t// logResponse calls applyCtxHeaders(ctx ?? undefined) unconditionally;\n\t\t\t// with no full Context the guard is a property check → equivalent to\n\t\t\t// skipping it. Sucrose-proven no-ctx.set writers skip the merge\n\t\t\t// entirely - needsFullContext handlers may have set ctx.set.headers.\n\t\t\tif (needsSetHeaders && needsFullContext && fullCtx) {\n\t\t\t\treturn this.applyCtxHeaders(fullCtx, res);\n\t\t\t}\n\t\t\treturn res;\n\t\t};\n\n\t\treturn (request: Request): Response | Promise<Response> => {\n\t\t\tconst fullCtx = needsFullContext\n\t\t\t\t? new Context(request, rawParams(request), this.di, this._clientIPResolver)\n\t\t\t\t: null;\n\t\t\tconst params = fullCtx ? fullCtx.params : rawParams(request);\n\t\t\tconst ctxArg = fullCtx ?? { request, params };\n\t\t\ttry {\n\t\t\t\t// No global middleware (collect gate) → pipeline is identity.\n\t\t\t\tconst raw = handler(ctxArg);\n\t\t\t\tif (raw instanceof Promise) {\n\t\t\t\t\treturn raw\n\t\t\t\t\t\t.then((v: unknown) => finish(v, request, fullCtx))\n\t\t\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\t\t\tconst errCtx =\n\t\t\t\t\t\t\t\tfullCtx ??\n\t\t\t\t\t\t\t\tnew Context(\n\t\t\t\t\t\t\t\t\trequest,\n\t\t\t\t\t\t\t\t\trawParams(request),\n\t\t\t\t\t\t\t\t\tthis.di,\n\t\t\t\t\t\t\t\t\tthis._clientIPResolver,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn this.handleError(request, parsePathname(request), errCtx, err);\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn finish(raw, request, fullCtx);\n\t\t\t} catch (err) {\n\t\t\t\tconst errCtx =\n\t\t\t\t\tfullCtx ??\n\t\t\t\t\tnew Context(\n\t\t\t\t\t\trequest,\n\t\t\t\t\t\trawParams(request),\n\t\t\t\t\t\tthis.di,\n\t\t\t\t\t\tthis._clientIPResolver,\n\t\t\t\t\t);\n\t\t\t\treturn this.handleError(request, parsePathname(request), errCtx, err);\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Build the native route handler for a static (parameter-free) path - the\n\t * function-handler sibling of constant-value promotion. Same gates and\n\t * the same response tail as `makeNativeDynamicHandler`, minus all param\n\t * handling: the FFI trie yields `{}` params on static paths, so the\n\t * closure shares one frozen empty object (AOT codegen parity - see\n\t * `EMPTY_PARAMS` in `compileAOTRouter`).\n\t *\n\t * This is what keeps function routes like\n\t * `app.post(\"/json\", async (ctx) => ctx.json(await ctx.body()))` off the\n\t * `fetch()` → `_dispatch()` path: Bun matches the exact path in C++ and\n\t * the closure runs the same JS the AOT codegen would run - minus the\n\t * pathname parse and the method/path switch.\n\t *\n\t * Unmatched methods fall through to `fetch()` → `_dispatch()`.\n\t */\n\tprivate makeNativeStaticHandler(\n\t\t// biome-ignore lint/suspicious/noExplicitAny: same shape the router stores\n\t\thandler: (...args: any[]) => any,\n\t): NativeDynamicHandler {\n\t\t// Sucrose decision - same cache as the fallback/AOT paths (unknown or\n\t\t// middleware-chain handlers default to the conservative true).\n\t\tconst cached = this._handlerFullContextCache.get(handler);\n\t\tconst needsFullContext = cached ? cached.needsFullContext : true;\n\t\tconst needsSetHeaders = cached ? cached.needsSetHeaders : true;\n\t\t// Baked like static values: flag toggles trigger _recompileAOT() →\n\t\t// collect() re-runs → this closure is rebuilt with the new flag.\n\t\tconst xpb = this.poweredByHeaderEnabled;\n\t\t// Shared per closure - params are always `{}` on a static path;\n\t\t// frozen mirrors the AOT codegen's EMPTY_PARAMS.\n\t\tconst EMPTY_PARAMS: Record<string, string> = Object.freeze({});\n\n\t\t// Raw pathname (error path only - the success path never needs it:\n\t\t// logging is off by the collect gate and static paths have no params).\n\t\tconst parsePathname = (request: Request): string => {\n\t\t\tconst url = request.url;\n\t\t\tlet start = url.indexOf(\"/\", url.indexOf(\"//\") + 2);\n\t\t\tif (start === -1) start = url.length;\n\t\t\tlet end = url.indexOf(\"?\", start);\n\t\t\tif (end === -1) end = url.length;\n\t\t\treturn start === url.length ? \"/\" : url.substring(start, end);\n\t\t};\n\n\t\t// Inline mirror of normalizeReturn(v) + logResponse(...) with\n\t\t// logRequests=false: same string/Response/toResponse branches, then\n\t\t// X-Powered-By, then (only when sucrose allows) ctx.set.headers.\n\t\tconst finish = (\n\t\t\tv: unknown,\n\t\t\trequest: Request,\n\t\t\tfullCtx: Context<DI> | null,\n\t\t): Response => {\n\t\t\tconst res =\n\t\t\t\ttypeof v === \"string\"\n\t\t\t\t\t? new Response(v)\n\t\t\t\t\t: v instanceof Response\n\t\t\t\t\t\t? v\n\t\t\t\t\t\t: toResponse(v, request);\n\t\t\tif (xpb) res.headers.set(\"X-Powered-By\", \"buntok\");\n\t\t\tif (needsSetHeaders && fullCtx) {\n\t\t\t\treturn this.applyCtxHeaders(fullCtx, res);\n\t\t\t}\n\t\t\treturn res;\n\t\t};\n\n\t\treturn (request: Request): Response | Promise<Response> => {\n\t\t\tconst fullCtx = needsFullContext\n\t\t\t\t? new Context(request, EMPTY_PARAMS, this.di, this._clientIPResolver)\n\t\t\t\t: null;\n\t\t\tconst ctxArg = fullCtx ?? { request, params: EMPTY_PARAMS };\n\t\t\ttry {\n\t\t\t\t// No global middleware (collect gate) → pipeline is identity.\n\t\t\t\tconst raw = handler(ctxArg);\n\t\t\t\tif (raw instanceof Promise) {\n\t\t\t\t\treturn raw\n\t\t\t\t\t\t.then((v: unknown) => finish(v, request, fullCtx))\n\t\t\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\t\t\tconst errCtx =\n\t\t\t\t\t\t\t\tfullCtx ??\n\t\t\t\t\t\t\t\tnew Context(\n\t\t\t\t\t\t\t\t\trequest,\n\t\t\t\t\t\t\t\t\tEMPTY_PARAMS,\n\t\t\t\t\t\t\t\t\tthis.di,\n\t\t\t\t\t\t\t\t\tthis._clientIPResolver,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn this.handleError(request, parsePathname(request), errCtx, err);\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn finish(raw, request, fullCtx);\n\t\t\t} catch (err) {\n\t\t\t\tconst errCtx =\n\t\t\t\t\tfullCtx ??\n\t\t\t\t\tnew Context(request, EMPTY_PARAMS, this.di, this._clientIPResolver);\n\t\t\t\treturn this.handleError(request, parsePathname(request), errCtx, err);\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Materialize a static value into a native route value - exactly mirroring\n\t * the branches the original handler runs per request:\n\t *\n\t * - string handler       → ct `text/plain;charset=utf-8` (Elysia parity)\n\t * - `ctx.text`           → 200 without explicit ct / non-200 `text/plain; charset=utf-8`\n\t * - `ctx.html`           → `text/html` + status always\n\t * - `ctx.json` / bare `{…}`/`[…]` → `Response.json(data[, { status }])`\n\t * - bare `42` / `true`   → `text/plain; charset=utf-8` (toResponse parity)\n\t * - bare `null`          → 204 No Content\n\t * - `BunFile` / `{ dir }` → passed through untouched (opaque to X-Powered-By;\n\t *   collect() skips them while the flag is enabled)\n\t *\n\t * Returns undefined if the bake fails → caller skips (the JS path handles\n\t * it). X-Powered-By reads the `poweredByHeaderEnabled` flag (the only flag\n\t * that can change after registration; always re-read at collect time).\n\t */\n\tprivate materializeStatic(\n\t\tvalue: string | NativeRouteValue | ConstResponseOp,\n\t): NativeRouteValue | undefined {\n\t\tconst xpb = this.poweredByHeaderEnabled;\n\t\ttry {\n\t\t\tif (value instanceof Response) return value;\n\t\t\t// BunFile (opaque native value) - no per-response headers possible.\n\t\t\tif (value instanceof Blob) return value;\n\t\t\tif (isDirRouteValue(value)) return value;\n\t\t\tif (typeof value === \"string\") {\n\t\t\t\treturn new Response(value, {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Type\": \"text/plain;charset=utf-8\",\n\t\t\t\t\t\t...(xpb ? { \"X-Powered-By\": \"buntok\" } : {}),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\tlet response: Response;\n\t\t\tswitch (value.kind) {\n\t\t\t\tcase \"string\":\n\t\t\t\t\tresponse = new Response(value.body, {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"text/plain;charset=utf-8\",\n\t\t\t\t\t\t\t...(xpb ? { \"X-Powered-By\": \"buntok\" } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"scalar\":\n\t\t\t\t\t// mirrors toResponse (src/helpers/response.ts:18) - spaced charset\n\t\t\t\t\tresponse = new Response(value.body, {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"text/plain; charset=utf-8\",\n\t\t\t\t\t\t\t...(xpb ? { \"X-Powered-By\": \"buntok\" } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"empty\":\n\t\t\t\t\t// mirrors toResponse(null) → 204 without body/content-type\n\t\t\t\t\tresponse = new Response(null, { status: 204 });\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"text\":\n\t\t\t\t\t// mirrors Context.text (src/context.ts:301): 200 without explicit ct\n\t\t\t\t\tresponse = value.status === 200\n\t\t\t\t\t\t? new Response(value.body)\n\t\t\t\t\t\t: new Response(value.body, {\n\t\t\t\t\t\t\tstatus: value.status,\n\t\t\t\t\t\t\theaders: { \"Content-Type\": \"text/plain; charset=utf-8\" },\n\t\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"html\":\n\t\t\t\t\tresponse = new Response(value.body, {\n\t\t\t\t\t\tstatus: value.status,\n\t\t\t\t\t\theaders: { \"Content-Type\": \"text/html\" },\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"json\":\n\t\t\t\t\tresponse = value.status === 200\n\t\t\t\t\t\t? Response.json(value.data)\n\t\t\t\t\t\t: Response.json(value.data, { status: value.status });\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (xpb) response.headers.set(\"X-Powered-By\", \"buntok\");\n\t\t\treturn response;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tpublic listen(port?: number, callback?: () => void): void {\n\t\t// Skip server startup when running under make:docs or when a CLI\n\t\t// command imports the entry point just to inspect it (debug:routes)\n\t\tif (process.env.BUNTOK_DOCS_BUILD === \"1\") return;\n\t\tif (process.env.BUNTOK_CLI_NO_LISTEN === \"1\") return;\n\t\tif (this.isListening) return;\n\t\tthis.isListening = true;\n\n\t\tconst startTime = performance.now();\n\n\t\t// Register API docs routes directly on router (bypasses openApiDocs)\n\t\tif (this._apiDocsConfig) {\n\t\t\tconst isProduction = process.env.NODE_ENV === \"production\";\n\t\t\tif (!(this._apiDocsConfig.safeOnProduction && isProduction)) {\n\t\t\t\tthis.registerApiDocsRoutes();\n\t\t\t}\n\t\t}\n\n\t\t// Perform AOT compilation for global middlewares\n\t\tthis.compileGlobalPipeline();\n\t\tthis._compiledAOTRouter = this.compileAOTRouter();\n\t\tthis._aotReady = true;\n\n\t\t// Background generate swagger.json (non-blocking, only affects startup)\n\t\tif (this._apiDocsConfig) {\n\t\t\tconst docsConfig = this._apiDocsConfig;\n\t\t\tconst openApiDocs = this.openApiDocs;\n\t\t\tsetImmediate(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst { generateOpenApiDocument } = await import(\"./helpers/openapi\");\n\t\t\t\t\tconst doc = generateOpenApiDocument({\n\t\t\t\t\t\topenApiDocs,\n\t\t\t\t\t\ttitle: docsConfig.title,\n\t\t\t\t\t\tversion: docsConfig.version,\n\t\t\t\t\t\tdescription: docsConfig.description,\n\t\t\t\t\t});\n\t\t\t\t\tif (doc) {\n\t\t\t\t\t\tthis._swaggerDocument = doc;\n\t\t\t\t\t\t// Write to disk for backward compat (make:docs, external tools)\n\t\t\t\t\t\tconst docsDir = join(process.cwd(), \"public/docs\");\n\t\t\t\t\t\tmkdirSync(docsDir, { recursive: true });\n\t\t\t\t\t\twriteFileSync(\n\t\t\t\t\t\t\tjoin(docsDir, \"swagger.json\"),\n\t\t\t\t\t\t\tJSON.stringify(doc, null, 2),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlogger.error(\"Failed to generate swagger.json\", {\n\t\t\t\t\t\terror: (err as Error).message,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tconst finalPort = port || Number(process.env.PORT) || 1212;\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Required for bun serve signature compatibility\n\t\tconst serveOptions: any = {\n\t\t\tport: finalPort,\n\t\t\t// Stable trampoline: Bun.serve captures the fetch reference at start,\n\t\t\t// so dispatch reads the latest `_compiledAOTRouter` field per request\n\t\t\t// - recompiles (flag toggles, setTrustedProxy) still apply post-listen.\n\t\t\tfetch: (request: Request, server: Server<WSData<DI>>) =>\n\t\t\t\tthis._dispatch(request, server),\n\t\t};\n\n\t\tif (this._reusePort) {\n\t\t\tserveOptions.reusePort = true;\n\t\t}\n\n\t\tif (this.wsRoutes.size > 0) {\n\t\t\tserveOptions.websocket = {\n\t\t\t\t// Bun-only native options - pluggable, zero-deps\n\t\t\t\tperMessageDeflate: this.wsOpts.perMessageDeflate ?? false,\n\t\t\t\tmaxPayloadLength: this.wsOpts.maxPayloadLength ?? 16 * 1024 * 1024,\n\t\t\t\tidleTimeout: this.wsOpts.idleTimeout ?? 120,\n\t\t\t\tmaxBackpressure: this.wsOpts.maxBackpressure,\n\t\t\t\tpublishToSelf: this.wsOpts.publishToSelf ?? false,\n\t\t\t\topen: async (ws: ServerWebSocket<WSData<DI>>) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (ws.data.handler.authenticate) {\n\t\t\t\t\t\t\tconst authData = await ws.data.handler.authenticate(ws);\n\t\t\t\t\t\t\tif (authData === null) {\n\t\t\t\t\t\t\t\tws.close(4001, \"Unauthorized\");\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t(ws.data as unknown as Record<string, unknown>).auth = authData;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tws.data.handler.open?.(ws);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tlogger.error(\"WS open error\", { error: (err as Error).message });\n\t\t\t\t\t\ttry { ws.close(1011, \"Internal error\"); } catch { }\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmessage: (\n\t\t\t\t\tws: ServerWebSocket<WSData<DI>>,\n\t\t\t\t\tmessage: string | Buffer,\n\t\t\t\t) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tws.data.handler.message?.(ws, message);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tlogger.error(\"WS message error\", { error: (err as Error).message });\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tclose: (\n\t\t\t\t\tws: ServerWebSocket<WSData<DI>>,\n\t\t\t\t\tcode: number,\n\t\t\t\t\treason: string,\n\t\t\t\t) => {\n\t\t\t\t\ttry { ws.data.handler.close?.(ws, code, reason); } catch (err) {\n\t\t\t\t\t\tlogger.error(\"WS close error\", { error: (err as Error).message });\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tdrain: (ws: ServerWebSocket<WSData<DI>>) => {\n\t\t\t\t\ttry { ws.data.handler.drain?.(ws); } catch { }\n\t\t\t\t},\n\t\t\t\tpong: (ws: ServerWebSocket<WSData<DI>>) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// heartbeat pong - reset alive (fix: pong is not a message)\n\t\t\t\t\t\t(ws.data.handler as unknown as { pong?: (ws: ServerWebSocket<WSData<DI>>) => void }).pong?.(ws);\n\t\t\t\t\t\t// also a fallback for wsHeartbeat attached on ws.data\n\t\t\t\t\t\tconst hb = (ws.data as unknown as { heartbeat?: { alive: boolean } }).heartbeat;\n\t\t\t\t\t\tif (hb) hb.alive = true;\n\t\t\t\t\t} catch { }\n\t\t\t\t},\n\t\t\t} as unknown as Record<string, unknown>;\n\t\t}\n\n\t\t// Promote static-value handlers to native Bun.serve routes - computed\n\t\t// once here, recomputed on AOT recompile (see _dispatch).\n\t\tthis._serveOptions = serveOptions;\n\t\tconst nativeStaticRoutes = this.collectNativeStaticRoutes();\n\t\tif (nativeStaticRoutes) serveOptions.routes = nativeStaticRoutes;\n\n\t\t// Auto-increment port if already in use\n\t\tlet currentPort = finalPort;\n\t\tconst maxRetries = 10;\n\t\tfor (let attempt = 0; attempt < maxRetries; attempt++) {\n\t\t\ttry {\n\t\t\t\tserveOptions.port = currentPort;\n\t\t\t\tthis.server = Bun.serve<WSData<DI>>(serveOptions);\n\t\t\t\tbreak;\n\t\t\t} catch (err: any) {\n\t\t\t\tif (err?.code === \"EADDRINUSE\" && attempt < maxRetries - 1) {\n\t\t\t\t\tconst originalPort = currentPort;\n\t\t\t\t\tcurrentPort++;\n\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t`⚠ Port ${originalPort} is already in use, using port ${currentPort} instead`,\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}\n\n\t\t// Setup graceful shutdown handlers\n\t\tthis.setupGracefulShutdown();\n\n\t\tconst startupTime = Math.round(performance.now() - startTime);\n\t\tconst env = process.env.NODE_ENV || \"development\";\n\t\t// Startup banner mengikuti toggle logger - app.disable(\"logger\")\n\t\t// membuat terminal sunyi total selama development.\n\t\tif (logger.enabled) {\n\t\t\tconsole.log(\n\t\t\t\t`\\n  \\x1b[36mBuntok v${VERSION}\\x1b[0m ready in \\x1b[32m${startupTime}ms\\x1b[0m\\n`,\n\t\t\t);\n\t\t\tconsole.log(`  Environment: \\x1b[33m${env}\\x1b[0m`);\n\t\t\tconsole.log(`  Listening on: \\x1b[36mhttp://localhost:${currentPort}\\x1b[0m`);\n\t\t\tif (this._apiDocsConfig) {\n\t\t\t\tconst docsPath = (this._apiDocsConfig.path ?? \"/docs\").replace(/\\/+$/, \"\");\n\t\t\t\tconsole.log(`  Docs:         \\x1b[36mhttp://localhost:${currentPort}${docsPath}/\\x1b[0m`);\n\t\t\t}\n\t\t\tconsole.log();\n\t\t}\n\n\t\tfor (const hook of this.startHooks) {\n\t\t\ttry {\n\t\t\t\tconst out = hook();\n\t\t\t\tif (out instanceof Promise) {\n\t\t\t\t\tout.catch((error) =>\n\t\t\t\t\t\tlogger.error(\"onStart hook failed\", {\n\t\t\t\t\t\t\terror: (error as Error).message,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"onStart hook failed\", {\n\t\t\t\t\terror: (error as Error).message,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (callback) callback();\n\t}\n\n\t/** Stop accepting traffic and release resources owned by this app. */\n\tpublic close(options: { timeout?: number; force?: boolean } = {}): Promise<void> {\n\t\tif (this.shutdownPromise) return this.shutdownPromise;\n\n\t\tconst timeout = options.timeout ?? this.shutdownTimeout;\n\t\tthis.shutdownPromise = (async () => {\n\t\t\tthis.removeSignalHandlers();\n\t\t\tif (!this.server) {\n\t\t\t\tthis.isListening = false;\n\t\t\t\tawait this.closeResources(timeout);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst server = this.server;\n\t\t\tthis.server = undefined;\n\t\t\tthis.isListening = false;\n\t\t\tlet timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n\t\t\ttry {\n\t\t\t\tconst stopped = await Promise.race([\n\t\t\t\t\tPromise.resolve(server.stop(false)).then(() => true),\n\t\t\t\t\tnew Promise<boolean>((resolve) => {\n\t\t\t\t\t\ttimeoutHandle = setTimeout(() => resolve(false), timeout);\n\t\t\t\t\t}),\n\t\t\t\t]);\n\t\t\t\tif (!stopped && options.force) server.stop(true);\n\t\t\t} finally {\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t}\n\t\t\tawait this.closeResources(timeout);\n\t\t})().catch((error) => {\n\t\t\tthis.shutdownPromise = undefined;\n\t\t\tthrow error;\n\t\t});\n\n\t\treturn this.shutdownPromise;\n\t}\n\n\tprivate async closeResources(timeout: number): Promise<void> {\n\t\tconst deadline = Date.now() + timeout;\n\t\tfor (const resource of this.resources) {\n\t\t\tconst remaining = deadline - Date.now();\n\t\t\tif (remaining <= 0) break;\n\t\t\tawait Promise.race([\n\t\t\t\t(resource.close ?? resource.dispose)?.(),\n\t\t\t\tnew Promise<void>((resolve) => setTimeout(resolve, remaining)),\n\t\t\t]);\n\t\t}\n\t\tthis.resources.clear();\n\t\tfor (const dispose of this.pluginDisposers.values()) {\n\t\t\tconst remaining = deadline - Date.now();\n\t\t\tif (remaining <= 0) break;\n\t\t\tawait Promise.race([\n\t\t\t\tdispose(this),\n\t\t\t\tnew Promise<void>((resolve) => setTimeout(resolve, remaining)),\n\t\t\t]);\n\t\t}\n\t\tthis.pluginDisposers.clear();\n\t\tfor (const hook of this.stopHooks) {\n\t\t\ttry {\n\t\t\t\tawait hook();\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"onStop hook failed\", {\n\t\t\t\t\terror: (error as Error).message,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Alias for close(), kept for hosts that use shutdown terminology. */\n\tpublic shutdown(options: { timeout?: number; force?: boolean } = {}): Promise<void> {\n\t\treturn this.close(options);\n\t}\n\n\t/**\n\t * Setup graceful shutdown handlers for SIGTERM and SIGINT signals.\n\t * When a signal is received, the server stops accepting new connections,\n\t * waits for in-flight requests to complete, then exits cleanly.\n\t */\n\tprivate setupGracefulShutdown(): void {\n\t\tif (!this.handleSignals || this.signalHandlers) return;\n\n\t\tconst shutdown = async (signal: string) => {\n\t\t\tlogger.info(`\\n${signal} received. Starting graceful shutdown...`);\n\t\t\tawait this.close();\n\t\t\tlogger.info(\"Server shut down gracefully\");\n\t\t\tprocess.exit(0);\n\t\t};\n\n\t\tconst signals = [\"SIGTERM\", \"SIGINT\"] as const;\n\t\tthis.signalHandlers = signals.map((signal) => {\n\t\t\tconst handler = () => { shutdown(signal).catch(() => process.exit(1)); };\n\t\t\tprocess.on(signal, handler);\n\t\t\treturn { signal, handler };\n\t\t});\n\t}\n\n\tprivate removeSignalHandlers(): void {\n\t\tfor (const { signal, handler } of this.signalHandlers ?? []) {\n\t\t\tprocess.off(signal, handler);\n\t\t}\n\t\tthis.signalHandlers = undefined;\n\t}\n}\n\nexport class RouterGroup<\n\tDI extends Record<string, unknown> = Record<string, unknown>,\n> {\n\tprivate prefix: string;\n\tprivate app: Buntok<DI>;\n\tprivate groupMiddlewares: Middleware<DI>[] = [];\n\n\tconstructor(prefix: string, app: Buntok<DI>) {\n\t\tthis.prefix = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n\t\tthis.app = app;\n\t}\n\n\tpublic use(middleware: Middleware<DI>): this {\n\t\tthis.groupMiddlewares.push(middleware);\n\t\treturn this;\n\t}\n\n\tpublic group(prefix: string): RouterGroup<DI> {\n\t\tconst newGroup = new RouterGroup<DI>(this.prefix + prefix, this.app);\n\t\tnewGroup.groupMiddlewares = [...this.groupMiddlewares];\n\t\treturn newGroup;\n\t}\n\n\tprivate normalizePath(path: string): string {\n\t\tconst cleanPath = path === \"/\" ? \"\" : path;\n\t\treturn `${this.prefix}${cleanPath}`;\n\t}\n\n\tpublic get<Path extends string>(path: Path, handler: Handler<DI, Path> | string | Response): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.app.registerRoute(\"GET\", this.normalizePath(path), [\n\t\t\t...this.groupMiddlewares,\n\t\t\t...handlers,\n\t\t], { source: \"group\", group: this.prefix });\n\t\treturn this;\n\t}\n\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.app.registerRoute(\"POST\", this.normalizePath(path), [\n\t\t\t...this.groupMiddlewares,\n\t\t\t...handlers,\n\t\t], { source: \"group\", group: this.prefix });\n\t\treturn this;\n\t}\n\n\tpublic put<Path extends string>(path: Path, handler: Handler<DI, Path> | string | Response): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.app.registerRoute(\"PUT\", this.normalizePath(path), [\n\t\t\t...this.groupMiddlewares,\n\t\t\t...handlers,\n\t\t], { source: \"group\", group: this.prefix });\n\t\treturn this;\n\t}\n\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.app.registerRoute(\"DELETE\", this.normalizePath(path), [\n\t\t\t...this.groupMiddlewares,\n\t\t\t...handlers,\n\t\t], { source: \"group\", group: this.prefix });\n\t\treturn this;\n\t}\n\n\t// QUERY method - like GET but with body support\n\tpublic query(path: string, handler: Handler<DI>): this;\n\tpublic query(\n\t\tpath: string,\n\t\tmiddleware: Middleware<DI>,\n\t\thandler: Handler<DI>,\n\t): this;\n\tpublic query(\n\t\tpath: string,\n\t\tm1: Middleware<DI>,\n\t\tm2: Middleware<DI>,\n\t\thandler: Handler<DI>,\n\t): this;\n\tpublic query(\n\t\tpath: string,\n\t\tm1: Middleware<DI>,\n\t\tm2: Middleware<DI>,\n\t\tm3: Middleware<DI>,\n\t\thandler: Handler<DI>,\n\t): this;\n\tpublic query(\n\t\tpath: string,\n\t\tm1: Middleware<DI>,\n\t\tm2: Middleware<DI>,\n\t\tm3: Middleware<DI>,\n\t\tm4: Middleware<DI>,\n\t\thandler: Handler<DI>,\n\t): this;\n\tpublic query(\n\t\tpath: string,\n\t\tm1: Middleware<DI>,\n\t\tm2: Middleware<DI>,\n\t\tm3: Middleware<DI>,\n\t\tm4: Middleware<DI>,\n\t\tm5: Middleware<DI>,\n\t\thandler: Handler<DI>,\n\t): this;\n\tpublic query(\n\t\tpath: string,\n\t\t...handlers: Array<Middleware<DI> | Handler<DI>>\n\t): this {\n\t\tthis.app.registerRoute(\"QUERY\", this.normalizePath(path), [\n\t\t\t...this.groupMiddlewares,\n\t\t\t...handlers,\n\t\t], { source: \"group\", group: this.prefix });\n\t\treturn this;\n\t}\n\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.app.registerRoute(\"OPTIONS\", this.normalizePath(path), [\n\t\t\t...this.groupMiddlewares,\n\t\t\t...handlers,\n\t\t], { source: \"group\", group: this.prefix });\n\t\treturn this;\n\t}\n\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.app.registerRoute(\"PATCH\", this.normalizePath(path), [\n\t\t\t...this.groupMiddlewares,\n\t\t\t...handlers,\n\t\t], { source: \"group\", group: this.prefix });\n\t\treturn this;\n\t}\n\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tthis.app.registerRoute(\"HEAD\", this.normalizePath(path), [\n\t\t\t...this.groupMiddlewares,\n\t\t\t...handlers,\n\t\t], { source: \"group\", group: this.prefix });\n\t\treturn this;\n\t}\n\n\t/**\n\t * Register a handler for all standard HTTP methods (GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS).\n\t */\n\tpublic all<Path extends string>(path: Path, handler: Handler<DI, Path> | string | Response): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\tm1: Middleware<DI, Path>,\n\t\tm2: Middleware<DI, Path>,\n\t\tm3: Middleware<DI, Path>,\n\t\tm4: Middleware<DI, Path>,\n\t\tm5: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path> | string | Response,\n\t): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path> | string | Response>\n\t): this {\n\t\tconst methods = [\n\t\t\t\"GET\",\n\t\t\t\"HEAD\",\n\t\t\t\"POST\",\n\t\t\t\"PUT\",\n\t\t\t\"PATCH\",\n\t\t\t\"DELETE\",\n\t\t\t\"OPTIONS\",\n\t\t];\n\t\tfor (const method of methods) {\n\t\t\tthis.app.registerRoute(method, this.normalizePath(path), [\n\t\t\t\t...this.groupMiddlewares,\n\t\t\t\t...handlers,\n\t\t\t], { source: \"group\", group: this.prefix });\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Register a WebSocket endpoint within this group.\n\t * Path is prefixed with the group prefix.\n\t */\n\tpublic ws(path: string, handler: WSHandler<DI>): this {\n\t\tthis.app.ws(this.normalizePath(path), handler);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Serve static files within this group.\n\t * Route path is prefixed with the group prefix.\n\t */\n\tpublic static(routePath: string, directory: string): this {\n\t\tthis.app.static(this.normalizePath(routePath), directory);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Register a decorator-based controller within this group.\n\t * The controller's prefix is combined with the group prefix.\n\t *\n\t * @example\n\t * const api = app.group(\"/api/v1\");\n\t * api.registerController(UserController);\n\t * api.registerController([UserController, PostController]);\n\t * // → routes registered as /api/v1/users, /api/v1/users/:id, etc.\n\t */\n\t// biome-ignore lint/suspicious/noExplicitAny: Constructor args are unknowable\n\tpublic registerController<T extends object>(target: (new (...args: any[]) => T) | T): this;\n\t// biome-ignore lint/suspicious/noExplicitAny: Constructor args are unknowable\n\tpublic registerController<T extends object>(targets: Array<(new (...args: any[]) => T) | T>): this;\n\t// biome-ignore lint/suspicious/noExplicitAny: Constructor args are unknowable\n\tpublic registerController<T extends object>(\n\t\ttarget: (new (...args: any[]) => T) | T | Array<(new (...args: any[]) => T) | T>,\n\t): this {\n\t\tif (Array.isArray(target)) {\n\t\t\tfor (const t of target) {\n\t\t\t\tthis.registerController(t);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tconst isInstance =\n\t\t\ttypeof target === \"object\" &&\n\t\t\ttarget !== null &&\n\t\t\ttypeof target === \"object\";\n\n\t\tconst ControllerClass = isInstance\n\t\t\t? // biome-ignore lint/suspicious/noExplicitAny: dynamic type narrowing\n\t\t\t(target as any).constructor\n\t\t\t: // biome-ignore lint/suspicious/noExplicitAny: dynamic type narrowing\n\t\t\t(target as new (\n\t\t\t\t...args: any[]\n\t\t\t) => T);\n\n\t\tconst meta = getControllerMeta(ControllerClass);\n\t\tif (!meta) {\n\t\t\tthrow new Error(\n\t\t\t\t`${ControllerClass.name} is not decorated with @Controller - did you forget to add it?`,\n\t\t\t);\n\t\t}\n\n\t\tlet instance: T;\n\n\t\tif (isInstance) {\n\t\t\tinstance = target as T;\n\t\t} else {\n\t\t\tconst container = this.app.getContainer();\n\t\t\tif (container.has(ControllerClass)) {\n\t\t\t\tinstance = container.resolve<T>(ControllerClass);\n\t\t\t} else {\n\t\t\t\tinstance = new ControllerClass();\n\t\t\t}\n\t\t}\n\n\t\tconst normalizedPrefix = meta.prefix.endsWith(\"/\")\n\t\t\t? meta.prefix.slice(0, -1)\n\t\t\t: meta.prefix;\n\n\t\tfor (const route of meta.routes) {\n\t\t\tconst cleanPath = route.path === \"/\" ? \"\" : route.path;\n\t\t\tconst fullPath =\n\t\t\t\t`${this.normalizePath(normalizedPrefix)}${cleanPath}` || \"/\";\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: dynamic method dispatch by decorated property key\n\t\t\tconst originalMethod = (instance as any)[route.propertyKey];\n\t\t\tlet handler = ((...args: any[]) => originalMethod.apply(instance, args)) as Handler<DI>;\n\t\t\t// Attach original for sucrose analysis (bound/closure wrappers hide toString)\n\t\t\t(handler as any)._sucroseTarget = originalMethod;\n\t\t\t// Apply @HttpCode/@SetHeader/@Redirect wrappers (same as Buntok.registerController)\n\t\t\thandler = applyRouteResponseDecorators(handler, route);\n\n\t\t\tthis.app.registerRoute(route.method, fullPath, [\n\t\t\t\t...this.groupMiddlewares,\n\t\t\t\t...(route.middlewares as Middleware<DI>[]),\n\t\t\t\thandler,\n\t\t\t], { source: \"controller\", controller: ControllerClass.name, group: this.prefix });\n\t\t}\n\n\t\treturn this;\n\t}\n}\n","import { Trie as NativeTrie } from \"../ffi\";\n\nexport interface LookupResult {\n\t// biome-ignore lint/suspicious/noExplicitAny: generic router handler\n\thandler: ((...args: any[]) => any) | null;\n\tparams: Record<string, string>;\n}\n\nconst EMPTY_PARAMS: Record<string, string> = Object.freeze({});\n\n// Ring buffer LRU cache for trie lookup results on dynamic routes.\n// Avoids re-walking the trie for the same (method, pathname) pair -\n// common in real apps where the same resource is hit repeatedly.\n// Uses O(1) circular buffer instead of O(n) Array.shift().\nconst CACHE_MAX = 2048;\n\nclass LookupCache {\n\tprivate map = new Map<string, Map<string, LookupResult>>();\n\tprivate buffer: Array<{ method: string; path: string } | undefined> =\n\t\tnew Array(CACHE_MAX);\n\tprivate head = 0;\n\tprivate tail = 0;\n\tprivate count = 0;\n\n\tget(method: string, path: string): LookupResult | undefined {\n\t\tconst methodMap = this.map.get(method);\n\t\tif (!methodMap) return undefined;\n\t\treturn methodMap.get(path);\n\t}\n\n\tset(method: string, path: string, val: LookupResult): void {\n\t\tlet methodMap = this.map.get(method);\n\t\tif (!methodMap) {\n\t\t\tmethodMap = new Map();\n\t\t\tthis.map.set(method, methodMap);\n\t\t}\n\n\t\tif (methodMap.has(path)) {\n\t\t\tmethodMap.set(path, val);\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.count >= CACHE_MAX) {\n\t\t\t// Evict the oldest entry (O(1) - no array re-indexing)\n\t\t\tconst oldest = this.buffer[this.head];\n\t\t\tif (oldest) {\n\t\t\t\tconst oldMethodMap = this.map.get(oldest.method);\n\t\t\t\tif (oldMethodMap) oldMethodMap.delete(oldest.path);\n\t\t\t}\n\t\t\tthis.buffer[this.head] = undefined;\n\t\t\tthis.head = (this.head + 1) % CACHE_MAX;\n\t\t} else {\n\t\t\tthis.count++;\n\t\t}\n\n\t\tmethodMap.set(path, val);\n\t\tthis.buffer[this.tail] = { method, path };\n\t\tthis.tail = (this.tail + 1) % CACHE_MAX;\n\t}\n}\n\nexport class Router {\n\t// biome-ignore lint/suspicious/noExplicitAny: generic router handler\n\tpublic staticRoutes: Map<string, Map<string, (...args: any[]) => any>> =\n\t\tnew Map();\n\n\t// Registry of dynamic (param/catchall) routes, mirroring staticRoutes:\n\t// path → method → handler. The native promotion pass iterates this to\n\t// build Bun.serve route values for `:param` paths.\n\tpublic dynamicRoutes: Map<string, Map<string, (...args: any[]) => any>> =\n\t\tnew Map();\n\n\t// LRU cache for dynamic (param/catchall) route lookups\n\tprivate readonly lookupCache = new LookupCache();\n\n\t// Trie for dynamic route lookup\n\tprivate nativeTrie: NativeTrie;\n\t// biome-ignore lint/suspicious/noExplicitAny: generic router handler\n\tprivate handlerRegistry: Map<number, (...args: any[]) => any> = new Map();\n\tprivate nextHandlerId = 0;\n\n\tconstructor() {\n\t\tthis.nativeTrie = new NativeTrie();\n\t}\n\n\tpublic insert(\n\t\tmethod: string,\n\t\tpath: string,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: generic router handler\n\t\thandler: (...args: any[]) => any,\n\t): void {\n\t\tif (path === \"\") return;\n\n\t\tconst upperMethod = method.toUpperCase();\n\t\tconst hasParams =\n\t\t\tpath.includes(\":\") || path.includes(\"*\");\n\n\t\t// Fast path: store static routes in flat map\n\t\tif (!hasParams) {\n\t\t\tlet methodMap = this.staticRoutes.get(path);\n\t\t\tif (!methodMap) {\n\t\t\t\tmethodMap = new Map();\n\t\t\t\tthis.staticRoutes.set(path, methodMap);\n\t\t\t}\n\t\t\tmethodMap.set(upperMethod, handler);\n\t\t\treturn;\n\t\t}\n\n\t\t// Register in trie for dynamic routes\n\t\tconst handlerId = this.nextHandlerId++;\n\t\tthis.handlerRegistry.set(handlerId, handler);\n\t\tconst compositeKey = `${upperMethod}:${path}`;\n\t\tthis.nativeTrie.insert(compositeKey, handlerId);\n\t\tlet dynMethodMap = this.dynamicRoutes.get(path);\n\t\tif (!dynMethodMap) {\n\t\t\tdynMethodMap = new Map();\n\t\t\tthis.dynamicRoutes.set(path, dynMethodMap);\n\t\t}\n\t\tdynMethodMap.set(upperMethod, handler);\n\t}\n\n\tpublic find(method: string, path: string): LookupResult {\n\t\tconst result = this.findOnce(method, path);\n\t\t// Standards-track behavior (Elysia/Hono/Express): a HEAD request is\n\t\t// answered by the GET route when no HEAD route is registered - Bun.serve\n\t\t// does the same for native route values, so the JS path mirrors it.\n\t\tif (result.handler === null && method === \"HEAD\") {\n\t\t\treturn this.findOnce(\"GET\", path);\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate findOnce(method: string, path: string): LookupResult {\n\t\t// Fast path: try flat static route cache first (O(1))\n\t\tconst methodMap = this.staticRoutes.get(path);\n\t\tif (methodMap) {\n\t\t\tconst handler = methodMap.get(method); // method is already uppercase\n\t\t\tif (handler) {\n\t\t\t\treturn { handler, params: EMPTY_PARAMS };\n\t\t\t}\n\t\t}\n\n\t\t// LRU cache for dynamic routes - avoids re-walking the trie for\n\t\t// repeated (method, pathname) pairs (e.g. same user ID hit often)\n\t\tconst cached = this.lookupCache.get(method, path);\n\t\tif (cached) return cached;\n\n\t\t// Trie lookup for dynamic routes\n\t\tconst compositeKey = `${method}:${path}`;\n\t\tconst nativeResult = this.nativeTrie.find(compositeKey);\n\n\t\tif (nativeResult.handlerId !== -1) {\n\t\t\tconst handler = this.handlerRegistry.get(nativeResult.handlerId);\n\t\t\tif (handler) {\n\t\t\t\tconst result: LookupResult = {\n\t\t\t\t\thandler,\n\t\t\t\t\tparams: nativeResult.params,\n\t\t\t\t};\n\t\t\t\tthis.lookupCache.set(method, path, result);\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\treturn { handler: null, params: EMPTY_PARAMS };\n\t}\n}\n"]}