{"version":3,"sources":["/home/pitok/Projects/framework-bun/packages/buntok-core/dist/chunk-T7LHYQ6Y.cjs","../src/app.ts","../src/router/index.ts"],"names":["EMPTY_PARAMS"],"mappings":"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","file":"/home/pitok/Projects/framework-bun/packages/buntok-core/dist/chunk-T7LHYQ6Y.cjs","sourcesContent":[null,"import { join, sep, dirname } from \"node:path\";\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport type { Server, ServerWebSocket } 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 { toResponse } from \"./helpers/response\";\nimport { analyzeHandler } from \"./aot/sucrose\";\nimport { logger } from \"./logger\";\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 untuk 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| 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| 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 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}\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 AppOptions {\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 `App.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)),\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));\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\treturn wrapped;\n}\n\nexport class App<DI extends Record<string, unknown> = Record<string, unknown>> {\n\tprivate router: Router;\n\tprivate middlewares: Middleware<DI>[] = [];\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 }>();\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: App<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// App-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: AppOptions = {}) {\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\treturn this;\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._aotReady = false;\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 App instance needed (ideal for src/env.ts)\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\t * @example\n\t * // Custom error handler - send to monitoring before exiting\n\t * const env = App.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 App();\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 App.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. Currently only `\"x-powered-by\"` is\n\t * supported, which turns off the `X-Powered-By: buntok` response header.\n\t * The header's value itself is not configurable — this only controls\n\t * whether it's sent.\n\t */\n\tpublic disable(feature: \"x-powered-by\"): this {\n\t\tif (feature === \"x-powered-by\") {\n\t\t\tthis.poweredByHeaderEnabled = false;\n\t\t}\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\"): this {\n\t\tif (feature === \"x-powered-by\") {\n\t\t\tthis.poweredByHeaderEnabled = true;\n\t\t}\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}\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>): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>,\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>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>,\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>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>,\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>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>,\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>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>,\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>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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 = join(process.cwd(), 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\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>>,\n\t\toptions?: { source?: \"route\" | \"controller\" | \"group\"; controller?: string; group?: string },\n\t): void {\n\t\tconst mainHandler = handlers[handlers.length - 1] as Handler<DI>;\n\t\tconst routeMiddlewares = handlers.slice(0, -1) as Middleware<DI>[];\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(`${method}:${path}`);\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});\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\tlet code = `return fns[${fns.length - 1}](ctx);`;\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(\"fns\", `return function(ctx) { ${code} }`);\n\t\treturn factory(fns) 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(import.meta.dir, \"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.middlewares.length === 0) {\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\tconst fns = [...this.middlewares];\n\t\tlet code = `return finalHandler(ctx);`;\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`return function(ctx, finalHandler) { ${code} }`,\n\t\t);\n\t\tthis.compiledGlobalPipeline = factory(fns) 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\tconst hasGlobalMiddleware = this.middlewares.length > 0;\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\"    ctx = new Context(request, EMPTY_PARAMS, di, clientIPResolver);\\n\" +\n\t\t\t\t\"    const data = { ctx, 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 };\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// 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\tif (!this.poweredByHeaderEnabled) {\n\t\t\t\t\t\t// Fastest path: no logging, no powered-by — skip setPoweredBy entirely\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) => typeof v === \"string\" ? new Response(v, plainTextHeaders) : v instanceof Response ? v : typeof v === \"object\" ? 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\t\tcode += \"      }\\n\";\n\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t'      if (typeof raw === \"string\") return new Response(raw, plainTextHeaders);\\n';\n\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t\"      if (raw instanceof Response) return raw;\\n\" +\n\t\t\t\t\t\t\t\"      if (typeof raw === \\\"object\\\") return Response.json(raw);\\n\" +\n\t\t\t\t\t\t\t\"      return toResponse(raw);\\n\";\n\t\t\t\t\t} else {\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(typeof v === \"string\" ? new Response(v, plainTextHeaders) : v instanceof Response ? v : typeof v === \"object\" ? 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\t\tcode += \"      }\\n\";\n\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t'      if (typeof raw === \"string\") return setPoweredBy(new Response(raw, plainTextHeaders));\\n';\n\t\t\t\t\t\tcode +=\n\t\t\t\t\t\t\t\"      if (raw instanceof Response) return setPoweredBy(raw);\\n\" +\n\t\t\t\t\t\t\t\"      if (typeof raw === \\\"object\\\") return setPoweredBy(Response.json(raw));\\n\" +\n\t\t\t\t\t\t\t\"      return setPoweredBy(toResponse(raw));\\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, new Response(v, plainTextHeaders)) : logResponse(request, pathname, v instanceof Response ? v : typeof v === \"object\" ? 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, new Response(raw, plainTextHeaders));\\n';\n\t\t\t\t\tcode +=\n\t\t\t\t\t\t\"      if (raw instanceof Response) return logResponse(request, pathname, raw);\\n\" +\n\t\t\t\t\t\t\"      if (typeof raw === \\\"object\\\") return logResponse(request, pathname, Response.json(raw));\\n\" +\n\t\t\t\t\t\t\"      return logResponse(request, pathname, 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\"setPoweredBy\",\n\t\t\t\"plainTextHeaders\",\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\tthis.setPoweredBy,\n\t\t\tthis._plainTextHeaders,\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 App instance instead of allocating a new closure per request\n\tprivate readonly logResponse = (\n\t\trequest: Request,\n\t\tpathname: string,\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\treturn response;\n\t};\n\n\t// Lightweight X-Powered-By setter for AOT skip-log path (no logging overhead)\n\tprivate readonly setPoweredBy = (response: Response): Response => {\n\t\tif (this.poweredByHeaderEnabled) {\n\t\t\tresponse.headers.set(\"X-Powered-By\", \"buntok\");\n\t\t}\n\t\treturn response;\n\t};\n\n\t// Pre-allocated headers for hot paths — avoid alloc per request\n\tprivate _plainTextHeaders = Object.freeze({ \"Content-Type\": \"text/plain; charset=utf-8\" });\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(value: unknown): 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),\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);\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): Response | Promise<Response> => {\n\t\tconst normalized = this.normalizeReturn(value);\n\t\tif (normalized instanceof Promise) {\n\t\t\treturn normalized.then((res) => this.logResponse(request, pathname, res));\n\t\t}\n\t\treturn this.logResponse(request, pathname, 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);\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 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 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\tif (!this.compiledGlobalPipeline) this.compileGlobalPipeline();\n\t\t// Lazy AOT — compile sekali saja (fix speed murah: sebelumnya compile tiap request)\n\t\tif (!this._aotReady) {\n\t\t\tthis._compiledAOTRouter = this.compileAOTRouter();\n\t\t\tthis._aotReady = true;\n\t\t}\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.handleRequest(request);\n\t}\n\n\t/**\n\t * Standard fetch handler for serverless platforms (Vercel, Cloudflare Workers, etc.).\n\t * Delegates to {@link request} which handles lazy AOT compilation.\n\t *\n\t * Usage:\n\t * ```ts\n\t * const app = new App();\n\t * export default app;\n\t * ```\n\t */\n\tpublic fetch(request: Request): Promise<Response> {\n\t\treturn this.request(request);\n\t}\n\n\tprivate _aotReady = false;\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\tconst cached = this._handlerFullContextCache.get(finalHandler);\n\t\tconst needsFullContext = 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))\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);\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\tpublic listen(port?: number, callback?: () => void): void {\n\t\t// Skip server startup when running under make:docs\n\t\tif (process.env.BUNTOK_DOCS_BUILD === \"1\") return;\n\t\tif (this.isListening) return;\n\t\tthis.isListening = true;\n\n\t\tconst startTime = performance.now();\n\n\t\t// Pre-compute whether logResponse can be skipped entirely\n\t\t// When logging is off, the AOT template skips logResponse() entirely —\n\t\t// X-Powered-By is inlined in the AOT codegen below.\n\t\tthis._skipLogResponse = !logger.logRequests;\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\tfetch: this._compiledAOTRouter,\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 bukan 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// juga fallback untuk wsHeartbeat yang attach di 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// 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\tconsole.log(\n\t\t\t`\\n  \\x1b[36mBuntok v${VERSION}\\x1b[0m ready in \\x1b[32m${startupTime}ms\\x1b[0m\\n`,\n\t\t);\n\t\tconsole.log(`  Environment: \\x1b[33m${env}\\x1b[0m`);\n\t\tconsole.log(`  Listening on: \\x1b[36mhttp://localhost:${currentPort}\\x1b[0m`);\n\t\tif (this._apiDocsConfig) {\n\t\t\tconst docsPath = (this._apiDocsConfig.path ?? \"/docs\").replace(/\\/+$/, \"\");\n\t\t\tconsole.log(`  Docs:         \\x1b[36mhttp://localhost:${currentPort}${docsPath}/\\x1b[0m`);\n\t\t}\n\t\tconsole.log();\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}\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: App<DI>;\n\tprivate groupMiddlewares: Middleware<DI>[] = [];\n\n\tconstructor(prefix: string, app: App<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>): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic get<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>,\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>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic post<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic put<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>,\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>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic delete<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>,\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>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic options<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>,\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>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic patch<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>,\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>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic head<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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>): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\tmiddleware: Middleware<DI, Path>,\n\t\thandler: Handler<DI, Path>,\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>,\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>,\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>,\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>,\n\t): this;\n\tpublic all<Path extends string>(\n\t\tpath: Path,\n\t\t...handlers: Array<Middleware<DI, Path> | Handler<DI, Path>>\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 App.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// 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}\n\n\tpublic find(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"]}