{"version":3,"sources":["/home/pitok/Projects/framework-bun/packages/buntok-core/dist/chunk-RMHTQ2C5.cjs","../src/version.ts","../src/aot/sucrose.ts","../src/app.ts","../src/container.ts","../src/sse.ts","../src/context.ts","../src/logger.ts","../src/ffi/fallback.ts","../src/ffi/index.ts","../src/router/index.ts","../src/middlewares/cors.ts"],"names":["__dirname","result","LogLevel","findLib","EMPTY_PARAMS"],"mappings":"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","file":"/home/pitok/Projects/framework-bun/packages/buntok-core/dist/chunk-RMHTQ2C5.cjs","sourcesContent":[null,"import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst __dirname = import.meta.dir;\nlet _version = \"0.0.0-dev\";\ntry {\n\tlet pkgPath = join(__dirname, \"..\", \"package.json\");\n\tif (!existsSync(pkgPath)) {\n\t\tpkgPath = join(__dirname, \"..\", \"..\", \"package.json\");\n\t}\n\tif (!existsSync(pkgPath)) {\n\t\tpkgPath = join(process.cwd(), \"node_modules\", \"@buntok\", \"core\", \"package.json\");\n\t}\n\tif (existsSync(pkgPath)) {\n\t\tconst pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n\t\tif (typeof pkg.version === \"string\") _version = pkg.version;\n\t}\n} catch {}\nexport const VERSION: string = _version;\n","/**\n * Sucrose-style static code analysis for handler optimization.\n *\n * Analyzes handler function source code at boot time to determine which\n * context properties are actually used, then generates optimized handlers\n * that only parse/query/validate the properties that are needed.\n *\n * This eliminates unnecessary work per request — if a handler doesn't use\n * `ctx.body`, we skip body parsing entirely.\n */\n\nexport interface HandlerAnalysis {\n\t/** Whether handler uses ctx.body() or ctx.request (requires body parsing) */\n\tneedsBody: boolean;\n\t/** Whether handler uses ctx.query (requires query parsing) */\n\tneedsQuery: boolean;\n\t/** Whether handler uses ctx.params (requires params) */\n\tneedsParams: boolean;\n\t/** Whether handler uses ctx.valid() (requires validation) */\n\tneedsValidation: boolean;\n\t/** Whether handler uses ctx.formData() (requires FormData parsing) */\n\tneedsFormData: boolean;\n\t/** Whether handler uses ctx.request.text() (requires text parsing) */\n\tneedsText: boolean;\n\t/** Whether handler uses ctx.request.arrayBuffer() (requires binary parsing) */\n\tneedsBinary: boolean;\n\t/** Whether handler uses Context methods that require full Context instance */\n\tneedsFullContext: boolean;\n}\n\n/**\n * Analyze a handler function to determine which context properties it uses.\n * Uses string analysis on the function source (like Elysia's Sucrose).\n *\n * @example\n * ```ts\n * const handler = (ctx) => {\n *   const data = ctx.valid(\"body\", schema);\n *   return ctx.json(data);\n * };\n *\n * const analysis = analyzeHandler(handler);\n * // { needsBody: true, needsQuery: false, needsParams: false, needsValidation: true, ... }\n * ```\n */\nexport function analyzeHandler(\n\thandler: (...args: any[]) => any,\n): HandlerAnalysis {\n\t// Default: assume all properties are needed (conservative)\n\tconst analysis: HandlerAnalysis = {\n\t\tneedsBody: true,\n\t\tneedsQuery: true,\n\t\tneedsParams: true,\n\t\tneedsValidation: true,\n\t\tneedsFormData: true,\n\t\tneedsText: true,\n\t\tneedsBinary: true,\n\t\tneedsFullContext: true,\n\t};\n\n\ttry {\n\t\t// Use _sucroseTarget if available (closure wrappers hide toString)\n\t\tconst target = (handler as any)._sucroseTarget ?? handler;\n\t\t// Get function source code\n\t\tconst source = target.toString();\n\n\t\t// Quick check: if source is too short or is a native function, return defaults\n\t\tif (source.length < 10 || source.includes(\"[native code]\")) {\n\t\t\treturn analysis;\n\t\t}\n\n\t\t// If handler uses destructuring in params (e.g. `handler({ params })`),\n\t\t// we can't safely skip Context — the destructured props come from ctx\n\t\tconst hasDestructuredParams = /\\(\\s*\\{[^}]*\\b(params|query|body|valid|request|headers|store|cookies|ip)\\b/.test(source) ||\n\t\t\t/function\\s*\\w*\\s*\\(\\s*\\{[^}]+\\}/.test(source) ||\n\t\t\t/\\)\\s*=>\\s*\\{[^}]*\\bparams\\b/.test(source);\n\n\t\tif (hasDestructuredParams) {\n\t\t\t// Destructured ctx props — detect WHICH props are destructured\n\t\t\tconst destrMatch = source.match(/\\(\\s*\\{([^}]+)\\}/);\n\t\t\tif (destrMatch) {\n\t\t\t\tconst destrProps = destrMatch[1];\n\t\t\t\tanalysis.needsBody = /body|request|raw|arrayBuffer/.test(destrProps);\n\t\t\t\tanalysis.needsQuery = /query/.test(destrProps);\n\t\t\t\tanalysis.needsParams = /params/.test(destrProps);\n\t\t\t\tanalysis.needsValidation = /valid/.test(destrProps);\n\t\t\t\tanalysis.needsFormData = /formData/.test(destrProps);\n\t\t\t\tanalysis.needsText = /request\\.text/.test(destrProps);\n\t\t\t\tanalysis.needsBinary = /request\\.arrayBuffer/.test(destrProps);\n\t\t\t}\n\t\t\treturn analysis;\n\t\t}\n\n\t\t// Analyze which properties are accessed\n\t\tanalysis.needsBody =\n\t\t\tsource.includes(\"ctx.body\") ||\n\t\t\tsource.includes(\"ctx.request\") ||\n\t\t\tsource.includes(\"ctx.raw\") ||\n\t\t\tsource.includes(\".body(\") ||\n\t\t\tsource.includes(\".arrayBuffer(\");\n\n\t\tanalysis.needsQuery =\n\t\t\tsource.includes(\"ctx.query\") ||\n\t\t\tsource.includes(\".query(\");\n\n\t\tanalysis.needsParams =\n\t\t\tsource.includes(\"ctx.params\") ||\n\t\t\tsource.includes(\".params(\");\n\n\t\tanalysis.needsValidation =\n\t\t\tsource.includes(\"ctx.valid\") ||\n\t\t\tsource.includes(\".valid(\");\n\n\t\tanalysis.needsFormData =\n\t\t\tsource.includes(\"ctx.formData\") ||\n\t\t\tsource.includes(\".formData(\");\n\n\t\tanalysis.needsText =\n\t\t\tsource.includes(\"ctx.request.text()\") ||\n\t\t\tsource.includes(\".text(\");\n\n\t\tanalysis.needsBinary =\n\t\t\tsource.includes(\"ctx.request.arrayBuffer()\") ||\n\t\t\tsource.includes(\".arrayBuffer(\");\n\n\t\t// Detect Context methods that require full Context instance\n\t\tanalysis.needsFullContext =\n\t\t\tanalysis.needsBody ||\n\t\t\tanalysis.needsQuery ||\n\t\t\tanalysis.needsParams ||\n\t\t\tanalysis.needsValidation ||\n\t\t\tanalysis.needsFormData ||\n\t\t\tanalysis.needsText ||\n\t\t\tanalysis.needsBinary ||\n\t\t\tsource.includes(\"ctx.getCookie\") ||\n\t\t\tsource.includes(\"ctx.getCookies\") ||\n\t\t\tsource.includes(\"ctx.cookies\") ||\n\t\t\tsource.includes(\"ctx.json\") ||\n\t\t\tsource.includes(\"ctx.success\") ||\n\t\t\tsource.includes(\"ctx.error\") ||\n\t\t\tsource.includes(\"ctx.created\") ||\n\t\t\tsource.includes(\"ctx.noContent\") ||\n\t\t\tsource.includes(\"ctx.status\") ||\n\t\t\tsource.includes(\"ctx.headers\") ||\n\t\t\tsource.includes(\"ctx.store\") ||\n\t\t\tsource.includes(\"ctx.ip\") ||\n\t\t\tsource.includes(\"ctx.request.headers\") ||\n\t\t\tsource.includes(\".getCookie(\") ||\n\t\t\tsource.includes(\".getCookies(\") ||\n\t\t\tsource.includes(\".json(\") ||\n\t\t\tsource.includes(\".success(\") ||\n\t\t\tsource.includes(\".error(\") ||\n\t\t\tsource.includes(\".created(\") ||\n\t\t\tsource.includes(\".noContent(\");\n\n\t\t// If handler is passed to another function, conservatively assume all properties needed\n\t\tif (\n\t\t\tsource.includes(\"handler(\") ||\n\t\t\tsource.includes(\"fn(\") ||\n\t\t\tsource.includes(\"next()\")\n\t\t) {\n\t\t\treturn {\n\t\t\t\tneedsBody: true,\n\t\t\t\tneedsQuery: true,\n\t\t\t\tneedsParams: true,\n\t\t\t\tneedsValidation: true,\n\t\t\t\tneedsFormData: true,\n\t\t\t\tneedsText: true,\n\t\t\t\tneedsBinary: true,\n\t\t\t\tneedsFullContext: true,\n\t\t\t};\n\t\t}\n\t} catch {\n\t\t// If analysis fails, return conservative defaults\n\t}\n\n\treturn analysis;\n}\n\n/**\n * Analyze a middleware chain to determine which context properties are needed.\n * Combines analysis of all handlers in the chain.\n *\n * @example\n * ```ts\n * const middlewares = [authMiddleware, validatorMiddleware, handler];\n * const analysis = analyzeHandlerChain(middlewares);\n * // Combined analysis of all handlers\n * ```\n */\nexport function analyzeHandlerChain(\n\thandlers: ((...args: any[]) => any)[],\n): HandlerAnalysis {\n\tconst combined: HandlerAnalysis = {\n\t\tneedsBody: false,\n\t\tneedsQuery: false,\n\t\tneedsParams: false,\n\t\tneedsValidation: false,\n\t\tneedsFormData: false,\n\t\tneedsText: false,\n\t\tneedsBinary: false,\n\t\tneedsFullContext: false,\n\t};\n\n\tfor (const handler of handlers) {\n\t\tconst analysis = analyzeHandler(handler);\n\t\tcombined.needsBody = combined.needsBody || analysis.needsBody;\n\t\tcombined.needsQuery = combined.needsQuery || analysis.needsQuery;\n\t\tcombined.needsParams = combined.needsParams || analysis.needsParams;\n\t\tcombined.needsValidation =\n\t\t\tcombined.needsValidation || analysis.needsValidation;\n\t\tcombined.needsFormData =\n\t\t\tcombined.needsFormData || analysis.needsFormData;\n\t\tcombined.needsText = combined.needsText || analysis.needsText;\n\t\tcombined.needsBinary = combined.needsBinary || analysis.needsBinary;\n\t\tcombined.needsFullContext = combined.needsFullContext || analysis.needsFullContext;\n\t}\n\n\treturn combined;\n}\n","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 } 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\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\tmessage:\n\t\t\t\t\tprocess.env.NODE_ENV === \"production\"\n\t\t\t\t\t\t? \"An unexpected error occurred\"\n\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\tconst hasStatus = route.statusCode !== undefined;\n\t\t\tconst hasHeaders = route.headers && route.headers.length > 0;\n\t\t\tconst hasRedirect = !!route.redirect;\n\t\t\tif (hasStatus || hasHeaders || hasRedirect) {\n\t\t\t\tconst original = handler;\n\t\t\t\tconst routeMeta = route;\n\t\t\t\tconst apply = (res: Response): Response => {\n\t\t\t\t\tlet r: Response = res;\n\t\t\t\t\tif (hasStatus && r.status === 200) {\n\t\t\t\t\t\t// Override status only if default 200 (preserve explicit ctx.status etc.)\n\t\t\t\t\t\tr = new Response(r.body, { status: routeMeta.statusCode!, headers: r.headers });\n\t\t\t\t\t} else if (hasStatus && r.status === 204 && routeMeta.statusCode !== 204) {\n\t\t\t\t\t\t// For void returns that became 204, respect HttpCode\n\t\t\t\t\t\tr = new Response(r.body, { status: routeMeta.statusCode!, headers: r.headers });\n\t\t\t\t\t}\n\t\t\t\t\tif (hasHeaders) {\n\t\t\t\t\t\tfor (const [k, v] of routeMeta.headers!) {\n\t\t\t\t\t\t\tr.headers.set(k, v);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn r;\n\t\t\t\t};\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: wrapper must accept any Context shape\n\t\t\t\thandler = ((ctx: any) => {\n\t\t\t\t\t// Redirect - static or dynamic override (Nest behavior)\n\t\t\t\t\tif (hasRedirect) {\n\t\t\t\t\t\tconst result: any = original(ctx);\n\t\t\t\t\t\t// If handler returns promise, handle async\n\t\t\t\t\t\tif (result instanceof Promise) {\n\t\t\t\t\t\t\treturn result.then((val: any) => {\n\t\t\t\t\t\t\t\tif (val instanceof Response) {\n\t\t\t\t\t\t\t\t\treturn new Response(val.body, {\n\t\t\t\t\t\t\t\t\t\tstatus: routeMeta.redirect!.statusCode,\n\t\t\t\t\t\t\t\t\t\theaders: { Location: routeMeta.redirect!.url, ...Object.fromEntries(val.headers) },\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (val && typeof val === \"object\" && \"url\" in val) {\n\t\t\t\t\t\t\t\t\tconst url = (val as any).url as string;\n\t\t\t\t\t\t\t\t\tconst sc = (val as any).statusCode ?? routeMeta.redirect!.statusCode;\n\t\t\t\t\t\t\t\t\treturn new Response(null, { status: sc, headers: { Location: url } });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Also allow string return as url override\n\t\t\t\t\t\t\t\tif (typeof val === \"string\" && val.startsWith(\"/\")) {\n\t\t\t\t\t\t\t\t\treturn new Response(null, { status: routeMeta.redirect!.statusCode, headers: { Location: val } });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Static redirect\n\t\t\t\t\t\t\t\treturn new Response(null, {\n\t\t\t\t\t\t\t\t\tstatus: routeMeta.redirect!.statusCode,\n\t\t\t\t\t\t\t\t\theaders: { Location: routeMeta.redirect!.url },\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (result instanceof Response) {\n\t\t\t\t\t\t// Handler returned a Response — apply redirect status + Location header\n\t\t\t\t\t\treturn new Response(result.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(result.headers) },\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (result && typeof result === \"object\" && \"url\" in result) {\n\t\t\t\t\t\t\tconst url = (result as any).url as string;\n\t\t\t\t\t\t\tconst sc = (result as any).statusCode ?? routeMeta.redirect!.statusCode;\n\t\t\t\t\t\t\treturn new Response(null, { status: sc, headers: { Location: url } });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (typeof result === \"string\" && result.startsWith(\"/\")) {\n\t\t\t\t\t\t\treturn new Response(null, { status: routeMeta.redirect!.statusCode, headers: { Location: result } });\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn new Response(null, {\n\t\t\t\t\t\t\tstatus: routeMeta.redirect!.statusCode,\n\t\t\t\t\t\t\theaders: { Location: routeMeta.redirect!.url },\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tconst raw: any = original(ctx);\n\t\t\t\t\tif (raw instanceof Promise) {\n\t\t\t\t\t\treturn raw.then((v: any) =>\n\t\t\t\t\t\t\ttypeof v === \"string\"\n\t\t\t\t\t\t\t\t? apply(new Response(v))\n\t\t\t\t\t\t\t\t: apply(v instanceof Response ? v : toResponse(v)),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn typeof raw === \"string\"\n\t\t\t\t\t\t? apply(new Response(raw))\n\t\t\t\t\t\t: apply(raw instanceof Response ? raw : toResponse(raw));\n\t\t\t\t}) as Handler<DI>;\n\t\t\t\t// Preserve sucrose target from original handler for AST analysis\n\t\t\t\t(handler as any)._sucroseTarget = (original as any)._sucroseTarget ?? original;\n\t\t\t}\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\tconst needsParamsOnly = !needsFullContext && cached.needsParams;\n\t\t\t\tconst ctxArg = needsFullContext ? \"ctx\" : needsParamsOnly ? \"{ request, params: routeParams }\" : \"{ 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\tconst handler = ((...args: any[]) => (instance as any)[route.propertyKey](...args)) as Handler<DI>;\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","export type Scope = \"singleton\" | \"transient\";\n\n// biome-ignore lint/complexity/noBannedTypes: Token can be string or class constructor\ntype Token = string | Function;\n\n// biome-ignore lint/suspicious/noExplicitAny: Generic provider defaults require any\nexport interface ClassProvider<T = any> {\n\tuseClass: new (\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Constructor args are unknowable\n\t\t...args: any[]\n\t) => T;\n\tscope?: Scope;\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: Generic provider defaults require any\nexport interface ValueProvider<T = any> {\n\tuseValue: T;\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: Generic provider defaults require any\nexport interface FactoryProvider<T = any> {\n\tuseFactory: (container: Container) => T;\n\tscope?: Scope;\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: Generic provider defaults require any\nexport type Provider<T = any> =\n\t| ClassProvider<T>\n\t| ValueProvider<T>\n\t| FactoryProvider<T>;\n\n// ── Dependency declaration registry (used by @Dependencies) ────────\nconst dependenciesRegistry = new Map<Function, any[]>();\n\n/**\n * Declares constructor dependencies for a class. Used with `container.scan()`\n * to auto-resolve dependencies without needing `emitDecoratorMetadata`.\n *\n * @example\n * ```ts\n * import { Dependencies, Controller } from \"@buntok/core\";\n *\n * @Dependencies(UserService, Logger)\n * @Controller(\"/users\")\n * class UserController {\n *   constructor(private service: UserService, private logger: Logger) {}\n * }\n * ```\n */\nexport function Dependencies(\n\t...tokens: any[]\n\t// biome-ignore lint/complexity/noBannedTypes: TC39 decorator signature\n): (target: Function, context: ClassDecoratorContext) => void {\n\treturn (target: Function, context: ClassDecoratorContext) => {\n\t\tif (context.kind !== \"class\") {\n\t\t\tthrow new Error(\"@Dependencies can only decorate classes\");\n\t\t}\n\t\tdependenciesRegistry.set(target, tokens);\n\t};\n}\n\n/**\n * Returns the dependency tokens declared via `@Dependencies()`.\n */\nexport function getDependencies(cls: any): any[] {\n\treturn dependenciesRegistry.get(cls) ?? [];\n}\n\n// ────────────────────────────────────────────────────────────────────\n\nfunction isClassProvider(p: Provider): p is ClassProvider {\n\treturn \"useClass\" in p;\n}\n\nfunction isValueProvider(p: Provider): p is ValueProvider {\n\treturn \"useValue\" in p;\n}\n\nfunction isFactoryProvider(p: Provider): p is FactoryProvider {\n\treturn \"useFactory\" in p;\n}\n\nexport class Container {\n\t// biome-ignore lint/suspicious/noExplicitAny: Internal provider storage\n\tprivate providers = new Map<Token, Provider<any>>();\n\t// biome-ignore lint/suspicious/noExplicitAny: Cached singleton instances\n\tprivate singletons = new Map<Token, any>();\n\tprivate resolving = new Set<Token>();\n\n\t/**\n\t * Register a provider for a given token (class or string key).\n\t */\n\tregister<T>(token: Token, provider: Provider<T>): this {\n\t\tthis.providers.set(token, provider);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Auto-register a class provider by its own constructor as the token.\n\t */\n\tregisterClass<T>(\n\t\tcls: new (\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: Constructor args are unknowable\n\t\t\t...args: any[]\n\t\t) => T,\n\t\tscope: Scope = \"singleton\",\n\t): this {\n\t\tthis.providers.set(cls, { useClass: cls, scope });\n\t\treturn this;\n\t}\n\n\t/**\n\t * Resolve a dependency by token. Returns cached instance for singletons.\n\t */\n\tresolve<T>(token: Token): T {\n\t\tconst cached = this.singletons.get(token);\n\t\tif (cached !== undefined) return cached as T;\n\n\t\tif (this.resolving.has(token)) {\n\t\t\tconst name = typeof token === \"function\" ? token.name : String(token);\n\t\t\tconst chain = [...this.resolving].map((t) =>\n\t\t\t\ttypeof t === \"function\" ? t.name : String(t),\n\t\t\t);\n\t\t\tthrow new Error(\n\t\t\t\t`Circular dependency detected: ${name}\\n` +\n\t\t\t\t\t`  Resolution chain: ${chain.join(\" -> \")} -> ${name}\\n` +\n\t\t\t\t\t`  Hint: Use FactoryProvider to break the cycle.`,\n\t\t\t);\n\t\t}\n\n\t\tconst provider = this.providers.get(token);\n\t\tif (!provider) {\n\t\t\tconst name = typeof token === \"function\" ? token.name : String(token);\n\t\t\tthrow new Error(\n\t\t\t\t`No provider registered for: ${name}\\n` +\n\t\t\t\t\t`  Hint: Register it with container.registerClass(${name}) or container.register(\"${name}\", { useClass: ${name} })`,\n\t\t\t);\n\t\t}\n\n\t\tthis.resolving.add(token);\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Dynamic instantiation\n\t\tlet instance: any;\n\t\tlet scope: Scope = \"singleton\";\n\n\t\tif (isClassProvider(provider)) {\n\t\t\tscope = provider.scope ?? \"singleton\";\n\t\t\tinstance = new provider.useClass();\n\t\t} else if (isValueProvider(provider)) {\n\t\t\tscope = \"singleton\";\n\t\t\tinstance = provider.useValue;\n\t\t} else if (isFactoryProvider(provider)) {\n\t\t\tscope = provider.scope ?? \"singleton\";\n\t\t\tinstance = provider.useFactory(this);\n\t\t}\n\n\t\tthis.resolving.delete(token);\n\n\t\tif (scope !== \"transient\") {\n\t\t\tthis.singletons.set(token, instance);\n\t\t}\n\n\t\treturn instance as T;\n\t}\n\n\t/**\n\t * Resolve and return an instance, or undefined if not registered.\n\t */\n\tget<T>(token: Token): T | undefined {\n\t\tif (this.singletons.has(token)) return this.singletons.get(token) as T;\n\t\tif (this.providers.has(token)) return this.resolve(token);\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Check whether a token has been registered.\n\t */\n\thas(token: Token): boolean {\n\t\treturn this.providers.has(token);\n\t}\n\n\t/**\n\t * Check whether a token has been resolved and cached.\n\t */\n\thasResolved(token: Token): boolean {\n\t\treturn this.singletons.has(token);\n\t}\n\n\t/**\n\t * Auto-scan classes and register them with dependency resolution.\n\t *\n\t * Reads dependencies declared via `@Dependencies()` decorator\n\t * (from `@buntok/core` decorators).\n\t *\n\t * @example\n\t * ```ts\n\t * import { Dependencies, Controller, Get } from \"@buntok/core\";\n\t *\n\t * @Dependencies(UserService)\n\t * @Controller(\"/users\")\n\t * class UserController {\n\t *   constructor(private service: UserService) {}\n\t * }\n\t *\n\t * const container = new Container();\n\t * container.scan([UserController]);\n\t * app.setContainer(container);\n\t * ```\n\t */\n\tscan(\n\t\tclasses: (new (...args: any[]) => any)[],\n\t\tscope: Scope = \"singleton\",\n\t): this {\n\t\tconst visited = new Set<Token>();\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata introspection\n\t\tconst self = this;\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Dynamic metadata introspection\n\t\tfunction introspect(cls: any): void {\n\t\t\tif (visited.has(cls)) return;\n\t\t\tvisited.add(cls);\n\n\t\t\t// Read dependency tokens from @Dependencies() decorator\n\t\t\tconst depTokens: any[] = getDependencies(cls);\n\n\t\t\t// Register dependencies first (bottom-up)\n\t\t\tfor (const dep of depTokens) {\n\t\t\t\tif (dep && typeof dep === \"function\") {\n\t\t\t\t\tintrospect(dep);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Register this class (skip if already registered manually)\n\t\t\tif (!self.has(cls)) {\n\t\t\t\tself.register(cls, {\n\t\t\t\t\tuseFactory: (c) => {\n\t\t\t\t\t\tconst args = depTokens.map(\n\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: Dynamic resolution\n\t\t\t\t\t\t\t(dep: any) => (dep ? c.resolve(dep) : undefined),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn new cls(...args);\n\t\t\t\t\t},\n\t\t\t\t\tscope,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfor (const cls of classes) {\n\t\t\tintrospect(cls);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Force-clear all providers and cached instances.\n\t * Useful in tests.\n\t */\n\tclear(): void {\n\t\tthis.providers.clear();\n\t\tthis.singletons.clear();\n\t\tthis.resolving.clear();\n\t}\n}\n","/**\n * Industrial SSE - Bun-only, in-memory default, pluggable to Redis/storage\n * Pattern mirip `StorageDriver` di `upload.ts:24` - default Memory, swap ke Redis tinggal inject.\n */\n\nexport interface SSEMessage {\n\t/** Event name */\n\tevent?: string;\n\t/** Message data */\n\tdata: string | object;\n\t/** Unique message ID for resumption */\n\tid?: string | number;\n}\n\n// ── Pluggable History Store (mirip StorageDriver) ──\nexport interface SSEHistoryStore {\n\t/** Persist message (dipanggil setiap send dengan id) */\n\tadd(message: SSEMessage): Promise<void> | void;\n\t/** Ambil pesan setelah lastEventId */\n\tgetAfter(lastEventId: string): Promise<SSEMessage[]> | SSEMessage[];\n\t/** Optional clear */\n\tclear?(): Promise<void> | void;\n}\n\n/** Default in-memory ring buffer 1000 msg - zero-deps */\nexport class MemorySSEHistory implements SSEHistoryStore {\n\tprivate messages: SSEMessage[] = [];\n\tconstructor(private maxSize = 1000) {}\n\tadd(message: SSEMessage): void {\n\t\t// hanya simpan yang punya id (butuh id untuk replay)\n\t\tif (message.id === undefined) return;\n\t\tthis.messages.push({ ...message });\n\t\tif (this.messages.length > this.maxSize) this.messages.shift();\n\t}\n\tgetAfter(lastEventId: string): SSEMessage[] {\n\t\tconst idx = this.messages.findIndex((m) => String(m.id) === String(lastEventId));\n\t\tif (idx === -1) return [];\n\t\treturn this.messages.slice(idx + 1);\n\t}\n\tclear(): void {\n\t\tthis.messages = [];\n\t}\n}\n\n// ── Pluggable PubSub (untuk broadcast cluster) ──\nexport interface SSEPubSub {\n\tpublish(channel: string, message: SSEMessage): Promise<void> | void;\n\tsubscribe(channel: string, handler: (msg: SSEMessage) => void): () => void;\n}\n\nexport class MemorySSEPubSub implements SSEPubSub {\n\tprivate channels = new Map<string, Set<(msg: SSEMessage) => void>>();\n\tpublish(channel: string, message: SSEMessage): void {\n\t\tconst subs = this.channels.get(channel);\n\t\tif (!subs) return;\n\t\tfor (const cb of subs) {\n\t\t\ttry {\n\t\t\t\tcb(message);\n\t\t\t} catch {}\n\t\t}\n\t}\n\tsubscribe(channel: string, handler: (msg: SSEMessage) => void): () => void {\n\t\tlet set = this.channels.get(channel);\n\t\tif (!set) {\n\t\t\tset = new Set();\n\t\t\tthis.channels.set(channel, set);\n\t\t}\n\t\tset.add(handler);\n\t\treturn () => set!.delete(handler);\n\t}\n}\n\nexport interface SSEOptions {\n\t/** Send initial connection event */\n\tsendInitial?: boolean;\n\t/** Custom event name for initial connection */\n\tinitialEvent?: string;\n\t/** Retry timeout in milliseconds (client reconnection) - default 3000 */\n\tretry?: number;\n\t/**\n\t * Maximum number of concurrent SSE connections.\n\t * When exceeded, new connections receive 503 Service Unavailable.\n\t * Set to 0 for unlimited (default).\n\t */\n\tmaxConnections?: number;\n\t/**\n\t * Callback to replay missed events on reconnection.\n\t * Receives the Last-Event-ID header value from the client.\n\t * Return an array of messages to replay.\n\t * Jika `historyStore` disediakan, callback ini opsional - store akan dipakai otomatis.\n\t */\n\tonReconnect?: (lastEventId: string) => Promise<SSEMessage[]>;\n\t/** Pluggable history store - default MemorySSEHistory (mirip StorageDriver) */\n\thistoryStore?: SSEHistoryStore;\n\t/** Custom headers tambahan */\n\theaders?: Record<string, string>;\n}\n\n/**\n * Global connection tracker for maxConnections enforcement.\n */\nconst connectionTracker = {\n\tconnections: new Set<SSE>(),\n};\n\n// Global default history (dipakai jika options.historyStore tidak diisi)\nconst defaultHistory = new MemorySSEHistory(1000);\n\nexport class SSE {\n\tprivate controller: ReadableStreamDefaultController | null = null;\n\tprivate encoder = new TextEncoder();\n\tprivate closed = false;\n\tprivate heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n\tprivate lastEventId: string | null = null;\n\tprivate abortHandler: (() => void) | null = null;\n\tprivate historyStore: SSEHistoryStore;\n\n\tconstructor(\n\t\tprivate request: Request,\n\t\tprivate options: SSEOptions = {},\n\t) {\n\t\t// Capture Last-Event-ID header (case-insensitive) + query fallback untuk proxy\n\t\tconst headerId = request.headers.get(\"last-event-id\");\n\t\tconst url = new URL(request.url);\n\t\tconst queryId = url.searchParams.get(\"lastEventId\") || url.searchParams.get(\"last-event-id\");\n\t\tthis.lastEventId = headerId || queryId;\n\t\tthis.historyStore = options.historyStore ?? defaultHistory;\n\t\t// Pre-aborted check\n\t\tif (request.signal.aborted) {\n\t\t\tthis.closed = true;\n\t\t}\n\t}\n\n\t/**\n\t * Create SSE response with ReadableStream - Bun-only, no external deps\n\t */\n\tconnect(): Response {\n\t\tif (this.closed && this.request.signal.aborted) {\n\t\t\treturn new Response(null, { status: 409 });\n\t\t}\n\t\t// Check maxConnections limit\n\t\tconst maxConnections = this.options.maxConnections ?? 0;\n\t\tif (maxConnections > 0 && connectionTracker.connections.size >= maxConnections) {\n\t\t\treturn new Response(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\terror: \"Service Unavailable\",\n\t\t\t\t\tmessage: \"Maximum connections reached. Please try again later.\",\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\tstatus: 503,\n\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// Track this connection\n\t\tconnectionTracker.connections.add(this);\n\n\t\tconst stream = new ReadableStream({\n\t\t\tstart: (controller) => {\n\t\t\t\tthis.controller = controller;\n\n\t\t\t\t// Send initial connection event\n\t\t\t\tif (this.options.sendInitial !== false) {\n\t\t\t\t\tconst eventName = this.options.initialEvent || \"connected\";\n\t\t\t\t\tthis.sendMessage({ event: eventName, data: \"connected\" });\n\t\t\t\t}\n\n\t\t\t\t// Send retry timeout - default 3000 jika tidak diisi tapi client expect\n\t\t\t\tif (this.options.retry !== undefined) {\n\t\t\t\t\tthis.sendRaw(`retry: ${this.options.retry}\\n\\n`);\n\t\t\t\t} else {\n\t\t\t\t\tthis.sendRaw(`retry: 3000\\n\\n`);\n\t\t\t\t}\n\n\t\t\t\t// Start heartbeat 30s fixed (industrial keep-alive)\n\t\t\t\tthis.startHeartbeat();\n\n\t\t\t\t// Handle client disconnect - once:true + cleanup\n\t\t\t\tthis.abortHandler = () => this.close();\n\t\t\t\tthis.request.signal.addEventListener(\"abort\", this.abortHandler, { once: true } as AddEventListenerOptions);\n\n\t\t\t\t// Replay missed events on reconnection - pakai store dulu, fallback onReconnect\n\t\t\t\tif (this.lastEventId) {\n\t\t\t\t\t// async tanpa block initial event\n\t\t\t\t\tqueueMicrotask(() => this.replayMissedEvents());\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancel: () => {\n\t\t\t\tthis.close();\n\t\t\t},\n\t\t});\n\n\t\tconst headers: Record<string, string> = {\n\t\t\t\"Content-Type\": \"text/event-stream; charset=utf-8\",\n\t\t\t\"Cache-Control\": \"no-cache, no-transform\",\n\t\t\tConnection: \"keep-alive\",\n\t\t\t\"X-Accel-Buffering\": \"no\", // Disable nginx buffering\n\t\t\t\"Content-Encoding\": \"none\",\n\t\t\t\"Cache-Control2\": \"no-cache\", // compat\n\t\t\t...this.options.headers,\n\t\t};\n\t\t// Explicit Transfer-Encoding chunked tidak perlu di Bun (auto), tapi keep header untuk proxy\n\t\treturn new Response(stream, {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/event-stream; charset=utf-8\",\n\t\t\t\t\"Cache-Control\": \"no-cache, no-transform\",\n\t\t\t\tConnection: \"keep-alive\",\n\t\t\t\t\"X-Accel-Buffering\": \"no\",\n\t\t\t\t...this.options.headers,\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Replay missed events from reconnection via historyStore / onReconnect\n\t */\n\tprivate async replayMissedEvents(): Promise<void> {\n\t\tif (!this.lastEventId) return;\n\n\t\ttry {\n\t\t\tlet missed: SSEMessage[] = [];\n\t\t\t// Prioritas: historyStore → onReconnect\n\t\t\tif (this.historyStore) {\n\t\t\t\tconst fromStore = await this.historyStore.getAfter(this.lastEventId);\n\t\t\t\tif (fromStore && fromStore.length > 0) missed = fromStore;\n\t\t\t}\n\t\t\tif (missed.length === 0 && this.options.onReconnect) {\n\t\t\t\tconst fromCb = await this.options.onReconnect(this.lastEventId);\n\t\t\t\tif (fromCb) missed = fromCb;\n\t\t\t}\n\t\t\tfor (const event of missed) {\n\t\t\t\tthis.send(event);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error(\"SSE reconnect replay error:\", error);\n\t\t}\n\t}\n\n\t/**\n\t * Send a message to the client - auto persist ke historyStore jika ada id\n\t */\n\tsend(message: SSEMessage): void {\n\t\tif (this.closed) return;\n\t\t// persist dulu untuk replay\n\t\tif (message.id !== undefined) {\n\t\t\ttry {\n\t\t\t\tconst r = this.historyStore.add(message);\n\t\t\t\tif (r instanceof Promise) r.catch(() => {});\n\t\t\t} catch {}\n\t\t}\n\t\tthis.sendMessage(message);\n\t}\n\n\t/**\n\t * Send a simple data message\n\t */\n\tsendData(data: string | object): void {\n\t\tthis.send({ data });\n\t}\n\n\t/**\n\t * Send a named event\n\t */\n\tsendEvent(event: string, data: string | object): void {\n\t\tthis.send({ event, data });\n\t}\n\n\t/**\n\t * Send a message with ID (for resumption)\n\t */\n\tsendWithId(id: string | number, data: string | object): void {\n\t\tthis.send({ id, data });\n\t}\n\n\t/**\n\t * Send SSE comment - untuk heartbeat custom\n\t */\n\tsendComment(comment: string): void {\n\t\tconst sanitized = String(comment).replace(/[\\r\\n]/g, \" \");\n\t\tthis.sendRaw(`: ${sanitized}\\n\\n`);\n\t}\n\n\tprivate disconnectCallbacks: Set<() => void> = new Set();\n\n\t/**\n\t * Register a callback to be called when the connection closes\n\t */\n\tonClose(callback: () => void): void {\n\t\tthis.disconnectCallbacks.add(callback);\n\t}\n\n\toffClose(callback: () => void): void {\n\t\tthis.disconnectCallbacks.delete(callback);\n\t}\n\n\t/**\n\t * Get the Last-Event-ID header value (for reconnection)\n\t */\n\tgetLastEventId(): string | null {\n\t\treturn this.lastEventId;\n\t}\n\n\t/**\n\t * Send raw string to the stream - dengan backpressure check\n\t */\n\tprivate sendRaw(raw: string): void {\n\t\tif (this.closed || !this.controller) return;\n\t\t// Backpressure: desiredSize <=0 berarti buffer penuh → drop atau tunggu\n\t\ttry {\n\t\t\tconst desired = (this.controller as unknown as { desiredSize?: number | null }).desiredSize;\n\t\t\tif (desired !== null && desired !== undefined && desired <= 0) {\n\t\t\t\tif (raw.startsWith(\":\")) return; // drop heartbeat jika penuh - jangan warn\n\t\t\t}\n\t\t\tthis.controller.enqueue(this.encoder.encode(raw));\n\t\t} catch (_error) {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/**\n\t * Validate event/id agar tidak break spec (no \\r \\n \\0)\n\t */\n\tprivate sanitizeField(value: string): string {\n\t\tif (/[\\r\\n\\0]/.test(value)) throw new Error(`Invalid SSE field contains newline: ${value}`);\n\t\treturn value;\n\t}\n\n\t/**\n\t * Format and send SSE message - sanitized\n\t */\n\tprivate sendMessage(message: SSEMessage): void {\n\t\tlet raw = \"\";\n\n\t\tif (message.id !== undefined) {\n\t\t\tconst idStr = String(message.id);\n\t\t\tthis.sanitizeField(idStr);\n\t\t\traw += `id: ${idStr}\\n`;\n\t\t}\n\t\tif (message.event) {\n\t\t\tthis.sanitizeField(message.event);\n\t\t\traw += `event: ${message.event}\\n`;\n\t\t}\n\n\t\tlet data: string;\n\t\tif (typeof message.data === \"object\") {\n\t\t\tif (message.data === null) data = \"null\";\n\t\t\telse data = JSON.stringify(message.data);\n\t\t} else {\n\t\t\tdata = String(message.data);\n\t\t}\n\n\t\t// SSE spec: data cannot contain single \\n, split ke multiple data: lines, handle \\r\\n\n\t\tconst dataLines = data.split(/\\r\\n|\\r|\\n/);\n\t\tfor (const line of dataLines) {\n\t\t\traw += `data: ${line}\\n`;\n\t\t}\n\n\t\traw += \"\\n\";\n\t\tthis.sendRaw(raw);\n\t}\n\n\t/**\n\t * Start heartbeat 30s fixed - keep-alive untuk LB/ALB\n\t */\n\tprivate startHeartbeat(): void {\n\t\t// 30s fixed sesuai instruksi - tidak configurable per request (industrial default)\n\t\tthis.heartbeatInterval = setInterval(() => {\n\t\t\tthis.sendRaw(\": heartbeat\\n\\n\");\n\t\t}, 30000);\n\t}\n\n\t/**\n\t * Close the SSE connection - idempotent + cleanup listener\n\t */\n\tclose(): void {\n\t\tif (this.closed) return;\n\t\tthis.closed = true;\n\n\t\t// Remove from global tracker\n\t\tconnectionTracker.connections.delete(this);\n\n\t\tfor (const cb of this.disconnectCallbacks) {\n\t\t\ttry {\n\t\t\t\tcb();\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error(\"SSE onClose error:\", e);\n\t\t\t}\n\t\t}\n\t\tthis.disconnectCallbacks.clear();\n\n\t\tif (this.abortHandler) {\n\t\t\ttry {\n\t\t\t\tthis.request.signal.removeEventListener(\"abort\", this.abortHandler);\n\t\t\t} catch {}\n\t\t\tthis.abortHandler = null;\n\t\t}\n\n\t\tif (this.heartbeatInterval) {\n\t\t\tclearInterval(this.heartbeatInterval);\n\t\t\tthis.heartbeatInterval = null;\n\t\t}\n\n\t\tif (this.controller) {\n\t\t\ttry {\n\t\t\t\tthis.controller.close();\n\t\t\t} catch (_e) {}\n\t\t\tthis.controller = null;\n\t\t}\n\t}\n\n\t/**\n\t * Check if connection is still open\n\t */\n\tget isConnected(): boolean {\n\t\treturn !this.closed;\n\t}\n\n\t/**\n\t * Get the number of active SSE connections\n\t */\n\tstatic get activeConnections(): number {\n\t\treturn connectionTracker.connections.size;\n\t}\n\n\t/**\n\t * Get all active SSE connections\n\t */\n\tstatic getActiveConnections(): ReadonlySet<SSE> {\n\t\treturn connectionTracker.connections;\n\t}\n\n\t/** Graceful close all - dipakai di App.setupGracefulShutdown */\n\tstatic closeAll(): void {\n\t\tfor (const c of [...connectionTracker.connections]) c.close();\n\t}\n}\n\n/**\n * SSE Broadcaster - in-memory default, pluggable ke Redis via pubSub\n *\n * @example Memory (default)\n * ```ts\n * const broadcaster = new SSEBroadcaster();\n * app.get(\"/events\", (ctx) => { const sse = createSSE(ctx.request); broadcaster.add(sse); sse.onClose(()=>broadcaster.remove(sse)); return sse.connect(); })\n * broadcaster.broadcast(\"update\", {count:42})\n * ```\n * @example Redis pluggable (mirip StorageDriver)\n * ```ts\n * class RedisSSEPubSub implements SSEPubSub { constructor(private redis: Redis){} publish(ch,msg){ redis.publish(ch, JSON.stringify(msg)) } subscribe(ch,cb){ redis.subscribe(ch,(m)=>cb(JSON.parse(m))); return ()=>redis.unsubscribe(ch)} }\n * const broadcaster = new SSEBroadcaster({ pubSub: new RedisSSEPubSub(redis), channel: \"buntok:sse\" })\n * ```\n */\nexport interface SSEBroadcasterOptions {\n\tpubSub?: SSEPubSub;\n\tchannel?: string;\n\thistoryStore?: SSEHistoryStore;\n}\nexport class SSEBroadcaster {\n\tprivate clients = new Set<SSE>();\n\tprivate pubSub?: SSEPubSub;\n\tprivate channel: string;\n\tprivate historyStore?: SSEHistoryStore;\n\tprivate unsubscribe?: () => void;\n\n\tconstructor(opts?: SSEBroadcasterOptions | SSEPubSub) {\n\t\t// backward compat: new SSEBroadcaster(pubSub)\n\t\tif (opts && typeof (opts as SSEPubSub).publish === \"function\" && typeof (opts as SSEPubSub).subscribe === \"function\") {\n\t\t\tthis.pubSub = opts as SSEPubSub;\n\t\t\tthis.channel = \"buntok:sse\";\n\t\t} else {\n\t\t\tconst o = opts as SSEBroadcasterOptions | undefined;\n\t\t\tthis.pubSub = o?.pubSub;\n\t\t\tthis.channel = o?.channel ?? \"buntok:sse\";\n\t\t\tthis.historyStore = o?.historyStore;\n\t\t}\n\t\tif (this.pubSub) {\n\t\t\tthis.unsubscribe = this.pubSub.subscribe(this.channel, (msg) => {\n\t\t\t\t// fan-out ke local clients tanpa loop publish lagi\n\t\t\t\tfor (const c of [...this.clients]) {\n\t\t\t\t\tif (c.isConnected) c.send(msg);\n\t\t\t\t\telse this.clients.delete(c);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Add an SSE connection to the broadcaster\n\t */\n\tadd(sse: SSE): void {\n\t\tthis.clients.add(sse);\n\t}\n\n\t/**\n\t * Remove an SSE connection from the broadcaster\n\t */\n\tremove(sse: SSE): void {\n\t\tthis.clients.delete(sse);\n\t}\n\n\t/**\n\t * Broadcast a named event to all connected clients - via pubSub jika ada\n\t */\n\tbroadcast(event: string, data: string | object): void {\n\t\tconst msg: SSEMessage = { event, data };\n\t\tif (this.pubSub) {\n\t\t\tconst r = this.pubSub.publish(this.channel, msg);\n\t\t\tif (r instanceof Promise) r.catch(() => this.localBroadcast(msg));\n\t\t\telse this.localBroadcast(msg);\n\t\t\treturn;\n\t\t}\n\t\tthis.localBroadcast(msg);\n\t}\n\n\tprivate localBroadcast(msg: SSEMessage): void {\n\t\tfor (const client of [...this.clients]) {\n\t\t\tif (client.isConnected) {\n\t\t\t\tclient.send(msg as SSEMessage);\n\t\t\t} else {\n\t\t\t\tthis.clients.delete(client);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Broadcast to clients matching a predicate\n\t */\n\tbroadcastWhere(\n\t\tpredicate: (sse: SSE) => boolean,\n\t\tevent: string,\n\t\tdata: string | object,\n\t): void {\n\t\tconst msg: SSEMessage = { event, data };\n\t\t// jika pubSub ada, tetap filter lokal (predicate tidak bisa di-remote)\n\t\tfor (const client of [...this.clients]) {\n\t\t\tif (!client.isConnected) {\n\t\t\t\tthis.clients.delete(client);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (predicate(client)) {\n\t\t\t\tclient.send(msg);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Send a message to all connected clients\n\t */\n\tsendAll(message: SSEMessage): void {\n\t\tif (this.pubSub) {\n\t\t\tconst r = this.pubSub.publish(this.channel, message);\n\t\t\tif (r instanceof Promise) r.catch(() => this.localSendAll(message));\n\t\t\telse this.localSendAll(message);\n\t\t\treturn;\n\t\t}\n\t\tthis.localSendAll(message);\n\t}\n\tprivate localSendAll(message: SSEMessage): void {\n\t\tfor (const client of [...this.clients]) {\n\t\t\tif (client.isConnected) client.send(message);\n\t\t\telse this.clients.delete(client);\n\t\t}\n\t}\n\n\t/**\n\t * Close all connections + unsubscribe pubSub\n\t */\n\tcloseAll(): void {\n\t\tif (this.unsubscribe) {\n\t\t\ttry { this.unsubscribe(); } catch {}\n\t\t\tthis.unsubscribe = undefined;\n\t\t}\n\t\tfor (const client of [...this.clients]) {\n\t\t\tclient.close();\n\t\t}\n\t\tthis.clients.clear();\n\t}\n\n\t/**\n\t * Get the number of connected clients\n\t */\n\tget size(): number {\n\t\t// Clean up disconnected clients\n\t\tfor (const client of [...this.clients]) {\n\t\t\tif (!client.isConnected) {\n\t\t\t\tthis.clients.delete(client);\n\t\t\t}\n\t\t}\n\t\treturn this.clients.size;\n\t}\n\n\t/**\n\t * Check if there are any connected clients\n\t */\n\tget isEmpty(): boolean {\n\t\treturn this.size === 0;\n\t}\n}\n\n/**\n * Create SSE helper from Buntok context - Bun-only\n */\nexport function createSSE(request: Request, options?: SSEOptions): SSE {\n\treturn new SSE(request, options);\n}\n","import { createSSE, type SSE, type SSEOptions } from \"./sse\";\nimport { getClientIP } from \"./helpers/network\";\n\nexport class Context<\n\tDI = Record<string, unknown>,\n\tParams = Record<string, string>,\n> {\n\tpublic request: Request;\n\tpublic params: Params & Record<string, string>;\n\tpublic user?: Record<string, unknown>;\n\n\tprivate _store: Record<string, unknown> | undefined;\n\tprivate _cookies: Record<string, string> | undefined;\n\tprivate _query: Record<string, string> | undefined;\n\tprivate _validated: Record<string, unknown> | undefined;\n\tpublic readonly di: DI;\n\tpublic _afterHooks?: Array<(res: Response) => Response | undefined>;\n\tprivate readonly clientIPResolver: (request: Request) => string;\n\n\tconstructor(request: Request, params: Record<string, string>, di: DI, clientIPResolver: (request: Request) => string = getClientIP) {\n\t\tthis.request = request;\n\t\tthis.params = params as unknown as Params & Record<string, string>;\n\t\tthis.di = di;\n\t\tthis.clientIPResolver = clientIPResolver;\n\t}\n\n\tpublic get store(): Record<string, unknown> {\n\t\tif (!this._store) {\n\t\t\tthis._store = {};\n\t\t}\n\t\treturn this._store;\n\t}\n\n\tpublic set store(value: Record<string, unknown>) {\n\t\tthis._store = value;\n\t}\n\n\tpublic get ip(): string {\n\t\treturn this.clientIPResolver(this.request);\n\t}\n\n\tprivate parseCookies(): Record<string, string> {\n\t\tif (this._cookies) return this._cookies;\n\n\t\tconst nativeCookies = (this.request as { cookies?: unknown }).cookies;\n\t\tif (nativeCookies && typeof nativeCookies === \"object\") {\n\t\t\tconst map = nativeCookies as Iterable<[string, string]>;\n\t\t\tconst result: Record<string, string> = {};\n\t\t\tfor (const [key, value] of map) {\n\t\t\t\tresult[key] = value;\n\t\t\t}\n\t\t\tthis._cookies = result;\n\t\t\treturn this._cookies;\n\t\t}\n\n\t\tconst cookieHeader = this.request.headers.get(\"Cookie\");\n\t\tif (!cookieHeader) {\n\t\t\tthis._cookies = {};\n\t\t\treturn this._cookies;\n\t\t}\n\n\t\tconst result: Record<string, string> = {};\n\t\tlet start = 0;\n\t\twhile (start < cookieHeader.length) {\n\t\t\tlet end = cookieHeader.indexOf(\";\", start);\n\t\t\tif (end === -1) end = cookieHeader.length;\n\n\t\t\tconst eqIdx = cookieHeader.indexOf(\"=\", start);\n\t\t\tif (eqIdx !== -1 && eqIdx < end) {\n\t\t\t\tlet keyStart = start;\n\t\t\t\twhile (keyStart < eqIdx && cookieHeader[keyStart] === \" \") keyStart++;\n\n\t\t\t\tlet valStart = eqIdx + 1;\n\t\t\t\twhile (valStart < end && cookieHeader[valStart] === \" \") valStart++;\n\n\t\t\t\tconst key = cookieHeader.substring(keyStart, eqIdx);\n\t\t\t\tconst val = cookieHeader.substring(valStart, end);\n\t\t\t\tif (key && val) result[key] = decodeURIComponent(val);\n\t\t\t}\n\t\t\tstart = end + 1;\n\t\t}\n\n\t\tthis._cookies = result;\n\t\treturn this._cookies;\n\t}\n\n\t/**\n\t * Get a cookie value from request\n\t */\n\tpublic getCookie(name: string): string | undefined {\n\t\tconst nativeCookies = (this.request as { cookies?: unknown }).cookies;\n\t\tif (\n\t\t\t!this._cookies &&\n\t\t\tnativeCookies &&\n\t\t\ttypeof (nativeCookies as { get?: unknown }).get === \"function\"\n\t\t) {\n\t\t\treturn (\n\t\t\t\t(nativeCookies as { get: (name: string) => string | null }).get(name) ??\n\t\t\t\tundefined\n\t\t\t);\n\t\t}\n\t\treturn this.parseCookies()[name];\n\t}\n\n\t/**\n\t * Get all cookies from request\n\t */\n\tpublic getCookies(): Record<string, string> {\n\t\treturn this.parseCookies();\n\t}\n\n\t/**\n\t * Parsed query string parameters - accessed as a plain property.\n\t * Parsed lazily and cached after first access.\n\t *\n\t * @example\n\t * // GET /search?q=buntok&limit=10\n\t * const { q, limit } = ctx.query;\n\t */\n\tpublic get query(): Record<string, string> {\n\t\tif (this._query) return this._query;\n\n\t\tthis._query = {};\n\t\tconst url = this.request.url;\n\t\tconst queryIdx = url.indexOf(\"?\");\n\t\tif (queryIdx !== -1) {\n\t\t\tconst queryStr = url.substring(queryIdx + 1);\n\t\t\tif (queryStr) {\n\t\t\t\tconst pairs = queryStr.split(\"&\");\n\t\t\t\tfor (let i = 0; i < pairs.length; i++) {\n\t\t\t\t\tconst pair = pairs[i] as string;\n\t\t\t\t\tif (!pair) continue;\n\t\t\t\t\tconst eqIdx = pair.indexOf(\"=\");\n\t\t\t\t\tif (eqIdx !== -1) {\n\t\t\t\t\t\tconst key = decodeURIComponent(\n\t\t\t\t\t\t\tpair.substring(0, eqIdx).replace(/\\+/g, \" \"),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst value = decodeURIComponent(\n\t\t\t\t\t\t\tpair.substring(eqIdx + 1).replace(/\\+/g, \" \"),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis._query[key] = value;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst key = decodeURIComponent(pair.replace(/\\+/g, \" \"));\n\t\t\t\t\t\tthis._query[key] = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this._query;\n\t}\n\n\t/**\n\t * Internal: used by validator middleware to stash parsed/validated data.\n\t * Not intended to be called directly from route handlers.\n\t */\n\tpublic setValidated(\n\t\ttarget: \"body\" | \"query\" | \"params\",\n\t\tdata: unknown,\n\t): void {\n\t\tif (!this._validated) this._validated = {};\n\t\tthis._validated[target] = data;\n\t}\n\n\t/**\n\t * Read data previously validated by `zValidator()` for the given target,\n\t * typed as `T`. Throws if no validator ran for that target, so a typo'd\n\t * target (or forgetting to add the middleware) fails loudly instead of\n\t * silently returning `undefined`.\n\t */\n\tpublic valid<T>(target: \"body\" | \"query\" | \"params\"): T {\n\t\tif (!this._validated || !(target in this._validated)) {\n\t\t\tthrow new Error(\n\t\t\t\t`ctx.valid(\"${target}\") called but no zValidator(\"${target}\", ...) middleware ran for this route`,\n\t\t\t);\n\t\t}\n\t\treturn this._validated[target] as T;\n\t}\n\n\tprivate _body: unknown | undefined;\n\n\tpublic async body<T>(): Promise<T> {\n\t\tif (this._body !== undefined) {\n\t\t\treturn this._body as T;\n\t\t}\n\t\tthis._body = await this.request.json();\n\t\treturn this._body as T;\n\t}\n\n\t// biome-ignore lint/suspicious/noExplicitAny: Undici types conflict with lib.dom FormData\n\tprivate _formData: any | undefined;\n\n\t/**\n\t * Parse and cache the multipart/form-data body.\n\t * Safe to call multiple times - the parsed FormData is cached after the first read,\n\t * so `zValidator(\"form\", ...)` and `uploader()` can both be used in the same route\n\t * without conflicting over the body stream.\n\t */\n\t// biome-ignore lint/suspicious/noExplicitAny: Undici types conflict with lib.dom FormData\n\tpublic async formData(): Promise<any> {\n\t\tif (this._formData !== undefined) {\n\t\t\treturn this._formData;\n\t\t}\n\t\tthis._formData = await this.request.formData();\n\t\treturn this._formData;\n\t}\n\n\tpublic json(data: unknown, status = 200): Response {\n\t\tif (status === 200) {\n\t\t\treturn Response.json(data);\n\t\t}\n\t\treturn Response.json(data, { status });\n\t}\n\n\tpublic success(data?: unknown, message = \"Success\", status = 200): Response {\n\t\treturn this.json({ success: true, message, data }, status);\n\t}\n\n\t/**\n\t * Standardize an offset-based pagination response.\n\t */\n\tpublic paginate<T>(\n\t\tdata: T[],\n\t\ttotal: number,\n\t\tpage: number,\n\t\tlimit: number,\n\t\tmessage = \"Success\",\n\t\tstatus = 200,\n\t): Response {\n\t\treturn this.json(\n\t\t\t{\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage,\n\t\t\t\tdata,\n\t\t\t\tmeta: {\n\t\t\t\t\tcurrentPage: page,\n\t\t\t\t\tperPage: limit,\n\t\t\t\t\ttotal,\n\t\t\t\t\tlastPage: Math.ceil(total / limit),\n\t\t\t\t\thasMore: page * limit < total,\n\t\t\t\t},\n\t\t\t},\n\t\t\tstatus,\n\t\t);\n\t}\n\n\t/**\n\t * Standardize a cursor-based pagination response (infinite scroll).\n\t */\n\tpublic cursorPaginate<T>(\n\t\tdata: T[],\n\t\tnextCursor: string | number | null,\n\t\tmessage = \"Success\",\n\t\tstatus = 200,\n\t): Response {\n\t\treturn this.json(\n\t\t\t{\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage,\n\t\t\t\tdata,\n\t\t\t\tmeta: {\n\t\t\t\t\tnextCursor,\n\t\t\t\t\thasMore: nextCursor !== null,\n\t\t\t\t},\n\t\t\t},\n\t\t\tstatus,\n\t\t);\n\t}\n\n\tpublic error(message: string, status = 400, details?: unknown): Response {\n\t\treturn this.json({ success: false, message, details }, status);\n\t}\n\n\tprivate static readonly TEXT_HEADERS = {\n\t\t\"Content-Type\": \"text/plain; charset=utf-8\",\n\t};\n\n\tpublic text(text: string, status = 200): Response {\n\t\tif (status === 200) {\n\t\t\treturn new Response(text);\n\t\t}\n\t\treturn new Response(text, {\n\t\t\tstatus,\n\t\t\theaders: Context.TEXT_HEADERS,\n\t\t});\n\t}\n\n\tprivate static readonly HTML_HEADERS = { \"Content-Type\": \"text/html\" };\n\t/**\n\t * Return HTML response\n\t */\n\tpublic html(html: string, status = 200): Response {\n\t\treturn new Response(html, {\n\t\t\tstatus,\n\t\t\theaders: Context.HTML_HEADERS,\n\t\t});\n\t}\n\n\t/**\n\t * Streaming HTML response using an async generator.\n\t * Yields HTML chunks progressively to the client.\n\t *\n\t * @example\n\t * ```ts\n\t * app.get('/stream', (ctx) => {\n\t *   return ctx.htmlStream(async function* () {\n\t *     yield '<!DOCTYPE html><html><body>';\n\t *     const data = await fetchData();\n\t *     yield `<p>${data}</p>`;\n\t *     yield '</body></html>';\n\t *   });\n\t * });\n\t * ```\n\t */\n\tpublic htmlStream(\n\t\tgenerator: AsyncIterable<string>,\n\t\toptions?: { status?: number; headers?: Record<string, string> },\n\t): Response {\n\t\tconst iterator = generator[Symbol.asyncIterator]();\n\t\tconst stream = new ReadableStream({\n\t\t\tasync pull(controller) {\n\t\t\t\tconst { value, done } = await iterator.next();\n\t\t\t\tif (done) {\n\t\t\t\t\tcontroller.close();\n\t\t\t\t} else {\n\t\t\t\t\tcontroller.enqueue(new TextEncoder().encode(value));\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\treturn new Response(stream, {\n\t\t\tstatus: options?.status ?? 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/html; charset=utf-8\",\n\t\t\t\t\"Transfer-Encoding\": \"chunked\",\n\t\t\t\t...options?.headers,\n\t\t\t},\n\t\t});\n\t}\n\n\tpublic onAfterResponse(hook: (res: Response) => Response | undefined): void {\n\t\tif (!this._afterHooks) this._afterHooks = [];\n\t\tthis._afterHooks.push(hook);\n\t}\n\n\t/**\n\t * Redirect to URL\n\t */\n\tpublic redirect(\n\t\turl: string,\n\t\tstatus: 301 | 302 | 303 | 307 | 308 = 302,\n\t): Response {\n\t\treturn new Response(null, {\n\t\t\tstatus,\n\t\t\theaders: { Location: url },\n\t\t});\n\t}\n\n\t/**\n\t * Return empty response with status code\n\t */\n\tpublic status(code: number): Response {\n\t\treturn new Response(null, { status: code });\n\t}\n\n\t/**\n\t * Start a Server-Sent Events (SSE) stream - Bun-only\n\t */\n\tpublic sse(\n\t\tcallback: (stream: SSE) => void | Promise<void>,\n\t\toptions?: SSEOptions,\n\t): Response {\n\t\tconst stream = createSSE(this.request, options);\n\n\t\t// queueMicrotask lebih cepat dari setTimeout(0) - tanpa macrotask latency\n\t\tqueueMicrotask(async () => {\n\t\t\ttry {\n\t\t\t\tawait callback(stream);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[SSE Error]\", err);\n\t\t\t\ttry { stream.sendEvent(\"error\", String((err as Error).message)); } catch { }\n\t\t\t\tstream.close();\n\t\t\t}\n\t\t});\n\n\t\treturn stream.connect();\n\t}\n}\n","import { appendFile, existsSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport enum LogLevel {\n\tDEBUG = 0,\n\tINFO = 1,\n\tWARN = 2,\n\tERROR = 3,\n}\n\nexport interface LoggerOptions {\n\tlevel?: LogLevel;\n\tformat?: \"text\" | \"json\";\n\t// Disable request logging (useful for benchmarks)\n\tlogRequests?: boolean;\n\t// Buffer settings\n\tflushInterval?: number; // ms between auto-flush (default: 2000)\n\tflushThreshold?: number; // lines before forced flush (default: 100)\n\t// Custom redaction patterns (merged with built-in SENSITIVE_KEY)\n\tredactPatterns?: (string | RegExp)[];\n\t// Custom redaction replacement text (default: \"[REDACTED]\")\n\tredactReplacement?: string;\n}\n\nconst REDACTED = \"[REDACTED]\";\nconst DEFAULT_SENSITIVE = /authorization|cookie|password|passwd|secret|token|api[-_]?key|database[-_]?url/i;\n\nfunction buildRedactRegex(patterns: (string | RegExp)[]): RegExp {\n\tconst sources = patterns.map((p) => (typeof p === \"string\" ? p : p.source));\n\treturn new RegExp(sources.join(\"|\"), \"i\");\n}\n\n/** Redact credentials and secrets from structured log metadata. */\nexport function redactLogMeta<T>(\n\tvalue: T,\n\tseen = new WeakSet<object>(),\n\textraPatterns?: (string | RegExp)[],\n\treplacement = REDACTED,\n): T {\n\tif (typeof value === \"string\" || value === null || typeof value !== \"object\") {\n\t\treturn value;\n\t}\n\tif (seen.has(value)) return \"[Circular]\" as T;\n\tseen.add(value);\n\n\tif (Array.isArray(value)) {\n\t\treturn value.map((item) => redactLogMeta(item, seen, extraPatterns, replacement)) as T;\n\t}\n\n\tconst regex = extraPatterns ? buildRedactRegex([DEFAULT_SENSITIVE, ...extraPatterns]) : DEFAULT_SENSITIVE;\n\tconst result: Record<string, unknown> = {};\n\tfor (const [key, item] of Object.entries(value)) {\n\t\tresult[key] = regex.test(key)\n\t\t\t? replacement\n\t\t\t: redactLogMeta(item, seen, extraPatterns, replacement);\n\t}\n\treturn result as T;\n}\n\n// Pre-computed ANSI colors for each log level\nconst COLORS: Record<number, string> = {\n\t[LogLevel.DEBUG]: \"\\x1b[34m\", // Blue\n\t[LogLevel.INFO]: \"\\x1b[32m\", // Green\n\t[LogLevel.WARN]: \"\\x1b[33m\", // Yellow\n\t[LogLevel.ERROR]: \"\\x1b[31m\", // Red\n};\nconst RESET = \"\\x1b[0m\";\nconst GRAY = \"\\x1b[90m\";\n\nexport class Logger {\n\tprivate level: LogLevel;\n\tprivate format: \"text\" | \"json\";\n\tprivate logDir: string | undefined;\n\tprivate isProd: boolean;\n\tprivate _logRequests: boolean;\n\n\t// Buffered file writer\n\tprivate fileBuffer: string[] = [];\n\tprivate flushTimer: ReturnType<typeof setInterval> | null = null;\n\tprivate flushInterval: number;\n\tprivate flushThreshold: number;\n\tprivate flushing = false;\n\n\t// Stdout/stderr buffer (non-blocking terminal output)\n\tprivate flushScheduled = false;\n\tprivate stdoutBuffer: string[] = [];\n\tprivate stderrBuffer: string[] = [];\n\n\t// Redaction\n\tprivate redactPatterns?: (string | RegExp)[];\n\tprivate redactReplacement: string;\n\n\tconstructor(options?: LoggerOptions) {\n\t\tthis.isProd = process.env.NODE_ENV === \"production\";\n\t\tthis.level =\n\t\t\toptions?.level ?? (this.isProd ? LogLevel.WARN : LogLevel.INFO);\n\t\tthis.format = options?.format ?? (this.isProd ? \"json\" : \"text\");\n\t\tthis._logRequests = options?.logRequests ?? (process.env.LOG_REQUESTS === \"true\" ? true : process.env.LOG_REQUESTS === \"false\" ? false : process.env.NODE_ENV !== \"production\");\n\t\tthis.flushInterval = options?.flushInterval ?? 2000;\n\t\tthis.flushThreshold = options?.flushThreshold ?? 100;\n\t\tthis.redactPatterns = options?.redactPatterns;\n\t\tthis.redactReplacement = options?.redactReplacement ?? REDACTED;\n\n\t\tthis.logDir = process.env.LOG_DIR;\n\t\tif (this.logDir && !existsSync(this.logDir)) {\n\t\t\tmkdirSync(this.logDir, { recursive: true });\n\t\t}\n\n\t\t// Start flush timer if file logging is enabled\n\t\tif (this.logDir) {\n\t\t\tthis.flushTimer = setInterval(() => this.flushFileBuffer(), this.flushInterval);\n\t\t\t// Allow process to exit even if timer is running\n\t\t\tif (this.flushTimer && typeof this.flushTimer.unref === \"function\") {\n\t\t\t\tthis.flushTimer.unref();\n\t\t\t}\n\t\t}\n\t}\n\n\t// Flush stdout/stderr to terminal\n\tprivate flush() {\n\t\tif (this.stdoutBuffer.length > 0) {\n\t\t\tprocess.stdout.write(this.stdoutBuffer.join(\"\"));\n\t\t\tthis.stdoutBuffer.length = 0;\n\t\t}\n\t\tif (this.stderrBuffer.length > 0) {\n\t\t\tprocess.stderr.write(this.stderrBuffer.join(\"\"));\n\t\t\tthis.stderrBuffer.length = 0;\n\t\t}\n\t\tthis.flushScheduled = false;\n\t}\n\n\tprivate scheduleFlush() {\n\t\tif (this.flushScheduled) return;\n\t\tthis.flushScheduled = true;\n\t\tqueueMicrotask(() => this.flush());\n\t}\n\n\t// Flush buffered log lines to file (batch write)\n\tprivate flushFileBuffer() {\n\t\tif (this.fileBuffer.length === 0 || !this.logDir) return;\n\t\tif (this.flushing) return; // prevent concurrent writes\n\n\t\tthis.flushing = true;\n\t\tconst lines = this.fileBuffer.splice(0); // take all buffered lines\n\t\tconst data = lines.join(\"\");\n\n\t\t// Determine date from first line's timestamp\n\t\tconst now = new Date();\n\t\tconst dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, \"0\")}-${String(now.getDate()).padStart(2, \"0\")}`;\n\t\tconst filePath = join(this.logDir, `app-${dateStr}.log`);\n\n\t\tappendFile(filePath, data, (err) => {\n\t\t\tif (err) {\n\t\t\t\t// Write failed lines back to buffer for retry\n\t\t\t\tthis.fileBuffer.unshift(...lines);\n\t\t\t}\n\t\t\tthis.flushing = false;\n\t\t});\n\t}\n\n\t// Enqueue a line for file writing\n\tprivate enqueueFile(line: string) {\n\t\tthis.fileBuffer.push(line);\n\t\tif (this.fileBuffer.length >= this.flushThreshold) {\n\t\t\tthis.flushFileBuffer();\n\t\t}\n\t}\n\n\tprivate print(\n\t\tlevel: LogLevel,\n\t\tlevelName: string,\n\t\tmessage: string,\n\t\tmeta?: Record<string, unknown>,\n\t) {\n\t\tif (level < this.level) return;\n\t\tconst safeMeta = meta\n\t\t\t? this.redactPatterns\n\t\t\t\t? redactLogMeta(meta, new WeakSet(), this.redactPatterns, this.redactReplacement)\n\t\t\t\t: meta\n\t\t\t: undefined;\n\n\t\tconst isStderr = level === LogLevel.ERROR;\n\n\t\tif (this.format === \"json\") {\n\t\t\tconst timestamp = new Date().toISOString();\n\t\t\tconst logEntryObj = { timestamp, level: levelName, message, ...safeMeta };\n\t\t\tconst jsonString = JSON.stringify(logEntryObj);\n\t\t\tconst line = `${jsonString}\\n`;\n\n\t\t\t// Non-blocking: buffer and schedule flush\n\t\t\tif (isStderr) {\n\t\t\t\tthis.stderrBuffer.push(line);\n\t\t\t} else {\n\t\t\t\tthis.stdoutBuffer.push(line);\n\t\t\t}\n\t\t\tthis.scheduleFlush();\n\n\t\t\t// File logging (buffered batch write)\n\t\t\tif (this.logDir) {\n\t\t\t\tthis.enqueueFile(line);\n\t\t\t}\n\t\t} else {\n\t\t\tconst now = Date.now();\n\t\t\tconst color = COLORS[level] ?? COLORS[LogLevel.INFO];\n\n\t\t\tlet logString = `[${now}] ${color}[${levelName}]${RESET} ${message}`;\n\n\t\t\tif (safeMeta) {\n\t\t\t\tconst keys = Object.keys(safeMeta);\n\t\t\t\tif (keys.length > 0) {\n\t\t\t\t\tif (keys.length === 1) {\n\t\t\t\t\t\tconst val = safeMeta[keys[0] || 0];\n\t\t\t\t\t\tlogString += ` ${GRAY}{${JSON.stringify(keys[0])}:${JSON.stringify(val)}}${RESET}`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogString += ` ${GRAY}${JSON.stringify(safeMeta)}${RESET}`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Non-blocking: buffer and schedule flush\n\t\t\tif (isStderr) {\n\t\t\t\tthis.stderrBuffer.push(`${logString}\\n`);\n\t\t\t} else {\n\t\t\t\tthis.stdoutBuffer.push(`${logString}\\n`);\n\t\t\t}\n\t\t\tthis.scheduleFlush();\n\n\t\t\t// File logging (buffered batch write) - strip ANSI for clean log files\n\t\t\tif (this.logDir) {\n\t\t\t\tconst cleanLine = `[${now}] [${levelName}] ${message}${safeMeta ? ` ${JSON.stringify(safeMeta)}` : \"\"}\\n`;\n\t\t\t\tthis.enqueueFile(cleanLine);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic debug(message: string, meta?: Record<string, unknown>) {\n\t\tthis.print(LogLevel.DEBUG, \"DEBUG\", message, meta);\n\t}\n\n\tpublic info(message: string, meta?: Record<string, unknown>) {\n\t\tthis.print(LogLevel.INFO, \"INFO\", message, meta);\n\t}\n\n\tpublic warn(message: string, meta?: Record<string, unknown>) {\n\t\tthis.print(LogLevel.WARN, \"WARN\", message, meta);\n\t}\n\n\tpublic error(message: string, meta?: Record<string, unknown>) {\n\t\tthis.print(LogLevel.ERROR, \"ERROR\", message, meta);\n\t}\n\n\tpublic get logRequests(): boolean {\n\t\treturn this._logRequests;\n\t}\n\n\t// Flush all buffers (useful for graceful shutdown)\n\tpublic flushSync() {\n\t\t// Flush terminal\n\t\tif (this.stdoutBuffer.length > 0) {\n\t\t\tprocess.stdout.write(this.stdoutBuffer.join(\"\"));\n\t\t\tthis.stdoutBuffer.length = 0;\n\t\t}\n\t\tif (this.stderrBuffer.length > 0) {\n\t\t\tprocess.stderr.write(this.stderrBuffer.join(\"\"));\n\t\t\tthis.stderrBuffer.length = 0;\n\t\t}\n\t\t// Flush file buffer synchronously\n\t\tif (this.flushTimer) {\n\t\t\tclearInterval(this.flushTimer);\n\t\t\tthis.flushTimer = null;\n\t\t}\n\t\t// One final async flush for remaining file lines\n\t\tif (this.fileBuffer.length > 0 && this.logDir) {\n\t\t\tconst lines = this.fileBuffer.splice(0);\n\t\t\tconst data = lines.join(\"\");\n\t\t\tconst now = new Date();\n\t\t\tconst dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, \"0\")}-${String(now.getDate()).padStart(2, \"0\")}`;\n\t\t\tconst filePath = join(this.logDir, `app-${dateStr}.log`);\n\t\t\t// Synchronous append for shutdown\n\t\t\ttry {\n\t\t\t\tconst { writeFileSync, appendFileSync } = require(\"node:fs\");\n\t\t\t\tappendFileSync(filePath, data);\n\t\t\t} catch {\n\t\t\t\t// Best effort\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Create logger with env-based configuration\nexport const logger = new Logger();\n","// ─── JS Fallback: Route Trie ──────────────────────────────────────────────────\n\ntype NodeType = \"static\" | \"param\" | \"catchall\";\n\ninterface TrieNode {\n\tchildren: Map<string, TrieNode>;\n\tparamChild: TrieNode | null;\n\tcatchAllChild: TrieNode | null;\n\thandlerId: number;\n\tparamName: string | null;\n\tnodeType: NodeType;\n}\n\nfunction createNode(nodeType: NodeType = \"static\"): TrieNode {\n\treturn {\n\t\tchildren: new Map(),\n\t\tparamChild: null,\n\t\tcatchAllChild: null,\n\t\thandlerId: -1,\n\t\tparamName: null,\n\t\tnodeType,\n\t};\n}\n\nfunction splitPath(path: string): string[] {\n\tconst segments: string[] = [];\n\tlet start = path[0] === \"/\" ? 1 : 0;\n\tfor (let i = start; i < path.length; i++) {\n\t\tif (path[i] === \"/\") {\n\t\t\tif (i > start) {\n\t\t\t\tsegments.push(path.substring(start, i));\n\t\t\t}\n\t\t\tstart = i + 1;\n\t\t}\n\t}\n\tif (start < path.length) {\n\t\tsegments.push(path.substring(start));\n\t}\n\treturn segments;\n}\n\n// ─── JS Fallback: Trie Implementation ────────────────────────────────────────\n\nexport class JSTrie {\n\tprivate root: TrieNode;\n\tprivate nodeCount: number = 0;\n\n\tconstructor() {\n\t\tthis.root = createNode();\n\t}\n\n\tinsert(path: string, handlerId: number): void {\n\t\tconst segments = splitPath(path);\n\t\tlet current = this.root;\n\n\t\tfor (const segment of segments) {\n\t\t\tif (segment.length === 0) continue;\n\n\t\t\tlet nodeType: NodeType = \"static\";\n\t\t\tlet cleanSegment = segment;\n\t\t\tlet paramName: string | null = null;\n\n\t\t\tif (segment[0] === \":\") {\n\t\t\t\tnodeType = \"param\";\n\t\t\t\tparamName = segment.slice(1);\n\t\t\t\tcleanSegment = \":\";\n\t\t\t} else if (segment[0] === \"*\") {\n\t\t\t\tnodeType = \"catchall\";\n\t\t\t\tparamName = segment.slice(1);\n\t\t\t\tcleanSegment = \"*\";\n\t\t\t}\n\n\t\t\tlet nextNode: TrieNode | null = null;\n\n\t\t\tif (nodeType === \"static\") {\n\t\t\t\tnextNode = current.children.get(cleanSegment) ?? null;\n\t\t\t} else if (nodeType === \"param\") {\n\t\t\t\tnextNode = current.paramChild;\n\t\t\t} else {\n\t\t\t\tnextNode = current.catchAllChild;\n\t\t\t}\n\n\t\t\tif (!nextNode) {\n\t\t\t\tnextNode = createNode(nodeType);\n\t\t\t\tnextNode.paramName = paramName;\n\n\t\t\t\tif (nodeType === \"static\") {\n\t\t\t\t\tcurrent.children.set(cleanSegment, nextNode);\n\t\t\t\t} else if (nodeType === \"param\") {\n\t\t\t\t\tcurrent.paramChild = nextNode;\n\t\t\t\t} else {\n\t\t\t\t\tcurrent.catchAllChild = nextNode;\n\t\t\t\t}\n\t\t\t\tthis.nodeCount++;\n\t\t\t}\n\n\t\t\tcurrent = nextNode;\n\n\t\t\tif (nodeType === \"catchall\") break;\n\t\t}\n\n\t\tcurrent.handlerId = handlerId;\n\t}\n\n\tfind(path: string): { handlerId: number; params: Record<string, string> } {\n\t\tlet current = this.root;\n\t\tconst params: Record<string, string> = {};\n\t\tlet start = path[0] === \"/\" ? 1 : 0;\n\n\t\tif (start >= path.length) {\n\t\t\treturn { handlerId: current.handlerId, params };\n\t\t}\n\n\t\twhile (start < path.length) {\n\t\t\tlet end = path.indexOf(\"/\", start);\n\t\t\tif (end === -1) end = path.length;\n\n\t\t\tif (end > start) {\n\t\t\t\tconst segment = path.substring(start, end);\n\t\t\t\tlet nextNode = current.children.get(segment);\n\n\t\t\t\tif (!nextNode) {\n\t\t\t\t\tif (current.paramChild) {\n\t\t\t\t\t\tnextNode = current.paramChild;\n\t\t\t\t\t\tif (nextNode.paramName) {\n\t\t\t\t\t\t\tparams[nextNode.paramName] = segment;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (current.catchAllChild) {\n\t\t\t\t\t\tnextNode = current.catchAllChild;\n\t\t\t\t\t\tparams[\"*\"] = path.substring(start);\n\t\t\t\t\t\tcurrent = nextNode;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn { handlerId: -1, params };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcurrent = nextNode;\n\t\t\t}\n\t\t\tstart = end + 1;\n\t\t}\n\n\t\treturn { handlerId: current.handlerId, params };\n\t}\n\n\tgetNodeCount(): number {\n\t\treturn this.nodeCount;\n\t}\n}\n\n// ─── JS Fallback: JSON Escape ────────────────────────────────────────────────\n\nexport function jsEscapeString(str: string): string {\n\treturn JSON.stringify(str);\n}\n\n// ─── JS Fallback: Query Parser ───────────────────────────────────────────────\n\nexport function jsParseQuery(query: string): Record<string, string> {\n\tif (!query) return {};\n\n\tconst params: Record<string, string> = {};\n\tconst pairs = query.split(\"&\");\n\n\tfor (const pair of pairs) {\n\t\tif (!pair) continue;\n\t\tconst eqIdx = pair.indexOf(\"=\");\n\t\tlet key: string;\n\t\tlet value: string;\n\n\t\tif (eqIdx === -1) {\n\t\t\tkey = pair;\n\t\t\tvalue = \"\";\n\t\t} else {\n\t\t\tkey = pair.substring(0, eqIdx);\n\t\t\tvalue = pair.substring(eqIdx + 1);\n\t\t}\n\n\t\tparams[decodeURIComponent(key)] = decodeURIComponent(value);\n\t}\n\n\treturn params;\n}\n\n// ─── JS Fallback: Cookie Parser ──────────────────────────────────────────────\n\nexport function jsParseCookies(cookieHeader: string): Record<string, string> {\n\tif (!cookieHeader) return {};\n\n\tconst cookies: Record<string, string> = {};\n\tconst pairs = cookieHeader.split(\";\");\n\n\tfor (const pair of pairs) {\n\t\tconst trimmed = pair.trim();\n\t\tif (!trimmed) continue;\n\n\t\tconst eqIdx = trimmed.indexOf(\"=\");\n\t\tlet name: string;\n\t\tlet value: string;\n\n\t\tif (eqIdx === -1) {\n\t\t\tname = trimmed;\n\t\t\tvalue = \"\";\n\t\t} else {\n\t\t\tname = trimmed.substring(0, eqIdx);\n\t\t\tvalue = trimmed.substring(eqIdx + 1);\n\t\t}\n\n\t\tcookies[name] = value;\n\t}\n\n\treturn cookies;\n}\n","import {\n\tJSTrie,\n\tjsEscapeString,\n\tjsParseCookies,\n\tjsParseQuery,\n} from \"./fallback\";\n\n// ─── Lazy Native Loading ─────────────────────────────────────────────────────\n\nlet _nativeAvailable: boolean | undefined;\n// biome-ignore lint/suspicious/noExplicitAny: FFI libs are dynamic\nlet _nativeJsonLib: any;\n// biome-ignore lint/suspicious/noExplicitAny: FFI ptr cache\nlet _ffi: any;\n\nfunction tryLoadNative(): void {\n\tif (_nativeAvailable !== undefined) return;\n\ttry {\n\t\t// biome-ignore lint: dynamic require for optional FFI\n\t\t_ffi = require(\"bun:ffi\");\n\t\t// biome-ignore lint: dynamic require\n\t\tconst fs = require(\"node:fs\");\n\t\t// biome-ignore lint: dynamic require\n\t\tconst path = require(\"node:path\");\n\n\t\tconst ext =\n\t\t\tprocess.platform === \"win32\"\n\t\t\t\t? \".dll\"\n\t\t\t\t: process.platform === \"darwin\"\n\t\t\t\t\t? \".dylib\"\n\t\t\t\t\t: \".so\";\n\t\tconst prefix = process.platform === \"win32\" ? \"\" : \"lib\";\n\n\t\tfunction findLib(name: string): string {\n\t\t\tconst candidates = [\n\t\t\t\tpath.join(\n\t\t\t\t\tprocess.cwd(),\n\t\t\t\t\t\"node_modules\",\n\t\t\t\t\t\".buntok-native\",\n\t\t\t\t\t`${prefix}${name}${ext}`,\n\t\t\t\t),\n\t\t\t\tpath.join(process.cwd(), \"dist\", \"native\", `${prefix}${name}${ext}`),\n\t\t\t\tpath.join(process.cwd(), \"zig-out\", \"lib\", `${prefix}${name}${ext}`),\n\t\t\t];\n\t\t\tfor (const p of candidates) {\n\t\t\t\tif (fs.existsSync(p)) return p;\n\t\t\t}\n\t\t\treturn \"\";\n\t\t}\n\n\t\tconst FFIType = _ffi.FFIType;\n\t\tconst jsonPath = findLib(\"buntok_json\");\n\n\t\tif (jsonPath) {\n\t\t\t_nativeJsonLib = _ffi.dlopen(jsonPath, {\n\t\t\t\tjson_init: { args: [], returns: FFIType.void },\n\t\t\t\tjson_deinit: { args: [], returns: FFIType.void },\n\t\t\t\tjson_escape_string: {\n\t\t\t\t\targs: [FFIType.ptr, FFIType.u32, FFIType.ptr, FFIType.ptr],\n\t\t\t\t\treturns: FFIType.i32,\n\t\t\t\t},\n\t\t\t});\n\t\t\t_nativeJsonLib.symbols.json_init();\n\t\t}\n\n\t\t_nativeAvailable = true;\n\t} catch {\n\t\t_nativeAvailable = false;\n\t}\n}\n\n// ─── Trie ────────────────────────────────────────────────────────────────────\n\n// Native trie removed - JS trie is faster when not doing double-walk.\n// Benchmark: native+JS was 38% SLOWER than JS-only due to syncing overhead.\n// JS engines optimize Map.get/set in native C++, so pure JS is optimal.\n\nexport class Trie {\n\tprivate jsImpl: JSTrie;\n\n\tconstructor() {\n\t\tthis.jsImpl = new JSTrie();\n\t}\n\n\tinsert(path: string, handlerId: number): void {\n\t\tthis.jsImpl.insert(path, handlerId);\n\t}\n\n\tfind(path: string): { handlerId: number; params: Record<string, string> } {\n\t\treturn this.jsImpl.find(path);\n\t}\n\n\tgetNodeCount(): number {\n\t\treturn this.jsImpl.getNodeCount();\n\t}\n}\n\n// ─── JSON Escape ─────────────────────────────────────────────────────────────\n\nexport function escapeString(str: string): string {\n\tif (_nativeAvailable && _nativeJsonLib) {\n\t\ttry {\n\t\t\tconst inputBuf = Buffer.from(str, \"utf-8\");\n\t\t\tconst outputPtrBuf = Buffer.alloc(8);\n\t\t\tconst outputLenBuf = Buffer.alloc(4);\n\n\t\t\tconst result = _nativeJsonLib.symbols.json_escape_string(\n\t\t\t\t_ffi.ptr(inputBuf),\n\t\t\t\tinputBuf.length,\n\t\t\t\t_ffi.ptr(outputPtrBuf),\n\t\t\t\t_ffi.ptr(outputLenBuf),\n\t\t\t);\n\n\t\t\tif (result === 0) {\n\t\t\t\tconst outLen = outputLenBuf.readUint32LE(0);\n\t\t\t\tconst outPtr = outputPtrBuf.readBigUInt64LE(0);\n\t\t\t\t// biome-ignore lint: reading native memory via FFI\n\t\t\t\tconst mem = new ArrayBuffer(Number(outPtr) + outLen);\n\t\t\t\tconst outBuf = Buffer.from(new Uint8Array(mem, Number(outPtr), outLen));\n\t\t\t\treturn outBuf.toString(\"utf-8\");\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to JS\n\t\t}\n\t}\n\treturn jsEscapeString(str);\n}\n\n// ─── Query Parser ────────────────────────────────────────────────────────────\n\nexport function parseQuery(query: string): Record<string, string> {\n\treturn jsParseQuery(query);\n}\n\n// ─── Cookie Parser ───────────────────────────────────────────────────────────\n\nexport function parseCookies(cookieHeader: string): Record<string, string> {\n\treturn jsParseCookies(cookieHeader);\n}\n\n// ─── Status ──────────────────────────────────────────────────────────────────\n\nexport function isNativeAvailable(): boolean {\n\ttryLoadNative();\n\treturn _nativeAvailable === true;\n}\n\nexport function getBackend(): \"native\" | \"js\" {\n\treturn isNativeAvailable() ? \"native\" : \"js\";\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","import type { Middleware } from \"../app\";\nimport { toResponse } from \"../helpers/response\";\n\nexport interface CorsOptions {\n\torigin?: string | string[] | ((origin: string) => boolean);\n\tmethods?: string[];\n\theaders?: string[];\n\tcredentials?: boolean;\n}\n\nexport function resolveOrigin(\n\trequestOrigin: string,\n\toptions: CorsOptions,\n): string {\n\tlet allowedOrigin = \"*\";\n\n\tif (typeof options.origin === \"function\") {\n\t\tallowedOrigin = options.origin(requestOrigin) ? requestOrigin : \"\";\n\t} else if (Array.isArray(options.origin)) {\n\t\tallowedOrigin = options.origin.includes(requestOrigin)\n\t\t\t? requestOrigin\n\t\t\t: \"\";\n\t} else if (options.origin) {\n\t\tallowedOrigin = options.origin;\n\t}\n\n\treturn allowedOrigin;\n}\n\nexport function applyCorsHeaders(\n\tresponse: Response,\n\trequestOrigin: string,\n\toptions: CorsOptions,\n): void {\n\tconst allowedOrigin = resolveOrigin(requestOrigin, options);\n\tresponse.headers.set(\"Access-Control-Allow-Origin\", allowedOrigin);\n\tif (options.credentials)\n\t\tresponse.headers.set(\"Access-Control-Allow-Credentials\", \"true\");\n}\n\nexport const cors = (options: CorsOptions = {}): Middleware => {\n\treturn async (ctx, next) => {\n\t\tconst requestOrigin = ctx.request.headers.get(\"Origin\") || \"*\";\n\t\tconst allowedOrigin = resolveOrigin(requestOrigin, options);\n\n\t\tif (ctx.request.method === \"OPTIONS\") {\n\t\t\tconst res = new Response(null, { status: 204 });\n\t\t\tres.headers.set(\"Access-Control-Allow-Origin\", allowedOrigin);\n\t\t\tres.headers.set(\n\t\t\t\t\"Access-Control-Allow-Methods\",\n\t\t\t\t(\n\t\t\t\t\toptions.methods || [\n\t\t\t\t\t\t\"GET\",\n\t\t\t\t\t\t\"POST\",\n\t\t\t\t\t\t\"PUT\",\n\t\t\t\t\t\t\"DELETE\",\n\t\t\t\t\t\t\"PATCH\",\n\t\t\t\t\t\t\"OPTIONS\",\n\t\t\t\t\t]\n\t\t\t\t).join(\",\"),\n\t\t\t);\n\t\t\tres.headers.set(\n\t\t\t\t\"Access-Control-Allow-Headers\",\n\t\t\t\t(\n\t\t\t\t\toptions.headers || [\"Content-Type\", \"Authorization\", \"x-api-key\"]\n\t\t\t\t).join(\",\"),\n\t\t\t);\n\t\t\tif (options.credentials)\n\t\t\t\tres.headers.set(\"Access-Control-Allow-Credentials\", \"true\");\n\t\t\treturn res;\n\t\t}\n\n\t\tconst response = toResponse(await next());\n\n\t\tapplyCorsHeaders(response, requestOrigin, options);\n\n\t\treturn response;\n\t};\n};\n"]}