{"version":3,"sources":["../../../node_modules/tsup/assets/cjs_shims.js","../src/sse.ts","../src/core-exports.ts","../src/ai.ts","../src/app.ts","../src/container.ts","../src/context.ts","../src/decorators.ts","../src/helpers/async-handler.ts","../src/helpers/response.ts","../src/logger.ts","../src/router/index.ts","../src/ffi/index.ts","../src/ffi/fallback.ts","../src/router/node.ts","../src/auth.ts","../src/oauth/index.ts","../src/oauth/types.ts","../src/oauth/pkce.ts","../src/oauth/state.ts","../src/helpers/cookie.ts","../src/oauth/provider.ts","../src/oauth/helpers.ts","../src/oauth/providers/google.ts","../src/oauth/providers/github.ts","../src/oauth/providers/apple.ts","../src/base-controller.ts","../src/base-service.ts","../src/cache.ts","../src/emitter.ts","../src/helpers/async.ts","../src/helpers/crypto.ts","../src/helpers/date.ts","../src/helpers/timezone.ts","../src/helpers/id.ts","../src/helpers/network.ts","../src/helpers/number.ts","../src/helpers/object.ts","../src/helpers/password.ts","../src/helpers/string.ts","../src/mailer.ts","../src/template.ts","../src/middlewares/audit-log.ts","../src/middlewares/body-size-limit.ts","../src/middlewares/compress.ts","../src/middlewares/cors.ts","../src/middlewares/health-check.ts","../src/middlewares/helmet.ts","../src/middlewares/rate-limiter.ts","../src/middlewares/request-id.ts","../src/middlewares/response-time.ts","../src/middlewares/timeout.ts","../src/middlewares/rbac.ts","../src/middlewares/validator.ts","../src/queue.ts","../src/payment/index.ts","../src/payment/types.ts","../src/payment/errors.ts","../src/payment/helpers.ts","../src/payment/middleware/webhook.ts","../src/payment/drivers/stripe.ts","../src/payment/drivers/midtrans.ts","../src/payment/drivers/xendit.ts","../src/payment/drivers/paypal.ts","../src/schedule.ts","../src/upload.ts","../src/ws-helpers.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n  typeof document === \"undefined\" \n    ? new URL(`file:${__filename}`).href \n    : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n      ? document.currentScript.src \n      : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\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","// Core\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nlet _version = \"0.0.0-dev\";\ntry {\n\t// 1. Check framework's own package.json (dev/monorepo context)\n\tlet pkgPath = join(__dirname, \"..\", \"package.json\");\n\tif (!existsSync(pkgPath)) {\n\t\t// 2. CLI bundle context (dist/cli/)\n\t\tpkgPath = join(__dirname, \"..\", \"..\", \"package.json\");\n\t}\n\tif (!existsSync(pkgPath)) {\n\t\t// 3. User project — read from node_modules/@buntok/core/package.json\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\nexport { z } from \"zod\";\n// AI\nexport {\n\tAICache,\n\tinjectSystemPrompt,\n\tstreamAI,\n} from \"./ai\";\nexport type {\n\tEnvValidationOptions,\n\tErrorHandler,\n\tExtractParams,\n\tHandler,\n\tHandlerReturn,\n\tMiddleware,\n\tNotFoundHandler,\n\tRouteContext,\n\tWSData,\n\tWSHandler,\n\tZodCtx,\n} from \"./app\";\nexport { App, type ApiDocsOptions, type StaticOptions, type WSOptions } from \"./app\";\n// Auth\nexport { JwtService, requireAuth } from \"./auth\";\n// OAuth\nexport {\n\tBaseOAuthProvider,\n\tclearOAuthCookies,\n\tcreateOAuth,\n\tcreateOAuth2AuthorizationURL,\n\tdecodeIdToken,\n\tgenerateCodeChallenge,\n\tgenerateCodeVerifier,\n\tgeneratePKCE,\n\tgetCodeVerifier,\n\tOAuthError,\n\tOAuthProviderError,\n\tOAuthStateError,\n\tOAuthTokenError,\n\tstoreOAuthState,\n\tvalidateOAuth2AuthorizationCode,\n\tverifyOAuthState,\n} from \"./oauth\";\nexport type {\n\tAppleProviderConfig,\n\tCreateAuthorizationURLOptions,\n\tOAuth2Tokens,\n\tOAuthProvider,\n\tOAuthProviderConfig,\n\tOAuthUser,\n\tValidateAuthorizationCodeOptions,\n} from \"./oauth\";\nexport { AppleProvider, type AppleUser } from \"./oauth\";\nexport { GitHubProvider, type GitHubUser } from \"./oauth\";\nexport { GoogleProvider, type GoogleUser } from \"./oauth\";\n// Base classes\nexport { BaseController } from \"./base-controller\";\nexport { BaseService } from \"./base-service\";\n// Cache\nexport { Cache, type CacheDriver, MemoryCacheDriver } from \"./cache\";\nexport {\n\ttype ClassProvider,\n\tContainer,\n\ttype FactoryProvider,\n\ttype Provider,\n\ttype Scope,\n\ttype ValueProvider,\n} from \"./container\";\nexport { Context } from \"./context\";\nexport type { ControllerMeta, RouteMeta } from \"./decorators\";\n// Emitter\nexport { emitter, EventEmitter } from \"./emitter\";\nexport type { AppEvents, EmitOptions, EventEmitterOptions } from \"./emitter\";\n// Decorators\nexport {\n\tAll,\n\tController,\n\tDelete,\n\tGet,\n\ttype GuardFn,\n\tHead,\n\tOptions,\n\tPatch,\n\tPost,\n\tPut,\n\tQuery,\n\tUse,\n\tUseGuard,\n\t// Nest-style alias (deprecated old kept)\n\tUseGuards,\n\t// New zero-cost decorators\n\tSetMetadata,\n\tPublic,\n\tHttpCode,\n\tSetHeader,\n\tHeader,\n\tRedirect,\n\tVersion,\n\tapplyDecorators,\n\tgetMetadata,\n} from \"./decorators\";\n// Native FFI\nexport { getBackend, isNativeAvailable } from \"./ffi\";\nexport type { RetryOptions } from \"./helpers/async\";\n// Async helpers\nexport { delay, retry } from \"./helpers/async\";\n// Response helpers (Elysia-style flexible return)\nexport { toResponse, toResponseMaybeAsync } from \"./helpers/response\";\n// Error helpers\nexport {\n\tasyncHandler,\n\tBadRequestError,\n\tConflictError,\n\tForbiddenError,\n\tHttpError,\n\tInternalServerError,\n\tMethodNotAllowedError,\n\tNotFoundError,\n\tServiceUnavailableError,\n\tTooManyRequestsError,\n\tUnauthorizedError,\n\tUnprocessableEntityError,\n} from \"./helpers/async-handler\";\nexport type { CookieOptions } from \"./helpers/cookie\";\n// Cookie helpers\nexport {\n\tdeleteCookie,\n\tgetCookie,\n\tgetCookies,\n\tparseCookies,\n\tserializeCookie,\n\tsetCookie,\n} from \"./helpers/cookie\";\n// Crypto helpers\nexport {\n\tdecrypt,\n\tencrypt,\n\thash,\n\thashVerify,\n\thmac,\n\tmd5,\n\trandomAlphaNumeric,\n\trandomBytes,\n\trandomHex,\n\trandomToken,\n\tsha256,\n\tsha512,\n} from \"./helpers/crypto\";\n// Date helpers\nexport {\n\taddDays,\n\tdaysBetween,\n\tendOfDay,\n\tformatDate,\n\tformatDuration,\n\tisAfter,\n\tisBefore,\n\tstartOfDay,\n\ttimeAgo,\n} from \"./helpers/date\";\n// Timezone helpers\nexport {\n\tformatGroupLabel,\n\tformatInTimezone,\n\tgetGroupLabels,\n\tgetTimezoneOffset,\n\tgetTimezoneOffsetString,\n\tgroupByTimezone,\n\tisValidTimezone,\n\tnowInTimezone,\n\tparseTime,\n\ttoISOWithTimezone,\n\ttoTimezoneParts,\n} from \"./helpers/timezone\";\nexport type { GroupByKey, GroupByTimezoneOptions } from \"./helpers/timezone\";\n// ID helpers\nexport {\n\tgenerateCode,\n\tnanoid,\n\tresetCounter,\n\tulid,\n} from \"./helpers/id\";\n// Network helpers\nexport { getClientIP, isPrivateIP, parseUserAgent } from \"./helpers/network\";\n// Number helpers\nexport {\n\tclamp,\n\tformatBytes,\n\tformatCurrency,\n\tformatNumber,\n\trandom,\n\trandomFloat,\n} from \"./helpers/number\";\n// Object helpers\nexport {\n\tchunk,\n\tdeepMerge,\n\tflatten,\n\tflattenObject,\n\tgroupBy,\n\tomit,\n\tpick,\n\tuniq,\n} from \"./helpers/object\";\n// Password helpers\nexport { hashPassword, verifyPassword } from \"./helpers/password\";\n// String helpers\nexport {\n\tcamelCase,\n\tcapitalize,\n\tkebabCase,\n\tslugify,\n\tsnakeCase,\n\ttruncate,\n} from \"./helpers/string\";\n// Logger\nexport { Logger, LogLevel, logger } from \"./logger\";\n// Mailer\nexport { Mailer, type MailerConfig, type MailOptions, type MailAttachment } from \"./mailer\";\n// Template Engine\nexport {\n\tTemplateEngine,\n\trender,\n\tregisterHelper,\n\tregisterPartial,\n\ttype TemplateOptions,\n\ttype HelperFn,\n} from \"./template\";\n// Middlewares\nexport { auditLog, type AuditLogEntry, type AuditLogOptions } from \"./middlewares/audit-log\";\nexport type { BodySizeLimitOptions } from \"./middlewares/body-size-limit\";\nexport { bodySizeLimit } from \"./middlewares/body-size-limit\";\nexport type { CompressOptions } from \"./middlewares/compress\";\nexport { compress } from \"./middlewares/compress\";\nexport type { CorsOptions } from \"./middlewares/cors\";\nexport { cors } from \"./middlewares/cors\";\nexport type {\n\tHealthCheckOptions,\n\tHealthStatus,\n} from \"./middlewares/health-check\";\nexport {\n\tcreateDatabaseCheck,\n\tcreateHealthCheck,\n\thealthCheck,\n} from \"./middlewares/health-check\";\nexport type { HelmetOptions } from \"./middlewares/helmet\";\n// Helmet\nexport { helmet } from \"./middlewares/helmet\";\nexport type { RateLimiterOptions } from \"./middlewares/rate-limiter\";\nexport {\n\trateLimiter,\n\tslidingWindowRateLimiter,\n} from \"./middlewares/rate-limiter\";\nexport type { RequestIdOptions } from \"./middlewares/request-id\";\nexport { requestId, shortId, uuid } from \"./middlewares/request-id\";\nexport type { ResponseTimeOptions } from \"./middlewares/response-time\";\nexport { responseTime } from \"./middlewares/response-time\";\n// Timeout\nexport { TimeoutError, timeout } from \"./middlewares/timeout\";\n// RBAC\nexport { requirePermission, requireRole } from \"./middlewares/rbac\";\nexport type { RequirePermissionOptions, RequireRoleOptions } from \"./middlewares/rbac\";\nexport type {\n\tBodyContentType,\n\tValidationTarget,\n\tZValidatorOptions,\n} from \"./middlewares/validator\";\nexport {\n\tvalidate,\n\tvalidateBody,\n\tvalidateParams,\n\tzResponse,\n\tzValidator,\n} from \"./middlewares/validator\";\n// Queue\nexport {\n\ttype Job,\n\ttype JobHandler,\n\tMemoryQueueDriver,\n\tQueue,\n\ttype QueueDriver,\n\ttype QueueOptions,\n} from \"./queue\";\nexport { Router } from \"./router\";\n// Payment\nexport {\n\tPaymentConfigurationError,\n\tPaymentError,\n\tPaymentIdempotencyError,\n\tPaymentProviderError,\n\tPaymentVerificationError,\n\tpaymentWebhook,\n\tcreatePayment,\n\tgenerateIdempotencyKey,\n\tnormalizeCheckoutStatus,\n\tnormalizeRefundStatus,\n\tnormalizeSubscriptionStatus,\n\tCreateCheckoutInputSchema,\n\tCreatePaymentLinkInputSchema,\n\tCreateRefundInputSchema,\n\tCreateSubscriptionInputSchema,\n\tMoneyAmountSchema,\n\tStripeDriver,\n\tMidtransDriver,\n\tXenditDriver,\n\tPayPalDriver,\n} from \"./payment\";\nexport type {\n\tCheckoutResult,\n\tCheckoutStatus,\n\tCreateCheckoutInput,\n\tCreatePaymentLinkInput,\n\tCreateRefundInput,\n\tCreateSubscriptionInput,\n\tPaymentDriver,\n\tPaymentLinkResult,\n\tPaymentOptions,\n\tRefundResult,\n\tRefundStatus,\n\tStripeDriverConfig,\n\tMidtransDriverConfig,\n\tXenditDriverConfig,\n\tPayPalDriverConfig,\n\tSubscriptionResult,\n\tSubscriptionStatus,\n\tWebhookEvent,\n\tWebhookEventType,\n\tWebhookMiddlewareOptions,\n} from \"./payment\";\n// Scheduler / CronJob\nexport {\n\tBunCronSchedulerDriver,\n\tCronJob,\n\tMemorySchedulerDriver,\n\tScheduler,\n\ttype SchedulerDriver,\n\tsetDefaultSchedulerDriver,\n} from \"./schedule\";\n// SSE - industrial, pluggable (mirip StorageDriver)\nexport type { SSEBroadcasterOptions, SSEHistoryStore, SSEMessage, SSEOptions, SSEPubSub } from \"./sse\";\nexport { MemorySSEHistory, MemorySSEPubSub, SSE, SSEBroadcaster, createSSE } from \"./sse\";\n// Upload\nexport type {\n\tImageUploadedFile,\n\tParseUploadResult,\n\tStorageDriver,\n\tUploadedFile,\n\tUploadFieldConfig,\n\tUploadOptions,\n} from \"./upload\";\nexport {\n\tdeleteUploadedFile,\n\tLocalDiskStorage,\n\tMemoryStorage,\n\thandleUploads,\n\tuploader,\n} from \"./upload\";\n// WebSocket helpers - industrial, pluggable\nexport type { RoomOptions, WSPubSub, WSRateLimitOptions, WSRateLimitStore } from \"./ws-helpers\";\nexport {\n\tMemoryWSPubSub,\n\tMemoryWSRateLimitStore,\n\tRoom,\n\tvalidateWSMessage,\n\twsAuth,\n\twsHeartbeat,\n\twsHeartbeatPong,\n\twsRateLimit,\n} from \"./ws-helpers\";\n","import type { CacheDriver } from \"./cache\";\nimport type { Context } from \"./context\";\n\n/**\n * Transforms an async iterable (like OpenAI chat completions stream) into a\n * Vercel AI SDK compatible stream response (Data Stream Protocol v1).\n *\n * @param ctx - The Buntok context\n * @param stream - An AsyncIterable representing the LLM chunks\n * @param options - Optional callbacks (e.g. onCompletion)\n * @returns A Response object with Server-Sent Events headers\n */\nexport function streamAI(\n\t_ctx: Context,\n\t// biome-ignore lint/suspicious/noExplicitAny: generic stream\n\tstream: AsyncIterable<any> | any,\n\toptions?: {\n\t\tonCompletion?: (fullText: string) => void | Promise<void>;\n\t},\n): Response {\n\tconst readable = new ReadableStream({\n\t\tasync start(controller) {\n\t\t\ttry {\n\t\t\t\tlet fullText = \"\";\n\n\t\t\t\t// Handle standard AsyncIterable (OpenAI, Anthropic standard)\n\t\t\t\tif (stream && Symbol.asyncIterator in stream) {\n\t\t\t\t\tfor await (const chunk of stream) {\n\t\t\t\t\t\t// Very naive check for OpenAI/Anthropic chunk formats\n\t\t\t\t\t\tconst content =\n\t\t\t\t\t\t\tchunk?.choices?.[0]?.delta?.content ||\n\t\t\t\t\t\t\tchunk?.message?.content ||\n\t\t\t\t\t\t\t(typeof chunk === \"string\" ? chunk : \"\");\n\n\t\t\t\t\t\tif (content) {\n\t\t\t\t\t\t\tfullText += content;\n\t\t\t\t\t\t\t// Format according to Vercel AI SDK Data Stream Protocol: 0:\"text\"\n\t\t\t\t\t\t\tconst data = `0:${JSON.stringify(content)}\\n`;\n\t\t\t\t\t\t\tcontroller.enqueue(new TextEncoder().encode(data));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(\"Provided stream is not an AsyncIterable\");\n\t\t\t\t}\n\n\t\t\t\t// Fire completion callback\n\t\t\t\tif (options?.onCompletion) {\n\t\t\t\t\tawait options.onCompletion(fullText);\n\t\t\t\t}\n\n\t\t\t\t// End of stream protocol: d:{\"finishReason\":\"stop\"}\n\t\t\t\tcontroller.enqueue(\n\t\t\t\t\tnew TextEncoder().encode(`d:{\"finishReason\":\"stop\"}\\n`),\n\t\t\t\t);\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: catching unknown error type\n\t\t\t} catch (e: any) {\n\t\t\t\t// Send error stream protocol: e:{\"message\":\"...\"}\n\t\t\t\tcontroller.enqueue(\n\t\t\t\t\tnew TextEncoder().encode(\n\t\t\t\t\t\t`e:${JSON.stringify({ message: e.message })}\\n`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tcontroller.close();\n\t\t\t}\n\t\t},\n\t});\n\n\treturn new Response(readable, {\n\t\theaders: {\n\t\t\t\"Content-Type\": \"text/x-unknown\", // Standard for Vercel AI stream\n\t\t\t\"Cache-Control\": \"no-cache, no-transform\",\n\t\t\tConnection: \"keep-alive\",\n\t\t\t\"x-vercel-ai-data-stream\": \"v1\",\n\t\t},\n\t});\n}\n\n/**\n * Safely injects a system prompt into an array of messages.\n * Removes any existing system prompts from user input to prevent prompt injection.\n *\n * @param messages - Array of existing chat messages\n * @param systemPrompt - The strict system instruction\n * @returns Cleaned array of messages with system prompt at the top\n */\n// biome-ignore lint/suspicious/noExplicitAny: standard AI message array\nexport function injectSystemPrompt(messages: any[], systemPrompt: string) {\n\tconst safeMessages = messages.filter((m) => m.role !== \"system\");\n\treturn [{ role: \"system\", content: systemPrompt }, ...safeMessages];\n}\n\n/**\n * Semantic Cache for AI responses using Buntok CacheDrivers.\n * It caches exact matches of chat histories to save LLM costs.\n */\nexport class AICache {\n\tconstructor(private driver: CacheDriver) {}\n\n\t/**\n\t * Generates a unique key based on the last few user messages.\n\t */\n\t// biome-ignore lint/suspicious/noExplicitAny: standard AI message array\n\tprivate hashMessages(messages: any[]): string {\n\t\tconst relevantMessages = messages\n\t\t\t.filter((m) => m.role === \"user\" || m.role === \"assistant\")\n\t\t\t.slice(-3);\n\t\tconst content = JSON.stringify(relevantMessages);\n\t\tlet hash = 0;\n\t\tfor (let i = 0; i < content.length; i++) {\n\t\t\thash = (hash << 5) - hash + content.charCodeAt(i);\n\t\t\thash = hash & hash;\n\t\t}\n\t\treturn `ai_cache_${hash}`;\n\t}\n\n\t/**\n\t * Checks if an identical conversation history has been answered recently.\n\t */\n\t// biome-ignore lint/suspicious/noExplicitAny: standard AI message array\n\tasync get(messages: any[]): Promise<string | null> {\n\t\tconst key = this.hashMessages(messages);\n\t\treturn this.driver.get<string>(key);\n\t}\n\n\t/**\n\t * Saves the generated AI response to cache.\n\t */\n\tasync set(\n\t\t// biome-ignore lint/suspicious/noExplicitAny: standard AI message array\n\t\tmessages: any[],\n\t\tresponseText: string,\n\t\tttlSeconds: number = 3600,\n\t): Promise<void> {\n\t\tconst key = this.hashMessages(messages);\n\t\tawait this.driver.set(key, responseText, ttlSeconds);\n\t}\n}\n","import { join, sep } from \"node:path\";\nimport type { Server, ServerWebSocket } from \"bun\";\nimport { 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 { logger } from \"./logger\";\nimport { Router } from \"./router\";\nimport { VERSION } from \"./core-exports\";\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\t? { [K in Param]: string } & ExtractParams<`/${Rest}`>\n\t\t: Path extends `${infer _Start}:${infer Param}`\n\t\t\t? { [K in Param]: string }\n\t\t\t: Path extends `${infer _Start}*${infer Catchall}`\n\t\t\t\t? { [K in Catchall]: string } & { \"*\": string }\n\t\t\t\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\t? QueryType\n\t\t\t: T extends \"params\"\n\t\t\t\t? ParamsType\n\t\t\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\t? U\n\t\t\t: T[\"body\"]\n\t\t: Target extends \"query\"\n\t\t\t? T[\"query\"] extends { _type: infer U }\n\t\t\t\t? U\n\t\t\t\t: T[\"query\"]\n\t\t\t: Target extends \"params\"\n\t\t\t\t? T[\"params\"] extends { _type: infer U }\n\t\t\t\t\t? U\n\t\t\t\t\t: T[\"params\"]\n\t\t\t\t: unknown;\n} & Context<\n\tRecord<string, unknown>,\n\tT[\"params\"] extends { _type: infer U }\n\t\t? U\n\t\t: T[\"params\"] extends Record<string, string>\n\t\t\t? T[\"params\"]\n\t\t\t: Record<string, string>\n>;\n\nexport type HandlerReturn =\n\t| Response\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\t| Response\n\t\t\t| string\n\t\t\t| number\n\t\t\t| boolean\n\t\t\t| bigint\n\t\t\t| Record<string, unknown>\n\t\t\t| unknown[]\n\t\t\t| null\n\t\t\t| undefined\n\t\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 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 iconPath: string = \"./public/favicon.ico\";\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 = true;\n\tprivate _reusePort: boolean = false;\n\tprivate _skipLogResponse: boolean = false;\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\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\tconstructor() {\n\t\tthis.router = new Router();\n\t\tthis.registerFaviconRoute();\n\t}\n\n\tpublic use(middleware: Middleware<DI>): this {\n\t\tthis.middlewares.push(middleware);\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\tconst envSchema = z.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) => ({\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) => `${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) => {\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 * ```\n\t */\n\tpublic registerController<T extends object>(\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Constructor args are unknowable\n\t\ttarget: (new (...args: any[]) => T) | T,\n\t): this {\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\t(target as any).constructor\n\t\t\t: // biome-ignore lint/suspicious/noExplicitAny: dynamic type narrowing\n\t\t\t\t(target as new (\n\t\t\t\t\t...args: any[]\n\t\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) {\n\t\t\tconst resolved = this.container.resolve<T>(ControllerClass);\n\t\t\tinstance = resolved;\n\t\t} else {\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\tlet handler = (instance as any)[route.propertyKey].bind(\n\t\t\t\tinstance,\n\t\t\t) as Handler<DI>;\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\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 && 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 && 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\tconst apply = (res: Response): Response => {\n\t\t\t\t\t\tlet r: Response = res;\n\t\t\t\t\t\tif (hasStatus && r.status === 200) {\n\t\t\t\t\t\t\t// Override status only if default 200 (preserve explicit ctx.status etc.)\n\t\t\t\t\t\t\tr = new Response(r.body, { status: routeMeta.statusCode!, headers: r.headers });\n\t\t\t\t\t\t} else if (hasStatus && r.status === 204 && routeMeta.statusCode !== 204) {\n\t\t\t\t\t\t\t// For void returns that became 204, respect HttpCode\n\t\t\t\t\t\t\tr = new Response(r.body, { status: routeMeta.statusCode!, headers: r.headers });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (hasHeaders) {\n\t\t\t\t\t\t\tfor (const [k, v] of routeMeta.headers!) {\n\t\t\t\t\t\t\t\tr.headers.set(k, v);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn r;\n\t\t\t\t\t};\n\t\t\t\t\tif (raw instanceof Promise) {\n\t\t\t\t\t\treturn raw.then((v: any) => apply(toResponse(v)));\n\t\t\t\t\t}\n\t\t\t\t\treturn apply(toResponse(raw));\n\t\t\t\t}) as Handler<DI>;\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]);\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\tthis.iconPath = path;\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);\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);\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);\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);\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);\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);\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);\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);\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);\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): 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// 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\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 = new URL(\"./cli/templates\", import.meta.url).pathname;\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\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 (reads fresh on every request)\n\t\tconst swaggerHandler: Handler<DI> = async () => {\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(JSON.stringify({ error: \"swagger.json not found. Run 'buntok make:docs' first.\" }), {\n\t\t\t\tstatus: 404,\n\t\t\t\theaders: { \"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};\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}\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\tlet code =\n\t\t\t\"return function(request, server) {\\n\" +\n\t\t\t\"  const url = request.url;\\n\" +\n\t\t\t\"  let start = url.indexOf('/', url.indexOf('//') + 2);\\n\" +\n\t\t\t\"  if (start === -1) start = url.length;\\n\" +\n\t\t\t\"  let end = url.indexOf('?', start);\\n\" +\n\t\t\t\"  if (end === -1) end = url.length;\\n\" +\n\t\t\t\"  const pathname = start === url.length ? '/' : url.substring(start, end);\\n\";\n\n\t\tif (this.wsRoutes.size > 0) {\n\t\t\tcode +=\n\t\t\t\t\"  if (server && wsRoutes.has(pathname)) {\\n\" +\n\t\t\t\t\"    const wsHandler = wsRoutes.get(pathname);\\n\" +\n\t\t\t\t\"    const ctx = new Context(request, EMPTY_PARAMS, di);\\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 += \"  const method = request.method;\\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\tcode += `    case \"${route.path}\": {\\n`;\n\t\t\t\tcode += \"      const ctx = new Context(request, EMPTY_PARAMS, di);\\n\";\n\t\t\t\tcode += \"      try {\\n\";\n\t\t\t\tcode +=\n\t\t\t\t\t\"        const raw = compiledGlobalPipeline(ctx, \" +\n\t\t\t\t\thandlerRef +\n\t\t\t\t\t\");\\n\";\n\t\t\t\tif (this._skipLogResponse) {\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) => toResponse(v)).catch((e) => handleError(request, pathname, ctx, e));\\n\";\n\t\t\t\t\tcode += \"        }\\n\";\n\t\t\t\t\tcode += \"        return toResponse(raw);\\n\";\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) => logResponse(request, pathname, toResponse(v))).catch((e) => handleError(request, pathname, ctx, e));\\n\";\n\t\t\t\t\tcode += \"        }\\n\";\n\t\t\t\t\tcode += \"        return logResponse(request, pathname, toResponse(raw));\\n\";\n\t\t\t\t}\n\t\t\t\tcode += \"      } catch (err) {\\n\";\n\t\t\t\tcode += \"        return handleError(request, pathname, ctx, err);\\n\";\n\t\t\t\tcode += \"      }\\n\";\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\" + \"  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\"toResponse\",\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\ttoResponse,\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// Skip building the log string entirely when request logging is off\n\t\tif (logger.logRequests) {\n\t\t\tconst status = response.status;\n\t\t\tconst logData = { 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\treturn response;\n\t};\n\n\t/**\n\t * Normalize flexible handler return (string | object | null etc.) to Response.\n\t * Used by both AOT and fallback paths.\n\t */\n\tprivate normalizeReturn(value: unknown): Response | Promise<Response> {\n\t\tif (value instanceof Promise) {\n\t\t\treturn value.then((v) => toResponse(v));\n\t\t}\n\t\treturn 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.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.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\t\ttypeof input === \"string\" && !/^https?:\\/\\//.test(input)\n\t\t\t\t\t\t\t? `http://localhost${input.startsWith(\"/\") ? \"\" : \"/\"}${input}`\n\t\t\t\t\t\t\t: // biome-ignore lint/suspicious/noExplicitAny: Standard fetch input overriding\n\t\t\t\t\t\t\t\t(input as any),\n\t\t\t\t\t\tinit,\n\t\t\t\t\t);\n\t\treturn this.handleRequest(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) 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\n\t\tconst ctx = new Context(request, route.params, this.di) as Context<DI>;\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\ttry {\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: Guaranteed by compileGlobalPipeline\n\t\t\tconst result = this.compiledGlobalPipeline!(ctx, 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) => this.handleError(request, pathname, ctx, err));\n\t\t\t}\n\t\t\treturn this.logNormalized(request, pathname, result);\n\t\t} catch (err) {\n\t\t\treturn this.handleError(request, pathname, ctx, 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\tthis._skipLogResponse = !logger.logRequests && !this.poweredByHeaderEnabled;\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\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`);\n\n\t\tif (callback) callback();\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\tconst shutdown = async (signal: string) => {\n\t\t\tlogger.info(`\\n${signal} received. Starting graceful shutdown...`);\n\n\t\t\tif (this.server) {\n\t\t\t\t// Stop accepting new connections\n\t\t\t\tthis.server.stop(false);\n\n\t\t\t\t// Drain SSE — industrial graceful (close all streams dengan 30s heartbeat comment)\n\t\t\t\ttry {\n\t\t\t\t\tconst { SSE } = await import(\"./sse\");\n\t\t\t\t\t// kirim close event sebelum terminate\n\t\t\t\t\tfor (const c of SSE.getActiveConnections()) {\n\t\t\t\t\t\ttry { c.sendEvent(\"close\", \"Server shutting down\"); } catch {}\n\t\t\t\t\t}\n\t\t\t\t\t// beri waktu 1s untuk flush\n\t\t\t\t\tawait new Promise((r) => setTimeout(r, 1000));\n\t\t\t\t\tSSE.closeAll();\n\t\t\t\t} catch {}\n\n\t\t\t\t// Drain WS — close dengan 1001 Going Away\n\t\t\t\ttry {\n\t\t\t\t\t// broadcast ke semua topic jika pakai publish\n\t\t\t\t\ttry { this.server.publish(\"buntok:shutdown\", \"shutting down\"); } catch {}\n\t\t\t\t} catch {}\n\n\t\t\t\t// Give in-flight requests time to complete (max 30 seconds)\n\t\t\t\tconst shutdownTimeout = 30_000;\n\t\t\t\tconst forceExitTimeout = setTimeout(() => {\n\t\t\t\t\tlogger.warn(\"Forcing shutdown after timeout\");\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}, shutdownTimeout);\n\t\t\t\t// Jangan clear langsung — biarkan timeout jadi safety net\n\t\t\t\t// Cleanup setelah graceful selesai\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tclearTimeout(forceExitTimeout);\n\t\t\t\t\tlogger.info(\"Server shut down gracefully\");\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t}, 1500);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlogger.info(\"Server shut down gracefully\");\n\t\t\tprocess.exit(0);\n\t\t};\n\n\t\tprocess.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\n\t\tprocess.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\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]);\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]);\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]);\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]);\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]);\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]);\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]);\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]);\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]);\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 * // → routes registered as /api/v1/users, /api/v1/users/:id, etc.\n\t */\n\tpublic registerController<T extends object>(\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Constructor args are unknowable\n\t\ttarget: (new (...args: any[]) => T) | T,\n\t): this {\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\t(target as any).constructor\n\t\t\t: // biome-ignore lint/suspicious/noExplicitAny: dynamic type narrowing\n\t\t\t\t(target as new (\n\t\t\t\t\t...args: any[]\n\t\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) {\n\t\t\t\tinstance = container.resolve<T>(ControllerClass);\n\t\t\t} else {\n\t\t\t\tinstance = new ControllerClass();\n\t\t\t}\n\t\t}\n\n\t\tconst normalizedPrefix = meta.prefix.endsWith(\"/\")\n\t\t\t? meta.prefix.slice(0, -1)\n\t\t\t: meta.prefix;\n\n\t\tfor (const route of meta.routes) {\n\t\t\tconst cleanPath = route.path === \"/\" ? \"\" : route.path;\n\t\t\tconst fullPath =\n\t\t\t\t`${this.normalizePath(normalizedPrefix)}${cleanPath}` || \"/\";\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: dynamic method dispatch by decorated property key\n\t\t\tconst handler = (instance as any)[route.propertyKey].bind(\n\t\t\t\tinstance,\n\t\t\t) as Handler<DI>;\n\n\t\t\tthis.app.registerRoute(route.method, fullPath, [\n\t\t\t\t...(route.middlewares as Middleware<DI>[]),\n\t\t\t\t...this.groupMiddlewares,\n\t\t\t\thandler,\n\t\t\t]);\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\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 * 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","import { createSSE, type SSE, type SSEOptions } from \"./sse\";\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\n\tconstructor(request: Request, params: Record<string, string>, di: DI) {\n\t\tthis.request = request;\n\t\tthis.params = params as unknown as Params & Record<string, string>;\n\t\tthis.di = di;\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\tconst forwardedFor = this.request.headers.get(\"x-forwarded-for\");\n\t\tif (forwardedFor) {\n\t\t\treturn forwardedFor.split(\",\")[0]?.trim() ?? \"\";\n\t\t}\n\t\treturn \"127.0.0.1\";\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\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 type { Middleware } from \"./app\";\nimport type { Context } from \"./context\";\n\n/**\n * Decorator-based controller routing, built on Stage 3 (TC39) decorators -\n * the same kind natively supported by Bun/TypeScript 5+ without setting\n * `experimentalDecorators`.\n *\n * This is a thin layer on top of the existing functional API: decorators\n * only run once at class-definition/bootstrap time, and end up calling the\n * exact same `app.registerRoute()` used by `app.get()`/`app.post()`. There\n * is zero per-request overhead - the router has no idea (and doesn't care)\n * whether a route came from a decorator or a direct `.get()` call.\n *\n * ```ts\n * @Controller(\"/users\")\n * class UserController {\n *   @Get(\"/:id\")\n *   getUser(ctx: Context) {\n *     return ctx.json({ id: ctx.params.id });\n *   }\n *\n *   @Post(\"/\")\n *   @Use(zValidator(\"body\", createUserSchema))\n *   createUser(ctx: Context) {\n *     const data = ctx.valid<{ name: string }>(\"body\");\n *     return ctx.json(data, 201);\n *   }\n * }\n *\n * app.registerController(UserController);\n * ```\n */\n\nexport interface RouteMeta {\n\tmethod: string;\n\tpath: string;\n\tpropertyKey: string;\n\tmiddlewares: Middleware[];\n\t/** @HttpCode status override (e.g. 201) */\n\tstatusCode?: number;\n\t/** @Header / @SetHeader entries */\n\theaders?: Array<[string, string]>;\n\t/** @Redirect target */\n\tredirect?: { url: string; statusCode: number };\n\t/** @Version value */\n\tversion?: string | string[];\n\t/** Generic metadata via SetMetadata */\n\tmetadata?: Map<string, unknown>;\n}\n\nexport interface ControllerMeta {\n\tprefix: string;\n\troutes: RouteMeta[];\n}\n\nlet pendingRoutes: RouteMeta[] = [];\n\n// Generic metadata registry for SetMetadata / Roles / Version\nconst metadataRegistry = new WeakMap<Function, Map<string, Map<string, unknown>>>();\nfunction getOrCreateMethodMetadata(\n\ttarget: Function,\n\tpropertyKey: string,\n): Map<string, unknown> {\n\tlet classMap = metadataRegistry.get(target);\n\tif (!classMap) {\n\t\tclassMap = new Map();\n\t\tmetadataRegistry.set(target, classMap);\n\t}\n\tlet methodMap = classMap.get(propertyKey);\n\tif (!methodMap) {\n\t\tmethodMap = new Map();\n\t\tclassMap.set(propertyKey, methodMap);\n\t}\n\treturn methodMap;\n}\n\n// biome-ignore lint/complexity/noBannedTypes: Native Decorator API uses Function\nconst controllerRegistry = new WeakMap<Function, ControllerMeta>();\n\ntype MethodDecoratorFn = (\n\t// biome-ignore lint/suspicious/noExplicitAny: Required for TS method decorator contravariance\n\toriginalMethod: (...args: any[]) => any,\n\tcontext: ClassMethodDecoratorContext,\n) => void;\n\nfunction createRouteDecorator(method: string) {\n\treturn (path: string): MethodDecoratorFn => {\n\t\treturn (_originalMethod, context) => {\n\t\t\tif (context.kind !== \"method\") {\n\t\t\t\tthrow new Error(`@${method} can only decorate methods`);\n\t\t\t}\n\t\t\tconst propertyKey = String(context.name);\n\t\t\tconst entry = pendingRoutes.find((r) => r.propertyKey === propertyKey);\n\t\t\tif (entry) {\n\t\t\t\tentry.method = method;\n\t\t\t\tentry.path = path;\n\t\t\t} else {\n\t\t\t\tpendingRoutes.push({\n\t\t\t\t\tmethod,\n\t\t\t\t\tpath,\n\t\t\t\t\tpropertyKey,\n\t\t\t\t\tmiddlewares: [],\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t};\n}\n\nexport const Get = createRouteDecorator(\"GET\");\nexport const Post = createRouteDecorator(\"POST\");\nexport const Put = createRouteDecorator(\"PUT\");\nexport const Patch = createRouteDecorator(\"PATCH\");\nexport const Delete = createRouteDecorator(\"DELETE\");\nexport const Options = createRouteDecorator(\"OPTIONS\");\nexport const Head = createRouteDecorator(\"HEAD\");\nexport const Query = createRouteDecorator(\"QUERY\");\n\n/**\n * Matches ALL HTTP methods. Useful for catch-all handlers or proxies.\n * Note: more specific method decorators (@Get, @Post, etc.) registered on the\n * same path will take precedence in the AOT-compiled router.\n */\nexport const All = createRouteDecorator(\"ALL\");\n\n/**\n * Attach middleware to a single decorated route. Stack multiple `@Use()`\n * calls to chain several - they run in the order listed, same as passing\n * multiple middleware args to `app.get(path, mw1, mw2, handler)`.\n */\n// biome-ignore lint/suspicious/noExplicitAny: Flexible middleware signature for decorators\nexport function Use(\n\tmiddleware: (ctx: any, next: any) => any,\n): MethodDecoratorFn {\n\treturn (_originalMethod, context) => {\n\t\tif (context.kind !== \"method\") {\n\t\t\tthrow new Error(\"@Use can only decorate methods\");\n\t\t}\n\t\tconst propertyKey = String(context.name);\n\t\tlet entry = pendingRoutes.find((r) => r.propertyKey === propertyKey);\n\t\tif (!entry) {\n\t\t\tentry = { method: \"\", path: \"\", propertyKey, middlewares: [] };\n\t\t\tpendingRoutes.push(entry);\n\t\t}\n\t\tentry.middlewares.unshift(middleware as Middleware);\n\t};\n}\n\nexport type GuardFn<DI = Record<string, unknown>> = (\n\tctx: Context<DI>,\n) => boolean | Promise<boolean>;\n\n/**\n * Apply one or more guards to a controller method.\n * A guard is a function that returns a boolean. If it returns false,\n * the request is rejected with a 403 Forbidden.\n */\nexport function UseGuard<DI = Record<string, unknown>>(\n\t...guards: GuardFn<DI>[]\n) {\n\t// biome-ignore lint/suspicious/noExplicitAny: Required for internal Context bypass\n\treturn Use(async (ctx: any, next: any) => {\n\t\tfor (const guard of guards) {\n\t\t\tconst passed = await guard(ctx);\n\t\t\tif (!passed) {\n\t\t\t\treturn ctx.error(\"Forbidden resource\", 403);\n\t\t\t}\n\t\t}\n\t\treturn next();\n\t});\n}\n\n/**\n * @deprecated Use `UseGuards` instead. Kept as alias to `UseGuard` for backward compatibility.\n */\nexport const UseGuards = UseGuard;\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Fase 1 zero-cost Nest-style decorators - boot-time metadata, <1% AOT overhead\n// ──────────────────────────────────────────────────────────────────────────────\n\n/**\n * Set arbitrary metadata on a handler (read via `getMetadata()` / Reflector).\n * Pure WeakMap write at decoration time - zero per-request cost.\n */\nexport function SetMetadata(key: string, value: unknown): MethodDecoratorFn {\n\treturn (_originalMethod, context) => {\n\t\tif (context.kind !== \"method\") {\n\t\t\tthrow new Error(\"@SetMetadata can only decorate methods\");\n\t\t}\n\t\tconst propertyKey = String(context.name);\n\t\tlet entry = pendingRoutes.find((r) => r.propertyKey === propertyKey);\n\t\tif (!entry) {\n\t\t\tentry = { method: \"\", path: \"\", propertyKey, middlewares: [] };\n\t\t\tpendingRoutes.push(entry);\n\t\t}\n\t\tif (!entry.metadata) entry.metadata = new Map();\n\t\tentry.metadata.set(key, value);\n\t\t// Also store in global metadataRegistry for Reflector-style lookups\n\t\t// We need a class reference; store lazily and resolve via Controller prefix later\n\t\t// For now, also keep pending; final association done in @Controller\n\t};\n}\n\n/**\n * Mark route as public (skip auth). Equivalent to `SetMetadata(\"isPublic\", true)` and checked by guards.\n */\nexport function Public(): MethodDecoratorFn {\n\treturn SetMetadata(\"isPublic\", true);\n}\n\n/**\n * Override HTTP status code for handler return (e.g. POST -> 201).\n * Stored as RouteMeta.statusCode and applied at registerRoute time via wrapper.\n */\nexport function HttpCode(statusCode: number): MethodDecoratorFn {\n\treturn (_originalMethod, context) => {\n\t\tif (context.kind !== \"method\") {\n\t\t\tthrow new Error(\"@HttpCode can only decorate methods\");\n\t\t}\n\t\tconst propertyKey = String(context.name);\n\t\tlet entry = pendingRoutes.find((r) => r.propertyKey === propertyKey);\n\t\tif (!entry) {\n\t\t\tentry = { method: \"\", path: \"\", propertyKey, middlewares: [] };\n\t\t\tpendingRoutes.push(entry);\n\t\t}\n\t\tentry.statusCode = statusCode;\n\t};\n}\n\n/**\n * Set a static response header for the route (e.g. `@SetHeader(\"x-cache\", \"hit\")`).\n * Multiple usages stack.\n */\nexport function SetHeader(name: string, value: string): MethodDecoratorFn {\n\treturn (_originalMethod, context) => {\n\t\tif (context.kind !== \"method\") {\n\t\t\tthrow new Error(\"@SetHeader can only decorate methods\");\n\t\t}\n\t\tconst propertyKey = String(context.name);\n\t\tlet entry = pendingRoutes.find((r) => r.propertyKey === propertyKey);\n\t\tif (!entry) {\n\t\t\tentry = { method: \"\", path: \"\", propertyKey, middlewares: [] };\n\t\t\tpendingRoutes.push(entry);\n\t\t}\n\t\tif (!entry.headers) entry.headers = [];\n\t\tentry.headers.push([name, value]);\n\t};\n}\n\n/** @deprecated Use `SetHeader` instead. Alias kept for Nest compatibility. */\nexport const Header = SetHeader;\n\n/**\n * Redirect to URL with status (default 302). Static redirect - handler not executed.\n * If handler returns `{url, statusCode}`, it overrides decorator value (Nest behavior).\n */\nexport function Redirect(url: string, statusCode = 302): MethodDecoratorFn {\n\treturn (_originalMethod, context) => {\n\t\tif (context.kind !== \"method\") {\n\t\t\tthrow new Error(\"@Redirect can only decorate methods\");\n\t\t}\n\t\tconst propertyKey = String(context.name);\n\t\tlet entry = pendingRoutes.find((r) => r.propertyKey === propertyKey);\n\t\tif (!entry) {\n\t\t\tentry = { method: \"\", path: \"\", propertyKey, middlewares: [] };\n\t\t\tpendingRoutes.push(entry);\n\t\t}\n\t\tentry.redirect = { url, statusCode };\n\t};\n}\n\n/**\n * Set API version for route (prefix or metadata). Stored as string, applied as path prefix or metadata.\n */\nexport function Version(version: string | string[]): MethodDecoratorFn {\n\treturn (_originalMethod, context) => {\n\t\tif (context.kind !== \"method\") {\n\t\t\tthrow new Error(\"@Version can only decorate methods\");\n\t\t}\n\t\tconst propertyKey = String(context.name);\n\t\tlet entry = pendingRoutes.find((r) => r.propertyKey === propertyKey);\n\t\tif (!entry) {\n\t\t\tentry = { method: \"\", path: \"\", propertyKey, middlewares: [] };\n\t\t\tpendingRoutes.push(entry);\n\t\t}\n\t\tentry.version = version;\n\t};\n}\n\n/**\n * Compose multiple decorators into one (Nest `applyDecorators` equivalent).\n * Zero-cost boot-time helper.\n */\nexport function applyDecorators(\n\t...decorators: Array<(target: any, context: any) => void>\n): MethodDecoratorFn & ((target: Function, context: ClassDecoratorContext) => void) {\n\treturn ((target: any, context: any) => {\n\t\tfor (const dec of decorators) {\n\t\t\t(dec as any)(target, context);\n\t\t}\n\t}) as any;\n}\n\n/**\n * Retrieve metadata set via @SetMetadata (helper for guards/interceptors).\n */\nexport function getMetadata(\n\ttarget: Function,\n\tpropertyKey: string,\n\tkey: string,\n): unknown {\n\tconst classMap = metadataRegistry.get(target);\n\tif (!classMap) return undefined;\n\tconst methodMap = classMap.get(propertyKey);\n\tif (!methodMap) return undefined;\n\treturn methodMap.get(key);\n}\n\n/**\n * Marks a class as a controller and registers its accumulated `@Get`/\n * `@Post`/etc. routes under `prefix`. Must be the outermost (topmost)\n * decorator on the class so it runs after all method decorators have\n * populated the pending route list.\n */\nexport function Controller(prefix = \"\") {\n\t// biome-ignore lint/complexity/noBannedTypes: Native Decorator API uses Function\n\treturn (target: Function, context: ClassDecoratorContext): void => {\n\t\tif (context.kind !== \"class\") {\n\t\t\tthrow new Error(\"@Controller can only decorate classes\");\n\t\t}\n\t\tconst routes = pendingRoutes.filter((r) => r.method !== \"\");\n\t\tpendingRoutes = [];\n\t\tcontrollerRegistry.set(target, { prefix, routes });\n\t};\n}\n\n/**\n * Reads the routes registered on a `@Controller`-decorated class. Used\n * internally by `App.registerController()`. Walks the prototype chain\n * to merge parent class routes with child class routes.\n */\nexport function getControllerMeta(\n\t// biome-ignore lint/complexity/noBannedTypes: Native Decorator API uses Function\n\tControllerClass: Function,\n): ControllerMeta | undefined {\n\tconst meta = controllerRegistry.get(ControllerClass);\n\n\t// Walk prototype chain to get parent routes\n\tconst parentProto = Object.getPrototypeOf(ControllerClass.prototype);\n\tconst ParentClass = parentProto?.constructor;\n\n\tif (\n\t\tParentClass &&\n\t\tParentClass !== Function.prototype &&\n\t\tParentClass !== Object\n\t) {\n\t\tconst parentMeta = getControllerMeta(ParentClass);\n\t\tif (parentMeta) {\n\t\t\t// Merge: parent routes + child routes (child overrides parent on same propertyKey)\n\t\t\tconst childRoutes = meta?.routes ?? [];\n\t\t\tconst parentRoutes = parentMeta.routes;\n\n\t\t\t// Child routes override parent routes with same propertyKey\n\t\t\tconst mergedRoutes = [...parentRoutes];\n\t\t\tfor (const childRoute of childRoutes) {\n\t\t\t\tconst existingIndex = mergedRoutes.findIndex(\n\t\t\t\t\t(r) => r.propertyKey === childRoute.propertyKey,\n\t\t\t\t);\n\t\t\t\tif (existingIndex >= 0) {\n\t\t\t\t\tmergedRoutes[existingIndex] = childRoute;\n\t\t\t\t} else {\n\t\t\t\t\tmergedRoutes.push(childRoute);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tprefix: meta?.prefix ?? parentMeta.prefix,\n\t\t\t\troutes: mergedRoutes,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn meta;\n}\n\n\n","import type { Context } from \"../context\";\nimport { toResponse } from \"./response\";\n\ntype RouteHandler<DI = Record<string, unknown>> = (\n\tctx: Context<DI>,\n) => Promise<Response>;\n\nexport function asyncHandler<DI = Record<string, unknown>>(\n\t// biome-ignore lint/suspicious/noExplicitAny: flexible return\n\thandler: (ctx: Context<DI>) => Promise<any>,\n): RouteHandler<DI> {\n\treturn async (ctx: Context<DI>): Promise<Response> => {\n\t\ttry {\n\t\t\tconst result = await handler(ctx);\n\t\t\treturn toResponse(result);\n\t\t} catch (error: unknown) {\n\t\t\tconst message =\n\t\t\t\terror instanceof Error ? error.message : \"Internal Server Error\";\n\t\t\tconst status = error instanceof HttpError ? error.status : 500;\n\n\t\t\tconst errorName =\n\t\t\t\tstatus === 400\n\t\t\t\t\t? \"Bad Request\"\n\t\t\t\t\t: status === 401\n\t\t\t\t\t\t? \"Unauthorized\"\n\t\t\t\t\t\t: status === 403\n\t\t\t\t\t\t\t? \"Forbidden\"\n\t\t\t\t\t\t\t: status === 404\n\t\t\t\t\t\t\t\t? \"Not Found\"\n\t\t\t\t\t\t\t\t: status === 405\n\t\t\t\t\t\t\t\t\t? \"Method Not Allowed\"\n\t\t\t\t\t\t\t\t\t: status === 409\n\t\t\t\t\t\t\t\t\t\t? \"Conflict\"\n\t\t\t\t\t\t\t\t\t\t: status === 422\n\t\t\t\t\t\t\t\t\t\t\t? \"Unprocessable Entity\"\n\t\t\t\t\t\t\t\t\t\t\t: status === 429\n\t\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\t: status === 503\n\t\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\t: \"Internal Server Error\";\n\n\t\t\treturn ctx.json({ success: false, error: errorName, message }, status);\n\t\t}\n\t};\n}\n\nexport class HttpError extends Error {\n\tstatus: number;\n\n\tconstructor(status: number, message: string) {\n\t\tsuper(message);\n\t\tthis.status = status;\n\t\tthis.name = \"HttpError\";\n\t}\n}\n\nexport class NotFoundError extends HttpError {\n\tconstructor(message = \"Not Found\") {\n\t\tsuper(404, message);\n\t\tthis.name = \"NotFoundError\";\n\t}\n}\n\nexport class BadRequestError extends HttpError {\n\tconstructor(message = \"Bad Request\") {\n\t\tsuper(400, message);\n\t\tthis.name = \"BadRequestError\";\n\t}\n}\n\nexport class UnauthorizedError extends HttpError {\n\tconstructor(message = \"Unauthorized\") {\n\t\tsuper(401, message);\n\t\tthis.name = \"UnauthorizedError\";\n\t}\n}\n\nexport class ForbiddenError extends HttpError {\n\tconstructor(message = \"Forbidden\") {\n\t\tsuper(403, message);\n\t\tthis.name = \"ForbiddenError\";\n\t}\n}\n\nexport class MethodNotAllowedError extends HttpError {\n\tconstructor(message = \"Method Not Allowed\") {\n\t\tsuper(405, message);\n\t\tthis.name = \"MethodNotAllowedError\";\n\t}\n}\n\nexport class ConflictError extends HttpError {\n\tconstructor(message = \"Conflict\") {\n\t\tsuper(409, message);\n\t\tthis.name = \"ConflictError\";\n\t}\n}\n\nexport class UnprocessableEntityError extends HttpError {\n\tconstructor(message = \"Unprocessable Entity\") {\n\t\tsuper(422, message);\n\t\tthis.name = \"UnprocessableEntityError\";\n\t}\n}\n\nexport class TooManyRequestsError extends HttpError {\n\tconstructor(message = \"Too Many Requests\") {\n\t\tsuper(429, message);\n\t\tthis.name = \"TooManyRequestsError\";\n\t}\n}\n\nexport class InternalServerError extends HttpError {\n\tconstructor(message = \"Internal Server Error\") {\n\t\tsuper(500, message);\n\t\tthis.name = \"InternalServerError\";\n\t}\n}\n\nexport class ServiceUnavailableError extends HttpError {\n\tconstructor(message = \"Service Unavailable\") {\n\t\tsuper(503, message);\n\t\tthis.name = \"ServiceUnavailableError\";\n\t}\n}\n","/**\n * Central response normalizer - Elysia-style flexible return.\n *\n * Allows handlers to return string | number | boolean | object | array | null | void\n * in addition to Response, and automatically serializes to correct Response.\n *\n * - Response -> passthrough\n * - null/undefined/void -> 204 No Content\n * - string -> text/plain; charset=utf-8\n * - number/boolean/bigint -> text/plain via String(value)\n * - Blob/ArrayBuffer/Uint8Array/ReadableStream -> BodyInit passthrough\n * - object/array -> application/json via Response.json\n */\n\nconst TEXT_HEADERS: Record<string, string> = {\n\t\"Content-Type\": \"text/plain; charset=utf-8\",\n};\n\nexport function toResponse(value: unknown): Response {\n\tif (value instanceof Response) return value;\n\tif (value === null || value === undefined) {\n\t\treturn new Response(null, { status: 204 });\n\t}\n\tconst t = typeof value;\n\tif (t === \"string\") {\n\t\treturn new Response(value as string, { headers: TEXT_HEADERS });\n\t}\n\tif (t === \"number\" || t === \"boolean\" || t === \"bigint\") {\n\t\treturn new Response(String(value), { headers: TEXT_HEADERS });\n\t}\n\t// Binary / stream bodies should not be JSON-stringified\n\tif (\n\t\tvalue instanceof Blob ||\n\t\tvalue instanceof ArrayBuffer ||\n\t\tvalue instanceof Uint8Array ||\n\t\tvalue instanceof ReadableStream\n\t) {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: BodyInit union is DOM-specific\n\t\treturn new Response(value as any);\n\t}\n\t// Array, plain object, etc. -> JSON\n\treturn Response.json(value);\n}\n\nexport function toResponseMaybeAsync(\n\tvalue: unknown,\n): Response | Promise<Response> {\n\tif (value instanceof Promise) {\n\t\treturn value.then(toResponse);\n\t}\n\treturn toResponse(value);\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\ninterface 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}\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\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 ?? true;\n\t\tthis.flushInterval = options?.flushInterval ?? 2000;\n\t\tthis.flushThreshold = options?.flushThreshold ?? 100;\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\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, ...meta };\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 (meta) {\n\t\t\t\tconst keys = Object.keys(meta);\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 = meta[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(meta)}${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}${meta ? ` ${JSON.stringify(meta)}` : \"\"}\\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\tlogRequests: process.env.LOG_REQUESTS !== \"false\",\n});\n","import { Trie as NativeTrie } from \"../ffi\";\nimport { NodeType, RouterNode } from \"./node\";\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// Simple fixed-size 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.\nconst CACHE_MAX = 2048;\n\nclass LookupCache {\n\tprivate map = new Map<string, Map<string, LookupResult>>();\n\tprivate queue: Array<{ method: string; path: string }> = [];\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.queue.length >= CACHE_MAX) {\n\t\t\t// Evict the oldest entry\n\t\t\tconst oldest = this.queue.shift();\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}\n\n\t\tmethodMap.set(path, val);\n\t\tthis.queue.push({ method, path });\n\t}\n}\n\nexport class Router {\n\tprivate root: RouterNode = new RouterNode(\"/\", NodeType.STATIC);\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\tprivate static splitPath(path: string): string[] {\n\t\tconst segments: string[] = [];\n\t\tlet start = 0;\n\t\tif (path[0] === \"/\") start = 1;\n\t\tfor (let i = start; i < path.length; i++) {\n\t\t\tif (path[i] === \"/\") {\n\t\t\t\tif (i > start) {\n\t\t\t\t\tsegments.push(path.substring(start, i));\n\t\t\t\t}\n\t\t\t\tstart = i + 1;\n\t\t\t}\n\t\t}\n\t\tif (start < path.length) {\n\t\t\tsegments.push(path.substring(start));\n\t\t}\n\t\treturn segments;\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 segments = Router.splitPath(path);\n\t\tconst hasParams = segments.some((s) => s[0] === \":\" || s[0] === \"*\");\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}\n\n\t\t// Register in trie for dynamic routes\n\t\tif (hasParams) {\n\t\t\tconst handlerId = this.nextHandlerId++;\n\t\t\tthis.handlerRegistry.set(handlerId, handler);\n\t\t\t// Use composite key: \"METHOD:/path/:param\"\n\t\t\tconst compositeKey = `${upperMethod}:${path}`;\n\t\t\tthis.nativeTrie.insert(compositeKey, handlerId);\n\t\t}\n\n\t\t// Also insert into JS trie for fallback / non-native\n\t\tlet currentNode = this.root;\n\n\t\tif (segments.length === 0) {\n\t\t\tthis.root.handlers.set(upperMethod, handler);\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const segment of segments) {\n\t\t\tlet nodeType = NodeType.STATIC;\n\t\t\tlet paramName: string | null = null;\n\t\t\tlet cleanSegment = segment;\n\n\t\t\tif (segment.startsWith(\":\")) {\n\t\t\t\tnodeType = NodeType.PARAM;\n\t\t\t\tparamName = segment.slice(1);\n\t\t\t\tcleanSegment = \":\";\n\t\t\t} else if (segment.startsWith(\"*\")) {\n\t\t\t\tnodeType = NodeType.CATCHALL;\n\t\t\t\tparamName = segment.slice(1);\n\t\t\t\tcleanSegment = \"*\";\n\t\t\t} else {\n\t\t\t\tnodeType = NodeType.STATIC;\n\t\t\t\tcleanSegment = segment;\n\t\t\t}\n\n\t\t\tlet childNode: RouterNode | undefined;\n\n\t\t\tif (nodeType === NodeType.STATIC) {\n\t\t\t\tchildNode = currentNode.staticChildren.get(cleanSegment);\n\t\t\t} else if (nodeType === NodeType.PARAM) {\n\t\t\t\tchildNode = currentNode.paramChild ?? undefined;\n\t\t\t} else {\n\t\t\t\tchildNode = currentNode.catchAllChild ?? undefined;\n\t\t\t}\n\n\t\t\tif (!childNode) {\n\t\t\t\tchildNode = new RouterNode(cleanSegment, nodeType);\n\n\t\t\t\tif (nodeType === NodeType.PARAM) {\n\t\t\t\t\tchildNode.paramName = paramName;\n\t\t\t\t\tcurrentNode.paramChild = childNode;\n\t\t\t\t} else if (nodeType === NodeType.CATCHALL) {\n\t\t\t\t\tchildNode.paramName = paramName;\n\t\t\t\t\tcurrentNode.catchAllChild = childNode;\n\t\t\t\t} else {\n\t\t\t\t\tcurrentNode.staticChildren.set(cleanSegment, childNode);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcurrentNode = childNode;\n\n\t\t\tif (nodeType === NodeType.CATCHALL) break;\n\t\t}\n\n\t\tcurrentNode.handlers.set(upperMethod, handler);\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\t{\n\t\t\tconst compositeKey = `${method}:${path}`;\n\t\t\tconst nativeResult = this.nativeTrie.find(compositeKey);\n\n\t\t\tif (nativeResult.handlerId !== -1) {\n\t\t\t\tconst handler = this.handlerRegistry.get(nativeResult.handlerId);\n\t\t\t\tif (handler) {\n\t\t\t\t\tconst result: LookupResult = {\n\t\t\t\t\t\thandler,\n\t\t\t\t\t\tparams: nativeResult.params,\n\t\t\t\t\t};\n\t\t\t\t\tthis.lookupCache.set(method, path, result);\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Slow path: JS trie traversal for param/catchall routes\n\t\tconst result: LookupResult = {\n\t\t\thandler: null,\n\t\t\tparams: null as unknown as Record<string, string>,\n\t\t};\n\t\tlet currentNode = this.root;\n\n\t\tlet start = path[0] === \"/\" ? 1 : 0;\n\t\tif (start >= path.length) {\n\t\t\tresult.handler = this.root.handlers.get(method) || null;\n\t\t\tif (result.handler) result.params = EMPTY_PARAMS;\n\t\t\telse result.params = EMPTY_PARAMS;\n\t\t\treturn result;\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 = currentNode.staticChildren.get(segment);\n\n\t\t\t\tif (!nextNode) {\n\t\t\t\t\tif (currentNode.paramChild) {\n\t\t\t\t\t\tnextNode = currentNode.paramChild;\n\t\t\t\t\t\tif (!result.params) result.params = {};\n\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: Known to exist due to node structure\n\t\t\t\t\t\tresult.params[nextNode.paramName!] = segment;\n\t\t\t\t\t} else if (currentNode.catchAllChild) {\n\t\t\t\t\t\tnextNode = currentNode.catchAllChild;\n\t\t\t\t\t\tif (!result.params) result.params = {};\n\t\t\t\t\t\tresult.params[\"*\"] = path.substring(start);\n\t\t\t\t\t\tcurrentNode = nextNode;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn { handler: null, params: EMPTY_PARAMS };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcurrentNode = nextNode;\n\t\t\t}\n\t\t\tstart = end + 1;\n\t\t}\n\n\t\tresult.handler = currentNode.handlers.get(method) || null;\n\t\tif (!result.params) result.params = EMPTY_PARAMS;\n\n\t\t// Cache the result for future identical lookups\n\t\tif (result.handler) {\n\t\t\tthis.lookupCache.set(method, path, result);\n\t\t}\n\n\t\treturn result;\n\t}\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","// ─── 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","export enum NodeType {\n\tSTATIC = 0,\n\tPARAM = 1,\n\tCATCHALL = 2,\n}\n\nexport interface RouteHandler {\n\tmethod: string;\n\t// biome-ignore lint/suspicious/noExplicitAny: generic router handler\n\thandler: (...args: any[]) => any;\n}\n\nexport class RouterNode {\n\tpath: string = \"\";\n\ttype: NodeType = NodeType.STATIC;\n\tstaticChildren: Map<string, RouterNode> = new Map();\n\tparamChild: RouterNode | null = null;\n\tcatchAllChild: RouterNode | null = null;\n\t// biome-ignore lint/suspicious/noExplicitAny: generic router handler\n\thandlers: Map<string, (...args: any[]) => any> = new Map();\n\tparamName: string | null = null;\n\n\tconstructor(path: string = \"\", type: NodeType = NodeType.STATIC) {\n\t\tthis.path = path;\n\t\tthis.type = type;\n\t}\n}\n","import type { Middleware } from \"./app\";\nimport type { Context } from \"./context\";\n\nconst textEncoder = new TextEncoder();\n\nfunction base64UrlEncode(buffer: ArrayBuffer | Uint8Array) {\n\treturn btoa(String.fromCharCode(...new Uint8Array(buffer)))\n\t\t.replace(/\\+/g, \"-\")\n\t\t.replace(/\\//g, \"_\")\n\t\t.replace(/=+$/, \"\");\n}\n\nfunction base64UrlDecode(str: string) {\n\tstr = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n\tconst pad = str.length % 4;\n\tif (pad) str += \"=\".repeat(4 - pad);\n\treturn Uint8Array.from(atob(str), (c) => c.charCodeAt(0));\n}\n\n/**\n * Zero-dependency, ultra-fast JWT implementation using WebCrypto API\n */\nexport class JwtService {\n\tconstructor(private secret: string) {}\n\n\tasync sign(\n\t\tpayload: Record<string, unknown>,\n\t\texpiresInSeconds?: number,\n\t): Promise<string> {\n\t\tconst header = base64UrlEncode(\n\t\t\ttextEncoder.encode(JSON.stringify({ alg: \"HS256\", typ: \"JWT\" })),\n\t\t);\n\n\t\tconst exp = expiresInSeconds\n\t\t\t? Math.floor(Date.now() / 1000) + expiresInSeconds\n\t\t\t: undefined;\n\t\tconst data = base64UrlEncode(\n\t\t\ttextEncoder.encode(JSON.stringify({ ...payload, exp })),\n\t\t);\n\n\t\tconst key = await crypto.subtle.importKey(\n\t\t\t\"raw\",\n\t\t\ttextEncoder.encode(this.secret),\n\t\t\t{ name: \"HMAC\", hash: \"SHA-256\" },\n\t\t\tfalse,\n\t\t\t[\"sign\"],\n\t\t);\n\n\t\tconst signature = await crypto.subtle.sign(\n\t\t\t\"HMAC\",\n\t\t\tkey,\n\t\t\ttextEncoder.encode(`${header}.${data}`),\n\t\t);\n\t\treturn `${header}.${data}.${base64UrlEncode(signature)}`;\n\t}\n\n\tasync verify<T = Record<string, unknown>>(token: string): Promise<T | null> {\n\t\tconst parts = token.split(\".\");\n\t\tif (parts.length !== 3) return null;\n\n\t\ttry {\n\t\t\tconst key = await crypto.subtle.importKey(\n\t\t\t\t\"raw\",\n\t\t\t\ttextEncoder.encode(this.secret),\n\t\t\t\t{ name: \"HMAC\", hash: \"SHA-256\" },\n\t\t\t\tfalse,\n\t\t\t\t[\"verify\"],\n\t\t\t);\n\n\t\t\tconst signature = base64UrlDecode(parts[2]!);\n\t\t\tconst valid = await crypto.subtle.verify(\n\t\t\t\t\"HMAC\",\n\t\t\t\tkey,\n\t\t\t\tsignature,\n\t\t\t\ttextEncoder.encode(`${parts[0]}.${parts[1]}`),\n\t\t\t);\n\n\t\t\tif (!valid) return null;\n\n\t\t\tconst payload = JSON.parse(\n\t\t\t\tnew TextDecoder().decode(base64UrlDecode(parts[1]!)),\n\t\t\t);\n\n\t\t\t// Check expiration\n\t\t\tif (payload.exp && Math.floor(Date.now() / 1000) > payload.exp) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn payload as T;\n\t\t} catch (_e) {\n\t\t\treturn null;\n\t\t}\n\t}\n}\n\n/**\n * Middleware that extracts JWT, verifies it, and injects user payload into `ctx.user`.\n * Returns 401 if unauthorized.\n *\n * Auth source is configured via environment variables:\n * - `AUTH_STORE=header` (default): Read from Authorization: Bearer <token> header\n * - `AUTH_STORE=cookie`: Read from HttpOnly cookie (name from AUTH_COOKIE env var)\n * - Falls back to header if cookie not found\n */\nexport function requireAuth(\n\tsecret: string,\n): Middleware<Record<string, unknown>> {\n\tconst jwt = new JwtService(secret);\n\n\treturn async (\n\t\tctx: Context<Record<string, unknown>>,\n\t\tnext: () => Promise<Response> | Response,\n\t) => {\n\t\tlet token: string | undefined;\n\t\tconst authStore = process.env.AUTH_STORE ?? \"header\";\n\n\t\t// Cookie-based auth\n\t\tif (authStore === \"cookie\") {\n\t\t\tconst cookieName = process.env.AUTH_COOKIE;\n\t\t\tif (cookieName) {\n\t\t\t\ttoken = ctx.getCookie(cookieName);\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to Authorization header (always try, even if AUTH_STORE=cookie)\n\t\tif (!token) {\n\t\t\tconst authHeader = ctx.request.headers.get(\"Authorization\");\n\t\t\tif (authHeader?.startsWith(\"Bearer \")) {\n\t\t\t\ttoken = authHeader.split(\" \")[1];\n\t\t\t}\n\t\t}\n\n\t\tif (!token) {\n\t\t\treturn ctx.json(\n\t\t\t\t{ error: \"Unauthorized\", message: \"Missing or invalid authentication token\" },\n\t\t\t\t401,\n\t\t\t);\n\t\t}\n\n\t\tconst user = await jwt.verify(token);\n\n\t\tif (!user) {\n\t\t\treturn ctx.json(\n\t\t\t\t{ error: \"Unauthorized\", message: \"Token is invalid or expired\" },\n\t\t\t\t401,\n\t\t\t);\n\t\t}\n\n\t\t// Inject user into context (buntok style)\n\t\tctx.user = user;\n\n\t\treturn next();\n\t};\n}\n","// ─── Types ────────────────────────────────────────────────────────────────────\nexport type {\n  OAuth2Tokens,\n  OAuthUser,\n  OAuthProviderConfig,\n  OAuthProvider,\n  CreateAuthorizationURLOptions,\n  ValidateAuthorizationCodeOptions,\n  AppleProviderConfig,\n} from \"./types\";\n\nexport {\n  OAuthError,\n  OAuthStateError,\n  OAuthTokenError,\n  OAuthProviderError,\n} from \"./types\";\n\n// ─── PKCE ─────────────────────────────────────────────────────────────────────\nexport {\n  generateCodeVerifier,\n  generateCodeChallenge,\n  generatePKCE,\n} from \"./pkce\";\n\n// ─── State Management ─────────────────────────────────────────────────────────\nexport {\n  storeOAuthState,\n  verifyOAuthState,\n  getCodeVerifier,\n  clearOAuthCookies,\n} from \"./state\";\n\n// ─── Base Provider ────────────────────────────────────────────────────────────\nexport { BaseOAuthProvider } from \"./provider\";\n\n// ─── Generic Helpers ──────────────────────────────────────────────────────────\nexport {\n  createOAuth2AuthorizationURL,\n  validateOAuth2AuthorizationCode,\n  decodeIdToken,\n} from \"./helpers\";\n\n// ─── Built-in Providers ───────────────────────────────────────────────────────\nexport { GoogleProvider, type GoogleUser } from \"./providers/google\";\nexport { GitHubProvider, type GitHubUser } from \"./providers/github\";\nexport { AppleProvider, type AppleUser } from \"./providers/apple\";\n\n// ─── Convenience Factory ──────────────────────────────────────────────────────\nimport type { OAuthProviderConfig, AppleProviderConfig } from \"./types\";\nimport { GoogleProvider } from \"./providers/google\";\nimport { GitHubProvider } from \"./providers/github\";\nimport { AppleProvider } from \"./providers/apple\";\n\n/**\n * Create OAuth providers with a simple factory API\n *\n * @example\n * ```ts\n * import { createOAuth } from \"@buntok/core\";\n *\n * const google = createOAuth.google({\n *   clientId: process.env.GOOGLE_CLIENT_ID!,\n *   clientSecret: process.env.GOOGLE_CLIENT_SECRET!,\n *   redirectURI: \"http://localhost:1212/auth/google/callback\",\n * });\n * ```\n */\nexport const createOAuth = {\n  google: (config: OAuthProviderConfig) => new GoogleProvider(config),\n  github: (config: OAuthProviderConfig) => new GitHubProvider(config),\n  apple: (config: AppleProviderConfig) => new AppleProvider(config),\n};\n","// ─── Token Types ──────────────────────────────────────────────────────────────\n\nexport interface OAuth2Tokens {\n  accessToken: string;\n  refreshToken?: string;\n  idToken?: string;\n  expiresAt?: number;\n  tokenType?: string;\n  scope?: string;\n}\n\n// ─── User Types ───────────────────────────────────────────────────────────────\n\nexport interface OAuthUser {\n  id: string;\n  name?: string;\n  email?: string;\n  emailVerified?: boolean;\n  image?: string;\n  [key: string]: unknown;\n}\n\n// ─── Provider Config ──────────────────────────────────────────────────────────\n\nexport interface OAuthProviderConfig {\n  clientId: string;\n  clientSecret: string;\n  redirectURI: string;\n  scopes?: string[];\n}\n\n// ─── Provider Interface ───────────────────────────────────────────────────────\n\nexport interface OAuthProvider {\n  readonly id: string;\n  createAuthorizationURL(state: string, codeVerifier: string): Promise<string> | string;\n  validateAuthorizationCode(\n    code: string,\n    redirectURI: string,\n    codeVerifier?: string,\n  ): Promise<OAuth2Tokens>;\n  getUserInfo(tokens: OAuth2Tokens): Promise<OAuthUser>;\n}\n\n// ─── Generic OAuth Helpers ────────────────────────────────────────────────────\n\nexport interface CreateAuthorizationURLOptions {\n  clientId: string;\n  redirectURI: string;\n  scopes?: string[];\n  state: string;\n  codeChallenge?: string;\n  additionalParams?: Record<string, string>;\n}\n\nexport interface ValidateAuthorizationCodeOptions {\n  code: string;\n  redirectURI: string;\n  clientId: string;\n  clientSecret: string;\n  codeVerifier?: string;\n  tokenEndpoint: string;\n}\n\n// ─── Apple-Specific Types ─────────────────────────────────────────────────────\n\nexport interface AppleProviderConfig extends OAuthProviderConfig {\n  teamId: string;\n  keyId: string;\n  privateKey: string;\n}\n\n// ─── Error Classes ────────────────────────────────────────────────────────────\n\nexport class OAuthError extends Error {\n  public readonly code: string;\n  public readonly provider: string;\n\n  constructor(message: string, code: string, provider: string) {\n    super(message);\n    this.name = \"OAuthError\";\n    this.code = code;\n    this.provider = provider;\n  }\n}\n\nexport class OAuthStateError extends OAuthError {\n  constructor(provider: string) {\n    super(\"OAuth state mismatch - possible CSRF attack\", \"STATE_MISMATCH\", provider);\n    this.name = \"OAuthStateError\";\n  }\n}\n\nexport class OAuthTokenError extends OAuthError {\n  constructor(message: string, provider: string) {\n    super(message, \"TOKEN_ERROR\", provider);\n    this.name = \"OAuthTokenError\";\n  }\n}\n\nexport class OAuthProviderError extends OAuthError {\n  public readonly providerError?: string;\n  public readonly providerErrorDescription?: string;\n\n  constructor(\n    message: string,\n    provider: string,\n    providerError?: string,\n    providerErrorDescription?: string,\n  ) {\n    super(message, \"PROVIDER_ERROR\", provider);\n    this.name = \"OAuthProviderError\";\n    this.providerError = providerError;\n    this.providerErrorDescription = providerErrorDescription;\n  }\n}\n","// ─── PKCE Helpers (RFC 7636) ───────────────────────────────────────────────────\n// Uses Web Crypto API (built-in Bun/Node 18+)\n\nconst CHARSET =\n  \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~\";\n\n/**\n * Generate a cryptographically random code verifier (RFC 7636 §4.1)\n * Length: 43-128 characters, using unreserved characters only\n */\nexport function generateCodeVerifier(length: number = 43): string {\n  if (length < 43 || length > 128) {\n    throw new RangeError(\"Code verifier length must be between 43 and 128\");\n  }\n\n  const bytes = new Uint8Array(length);\n  crypto.getRandomValues(bytes);\n\n  let verifier = \"\";\n  for (let i = 0; i < length; i++) {\n    verifier += CHARSET[bytes[i]! % CHARSET.length];\n  }\n  return verifier;\n}\n\n/**\n * Compute S256 code challenge from a code verifier (RFC 7636 §4.2)\n * code_challenge = BASE64URL(SHA256(code_verifier))\n */\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n  const encoder = new TextEncoder();\n  const data = encoder.encode(verifier);\n  const digest = await crypto.subtle.digest(\"SHA-256\", data);\n  return base64UrlEncode(new Uint8Array(digest));\n}\n\n/**\n * Generate PKCE code verifier + challenge pair\n */\nexport async function generatePKCE(): Promise<{\n  codeVerifier: string;\n  codeChallenge: string;\n}> {\n  const codeVerifier = generateCodeVerifier();\n  const codeChallenge = await generateCodeChallenge(codeVerifier);\n  return { codeVerifier, codeChallenge };\n}\n\n// ─── Base64URL Encoding ───────────────────────────────────────────────────────\n\nfunction base64UrlEncode(buffer: Uint8Array): string {\n  let binary = \"\";\n  for (let i = 0; i < buffer.length; i++) {\n    binary += String.fromCharCode(buffer[i]!);\n  }\n  return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n","import {\n  setCookie,\n  getCookie,\n  deleteCookie,\n} from \"../helpers/cookie\";\n\n// ─── Cookie Names ─────────────────────────────────────────────────────────────\n\nconst OAUTH_STATE_COOKIE = \"__buntok_oauth_state\";\nconst OAUTH_VERIFIER_COOKIE = \"__buntok_oauth_verifier\";\n\n// ─── State Management ─────────────────────────────────────────────────────────\n\n/**\n * Store OAuth state + PKCE code verifier in HttpOnly cookies\n */\nexport function storeOAuthState(\n  response: Response,\n  state: string,\n  codeVerifier: string,\n): Response {\n  let res = setCookie(response, OAUTH_STATE_COOKIE, state, {\n    httpOnly: true,\n    secure: true,\n    sameSite: \"lax\",\n    path: \"/\",\n    maxAge: 600, // 10 minutes\n  });\n\n  res = setCookie(res, OAUTH_VERIFIER_COOKIE, codeVerifier, {\n    httpOnly: true,\n    secure: true,\n    sameSite: \"lax\",\n    path: \"/\",\n    maxAge: 600,\n  });\n\n  return res;\n}\n\n/**\n * Verify OAuth state matches (prevents CSRF)\n */\nexport function verifyOAuthState(\n  request: Request,\n  expectedState: string,\n): boolean {\n  const storedState = getCookie(request, OAUTH_STATE_COOKIE);\n  if (!storedState) return false;\n  return storedState === expectedState;\n}\n\n/**\n * Get PKCE code verifier from cookie\n */\nexport function getCodeVerifier(request: Request): string | undefined {\n  return getCookie(request, OAUTH_VERIFIER_COOKIE);\n}\n\n/**\n * Clear OAuth cookies (called automatically after callback)\n */\nexport function clearOAuthCookies(response: Response): Response {\n  let res = deleteCookie(response, OAUTH_STATE_COOKIE, {\n    httpOnly: true,\n    secure: true,\n    sameSite: \"lax\",\n    path: \"/\",\n  });\n\n  res = deleteCookie(res, OAUTH_VERIFIER_COOKIE, {\n    httpOnly: true,\n    secure: true,\n    sameSite: \"lax\",\n    path: \"/\",\n  });\n\n  return res;\n}\n","export interface CookieOptions {\n\t/** Domain to set the cookie on */\n\tdomain?: string;\n\t/** Expiration time in seconds */\n\tmaxAge?: number;\n\t/** Absolute expiration date */\n\texpires?: Date;\n\t/** Cookie path (default: /) */\n\tpath?: string;\n\t/** Secure flag (HTTPS only) */\n\tsecure?: boolean;\n\t/** HttpOnly flag (not accessible via JavaScript) */\n\thttpOnly?: boolean;\n\t/** SameSite policy */\n\tsameSite?: \"strict\" | \"lax\" | \"none\";\n\t/** Cookie partition key (for partitioned cookies) */\n\tpartitioned?: boolean;\n}\n\n/**\n * Parse cookies from Cookie header string\n */\nexport function parseCookies(cookieHeader: string): Record<string, string> {\n\tconst cookies: Record<string, string> = {};\n\n\tif (!cookieHeader) return cookies;\n\n\tconst pairs = cookieHeader.split(\";\");\n\n\tfor (const pair of pairs) {\n\t\tconst [name, ...valueParts] = pair.split(\"=\");\n\t\tif (name === undefined) continue;\n\t\tconst trimmedName = name.trim();\n\t\tconst value = valueParts.join(\"=\").trim();\n\n\t\tif (trimmedName) {\n\t\t\tcookies[trimmedName] = decodeURIComponent(value);\n\t\t}\n\t}\n\n\treturn cookies;\n}\n\n/**\n * Serialize a cookie to a string\n */\nexport function serializeCookie(\n\tname: string,\n\tvalue: string,\n\toptions: CookieOptions = {},\n): string {\n\tlet cookie = `${name}=${encodeURIComponent(value)}`;\n\n\tif (options.domain) {\n\t\tcookie += `; Domain=${options.domain}`;\n\t}\n\n\tif (options.maxAge !== undefined) {\n\t\tcookie += `; Max-Age=${options.maxAge}`;\n\t}\n\n\tif (options.expires) {\n\t\tcookie += `; Expires=${options.expires.toUTCString()}`;\n\t}\n\n\tcookie += `; Path=${options.path || \"/\"}`;\n\n\tif (options.secure) {\n\t\tcookie += \"; Secure\";\n\t}\n\n\tif (options.httpOnly) {\n\t\tcookie += \"; HttpOnly\";\n\t}\n\n\tif (options.sameSite) {\n\t\tcookie += `; SameSite=${options.sameSite.charAt(0).toUpperCase() + options.sameSite.slice(1)}`;\n\t}\n\n\tif (options.partitioned) {\n\t\tcookie += \"; Partitioned\";\n\t}\n\n\treturn cookie;\n}\n\n/**\n * Get a cookie value from request\n */\nexport function getCookie(request: Request, name: string): string | undefined {\n\tconst cookieHeader = request.headers.get(\"Cookie\");\n\tif (!cookieHeader) return undefined;\n\n\tconst cookies = parseCookies(cookieHeader);\n\treturn cookies[name];\n}\n\n/**\n * Get all cookies from request\n */\nexport function getCookies(request: Request): Record<string, string> {\n\tconst cookieHeader = request.headers.get(\"Cookie\");\n\treturn parseCookies(cookieHeader || \"\");\n}\n\n/**\n * Set a cookie on Response\n */\nexport function setCookie(\n\tresponse: Response,\n\tname: string,\n\tvalue: string,\n\toptions: CookieOptions = {},\n): Response {\n\tconst cookie = serializeCookie(name, value, options);\n\n\t// Clone response headers into a new Headers object to avoid\n\t// the body-stream being consumed by the Response constructor\n\t// when the original response's body is already locked.\n\tconst newHeaders = new Headers();\n\tresponse.headers.forEach((value, key) => {\n\t\tnewHeaders.set(key, value);\n\t});\n\tnewHeaders.append(\"Set-Cookie\", cookie);\n\n\treturn new Response(response.body, {\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\theaders: newHeaders,\n\t});\n}\n\n/**\n * Delete a cookie (set expired)\n */\nexport function deleteCookie(\n\tresponse: Response,\n\tname: string,\n\toptions: Omit<CookieOptions, \"maxAge\" | \"expires\"> = {},\n): Response {\n\treturn setCookie(response, name, \"\", {\n\t\t...options,\n\t\tmaxAge: 0,\n\t\texpires: new Date(0),\n\t});\n}\n","import type {\n  OAuthProvider,\n  OAuthProviderConfig,\n  OAuth2Tokens,\n  OAuthUser,\n} from \"./types\";\n\n/**\n * Base class for OAuth providers.\n * Extend this to implement custom providers.\n */\nexport abstract class BaseOAuthProvider implements OAuthProvider {\n  abstract readonly id: string;\n\n  protected config: OAuthProviderConfig;\n\n  constructor(config: OAuthProviderConfig) {\n    this.config = config;\n  }\n\n  abstract createAuthorizationURL(\n    state: string,\n    codeVerifier: string,\n  ): Promise<string> | string;\n\n  abstract validateAuthorizationCode(\n    code: string,\n    redirectURI: string,\n    codeVerifier?: string,\n  ): Promise<OAuth2Tokens>;\n\n  abstract getUserInfo(tokens: OAuth2Tokens): Promise<OAuthUser>;\n}\n","import type {\n  CreateAuthorizationURLOptions,\n  ValidateAuthorizationCodeOptions,\n  OAuth2Tokens,\n} from \"./types\";\nimport { OAuthProviderError } from \"./types\";\n\n// ─── Create Authorization URL ─────────────────────────────────────────────────\n\n/**\n * Create an OAuth2 authorization URL for any provider\n */\nexport function createOAuth2AuthorizationURL(\n  authorizationEndpoint: string,\n  options: CreateAuthorizationURLOptions,\n): string {\n  const url = new URL(authorizationEndpoint);\n\n  url.searchParams.set(\"response_type\", \"code\");\n  url.searchParams.set(\"client_id\", options.clientId);\n  url.searchParams.set(\"redirect_uri\", options.redirectURI);\n  url.searchParams.set(\"state\", options.state);\n\n  if (options.scopes?.length) {\n    url.searchParams.set(\"scope\", options.scopes.join(\" \"));\n  }\n\n  if (options.codeChallenge) {\n    url.searchParams.set(\"code_challenge\", options.codeChallenge);\n    url.searchParams.set(\"code_challenge_method\", \"S256\");\n  }\n\n  if (options.additionalParams) {\n    for (const [key, value] of Object.entries(options.additionalParams)) {\n      url.searchParams.set(key, value);\n    }\n  }\n\n  return url.toString();\n}\n\n// ─── Validate Authorization Code ──────────────────────────────────────────────\n\n/**\n * Validate an OAuth2 authorization code with any provider's token endpoint\n */\nexport async function validateOAuth2AuthorizationCode(\n  options: ValidateAuthorizationCodeOptions,\n): Promise<OAuth2Tokens> {\n  const body = new URLSearchParams({\n    grant_type: \"authorization_code\",\n    code: options.code,\n    redirect_uri: options.redirectURI,\n    client_id: options.clientId,\n    client_secret: options.clientSecret,\n  });\n\n  if (options.codeVerifier) {\n    body.set(\"code_verifier\", options.codeVerifier);\n  }\n\n  const response = await fetch(options.tokenEndpoint, {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application/x-www-form-urlencoded\",\n      Accept: \"application/json\",\n    },\n    body: body.toString(),\n  });\n\n  const data = (await response.json()) as Record<string, unknown>;\n\n  if (!response.ok) {\n    throw new OAuthProviderError(\n      `Token exchange failed: ${data.error_description || data.error || \"Unknown error\"}`,\n      \"unknown\",\n      data.error as string,\n      data.error_description as string,\n    );\n  }\n\n  return {\n    accessToken: data.access_token as string,\n    refreshToken: data.refresh_token as string | undefined,\n    idToken: data.id_token as string | undefined,\n    expiresAt: data.expires_in\n      ? Date.now() + (data.expires_in as number) * 1000\n      : undefined,\n    tokenType: data.token_type as string | undefined,\n    scope: data.scope as string | undefined,\n  };\n}\n\n// ─── Decode ID Token (JWT) ────────────────────────────────────────────────────\n\n/**\n * Decode an ID token (JWT) without verification.\n * For production, verify the signature using the provider's public keys.\n */\nexport function decodeIdToken(idToken: string): Record<string, unknown> {\n  const parts = idToken.split(\".\");\n  if (parts.length !== 3) {\n    throw new Error(\"Invalid ID token format\");\n  }\n\n  const payload = parts[1]!;\n  const decoded = atob(payload.replace(/-/g, \"+\").replace(/_/g, \"/\"));\n  return JSON.parse(decoded) as Record<string, unknown>;\n}\n","import { BaseOAuthProvider } from \"../provider\";\nimport { OAuthTokenError, OAuthProviderError } from \"../types\";\nimport { createOAuth2AuthorizationURL, decodeIdToken } from \"../helpers\";\nimport { generateCodeChallenge } from \"../pkce\";\nimport type {\n  OAuthProviderConfig,\n  OAuth2Tokens,\n  OAuthUser,\n} from \"../types\";\n\n// ─── Google OAuth2 / OIDC ─────────────────────────────────────────────────────\n// Docs: https://developers.google.com/identity/openid-connect/openid-connect\n\nconst AUTHORIZATION_ENDPOINT = \"https://accounts.google.com/o/oauth2/v2/auth\";\nconst TOKEN_ENDPOINT = \"https://oauth2.googleapis.com/token\";\nconst USERINFO_ENDPOINT = \"https://www.googleapis.com/oauth2/v3/userinfo\";\nconst ISSUER = \"https://accounts.google.com\";\n\nexport interface GoogleUser extends OAuthUser {\n  sub: string;\n  name?: string;\n  given_name?: string;\n  family_name?: string;\n  picture?: string;\n  email?: string;\n  email_verified?: boolean;\n  locale?: string;\n}\n\nexport class GoogleProvider extends BaseOAuthProvider {\n  readonly id = \"google\";\n\n  constructor(config: OAuthProviderConfig) {\n    super({\n      ...config,\n      scopes: config.scopes ?? [\"openid\", \"email\", \"profile\"],\n    });\n  }\n\n  async createAuthorizationURL(state: string, codeVerifier: string): Promise<string> {\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n    return createOAuth2AuthorizationURL(AUTHORIZATION_ENDPOINT, {\n      clientId: this.config.clientId,\n      redirectURI: this.config.redirectURI,\n      scopes: this.config.scopes,\n      state,\n      codeChallenge,\n    });\n  }\n\n  async validateAuthorizationCode(\n    code: string,\n    redirectURI: string,\n    codeVerifier?: string,\n  ): Promise<OAuth2Tokens> {\n    const body = new URLSearchParams({\n      grant_type: \"authorization_code\",\n      code,\n      redirect_uri: redirectURI,\n      client_id: this.config.clientId,\n      client_secret: this.config.clientSecret,\n    });\n\n    if (codeVerifier) {\n      body.set(\"code_verifier\", codeVerifier);\n    }\n\n    const response = await fetch(TOKEN_ENDPOINT, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/x-www-form-urlencoded\",\n        Accept: \"application/json\",\n      },\n      body: body.toString(),\n    });\n\n    const data = (await response.json()) as Record<string, unknown>;\n\n    if (!response.ok) {\n      throw new OAuthTokenError(\n        `Google token exchange failed: ${data.error_description || data.error || \"Unknown error\"}`,\n        this.id,\n      );\n    }\n\n    return {\n      accessToken: data.access_token as string,\n      refreshToken: data.refresh_token as string | undefined,\n      idToken: data.id_token as string | undefined,\n      expiresAt: data.expires_in\n        ? Date.now() + (data.expires_in as number) * 1000\n        : undefined,\n      tokenType: data.token_type as string | undefined,\n      scope: data.scope as string | undefined,\n    };\n  }\n\n  async getUserInfo(tokens: OAuth2Tokens): Promise<GoogleUser> {\n    // Try to decode ID token first (OIDC - no extra API call needed)\n    if (tokens.idToken) {\n      const claims = decodeIdToken(tokens.idToken);\n\n      // Verify issuer\n      if (claims.iss !== ISSUER && claims.iss !== \"accounts.google.com\") {\n        throw new OAuthProviderError(\n          \"Invalid Google ID token issuer\",\n          this.id,\n          \"invalid_issuer\",\n        );\n      }\n\n      return {\n        id: claims.sub as string,\n        sub: claims.sub as string,\n        name: claims.name as string | undefined,\n        given_name: claims.given_name as string | undefined,\n        family_name: claims.family_name as string | undefined,\n        picture: claims.picture as string | undefined,\n        email: claims.email as string | undefined,\n        emailVerified: claims.email_verified as boolean | undefined,\n        locale: claims.locale as string | undefined,\n      };\n    }\n\n    // Fallback to userinfo endpoint\n    const response = await fetch(USERINFO_ENDPOINT, {\n      headers: {\n        Authorization: `Bearer ${tokens.accessToken}`,\n      },\n    });\n\n    if (!response.ok) {\n      throw new OAuthTokenError(\n        `Failed to fetch Google user info: ${response.status}`,\n        this.id,\n      );\n    }\n\n    const data = (await response.json()) as Record<string, unknown>;\n\n    return {\n      id: data.sub as string,\n      sub: data.sub as string,\n      name: data.name as string | undefined,\n      given_name: data.given_name as string | undefined,\n      family_name: data.family_name as string | undefined,\n      picture: data.picture as string | undefined,\n      email: data.email as string | undefined,\n      emailVerified: data.email_verified as boolean | undefined,\n      locale: data.locale as string | undefined,\n    };\n  }\n}\n","import { BaseOAuthProvider } from \"../provider\";\nimport { OAuthTokenError } from \"../types\";\nimport { createOAuth2AuthorizationURL } from \"../helpers\";\nimport type {\n  OAuthProviderConfig,\n  OAuth2Tokens,\n  OAuthUser,\n} from \"../types\";\n\n// ─── GitHub OAuth2 ────────────────────────────────────────────────────────────\n// Docs: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps\n\nconst AUTHORIZATION_ENDPOINT = \"https://github.com/login/oauth/authorize\";\nconst TOKEN_ENDPOINT = \"https://github.com/login/oauth/access_token\";\nconst API_BASE = \"https://api.github.com\";\n\nexport interface GitHubUser extends OAuthUser {\n  login: string;\n  avatar_url?: string;\n  html_url?: string;\n  bio?: string;\n  company?: string;\n  location?: string;\n  blog?: string;\n}\n\nexport class GitHubProvider extends BaseOAuthProvider {\n  readonly id = \"github\";\n\n  constructor(config: OAuthProviderConfig) {\n    super({\n      ...config,\n      scopes: config.scopes ?? [\"user:email\"],\n    });\n  }\n\n  createAuthorizationURL(state: string, _codeVerifier: string): string {\n    // GitHub doesn't support PKCE (as of 2026)\n    return createOAuth2AuthorizationURL(AUTHORIZATION_ENDPOINT, {\n      clientId: this.config.clientId,\n      redirectURI: this.config.redirectURI,\n      scopes: this.config.scopes,\n      state,\n    });\n  }\n\n  async validateAuthorizationCode(\n    code: string,\n    _redirectURI: string,\n    _codeVerifier?: string,\n  ): Promise<OAuth2Tokens> {\n    // GitHub uses HTTP Basic Auth for token exchange\n    const credentials = btoa(\n      `${this.config.clientId}:${this.config.clientSecret}`,\n    );\n\n    const body = new URLSearchParams({\n      grant_type: \"authorization_code\",\n      code,\n    });\n\n    const response = await fetch(TOKEN_ENDPOINT, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/x-www-form-urlencoded\",\n        Accept: \"application/json\",\n        Authorization: `Basic ${credentials}`,\n      },\n      body: body.toString(),\n    });\n\n    const data = (await response.json()) as Record<string, unknown>;\n\n    if (!response.ok) {\n      throw new OAuthTokenError(\n        `GitHub token exchange failed: ${data.error_description || data.error || \"Unknown error\"}`,\n        this.id,\n      );\n    }\n\n    return {\n      accessToken: data.access_token as string,\n      refreshToken: data.refresh_token as string | undefined,\n      tokenType: data.token_type as string | undefined,\n      scope: data.scope as string | undefined,\n    };\n  }\n\n  async getUserInfo(tokens: OAuth2Tokens): Promise<GitHubUser> {\n    // Fetch user profile\n    const userResponse = await fetch(`${API_BASE}/user`, {\n      headers: {\n        Authorization: `Bearer ${tokens.accessToken}`,\n        Accept: \"application/vnd.github+json\",\n      },\n    });\n\n    if (!userResponse.ok) {\n      throw new OAuthTokenError(\n        `Failed to fetch GitHub user: ${userResponse.status}`,\n        this.id,\n      );\n    }\n\n    const userData = (await userResponse.json()) as Record<string, unknown>;\n\n    // Fetch user emails (email may be private)\n    const emailsResponse = await fetch(`${API_BASE}/user/emails`, {\n      headers: {\n        Authorization: `Bearer ${tokens.accessToken}`,\n        Accept: \"application/vnd.github+json\",\n      },\n    });\n\n    let primaryEmail: string | undefined;\n    let emailVerified = false;\n\n    if (emailsResponse.ok) {\n      const emails = (await emailsResponse.json()) as Array<{\n        email: string;\n        primary: boolean;\n        verified: boolean;\n      }>;\n      const primary = emails.find((e) => e.primary);\n      if (primary) {\n        primaryEmail = primary.email;\n        emailVerified = primary.verified;\n      }\n    }\n\n    return {\n      id: String(userData.id),\n      name: (userData.name as string) || (userData.login as string),\n      email: primaryEmail,\n      emailVerified,\n      image: userData.avatar_url as string | undefined,\n      login: userData.login as string,\n      avatar_url: userData.avatar_url as string | undefined,\n      html_url: userData.html_url as string | undefined,\n      bio: userData.bio as string | undefined,\n      company: userData.company as string | undefined,\n      location: userData.location as string | undefined,\n      blog: userData.blog as string | undefined,\n    };\n  }\n}\n","import { BaseOAuthProvider } from \"../provider\";\nimport { OAuthTokenError, OAuthProviderError } from \"../types\";\nimport { createOAuth2AuthorizationURL, decodeIdToken } from \"../helpers\";\nimport { generateCodeChallenge } from \"../pkce\";\nimport type {\n  AppleProviderConfig,\n  OAuth2Tokens,\n  OAuthUser,\n} from \"../types\";\n\n// ─── Apple OIDC ───────────────────────────────────────────────────────────────\n// Docs: https://developer.apple.com/documentation/sign-in-with-apple\n// NOTE: Apple only sends name on FIRST authentication. Store it if you get it.\n\nconst AUTHORIZATION_ENDPOINT = \"https://appleid.apple.com/auth/authorize\";\nconst TOKEN_ENDPOINT = \"https://appleid.apple.com/auth/token\";\nconst ISSUER = \"https://appleid.apple.com\";\n\nexport interface AppleUser extends OAuthUser {\n  sub: string;\n  email?: string;\n  emailVerified?: boolean;\n  // Apple only sends these ONCE (first auth)\n  /** Raw Apple name object - only available on first authentication */\n  appleName?: {\n    firstName?: string;\n    lastName?: string;\n  };\n}\n\n// ─── JWT Helpers (for Apple client_secret) ─────────────────────────────────────\n\nfunction base64UrlEncode(data: string): string {\n  return btoa(data).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nasync function importPrivateKey(privateKey: string): Promise<CryptoKey> {\n  // Clean the key\n  const cleaned = privateKey\n    .replace(/-----BEGIN PRIVATE KEY-----/, \"\")\n    .replace(/-----END PRIVATE KEY-----/, \"\")\n    .replace(/\\s+/g, \"\");\n\n  const binaryDer = Uint8Array.from(atob(cleaned), (c) => c.charCodeAt(0));\n\n  return crypto.subtle.importKey(\n    \"pkcs8\",\n    binaryDer,\n    { name: \"ECDSA\", namedCurve: \"P-256\" },\n    false,\n    [\"sign\"],\n  );\n}\n\nasync function signJWT(\n  payload: Record<string, unknown>,\n  privateKey: string,\n  keyId: string,\n): Promise<string> {\n  const header = {\n    alg: \"ES256\",\n    kid: keyId,\n  };\n\n  const encodedHeader = base64UrlEncode(JSON.stringify(header));\n  const encodedPayload = base64UrlEncode(JSON.stringify(payload));\n  const signingInput = `${encodedHeader}.${encodedPayload}`;\n\n  const key = await importPrivateKey(privateKey);\n  const encoder = new TextEncoder();\n  const signature = await crypto.subtle.sign(\n    { name: \"ECDSA\", hash: \"SHA-256\" },\n    key,\n    encoder.encode(signingInput),\n  );\n\n  // Convert DER signature to raw R||S format\n  const der = new Uint8Array(signature);\n  // DER: 0x30 [total] 0x02 [rLen] [r...] 0x02 [sLen] [s...]\n  const rLen = der[3]!;\n  const r = der.slice(4, 4 + rLen);\n  const sLen = der[5 + rLen]!;\n  const s = der.slice(6 + rLen, 6 + rLen + sLen);\n\n  // Pad R and S to 32 bytes each\n  const rPadded = new Uint8Array(32);\n  const sPadded = new Uint8Array(32);\n  rPadded.set(r.slice(-32), 32 - Math.min(r.length, 32));\n  sPadded.set(s.slice(-32), 32 - Math.min(s.length, 32));\n\n  // Concatenate R || S\n  const rawSignature = new Uint8Array(64);\n  rawSignature.set(rPadded, 0);\n  rawSignature.set(sPadded, 32);\n\n  const encodedSignature = base64UrlEncode(\n    String.fromCharCode(...rawSignature),\n  );\n\n  return `${signingInput}.${encodedSignature}`;\n}\n\n// ─── Apple Provider ───────────────────────────────────────────────────────────\n\nexport class AppleProvider extends BaseOAuthProvider {\n  readonly id = \"apple\";\n\n  private teamId: string;\n  private keyId: string;\n  private privateKey: string;\n\n  constructor(config: AppleProviderConfig) {\n    super({\n      ...config,\n      scopes: config.scopes ?? [\"name\", \"email\"],\n    });\n    this.teamId = config.teamId;\n    this.keyId = config.keyId;\n    this.privateKey = config.privateKey;\n  }\n\n  /**\n   * Generate client_secret JWT (required by Apple)\n   */\n  private async generateClientSecret(): Promise<string> {\n    const now = Math.floor(Date.now() / 1000);\n\n    return signJWT(\n      {\n        iss: this.teamId,\n        iat: now,\n        exp: now + 15777000, // 6 months (Apple max)\n        aud: ISSUER,\n        sub: this.config.clientId,\n      },\n      this.privateKey,\n      this.keyId,\n    );\n  }\n\n  async createAuthorizationURL(state: string, codeVerifier: string): Promise<string> {\n    // Apple uses a space-separated scope (not comma)\n    const scopes = this.config.scopes?.join(\" \") ?? \"name email\";\n    const codeChallenge = await generateCodeChallenge(codeVerifier);\n\n    return createOAuth2AuthorizationURL(AUTHORIZATION_ENDPOINT, {\n      clientId: this.config.clientId,\n      redirectURI: this.config.redirectURI,\n      scopes: [scopes],\n      state,\n      codeChallenge,\n      additionalParams: {\n        response_mode: \"form_post\",\n      },\n    });\n  }\n\n  async validateAuthorizationCode(\n    code: string,\n    redirectURI: string,\n    codeVerifier?: string,\n  ): Promise<OAuth2Tokens> {\n    const clientSecret = await this.generateClientSecret();\n\n    const body = new URLSearchParams({\n      grant_type: \"authorization_code\",\n      code,\n      redirect_uri: redirectURI,\n      client_id: this.config.clientId,\n      client_secret: clientSecret,\n    });\n\n    if (codeVerifier) {\n      body.set(\"code_verifier\", codeVerifier);\n    }\n\n    const response = await fetch(TOKEN_ENDPOINT, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/x-www-form-urlencoded\",\n        Accept: \"application/json\",\n      },\n      body: body.toString(),\n    });\n\n    const data = (await response.json()) as Record<string, unknown>;\n\n    if (!response.ok) {\n      throw new OAuthTokenError(\n        `Apple token exchange failed: ${data.error_description || data.error || \"Unknown error\"}`,\n        this.id,\n      );\n    }\n\n    return {\n      accessToken: data.access_token as string,\n      refreshToken: data.refresh_token as string | undefined,\n      idToken: data.id_token as string | undefined,\n      expiresAt: data.expires_in\n        ? Date.now() + (data.expires_in as number) * 1000\n        : undefined,\n      tokenType: data.token_type as string | undefined,\n      scope: data.scope as string | undefined,\n    };\n  }\n\n  async getUserInfo(tokens: OAuth2Tokens): Promise<AppleUser> {\n    if (!tokens.idToken) {\n      throw new OAuthProviderError(\n        \"Apple did not return an ID token\",\n        this.id,\n        \"no_id_token\",\n      );\n    }\n\n    const claims = decodeIdToken(tokens.idToken);\n\n    // Verify issuer\n    if (claims.iss !== ISSUER) {\n      throw new OAuthProviderError(\n        \"Invalid Apple ID token issuer\",\n        this.id,\n        \"invalid_issuer\",\n      );\n    }\n\n    // Verify audience\n    if (claims.aud !== this.config.clientId) {\n      throw new OAuthProviderError(\n        \"Invalid Apple ID token audience\",\n        this.id,\n        \"invalid_audience\",\n      );\n    }\n\n    return {\n      id: claims.sub as string,\n      sub: claims.sub as string,\n      email: claims.email as string | undefined,\n      emailVerified: claims.email_verified as boolean | undefined,\n      // Apple only sends name on FIRST auth - may be undefined\n      appleName: claims.name as AppleUser[\"appleName\"],\n    };\n  }\n}\n","import type { Context } from \"./context\";\nimport { Controller, Delete, Get, Post, Put } from \"./decorators\";\n\n/**\n * Abstract base controller with built-in CRUD routes using decorators.\n *\n * Extend this class and provide a route prefix via @Controller decorator.\n * The CRUD methods are pre-decorated with @Get, @Post, @Put, @Delete.\n *\n * @example\n * ```ts\n * import { Controller, BaseController, Context } from \"@buntok/core\";\n *\n * // Simple usage (no input types needed)\n * @Controller(\"/users\")\n * class UserController extends BaseController<User> {\n *   constructor(private userService: UserService) {\n *     super(userService);\n *   }\n * }\n *\n * // With typed inputs (optional)\n * @Controller(\"/users\")\n * class UserController extends BaseController<User, CreateUserInput, UpdateUserInput> {\n *   constructor(private userService: UserService) {\n *     super(userService);\n *   }\n * }\n *\n * // Routes automatically registered:\n * // GET    /users\n * // GET    /users/:id\n * // POST   /users\n * // PUT    /users/:id\n * // DELETE /users/:id\n * ```\n */\n@Controller(\"\")\nexport abstract class BaseController<T, CreateInput = any, UpdateInput = any> {\n\tconstructor(\n\t\tprotected service: {\n\t\t\tgetAll: () => Promise<T[]>;\n\t\t\tgetById: (id: string | number) => Promise<T>;\n\t\t\tcreate: (data: CreateInput) => Promise<T>;\n\t\t\tupdate: (id: string | number, data: UpdateInput) => Promise<T>;\n\t\t\tdelete: (id: string | number) => Promise<T>;\n\t\t},\n\t) {}\n\n\t/**\n\t * Parse URL param id to the correct type.\n\t * Default: tries to convert to number, falls back to string.\n\t * Override this if you need custom id parsing (e.g., UUID).\n\t */\n\tprotected parseId(id: string): string | number {\n\t\tif (id === \"\") return id;\n\t\tconst num = Number(id);\n\t\treturn Number.isNaN(num) ? id : num;\n\t}\n\n\t@Get(\"/\")\n\tasync getAll(ctx: Context) {\n\t\tconst data = await this.service.getAll();\n\t\treturn ctx.success(data);\n\t}\n\n\t@Get(\"/:id\")\n\tasync getById(ctx: Context) {\n\t\tconst id = this.parseId(ctx.params.id ?? \"\");\n\t\tconst data = await this.service.getById(id);\n\t\treturn ctx.success(data);\n\t}\n\n\t@Post(\"/\")\n\tasync create(ctx: Context) {\n\t\tconst body = await ctx.body();\n\t\tconst data = await this.service.create(body as CreateInput);\n\t\treturn ctx.success(data, `Created successfully!.`, 201);\n\t}\n\n\t@Put(\"/:id\")\n\tasync update(ctx: Context) {\n\t\tconst id = this.parseId(ctx.params.id ?? \"\");\n\t\tconst body = await ctx.body();\n\t\tconst data = await this.service.update(id, body as UpdateInput);\n\t\treturn ctx.success(data);\n\t}\n\n\t@Delete(\"/:id\")\n\tasync delete(ctx: Context) {\n\t\tconst id = this.parseId(ctx.params.id ?? \"\");\n\t\tawait this.service.delete(id);\n\t\treturn ctx.status(204);\n\t}\n}\n","import { NotFoundError } from \"./helpers/async-handler\";\n\nexport abstract class BaseService<T, CreateInput = any, UpdateInput = any> {\n\tconstructor(\n\t\tprotected repository: {\n\t\t\tfindAll: () => Promise<T[]>;\n\t\t\tfindById: (id: string | number) => Promise<T | null>;\n\t\t\tcreate: (data: CreateInput) => Promise<T>;\n\t\t\tupdate: (id: string | number, data: UpdateInput) => Promise<T>;\n\t\t\tdelete: (id: string | number) => Promise<T>;\n\t\t\tcount: () => Promise<number>;\n\t\t},\n\t) {}\n\n\tasync getAll(): Promise<T[]> {\n\t\treturn this.repository.findAll();\n\t}\n\n\tasync getById(id: string | number): Promise<T> {\n\t\tconst item = await this.repository.findById(id);\n\t\tif (!item) throw new NotFoundError(`Data dengan id ${id} tidak ditemukan`);\n\t\treturn item;\n\t}\n\n\tasync create(data: CreateInput): Promise<T> {\n\t\treturn this.repository.create(data);\n\t}\n\n\tasync update(id: string | number, data: UpdateInput): Promise<T> {\n\t\tawait this.getById(id);\n\t\treturn this.repository.update(id, data);\n\t}\n\n\tasync delete(id: string | number): Promise<T> {\n\t\tawait this.getById(id);\n\t\treturn this.repository.delete(id);\n\t}\n\n\tasync count(): Promise<number> {\n\t\treturn this.repository.count();\n\t}\n}\n","export interface CacheDriver {\n\tget<T>(key: string): Promise<T | null>;\n\tset<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;\n\tdelete(key: string): Promise<void>;\n\tclear(): Promise<void>;\n\t/** Optional: list all stored keys (used by deletePattern / keys) */\n\tkeys?(): Promise<string[]>;\n}\n\nexport class MemoryCacheDriver implements CacheDriver {\n\tprivate store = new Map<string, { value: unknown; expiry: number | null }>();\n\n\tasync get<T>(key: string): Promise<T | null> {\n\t\tconst item = this.store.get(key);\n\t\tif (!item) return null;\n\t\tif (item.expiry && Date.now() > item.expiry) {\n\t\t\tthis.store.delete(key);\n\t\t\treturn null;\n\t\t}\n\t\treturn item.value as T;\n\t}\n\n\tasync set<T>(key: string, value: T, ttlSeconds?: number): Promise<void> {\n\t\tconst expiry = ttlSeconds ? Date.now() + ttlSeconds * 1000 : null;\n\t\tthis.store.set(key, { value, expiry });\n\t}\n\n\tasync delete(key: string): Promise<void> {\n\t\tthis.store.delete(key);\n\t}\n\n\tasync clear(): Promise<void> {\n\t\tthis.store.clear();\n\t}\n\n\tasync keys(): Promise<string[]> {\n\t\tconst now = Date.now();\n\t\tconst result: string[] = [];\n\t\tfor (const [key, item] of this.store.entries()) {\n\t\t\tif (!item.expiry || now <= item.expiry) {\n\t\t\t\tresult.push(key);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n}\n\nexport class Cache {\n\tconstructor(private driver: CacheDriver = new MemoryCacheDriver()) {}\n\n\tasync get<T>(key: string): Promise<T | null> {\n\t\treturn this.driver.get<T>(key);\n\t}\n\n\tasync set<T>(key: string, value: T, ttlSeconds?: number): Promise<void> {\n\t\treturn this.driver.set(key, value, ttlSeconds);\n\t}\n\n\tasync delete(key: string): Promise<void> {\n\t\treturn this.driver.delete(key);\n\t}\n\n\tasync clear(): Promise<void> {\n\t\treturn this.driver.clear();\n\t}\n\n\t/**\n\t * Returns true if the key exists and has not expired.\n\t */\n\tasync has(key: string): Promise<boolean> {\n\t\treturn (await this.driver.get(key)) !== null;\n\t}\n\n\t/**\n\t * Get value from cache, or execute the factory function to compute and cache it.\n\t *\n\t * @example\n\t * const user = await cache.getOrSet(`user:${id}`, () => db.findUser(id), 300);\n\t */\n\tasync getOrSet<T>(\n\t\tkey: string,\n\t\tfactory: () => Promise<T>,\n\t\tttlSeconds?: number,\n\t): Promise<T> {\n\t\tconst existing = await this.get<T>(key);\n\t\tif (existing !== null) return existing;\n\t\tconst val = await factory();\n\t\tawait this.set(key, val, ttlSeconds);\n\t\treturn val;\n\t}\n\n\t/**\n\t * Atomically increment a numeric value stored at `key`.\n\t * If the key does not exist it is initialized to 0 then incremented.\n\t *\n\t * @param key - Cache key\n\t * @param amount - Amount to add (default: 1)\n\t * @param ttlSeconds - Optional TTL; only applied when the key is first created\n\t */\n\tasync increment(\n\t\tkey: string,\n\t\tamount = 1,\n\t\tttlSeconds?: number,\n\t): Promise<number> {\n\t\tconst current = (await this.get<number>(key)) ?? 0;\n\t\tconst next = current + amount;\n\t\tawait this.set(key, next, current === null ? ttlSeconds : undefined);\n\t\treturn next;\n\t}\n\n\t/**\n\t * Atomically decrement a numeric value stored at `key`.\n\t * If the key does not exist it is initialized to 0 then decremented.\n\t */\n\tasync decrement(\n\t\tkey: string,\n\t\tamount = 1,\n\t\tttlSeconds?: number,\n\t): Promise<number> {\n\t\treturn this.increment(key, -amount, ttlSeconds);\n\t}\n\n\t/**\n\t * Get multiple keys in a single call. Returns `null` for missing keys.\n\t *\n\t * @example\n\t * const [user, post] = await cache.mget([`user:1`, `post:42`]);\n\t */\n\tasync mget<T>(keys: string[]): Promise<(T | null)[]> {\n\t\treturn Promise.all(keys.map((k) => this.get<T>(k)));\n\t}\n\n\t/**\n\t * Set multiple key-value pairs with the same optional TTL.\n\t *\n\t * @example\n\t * await cache.mset([[\"user:1\", userData], [\"user:2\", user2Data]], 300);\n\t */\n\tasync mset<T>(entries: [string, T][], ttlSeconds?: number): Promise<void> {\n\t\tawait Promise.all(\n\t\t\tentries.map(([key, value]) => this.set(key, value, ttlSeconds)),\n\t\t);\n\t}\n\n\t/**\n\t * Delete all keys matching a glob-style pattern.\n\t * Requires the underlying driver to implement `keys()`.\n\t *\n\t * Supported wildcards:\n\t *  - `*` matches any sequence of characters\n\t *  - `?` matches any single character\n\t *\n\t * @example\n\t * await cache.deletePattern(\"session:*\");\n\t * await cache.deletePattern(\"tmp:??:*\");\n\t */\n\tasync deletePattern(pattern: string): Promise<number> {\n\t\tif (!this.driver.keys) {\n\t\t\tthrow new Error(\n\t\t\t\t\"deletePattern() requires the cache driver to implement keys(). \" +\n\t\t\t\t\t\"MemoryCacheDriver supports it; for Redis use SCAN + DEL.\",\n\t\t\t);\n\t\t}\n\t\tconst regex = this.globToRegex(pattern);\n\t\tconst allKeys = await this.driver.keys();\n\t\tconst matching = allKeys.filter((k) => regex.test(k));\n\t\tawait Promise.all(matching.map((k) => this.delete(k)));\n\t\treturn matching.length;\n\t}\n\n\t/**\n\t * List all keys currently stored (non-expired).\n\t * Requires the underlying driver to implement `keys()`.\n\t */\n\tasync keys(): Promise<string[]> {\n\t\tif (!this.driver.keys) {\n\t\t\tthrow new Error(\n\t\t\t\t\"keys() requires the cache driver to implement keys(). \" +\n\t\t\t\t\t\"MemoryCacheDriver supports it.\",\n\t\t\t);\n\t\t}\n\t\treturn this.driver.keys();\n\t}\n\n\t/** Convert a glob pattern to a RegExp */\n\tprivate globToRegex(pattern: string): RegExp {\n\t\tconst escaped = pattern\n\t\t\t.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\") // escape regex specials\n\t\t\t.replace(/\\*/g, \".*\") // * → .*\n\t\t\t.replace(/\\?/g, \".\"); // ? → .\n\t\treturn new RegExp(`^${escaped}$`);\n\t}\n}\n","/**\n * Lightweight event emitter for loose coupling between modules.\n *\n * @example\n * ```ts\n * import { emitter } from \"buntok\";\n *\n * // Subscribe to events\n * emitter.on(\"user:created\", async ({ user, ctx }) => {\n *   await sendWelcomeEmail(user.email);\n * });\n *\n * // Emit events\n * emitter.emit(\"user:created\", { user, ctx });\n *\n * // One-time listener\n * emitter.once(\"app:ready\", () => {\n *   console.log(\"App is ready!\");\n * });\n * ```\n */\n\ntype EventMap = Record<string, any>;\n\ntype Listener<T> = (data: T) => Promise<void> | void;\n\nexport interface EmitOptions {\n\t/**\n\t * Isolate errors per listener. When true, a failing listener won't reject\n\t * the entire emit() call or affect other listeners.\n\t * Defaults to false for backward compatibility.\n\t */\n\tisolatedErrors?: boolean;\n\n\t/**\n\t * Custom error handler called when a listener throws.\n\t * Only used when `isolatedErrors` is true.\n\t */\n\tonError?: (event: string, error: unknown, listener: Listener<any>) => void;\n}\n\nexport interface EventEmitterOptions {\n\t/**\n\t * Maximum number of listeners per event.\n\t * Set to 0 or undefined for unlimited (default).\n\t * When exceeded, `on()` throws an error.\n\t */\n\tmaxListeners?: number;\n}\n\nexport class EventEmitter<TEvents extends EventMap = EventMap> {\n\tprivate listeners = new Map<keyof TEvents, Set<Listener<any>>>();\n\tprivate maxListeners: number;\n\n\tconstructor(options?: EventEmitterOptions) {\n\t\tthis.maxListeners = options?.maxListeners ?? 0;\n\t}\n\n\t/**\n\t * Subscribe to an event.\n\t * @returns Unsubscribe function\n\t */\n\ton<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): () => void {\n\t\tif (!this.listeners.has(event)) {\n\t\t\tthis.listeners.set(event, new Set());\n\t\t}\n\n\t\tconst eventListeners = this.listeners.get(event)!;\n\n\t\t// Check maxListeners limit\n\t\tif (this.maxListeners > 0 && eventListeners.size >= this.maxListeners) {\n\t\t\tthrow new Error(\n\t\t\t\t`Max listeners (${this.maxListeners}) exceeded for event \"${String(event)}\". ` +\n\t\t\t\t`Use increaseMaxListeners() to increase the limit.`,\n\t\t\t);\n\t\t}\n\n\t\teventListeners.add(listener);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tthis.listeners.get(event)?.delete(listener);\n\t\t};\n\t}\n\n\t/**\n\t * Subscribe to an event, but only fire once.\n\t * @returns Unsubscribe function\n\t */\n\tonce<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): () => void {\n\t\tconst wrapper: Listener<TEvents[K]> = async (data) => {\n\t\t\tunsub();\n\t\t\tawait listener(data);\n\t\t};\n\t\tconst unsub = this.on(event, wrapper);\n\t\treturn unsub;\n\t}\n\n\t/**\n\t * Emit an event with data.\n\t * Returns a promise that resolves when all listeners have finished.\n\t *\n\t * @example\n\t * // Default behavior - all listeners run in parallel, any error rejects\n\t * await emitter.emit(\"user:created\", { user });\n\t *\n\t * @example\n\t * // With error isolation - listeners run in parallel, errors don't affect others\n\t * await emitter.emit(\"user:created\", { user }, {\n\t *   isolatedErrors: true,\n\t *   onError: (event, error, listener) => {\n\t *     console.error(`Listener failed for ${event}:`, error);\n\t *   }\n\t * });\n\t */\n\tasync emit<K extends keyof TEvents>(\n\t\tevent: K,\n\t\tdata: TEvents[K],\n\t\toptions?: EmitOptions,\n\t): Promise<void> {\n\t\tconst listeners = this.listeners.get(event);\n\t\tif (!listeners || listeners.size === 0) return;\n\n\t\tconst promises: Promise<void>[] = [];\n\t\tfor (const listener of listeners) {\n\t\t\tpromises.push(this.invokeListener(event, listener, data, options));\n\t\t}\n\n\t\tif (options?.isolatedErrors) {\n\t\t\t// Use Promise.allSettled to isolate errors\n\t\t\tawait Promise.allSettled(promises);\n\t\t} else {\n\t\t\t// Default behavior - any error rejects\n\t\t\tawait Promise.all(promises);\n\t\t}\n\t}\n\n\t/**\n\t * Emit an event serially (one listener at a time).\n\t * Stops on first error unless `isolatedErrors` is true.\n\t *\n\t * @example\n\t * // Serial execution - stops on first error\n\t * await emitter.emitSerial(\"user:created\", { user });\n\t *\n\t * @example\n\t * // With error isolation - continues despite errors\n\t * await emitter.emitSerial(\"user:created\", { user }, {\n\t *   isolatedErrors: true,\n\t *   onError: (event, error) => console.error(error),\n\t * });\n\t */\n\tasync emitSerial<K extends keyof TEvents>(\n\t\tevent: K,\n\t\tdata: TEvents[K],\n\t\toptions?: EmitOptions,\n\t): Promise<void> {\n\t\tconst listeners = this.listeners.get(event);\n\t\tif (!listeners || listeners.size === 0) return;\n\n\t\tfor (const listener of listeners) {\n\t\t\tawait this.invokeListener(event, listener, data, options);\n\t\t}\n\t}\n\n\t/**\n\t * Remove all listeners for an event, or all listeners entirely.\n\t */\n\toff<K extends keyof TEvents>(event?: K): void {\n\t\tif (event) {\n\t\t\tthis.listeners.delete(event);\n\t\t} else {\n\t\t\tthis.listeners.clear();\n\t\t}\n\t}\n\n\t/**\n\t * Get the number of listeners for an event.\n\t */\n\tlistenerCount<K extends keyof TEvents>(event: K): number {\n\t\treturn this.listeners.get(event)?.size ?? 0;\n\t}\n\n\t/**\n\t * Get all event names that have listeners.\n\t */\n\teventNames(): (string | symbol)[] {\n\t\tconst keys = Array.from(this.listeners.keys());\n\t\tconst result: (string | symbol)[] = [];\n\t\tfor (const key of keys) {\n\t\t\tif (typeof key === \"string\" || typeof key === \"symbol\") {\n\t\t\t\tresult.push(key);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Increase the max listeners limit for an event.\n\t * Returns the EventEmitter for chaining.\n\t */\n\tincreaseMaxListeners(maxListeners: number): this {\n\t\tthis.maxListeners = maxListeners;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Get the current max listeners limit.\n\t */\n\tgetMaxListeners(): number {\n\t\treturn this.maxListeners;\n\t}\n\n\t/**\n\t * Invoke a single listener with error handling.\n\t */\n\tprivate async invokeListener<K extends keyof TEvents>(\n\t\tevent: K,\n\t\tlistener: Listener<TEvents[K]>,\n\t\tdata: TEvents[K],\n\t\toptions?: EmitOptions,\n\t): Promise<void> {\n\t\ttry {\n\t\t\tawait Promise.resolve(listener(data));\n\t\t} catch (error) {\n\t\t\tif (options?.isolatedErrors) {\n\t\t\t\toptions.onError?.(String(event), error, listener);\n\t\t\t} else {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Default emitter instance with common application events.\n *\n * @example\n * ```ts\n * import { emitter } from \"buntok\";\n *\n * emitter.on(\"user:created\", ({ user }) => {\n *   console.log(\"New user:\", user.name);\n * });\n * ```\n */\nexport interface AppEvents {\n\t// Auth events\n\t\"user:created\": { user: any; ctx?: any };\n\t\"user:updated\": { user: any; ctx?: any };\n\t\"user:deleted\": { userId: string | number; ctx?: any };\n\t\"user:logged_in\": { user: any; ctx?: any };\n\t\"user:logged_out\": { user: any; ctx?: any };\n\n\t// Request events\n\t\"request:start\": { method: string; path: string; ctx?: any };\n\t\"request:end\": { method: string; path: string; status: number; duration: number; ctx?: any };\n\t\"request:error\": { method: string; path: string; error: Error; ctx?: any };\n\n\t// App events\n\t\"app:ready\": void;\n\t\"app:shutdown\": void;\n\n\t// Custom events (extensible)\n\t[key: string]: any;\n}\n\nexport const emitter = new EventEmitter<AppEvents>();\n","/**\n * Async sleep - returns a promise that resolves after `ms` milliseconds.\n *\n * @example\n * await delay(1000); // wait 1 second\n */\nexport function delay(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport interface RetryOptions {\n\t/** Maximum number of retries (default: 3) */\n\tretries?: number;\n\t/** Delay between retries in ms (default: 1000) */\n\tdelay?: number;\n\t/** Backoff strategy: \"fixed\" or \"exponential\" (default: \"exponential\") */\n\tbackoff?: \"fixed\" | \"exponential\";\n\t/** Function to decide if the error is retryable. Default: always retry. */\n\tonError?: (error: unknown, attempt: number) => boolean;\n}\n\n/**\n * Retry an async function with configurable backoff.\n *\n * @example\n * const data = await retry(\n *   () => fetch(\"https://api.example.com/data\").then(r => r.json()),\n *   { retries: 3, delay: 1000, backoff: \"exponential\" }\n * );\n */\nexport async function retry<T>(\n\tfn: () => Promise<T>,\n\toptions?: RetryOptions,\n): Promise<T> {\n\tconst {\n\t\tretries = 3,\n\t\tdelay: baseDelay = 1000,\n\t\tbackoff = \"exponential\",\n\t\tonError,\n\t} = options ?? {};\n\n\tlet lastError: unknown;\n\n\tfor (let attempt = 0; attempt <= retries; attempt++) {\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} catch (err) {\n\t\t\tlastError = err;\n\n\t\t\tif (onError && !onError(err, attempt)) {\n\t\t\t\tthrow err;\n\t\t\t}\n\n\t\t\tif (attempt < retries) {\n\t\t\t\tconst waitTime =\n\t\t\t\t\tbackoff === \"exponential\" ? baseDelay * 2 ** attempt : baseDelay;\n\t\t\t\tawait delay(waitTime);\n\t\t\t}\n\t\t}\n\t}\n\n\tthrow lastError;\n}\n","const ENCODER = new TextEncoder();\nconst DECODER = new TextDecoder();\n\nfunction toBuffer(\n\tdata: string | ArrayBuffer | Uint8Array,\n): Uint8Array<ArrayBuffer> {\n\tif (typeof data === \"string\") return ENCODER.encode(data);\n\tif (data instanceof ArrayBuffer) return new Uint8Array(data);\n\treturn new Uint8Array(\n\t\tdata.buffer as ArrayBuffer,\n\t\tdata.byteOffset,\n\t\tdata.byteLength,\n\t);\n}\n\nfunction toHex(buffer: Uint8Array): string {\n\treturn [...buffer].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n// ── Hash ─────────────────────────────────────────────────────────────\n\nexport function hash(\n\tdata: string | ArrayBuffer | Uint8Array,\n\talgorithm: \"SHA-1\" | \"SHA-256\" | \"SHA-384\" | \"SHA-512\" = \"SHA-256\",\n): string {\n\tconst algo = algorithm.toLowerCase().replace(\"-\", \"\") as\n\t\t| \"sha1\"\n\t\t| \"sha256\"\n\t\t| \"sha384\"\n\t\t| \"sha512\";\n\tconst hasher = new Bun.CryptoHasher(algo);\n\thasher.update(toBuffer(data));\n\treturn hasher.digest(\"hex\");\n}\n\nexport function sha256(data: string | ArrayBuffer | Uint8Array): string {\n\treturn hash(data, \"SHA-256\");\n}\n\nexport function sha512(data: string | ArrayBuffer | Uint8Array): string {\n\treturn hash(data, \"SHA-512\");\n}\n\n/**\n * MD5 hash - uses a pure JS implementation since WebCrypto doesn't support MD5.\n * Intended for legacy compatibility and cache keys, NOT for security.\n */\nexport async function md5(\n\tdata: string | ArrayBuffer | Uint8Array,\n): Promise<string> {\n\tconst buf = toBuffer(data);\n\tconst T = [\n\t\t0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,\n\t\t0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,\n\t\t0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,\n\t\t0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,\n\t\t0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,\n\t\t0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,\n\t\t0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,\n\t\t0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,\n\t\t0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,\n\t\t0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,\n\t\t0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,\n\t];\n\tconst S = [\n\t\t7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5,\n\t\t9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11,\n\t\t16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10,\n\t\t15, 21,\n\t];\n\n\tconst msg = new Uint8Array((((buf.length + 8) >>> 6) + 1) << 6);\n\tmsg.set(buf);\n\tmsg[buf.length] = 0x80;\n\tconst msgBuffer = msg.buffer as ArrayBuffer;\n\tconst view = new DataView(msgBuffer);\n\tview.setUint32(msg.length - 8, buf.length * 8, true);\n\tview.setUint32(msg.length - 4, 0, true);\n\n\tlet [a0, b0, c0, d0] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476];\n\n\tfor (let i = 0; i < msg.length; i += 64) {\n\t\tconst M = new Array<number>(16).fill(0);\n\t\tfor (let j = 0; j < 16; j++) M[j] = view.getUint32(i + j * 4, true);\n\n\t\tlet [A, B, C, D] = [a0, b0, c0, d0];\n\t\tlet g = 0;\n\n\t\tfor (let j = 0; j < 64; j++) {\n\t\t\tlet F: number;\n\t\t\tif (j < 16) {\n\t\t\t\tF = (B & C) | (~B & D);\n\t\t\t\tg = j;\n\t\t\t} else if (j < 32) {\n\t\t\t\tF = (D & B) | (~D & C);\n\t\t\t\tg = (5 * j + 1) % 16;\n\t\t\t} else if (j < 48) {\n\t\t\t\tF = B ^ C ^ D;\n\t\t\t\tg = (3 * j + 5) % 16;\n\t\t\t} else {\n\t\t\t\tF = C ^ (B | ~D);\n\t\t\t\tg = (7 * j) % 16;\n\t\t\t}\n\t\t\tF = (F + A + T[j]! + M[g]!) | 0;\n\t\t\tA = D;\n\t\t\tD = C;\n\t\t\tC = B;\n\t\t\tB = (B + ((F << S[j]!) | (F >>> (32 - S[j]!)))) | 0;\n\t\t}\n\n\t\ta0 = (a0 + A) | 0;\n\t\tb0 = (b0 + B) | 0;\n\t\tc0 = (c0 + C) | 0;\n\t\td0 = (d0 + D) | 0;\n\t}\n\n\tconst result = new Uint8Array(16);\n\tconst rView = new DataView(result.buffer as ArrayBuffer);\n\trView.setUint32(0, a0, true);\n\trView.setUint32(4, b0, true);\n\trView.setUint32(8, c0, true);\n\trView.setUint32(12, d0, true);\n\treturn toHex(result);\n}\n\n// ── HMAC ─────────────────────────────────────────────────────────────\n\nexport async function hmac(\n\tdata: string | ArrayBuffer | Uint8Array,\n\tkey: string | ArrayBuffer | Uint8Array,\n\talgorithm: \"SHA-1\" | \"SHA-256\" | \"SHA-384\" | \"SHA-512\" = \"SHA-256\",\n): Promise<string> {\n\tconst cryptoKey = await crypto.subtle.importKey(\n\t\t\"raw\",\n\t\ttoBuffer(key),\n\t\t{ name: \"HMAC\", hash: algorithm },\n\t\tfalse,\n\t\t[\"sign\"],\n\t);\n\tconst signature = await crypto.subtle.sign(\"HMAC\", cryptoKey, toBuffer(data));\n\treturn toHex(new Uint8Array(signature));\n}\n\nexport async function hashVerify(\n\tdata: string | ArrayBuffer | Uint8Array,\n\texpected: string,\n\talgorithm: \"SHA-1\" | \"SHA-256\" | \"SHA-384\" | \"SHA-512\" = \"SHA-256\",\n): Promise<boolean> {\n\tconst actual = hash(data, algorithm);\n\tif (actual.length !== expected.length) return false;\n\tlet result = 0;\n\tfor (let i = 0; i < actual.length; i++) {\n\t\tresult |= actual.charCodeAt(i) ^ expected.charCodeAt(i);\n\t}\n\treturn result === 0;\n}\n\n// ── Random ───────────────────────────────────────────────────────────\n\nexport function randomBytes(length: number): Uint8Array {\n\treturn crypto.getRandomValues(new Uint8Array(length));\n}\n\nexport function randomHex(length: number): string {\n\treturn toHex(randomBytes(Math.ceil(length / 2))).slice(0, length);\n}\n\nconst ALPHA_NUM =\n\t\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\nexport function randomAlphaNumeric(length: number): string {\n\tconst bytes = randomBytes(length);\n\treturn Array.from(bytes, (b) => ALPHA_NUM[b % ALPHA_NUM.length]).join(\"\");\n}\n\nexport function randomToken(length = 32): string {\n\tconst bytes = randomBytes(length);\n\treturn btoa(String.fromCharCode(...bytes))\n\t\t.replace(/\\+/g, \"-\")\n\t\t.replace(/\\//g, \"_\")\n\t\t.replace(/=+$/, \"\");\n}\n\n// ── Encrypt / Decrypt (AES-256-GCM) ─────────────────────────────────\n\nasync function importAesKey(\n\tkey: string | ArrayBuffer | Uint8Array,\n): Promise<CryptoKey> {\n\tconst keyData = typeof key === \"string\" ? ENCODER.encode(key) : toBuffer(key);\n\tconst rawKey =\n\t\tkeyData.length === 32\n\t\t\t? keyData\n\t\t\t: new Uint8Array(await crypto.subtle.digest(\"SHA-256\", keyData));\n\treturn crypto.subtle.importKey(\"raw\", rawKey, \"AES-GCM\", false, [\n\t\t\"encrypt\",\n\t\t\"decrypt\",\n\t]);\n}\n\nexport async function encrypt(\n\tdata: string | ArrayBuffer | Uint8Array,\n\tkey: string | ArrayBuffer | Uint8Array,\n\tiv?: Uint8Array,\n): Promise<{ ciphertext: string; iv: string }> {\n\tconst cryptoKey = await importAesKey(key);\n\tconst ivBytes = (iv ??\n\t\tcrypto.getRandomValues(new Uint8Array(12))) as Uint8Array<ArrayBuffer>;\n\tconst encrypted = await crypto.subtle.encrypt(\n\t\t{ name: \"AES-GCM\", iv: ivBytes },\n\t\tcryptoKey,\n\t\ttoBuffer(data),\n\t);\n\treturn {\n\t\tciphertext: toHex(new Uint8Array(encrypted)),\n\t\tiv: toHex(ivBytes),\n\t};\n}\n\nexport async function decrypt(\n\tciphertext: string,\n\tkey: string | ArrayBuffer | Uint8Array,\n\tiv: string,\n): Promise<string> {\n\tconst cryptoKey = await importAesKey(key);\n\tconst ivBytes = new Uint8Array(\n\t\tiv.match(/.{1,2}/g)?.map((h) => Number.parseInt(h, 16)) ?? [],\n\t);\n\tconst data = new Uint8Array(\n\t\tciphertext.match(/.{1,2}/g)?.map((h) => Number.parseInt(h, 16)) ?? [],\n\t);\n\tconst decrypted = await crypto.subtle.decrypt(\n\t\t{ name: \"AES-GCM\", iv: ivBytes },\n\t\tcryptoKey,\n\t\tdata,\n\t);\n\treturn DECODER.decode(decrypted);\n}\n","const UNITS: [string, number][] = [\n\t[\"year\", 31536000],\n\t[\"month\", 2628000],\n\t[\"week\", 604800],\n\t[\"day\", 86400],\n\t[\"hour\", 3600],\n\t[\"minute\", 60],\n\t[\"second\", 1],\n];\n\nfunction pluralize(unit: string, value: number): string {\n\treturn value === 1 ? unit : `${unit}s`;\n}\n\nfunction toTemporal(date: Date | string | number): Temporal.Instant {\n\tif (date instanceof Date) {\n\t\treturn Temporal.Instant.fromEpochMilliseconds(date.getTime());\n\t}\n\tif (typeof date === \"number\") {\n\t\treturn Temporal.Instant.fromEpochMilliseconds(date);\n\t}\n\treturn Temporal.Instant.from(date);\n}\n\n/**\n * Format a Date to ISO string or custom format.\n *\n * @example\n * formatDate(new Date()); // \"2024-01-15T10:30:00.000Z\"\n */\nexport function formatDate(date: Date | string | number): string {\n\treturn toTemporal(date).toString();\n}\n\n/**\n * Get human-readable relative time (\"3 minutes ago\", \"2 hours ago\").\n *\n * @example\n * timeAgo(new Date(Date.now() - 180000)); // \"3 minutes ago\"\n * timeAgo(new Date(Date.now() - 7200000)); // \"2 hours ago\"\n */\nexport function timeAgo(date: Date | string | number): string {\n\tconst d = date instanceof Date ? date : new Date(date);\n\tconst seconds = Math.floor((Date.now() - d.getTime()) / 1000);\n\n\tfor (const [unit, secs] of UNITS) {\n\t\tconst value = Math.floor(seconds / secs);\n\t\tif (value >= 1) {\n\t\t\treturn `${value} ${pluralize(unit, value)} ago`;\n\t\t}\n\t}\n\n\treturn \"just now\";\n}\n\n/**\n * Calculate the number of whole days between two dates.\n *\n * @example\n * daysBetween(new Date(\"2024-01-01\"), new Date(\"2024-01-15\")); // 14\n */\nexport function daysBetween(\n\tdate1: Date | string | number,\n\tdate2: Date | string | number,\n): number {\n\tconst ms1 = toTemporal(date1).epochMilliseconds;\n\tconst ms2 = toTemporal(date2).epochMilliseconds;\n\treturn Math.round((ms2 - ms1) / 86400000);\n}\n\n/**\n * Add days to a date and return a new Date.\n *\n * @example\n * addDays(new Date(\"2024-01-01\"), 30); // Date(\"2024-01-31\")\n */\nexport function addDays(\n\tdate: Date | string | number,\n\tdays: number,\n): Date {\n\tconst d = date instanceof Date ? date : new Date(date);\n\tconst result = new Date(d);\n\tresult.setDate(result.getDate() + days);\n\treturn result;\n}\n\n/**\n * Check if date1 is before date2.\n *\n * @example\n * isBefore(new Date(\"2024-01-01\"), new Date(\"2024-01-15\")); // true\n */\nexport function isBefore(\n\tdate1: Date | string | number,\n\tdate2: Date | string | number,\n): boolean {\n\treturn toTemporal(date1).epochMilliseconds < toTemporal(date2).epochMilliseconds;\n}\n\n/**\n * Check if date1 is after date2.\n *\n * @example\n * isAfter(new Date(\"2024-01-15\"), new Date(\"2024-01-01\")); // true\n */\nexport function isAfter(\n\tdate1: Date | string | number,\n\tdate2: Date | string | number,\n): boolean {\n\treturn toTemporal(date1).epochMilliseconds > toTemporal(date2).epochMilliseconds;\n}\n\n/**\n * Get the start of day (00:00:00) for a given date.\n *\n * @example\n * startOfDay(new Date(\"2024-01-15T14:30:00\")); // Date(\"2024-01-15T00:00:00\")\n */\nexport function startOfDay(date: Date | string | number): Date {\n\tconst d = date instanceof Date ? new Date(date) : new Date(date);\n\td.setHours(0, 0, 0, 0);\n\treturn d;\n}\n\n/**\n * Get the end of day (23:59:59.999) for a given date.\n *\n * @example\n * endOfDay(new Date(\"2024-01-15T14:30:00\")); // Date(\"2024-01-15T23:59:59.999\")\n */\nexport function endOfDay(date: Date | string | number): Date {\n\tconst d = date instanceof Date ? new Date(date) : new Date(date);\n\td.setHours(23, 59, 59, 999);\n\treturn d;\n}\n\n/**\n * Format a duration in seconds to human-readable string (\"2h 30m 15s\").\n *\n * @example\n * formatDuration(9015);  // \"2h 30m 15s\"\n * formatDuration(65);    // \"1m 5s\"\n * formatDuration(30);    // \"30s\"\n */\nexport function formatDuration(seconds: number): string {\n\tconst h = Math.floor(seconds / 3600);\n\tconst m = Math.floor((seconds % 3600) / 60);\n\tconst s = Math.floor(seconds % 60);\n\n\tconst parts: string[] = [];\n\tif (h > 0) parts.push(`${h}h`);\n\tif (m > 0) parts.push(`${m}m`);\n\tif (s > 0 || parts.length === 0) parts.push(`${s}s`);\n\n\treturn parts.join(\" \");\n}\n","/**\n * Timezone helper utilities for handling time conversions between server and client.\n *\n * Common use case:\n * - Server stores times in ISO +7 (Asia/Jakarta)\n * - Dashboard needs to display/group data by client's local timezone\n */\n\nfunction toDate(date: Date | string | number): Date {\n\treturn date instanceof Date ? date : new Date(date);\n}\n\n/**\n * Get the timezone offset in minutes for a given IANA timezone.\n *\n * @example\n * getTimezoneOffset(\"Asia/Jakarta\"); // -420 (UTC+7)\n * getTimezoneOffset(\"America/New_York\"); // varies (DST aware)\n */\nexport function getTimezoneOffset(timezone: string, date?: Date): number {\n\tconst d = date ?? new Date();\n\tconst utcStr = d.toLocaleString(\"en-US\", { timeZone: \"UTC\" });\n\tconst tzStr = d.toLocaleString(\"en-US\", { timeZone: timezone });\n\tconst utc = new Date(utcStr);\n\tconst tz = new Date(tzStr);\n\treturn (utc.getTime() - tz.getTime()) / 60000;\n}\n\n/**\n * Parse a time string and interpret it in a specific timezone.\n *\n * If the string has no timezone info (no Z, no +07:00), it will be\n * interpreted as being in the specified timezone.\n *\n * @example\n * // Server receives \"2026-08-24 05:00\" from client in UTC+7\n * const date = parseTime(\"2026-08-24 05:00\", \"Asia/Jakarta\");\n * date.toISOString(); // \"2026-08-23T22:00:00.000Z\" (correct UTC)\n */\nexport function parseTime(timeStr: string, timezone: string): Date {\n\t// If already has timezone info (Z or ±HH:MM), use native parsing\n\tif (/[Zz]$|[+-]\\d{2}:\\d{2}$/.test(timeStr.trim())) {\n\t\treturn new Date(timeStr);\n\t}\n\n\t// Parse as local time in target timezone\n\tconst d = new Date(timeStr);\n\tif (Number.isNaN(d.getTime())) {\n\t\tthrow new Error(`Invalid date string: \"${timeStr}\"`);\n\t}\n\n\t// Get what this date looks like in the target timezone\n\tconst offset = getTimezoneOffset(timezone, d);\n\tconst utcOffset = d.getTimezoneOffset(); // local offset in minutes (negative for east)\n\n\t// Adjust: move from local interpretation to target timezone\n\tconst adjusted = new Date(d.getTime() + (utcOffset + offset) * 60000);\n\treturn adjusted;\n}\n\n/**\n * Convert a Date to a specific timezone and return parts.\n *\n * @example\n * const parts = toTimezoneParts(new Date(\"2026-08-23T22:00:00Z\"), \"Asia/Jakarta\");\n * // { year: 2026, month: 8, day: 24, hour: 5, minute: 0, second: 0 }\n */\nexport function toTimezoneParts(date: Date, timezone: string) {\n\tconst d = toDate(date);\n\tconst parts = new Intl.DateTimeFormat(\"en-US\", {\n\t\ttimeZone: timezone,\n\t\tyear: \"numeric\",\n\t\tmonth: \"2-digit\",\n\t\tday: \"2-digit\",\n\t\thour: \"2-digit\",\n\t\tminute: \"2-digit\",\n\t\tsecond: \"2-digit\",\n\t\thour12: false,\n\t}).formatToParts(d);\n\n\tconst get = (type: string) => Number(parts.find((p) => p.type === type)?.value ?? 0);\n\n\treturn {\n\t\tyear: get(\"year\"),\n\t\tmonth: get(\"month\"),\n\t\tday: get(\"day\"),\n\t\thour: get(\"hour\"),\n\t\tminute: get(\"minute\"),\n\t\tsecond: get(\"second\"),\n\t};\n}\n\n/**\n * Format a Date in a specific timezone.\n *\n * @example\n * const date = new Date(\"2026-08-23T22:00:00Z\");\n * formatInTimezone(date, \"Asia/Jakarta\"); // \"2026-08-24 05:00:00\"\n * formatInTimezone(date, \"Asia/Jakarta\", \"short\"); // \"2026-08-24 05:00\"\n * formatInTimezone(date, \"Asia/Jakarta\", \"full\"); // \"2026-08-24 05:00:00.000\"\n */\nexport function formatInTimezone(\n\tdate: Date | string | number,\n\ttimezone: string,\n\tformat: \"short\" | \"default\" | \"full\" = \"default\",\n): string {\n\tconst d = toDate(date);\n\tconst parts = toTimezoneParts(d, timezone);\n\n\tconst pad = (n: number) => String(n).padStart(2, \"0\");\n\tconst y = parts.year;\n\tconst m = pad(parts.month);\n\tconst day = pad(parts.day);\n\tconst h = pad(parts.hour);\n\tconst min = pad(parts.minute);\n\tconst sec = pad(parts.second);\n\n\tswitch (format) {\n\t\tcase \"short\":\n\t\t\treturn `${y}-${m}-${day} ${h}:${min}`;\n\t\tcase \"full\":\n\t\t\treturn `${y}-${m}-${day} ${h}:${min}:${sec}.000`;\n\t\tdefault:\n\t\t\treturn `${y}-${m}-${day} ${h}:${min}:${sec}`;\n\t}\n}\n\n/**\n * Get current time in a specific timezone.\n *\n * @example\n * const now = nowInTimezone(\"Asia/Jakarta\");\n * // Date object representing current time, displayable in Jakarta timezone\n */\nexport function nowInTimezone(timezone: string): Date {\n\tconst now = new Date();\n\tconst parts = toTimezoneParts(now, timezone);\n\tconst reconstructed = new Date(\n\t\tDate.UTC(parts.year, parts.month - 1, parts.day, parts.hour, parts.minute, parts.second),\n\t);\n\tconst tzOffset = getTimezoneOffset(timezone, now);\n\treturn new Date(reconstructed.getTime() + tzOffset * 60000);\n}\n\n/**\n * Get the timezone offset string (e.g., \"+07:00\", \"-05:00\") for a timezone.\n *\n * @example\n * getTimezoneOffsetString(\"Asia/Jakarta\"); // \"+07:00\"\n * getTimezoneOffsetString(\"America/New_York\"); // \"-04:00\" or \"-05:00\" (DST)\n */\nexport function getTimezoneOffsetString(timezone: string, date?: Date): string {\n\tconst offset = getTimezoneOffset(timezone, date);\n\tconst sign = offset <= 0 ? \"+\" : \"-\";\n\tconst absOffset = Math.abs(offset);\n\tconst hours = Math.floor(absOffset / 60);\n\tconst minutes = absOffset % 60;\n\treturn `${sign}${String(hours).padStart(2, \"0\")}:${String(minutes).padStart(2, \"0\")}`;\n}\n\n/**\n * Convert a Date to ISO string with a specific timezone offset.\n *\n * @example\n * const date = new Date(\"2026-08-23T22:00:00Z\");\n * toISOWithTimezone(date, \"Asia/Jakarta\");\n * // \"2026-08-24T05:00:00+07:00\"\n */\nexport function toISOWithTimezone(date: Date | string | number, timezone: string): string {\n\tconst d = toDate(date);\n\tconst parts = toTimezoneParts(d, timezone);\n\tconst offset = getTimezoneOffsetString(timezone, d);\n\n\tconst pad = (n: number) => String(n).padStart(2, \"0\");\n\treturn `${parts.year}-${pad(parts.month)}-${pad(parts.day)}T${pad(parts.hour)}:${pad(parts.minute)}:${pad(parts.second)}${offset}`;\n}\n\nexport type GroupByKey = \"hour\" | \"day\" | \"month\" | \"year\";\n\nexport interface GroupByTimezoneOptions {\n\tlocale?: string;\n\tlabelFormatter?: (key: string, groupBy: GroupByKey) => string;\n}\n\nfunction defaultLabelFormatter(key: string, groupBy: GroupByKey, locale: string): string {\n\t// If key looks like a date (YYYY-MM-DD)\n\tif (/^\\d{4}-\\d{2}-\\d{2}$/.test(key)) {\n\t\tconst [y, m, d] = key.split(\"-\").map(Number) as [number, number, number];\n\t\tconst date = new Date(y, m - 1, d);\n\t\treturn new Intl.DateTimeFormat(locale, {\n\t\t\tweekday: \"long\",\n\t\t\tyear: \"numeric\",\n\t\t\tmonth: \"long\",\n\t\t\tday: \"numeric\",\n\t\t}).format(date);\n\t}\n\n\t// If key looks like YYYY-MM\n\tif (/^\\d{4}-\\d{2}$/.test(key)) {\n\t\tconst [y, m] = key.split(\"-\").map(Number) as [number, number];\n\t\tconst date = new Date(y, m - 1, 1);\n\t\treturn new Intl.DateTimeFormat(locale, {\n\t\t\tyear: \"numeric\",\n\t\t\tmonth: \"long\",\n\t\t}).format(date);\n\t}\n\n\t// If key is just a year\n\tif (/^\\d{4}$/.test(key)) {\n\t\treturn key;\n\t}\n\n\t// If key is hour (00-23)\n\tif (/^\\d{2}$/.test(key)) {\n\t\tconst hour = Number(key);\n\t\tconst date = new Date(2000, 0, 1, hour);\n\t\treturn new Intl.DateTimeFormat(locale, {\n\t\t\thour: \"numeric\",\n\t\t\thour12: false,\n\t\t}).format(date);\n\t}\n\n\treturn key;\n}\n\n/**\n * Format a group key into a human-readable label.\n *\n * @example\n * formatGroupLabel(\"2026-08-24\", \"day\", \"id\");\n * // \"Rabu, 24 Agustus 2026\"\n *\n * formatGroupLabel(\"2026-08-24\", \"day\", \"en\");\n * // \"Wednesday, August 24, 2026\"\n *\n * formatGroupLabel(\"05\", \"hour\", \"id\");\n * // \"05.00\"\n */\nexport function formatGroupLabel(\n\tkey: string,\n\tgroupBy: GroupByKey,\n\tlocale = \"en-US\",\n): string {\n\treturn defaultLabelFormatter(key, groupBy, locale);\n}\n\n/**\n * Group items by their date value in a specific timezone.\n *\n * @example\n * const transactions = [\n *   { id: 1, createdAt: \"2026-08-24T05:00:00+07:00\", amount: 100 },\n *   { id: 2, createdAt: \"2026-08-24T08:30:00+07:00\", amount: 200 },\n *   { id: 3, createdAt: \"2026-08-24T14:00:00+07:00\", amount: 150 },\n * ];\n *\n * // Group by hour in Jakarta timezone\n * const hourly = groupByTimezone(transactions, \"createdAt\", \"Asia/Jakarta\", \"hour\");\n * // Map {\n * //   \"05\" => [{ id: 1, ... }],\n * //   \"08\" => [{ id: 2, ... }],\n * //   \"14\" => [{ id: 3, ... }],\n * // }\n *\n * // Group by day\n * const daily = groupByTimezone(transactions, \"createdAt\", \"Asia/Jakarta\", \"day\");\n * // Map {\n * //   \"2026-08-24\" => [all 3 transactions],\n * // }\n *\n * // With human-readable labels\n * const dailyWithLabels = groupByTimezone(\n *   transactions, \"createdAt\", \"Asia/Jakarta\", \"day\",\n *   { locale: \"id\" }\n * );\n * // Labels: \"Rabu, 24 Agustus 2026\"\n */\nexport function groupByTimezone<T>(\n\titems: T[],\n\tdateField: keyof T,\n\ttimezone: string,\n\tgroupBy: GroupByKey = \"day\",\n\toptions?: GroupByTimezoneOptions,\n): Map<string, T[]> {\n\tconst groups = new Map<string, T[]>();\n\tconst locale = options?.locale ?? \"en-US\";\n\n\tfor (const item of items) {\n\t\tconst dateVal = item[dateField];\n\t\tif (!dateVal) continue;\n\n\t\tconst d = toDate(dateVal as Date | string | number);\n\t\tconst parts = toTimezoneParts(d, timezone);\n\t\tconst pad = (n: number) => String(n).padStart(2, \"0\");\n\n\t\tlet key: string;\n\t\tswitch (groupBy) {\n\t\t\tcase \"hour\":\n\t\t\t\tkey = `${pad(parts.hour)}`;\n\t\t\t\tbreak;\n\t\t\tcase \"month\":\n\t\t\t\tkey = `${parts.year}-${pad(parts.month)}`;\n\t\t\t\tbreak;\n\t\t\tcase \"year\":\n\t\t\t\tkey = `${parts.year}`;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tkey = `${parts.year}-${pad(parts.month)}-${pad(parts.day)}`;\n\t\t}\n\n\t\tconst group = groups.get(key) ?? [];\n\t\tgroup.push(item);\n\t\tgroups.set(key, group);\n\t}\n\n\treturn groups;\n}\n\n/**\n * Get labels for groupByTimezone keys.\n *\n * @example\n * const hourly = groupByTimezone(transactions, \"createdAt\", \"Asia/Jakarta\", \"hour\");\n * const labels = getGroupLabels(hourly, \"hour\", \"id\");\n * // Map { \"05\" => \"05.00\", \"08\" => \"08.00\", ... }\n *\n * const daily = groupByTimezone(transactions, \"createdAt\", \"Asia/Jakarta\", \"day\");\n * const labels = getGroupLabels(daily, \"day\", \"id\");\n * // Map { \"2026-08-24\" => \"Rabu, 24 Agustus 2026\", ... }\n */\nexport function getGroupLabels(\n\tgroups: Map<string, unknown[]>,\n\tgroupBy: GroupByKey,\n\tlocale = \"en-US\",\n): Map<string, string> {\n\tconst labels = new Map<string, string>();\n\tfor (const key of groups.keys()) {\n\t\tlabels.set(key, formatGroupLabel(key, groupBy, locale));\n\t}\n\treturn labels;\n}\n\n/**\n * Check if a timezone string is valid.\n *\n * @example\n * isValidTimezone(\"Asia/Jakarta\"); // true\n * isValidTimezone(\"Invalid/Zone\"); // false\n */\nexport function isValidTimezone(timezone: string): boolean {\n\ttry {\n\t\tnew Intl.DateTimeFormat(\"en-US\", { timeZone: timezone });\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n","const _ALPHANUMERIC =\n\t\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst urlAlphabet =\n\t\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n\n/**\n * Generate a sequential code with prefix and auto-incrementing counter.\n *\n * @example\n * generateCode(\"T\");      // \"T0001\"\n * generateCode(\"T\");      // \"T0002\"\n * generateCode(\"INV\");    // \"INV0001\"\n * generateCode(\"ORD\", 42); // \"ORD0042\"\n */\nexport function generateCode(prefix: string, counter?: number): string {\n\tif (counter === undefined) {\n\t\t// Use module-level counter per prefix\n\t\tconst current = counters.get(prefix) ?? 0;\n\t\tcounter = current + 1;\n\t\tcounters.set(prefix, counter);\n\t}\n\treturn `${prefix}${counter.toString().padStart(4, \"0\")}`;\n}\n\nconst counters = new Map<string, number>();\n\n/**\n * Reset the auto-increment counter for a prefix.\n *\n * @example\n * resetCounter(\"T\"); // next generateCode(\"T\") will be \"T0001\"\n */\nexport function resetCounter(prefix: string): void {\n\tcounters.delete(prefix);\n}\n\n/**\n * Generate a URL-safe unique ID (nanoid-style).\n *\n * @example\n * nanoid();     // \"V1StGXR8_Z5jdHi6B-myT\"  (21 chars)\n * nanoid(10);   // \"V1StGXR8_Z5\"             (10 chars)\n */\nexport function nanoid(size = 21): string {\n\tconst bytes = crypto.getRandomValues(new Uint8Array(size));\n\treturn Array.from(bytes, (b) => urlAlphabet[b % 64]).join(\"\");\n}\n\n/**\n * Generate a ULID (Time-Ordered Unique Identifier).\n * Format: 26 chars, sortable by creation time.\n *\n * @example\n * ulid(); // \"01ARZ3NDEKTSV4RRFFQ69G5FAV\"\n */\nexport function ulid(): string {\n\tconst time = Date.now();\n\tconst timeStr = encodeTime(time, 10);\n\tconst randomStr = encodeRandom(16);\n\treturn timeStr + randomStr;\n}\n\nconst ENCODING = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\nfunction encodeTime(time: number, length: number): string {\n\tlet result = \"\";\n\tfor (let i = length - 1; i >= 0; i--) {\n\t\tresult = ENCODING[time % 32] + result;\n\t\ttime = Math.floor(time / 32);\n\t}\n\treturn result;\n}\n\nfunction encodeRandom(length: number): string {\n\tconst bytes = crypto.getRandomValues(new Uint8Array(length));\n\treturn Array.from(bytes, (b) => ENCODING[b % 32]).join(\"\");\n}\n","const PRIVATE_IP_REGEX =\n\t/^(10\\.|172\\.(1[6-9]|2\\d|3[01])\\.|192\\.168\\.|127\\.|0\\.|localhost|::1|fc|fd)/i;\n\n/**\n * Get the client IP address from a Request.\n * Checks X-Forwarded-For, X-Real-IP, then falls back to request.remoteAddress.\n */\nexport function getClientIP(request: Request): string {\n\tconst xff = request.headers.get(\"x-forwarded-for\");\n\tif (xff) {\n\t\tconst first = xff.split(\",\")[0]?.trim();\n\t\tif (first) return first;\n\t}\n\n\tconst xri = request.headers.get(\"x-real-ip\");\n\tif (xri) return xri;\n\n\t// Bun exposes remoteAddress on the request\n\t// biome-ignore lint/suspicious/noExplicitAny: Bun-specific property\n\tconst remote = (request as any).remoteAddress;\n\tif (remote) return remote;\n\n\treturn \"unknown\";\n}\n\n/**\n * Check if an IP address is a private/reserved address.\n */\nexport function isPrivateIP(ip: string): boolean {\n\treturn PRIVATE_IP_REGEX.test(ip);\n}\n\ninterface UserAgentInfo {\n\tbrowser: string;\n\tos: string;\n\tdevice: string;\n}\n\nconst BROWSER_PATTERNS: [RegExp, string][] = [\n\t[/opr\\//i, \"Opera\"],\n\t[/edg/i, \"Edge\"],\n\t[/chrome/i, \"Chrome\"],\n\t[/firefox/i, \"Firefox\"],\n\t[/safari/i, \"Safari\"],\n\t[/msie|trident/i, \"IE\"],\n];\n\nconst OS_PATTERNS: [RegExp, string][] = [\n\t[/windows/i, \"Windows\"],\n\t[/mac os/i, \"macOS\"],\n\t[/linux/i, \"Linux\"],\n\t[/android/i, \"Android\"],\n\t[/iphone|ipad|ipod/i, \"iOS\"],\n\t[/cros/i, \"Chrome OS\"],\n\t[/winphone/i, \"Windows Phone\"],\n];\n\nconst DEVICE_PATTERNS: [RegExp, string][] = [\n\t[/mobile|android.*mobile|iphone/i, \"Mobile\"],\n\t[/ipad|tablet|android(?!.*mobile)/i, \"Tablet\"],\n];\n\n/**\n * Parse the User-Agent header into a simple `{ browser, os, device }` object.\n */\nexport function parseUserAgent(request: Request): UserAgentInfo {\n\tconst ua = request.headers.get(\"user-agent\") ?? \"\";\n\n\tlet browser = \"Other\";\n\tfor (const [pattern, name] of BROWSER_PATTERNS) {\n\t\tif (pattern.test(ua)) {\n\t\t\tbrowser = name;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet os = \"Other\";\n\tfor (const [pattern, name] of OS_PATTERNS) {\n\t\tif (pattern.test(ua)) {\n\t\t\tos = name;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet device = \"Desktop\";\n\tfor (const [pattern, name] of DEVICE_PATTERNS) {\n\t\tif (pattern.test(ua)) {\n\t\t\tdevice = name;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn { browser, os, device };\n}\n","/**\n * Clamp a number between min and max (inclusive).\n *\n * @example\n * clamp(15, 0, 10);  // 10\n * clamp(-5, 0, 10);  // 0\n * clamp(5, 0, 10);   // 5\n */\nexport function clamp(value: number, min: number, max: number): number {\n\treturn Math.min(Math.max(value, min), max);\n}\n\n/**\n * Random integer between min and max (inclusive).\n *\n * @example\n * random(1, 100); // 42\n */\nexport function random(min: number, max: number): number {\n\treturn Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\n/**\n * Random float between min and max.\n *\n * @example\n * randomFloat(1.5, 3.5); // 2.731\n */\nexport function randomFloat(min: number, max: number): number {\n\treturn Math.random() * (max - min) + min;\n}\n\n/**\n * Format a number with locale-aware separators.\n *\n * @example\n * formatNumber(1000000);       // \"1,000,000\"\n * formatNumber(1000000, \"de\"); // \"1.000.000\"\n */\nexport function formatNumber(n: number, locale = \"en-US\"): string {\n\treturn n.toLocaleString(locale);\n}\n\n/**\n * Format bytes to human-readable string.\n *\n * @example\n * formatBytes(0);          // \"0 B\"\n * formatBytes(1024);       // \"1 KB\"\n * formatBytes(1536);       // \"1.5 KB\"\n * formatBytes(1048576);    // \"1 MB\"\n */\nexport function formatBytes(bytes: number): string {\n\tif (bytes === 0) return \"0 B\";\n\tconst units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"];\n\tconst i = Math.floor(Math.log(bytes) / Math.log(1024));\n\tconst size = bytes / 1024 ** i;\n\treturn `${size === 0 ? \"0\" : size.toFixed(size >= 100 ? 0 : size >= 10 ? 1 : 2)} ${units[i]}`;\n}\n\n/**\n * Format a number as currency.\n *\n * @example\n * formatCurrency(1000);          // \"$1,000.00\"\n * formatCurrency(1000, \"EUR\");   // \"€1,000.00\"\n * formatCurrency(1000, \"IDR\", \"id-ID\"); // \"Rp1.000\"\n */\nexport function formatCurrency(\n\tamount: number,\n\tcurrency = \"USD\",\n\tlocale = \"en-US\",\n): string {\n\treturn amount.toLocaleString(locale, {\n\t\tstyle: \"currency\",\n\t\tcurrency,\n\t});\n}\n","/**\n * Pick specified keys from an object.\n * `pick({ a: 1, b: 2, c: 3 }, [\"a\", \"c\"])` → `{ a: 1, c: 3 }`\n */\nexport function pick<T extends Record<string, unknown>, K extends keyof T>(\n\tobj: T,\n\tkeys: K[],\n): Pick<T, K> {\n\tconst result = {} as Pick<T, K>;\n\tfor (const key of keys) {\n\t\tif (key in obj) result[key] = obj[key];\n\t}\n\treturn result;\n}\n\n/**\n * Omit specified keys from an object.\n * `omit({ a: 1, b: 2, c: 3 }, [\"b\"])` → `{ a: 1, c: 3 }`\n */\nexport function omit<T extends Record<string, unknown>, K extends keyof T>(\n\tobj: T,\n\tkeys: K[],\n): Omit<T, K> {\n\tconst result = { ...obj };\n\tfor (const key of keys) {\n\t\tdelete result[key];\n\t}\n\treturn result as Omit<T, K>;\n}\n\n/**\n * Group an array of objects by a key or field function.\n * `groupBy([{ type: \"a\" }, { type: \"b\" }, { type: \"a\" }], \"type\")`\n * → `{ a: [{ type: \"a\" }, { type: \"a\" }], b: [{ type: \"b\" }] }`\n */\nexport function groupBy<T>(\n\tarr: T[],\n\tkey: keyof T | ((item: T) => string),\n): Record<string, T[]> {\n\tconst result: Record<string, T[]> = {};\n\tfor (const item of arr) {\n\t\tconst k = typeof key === \"function\" ? key(item) : String(item[key]);\n\t\tif (!result[k]) {\n\t\t\tresult[k] = [];\n\t\t}\n\t\tresult[k].push(item);\n\t}\n\treturn result;\n}\n\n/**\n * Return unique values from an array.\n * `uniq([1, 2, 2, 3])` → `[1, 2, 3]`\n */\nexport function uniq<T>(arr: T[]): T[] {\n\treturn [...new Set(arr)];\n}\n\n/**\n * Flatten a nested array.\n * `flatten([[1, 2], [3, [4, 5]]])` → `[1, 2, 3, 4, 5]`\n */\nexport function flatten<T>(arr: unknown[], depth = Infinity): T[] {\n\treturn arr.flat(depth) as T[];\n}\n\n/**\n * Split an array into chunks of a given size.\n * `chunk([1, 2, 3, 4, 5], 2)` → `[[1, 2], [3, 4], [5]]`\n */\nexport function chunk<T>(arr: T[], size: number): T[][] {\n\tif (size <= 0) throw new Error(\"chunk size must be > 0\");\n\tconst chunks: T[][] = [];\n\tfor (let i = 0; i < arr.length; i += size) {\n\t\tchunks.push(arr.slice(i, i + size));\n\t}\n\treturn chunks;\n}\n\n/**\n * Deep merge two objects. Arrays are replaced, not merged.\n *\n * @example\n * deepMerge({ a: 1, b: { c: 2 } }, { b: { d: 3 } });\n * // => { a: 1, b: { c: 2, d: 3 } }\n */\nexport function deepMerge<T extends Record<string, unknown>>(\n\ttarget: T,\n\t...sources: Partial<T>[]\n): T {\n\tconst result = { ...target };\n\tfor (const source of sources) {\n\t\tfor (const key of Object.keys(source) as (keyof T)[]) {\n\t\t\tconst targetVal = result[key];\n\t\t\tconst sourceVal = source[key];\n\t\t\tif (isPlainObject(targetVal) && isPlainObject(sourceVal)) {\n\t\t\t\t(result[key] as Record<string, unknown>) = deepMerge(\n\t\t\t\t\ttargetVal as Record<string, unknown>,\n\t\t\t\t\tsourceVal as Record<string, unknown>,\n\t\t\t\t);\n\t\t\t} else if (sourceVal !== undefined) {\n\t\t\t\tresult[key] = sourceVal as T[typeof key];\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction isPlainObject(val: unknown): val is Record<string, unknown> {\n\treturn typeof val === \"object\" && val !== null && !Array.isArray(val);\n}\n\n/**\n * Flatten a nested object into a single-depth object with dot-notation keys.\n *\n * @example\n * flattenObject({ a: { b: { c: 1 } } });\n * // => { \"a.b.c\": 1 }\n *\n * flattenObject({ a: { b: 1 }, c: 2 }, \"-\");\n * // => { \"a-b\": 1, c: 2 }\n */\nexport function flattenObject(\n\tobj: Record<string, unknown>,\n\tsep = \".\",\n): Record<string, unknown> {\n\tconst result: Record<string, unknown> = {};\n\n\tfunction recurse(current: Record<string, unknown>, prefix: string) {\n\t\tfor (const key of Object.keys(current)) {\n\t\t\tconst value = current[key];\n\t\t\tconst newKey = prefix ? `${prefix}${sep}${key}` : key;\n\n\t\t\tif (isPlainObject(value)) {\n\t\t\t\trecurse(value as Record<string, unknown>, newKey);\n\t\t\t} else {\n\t\t\t\tresult[newKey] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\trecurse(obj, \"\");\n\treturn result;\n}\n","import { scryptSync, randomBytes, timingSafeEqual } from \"node:crypto\";\n\nconst SCRYPT_OPTIONS = {\n\tN: 16384, // 2^14 - memory cost (16 MB)\n\tr: 8, // block size\n\tp: 1, // parallelization\n};\nconst KEY_LENGTH = 64;\nconst SALT_LENGTH = 16;\n\n/**\n * Hash a password using scrypt (memory-hard algorithm).\n * Returns a string in the format `scrypt:<salt>:<hash>` (hex-encoded).\n *\n * @example\n * ```ts\n * const hashed = await hashPassword(\"mypassword\");\n * // \"scrypt:a1b2c3d4...:e5f6g7h8...\"\n * ```\n */\nexport async function hashPassword(password: string): Promise<string> {\n\tconst salt = randomBytes(SALT_LENGTH);\n\tconst hash = scryptSync(password, salt, KEY_LENGTH, SCRYPT_OPTIONS);\n\treturn `scrypt:${salt.toString(\"hex\")}:${hash.toString(\"hex\")}`;\n}\n\n/**\n * Verify a password against a stored hash string.\n * Supports both scrypt (`scrypt:<salt>:<hash>`) and legacy PBKDF2 (`iterations:salt:hash`) formats.\n * Uses timing-safe comparison.\n *\n * @example\n * ```ts\n * const valid = await verifyPassword(\"mypassword\", hashed);  // true\n * const wrong = await verifyPassword(\"wrong\", hashed);        // false\n * ```\n */\nexport async function verifyPassword(\n\tpassword: string,\n\tstored: string,\n): Promise<boolean> {\n\t// Scrypt format\n\tif (stored.startsWith(\"scrypt:\")) {\n\t\tconst parts = stored.split(\":\");\n\t\tif (parts.length !== 3) return false;\n\n\t\tconst saltHex = parts[1] as string;\n\t\tconst expectedHash = parts[2] as string;\n\t\tconst salt = Buffer.from(saltHex, \"hex\");\n\t\tconst test = scryptSync(password, salt, KEY_LENGTH, SCRYPT_OPTIONS);\n\n\t\treturn timingSafeEqual(\n\t\t\tBuffer.from(expectedHash, \"hex\"),\n\t\t\ttest,\n\t\t);\n\t}\n\n\t// Legacy PBKDF2 format\n\treturn verifyPBKDF2Legacy(password, stored);\n}\n\n// ─── PBKDF2 Legacy Support ─────────────────────────────────────────────\n\nconst PBKDF2_ITERATIONS = 100_000;\nconst PBKDF2_KEY_LENGTH = 64;\nconst PBKDF2_DIGEST = \"SHA-256\";\n\nfunction toHex(buffer: Uint8Array): string {\n\treturn [...buffer].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nfunction fromHex(hex: string): Uint8Array {\n\treturn new Uint8Array(\n\t\thex.match(/.{1,2}/g)?.map((h) => Number.parseInt(h, 16)) ?? [],\n\t);\n}\n\nasync function verifyPBKDF2Legacy(\n\tpassword: string,\n\tstored: string,\n): Promise<boolean> {\n\tconst parts = stored.split(\":\");\n\tif (parts.length < 3) return false;\n\n\tconst iterations = Number(parts[0]);\n\tconst saltHex = parts[1] as string;\n\tconst expectedHash = parts[2] as string;\n\tconst salt = fromHex(saltHex) as Uint8Array<ArrayBuffer>;\n\n\tconst key = await crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tnew TextEncoder().encode(password),\n\t\t\"PBKDF2\",\n\t\tfalse,\n\t\t[\"deriveBits\"],\n\t);\n\tconst derived = await crypto.subtle.deriveBits(\n\t\t{ name: \"PBKDF2\", salt, iterations, hash: PBKDF2_DIGEST },\n\t\tkey,\n\t\tPBKDF2_KEY_LENGTH * 8,\n\t);\n\tconst actual = toHex(new Uint8Array(derived));\n\n\tif (actual.length !== expectedHash.length) return false;\n\tlet result = 0;\n\tfor (let i = 0; i < actual.length; i++) {\n\t\tresult |= actual.charCodeAt(i) ^ expectedHash.charCodeAt(i);\n\t}\n\treturn result === 0;\n}\n","/**\n * Convert a string to a URL-friendly slug.\n * `\"Hello World!\"` → `\"hello-world\"`\n */\nexport function slugify(str: string): string {\n\treturn str\n\t\t.toLowerCase()\n\t\t.trim()\n\t\t.replace(/[^\\w\\s-]/g, \"\")\n\t\t.replace(/[\\s_]+/g, \"-\")\n\t\t.replace(/-+/g, \"-\")\n\t\t.replace(/^-|-$/g, \"\");\n}\n\n/**\n * Truncate a string to a maximum length with an ellipsis suffix.\n * `\"Lorem ipsum dolor sit\"` → `\"Lorem ipsum...\"` (max=13)\n */\nexport function truncate(str: string, max = 100, suffix = \"...\"): string {\n\tif (str.length <= max) return str;\n\treturn str.slice(0, max - suffix.length) + suffix;\n}\n\n/**\n * Capitalize the first letter of a string.\n * `\"hello\"` → `\"Hello\"`\n */\nexport function capitalize(str: string): string {\n\treturn str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Convert a string to camelCase.\n * `\"hello-world\"` → `\"helloWorld\"`\n * `\"hello_world\"` → `\"helloWorld\"`\n */\nexport function camelCase(str: string): string {\n\treturn str\n\t\t.replace(/[-_\\s]+(.)/g, (_, c: string) => c.toUpperCase())\n\t\t.replace(/^(.)/, (_, c: string) => c.toLowerCase());\n}\n\n/**\n * Convert a string to snake_case.\n * `\"helloWorld\"` → `\"hello_world\"`\n * `\"hello-world\"` → `\"hello_world\"`\n */\nexport function snakeCase(str: string): string {\n\treturn str\n\t\t.replace(/([A-Z])/g, \"_$1\")\n\t\t.replace(/[-\\s]+/g, \"_\")\n\t\t.toLowerCase()\n\t\t.replace(/^_/, \"\")\n\t\t.replace(/_+/g, \"_\");\n}\n\n/**\n * Convert a string to kebab-case.\n * `\"helloWorld\"` → `\"hello-world\"`\n * `\"hello_world\"` → `\"hello-world\"`\n */\nexport function kebabCase(str: string): string {\n\treturn snakeCase(str).replace(/_/g, \"-\");\n}\n","export interface MailAttachment {\n\tfilename: string;\n\t/** Buffer, base64 string, or file path */\n\tcontent?: Buffer | string;\n\t/** Remote URL (Resend only) */\n\tpath?: string;\n\t/** MIME type (e.g., \"application/pdf\", \"image/png\") */\n\tcontentType?: string;\n\t/** Content-ID for inline images (e.g., \"logo\" for cid:logo) */\n\tcid?: string;\n}\n\nexport interface MailOptions {\n\tfrom: string;\n\tto: string | string[];\n\t/** Carbon Copy recipients */\n\tcc?: string | string[];\n\t/** Blind Carbon Copy recipients */\n\tbcc?: string | string[];\n\t/** Reply-To address (different from from) */\n\treplyTo?: string | string[];\n\tsubject: string;\n\ttext?: string;\n\thtml?: string;\n\t/** File attachments */\n\tattachments?: MailAttachment[];\n}\n\nexport interface MailerConfig {\n\tprovider: \"resend\" | \"sendgrid\" | \"mailgun\" | \"smtp\";\n\t/** Required for Resend, SendGrid, and Mailgun */\n\tapiKey?: string;\n\t/** Required for Mailgun */\n\tdomain?: string;\n\t/** Required for SMTP */\n\tsmtp?: {\n\t\thost: string;\n\t\tport: number;\n\t\tsecure?: boolean;\n\t\tauth: {\n\t\t\tuser: string;\n\t\t\tpass: string;\n\t\t};\n\t};\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction toBase64(content: Buffer | string): string {\n\tif (typeof content === \"string\") {\n\t\t// Assume already base64 encoded\n\t\treturn content;\n\t}\n\treturn content.toString(\"base64\");\n}\n\nfunction toArray(value: string | string[]): string[] {\n\treturn Array.isArray(value) ? value : [value];\n}\n\nfunction inferMimeType(filename: string): string {\n\tconst ext = filename.split(\".\").pop()?.toLowerCase();\n\tconst mimeMap: Record<string, string> = {\n\t\tpdf: \"application/pdf\",\n\t\tpng: \"image/png\",\n\t\tjpg: \"image/jpeg\",\n\t\tjpeg: \"image/jpeg\",\n\t\tgif: \"image/gif\",\n\t\tsvg: \"image/svg+xml\",\n\t\twebp: \"image/webp\",\n\t\ttxt: \"text/plain\",\n\t\thtml: \"text/html\",\n\t\tcss: \"text/css\",\n\t\tjs: \"application/javascript\",\n\t\tjson: \"application/json\",\n\t\tzip: \"application/zip\",\n\t\tdoc: \"application/msword\",\n\t\tdocx: \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n\t\txls: \"application/vnd.ms-excel\",\n\t\txlsx: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n\t};\n\treturn mimeMap[ext || \"\"] || \"application/octet-stream\";\n}\n\n/**\n * Built-in Mailer wrapper for Buntok.\n * Supports Resend, SendGrid, and Mailgun (HTTP-based, zero-deps).\n * Also supports SMTP via dynamic import of 'nodemailer' (requires user installation).\n */\nexport class Mailer {\n\tconstructor(private config: MailerConfig) {}\n\n\t/**\n\t * Send an email asynchronously.\n\t * If you don't await this method, it acts as a background queue (fire-and-forget).\n\t */\n\tasync send(\n\t\toptions: MailOptions,\n\t): Promise<{ success: boolean; id?: string; error?: string }> {\n\t\tif (this.config.provider === \"resend\") {\n\t\t\treturn this.sendResend(options);\n\t\t}\n\n\t\tif (this.config.provider === \"sendgrid\") {\n\t\t\treturn this.sendSendGrid(options);\n\t\t}\n\n\t\tif (this.config.provider === \"mailgun\") {\n\t\t\treturn this.sendMailgun(options);\n\t\t}\n\n\t\tif (this.config.provider === \"smtp\") {\n\t\t\treturn this.sendSmtp(options);\n\t\t}\n\n\t\treturn { success: false, error: \"Unsupported provider\" };\n\t}\n\n\t// ─── Resend ──────────────────────────────────────────────────────────────\n\n\tprivate async sendResend(\n\t\toptions: MailOptions,\n\t): Promise<{ success: boolean; id?: string; error?: string }> {\n\t\ttry {\n\t\t\tconst payload: Record<string, unknown> = {\n\t\t\t\tfrom: options.from,\n\t\t\t\tto: toArray(options.to),\n\t\t\t\tsubject: options.subject,\n\t\t\t\ttext: options.text,\n\t\t\t\thtml: options.html,\n\t\t\t};\n\n\t\t\tif (options.cc) payload.cc = toArray(options.cc);\n\t\t\tif (options.bcc) payload.bcc = toArray(options.bcc);\n\t\t\tif (options.replyTo) payload.reply_to = toArray(options.replyTo);\n\n\t\t\tif (options.attachments && options.attachments.length > 0) {\n\t\t\t\tpayload.attachments = options.attachments.map((att) => {\n\t\t\t\t\tconst attachment: Record<string, unknown> = {\n\t\t\t\t\t\tfilename: att.filename,\n\t\t\t\t\t};\n\n\t\t\t\t\tif (att.path) {\n\t\t\t\t\t\tattachment.path = att.path;\n\t\t\t\t\t} else if (att.content) {\n\t\t\t\t\t\tattachment.content = toBase64(att.content);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (att.contentType) {\n\t\t\t\t\t\tattachment.content_type = att.contentType;\n\t\t\t\t\t} else if (att.filename) {\n\t\t\t\t\t\tattachment.content_type = inferMimeType(att.filename);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (att.cid) {\n\t\t\t\t\t\tattachment.content_id = att.cid;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn attachment;\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst res = await fetch(\"https://api.resend.com/emails\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${this.config.apiKey}`,\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t});\n\n\t\t\tconst data = (await res.json()) as Record<string, unknown>;\n\t\t\tif (!res.ok) return { success: false, error: data.message as string };\n\t\t\treturn { success: true, id: data.id as string };\n\t\t} catch (err: unknown) {\n\t\t\tconst e = err as Error;\n\t\t\treturn { success: false, error: e.message };\n\t\t}\n\t}\n\n\t// ─── SendGrid ────────────────────────────────────────────────────────────\n\n\tprivate async sendSendGrid(\n\t\toptions: MailOptions,\n\t): Promise<{ success: boolean; id?: string; error?: string }> {\n\t\ttry {\n\t\t\tconst toArray = (v: string | string[]) =>\n\t\t\t\t(Array.isArray(v) ? v : [v]).map((email) => ({ email }));\n\n\t\t\tconst personalization: Record<string, unknown> = {\n\t\t\t\tto: toArray(options.to),\n\t\t\t};\n\t\t\tif (options.cc) personalization.cc = toArray(options.cc);\n\t\t\tif (options.bcc) personalization.bcc = toArray(options.bcc);\n\n\t\t\tconst payload: Record<string, unknown> = {\n\t\t\t\tpersonalizations: [personalization],\n\t\t\t\tfrom: { email: options.from },\n\t\t\t\tsubject: options.subject,\n\t\t\t};\n\n\t\t\tif (options.replyTo) {\n\t\t\t\tconst replyToArr = toArray(options.replyTo);\n\t\t\t\tif (replyToArr.length === 1) {\n\t\t\t\t\tpayload.reply_to = { email: replyToArr[0] };\n\t\t\t\t} else {\n\t\t\t\t\tpayload.reply_to_list = replyToArr.map((email) => ({ email }));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst content = [];\n\t\t\tif (options.text)\n\t\t\t\tcontent.push({ type: \"text/plain\", value: options.text });\n\t\t\tif (options.html)\n\t\t\t\tcontent.push({ type: \"text/html\", value: options.html });\n\t\t\tpayload.content = content;\n\n\t\t\tif (options.attachments && options.attachments.length > 0) {\n\t\t\t\tpayload.attachments = options.attachments.map((att) => {\n\t\t\t\t\tconst attachment: Record<string, unknown> = {\n\t\t\t\t\t\tcontent: att.content ? toBase64(att.content) : \"\",\n\t\t\t\t\t\tfilename: att.filename,\n\t\t\t\t\t\tdisposition: att.cid ? \"inline\" : \"attachment\",\n\t\t\t\t\t};\n\n\t\t\t\t\tif (att.contentType) {\n\t\t\t\t\t\tattachment.type = att.contentType;\n\t\t\t\t\t} else if (att.filename) {\n\t\t\t\t\t\tattachment.type = inferMimeType(att.filename);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (att.cid) {\n\t\t\t\t\t\tattachment.content_id = att.cid;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn attachment;\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst res = await fetch(\"https://api.sendgrid.com/v3/mail/send\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${this.config.apiKey}`,\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t});\n\n\t\t\tif (!res.ok) {\n\t\t\t\tconst data = (await res.json()) as { errors?: { message: string }[] };\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: data.errors?.[0]?.message || \"SendGrid Error\",\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { success: true };\n\t\t} catch (err: unknown) {\n\t\t\tconst e = err as Error;\n\t\t\treturn { success: false, error: e.message };\n\t\t}\n\t}\n\n\t// ─── Mailgun ─────────────────────────────────────────────────────────────\n\n\tprivate async sendMailgun(\n\t\toptions: MailOptions,\n\t): Promise<{ success: boolean; id?: string; error?: string }> {\n\t\ttry {\n\t\t\tif (!this.config.domain)\n\t\t\t\tthrow new Error(\"Mailgun requires a domain configured\");\n\n\t\t\tconst formData = new FormData();\n\t\t\tformData.append(\"from\", options.from);\n\n\t\t\tconst toArray = (v: string | string[]) =>\n\t\t\t\tArray.isArray(v) ? v : [v];\n\t\t\tfor (const t of toArray(options.to)) formData.append(\"to\", t);\n\t\t\tif (options.cc) for (const c of toArray(options.cc)) formData.append(\"cc\", c);\n\t\t\tif (options.bcc) for (const b of toArray(options.bcc)) formData.append(\"bcc\", b);\n\n\t\t\tformData.append(\"subject\", options.subject);\n\t\t\tif (options.text) formData.append(\"text\", options.text);\n\t\t\tif (options.html) formData.append(\"html\", options.html);\n\n\t\t\tif (options.replyTo) {\n\t\t\t\tconst replyTo = toArray(options.replyTo).join(\", \");\n\t\t\t\tformData.append(\"h:Reply-To\", replyTo);\n\t\t\t}\n\n\t\t\tif (options.attachments && options.attachments.length > 0) {\n\t\t\t\tfor (const att of options.attachments) {\n\t\t\t\t\tif (att.cid) {\n\t\t\t\t\t\t// Inline attachment\n\t\t\t\t\t\tif (att.content) {\n\t\t\t\t\t\t\tconst blob =\n\t\t\t\t\t\t\t\ttypeof att.content === \"string\"\n\t\t\t\t\t\t\t\t\t? new Blob([Uint8Array.from(atob(att.content), (c) => c.charCodeAt(0))])\n\t\t\t\t\t\t\t\t\t: new Blob([att.content]);\n\t\t\t\t\t\t\tformData.append(\"inline\", blob, att.filename);\n\t\t\t\t\t\t} else if (att.path) {\n\t\t\t\t\t\t\tconst res = await fetch(att.path);\n\t\t\t\t\t\t\tconst blob = await res.blob();\n\t\t\t\t\t\t\tformData.append(\"inline\", blob, att.filename);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Regular attachment\n\t\t\t\t\t\tif (att.content) {\n\t\t\t\t\t\t\tconst blob =\n\t\t\t\t\t\t\t\ttypeof att.content === \"string\"\n\t\t\t\t\t\t\t\t\t? new Blob([Uint8Array.from(atob(att.content), (c) => c.charCodeAt(0))])\n\t\t\t\t\t\t\t\t\t: new Blob([att.content]);\n\t\t\t\t\t\t\tformData.append(\"attachment\", blob, att.filename);\n\t\t\t\t\t\t} else if (att.path) {\n\t\t\t\t\t\t\tconst res = await fetch(att.path);\n\t\t\t\t\t\t\tconst blob = await res.blob();\n\t\t\t\t\t\t\tformData.append(\"attachment\", blob, att.filename);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst basicAuth = btoa(`api:${this.config.apiKey}`);\n\t\t\tconst res = await fetch(\n\t\t\t\t`https://api.mailgun.net/v3/${this.config.domain}/messages`,\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: { Authorization: `Basic ${basicAuth}` },\n\t\t\t\t\tbody: formData,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst data = (await res.json()) as Record<string, unknown>;\n\t\t\tif (!res.ok) return { success: false, error: data.message as string };\n\t\t\treturn { success: true, id: data.id as string };\n\t\t} catch (err: unknown) {\n\t\t\tconst e = err as Error;\n\t\t\treturn { success: false, error: e.message };\n\t\t}\n\t}\n\n\t// ─── SMTP (nodemailer) ──────────────────────────────────────────────────\n\n\tprivate async sendSmtp(\n\t\toptions: MailOptions,\n\t): Promise<{ success: boolean; id?: string; error?: string }> {\n\t\tif (!this.config.smtp)\n\t\t\treturn { success: false, error: \"SMTP configuration missing\" };\n\t\ttry {\n\t\t\t// Dynamic import to keep Buntok dependency-free\n\t\t\t// @ts-expect-error\n\t\t\tconst nodemailer = await import(\"nodemailer\");\n\t\t\tconst transporter = nodemailer.createTransport(this.config.smtp);\n\n\t\t\tconst mailOptions: Record<string, unknown> = {\n\t\t\t\tfrom: options.from,\n\t\t\t\tto: toArray(options.to).join(\",\"),\n\t\t\t\tsubject: options.subject,\n\t\t\t\ttext: options.text,\n\t\t\t\thtml: options.html,\n\t\t\t};\n\n\t\t\tif (options.cc) mailOptions.cc = toArray(options.cc).join(\",\");\n\t\t\tif (options.bcc) mailOptions.bcc = toArray(options.bcc).join(\",\");\n\t\t\tif (options.replyTo) mailOptions.replyTo = toArray(options.replyTo).join(\",\");\n\n\t\t\tif (options.attachments && options.attachments.length > 0) {\n\t\t\t\tmailOptions.attachments = options.attachments.map((att) => {\n\t\t\t\t\tconst attachment: Record<string, unknown> = {\n\t\t\t\t\t\tfilename: att.filename,\n\t\t\t\t\t};\n\n\t\t\t\t\tif (att.path) {\n\t\t\t\t\t\tattachment.path = att.path;\n\t\t\t\t\t} else if (att.content) {\n\t\t\t\t\t\tattachment.content =\n\t\t\t\t\t\t\ttypeof att.content === \"string\"\n\t\t\t\t\t\t\t\t? Buffer.from(att.content, \"base64\")\n\t\t\t\t\t\t\t\t: att.content;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (att.contentType) {\n\t\t\t\t\t\tattachment.contentType = att.contentType;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (att.cid) {\n\t\t\t\t\t\tattachment.cid = att.cid;\n\t\t\t\t\t\tattachment.contentDisposition = \"inline\";\n\t\t\t\t\t}\n\n\t\t\t\t\treturn attachment;\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst info = await transporter.sendMail(mailOptions);\n\t\t\treturn { success: true, id: info.messageId };\n\t\t} catch (err: unknown) {\n\t\t\tconst e = err as { code?: string; message: string };\n\t\t\tif (e.code === \"ERR_MODULE_NOT_FOUND\") {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: \"Nodemailer is required for SMTP. Run 'bun add nodemailer'\",\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { success: false, error: e.message };\n\t\t}\n\t}\n}\n","// ──────────────────────────────────────────────────────────────────────────────\n// Buntok Template Engine - Handlebars-like, zero-deps\n// ──────────────────────────────────────────────────────────────────────────────\n\nexport interface TemplateOptions {\n\tstrict?: boolean;\n\tescapeHtml?: boolean;\n\tonMissing?: (path: string, availableKeys: string[]) => void;\n}\n\nexport interface HelperFn {\n\t(...args: unknown[]): string;\n}\n\n// ─── AST Node Types ───────────────────────────────────────────────────────────\n\ninterface TextNode {\n\ttype: \"text\";\n\tvalue: string;\n}\n\ninterface VariableNode {\n\ttype: \"variable\";\n\tpath: string;\n\tescaped: boolean;\n}\n\ninterface BlockNode {\n\ttype: \"block\";\n\tblockType: \"if\" | \"unless\" | \"each\";\n\texpression: string;\n\tchildren: ASTNode[];\n\tinverse?: ASTNode[];\n}\n\ninterface PartialNode {\n\ttype: \"partial\";\n\tname: string;\n}\n\ninterface CommentNode {\n\ttype: \"comment\";\n\tvalue: string;\n}\n\ntype ASTNode = TextNode | VariableNode | BlockNode | PartialNode | CommentNode;\n\n// ─── Tokenizer ────────────────────────────────────────────────────────────────\n\ntype TokenType =\n\t| \"TEXT\"\n\t| \"VARIABLE\"\n\t| \"BLOCK_OPEN\"\n\t| \"BLOCK_CLOSE\"\n\t| \"PARTIAL\"\n\t| \"COMMENT\";\n\ninterface Token {\n\ttype: TokenType;\n\tvalue: string;\n\tpath?: string;\n\tescaped?: boolean;\n}\n\nfunction tokenize(template: string): Token[] {\n\tconst tokens: Token[] = [];\n\tlet pos = 0;\n\n\twhile (pos < template.length) {\n\t\tconst openIndex = template.indexOf(\"{{\", pos);\n\t\tif (openIndex === -1) {\n\t\t\ttokens.push({ type: \"TEXT\", value: template.slice(pos) });\n\t\t\tbreak;\n\t\t}\n\n\t\tif (openIndex > pos) {\n\t\t\ttokens.push({ type: \"TEXT\", value: template.slice(pos, openIndex) });\n\t\t}\n\n\t\t// Look for }}} first (triple braces), then }} (double braces)\n\t\tlet closeIndex = template.indexOf(\"}}}\", openIndex + 2);\n\t\tlet closeLen = 3;\n\t\tlet tagStart = openIndex + 2;\n\t\tif (closeIndex === -1) {\n\t\t\tcloseIndex = template.indexOf(\"}}\", openIndex + 2);\n\t\t\tcloseLen = 2;\n\t\t} else {\n\t\t\t// Triple braces: skip the third {\n\t\t\ttagStart = openIndex + 3;\n\t\t}\n\t\tif (closeIndex === -1) {\n\t\t\ttokens.push({ type: \"TEXT\", value: template.slice(openIndex) });\n\t\t\tbreak;\n\t\t}\n\n\t\tconst tagContent = template.slice(tagStart, closeIndex).trim();\n\t\tpos = closeIndex + closeLen;\n\n\t\t// Triple braces = unescaped output\n\t\tconst isTripleBrace = closeLen === 3;\n\n\t\t// Classify tag\n\t\tif (tagContent.startsWith(\"!\")) {\n\t\t\ttokens.push({ type: \"COMMENT\", value: tagContent.slice(1).trim() });\n\t\t} else if (tagContent === \"else\") {\n\t\t\ttokens.push({ type: \"BLOCK_OPEN\", value: \"else\" });\n\t\t} else if (tagContent.startsWith(\"#\")) {\n\t\t\ttokens.push({ type: \"BLOCK_OPEN\", value: tagContent.slice(1).trim() });\n\t\t} else if (tagContent.startsWith(\"/\")) {\n\t\t\ttokens.push({ type: \"BLOCK_CLOSE\", value: tagContent.slice(1).trim() });\n\t\t} else if (tagContent.startsWith(\">\")) {\n\t\t\ttokens.push({ type: \"PARTIAL\", value: tagContent.slice(1).trim() });\n\t\t} else {\n\t\t\ttokens.push({ type: \"VARIABLE\", value: tagContent, path: tagContent, escaped: !isTripleBrace });\n\t\t}\n\t}\n\n\treturn tokens;\n}\n\n// ─── Parser ───────────────────────────────────────────────────────────────────\n\nfunction parseBlockType(value: string): { blockType: \"if\" | \"unless\" | \"each\"; expression: string } {\n\tconst spaceIndex = value.indexOf(\" \");\n\tconst blockType = (spaceIndex === -1 ? value : value.slice(0, spaceIndex)) as \"if\" | \"unless\" | \"each\";\n\tconst expression = spaceIndex === -1 ? \"\" : value.slice(spaceIndex + 1).trim();\n\treturn { blockType, expression };\n}\n\nfunction parse(tokens: Token[]): ASTNode[] {\n\tconst nodes: ASTNode[] = [];\n\tlet pos = 0;\n\n\twhile (pos < tokens.length) {\n\t\tconst token = tokens[pos];\n\t\tif (!token) break;\n\n\t\tif (token.type === \"TEXT\") {\n\t\t\tnodes.push({ type: \"text\", value: token.value });\n\t\t\tpos++;\n\t\t} else if (token.type === \"VARIABLE\") {\n\t\t\tnodes.push({\n\t\t\t\ttype: \"variable\",\n\t\t\t\tpath: token.path || \"\",\n\t\t\t\tescaped: token.escaped ?? true,\n\t\t\t});\n\t\t\tpos++;\n\t\t} else if (token.type === \"BLOCK_OPEN\") {\n\t\t\tconst { blockType, expression } = parseBlockType(token.value);\n\t\t\tpos++;\n\n\t\t\t// Handle standalone {{else}} token\n\t\t\tif (blockType === (\"else\" as string)) {\n\t\t\t\t// This shouldn't happen at top level, but handle gracefully\n\t\t\t\treturn nodes;\n\t\t\t}\n\n\t\t\tconst children: ASTNode[] = [];\n\t\t\tconst inverse: ASTNode[] = [];\n\t\t\tlet depth = 1;\n\t\t\tlet inElse = false;\n\n\t\t\twhile (pos < tokens.length && depth > 0) {\n\t\t\t\tconst t = tokens[pos];\n\t\t\t\tif (!t) break;\n\n\t\t\t\tif (t.type === \"BLOCK_OPEN\" && t.value === \"else\") {\n\t\t\t\t\tinElse = true;\n\t\t\t\t\tpos++;\n\t\t\t\t} else if (t.type === \"BLOCK_OPEN\") {\n\t\t\t\t\tconst nested = parseBlockType(t.value);\n\t\t\t\t\tdepth++;\n\t\t\t\t\t// Parse nested block properly\n\t\t\t\t\tpos++;\n\t\t\t\t\tconst nestedChildren: ASTNode[] = [];\n\t\t\t\t\tconst nestedInverse: ASTNode[] = [];\n\t\t\t\t\tlet nestedDepth = 1;\n\t\t\t\t\tlet nestedInElse = false;\n\n\t\t\t\t\twhile (pos < tokens.length && nestedDepth > 0) {\n\t\t\t\t\t\tconst nt = tokens[pos];\n\t\t\t\t\t\tif (!nt) break;\n\t\t\t\t\t\tif (nt.type === \"BLOCK_OPEN\" && nt.value === \"else\") {\n\t\t\t\t\t\t\tnestedInElse = true;\n\t\t\t\t\t\t\tpos++;\n\t\t\t\t\t\t} else if (nt.type === \"BLOCK_OPEN\") {\n\t\t\t\t\t\t\tnestedDepth++;\n\t\t\t\t\t\t\tnestedChildren.push(...parse([nt]));\n\t\t\t\t\t\t\tpos++;\n\t\t\t\t\t\t} else if (nt.type === \"BLOCK_CLOSE\") {\n\t\t\t\t\t\t\tnestedDepth--;\n\t\t\t\t\t\t\tif (nestedDepth === 0) {\n\t\t\t\t\t\t\t\tpos++;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnestedInverse.push({ type: \"text\", value: `{{/${nt.value}}}` });\n\t\t\t\t\t\t\tpos++;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (nestedInElse) nestedInverse.push({ type: \"text\", value: nt.value });\n\t\t\t\t\t\t\telse nestedChildren.push({ type: \"text\", value: nt.value });\n\t\t\t\t\t\t\tpos++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst nestedBlock: BlockNode = {\n\t\t\t\t\t\ttype: \"block\",\n\t\t\t\t\t\tblockType: nested.blockType,\n\t\t\t\t\t\texpression: nested.expression,\n\t\t\t\t\t\tchildren: nestedChildren,\n\t\t\t\t\t\tinverse: nestedInverse.length > 0 ? nestedInverse : undefined,\n\t\t\t\t\t};\n\t\t\t\t\tif (inElse) inverse.push(nestedBlock);\n\t\t\t\t\telse children.push(nestedBlock);\n\t\t\t\t} else if (t.type === \"BLOCK_CLOSE\") {\n\t\t\t\t\tdepth--;\n\t\t\t\t\tif (depth === 0) {\n\t\t\t\t\t\tpos++;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tinverse.push({ type: \"text\", value: `{{/${t.value}}}` });\n\t\t\t\t\tpos++;\n\t\t\t\t} else if (t.type === \"TEXT\") {\n\t\t\t\t\tif (inElse) {\n\t\t\t\t\t\tinverse.push({ type: \"text\", value: t.value });\n\t\t\t\t\t} else {\n\t\t\t\t\t\tchildren.push({ type: \"text\", value: t.value });\n\t\t\t\t\t}\n\t\t\t\t\tpos++;\n\t\t\t\t} else if (t.type === \"VARIABLE\") {\n\t\t\t\t\tconst node: VariableNode = {\n\t\t\t\t\t\ttype: \"variable\",\n\t\t\t\t\t\tpath: t.path || \"\",\n\t\t\t\t\t\tescaped: t.escaped ?? true,\n\t\t\t\t\t};\n\t\t\t\t\tif (inElse) inverse.push(node);\n\t\t\t\t\telse children.push(node);\n\t\t\t\t\tpos++;\n\t\t\t\t} else {\n\t\t\t\t\tpos++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnodes.push({\n\t\t\t\ttype: \"block\",\n\t\t\t\tblockType,\n\t\t\t\texpression,\n\t\t\t\tchildren,\n\t\t\t\tinverse: inverse.length > 0 ? inverse : undefined,\n\t\t\t});\n\t\t} else if (token.type === \"PARTIAL\") {\n\t\t\tnodes.push({ type: \"partial\", name: token.value });\n\t\t\tpos++;\n\t\t} else if (token.type === \"COMMENT\") {\n\t\t\tpos++;\n\t\t} else {\n\t\t\tpos++;\n\t\t}\n\t}\n\n\treturn nodes;\n}\n\n// ─── Renderer ─────────────────────────────────────────────────────────────────\n\nconst ESCAPE_MAP: Record<string, string> = {\n\t\"&\": \"&amp;\",\n\t\"<\": \"&lt;\",\n\t\">\": \"&gt;\",\n\t'\"': \"&quot;\",\n\t\"'\": \"&#x27;\",\n};\n\nfunction escapeHtml(str: string): string {\n\treturn str.replace(/[&<>\"']/g, (char) => ESCAPE_MAP[char] || char);\n}\n\nfunction resolvePath(path: string, context: unknown): unknown {\n\tconst parts = path.split(\".\");\n\tlet current = context;\n\n\tfor (const part of parts) {\n\t\tif (current == null || typeof current !== \"object\") {\n\t\t\treturn undefined;\n\t\t}\n\t\tcurrent = (current as Record<string, unknown>)[part];\n\t}\n\n\treturn current;\n}\n\nfunction collectKeys(obj: unknown, prefix = \"\"): string[] {\n\tconst keys: string[] = [];\n\tif (obj == null || typeof obj !== \"object\") return keys;\n\n\tfor (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n\t\tconst fullKey = prefix ? `${prefix}.${key}` : key;\n\t\tkeys.push(fullKey);\n\t\tif (value != null && typeof value === \"object\" && !Array.isArray(value)) {\n\t\t\tkeys.push(...collectKeys(value, fullKey));\n\t\t}\n\t}\n\treturn keys;\n}\n\nfunction levenshteinDistance(a: string, b: string): number {\n\tconst m = a.length;\n\tconst n = b.length;\n\tconst dp: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0) as number[]);\n\n\tfor (let i = 0; i <= m; i++) {\n\t\tconst row = dp[i];\n\t\tif (row) row[0] = i;\n\t}\n\tfor (let j = 0; j <= n; j++) {\n\t\tconst row = dp[0];\n\t\tif (row) row[j] = j;\n\t}\n\n\tfor (let i = 1; i <= m; i++) {\n\t\tfor (let j = 1; j <= n; j++) {\n\t\t\tconst row = dp[i];\n\t\t\tconst prevRow = dp[i - 1];\n\t\t\tif (row && prevRow) {\n\t\t\t\trow[j] =\n\t\t\t\t\ta[i - 1] === b[j - 1]\n\t\t\t\t\t\t? (prevRow[j - 1] ?? 0)\n\t\t\t\t\t\t: Math.min(prevRow[j] ?? 0, row[j - 1] ?? 0, prevRow[j - 1] ?? 0) + 1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn dp[m]?.[n] ?? 0;\n}\n\nfunction suggestVariable(path: string, availableKeys: string[]): string | null {\n\tconst basePath = path.split(\".\")[0] || \"\";\n\tlet bestMatch: string | null = null;\n\tlet bestDistance = Infinity;\n\n\tfor (const key of availableKeys) {\n\t\tconst keyBase = key.split(\".\")[0] || \"\";\n\t\tconst distance = levenshteinDistance(basePath, keyBase);\n\t\tif (distance < bestDistance && distance <= 3) {\n\t\t\tbestDistance = distance;\n\t\t\tbestMatch = key;\n\t\t}\n\t}\n\n\treturn bestMatch;\n}\n\nfunction renderNodes(\n\tnodes: ASTNode[],\n\tcontext: unknown,\n\toptions: TemplateOptions,\n\tpartials: Map<string, ASTNode[]>,\n\thelpers: Map<string, HelperFn>,\n): string {\n\tconst parts: string[] = [];\n\n\tfor (const node of nodes) {\n\t\tswitch (node.type) {\n\t\t\tcase \"text\":\n\t\t\t\tparts.push(node.value);\n\t\t\t\tbreak;\n\n\t\t\tcase \"variable\": {\n\t\t\t\t// Check if this is a helper call (e.g., \"upper name\")\n\t\t\t\tconst spaceIdx = node.path.indexOf(\" \");\n\t\t\t\tif (spaceIdx !== -1) {\n\t\t\t\t\tconst helperName = node.path.slice(0, spaceIdx);\n\t\t\t\t\tconst argPath = node.path.slice(spaceIdx + 1).trim();\n\t\t\t\t\tconst helper = helpers.get(helperName);\n\t\t\t\t\tif (helper) {\n\t\t\t\t\t\tconst argValue = resolvePath(argPath, context);\n\t\t\t\t\t\tparts.push(helper(argValue));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst value = resolvePath(node.path, context);\n\n\t\t\t\tif (value === undefined || value === null) {\n\t\t\t\t\tif (options.strict) {\n\t\t\t\t\t\tconst availableKeys = collectKeys(context);\n\t\t\t\t\t\tconst suggestion = suggestVariable(node.path, availableKeys);\n\t\t\t\t\t\tlet msg = `TemplateError: Variable '${node.path}' not found in context.`;\n\t\t\t\t\t\tif (availableKeys.length > 0) {\n\t\t\t\t\t\t\tmsg += `\\n  Available keys: ${availableKeys.slice(0, 10).join(\", \")}`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (suggestion) {\n\t\t\t\t\t\t\tmsg += `\\n  Did you mean: '${suggestion}'?`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow new Error(msg);\n\t\t\t\t\t}\n\t\t\t\t\tif (options.onMissing) {\n\t\t\t\t\t\toptions.onMissing(node.path, collectKeys(context));\n\t\t\t\t\t}\n\t\t\t\t\tparts.push(\"\");\n\t\t\t\t} else if (typeof value === \"function\") {\n\t\t\t\t\tparts.push(String(value));\n\t\t\t\t} else if (node.escaped) {\n\t\t\t\t\tparts.push(escapeHtml(String(value)));\n\t\t\t\t} else {\n\t\t\t\t\tparts.push(String(value));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"block\": {\n\t\t\t\tconst value = resolvePath(node.expression, context);\n\n\t\t\t\tif (node.blockType === \"if\") {\n\t\t\t\t\tif (value && !(Array.isArray(value) && value.length === 0)) {\n\t\t\t\t\t\tparts.push(renderNodes(node.children, context, options, partials, helpers));\n\t\t\t\t\t} else if (node.inverse) {\n\t\t\t\t\t\tparts.push(renderNodes(node.inverse, context, options, partials, helpers));\n\t\t\t\t\t}\n\t\t\t\t} else if (node.blockType === \"unless\") {\n\t\t\t\t\tif (!value || (Array.isArray(value) && value.length === 0)) {\n\t\t\t\t\t\tparts.push(renderNodes(node.children, context, options, partials, helpers));\n\t\t\t\t\t} else if (node.inverse) {\n\t\t\t\t\t\tparts.push(renderNodes(node.inverse, context, options, partials, helpers));\n\t\t\t\t\t}\n\t\t\t\t} else if (node.blockType === \"each\") {\n\t\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\t\t\t\t\tconst item = value[i];\n\t\t\t\t\t\t\tconst eachContext =\n\t\t\t\t\t\t\t\ttypeof item === \"object\" && item !== null\n\t\t\t\t\t\t\t\t\t? { ...item, \"@index\": i, \"@first\": i === 0, \"@last\": i === value.length - 1, \"../\": context }\n\t\t\t\t\t\t\t\t\t: { \"@value\": item, \"@index\": i, \"@first\": i === 0, \"@last\": i === value.length - 1, \"../\": context };\n\t\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t\trenderNodes(node.children, eachContext, options, partials, helpers),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (node.inverse) {\n\t\t\t\t\t\tparts.push(renderNodes(node.inverse, context, options, partials, helpers));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"partial\": {\n\t\t\t\tconst partialNodes = partials.get(node.name);\n\t\t\t\tif (partialNodes) {\n\t\t\t\t\tparts.push(renderNodes(partialNodes, context, options, partials, helpers));\n\t\t\t\t} else if (options.strict) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`TemplateError: Partial '${node.name}' not found. Register it with engine.registerPartial().`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"comment\":\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn parts.join(\"\");\n}\n\n// ─── TemplateEngine Class ─────────────────────────────────────────────────────\n\nexport class TemplateEngine {\n\tprivate options: TemplateOptions;\n\tprivate partials = new Map<string, ASTNode[]>();\n\tprivate helpers = new Map<string, HelperFn>();\n\n\tconstructor(options: TemplateOptions = {}) {\n\t\tthis.options = {\n\t\t\tstrict: true,\n\t\t\tescapeHtml: true,\n\t\t\t...options,\n\t\t};\n\t}\n\n\tregisterPartial(name: string, template: string): void {\n\t\tconst tokens = tokenize(template);\n\t\tthis.partials.set(name, parse(tokens));\n\t}\n\n\tregisterHelper(name: string, fn: HelperFn): void {\n\t\tthis.helpers.set(name, fn);\n\t}\n\n\trender(template: string, context: unknown): string {\n\t\tconst tokens = tokenize(template);\n\t\tconst ast = parse(tokens);\n\t\treturn renderNodes(ast, context, this.options, this.partials, this.helpers);\n\t}\n\n\tcompile(template: string): (context: unknown) => string {\n\t\tconst tokens = tokenize(template);\n\t\tconst ast = parse(tokens);\n\t\treturn (context: unknown) =>\n\t\t\trenderNodes(ast, context, this.options, this.partials, this.helpers);\n\t}\n}\n\n// ─── Convenience Functions ────────────────────────────────────────────────────\n\nconst defaultEngine = new TemplateEngine();\n\nexport function render(template: string, context: unknown): string {\n\treturn defaultEngine.render(template, context);\n}\n\nexport function registerPartial(name: string, template: string): void {\n\tdefaultEngine.registerPartial(name, template);\n}\n\nexport function registerHelper(name: string, fn: HelperFn): void {\n\tdefaultEngine.registerHelper(name, fn);\n}\n","/**\n * Audit logging middleware for tracking user actions.\n *\n * @example\n * ```ts\n * import { auditLog } from \"buntok\";\n *\n * // Log all requests\n * app.use(auditLog());\n *\n * // Log with custom storage\n * app.use(auditLog({\n *   storage: async (entry) => {\n *     await db.auditLog.create({ data: entry });\n *   },\n *   excludePaths: [\"/health\", \"/docs\"],\n *   excludeMethods: [\"OPTIONS\"],\n * }));\n * ```\n */\n\nexport interface AuditLogEntry {\n\ttimestamp: string;\n\tmethod: string;\n\tpath: string;\n\tstatus: number;\n\tduration: number;\n\tip?: string;\n\tuserId?: string | number;\n\tuserAgent?: string;\n\tbody?: any;\n\tquery?: Record<string, any>;\n\terror?: string;\n}\n\nexport interface AuditLogOptions {\n\t/** Custom storage function. If not provided, logs to console. */\n\tstorage?: (entry: AuditLogEntry) => Promise<void> | void;\n\n\t/** Paths to exclude from logging */\n\texcludePaths?: string[];\n\n\t/** Methods to exclude from logging */\n\texcludeMethods?: string[];\n\n\t/** Whether to log request body (default: false) */\n\tlogBody?: boolean;\n\n\t/** Whether to log query params (default: true) */\n\tlogQuery?: boolean;\n\n\t/** Max body size to log in bytes (default: 1024) */\n\tmaxBodySize?: number;\n}\n\nfunction shouldLog(\n\tpath: string,\n\tmethod: string,\n\toptions: AuditLogOptions,\n): boolean {\n\tif (options.excludePaths?.some((p) => path.startsWith(p))) return false;\n\tif (options.excludeMethods?.includes(method)) return false;\n\treturn true;\n}\n\nfunction truncate(str: string, max: number): string {\n\tif (str.length <= max) return str;\n\treturn `${str.slice(0, max)}...[truncated]`;\n}\n\n/**\n * Audit logging middleware.\n * Logs all requests with timing, user info, and optional body/query.\n */\nexport function auditLog(options: AuditLogOptions = {}) {\n\tconst {\n\t\tlogBody = false,\n\t\tlogQuery = true,\n\t\tmaxBodySize = 1024,\n\t} = options;\n\n\treturn async (ctx: any, next: () => Promise<Response> | Response) => {\n\t\tconst method = ctx.request.method;\n\t\tconst path = ctx.request.url;\n\t\tconst start = performance.now();\n\n\t\tif (!shouldLog(path, method, options)) {\n\t\t\treturn next();\n\t\t}\n\n\t\tlet response: Response | undefined;\n\t\ttry {\n\t\t\tresponse = await next();\n\t\t} finally {\n\t\t\tconst duration = performance.now() - start;\n\t\t\tconst status = response?.status ?? 200;\n\n\t\t\tconst entry: AuditLogEntry = {\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tstatus,\n\t\t\t\tduration: Math.round(duration * 100) / 100,\n\t\t\t\tip: ctx.request.headers?.get(\"x-forwarded-for\") ?? \"\",\n\t\t\t\tuserId: ctx.user?.id,\n\t\t\t\tuserAgent: ctx.request.headers?.get(\"user-agent\"),\n\t\t\t};\n\n\t\t\tif (logBody) {\n\t\t\t\ttry {\n\t\t\t\t\tconst cloned = ctx.request.clone();\n\t\t\t\t\tconst bodyStr = await cloned.text();\n\t\t\t\t\tentry.body = truncate(bodyStr, maxBodySize);\n\t\t\t\t} catch {\n\t\t\t\t\t// body already consumed\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (logQuery) {\n\t\t\t\ttry {\n\t\t\t\t\tconst url = new URL(ctx.request.url);\n\t\t\t\t\tconst query = Object.fromEntries(url.searchParams);\n\t\t\t\t\tif (Object.keys(query).length > 0) {\n\t\t\t\t\t\tentry.query = query;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// invalid URL\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (status >= 400) {\n\t\t\t\tentry.error = ctx._error?.message;\n\t\t\t}\n\n\t\t\t// Custom storage or console\n\t\t\tif (options.storage) {\n\t\t\t\tawait options.storage(entry);\n\t\t\t} else {\n\t\t\t\tconst logFn = status >= 500\n\t\t\t\t\t? console.error\n\t\t\t\t\t: status >= 400\n\t\t\t\t\t\t? console.warn\n\t\t\t\t\t\t: console.log;\n\t\t\t\tlogFn(`[audit] ${method} ${path} ${status} ${entry.duration}ms`);\n\t\t\t}\n\t\t}\n\n\t\treturn response as Response;\n\t};\n}\n","import type { Middleware } from \"../app\";\nimport { BadRequestError } from \"../helpers/async-handler\";\n\nexport interface BodySizeLimitOptions {\n\t/**\n\t * Maximum allowed request body size in bytes.\n\t * Defaults to 10MB (10 * 1024 * 1024).\n\t */\n\tmaxSize?: number;\n\n\t/**\n\t * Custom error message when body size exceeds limit.\n\t * Defaults to: \"Request body too large. Maximum size is {maxSize} bytes.\"\n\t */\n\tmessage?: string;\n\n\t/**\n\t * HTTP status code for oversized requests.\n\t * Defaults to 413 (Payload Too Large).\n\t */\n\tstatusCode?: number;\n}\n\n/**\n * Middleware to limit incoming request body size.\n *\n * Checks the Content-Length header before the body is parsed.\n * Returns 413 (Payload Too Large) if the body exceeds the configured limit.\n *\n * @example\n * // Global: limit all requests to 1MB\n * app.use(bodySizeLimit({ maxSize: 1024 * 1024 }));\n *\n * @example\n * // Per-route: limit file upload endpoint to 50MB\n * app.post(\"/upload\", bodySizeLimit({ maxSize: 50 * 1024 * 1024 }), handler);\n *\n * @example\n * // Custom error message\n * app.use(bodySizeLimit({\n *   maxSize: 1024 * 1024,\n *   message: \"File too large. Max 1MB allowed.\",\n * }));\n */\nexport function bodySizeLimit(options?: BodySizeLimitOptions): Middleware {\n\tconst maxSize = options?.maxSize ?? 10 * 1024 * 1024; // 10MB default\n\tconst statusCode = options?.statusCode ?? 413;\n\n\treturn async (ctx, next) => {\n\t\tconst contentLength = ctx.request.headers.get(\"content-length\");\n\n\t\tif (contentLength) {\n\t\t\tconst size = Number.parseInt(contentLength, 10);\n\n\t\t\tif (!Number.isNaN(size) && size > maxSize) {\n\t\t\t\tconst message =\n\t\t\t\t\toptions?.message ??\n\t\t\t\t\t`Request body too large. Maximum size is ${maxSize} bytes.`;\n\n\t\t\t\treturn ctx.json(\n\t\t\t\t\t{\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tmessage,\n\t\t\t\t\t},\n\t\t\t\t\tstatusCode,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn next();\n\t};\n}\n","import type { Middleware } from \"../app\";\n\nexport interface CompressOptions {\n\t/**\n\t * Minimum response body size (bytes) before compressing. Compressing\n\t * tiny payloads wastes CPU for zero/negative gain, so this defaults to\n\t * 1024 rather than compressing everything unconditionally.\n\t */\n\tthreshold?: number;\n\t/** Content-Type prefixes eligible for compression. */\n\ttypes?: string[];\n\t/** Brotli compression level (1-11). Default 4 gives ~85% of max compression\n\t * at 3-5x the speed of level 11. Set to 11 for maximum ratio. */\n\tbrotliLevel?: number;\n}\n\nconst DEFAULT_TYPES = [\n\t\"text/\",\n\t\"application/json\",\n\t\"application/javascript\",\n\t\"application/xml\",\n\t\"image/svg+xml\",\n];\n\nconst DEFAULT_OPTIONS: Required<CompressOptions> = {\n\tthreshold: 1024,\n\ttypes: DEFAULT_TYPES,\n\tbrotliLevel: 4,\n};\n\n/**\n * Compress response bodies with gzip or brotli, negotiated from the\n * request's `Accept-Encoding` header. Opt-in via `app.use(compress())` -\n * compression is real CPU work, so routes that don't need it (or that\n * already stream pre-compressed/binary content) shouldn't pay for it.\n *\n * Uses Bun's native `Bun.gzipSync` (Zig, not a JS gzip implementation) and\n * falls back to `node:zlib`'s brotli when the client prefers `br`.\n *\n * Brotli defaults to level 4 for a good speed/ratio tradeoff - roughly\n * 3-5x faster than level 11 with only ~15% larger output.\n */\nexport function compress(options: CompressOptions = {}): Middleware {\n\tconst opts = { ...DEFAULT_OPTIONS, ...options };\n\n\treturn async (ctx, next) => {\n\t\tconst result = await next();\n\t\tif (!(result instanceof Response) || !result.body) return result;\n\n\t\tif (result.headers.get(\"Content-Encoding\")) return result;\n\n\t\tconst contentType = result.headers.get(\"Content-Type\") || \"\";\n\t\t// Industrial: jangan compress SSE/WebSocket streaming - break spec\n\t\tif (contentType.includes(\"text/event-stream\")) return result;\n\t\tconst eligible = opts.types.some((t) => contentType.startsWith(t));\n\t\tif (!eligible) return result;\n\n\t\tconst acceptEncoding = ctx.request.headers.get(\"Accept-Encoding\") || \"\";\n\t\tconst supportsBrotli = acceptEncoding.includes(\"br\");\n\t\tconst supportsGzip = acceptEncoding.includes(\"gzip\");\n\t\tif (!supportsBrotli && !supportsGzip) return result;\n\n\t\t// Fast path: use Content-Length header to skip buffering for small responses\n\t\tconst contentLength = result.headers.get(\"Content-Length\");\n\t\tif (contentLength && Number(contentLength) < opts.threshold) {\n\t\t\treturn result;\n\t\t}\n\n\t\t// If no Content-Length, we must buffer to check size - but only compress\n\t\t// if above threshold. For small responses without Content-Length, skip\n\t\t// compression entirely to avoid unnecessary buffering + new Response.\n\t\tif (!contentLength) return result;\n\n\t\tconst buffer = new Uint8Array(await result.arrayBuffer());\n\t\tif (buffer.byteLength < opts.threshold) {\n\t\t\treturn result;\n\t\t}\n\n\t\tlet compressed: Uint8Array;\n\t\tlet encoding: string;\n\n\t\tif (supportsBrotli) {\n\t\t\tconst zlib = await import(\"node:zlib\");\n\t\t\tcompressed = zlib.brotliCompressSync(buffer, {\n\t\t\t\tparams: {\n\t\t\t\t\t[zlib.constants.BROTLI_PARAM_QUALITY]: opts.brotliLevel,\n\t\t\t\t},\n\t\t\t});\n\t\t\tencoding = \"br\";\n\t\t} else {\n\t\t\tcompressed = Bun.gzipSync(buffer);\n\t\t\tencoding = \"gzip\";\n\t\t}\n\n\t\tconst headers = new Headers(result.headers);\n\t\theaders.set(\"Content-Encoding\", encoding);\n\t\theaders.set(\"Vary\", \"Accept-Encoding\");\n\t\theaders.delete(\"Content-Length\");\n\n\t\treturn new Response(compressed, {\n\t\t\tstatus: result.status,\n\t\t\tstatusText: result.statusText,\n\t\t\theaders,\n\t\t});\n\t};\n}\n","import type { Middleware } from \"../app\";\n\nexport interface CorsOptions {\n\torigin?: string | string[] | ((origin: string) => boolean);\n\tmethods?: string[];\n\theaders?: string[];\n\tcredentials?: boolean;\n}\n\nexport const cors = (options: CorsOptions = {}): Middleware => {\n\treturn async (ctx, next) => {\n\t\tconst requestOrigin = ctx.request.headers.get(\"Origin\") || \"*\";\n\t\tlet allowedOrigin = \"*\";\n\n\t\tif (typeof options.origin === \"function\") {\n\t\t\tallowedOrigin = options.origin(requestOrigin) ? requestOrigin : \"\";\n\t\t} else if (Array.isArray(options.origin)) {\n\t\t\tallowedOrigin = options.origin.includes(requestOrigin)\n\t\t\t\t? requestOrigin\n\t\t\t\t: \"\";\n\t\t} else if (options.origin) {\n\t\t\tallowedOrigin = options.origin;\n\t\t}\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\tres.headers.set(\"X-Powered-By\", \"Buntok\");\n\t\t\treturn res;\n\t\t}\n\n\t\tconst response = await next();\n\n\t\tresponse.headers.set(\"Access-Control-Allow-Origin\", allowedOrigin);\n\t\tresponse.headers.set(\"X-Powered-By\", \"Buntok\");\n\t\tif (options.credentials)\n\t\t\tresponse.headers.set(\"Access-Control-Allow-Credentials\", \"true\");\n\n\t\treturn response;\n\t};\n};\n","import type { Context } from \"../context\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyApp = {\n\tget: (\n\t\tpath: string,\n\t\thandler: (ctx: Context) => Promise<Response> | Response,\n\t) => void;\n};\n\nexport interface HealthCheckOptions {\n\t/** Health check endpoint path (default: /health) */\n\tpath?: string;\n\t/** Custom health check function */\n\tcheck?: () => Promise<HealthStatus> | HealthStatus;\n\t/** Include uptime in response (default: true) */\n\tincludeUptime?: boolean;\n\t/** Include version in response */\n\tversion?: string;\n}\n\nexport interface HealthStatus {\n\tstatus: \"healthy\" | \"unhealthy\" | \"degraded\";\n\tmessage?: string;\n\tchecks?: Record<\n\t\tstring,\n\t\t{ status: string; message?: string; duration?: number }\n\t>;\n}\n\nconst startTime = Date.now();\n\n/**\n * Register health check endpoint on the app\n */\nexport function healthCheck(app: AnyApp, options: HealthCheckOptions = {}) {\n\tconst path = options.path || \"/health\";\n\n\tapp.get(path, async (ctx: Context) => {\n\t\ttry {\n\t\t\t// Run custom health check if provided\n\t\t\tlet healthStatus: HealthStatus = { status: \"healthy\" };\n\n\t\t\tif (options.check) {\n\t\t\t\thealthStatus = await options.check();\n\t\t\t}\n\n\t\t\tconst response: Record<string, unknown> = {\n\t\t\t\t...healthStatus,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\tuptime:\n\t\t\t\t\toptions.includeUptime !== false\n\t\t\t\t\t\t? Math.floor((Date.now() - startTime) / 1000)\n\t\t\t\t\t\t: undefined,\n\t\t\t\tversion: options.version,\n\t\t\t};\n\n\t\t\t// Clean up undefined values\n\t\t\tObject.keys(response).forEach((key) => {\n\t\t\t\tif (response[key] === undefined) {\n\t\t\t\t\tdelete response[key];\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst statusCode = healthStatus.status === \"healthy\" ? 200 : 503;\n\t\t\treturn ctx.json(response, statusCode);\n\t\t} catch (_error) {\n\t\t\treturn ctx.json(\n\t\t\t\t{\n\t\t\t\t\tstatus: \"unhealthy\",\n\t\t\t\t\terror: \"Unknown error\",\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t},\n\t\t\t\t503,\n\t\t\t);\n\t\t}\n\t});\n}\n\n/**\n * Create a database health check function\n */\nexport function createDatabaseCheck(\n\tcheckFn: () => Promise<boolean>,\n): () => Promise<HealthStatus> {\n\treturn async () => {\n\t\tconst start = performance.now();\n\t\ttry {\n\t\t\tconst isHealthy = await checkFn();\n\t\t\tconst duration = performance.now() - start;\n\n\t\t\treturn {\n\t\t\t\tstatus: isHealthy ? \"healthy\" : \"unhealthy\",\n\t\t\t\tchecks: {\n\t\t\t\t\tdatabase: {\n\t\t\t\t\t\tstatus: isHealthy ? \"up\" : \"down\",\n\t\t\t\t\t\tduration: Math.round(duration),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tstatus: \"unhealthy\",\n\t\t\t\tchecks: {\n\t\t\t\t\tdatabase: {\n\t\t\t\t\t\tstatus: \"down\",\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\terror instanceof Error ? error.message : \"Connection failed\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t};\n}\n\n/**\n * Create a combined health check function\n */\nexport function createHealthCheck(\n\tchecks: Array<{ name: string; check: () => Promise<boolean> }>,\n): () => Promise<HealthStatus> {\n\treturn async () => {\n\t\tconst results: Record<string, { status: string; duration?: number }> = {};\n\t\tlet overallStatus: \"healthy\" | \"unhealthy\" | \"degraded\" = \"healthy\";\n\n\t\tfor (const { name, check } of checks) {\n\t\t\tconst start = performance.now();\n\t\t\ttry {\n\t\t\t\tconst isHealthy = await check();\n\t\t\t\tconst duration = performance.now() - start;\n\n\t\t\t\tresults[name] = {\n\t\t\t\t\tstatus: isHealthy ? \"up\" : \"down\",\n\t\t\t\t\tduration: Math.round(duration),\n\t\t\t\t};\n\n\t\t\t\tif (!isHealthy) {\n\t\t\t\t\toverallStatus = \"unhealthy\";\n\t\t\t\t}\n\t\t\t} catch (_error) {\n\t\t\t\tresults[name] = {\n\t\t\t\t\tstatus: \"down\",\n\t\t\t\t};\n\t\t\t\toverallStatus = \"unhealthy\";\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tstatus: overallStatus,\n\t\t\tchecks: results,\n\t\t};\n\t};\n}\n","import type { Middleware } from \"../app\";\n\nexport interface HelmetOptions {\n\t/** X-Content-Type-Options (default: \"nosniff\") */\n\tcontentTypeOptions?: string;\n\t/** X-Frame-Options (default: \"DENY\") */\n\tframeOptions?: string;\n\t/** X-XSS-Protection (default: \"0\") */\n\txssProtection?: string;\n\t/** Referrer-Policy (default: \"no-referrer\") */\n\treferrerPolicy?: string;\n\t/** Strict-Transport-Security (default: \"max-age=31536000; includeSubDomains\") */\n\thsts?: string;\n\t/** X-DNS-Prefetch-Control (default: \"on\") */\n\tdnsPrefetch?: string;\n\t/** Permissions-Policy (default: \"camera=(), microphone=(), geolocation=()\") */\n\tpermissionsPolicy?: string;\n\t/** Custom headers to add */\n\tadditionalHeaders?: Record<string, string>;\n}\n\nconst DEFAULT_HEADERS: Record<string, string> = {\n\t\"X-Content-Type-Options\": \"nosniff\",\n\t\"X-Frame-Options\": \"DENY\",\n\t\"X-XSS-Protection\": \"0\",\n\t\"Referrer-Policy\": \"no-referrer\",\n\t\"Strict-Transport-Security\": \"max-age=31536000; includeSubDomains\",\n\t\"X-DNS-Prefetch-Control\": \"on\",\n\t\"Permissions-Policy\": \"camera=(), microphone=(), geolocation=()\",\n};\n\n/**\n * Security headers middleware - adds common security headers to all responses.\n *\n * @example\n * import { helmet } from \"@buntok/core\";\n *\n * // Default - all standard headers\n * app.use(helmet());\n *\n * // Custom options\n * app.use(helmet({\n *   frameOptions: \"SAMEORIGIN\",\n *   hsts: \"max-age=63072000\",\n * }));\n */\nexport function helmet(options?: HelmetOptions): Middleware {\n\tconst headers: Record<string, string> = { ...DEFAULT_HEADERS };\n\n\tif (options?.contentTypeOptions)\n\t\theaders[\"X-Content-Type-Options\"] = options.contentTypeOptions;\n\tif (options?.frameOptions) headers[\"X-Frame-Options\"] = options.frameOptions;\n\tif (options?.xssProtection)\n\t\theaders[\"X-XSS-Protection\"] = options.xssProtection;\n\tif (options?.referrerPolicy)\n\t\theaders[\"Referrer-Policy\"] = options.referrerPolicy;\n\tif (options?.hsts) headers[\"Strict-Transport-Security\"] = options.hsts;\n\tif (options?.dnsPrefetch)\n\t\theaders[\"X-DNS-Prefetch-Control\"] = options.dnsPrefetch;\n\tif (options?.permissionsPolicy)\n\t\theaders[\"Permissions-Policy\"] = options.permissionsPolicy;\n\tif (options?.additionalHeaders)\n\t\tObject.assign(headers, options.additionalHeaders);\n\n\treturn async (_ctx, next) => {\n\t\tconst response = await next();\n\t\t// Set headers directly on the response - avoids copying Headers + creating new Response\n\t\tfor (const [key, value] of Object.entries(headers)) {\n\t\t\tif (!response.headers.has(key)) {\n\t\t\t\tresponse.headers.set(key, value);\n\t\t\t}\n\t\t}\n\t\treturn response;\n\t};\n}\n","import type { Middleware } from \"../app\";\nimport type { Context } from \"../context\";\n\nexport interface RateLimiterOptions {\n\t/** Maximum requests per window */\n\tmax?: number;\n\t/** Window duration in milliseconds (default: 60000 = 1 minute) */\n\twindowMs?: number;\n\t/** Custom key function (default: IP address) */\n\tkeyGenerator?: (ctx: Context) => string;\n\t/** Custom message when rate limit exceeded */\n\tmessage?: string;\n\t/** HTTP status code when rate limit exceeded (default: 429) */\n\tstatusCode?: number;\n\t/** Skip rate limiting for certain requests */\n\tskip?: (ctx: Context) => boolean;\n\t/** Headers to include in response */\n\theaders?: boolean;\n\t/**\n\t * Where counters are stored. Defaults to an in-memory Map, which is lost\n\t * on restart and not shared across processes/instances. Pass\n\t * `sqliteStore(path)` to persist counters in a bun:sqlite database instead\n\t * (e.g. shared across a clustered deployment via a shared file, or simply\n\t * to survive restarts without adding an external dependency like Redis).\n\t */\n\tstore?: RateLimitStore<unknown>;\n}\n\ninterface RateLimitEntry {\n\tcount: number;\n\tresetTime: number;\n}\n\n/**\n * Minimal Map-like interface the rate limiters need. Implemented by both the\n * default in-memory store and the optional bun:sqlite-backed store below.\n */\nexport interface RateLimitStore<T> {\n\tget(key: string): T | undefined;\n\tset(key: string, value: T): void;\n\tdelete(key: string): void;\n\tentries(): IterableIterator<[string, T]>;\n}\n\nfunction memoryStore<T>(): RateLimitStore<T> {\n\treturn new Map<string, T>();\n}\n\n/**\n * Persist rate-limit counters in a bun:sqlite database file instead of an\n * in-memory Map. Useful when you want counters to survive process restarts,\n * or to be shared across multiple instances pointed at the same file, without\n * pulling in an external dependency like Redis.\n *\n * Requires the Bun runtime (uses `bun:sqlite`).\n */\nexport function sqliteStore<T>(\n\tpath = \"rate-limiter.sqlite\",\n): RateLimitStore<T> {\n\tconst { Database } = require(\"bun:sqlite\") as typeof import(\"bun:sqlite\");\n\tconst db = new Database(path);\n\tdb.run(\n\t\t\"CREATE TABLE IF NOT EXISTS rate_limit_entries (key TEXT PRIMARY KEY, value TEXT NOT NULL)\",\n\t);\n\n\tconst getStmt = db.query(\n\t\t\"SELECT value FROM rate_limit_entries WHERE key = ?\",\n\t);\n\tconst setStmt = db.query(\n\t\t\"INSERT INTO rate_limit_entries (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value\",\n\t);\n\tconst deleteStmt = db.query(\"DELETE FROM rate_limit_entries WHERE key = ?\");\n\tconst allStmt = db.query(\"SELECT key, value FROM rate_limit_entries\");\n\n\treturn {\n\t\tget(key: string): T | undefined {\n\t\t\tconst row = getStmt.get(key) as { value: string } | null;\n\t\t\treturn row ? (JSON.parse(row.value) as T) : undefined;\n\t\t},\n\t\tset(key: string, value: T): void {\n\t\t\tsetStmt.run(key, JSON.stringify(value));\n\t\t},\n\t\tdelete(key: string): void {\n\t\t\tdeleteStmt.run(key);\n\t\t},\n\t\t*entries(): IterableIterator<[string, T]> {\n\t\t\tconst rows = allStmt.all() as Array<{ key: string; value: string }>;\n\t\t\tfor (const row of rows) {\n\t\t\t\tyield [row.key, JSON.parse(row.value) as T];\n\t\t\t}\n\t\t},\n\t};\n}\n\nconst DEFAULT_OPTIONS: Required<\n\tOmit<RateLimiterOptions, \"keyGenerator\" | \"skip\" | \"store\">\n> = {\n\tmax: 100,\n\twindowMs: 60000,\n\tmessage: \"Too many requests, please try again later\",\n\tstatusCode: 429,\n\theaders: true,\n};\n\n/**\n * Simple in-memory rate limiter\n */\nexport function rateLimiter(options: RateLimiterOptions = {}): Middleware {\n\tconst opts = { ...DEFAULT_OPTIONS, ...options };\n\tconst store =\n\t\t(options.store as RateLimitStore<RateLimitEntry>) ??\n\t\tmemoryStore<RateLimitEntry>();\n\n\t// Cleanup old entries periodically\n\tconst cleanup = setInterval(() => {\n\t\tconst now = Date.now();\n\t\tfor (const [key, entry] of store.entries()) {\n\t\t\tif (now > entry.resetTime) {\n\t\t\t\tstore.delete(key);\n\t\t\t}\n\t\t}\n\t}, opts.windowMs);\n\n\t// Prevent cleanup from keeping process alive\n\tif (typeof cleanup === \"object\" && cleanup.unref) {\n\t\tcleanup.unref();\n\t}\n\n\tconst getKey =\n\t\toptions.keyGenerator ||\n\t\t((ctx: Context) => {\n\t\t\treturn (\n\t\t\t\tctx.request.headers.get(\"x-forwarded-for\")?.split(\",\")[0]?.trim() ||\n\t\t\t\tctx.request.headers.get(\"x-real-ip\") ||\n\t\t\t\t\"unknown\"\n\t\t\t);\n\t\t});\n\n\treturn async (ctx, next) => {\n\t\t// Skip if custom skip function returns true\n\t\tif (options.skip?.(ctx)) {\n\t\t\treturn next();\n\t\t}\n\n\t\tconst key = getKey(ctx);\n\t\tconst now = Date.now();\n\t\tconst entry = store.get(key);\n\n\t\tlet count = 1;\n\t\tlet resetTime = now + opts.windowMs;\n\n\t\tif (entry && now < entry.resetTime) {\n\t\t\tcount = entry.count + 1;\n\t\t\tresetTime = entry.resetTime;\n\t\t}\n\n\t\tstore.set(key, { count, resetTime });\n\n\t\t// Check if rate limit exceeded\n\t\tif (count > opts.max) {\n\t\t\tconst response = new Response(JSON.stringify({ error: opts.message }), {\n\t\t\t\tstatus: opts.statusCode,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\"Retry-After\": String(Math.ceil((resetTime - now) / 1000)),\n\t\t\t\t\t\"X-RateLimit-Limit\": String(opts.max),\n\t\t\t\t\t\"X-RateLimit-Remaining\": \"0\",\n\t\t\t\t\t\"X-RateLimit-Reset\": String(Math.ceil(resetTime / 1000)),\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn response;\n\t\t}\n\n\t\tconst result = await next();\n\n\t\t// Add rate limit headers to successful response\n\t\tif (opts.headers && result instanceof Response) {\n\t\t\tresult.headers.set(\"X-RateLimit-Limit\", String(opts.max));\n\t\t\tresult.headers.set(\n\t\t\t\t\"X-RateLimit-Remaining\",\n\t\t\t\tString(Math.max(0, opts.max - count)),\n\t\t\t);\n\t\t\tresult.headers.set(\n\t\t\t\t\"X-RateLimit-Reset\",\n\t\t\t\tString(Math.ceil(resetTime / 1000)),\n\t\t\t);\n\t\t}\n\n\t\treturn result;\n\t};\n}\n\n/**\n * Sliding window rate limiter (more accurate but uses more memory)\n */\nexport function slidingWindowRateLimiter(\n\toptions: RateLimiterOptions = {},\n): Middleware {\n\tconst opts = { ...DEFAULT_OPTIONS, ...options };\n\tconst store =\n\t\t(options.store as RateLimitStore<number[]>) ?? memoryStore<number[]>();\n\n\tconst cleanup = setInterval(() => {\n\t\tconst windowStart = Date.now() - opts.windowMs;\n\t\tfor (const [key, timestamps] of store.entries()) {\n\t\t\tconst valid = timestamps.filter((t) => t > windowStart);\n\t\t\tif (valid.length === 0) {\n\t\t\t\tstore.delete(key);\n\t\t\t} else if (valid.length !== timestamps.length) {\n\t\t\t\tstore.set(key, valid);\n\t\t\t}\n\t\t}\n\t}, opts.windowMs);\n\n\tif (typeof cleanup === \"object\" && cleanup.unref) {\n\t\tcleanup.unref();\n\t}\n\n\tconst getKey =\n\t\toptions.keyGenerator ||\n\t\t((ctx: Context) => {\n\t\t\treturn (\n\t\t\t\tctx.request.headers.get(\"x-forwarded-for\")?.split(\",\")[0]?.trim() ||\n\t\t\t\tctx.request.headers.get(\"x-real-ip\") ||\n\t\t\t\t\"unknown\"\n\t\t\t);\n\t\t});\n\n\treturn async (ctx, next) => {\n\t\tif (options.skip?.(ctx)) {\n\t\t\treturn next();\n\t\t}\n\n\t\tconst key = getKey(ctx);\n\t\tconst now = Date.now();\n\t\tconst windowStart = now - opts.windowMs;\n\n\t\t// Get existing timestamps\n\t\tconst timestamps = store.get(key) || [];\n\n\t\t// Filter to only timestamps within window\n\t\tconst validTimestamps = timestamps.filter((t) => t > windowStart);\n\n\t\tif (validTimestamps.length >= opts.max) {\n\t\t\tconst oldestTimestamp = validTimestamps[0] || 0;\n\t\t\tconst retryAfter = Math.ceil(\n\t\t\t\t(oldestTimestamp + opts.windowMs - now) / 1000,\n\t\t\t);\n\n\t\t\treturn new Response(JSON.stringify({ error: opts.message }), {\n\t\t\t\tstatus: opts.statusCode,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\"Retry-After\": String(retryAfter),\n\t\t\t\t\t\"X-RateLimit-Limit\": String(opts.max),\n\t\t\t\t\t\"X-RateLimit-Remaining\": \"0\",\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\t// Add current timestamp\n\t\tvalidTimestamps.push(now);\n\t\tstore.set(key, validTimestamps);\n\n\t\tconst result = await next();\n\n\t\tif (result instanceof Response) {\n\t\t\tresult.headers.set(\"X-RateLimit-Limit\", String(opts.max));\n\t\t\tresult.headers.set(\n\t\t\t\t\"X-RateLimit-Remaining\",\n\t\t\t\tString(opts.max - validTimestamps.length),\n\t\t\t);\n\t\t}\n\n\t\treturn result;\n\t};\n}\n","import type { Middleware } from \"../app\";\n\nexport interface RequestIdOptions {\n\t/** Header name (default: x-request-id) */\n\theader?: string;\n\t/** Custom generator function */\n\tgenerator?: () => string;\n\t/** Store request ID in ctx.store (default: true) */\n\tstore?: boolean;\n\t/** Property name in ctx.store (default: requestId) */\n\tstoreKey?: string;\n}\n\n/**\n * Generate a unique request ID\n */\nfunction generateRequestId(): string {\n\treturn crypto.randomUUID();\n}\n\n/**\n * Middleware to add unique request ID to every request\n */\nexport function requestId(options: RequestIdOptions = {}): Middleware {\n\tconst header = options.header || \"x-request-id\";\n\tconst storeKey = options.storeKey || \"requestId\";\n\tconst generator = options.generator || generateRequestId;\n\tconst useStore = options.store !== false;\n\n\treturn async (ctx, next) => {\n\t\t// Check for existing request ID (from upstream proxy)\n\t\tconst existingId = ctx.request.headers.get(header);\n\t\tconst id = existingId || generator();\n\n\t\t// Store in ctx.store if enabled\n\t\tif (useStore) {\n\t\t\tctx.store[storeKey] = id;\n\t\t}\n\n\t\tconst result = await next();\n\n\t\t// Add request ID to response headers\n\t\tif (result instanceof Response) {\n\t\t\tresult.headers.set(header, id);\n\t\t}\n\n\t\treturn result;\n\t};\n}\n\n/**\n * Simple UUID v4 generator (no dependencies)\n */\nexport function uuid(): string {\n\treturn \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n\t\tconst r = (Math.random() * 16) | 0;\n\t\tconst v = c === \"x\" ? r : (r & 0x3) | 0x8;\n\t\treturn v.toString(16);\n\t});\n}\n\n/**\n * Short ID generator (8 characters)\n */\nexport function shortId(): string {\n\treturn crypto.randomUUID().replace(/-/g, \"\").slice(0, 8);\n}\n","import type { Middleware } from \"../app\";\n\nexport interface ResponseTimeOptions {\n\t/** Header name (default: x-response-time) */\n\theader?: string;\n\t/** Format: 'ms' | 's' (default: 'ms') */\n\tformat?: \"ms\" | \"s\";\n\t/** Store response time in ctx.store (default: false) */\n\tstore?: boolean;\n\t/** Property name in ctx.store (default: responseTime) */\n\tstoreKey?: string;\n}\n\n/**\n * Middleware to measure and add response time to response headers\n */\nexport function responseTime(options: ResponseTimeOptions = {}): Middleware {\n\tconst header = options.header || \"x-response-time\";\n\tconst format = options.format || \"ms\";\n\tconst storeKey = options.storeKey || \"responseTime\";\n\n\treturn async (ctx, next) => {\n\t\tconst start = performance.now();\n\n\t\tconst result = await next();\n\n\t\tconst duration = performance.now() - start;\n\t\tconst formatted =\n\t\t\tformat === \"s\"\n\t\t\t\t? `${(duration / 1000).toFixed(3)}s`\n\t\t\t\t: `${duration.toFixed(2)}ms`;\n\n\t\t// Store in ctx.store if enabled\n\t\tif (options.store) {\n\t\t\tctx.store[storeKey] = formatted;\n\t\t}\n\n\t\t// Add response time header\n\t\tif (result instanceof Response) {\n\t\t\tresult.headers.set(header, formatted);\n\t\t}\n\n\t\treturn result;\n\t};\n}\n","import type { Middleware } from \"../app\";\n\n/**\n * Request timeout middleware - automatically aborts the handler if it takes\n * longer than `ms` milliseconds, returning 408 Request Timeout.\n *\n * @example\n * import { timeout } from \"@buntok/core\";\n *\n * app.get(\"/slow\", timeout(5000), async (ctx) => {\n *   await longOperation();\n *   return ctx.json({ ok: true });\n * });\n *\n * // Custom error message\n * app.post(\"/upload\", timeout(30000, \"Upload timed out\"), handler);\n */\nexport function timeout(ms: number, message = \"Request timed out\"): Middleware {\n\treturn async (_ctx, next) => {\n\t\t// Industrial: skip timeout for SSE - SSE adalah long-lived, timeout akan bunuh koneksi 30s heartbeat\n\t\tif (_ctx.request.headers.get(\"accept\")?.includes(\"text/event-stream\")) return next();\n\t\tlet timeoutId: ReturnType<typeof setTimeout>;\n\n\t\tconst timeoutPromise = new Promise<never>((_, reject) => {\n\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\treject(new TimeoutError(message, ms));\n\t\t\t}, ms);\n\t\t});\n\n\t\ttry {\n\t\t\tconst response = await Promise.race([next(), timeoutPromise]);\n\t\t\treturn response;\n\t\t} finally {\n\t\t\tclearTimeout(timeoutId!);\n\t\t}\n\t};\n}\n\nexport class TimeoutError extends Error {\n\tpublic readonly timeoutMs: number;\n\n\tconstructor(message: string, timeoutMs: number) {\n\t\tsuper(message);\n\t\tthis.name = \"TimeoutError\";\n\t\tthis.timeoutMs = timeoutMs;\n\t}\n}\n","/**\n * Role-Based Access Control (RBAC) middleware.\n *\n * @example\n * ```ts\n * import { requireRole, requirePermission } from \"buntok\";\n *\n * // Require specific role\n * app.get(\"/admin\", requireAuth(secret), requireRole(\"admin\"), adminHandler);\n *\n * // Require any of multiple roles\n * app.get(\"/mod\", requireAuth(secret), requireRole(\"admin\", \"moderator\"), modHandler);\n *\n * // Require specific permission\n * app.delete(\"/users/:id\", requireAuth(secret), requirePermission(\"users:delete\"), deleteUser);\n *\n * // Custom role resolver\n * app.use(requireRole({\n *   resolver: (user) => user.roles,  // extract roles from JWT payload\n *   roles: [\"admin\"],\n * }));\n * ```\n */\n\ntype UserWithRoles = {\n\trole?: string;\n\troles?: string[];\n\t[key: string]: any;\n};\n\nexport interface RequireRoleOptions {\n\t/** Extract roles from user object. Default: (user) => user.role || user.roles */\n\tresolver?: (user: any) => string | string[] | undefined;\n\n\t/** Required roles (user must have at least one) */\n\troles: string[];\n\n\t/** Custom error message */\n\tmessage?: string;\n}\n\n/**\n * Middleware that requires the user to have at least one of the specified roles.\n * Must be used AFTER requireAuth middleware.\n */\nexport function requireRole(\n\t...roles: string[]\n): (ctx: any, next: () => Promise<Response> | Response) => Promise<Response> | Response;\nexport function requireRole(\n\toptions: RequireRoleOptions,\n): (ctx: any, next: () => Promise<Response> | Response) => Promise<Response> | Response;\nexport function requireRole(\n\t...args: any[]\n): (ctx: any, next: () => Promise<Response> | Response) => Promise<Response> | Response {\n\t// Parse arguments\n\tlet options: RequireRoleOptions;\n\tif (args.length === 1 && typeof args[0] === \"object\" && !Array.isArray(args[0])) {\n\t\toptions = args[0];\n\t} else {\n\t\toptions = { roles: args.flat() };\n\t}\n\n\tconst { roles: requiredRoles, resolver, message } = options;\n\n\treturn async (ctx, next) => {\n\t\tconst user = ctx.user as UserWithRoles | undefined;\n\n\t\tif (!user) {\n\t\t\treturn ctx.json({ success: false, message: \"Authentication required\" }, 401);\n\t\t}\n\n\t\t// Resolve user roles\n\t\tlet userRoles: string[];\n\t\tif (resolver) {\n\t\t\tconst resolved = resolver(user);\n\t\t\tuserRoles = Array.isArray(resolved) ? resolved : resolved ? [resolved] : [];\n\t\t} else {\n\t\t\tuserRoles = [];\n\t\t\tif (user.role) userRoles.push(user.role);\n\t\t\tif (user.roles) userRoles.push(...user.roles);\n\t\t}\n\n\t\t// Check if user has any required role\n\t\tconst hasRole = requiredRoles.some((r) => userRoles.includes(r));\n\n\t\tif (!hasRole) {\n\t\t\treturn ctx.json({\n\t\t\t\tsuccess: false,\n\t\t\t\terror: \"Forbidden\",\n\t\t\t\tmessage: message ?? `Requires one of: ${requiredRoles.join(\", \")}`,\n\t\t\t}, 403);\n\t\t}\n\n\t\treturn next();\n\t};\n}\n\nexport interface RequirePermissionOptions {\n\t/** Extract permissions from user object. Default: (user) => user.permissions */\n\tresolver?: (user: any) => string[] | undefined;\n\n\t/** Required permissions (user must have ALL) */\n\tpermissions: string[];\n\n\t/** Custom error message */\n\tmessage?: string;\n}\n\n/**\n * Middleware that requires the user to have ALL specified permissions.\n * Must be used AFTER requireAuth middleware.\n */\nexport function requirePermission(\n\t...permissions: string[]\n): (ctx: any, next: () => Promise<Response> | Response) => Promise<Response> | Response;\nexport function requirePermission(\n\toptions: RequirePermissionOptions,\n): (ctx: any, next: () => Promise<Response> | Response) => Promise<Response> | Response;\nexport function requirePermission(\n\t...args: any[]\n): (ctx: any, next: () => Promise<Response> | Response) => Promise<Response> | Response {\n\tlet options: RequirePermissionOptions;\n\tif (args.length === 1 && typeof args[0] === \"object\" && !Array.isArray(args[0])) {\n\t\toptions = args[0];\n\t} else {\n\t\toptions = { permissions: args.flat() };\n\t}\n\n\tconst { permissions: requiredPermissions, resolver, message } = options;\n\n\treturn async (ctx, next) => {\n\t\tconst user = ctx.user as UserWithRoles | undefined;\n\n\t\tif (!user) {\n\t\t\treturn ctx.json({ success: false, message: \"Authentication required\" }, 401);\n\t\t}\n\n\t\t// Resolve user permissions\n\t\tlet userPermissions: string[];\n\t\tif (resolver) {\n\t\t\tuserPermissions = resolver(user) ?? [];\n\t\t} else {\n\t\t\tuserPermissions = (user as any).permissions ?? [];\n\t\t}\n\n\t\t// Check if user has all required permissions\n\t\tconst hasAll = requiredPermissions.every((p) => userPermissions.includes(p));\n\n\t\tif (!hasAll) {\n\t\t\tconst missing = requiredPermissions.filter((p) => !userPermissions.includes(p));\n\t\t\treturn ctx.json({\n\t\t\t\tsuccess: false,\n\t\t\t\terror: \"Forbidden\",\n\t\t\t\tmessage: message ?? `Missing permissions: ${missing.join(\", \")}`,\n\t\t\t}, 403);\n\t\t}\n\n\t\treturn next();\n\t};\n}\n","import { z } from \"zod\";\nimport type { Middleware } from \"../app\";\n\nexport interface ValidatorSchema {\n\tparse: (data: unknown) => unknown;\n}\n\nexport interface ValidateOptions {\n\tbody?: ValidatorSchema;\n\tparams?: ValidatorSchema;\n}\n\n/** @deprecated Prefer `zValidator()`, which gives you `ctx.valid()` with full type inference. */\nexport const validate = (schemas: ValidateOptions): Middleware => {\n\treturn async (ctx, next) => {\n\t\tconst errors: string[] = [];\n\n\t\tif (schemas.body) {\n\t\t\ttry {\n\t\t\t\tconst bodyData = await ctx.body();\n\t\t\t\tctx.store.validatedBody = schemas.body.parse(bodyData);\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : \"Invalid body\";\n\t\t\t\terrors.push(`body: ${message}`);\n\t\t\t}\n\t\t}\n\n\t\tif (schemas.params) {\n\t\t\ttry {\n\t\t\t\tctx.store.validatedParams = schemas.params.parse(ctx.params);\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconst message = err instanceof Error ? err.message : \"Invalid params\";\n\t\t\t\terrors.push(`params: ${message}`);\n\t\t\t}\n\t\t}\n\n\t\tif (errors.length > 0) {\n\t\t\treturn ctx.json(\n\t\t\t\t{\n\t\t\t\t\terror: \"Validation Failed\",\n\t\t\t\t\tdetails: errors,\n\t\t\t\t},\n\t\t\t\t400,\n\t\t\t);\n\t\t}\n\n\t\treturn next();\n\t};\n};\n\n/** @deprecated Prefer `zValidator(\"body\", schema)`. */\nexport const validateBody = (schema: ValidatorSchema): Middleware => {\n\treturn validate({ body: schema });\n};\n\n/** @deprecated Prefer `zValidator(\"params\", schema)`. */\nexport const validateParams = (schema: ValidatorSchema): Middleware => {\n\treturn validate({ params: schema });\n};\n\nexport type ValidationTarget = \"body\" | \"query\" | \"params\";\n\n/**\n * Content types supported by `zValidator(\"body\", schema, { contentType })`.\n * Defaults to `application/json` when `contentType` is omitted.\n */\nexport type BodyContentType =\n\t/**\n\t * Standard JSON body - default behavior when `contentType` is omitted.\n\t *\n\t * Parsed via `JSON.parse`. Zod schema receives the parsed JavaScript object.\n\t *\n\t * @example\n\t * zValidator(\"body\", z.object({ name: z.string() }))\n\t * // equivalent to: { contentType: \"application/json\" }\n\t */\n\t| \"application/json\"\n\t/**\n\t * Parse fields from `multipart/form-data`.\n\t * Supports both text fields (as strings) and file fields (as File objects).\n\t * Validate file fields using `z.file()` (requires Zod v4+).\n\t *\n\t * Zod schema receives `Record<string, string | File>`. of all non-file fields.\n\t *\n\t * @example\n\t * zValidator(\"body\", z.object({ name: z.string() }), { contentType: \"multipart/form-data\" })\n\t */\n\t| \"multipart/form-data\"\n\t/**\n\t * Parse fields from an `application/x-www-form-urlencoded` body.\n\t * All values are strings - use `z.coerce.number()`, `z.coerce.boolean()`, etc. for coercion.\n\t *\n\t * Zod schema receives `Record<string, string>`.\n\t *\n\t * @example\n\t * zValidator(\"body\", z.object({ email: z.string().email(), age: z.coerce.number() }), {\n\t *   contentType: \"application/x-www-form-urlencoded\",\n\t * })\n\t */\n\t| \"application/x-www-form-urlencoded\"\n\t/**\n\t * Parse a plain text body.\n\t * Zod schema receives the raw body as a `string`.\n\t *\n\t * @example\n\t * zValidator(\"body\", z.string().min(1), { contentType: \"text/plain\" })\n\t */\n\t| \"text/plain\"\n\t/**\n\t * Parse an XML body (W3C standard MIME type).\n\t * Zod schema receives the raw XML as a `string` - parse it further with your preferred XML library.\n\t *\n\t * @example\n\t * zValidator(\"body\", z.string(), { contentType: \"application/xml\" })\n\t */\n\t| \"application/xml\"\n\t/**\n\t * Parse an XML body (legacy/vendor MIME type, functionally identical to `application/xml`).\n\t * Zod schema receives the raw XML as a `string`.\n\t *\n\t * @example\n\t * zValidator(\"body\", z.string(), { contentType: \"text/xml\" })\n\t */\n\t| \"text/xml\"\n\t/**\n\t * Parse a raw binary body.\n\t * Zod schema receives an `ArrayBuffer` - use `z.instanceof(ArrayBuffer)` or process it manually.\n\t *\n\t * @example\n\t * zValidator(\"body\", z.instanceof(ArrayBuffer), { contentType: \"application/octet-stream\" })\n\t */\n\t| \"application/octet-stream\";\n\nexport interface ZValidatorOptions {\n\t/**\n\t * Override the expected request body content type.\n\t * Only applies when `target` is `\"body\"`. Defaults to `application/json`.\n\t *\n\t * - `\"multipart/form-data\"` - text and file fields from FormData; validate files with `z.file()`\n\t * - `\"application/x-www-form-urlencoded\"` - URL-encoded key=value body\n\t *\n\t * Omit this option (or the entire `options` argument) for standard JSON bodies.\n\t */\n\tcontentType?: BodyContentType;\n}\n\nexport type SchemaType = z.ZodType | Record<string, z.ZodTypeAny>;\n\nfunction wrapSchema(schema: SchemaType): z.ZodType {\n\t// biome-ignore lint/suspicious/noExplicitAny: Required to check internal Zod fields\n\treturn schema instanceof z.ZodType || (schema as any)?._def\n\t\t? (schema as z.ZodType)\n\t\t: z.object(schema as Record<string, z.ZodTypeAny>);\n}\n\n/**\n * Validate request body/query/params against a Zod schema and expose the\n * parsed, typed result via `ctx.valid(target)` - no manual casting needed.\n *\n * ```ts\n * const schema = z.object({ name: z.string(), age: z.number() });\n *\n * // JSON body (default)\n * app.post(\"/users\", zValidator(\"body\", schema), (ctx) => {\n *   const data = ctx.valid<z.infer<typeof schema>>(\"body\");\n *   return ctx.json(data);\n * });\n *\n * // multipart/form-data text fields (pair with uploader() for files)\n * app.post(\"/profile\", zValidator(\"body\", schema, { contentType: \"multipart/form-data\" }), ...);\n *\n * // application/x-www-form-urlencoded\n * app.post(\"/login\", zValidator(\"body\", schema, { contentType: \"application/x-www-form-urlencoded\" }), ...);\n * ```\n *\n * On failure, responds with 422 and structured error details.\n */\nexport function zValidator(\n\ttarget: ValidationTarget,\n\tschema: SchemaType | (new () => unknown),\n\toptions?: ZValidatorOptions,\n): Middleware {\n\tconst finalSchema = wrapSchema(schema as SchemaType);\n\tconst resolvedContentType: BodyContentType =\n\t\toptions?.contentType ?? \"application/json\";\n\n\tconst middleware: Middleware = async (ctx, next) => {\n\t\tlet raw: unknown;\n\n\t\tif (target === \"body\") {\n\t\t\tif (resolvedContentType === \"multipart/form-data\") {\n\t\t\t\t// Parse both text and file fields from multipart/form-data\n\t\t\t\tconst ct = ctx.request.headers.get(\"content-type\") || \"\";\n\t\t\t\tif (!ct.includes(\"multipart/form-data\")) {\n\t\t\t\t\treturn ctx.error(\"Validation Failed\", 422, [\n\t\t\t\t\t\t{ field: \"content-type\", message: \"expected multipart/form-data content-type\" },\n\t\t\t\t\t]);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst formData = await ctx.formData();\n\t\t\t\t\tconst fields: Record<string, string | File> = {};\n\t\t\t\t\tfor (const [key, value] of formData.entries()) {\n\t\t\t\t\t\tif (value instanceof File) {\n\t\t\t\t\t\t\tfields[key] = value;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfields[key] = value.toString();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\traw = fields;\n\t\t\t} catch {\n\t\t\t\treturn ctx.error(\"Validation Failed\", 422, [\n\t\t\t\t\t{ field: \"body\", message: \"failed to parse multipart/form-data\" },\n\t\t\t\t]);\n\t\t\t\t}\n\t\t\t} else if (resolvedContentType === \"application/x-www-form-urlencoded\") {\n\t\t\t\tconst ct = ctx.request.headers.get(\"content-type\") || \"\";\n\t\t\tif (!ct.includes(\"application/x-www-form-urlencoded\")) {\n\t\t\t\treturn ctx.error(\"Validation Failed\", 422, [\n\t\t\t\t\t{ field: \"content-type\", message: \"expected application/x-www-form-urlencoded content-type\" },\n\t\t\t\t]);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst text = await ctx.request.text();\n\t\t\t\t\tconst params = new URLSearchParams(text);\n\t\t\t\t\tconst fields: Record<string, string> = {};\n\t\t\t\t\tfor (const [key, value] of params.entries()) {\n\t\t\t\t\t\tfields[key] = value;\n\t\t\t\t\t}\n\t\t\t\t\traw = fields;\n\t\t\t} catch {\n\t\t\t\treturn ctx.error(\"Validation Failed\", 422, [\n\t\t\t\t\t{ field: \"body\", message: \"failed to parse application/x-www-form-urlencoded\" },\n\t\t\t\t]);\n\t\t\t\t}\n\t\t\t} else if (\n\t\t\t\tresolvedContentType === \"text/plain\" ||\n\t\t\t\tresolvedContentType === \"application/xml\" ||\n\t\t\t\tresolvedContentType === \"text/xml\"\n\t\t\t) {\n\t\t\t\tconst ct = ctx.request.headers.get(\"content-type\") || \"\";\n\t\t\tif (!ct.includes(resolvedContentType)) {\n\t\t\t\treturn ctx.error(\"Validation Failed\", 422, [\n\t\t\t\t\t{ field: \"content-type\", message: `expected ${resolvedContentType} content-type` },\n\t\t\t\t]);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\traw = await ctx.request.text();\n\t\t\t} catch {\n\t\t\t\treturn ctx.error(\"Validation Failed\", 422, [\n\t\t\t\t\t{ field: \"body\", message: `failed to read ${resolvedContentType} body` },\n\t\t\t\t]);\n\t\t\t\t}\n\t\t\t} else if (resolvedContentType === \"application/octet-stream\") {\n\t\t\t\tconst ct = ctx.request.headers.get(\"content-type\") || \"\";\n\t\t\tif (!ct.includes(\"application/octet-stream\")) {\n\t\t\t\treturn ctx.error(\"Validation Failed\", 422, [\n\t\t\t\t\t{ field: \"content-type\", message: \"expected application/octet-stream content-type\" },\n\t\t\t\t]);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\traw = await ctx.request.arrayBuffer();\n\t\t\t} catch {\n\t\t\t\treturn ctx.error(\"Validation Failed\", 422, [\n\t\t\t\t\t{ field: \"body\", message: \"failed to read application/octet-stream body\" },\n\t\t\t\t]);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Default: application/json\n\t\t\t\ttry {\n\t\t\t\t\traw = await ctx.body();\n\t\t\t} catch {\n\t\t\t\treturn ctx.error(\"Validation Failed\", 422, [\n\t\t\t\t\t{ field: \"body\", message: \"invalid JSON\" },\n\t\t\t\t]);\n\t\t\t}\n\t\t\t}\n\t\t} else if (target === \"query\") {\n\t\t\traw = ctx.query;\n\t\t} else {\n\t\t\traw = ctx.params;\n\t\t}\n\n\t\tconst result = finalSchema.safeParse(raw);\n\t\tif (!result.success) {\n\t\t\treturn ctx.error(\n\t\t\t\t\"Validation Failed\",\n\t\t\t\t422,\n\t\t\t\tresult.error.issues.map(\n\t\t\t\t\t(issue) => ({\n\t\t\t\t\t\tfield: issue.path.join(\".\") || target,\n\t\t\t\t\t\tmessage: issue.message,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tctx.setValidated(target, result.data);\n\n\t\treturn next();\n\t};\n\n\t// Attach metadata for OpenAPI generation\n\tconst mwMeta = middleware as unknown as Record<string, unknown>;\n\tmwMeta._isBuntokValidator = true;\n\tmwMeta._target = target;\n\tmwMeta._schema = finalSchema;\n\tmwMeta._contentType = target === \"body\" ? resolvedContentType : \"\";\n\n\treturn middleware;\n}\n\n/**\n * Document the response schema for OpenAPI.\n * Note: Currently this is for documentation purposes only and does not perform runtime response validation.\n */\nexport function zResponse(\n\tstatus: number,\n\tschema: SchemaType | (new () => unknown) | [new () => unknown],\n\tdescription: string = \"Success\",\n): Middleware {\n\tconst finalSchema = wrapSchema(schema as SchemaType);\n\n\t// Wrap in standard Buntok response envelope\n\tconst envelopedSchema = z.object({\n\t\tsuccess: z.boolean(),\n\t\tmessage: z.string(),\n\t\tdata: finalSchema,\n\t});\n\n\tconst middleware: Middleware = async (_ctx, next) => {\n\t\treturn next();\n\t};\n\n\t// Attach metadata for OpenAPI generation\n\tconst mwMeta = middleware as unknown as Record<string, unknown>;\n\tmwMeta._isBuntokResponse = true;\n\tmwMeta._status = status;\n\tmwMeta._schema = envelopedSchema;\n\tmwMeta._description = description;\n\n\treturn middleware;\n}\n","// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type JobHandler<T> = (job: Job<T>) => Promise<void> | void;\n\nexport interface Job<T> {\n\t/** Auto-generated unique identifier */\n\tid: string;\n\t/** Payload passed by the caller */\n\tdata: T;\n\t/** Higher number = processed sooner (default: 0) */\n\tpriority: number;\n\t/** Milliseconds to wait before the job is eligible for processing */\n\tdelay: number;\n\t/** How many times this job has been attempted (0 = first attempt) */\n\tattempt: number;\n\t/** Timestamp when the job was added */\n\tcreatedAt: number;\n}\n\nexport interface QueueOptions {\n\t/**\n\t * Maximum number of retry attempts after the first failure.\n\t * Set to 0 (default) to disable retries.\n\t */\n\tmaxRetries?: number;\n\t/**\n\t * Base delay in milliseconds between retry attempts (default: 1000).\n\t * With `backoff: \"exponential\"` this value is doubled each attempt.\n\t */\n\tretryDelay?: number;\n\t/**\n\t * Retry backoff strategy.\n\t *  - `\"fixed\"` (default) - always waits `retryDelay` ms\n\t *  - `\"exponential\"` - waits `retryDelay * 2^attempt` ms\n\t */\n\tbackoff?: \"fixed\" | \"exponential\";\n}\n\nexport interface QueueDriver<T> {\n\tadd(data: T, opts?: { priority?: number; delay?: number }): Promise<void>;\n\tprocess(handler: JobHandler<T>): void;\n\tsize(): number;\n\tclear(): void;\n}\n\n// ─── Memory Driver ────────────────────────────────────────────────────────────\n\nexport class MemoryQueueDriver<T> implements QueueDriver<T> {\n\tprivate queue: Job<T>[] = [];\n\tprivate isProcessing = false;\n\tprivate handlers: JobHandler<T>[] = [];\n\tprivate readonly opts: Required<QueueOptions>;\n\n\tconstructor(\n\t\tpublic name: string,\n\t\toptions: QueueOptions = {},\n\t) {\n\t\tthis.opts = {\n\t\t\tmaxRetries: options.maxRetries ?? 0,\n\t\t\tretryDelay: options.retryDelay ?? 1000,\n\t\t\tbackoff: options.backoff ?? \"fixed\",\n\t\t};\n\t}\n\n\tprocess(handler: JobHandler<T>) {\n\t\tthis.handlers.push(handler);\n\t\tthis.pump();\n\t}\n\n\tasync add(\n\t\tdata: T,\n\t\topts: { priority?: number; delay?: number } = {},\n\t): Promise<void> {\n\t\tconst job: Job<T> = {\n\t\t\tid: crypto.randomUUID(),\n\t\t\tdata,\n\t\t\tpriority: opts.priority ?? 0,\n\t\t\tdelay: opts.delay ?? 0,\n\t\t\tattempt: 0,\n\t\t\tcreatedAt: Date.now(),\n\t\t};\n\n\t\tif (job.delay > 0) {\n\t\t\t// Schedule for later\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.enqueue(job);\n\t\t\t\tthis.pump();\n\t\t\t}, job.delay);\n\t\t} else {\n\t\t\tthis.enqueue(job);\n\t\t\tthis.pump();\n\t\t}\n\t}\n\n\tprivate enqueue(job: Job<T>): void {\n\t\t// Insert in priority order (higher priority first) using binary search\n\t\tif (job.priority === 0 || this.queue.length === 0) {\n\t\t\tthis.queue.push(job);\n\t\t\treturn;\n\t\t}\n\t\tlet lo = 0;\n\t\tlet hi = this.queue.length;\n\t\twhile (lo < hi) {\n\t\t\tconst mid = (lo + hi) >>> 1;\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: bounds checked\n\t\t\tif (this.queue[mid]!.priority >= job.priority) lo = mid + 1;\n\t\t\telse hi = mid;\n\t\t}\n\t\tthis.queue.splice(lo, 0, job);\n\t}\n\n\tprivate retryDelay(attempt: number): number {\n\t\tif (this.opts.backoff === \"exponential\") {\n\t\t\treturn this.opts.retryDelay * 2 ** attempt;\n\t\t}\n\t\treturn this.opts.retryDelay;\n\t}\n\n\tprivate async pump(): Promise<void> {\n\t\tif (this.isProcessing || this.handlers.length === 0) return;\n\t\tthis.isProcessing = true;\n\n\t\twhile (this.queue.length > 0) {\n\t\t\tconst job = this.queue.shift();\n\t\t\tif (job === undefined) break;\n\n\t\t\tfor (const handler of this.handlers) {\n\t\t\t\ttry {\n\t\t\t\t\tawait handler(job);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst nextAttempt = job.attempt + 1;\n\t\t\t\t\tif (nextAttempt <= this.opts.maxRetries) {\n\t\t\t\t\t\tconst delay = this.retryDelay(job.attempt);\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[Queue:${this.name}] Job ${job.id} failed (attempt ${nextAttempt}/${this.opts.maxRetries + 1}), retrying in ${delay}ms…`,\n\t\t\t\t\t\t\terr,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tthis.enqueue({ ...job, attempt: nextAttempt });\n\t\t\t\t\t\t\tthis.pump();\n\t\t\t\t\t\t}, delay);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t`[Queue:${this.name}] Job ${job.id} permanently failed after ${nextAttempt} attempt(s):`,\n\t\t\t\t\t\t\terr,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Yield to the event loop between jobs to avoid blocking HTTP requests\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 0));\n\t\t}\n\n\t\tthis.isProcessing = false;\n\t}\n\n\t/** Number of jobs currently waiting in the queue */\n\tsize(): number {\n\t\treturn this.queue.length;\n\t}\n\n\t/** Remove all pending jobs from the queue */\n\tclear(): void {\n\t\tthis.queue = [];\n\t}\n}\n\n// ─── Queue (high-level API) ────────────────────────────────────────────────────\n\nexport class Queue<T = unknown> {\n\tprivate driver: QueueDriver<T>;\n\n\tconstructor(\n\t\tpublic name: string,\n\t\tdriverOrOptions?: QueueDriver<T> | QueueOptions,\n\t\toptions?: QueueOptions,\n\t) {\n\t\t// Overloads:\n\t\t//   new Queue(\"email\")\n\t\t//   new Queue(\"email\", { maxRetries: 3 })\n\t\t//   new Queue(\"email\", redisDriver)\n\t\t//   new Queue(\"email\", redisDriver, { maxRetries: 3 })\n\t\tif (\n\t\t\tdriverOrOptions &&\n\t\t\ttypeof (driverOrOptions as QueueDriver<T>).add === \"function\"\n\t\t) {\n\t\t\tthis.driver = driverOrOptions as QueueDriver<T>;\n\t\t} else {\n\t\t\tthis.driver = new MemoryQueueDriver<T>(\n\t\t\t\tname,\n\t\t\t\t(driverOrOptions as QueueOptions) ?? options ?? {},\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Add a job to the queue.\n\t *\n\t * @param data - Job payload\n\t * @param opts.priority - Higher numbers are processed first (default: 0)\n\t * @param opts.delay - Milliseconds to wait before processing (default: 0)\n\t *\n\t * @example\n\t * await emailQueue.add({ to: \"user@example.com\" }, { delay: 5000, priority: 10 });\n\t */\n\tasync add(\n\t\tdata: T,\n\t\topts: { priority?: number; delay?: number } = {},\n\t): Promise<void> {\n\t\treturn this.driver.add(data, opts);\n\t}\n\n\t/**\n\t * Register a handler that processes jobs as they arrive.\n\t * The handler now receives the full `Job<T>` object (not just data),\n\t * so you can inspect `job.id`, `job.attempt`, `job.createdAt`, etc.\n\t *\n\t * @example\n\t * emailQueue.process(async (job) => {\n\t *   console.log(`Attempt ${job.attempt + 1} for job ${job.id}`);\n\t *   await sendEmail(job.data.to, job.data.subject);\n\t * });\n\t */\n\tprocess(handler: JobHandler<T>): void {\n\t\tthis.driver.process(handler);\n\t}\n\n\t/** Number of jobs currently waiting in the queue */\n\tsize(): number {\n\t\treturn this.driver.size();\n\t}\n\n\t/** Remove all pending (not yet started) jobs */\n\tclear(): void {\n\t\tthis.driver.clear();\n\t}\n}\n","// ─── Types ────────────────────────────────────────────────────────────────────\nexport type {\n\tCheckoutResult,\n\tCheckoutStatus,\n\tCreateCheckoutInput,\n\tCreatePaymentLinkInput,\n\tCreateRefundInput,\n\tCreateSubscriptionInput,\n\tLineItem,\n\tPaymentLinkResult,\n\tPaymentOptions,\n\tRefundResult,\n\tRefundStatus,\n\tSubscriptionResult,\n\tSubscriptionStatus,\n\tWebhookEvent,\n\tWebhookEventType,\n} from \"./types\";\n\nexport {\n\tCreateCheckoutInputSchema,\n\tCreatePaymentLinkInputSchema,\n\tCreateRefundInputSchema,\n\tCreateSubscriptionInputSchema,\n\tMoneyAmountSchema,\n} from \"./types\";\n\n// ─── Errors ───────────────────────────────────────────────────────────────────\nexport {\n\tPaymentConfigurationError,\n\tPaymentError,\n\tPaymentIdempotencyError,\n\tPaymentProviderError,\n\tPaymentVerificationError,\n} from \"./errors\";\n\n// ─── Driver Interface ─────────────────────────────────────────────────────────\nexport type { PaymentDriver } from \"./driver\";\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\nexport {\n\tgenerateIdempotencyKey,\n\tnormalizeCheckoutStatus,\n\tnormalizeRefundStatus,\n\tnormalizeSubscriptionStatus,\n} from \"./helpers\";\n\n// ─── Middleware ────────────────────────────────────────────────────────────────\nexport { paymentWebhook } from \"./middleware/webhook\";\nexport type { WebhookMiddlewareOptions } from \"./middleware/webhook\";\n\n// ─── Drivers ──────────────────────────────────────────────────────────────────\nexport { StripeDriver, type StripeDriverConfig } from \"./drivers/stripe\";\nexport { MidtransDriver, type MidtransDriverConfig } from \"./drivers/midtrans\";\nexport { XenditDriver, type XenditDriverConfig } from \"./drivers/xendit\";\nexport { PayPalDriver, type PayPalDriverConfig } from \"./drivers/paypal\";\n\n// ─── Convenience Factory ──────────────────────────────────────────────────────\nimport type { PaymentDriver } from \"./driver\";\nimport type { StripeDriverConfig } from \"./drivers/stripe\";\nimport { StripeDriver } from \"./drivers/stripe\";\nimport type { MidtransDriverConfig } from \"./drivers/midtrans\";\nimport { MidtransDriver } from \"./drivers/midtrans\";\nimport type { XenditDriverConfig } from \"./drivers/xendit\";\nimport { XenditDriver } from \"./drivers/xendit\";\nimport type { PayPalDriverConfig } from \"./drivers/paypal\";\nimport { PayPalDriver } from \"./drivers/paypal\";\n\n/**\n * Create payment drivers with a simple factory API.\n *\n * @example\n * ```ts\n * import { createPayment } from \"@buntok/core\";\n *\n * const stripe = createPayment.stripe({\n *   secretKey: process.env.STRIPE_SECRET_KEY!,\n *   webhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,\n * });\n *\n * const midtrans = createPayment.midtrans({\n *   serverKey: process.env.MIDTRANS_SERVER_KEY!,\n *   isProduction: false,\n * });\n * ```\n */\nexport const createPayment = {\n\tstripe: (config: StripeDriverConfig): PaymentDriver => new StripeDriver(config),\n\tmidtrans: (config: MidtransDriverConfig): PaymentDriver => new MidtransDriver(config),\n\txendit: (config: XenditDriverConfig): PaymentDriver => new XenditDriver(config),\n\tpaypal: (config: PayPalDriverConfig): PaymentDriver => new PayPalDriver(config),\n};\n","import { z } from \"zod\";\n\n// ─── Normalized Status Types ──────────────────────────────────────────────────\n\nexport type CheckoutStatus =\n\t| \"pending\"\n\t| \"processing\"\n\t| \"requires_action\"\n\t| \"completed\"\n\t| \"failed\"\n\t| \"expired\"\n\t| \"cancelled\";\n\nexport type SubscriptionStatus =\n\t| \"active\"\n\t| \"past_due\"\n\t| \"cancelled\"\n\t| \"suspended\"\n\t| \"expired\"\n\t| \"incomplete\";\n\nexport type RefundStatus =\n\t| \"pending\"\n\t| \"completed\"\n\t| \"failed\"\n\t| \"partially_refunded\";\n\nexport type WebhookEventType =\n\t| \"payment.completed\"\n\t| \"payment.failed\"\n\t| \"payment.expired\"\n\t| \"payment.created\"\n\t| \"subscription.created\"\n\t| \"subscription.cancelled\"\n\t| \"subscription.payment_succeeded\"\n\t| \"subscription.payment_failed\"\n\t| \"subscription.suspended\"\n\t| \"refund.completed\"\n\t| \"refund.failed\";\n\n// ─── Line Item ────────────────────────────────────────────────────────────────\n\nexport interface LineItem {\n\tname: string;\n\tquantity: number;\n\tamount: number;\n\tdescription?: string;\n\timageUrl?: string;\n\tmetadata?: Record<string, unknown>;\n}\n\n// ─── Input Schemas ────────────────────────────────────────────────────────────\n\nexport const MoneyAmountSchema = z.object({\n\tamount: z.number().positive(),\n\tcurrency: z.string().min(3).max(3).toUpperCase(),\n});\n\nexport const CreateCheckoutInputSchema = z.object({\n\tamount: z.number().positive(),\n\tcurrency: z.string().min(3).max(3).transform((s) => s.toUpperCase()),\n\tdescription: z.string().optional(),\n\tcustomerEmail: z.string().email().optional(),\n\tcustomerName: z.string().optional(),\n\tsuccessUrl: z.string().url().optional(),\n\tcancelUrl: z.string().url().optional(),\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n\titems: z\n\t\t.array(\n\t\t\tz.object({\n\t\t\t\tname: z.string(),\n\t\t\t\tquantity: z.number().int().positive(),\n\t\t\t\tamount: z.number().positive(),\n\t\t\t\tdescription: z.string().optional(),\n\t\t\t}),\n\t\t)\n\t\t.optional(),\n});\n\nexport const CreateRefundInputSchema = z.object({\n\tpaymentId: z.string().min(1),\n\tamount: z.number().positive().optional(),\n\treason: z.string().optional(),\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport const CreateSubscriptionInputSchema = z.object({\n\tplanId: z.string().min(1),\n\tcustomerEmail: z.string().email().optional(),\n\tcustomerName: z.string().optional(),\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n\ttrialPeriodDays: z.number().int().nonnegative().optional(),\n});\n\nexport const CreatePaymentLinkInputSchema = z.object({\n\tamount: z.number().positive(),\n\tcurrency: z.string().min(3).max(3).transform((s) => s.toUpperCase()),\n\tdescription: z.string().optional(),\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n\texpiresAt: z.string().datetime().optional(),\n});\n\n// ─── Input Types ──────────────────────────────────────────────────────────────\n\nexport type CreateCheckoutInput = z.infer<typeof CreateCheckoutInputSchema>;\nexport type CreateRefundInput = z.infer<typeof CreateRefundInputSchema>;\nexport type CreateSubscriptionInput = z.infer<typeof CreateSubscriptionInputSchema>;\nexport type CreatePaymentLinkInput = z.infer<typeof CreatePaymentLinkInputSchema>;\n\n// ─── Payment Options ──────────────────────────────────────────────────────────\n\nexport interface PaymentOptions {\n\tidempotencyKey?: string;\n}\n\n// ─── Result Types ─────────────────────────────────────────────────────────────\n\nexport interface CheckoutResult {\n\tid: string;\n\tstatus: CheckoutStatus;\n\tamount: number;\n\tcurrency: string;\n\tprovider: string;\n\t/** Checkout URL for customer redirect (when status is \"pending\" or \"requires_action\") */\n\tcheckoutUrl?: string;\n\t/** Payment intent / session ID from the provider */\n\tproviderPaymentId?: string;\n\tclientSecret?: string;\n\tmetadata?: Record<string, unknown>;\n\texpiresAt?: Date;\n\tcreatedAt: Date;\n}\n\nexport interface RefundResult {\n\tid: string;\n\tstatus: RefundStatus;\n\tamount: number;\n\tcurrency: string;\n\tprovider: string;\n\tpaymentId: string;\n\treason?: string;\n\tmetadata?: Record<string, unknown>;\n\tcreatedAt: Date;\n}\n\nexport interface SubscriptionResult {\n\tid: string;\n\tstatus: SubscriptionStatus;\n\tprovider: string;\n\tplanId: string;\n\tcustomerEmail?: string;\n\tmetadata?: Record<string, unknown>;\n\tcurrentPeriodStart?: Date;\n\tcurrentPeriodEnd?: Date;\n\tcreatedAt: Date;\n}\n\nexport interface PaymentLinkResult {\n\tid: string;\n\turl: string;\n\tamount: number;\n\tcurrency: string;\n\tprovider: string;\n\tmetadata?: Record<string, unknown>;\n\texpiresAt?: Date;\n\tcreatedAt: Date;\n}\n\n// ─── Webhook Event ────────────────────────────────────────────────────────────\n\nexport interface WebhookEvent {\n\tid: string;\n\ttype: WebhookEventType;\n\tprovider: string;\n\trawData: unknown;\n\t/** The payment/subscription ID from the provider */\n\tentityId?: string;\n\tamount?: number;\n\tcurrency?: string;\n\tstatus?: string;\n\tmetadata?: Record<string, unknown>;\n\tcreatedAt: Date;\n}\n","import { HttpError } from \"../helpers/async-handler\";\n\nexport class PaymentError extends HttpError {\n\tprovider: string;\n\tproviderCode?: string;\n\n\tconstructor(\n\t\tmessage: string,\n\t\tstatus: number,\n\t\tprovider: string,\n\t\tproviderCode?: string,\n\t) {\n\t\tsuper(status, message);\n\t\tthis.name = \"PaymentError\";\n\t\tthis.provider = provider;\n\t\tthis.providerCode = providerCode;\n\t}\n}\n\nexport class PaymentVerificationError extends PaymentError {\n\tconstructor(provider: string, message = \"Webhook signature verification failed\") {\n\t\tsuper(message, 400, provider, \"VERIFICATION_FAILED\");\n\t\tthis.name = \"PaymentVerificationError\";\n\t}\n}\n\nexport class PaymentIdempotencyError extends PaymentError {\n\tconstructor(provider: string, message = \"Idempotency key reuse detected\") {\n\t\tsuper(message, 409, provider, \"IDEMPOTENCY_CONFLICT\");\n\t\tthis.name = \"PaymentIdempotencyError\";\n\t}\n}\n\nexport class PaymentProviderError extends PaymentError {\n\tconstructor(provider: string, providerCode: string, message: string) {\n\t\tsuper(message, 502, provider, providerCode);\n\t\tthis.name = \"PaymentProviderError\";\n\t}\n}\n\nexport class PaymentConfigurationError extends PaymentError {\n\tconstructor(provider: string, message = \"Invalid payment driver configuration\") {\n\t\tsuper(message, 500, provider, \"CONFIGURATION_ERROR\");\n\t\tthis.name = \"PaymentConfigurationError\";\n\t}\n}\n","import type {\n\tCheckoutStatus,\n\tRefundStatus,\n\tSubscriptionStatus,\n} from \"./types\";\n\n// ─── ID Generation ────────────────────────────────────────────────────────────\n\n/**\n * Generate a unique idempotency key for payment operations.\n * Format: `pay_{uuid}` - cryptographically random, safe for concurrent use.\n */\nexport function generateIdempotencyKey(): string {\n\treturn `pay_${crypto.randomUUID()}`;\n}\n\n// ─── Checkout Status Normalization ────────────────────────────────────────────\n\nconst STRIPE_CHECKOUT_STATUS: Record<string, CheckoutStatus> = {\n\topen: \"pending\",\n\tcomplete: \"completed\",\n\texpired: \"expired\",\n};\n\nconst STRIPE_INTENT_STATUS: Record<string, CheckoutStatus> = {\n\trequires_payment_method: \"pending\",\n\trequires_confirmation: \"pending\",\n\trequires_action: \"requires_action\",\n\tprocessing: \"processing\",\n\trequires_capture: \"processing\",\n\tsucceeded: \"completed\",\n\tcanceled: \"cancelled\",\n};\n\nconst MIDTRANS_STATUS: Record<string, CheckoutStatus> = {\n\tpending: \"pending\",\n\tsettlement: \"completed\",\n\tcapture: \"completed\",\n\tdeny: \"failed\",\n\tfailure: \"failed\",\n\tcancel: \"cancelled\",\n\texpire: \"expired\",\n};\n\nconst XENDIT_STATUS: Record<string, CheckoutStatus> = {\n\tPENDING: \"pending\",\n\tREQUIRES_ACTION: \"requires_action\",\n\tSUCCEEDED: \"completed\",\n\tFAILED: \"failed\",\n\tCANCELED: \"cancelled\",\n\tEXPIRED: \"expired\",\n};\n\nconst PAYPAL_STATUS: Record<string, CheckoutStatus> = {\n\tCREATED: \"pending\",\n\tSAVED: \"pending\",\n\tAPPROVED: \"completed\",\n\tVOIDED: \"cancelled\",\n\tCOMPLETED: \"completed\",\n\tPAYER_ACTION_REQUIRED: \"requires_action\",\n};\n\n/**\n * Normalize a provider-specific checkout status into a unified CheckoutStatus.\n *\n * @param provider - The payment provider identifier\n * @param nativeStatus - The provider's native status string\n * @returns The normalized CheckoutStatus\n */\nexport function normalizeCheckoutStatus(\n\tprovider: string,\n\tnativeStatus: string,\n): CheckoutStatus {\n\tswitch (provider) {\n\t\tcase \"stripe\": {\n\t\t\t// Stripe checkout session status OR payment intent status\n\t\t\treturn (\n\t\t\t\tSTRIPE_CHECKOUT_STATUS[nativeStatus] ??\n\t\t\t\tSTRIPE_INTENT_STATUS[nativeStatus] ??\n\t\t\t\t\"pending\"\n\t\t\t);\n\t\t}\n\t\tcase \"midtrans\":\n\t\t\treturn MIDTRANS_STATUS[nativeStatus] ?? \"pending\";\n\t\tcase \"xendit\":\n\t\t\treturn XENDIT_STATUS[nativeStatus] ?? \"pending\";\n\t\tcase \"paypal\":\n\t\t\treturn PAYPAL_STATUS[nativeStatus] ?? \"pending\";\n\t\tdefault:\n\t\t\treturn \"pending\";\n\t}\n}\n\n// ─── Refund Status Normalization ──────────────────────────────────────────────\n\nconst STRIPE_REFUND_STATUS: Record<string, RefundStatus> = {\n\tpending: \"pending\",\n\tsucceeded: \"completed\",\n\tfailed: \"failed\",\n\tpartial: \"partially_refunded\",\n};\n\nconst MIDTRANS_REFUND_STATUS: Record<string, RefundStatus> = {\n\trefund: \"completed\",\n\tpartial_refund: \"partially_refunded\",\n};\n\nconst XENDIT_REFUND_STATUS: Record<string, RefundStatus> = {\n\tPENDING: \"pending\",\n\tSUCCEEDED: \"completed\",\n\tFAILED: \"failed\",\n};\n\nconst PAYPAL_REFUND_STATUS: Record<string, RefundStatus> = {\n\tPENDING: \"pending\",\n\tCOMPLETED: \"completed\",\n\tFAILED: \"failed\",\n\tREFUNDED: \"partially_refunded\",\n\tCANCELLED: \"failed\",\n};\n\n/**\n * Normalize a provider-specific refund status into a unified RefundStatus.\n */\nexport function normalizeRefundStatus(\n\tprovider: string,\n\tnativeStatus: string,\n): RefundStatus {\n\tswitch (provider) {\n\t\tcase \"stripe\":\n\t\t\treturn STRIPE_REFUND_STATUS[nativeStatus] ?? \"pending\";\n\t\tcase \"midtrans\":\n\t\t\treturn MIDTRANS_REFUND_STATUS[nativeStatus] ?? \"pending\";\n\t\tcase \"xendit\":\n\t\t\treturn XENDIT_REFUND_STATUS[nativeStatus] ?? \"pending\";\n\t\tcase \"paypal\":\n\t\t\treturn PAYPAL_REFUND_STATUS[nativeStatus] ?? \"pending\";\n\t\tdefault:\n\t\t\treturn \"pending\";\n\t}\n}\n\n// ─── Subscription Status Normalization ────────────────────────────────────────\n\nconst STRIPE_SUBSCRIPTION_STATUS: Record<string, SubscriptionStatus> = {\n\tactive: \"active\",\n\tpast_due: \"past_due\",\n\tcanceled: \"cancelled\",\n\tunpaid: \"expired\",\n\tincomplete: \"incomplete\",\n\tincomplete_expired: \"expired\",\n\ttrialing: \"active\",\n};\n\nconst PAYPAL_SUBSCRIPTION_STATUS: Record<string, SubscriptionStatus> = {\n\tACTIVE: \"active\",\n\tCANCELLED: \"cancelled\",\n\tSUSPENDED: \"suspended\",\n\tEXPIRED: \"expired\",\n};\n\n/**\n * Normalize a provider-specific subscription status into a unified SubscriptionStatus.\n */\nexport function normalizeSubscriptionStatus(\n\tprovider: string,\n\tnativeStatus: string,\n): SubscriptionStatus {\n\tswitch (provider) {\n\t\tcase \"stripe\":\n\t\t\treturn STRIPE_SUBSCRIPTION_STATUS[nativeStatus] ?? \"active\";\n\t\tcase \"paypal\":\n\t\t\treturn PAYPAL_SUBSCRIPTION_STATUS[nativeStatus] ?? \"active\";\n\t\tdefault:\n\t\t\treturn \"active\";\n\t}\n}\n","import type { Middleware } from \"../../app\";\nimport type { Context } from \"../../context\";\nimport { PaymentVerificationError } from \"../errors\";\nimport type { PaymentDriver } from \"../driver\";\n\nexport interface WebhookMiddlewareOptions {\n\t/** The payment driver to use for verification */\n\tdriver: PaymentDriver;\n\t/** Webhook signing secret from the payment provider */\n\tsecret: string;\n\t/**\n\t * Header name that contains the signature.\n\t * Defaults vary by provider: Stripe uses \"stripe-signature\",\n\t * Midtrans uses \"x-signature\", Xendit uses \"x-callback-token\",\n\t * PayPal uses \"paypal-transmission-sig\".\n\t */\n\tsignatureHeader?: string;\n}\n\n/**\n * Middleware that verifies payment webhook signatures and injects\n * the parsed event into `ctx.store.paymentEvent`.\n *\n * @example\n * ```ts\n * import { paymentWebhook } from \"@buntok/core\";\n *\n * const stripe = new StripeDriver({ secretKey: \"sk_...\" });\n *\n * app.post(\"/webhooks/stripe\",\n *   paymentWebhook({\n *     driver: stripe,\n *     secret: process.env.STRIPE_WEBHOOK_SECRET!,\n *     signatureHeader: \"stripe-signature\",\n *   }),\n *   (ctx) => {\n *     const event = ctx.store.paymentEvent;\n *     // Handle the event...\n *     return ctx.json({ received: true });\n *   }\n * );\n * ```\n */\nexport function paymentWebhook(options: WebhookMiddlewareOptions): Middleware {\n\tconst {\n\t\tdriver,\n\t\tsecret,\n\t\tsignatureHeader = getDefaultSignatureHeader(driver.id),\n\t} = options;\n\n\treturn async (ctx: Context, next: () => Promise<Response> | Response) => {\n\t\tconst rawBody = await ctx.request.text();\n\t\tconst signature = ctx.request.headers.get(signatureHeader);\n\n\t\tif (!signature) {\n\t\t\tthrow new PaymentVerificationError(\n\t\t\t\tdriver.id,\n\t\t\t\t`Missing signature header: ${signatureHeader}`,\n\t\t\t);\n\t\t}\n\n\t\tconst isValid = await driver.verifyWebhookSignature(rawBody, signature, secret);\n\t\tif (!isValid) {\n\t\t\tthrow new PaymentVerificationError(driver.id);\n\t\t}\n\n\t\tconst event = driver.parseWebhookEvent(rawBody);\n\t\tctx.store.paymentEvent = event;\n\n\t\treturn next();\n\t};\n}\n\n/**\n * Get the default signature header name for a provider.\n */\nfunction getDefaultSignatureHeader(provider: string): string {\n\tswitch (provider) {\n\t\tcase \"stripe\":\n\t\t\treturn \"stripe-signature\";\n\t\tcase \"midtrans\":\n\t\t\treturn \"x-signature\";\n\t\tcase \"xendit\":\n\t\t\treturn \"x-callback-token\";\n\t\tcase \"paypal\":\n\t\t\treturn \"paypal-transmission-sig\";\n\t\tdefault:\n\t\t\treturn \"x-payment-signature\";\n\t}\n}\n","import type { PaymentDriver } from \"../driver\";\nimport type {\n\tCreateCheckoutInput,\n\tCreatePaymentLinkInput,\n\tCreateRefundInput,\n\tCreateSubscriptionInput,\n\tCheckoutResult,\n\tPaymentLinkResult,\n\tPaymentOptions,\n\tRefundResult,\n\tSubscriptionResult,\n\tWebhookEvent,\n} from \"../types\";\nimport { normalizeCheckoutStatus, normalizeRefundStatus, normalizeSubscriptionStatus } from \"../helpers\";\nimport {\n\tPaymentConfigurationError,\n\tPaymentProviderError,\n} from \"../errors\";\n\nexport interface StripeDriverConfig {\n\tsecretKey: string;\n\t/** Your Stripe webhook signing secret (e.g., \"whsec_...\") */\n\twebhookSecret?: string;\n\t/** API version override (default: \"2024-12-18.acacia\") */\n\tapiVersion?: string;\n}\n\nconst API_BASE = \"https://api.stripe.com/v1\";\n\nexport class StripeDriver implements PaymentDriver {\n\treadonly id = \"stripe\";\n\n\tprivate secretKey: string;\n\tprivate webhookSecret: string;\n\tprivate apiVersion: string;\n\n\tconstructor(config: StripeDriverConfig) {\n\t\tif (!config.secretKey) {\n\t\t\tthrow new PaymentConfigurationError(\n\t\t\t\tthis.id,\n\t\t\t\t\"Stripe secretKey is required\",\n\t\t\t);\n\t\t}\n\t\tthis.secretKey = config.secretKey;\n\t\tthis.webhookSecret = config.webhookSecret ?? \"\";\n\t\tthis.apiVersion = config.apiVersion ?? \"2024-12-18.acacia\";\n\t}\n\n\t// ─── HTTP ──────────────────────────────────────────────────────────────\n\n\tprivate async request<T>(\n\t\tmethod: string,\n\t\tpath: string,\n\t\tbody?: Record<string, unknown>,\n\t): Promise<T> {\n\t\tconst url = `${API_BASE}${path}`;\n\t\tconst headers: Record<string, string> = {\n\t\t\tAuthorization: `Bearer ${this.secretKey}`,\n\t\t\t\"Stripe-Version\": this.apiVersion,\n\t\t};\n\n\t\tlet res: Response;\n\t\tif (method === \"GET\") {\n\t\t\tconst params = body\n\t\t\t\t? `?${new URLSearchParams(body as Record<string, string>).toString()}`\n\t\t\t\t: \"\";\n\t\t\tres = await fetch(`${url}${params}`, { method, headers });\n\t\t} else {\n\t\t\theaders[\"Content-Type\"] = \"application/x-www-form-urlencoded\";\n\t\t\tconst formBody = body ? this.flattenParams(body) : \"\";\n\t\t\tres = await fetch(url, { method, headers, body: formBody });\n\t\t}\n\n\t\tconst data = await res.json();\n\n\t\tif (!res.ok) {\n\t\t\tconst err = data as { error?: { message?: string; type?: string; code?: string } };\n\t\t\tthrow new PaymentProviderError(\n\t\t\t\tthis.id,\n\t\t\t\terr.error?.code ?? \"api_error\",\n\t\t\t\terr.error?.message ?? \"Stripe API error\",\n\t\t\t);\n\t\t}\n\n\t\treturn data as T;\n\t}\n\n\t/** Convert nested objects to Stripe's dot-notation form params */\n\tprivate flattenParams(\n\t\tobj: Record<string, unknown>,\n\t\tprefix = \"\",\n\t): string {\n\t\tconst parts: string[] = [];\n\t\tfor (const [key, value] of Object.entries(obj)) {\n\t\t\tif (value === undefined || value === null) continue;\n\t\t\tconst fullKey = prefix ? `${prefix}[${key}]` : key;\n\t\t\tif (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n\t\t\t\tparts.push(this.flattenParams(value as Record<string, unknown>, fullKey));\n\t\t\t} else if (Array.isArray(value)) {\n\t\t\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\t\t\tconst itemKey = `${fullKey}[${i}]`;\n\t\t\t\t\tif (typeof value[i] === \"object\" && value[i] !== null) {\n\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\tthis.flattenParams(value[i] as Record<string, unknown>, itemKey),\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tparts.push(`${encodeURIComponent(itemKey)}=${encodeURIComponent(String(value[i]))}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tparts.push(`${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`);\n\t\t\t}\n\t\t}\n\t\treturn parts.join(\"&\");\n\t}\n\n\t// ─── Checkout ─────────────────────────────────────────────────────────\n\n\tasync createCheckout(\n\t\tinput: CreateCheckoutInput,\n\t\topts?: PaymentOptions,\n\t): Promise<CheckoutResult> {\n\t\tconst params: Record<string, unknown> = {\n\t\t\tmode: \"payment\",\n\t\t\tpayment_method_types: [\"card\"],\n\t\t\tline_items: [\n\t\t\t\t{\n\t\t\t\t\tprice_data: {\n\t\t\t\t\t\tcurrency: input.currency.toLowerCase(),\n\t\t\t\t\t\tproduct_data: {\n\t\t\t\t\t\t\tname: input.description ?? \"Payment\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\tunit_amount: this.toSmallestUnit(input.amount, input.currency),\n\t\t\t\t\t},\n\t\t\t\t\tquantity: 1,\n\t\t\t\t},\n\t\t\t],\n\t\t\tsuccess_url: input.successUrl ?? \"https://example.com/success\",\n\t\t\tcancel_url: input.cancelUrl ?? \"https://example.com/cancel\",\n\t\t};\n\n\t\tif (input.customerEmail) {\n\t\t\tparams.customer_email = input.customerEmail;\n\t\t}\n\t\tif (input.metadata) {\n\t\t\tparams.metadata = input.metadata;\n\t\t}\n\t\tif (opts?.idempotencyKey) {\n\t\t\t// Passed as header, not body\n\t\t}\n\n\t\tconst res = await this.request<{\n\t\t\tid: string;\n\t\t\tstatus: string;\n\t\t\tamount_total: number | null;\n\t\t\tcurrency: string | null;\n\t\t\turl: string | null;\n\t\t\tpayment_intent: string | { id: string; client_secret: string } | null;\n\t\t\texpires_at: number;\n\t\t\tcreated: number;\n\t\t\tmetadata: Record<string, unknown>;\n\t\t}>(\"POST\", \"/checkout/sessions\", params);\n\n\t\treturn {\n\t\t\tid: res.id,\n\t\t\tstatus: normalizeCheckoutStatus(this.id, res.status),\n\t\t\tamount: input.amount,\n\t\t\tcurrency: input.currency.toUpperCase(),\n\t\t\tprovider: this.id,\n\t\t\tcheckoutUrl: res.url ?? undefined,\n\t\t\tproviderPaymentId:\n\t\t\t\ttypeof res.payment_intent === \"string\"\n\t\t\t\t\t? res.payment_intent\n\t\t\t\t\t: typeof res.payment_intent === \"object\" && res.payment_intent\n\t\t\t\t\t\t? res.payment_intent.id\n\t\t\t\t\t\t: undefined,\n\t\t\tclientSecret:\n\t\t\t\ttypeof res.payment_intent === \"object\" && res.payment_intent\n\t\t\t\t\t? res.payment_intent.client_secret\n\t\t\t\t\t: undefined,\n\t\t\tmetadata: res.metadata,\n\t\t\texpiresAt: res.expires_at ? new Date(res.expires_at * 1000) : undefined,\n\t\t\tcreatedAt: new Date(res.created * 1000),\n\t\t};\n\t}\n\n\t// ─── Refund ───────────────────────────────────────────────────────────\n\n\tasync createRefund(\n\t\tinput: CreateRefundInput,\n\t\topts?: PaymentOptions,\n\t): Promise<RefundResult> {\n\t\tconst params: Record<string, unknown> = {\n\t\t\tpayment_intent: input.paymentId,\n\t\t};\n\t\tif (input.amount) {\n\t\t\tparams.amount = this.toSmallestUnit(input.amount, \"IDR\");\n\t\t}\n\t\tif (input.reason) {\n\t\t\tparams.reason = input.reason;\n\t\t}\n\t\tif (input.metadata) {\n\t\t\tparams.metadata = input.metadata;\n\t\t}\n\n\t\tconst res = await this.request<{\n\t\t\tid: string;\n\t\t\tstatus: string;\n\t\t\tamount: number;\n\t\t\tcurrency: string;\n\t\t\tpayment_intent: string;\n\t\t\treason: string | null;\n\t\t\tcreated: number;\n\t\t\tmetadata: Record<string, unknown>;\n\t\t}>(\"POST\", \"/refunds\", params);\n\n\t\treturn {\n\t\t\tid: res.id,\n\t\t\tstatus: normalizeRefundStatus(this.id, res.status),\n\t\t\tamount: this.fromSmallestUnit(res.amount, res.currency),\n\t\t\tcurrency: res.currency.toUpperCase(),\n\t\t\tprovider: this.id,\n\t\t\tpaymentId: res.payment_intent,\n\t\t\treason: res.reason ?? undefined,\n\t\t\tmetadata: res.metadata,\n\t\t\tcreatedAt: new Date(res.created * 1000),\n\t\t};\n\t}\n\n\t// ─── Subscription ─────────────────────────────────────────────────────\n\n\tasync createSubscription(\n\t\tinput: CreateSubscriptionInput,\n\t\topts?: PaymentOptions,\n\t): Promise<SubscriptionResult> {\n\t\tconst params: Record<string, unknown> = {\n\t\t\tprice: input.planId,\n\t\t};\n\t\tif (input.customerEmail) {\n\t\t\tparams.customer_email = input.customerEmail;\n\t\t}\n\t\tif (input.metadata) {\n\t\t\tparams.metadata = input.metadata;\n\t\t}\n\t\tif (input.trialPeriodDays) {\n\t\t\tparams.trial_period_days = input.trialPeriodDays;\n\t\t}\n\n\t\tconst res = await this.request<{\n\t\t\tid: string;\n\t\t\tstatus: string;\n\t\t\tcurrent_period_start: number;\n\t\t\tcurrent_period_end: number;\n\t\t\tcreated: number;\n\t\t\tmetadata: Record<string, unknown>;\n\t\t\titems: { data: Array<{ price: { id: string } }> };\n\t\t}>(\"POST\", \"/subscriptions\", params);\n\n\t\treturn {\n\t\t\tid: res.id,\n\t\t\tstatus: normalizeSubscriptionStatus(this.id, res.status),\n\t\t\tprovider: this.id,\n\t\t\tplanId: res.items.data[0]?.price.id ?? input.planId,\n\t\t\tcustomerEmail: input.customerEmail,\n\t\t\tmetadata: res.metadata,\n\t\t\tcurrentPeriodStart: new Date(res.current_period_start * 1000),\n\t\t\tcurrentPeriodEnd: new Date(res.current_period_end * 1000),\n\t\t\tcreatedAt: new Date(res.created * 1000),\n\t\t};\n\t}\n\n\t// ─── Payment Link ─────────────────────────────────────────────────────\n\n\tasync createPaymentLink(\n\t\tinput: CreatePaymentLinkInput,\n\t): Promise<PaymentLinkResult> {\n\t\tconst params: Record<string, unknown> = {\n\t\t\tline_items: [\n\t\t\t\t{\n\t\t\t\t\tprice_data: {\n\t\t\t\t\t\tcurrency: input.currency.toLowerCase(),\n\t\t\t\t\t\tproduct_data: {\n\t\t\t\t\t\t\tname: input.description ?? \"Payment\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\tunit_amount: this.toSmallestUnit(input.amount, input.currency),\n\t\t\t\t\t},\n\t\t\t\t\tquantity: 1,\n\t\t\t\t},\n\t\t\t],\n\t\t\tactive: true,\n\t\t};\n\n\t\tif (input.metadata) {\n\t\t\tparams.metadata = input.metadata;\n\t\t}\n\n\t\tconst res = await this.request<{\n\t\t\tid: string;\n\t\t\turl: string;\n\t\t\tactive: boolean;\n\t\t\tcreated: number;\n\t\t\tmetadata: Record<string, unknown>;\n\t\t}>(\"POST\", \"/payment_links\", params);\n\n\t\treturn {\n\t\t\tid: res.id,\n\t\t\turl: res.url,\n\t\t\tamount: input.amount,\n\t\t\tcurrency: input.currency.toUpperCase(),\n\t\t\tprovider: this.id,\n\t\t\tmetadata: res.metadata,\n\t\t\texpiresAt: input.expiresAt ? new Date(input.expiresAt) : undefined,\n\t\t\tcreatedAt: new Date(res.created * 1000),\n\t\t};\n\t}\n\n\t// ─── Webhook Verification ─────────────────────────────────────────────\n\n\tasync verifyWebhookSignature(\n\t\tpayload: string,\n\t\tsignature: string,\n\t\t_secret: string,\n\t): Promise<boolean> {\n\t\tconst secret = _secret || this.webhookSecret;\n\t\tif (!secret) return false;\n\n\t\ttry {\n\t\t\tconst parts = Object.fromEntries(\n\t\t\t\tsignature.split(\",\").map((p) => p.split(\"=\")),\n\t\t\t);\n\t\t\tconst timestamp = Number(parts.t);\n\t\t\tconst receivedSig = parts.v1;\n\n\t\t\tif (!timestamp || !receivedSig) return false;\n\n\t\t\t// Reject if timestamp is > 5 minutes old\n\t\t\tconst tolerance = 300;\n\t\t\tif (Math.abs(Date.now() / 1000 - timestamp) > tolerance) return false;\n\n\t\t\tconst signedPayload = `${timestamp}.${payload}`;\n\t\t\tconst computed = await this.hmacSha256(signedPayload, secret);\n\t\t\treturn computed === receivedSig;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate async hmacSha256(message: string, secret: string): Promise<string> {\n\t\tconst encoder = new TextEncoder();\n\t\tconst key = await crypto.subtle.importKey(\n\t\t\t\"raw\",\n\t\t\tencoder.encode(secret),\n\t\t\t{ name: \"HMAC\", hash: \"SHA-256\" },\n\t\t\tfalse,\n\t\t\t[\"sign\"],\n\t\t);\n\t\tconst signature = await crypto.subtle.sign(\n\t\t\t\"HMAC\",\n\t\t\tkey,\n\t\t\tencoder.encode(message),\n\t\t);\n\t\treturn Array.from(new Uint8Array(signature))\n\t\t\t.map((b) => b.toString(16).padStart(2, \"0\"))\n\t\t\t.join(\"\");\n\t}\n\n\tparseWebhookEvent(payload: string): WebhookEvent {\n\t\tconst event = JSON.parse(payload) as {\n\t\t\tid: string;\n\t\t\ttype: string;\n\t\t\tcreated: number;\n\t\t\tdata: { object: Record<string, unknown> };\n\t\t};\n\n\t\tconst typeMap: Record<string, WebhookEvent[\"type\"]> = {\n\t\t\t\"checkout.session.completed\": \"payment.completed\",\n\t\t\t\"payment_intent.succeeded\": \"payment.completed\",\n\t\t\t\"payment_intent.payment_failed\": \"payment.failed\",\n\t\t\t\"checkout.session.expired\": \"payment.expired\",\n\t\t\t\"customer.subscription.created\": \"subscription.created\",\n\t\t\t\"customer.subscription.deleted\": \"subscription.cancelled\",\n\t\t\t\"invoice.paid\": \"subscription.payment_succeeded\",\n\t\t\t\"invoice.payment_failed\": \"subscription.payment_failed\",\n\t\t\t\"charge.refunded\": \"refund.completed\",\n\t\t};\n\n\t\tconst obj = event.data.object;\n\t\tconst normalizedType = typeMap[event.type] ?? \"payment.created\";\n\n\t\treturn {\n\t\t\tid: event.id,\n\t\t\ttype: normalizedType,\n\t\t\tprovider: this.id,\n\t\t\trawData: event,\n\t\t\tentityId: (obj.id as string) ?? undefined,\n\t\t\tamount: typeof obj.amount === \"number\" ? obj.amount / 100 : undefined,\n\t\t\tcurrency: typeof obj.currency === \"string\" ? obj.currency.toUpperCase() : undefined,\n\t\t\tstatus: typeof obj.status === \"string\" ? obj.status : undefined,\n\t\t\tmetadata: (obj.metadata as Record<string, unknown>) ?? undefined,\n\t\t\tcreatedAt: new Date(event.created * 1000),\n\t\t};\n\t}\n\n\t// ─── Currency Helpers ─────────────────────────────────────────────────\n\n\tprivate toSmallestUnit(amount: number, currency: string): number {\n\t\tconst zeroDecimal = [\"BIF\", \"CLP\", \"DJF\", \"GNF\", \"JPY\", \"KMF\", \"KRW\", \"MGA\", \"PYG\", \"RWF\", \"UGX\", \"VND\", \"VUV\", \"XAF\", \"XOF\", \"XPF\"];\n\t\treturn zeroDecimal.includes(currency.toUpperCase())\n\t\t\t? Math.round(amount)\n\t\t\t: Math.round(amount * 100);\n\t}\n\n\tprivate fromSmallestUnit(amount: number, currency: string): number {\n\t\tconst zeroDecimal = [\"BIF\", \"CLP\", \"DJF\", \"GNF\", \"JPY\", \"KMF\", \"KRW\", \"MGA\", \"PYG\", \"RWF\", \"UGX\", \"VND\", \"VUV\", \"XAF\", \"XOF\", \"XPF\"];\n\t\treturn zeroDecimal.includes(currency.toUpperCase())\n\t\t\t? amount\n\t\t\t: amount / 100;\n\t}\n}\n","import type { PaymentDriver } from \"../driver\";\nimport type {\n\tCreateCheckoutInput,\n\tCreateRefundInput,\n\tCreateSubscriptionInput,\n\tCheckoutResult,\n\tPaymentOptions,\n\tRefundResult,\n\tSubscriptionResult,\n\tWebhookEvent,\n} from \"../types\";\nimport {\n\tnormalizeCheckoutStatus,\n\tnormalizeRefundStatus,\n} from \"../helpers\";\nimport {\n\tPaymentProviderError,\n} from \"../errors\";\n\nexport interface MidtransDriverConfig {\n\t/** Your Midtrans server key (e.g., \"SB-Mid-server-...\") */\n\tserverKey: string;\n\t/** Your Midtrans client key (for frontend Snap integration) */\n\tclientKey?: string;\n\t/** Use sandbox mode (default: false) */\n\tisProduction?: boolean;\n\t/** Webhook notification URL for Midtrans to POST to */\n\tnotificationUrl?: string;\n}\n\n// ─── API Request/Response Types ───────────────────────────────────────────────\n\ninterface MidtransSnapRequest {\n\ttransaction_details: {\n\t\torder_id: string;\n\t\tgross_amount: number;\n\t};\n\tcredit_card: { secure: boolean };\n\tcustomer_details?: {\n\t\temail?: string;\n\t\tfirst_name?: string;\n\t\tlast_name?: string;\n\t};\n\titem_details?: Array<{\n\t\tid: string;\n\t\tprice: number;\n\t\tquantity: number;\n\t\tname: string;\n\t}>;\n\tcallbacks?: { finish: string };\n\tcustom_field1?: string;\n}\n\ninterface MidtransSnapResponse {\n\ttoken: string;\n\tredirect_url: string;\n}\n\ninterface MidtransRefundRequest {\n\trefund_type: \"full\" | \"partial\";\n\trefund_amount?: number;\n\treason?: string;\n}\n\ninterface MidtransRefundResponse {\n\tstatus_code: string;\n\tstatus_message: string;\n\ttransaction_status: string;\n}\n\ninterface MidtransSubscriptionRequest {\n\tname: string;\n\tamount: number;\n\tcurrency: string;\n\tinterval: string;\n\tinterval_count: number;\n\tcustomer_email?: string;\n}\n\ninterface MidtransSubscriptionResponse {\n\tid: string;\n\tstatus: string;\n\tcreated_at: string;\n}\n\ninterface MidtransWebhookBody {\n\tsignature_key: string;\n\torder_id: string;\n\tstatus_code: string;\n\ttransaction_status: string;\n\tgross_amount: string;\n\ttransaction_time: string;\n\tcustom_field1?: string;\n\t[key: string]: unknown;\n}\n\ninterface MidtransErrorResponse {\n\tstatus_code?: string;\n\tstatus_message?: string;\n\terror_messages?: string[];\n\t[key: string]: unknown;\n}\n\n// ─── Base URLs ────────────────────────────────────────────────────────────────\n\nconst SNAP_BASE_DEV = \"https://app.sandbox.midtrans.com/snap\";\nconst SNAP_BASE_PROD = \"https://app.midtrans.com/snap\";\nconst API_BASE_DEV = \"https://api.sandbox.midtrans.com/v2\";\nconst API_BASE_PROD = \"https://api.midtrans.com/v2\";\n\n// ─── Driver ───────────────────────────────────────────────────────────────────\n\nexport class MidtransDriver implements PaymentDriver {\n\treadonly id = \"midtrans\";\n\n\tprivate serverKey: string;\n\tprivate snapBase: string;\n\tprivate apiBase: string;\n\tprivate notificationUrl?: string;\n\n\tconstructor(config: MidtransDriverConfig) {\n\t\tif (!config.serverKey) {\n\t\t\tthrow new PaymentProviderError(\n\t\t\t\tthis.id,\n\t\t\t\t\"CONFIGURATION_ERROR\",\n\t\t\t\t\"Midtrans serverKey is required\",\n\t\t\t);\n\t\t}\n\t\tthis.serverKey = config.serverKey;\n\t\tconst isProd = config.isProduction ?? false;\n\t\tthis.snapBase = isProd ? SNAP_BASE_PROD : SNAP_BASE_DEV;\n\t\tthis.apiBase = isProd ? API_BASE_PROD : API_BASE_DEV;\n\t\tthis.notificationUrl = config.notificationUrl;\n\t}\n\n\t// ─── HTTP ──────────────────────────────────────────────────────────────\n\n\tprivate authHeader(): string {\n\t\tconst encoded = btoa(`${this.serverKey}:`);\n\t\treturn `Basic ${encoded}`;\n\t}\n\n\tprivate async request<T>(\n\t\tmethod: string,\n\t\tbase: string,\n\t\tpath: string,\n\t\tbody?: MidtransSnapRequest | MidtransRefundRequest | MidtransSubscriptionRequest,\n\t): Promise<T> {\n\t\tconst url = `${base}${path}`;\n\t\tconst headers: Record<string, string> = {\n\t\t\tAuthorization: this.authHeader(),\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t};\n\n\t\tconst res = await fetch(url, {\n\t\t\tmethod,\n\t\t\theaders,\n\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t});\n\n\t\tconst data = (await res.json()) as Record<string, unknown>;\n\n\t\tif (!res.ok || data.error_messages) {\n\t\t\tconst errData = data as unknown as MidtransErrorResponse;\n\t\t\tthrow new PaymentProviderError(\n\t\t\t\tthis.id,\n\t\t\t\terrData.status_code ?? \"api_error\",\n\t\t\t\terrData.error_messages?.join(\", \") ??\n\t\t\t\t\terrData.status_message ??\n\t\t\t\t\t\"Midtrans API error\",\n\t\t\t);\n\t\t}\n\n\t\treturn data as T;\n\t}\n\n\t// ─── Checkout ─────────────────────────────────────────────────────────\n\n\tasync createCheckout(\n\t\tinput: CreateCheckoutInput,\n\t\topts?: PaymentOptions,\n\t): Promise<CheckoutResult> {\n\t\tconst orderId = opts?.idempotencyKey ?? `ORDER-${crypto.randomUUID().slice(0, 8)}`;\n\n\t\tconst params: MidtransSnapRequest = {\n\t\t\ttransaction_details: {\n\t\t\t\torder_id: orderId,\n\t\t\t\tgross_amount: input.amount,\n\t\t\t},\n\t\t\tcredit_card: {\n\t\t\t\tsecure: true,\n\t\t\t},\n\t\t};\n\n\t\tif (input.customerEmail || input.customerName) {\n\t\t\tconst nameParts = input.customerName?.split(\" \") ?? [];\n\t\t\tparams.customer_details = {\n\t\t\t\temail: input.customerEmail,\n\t\t\t\tfirst_name: nameParts[0],\n\t\t\t\tlast_name: nameParts.slice(1).join(\" \") || undefined,\n\t\t\t};\n\t\t}\n\n\t\tif (input.description) {\n\t\t\tparams.item_details = [\n\t\t\t\t{\n\t\t\t\t\tid: orderId,\n\t\t\t\t\tprice: input.amount,\n\t\t\t\t\tquantity: 1,\n\t\t\t\t\tname: input.description,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\tif (this.notificationUrl) {\n\t\t\tparams.callbacks = {\n\t\t\t\tfinish: input.successUrl ?? \"https://example.com/success\",\n\t\t\t};\n\t\t}\n\n\t\tif (input.metadata) {\n\t\t\tparams.custom_field1 = JSON.stringify(input.metadata);\n\t\t}\n\n\t\tconst res = await this.request<MidtransSnapResponse>(\n\t\t\t\"POST\",\n\t\t\tthis.snapBase,\n\t\t\t\"/transactions\",\n\t\t\tparams,\n\t\t);\n\n\t\treturn {\n\t\t\tid: orderId,\n\t\t\tstatus: \"pending\",\n\t\t\tamount: input.amount,\n\t\t\tcurrency: input.currency.toUpperCase(),\n\t\t\tprovider: this.id,\n\t\t\tcheckoutUrl: res.redirect_url,\n\t\t\tproviderPaymentId: res.token,\n\t\t\tmetadata: input.metadata,\n\t\t\tcreatedAt: new Date(),\n\t\t};\n\t}\n\n\t// ─── Refund ───────────────────────────────────────────────────────────\n\n\tasync createRefund(\n\t\tinput: CreateRefundInput,\n\t\topts?: PaymentOptions,\n\t): Promise<RefundResult> {\n\t\tconst params: MidtransRefundRequest = {\n\t\t\trefund_type: input.amount ? \"partial\" : \"full\",\n\t\t};\n\t\tif (input.amount) {\n\t\t\tparams.refund_amount = input.amount;\n\t\t}\n\t\tif (input.reason) {\n\t\t\tparams.reason = input.reason;\n\t\t}\n\n\t\tconst res = await this.request<MidtransRefundResponse>(\n\t\t\t\"POST\",\n\t\t\tthis.apiBase,\n\t\t\t`/transactions/${input.paymentId}/refund`,\n\t\t\tparams,\n\t\t);\n\n\t\treturn {\n\t\t\tid: `${input.paymentId}-refund-${crypto.randomUUID().slice(0, 8)}`,\n\t\t\tstatus: normalizeRefundStatus(this.id, res.transaction_status),\n\t\t\tamount: input.amount ?? 0,\n\t\t\tcurrency: \"IDR\",\n\t\t\tprovider: this.id,\n\t\t\tpaymentId: input.paymentId,\n\t\t\treason: input.reason,\n\t\t\tmetadata: input.metadata,\n\t\t\tcreatedAt: new Date(),\n\t\t};\n\t}\n\n\t// ─── Subscription (Midtrans Recurring) ────────────────────────────────\n\n\tasync createSubscription(\n\t\tinput: CreateSubscriptionInput,\n\t\topts?: PaymentOptions,\n\t): Promise<SubscriptionResult> {\n\t\tconst params: MidtransSubscriptionRequest = {\n\t\t\tname: input.planId,\n\t\t\tamount: 0,\n\t\t\tcurrency: \"IDR\",\n\t\t\tinterval: \"month\",\n\t\t\tinterval_count: 1,\n\t\t};\n\n\t\tif (input.customerEmail) {\n\t\t\tparams.customer_email = input.customerEmail;\n\t\t}\n\n\t\tconst res = await this.request<MidtransSubscriptionResponse>(\n\t\t\t\"POST\",\n\t\t\tthis.apiBase,\n\t\t\t\"/subscriptions\",\n\t\t\tparams,\n\t\t);\n\n\t\treturn {\n\t\t\tid: res.id,\n\t\t\tstatus: res.status === \"active\" ? \"active\" : \"incomplete\",\n\t\t\tprovider: this.id,\n\t\t\tplanId: input.planId,\n\t\t\tcustomerEmail: input.customerEmail,\n\t\t\tmetadata: input.metadata,\n\t\t\tcreatedAt: new Date(res.created_at),\n\t\t};\n\t}\n\n\t// ─── Webhook Verification ─────────────────────────────────────────────\n\n\tasync verifyWebhookSignature(\n\t\tpayload: string,\n\t\tsignature: string,\n\t\tsecret: string,\n\t): Promise<boolean> {\n\t\ttry {\n\t\t\tconst body = JSON.parse(payload) as MidtransWebhookBody;\n\t\t\tif (!body.signature_key || !body.order_id || !body.status_code) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst serverKey = secret || this.serverKey;\n\t\t\tconst raw = `${body.order_id}${body.status_code}${serverKey}`;\n\t\t\tconst computed = await this.sha512(raw);\n\t\t\treturn computed === body.signature_key;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate async sha512(message: string): Promise<string> {\n\t\tconst encoder = new TextEncoder();\n\t\tconst data = encoder.encode(message);\n\t\tconst hashBuffer = await crypto.subtle.digest(\"SHA-512\", data);\n\t\treturn Array.from(new Uint8Array(hashBuffer))\n\t\t\t.map((b) => b.toString(16).padStart(2, \"0\"))\n\t\t\t.join(\"\");\n\t}\n\n\tparseWebhookEvent(payload: string): WebhookEvent {\n\t\tconst body = JSON.parse(payload) as MidtransWebhookBody;\n\n\t\tconst typeMap: Record<string, WebhookEvent[\"type\"]> = {\n\t\t\tsettlement: \"payment.completed\",\n\t\t\tcapture: \"payment.completed\",\n\t\t\tpending: \"payment.created\",\n\t\t\tdeny: \"payment.failed\",\n\t\t\tfailure: \"payment.failed\",\n\t\t\tcancel: \"payment.failed\",\n\t\t\texpire: \"payment.expired\",\n\t\t\trefund: \"refund.completed\",\n\t\t\tpartial_refund: \"refund.completed\",\n\t\t};\n\n\t\treturn {\n\t\t\tid: body.order_id,\n\t\t\ttype: typeMap[body.transaction_status] ?? \"payment.created\",\n\t\t\tprovider: this.id,\n\t\t\trawData: body,\n\t\t\tentityId: body.order_id,\n\t\t\tamount: body.gross_amount ? Number(body.gross_amount) : undefined,\n\t\t\tcurrency: \"IDR\",\n\t\t\tstatus: body.transaction_status,\n\t\t\tmetadata: body.custom_field1\n\t\t\t\t? JSON.parse(body.custom_field1)\n\t\t\t\t: undefined,\n\t\t\tcreatedAt: body.transaction_time\n\t\t\t\t? new Date(body.transaction_time)\n\t\t\t\t: new Date(),\n\t\t};\n\t}\n}\n","import type { PaymentDriver } from \"../driver\";\nimport type {\n\tCreateCheckoutInput,\n\tCreatePaymentLinkInput,\n\tCreateRefundInput,\n\tCheckoutResult,\n\tPaymentLinkResult,\n\tPaymentOptions,\n\tRefundResult,\n\tWebhookEvent,\n} from \"../types\";\nimport {\n\tnormalizeCheckoutStatus,\n\tnormalizeRefundStatus,\n} from \"../helpers\";\nimport {\n\tPaymentProviderError,\n} from \"../errors\";\n\nexport interface XenditDriverConfig {\n\t/** Your Xendit secret API key (e.g., \"xnd_development_...\") */\n\tsecretKey: string;\n\t/** Use sandbox mode (default: false) */\n\tisProduction?: boolean;\n}\n\n// ─── API Request/Response Types ───────────────────────────────────────────────\n\ninterface XenditPaymentMethod {\n\ttype: string;\n\treusability?: string;\n\tpermanent?: boolean;\n\tbank_transfer?: { bank: string };\n\tvirtual_account_info?: { permanent: boolean };\n}\n\ninterface XenditPaymentRequest {\n\treference_id: string;\n\tamount: number;\n\tcurrency: string;\n\tpayment_method: XenditPaymentMethod;\n\tdescription?: string;\n\tcustomer?: {\n\t\treference_id: string;\n\t\temail?: string;\n\t\tname?: string;\n\t};\n\tmetadata?: Record<string, unknown>;\n}\n\ninterface XenditPaymentResponse {\n\tid: string;\n\treference_id: string;\n\tstatus: string;\n\tamount: number;\n\tcurrency: string;\n\tdescription: string;\n\tcreated: string;\n\tupdated: string;\n\tactions?: Array<{ url: string }>;\n\tmetadata?: Record<string, unknown>;\n}\n\ninterface XenditRefundRequest {\n\tpayment_request_id: string;\n\tamount?: number;\n\treason?: string;\n}\n\ninterface XenditRefundResponse {\n\tid: string;\n\tpayment_request_id: string;\n\tstatus: string;\n\tamount: number;\n\tcreated: string;\n}\n\ninterface XenditErrorResponse {\n\terror_code?: string;\n\tmessage?: string;\n\terrors?: Array<{ message?: string }>;\n}\n\ninterface XenditWebhookBody {\n\tid: string;\n\treference_id?: string;\n\tstatus: string;\n\tamount: number;\n\tcurrency: string;\n\tcreated: string;\n\tupdated?: string;\n\tdescription?: string;\n\tpayment_request_id?: string;\n\tmetadata?: Record<string, unknown>;\n\t[key: string]: unknown;\n}\n\n// ─── Driver ───────────────────────────────────────────────────────────────────\n\nexport class XenditDriver implements PaymentDriver {\n\treadonly id = \"xendit\";\n\n\tprivate secretKey: string;\n\tprivate apiBase: string;\n\n\tconstructor(config: XenditDriverConfig) {\n\t\tif (!config.secretKey) {\n\t\t\tthrow new PaymentProviderError(\n\t\t\t\tthis.id,\n\t\t\t\t\"CONFIGURATION_ERROR\",\n\t\t\t\t\"Xendit secretKey is required\",\n\t\t\t);\n\t\t}\n\t\tthis.secretKey = config.secretKey;\n\t\tthis.apiBase = \"https://api.xendit.co\";\n\t}\n\n\t// ─── HTTP ──────────────────────────────────────────────────────────────\n\n\tprivate async request<T>(\n\t\tmethod: string,\n\t\tpath: string,\n\t\tbody?: XenditPaymentRequest | XenditRefundRequest,\n\t): Promise<T> {\n\t\tconst url = `${this.apiBase}${path}`;\n\t\tconst headers: Record<string, string> = {\n\t\t\tAuthorization: this.secretKey,\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t};\n\n\t\tconst res = await fetch(url, {\n\t\t\tmethod,\n\t\t\theaders,\n\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t});\n\n\t\tconst data = (await res.json()) as Record<string, unknown>;\n\n\t\tif (!res.ok) {\n\t\t\tconst errData = data as unknown as XenditErrorResponse;\n\t\t\tthrow new PaymentProviderError(\n\t\t\t\tthis.id,\n\t\t\t\terrData.error_code ?? \"api_error\",\n\t\t\t\terrData.message ??\n\t\t\t\t\terrData.errors?.[0]?.message ??\n\t\t\t\t\t\"Xendit API error\",\n\t\t\t);\n\t\t}\n\n\t\treturn data as T;\n\t}\n\n\t// ─── Checkout (Payment Request) ───────────────────────────────────────\n\n\tasync createCheckout(\n\t\tinput: CreateCheckoutInput,\n\t\topts?: PaymentOptions,\n\t): Promise<CheckoutResult> {\n\t\tconst referenceId = opts?.idempotencyKey ?? `REF-${crypto.randomUUID().slice(0, 8)}`;\n\n\t\tconst params: XenditPaymentRequest = {\n\t\t\treference_id: referenceId,\n\t\t\tamount: input.amount,\n\t\t\tcurrency: input.currency.toUpperCase(),\n\t\t\tpayment_method: {\n\t\t\t\ttype: \"VIRTUAL_ACCOUNT\",\n\t\t\t\tpermanent: false,\n\t\t\t},\n\t\t\tdescription: input.description ?? \"Payment\",\n\t\t};\n\n\t\tif (input.customerEmail || input.customerName) {\n\t\t\tparams.customer = {\n\t\t\t\treference_id: referenceId,\n\t\t\t\temail: input.customerEmail,\n\t\t\t\tname: input.customerName,\n\t\t\t};\n\t\t}\n\n\t\tif (input.metadata) {\n\t\t\tparams.metadata = input.metadata;\n\t\t}\n\n\t\tconst res = await this.request<XenditPaymentResponse>(\n\t\t\t\"POST\",\n\t\t\t\"/payment_requests\",\n\t\t\tparams,\n\t\t);\n\n\t\tconst actions = res.actions ?? [];\n\t\tconst checkoutUrl = actions.find((a) => a.url)?.url;\n\n\t\treturn {\n\t\t\tid: res.id,\n\t\t\tstatus: normalizeCheckoutStatus(this.id, res.status),\n\t\t\tamount: res.amount,\n\t\t\tcurrency: res.currency,\n\t\t\tprovider: this.id,\n\t\t\tcheckoutUrl,\n\t\t\tproviderPaymentId: res.id,\n\t\t\tmetadata: res.metadata,\n\t\t\tcreatedAt: new Date(res.created),\n\t\t};\n\t}\n\n\t// ─── Refund ───────────────────────────────────────────────────────────\n\n\tasync createRefund(\n\t\tinput: CreateRefundInput,\n\t\topts?: PaymentOptions,\n\t): Promise<RefundResult> {\n\t\tconst params: XenditRefundRequest = {\n\t\t\tpayment_request_id: input.paymentId,\n\t\t};\n\t\tif (input.amount) {\n\t\t\tparams.amount = input.amount;\n\t\t}\n\t\tif (input.reason) {\n\t\t\tparams.reason = input.reason;\n\t\t}\n\n\t\tconst res = await this.request<XenditRefundResponse>(\n\t\t\t\"POST\",\n\t\t\t\"/refunds\",\n\t\t\tparams,\n\t\t);\n\n\t\treturn {\n\t\t\tid: res.id,\n\t\t\tstatus: normalizeRefundStatus(this.id, res.status),\n\t\t\tamount: res.amount,\n\t\t\tcurrency: \"IDR\",\n\t\t\tprovider: this.id,\n\t\t\tpaymentId: res.payment_request_id,\n\t\t\treason: input.reason,\n\t\t\tmetadata: input.metadata,\n\t\t\tcreatedAt: new Date(res.created),\n\t\t};\n\t}\n\n\t// ─── Payment Link ─────────────────────────────────────────────────────\n\n\tasync createPaymentLink(\n\t\tinput: CreatePaymentLinkInput,\n\t): Promise<PaymentLinkResult> {\n\t\tconst params: XenditPaymentRequest = {\n\t\t\treference_id: `REF-${crypto.randomUUID().slice(0, 8)}`,\n\t\t\tamount: input.amount,\n\t\t\tcurrency: input.currency.toUpperCase(),\n\t\t\tpayment_method: {\n\t\t\t\ttype: \"VIRTUAL_ACCOUNT\",\n\t\t\t},\n\t\t\tdescription: input.description ?? \"Payment\",\n\t\t};\n\n\t\tif (input.metadata) {\n\t\t\tparams.metadata = input.metadata;\n\t\t}\n\n\t\tconst res = await this.request<XenditPaymentResponse>(\n\t\t\t\"POST\",\n\t\t\t\"/payment_requests\",\n\t\t\tparams,\n\t\t);\n\n\t\tconst actions = res.actions ?? [];\n\t\tconst url = actions.find((a) => a.url)?.url ?? \"\";\n\n\t\treturn {\n\t\t\tid: res.id,\n\t\t\turl,\n\t\t\tamount: res.amount,\n\t\t\tcurrency: res.currency,\n\t\t\tprovider: this.id,\n\t\t\tmetadata: res.metadata,\n\t\t\texpiresAt: input.expiresAt ? new Date(input.expiresAt) : undefined,\n\t\t\tcreatedAt: new Date(res.created),\n\t\t};\n\t}\n\n\t// ─── Webhook Verification ─────────────────────────────────────────────\n\n\tasync verifyWebhookSignature(\n\t\tpayload: string,\n\t\tsignature: string,\n\t\tsecret: string,\n\t): Promise<boolean> {\n\t\ttry {\n\t\t\tconst encoder = new TextEncoder();\n\t\t\tconst key = await crypto.subtle.importKey(\n\t\t\t\t\"raw\",\n\t\t\t\tencoder.encode(secret),\n\t\t\t\t{ name: \"HMAC\", hash: \"SHA-256\" },\n\t\t\t\tfalse,\n\t\t\t\t[\"sign\"],\n\t\t\t);\n\t\t\tconst sig = await crypto.subtle.sign(\"HMAC\", key, encoder.encode(payload));\n\t\t\tconst computed = Array.from(new Uint8Array(sig))\n\t\t\t\t.map((b) => b.toString(16).padStart(2, \"0\"))\n\t\t\t\t.join(\"\");\n\t\t\treturn computed === signature;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tparseWebhookEvent(payload: string): WebhookEvent {\n\t\tconst body = JSON.parse(payload) as XenditWebhookBody;\n\n\t\tconst typeMap: Record<string, WebhookEvent[\"type\"]> = {\n\t\t\tSUCCEEDED: \"payment.completed\",\n\t\t\tPENDING: \"payment.created\",\n\t\t\tFAILED: \"payment.failed\",\n\t\t\tREQUIRES_ACTION: \"payment.failed\",\n\t\t\tCANCELLED: \"payment.failed\",\n\t\t\tEXPIRED: \"payment.expired\",\n\t\t};\n\n\t\treturn {\n\t\t\tid: body.id,\n\t\t\ttype: typeMap[body.status] ?? \"payment.created\",\n\t\t\tprovider: this.id,\n\t\t\trawData: body,\n\t\t\tentityId: body.id,\n\t\t\tamount: body.amount,\n\t\t\tcurrency: body.currency,\n\t\t\tstatus: body.status,\n\t\t\tmetadata: body.metadata,\n\t\t\tcreatedAt: new Date(body.created),\n\t\t};\n\t}\n}\n","import type { PaymentDriver } from \"../driver\";\nimport type {\n\tCreateCheckoutInput,\n\tCreateRefundInput,\n\tCreateSubscriptionInput,\n\tCheckoutResult,\n\tPaymentOptions,\n\tRefundResult,\n\tSubscriptionResult,\n\tWebhookEvent,\n} from \"../types\";\nimport {\n\tnormalizeCheckoutStatus,\n\tnormalizeRefundStatus,\n} from \"../helpers\";\nimport {\n\tPaymentConfigurationError,\n\tPaymentProviderError,\n} from \"../errors\";\n\nexport interface PayPalDriverConfig {\n\t/** PayPal client ID */\n\tclientId: string;\n\t/** PayPal client secret */\n\tclientSecret: string;\n\t/** Use sandbox mode (default: false) */\n\tisProduction?: boolean;\n}\n\n// ─── API Request/Response Types ───────────────────────────────────────────────\n\ninterface PayPalOrderRequest {\n\tintent: \"CAPTURE\";\n\tpurchase_units: Array<{\n\t\tamount: {\n\t\t\tcurrency_code: string;\n\t\t\tvalue: string;\n\t\t};\n\t\tdescription?: string;\n\t}>;\n\tapplication_context: {\n\t\tbrand_name: string;\n\t\tlanding_page: string;\n\t\tuser_action: string;\n\t\treturn_url?: string;\n\t\tcancel_url?: string;\n\t};\n}\n\ninterface PayPalOrderResponse {\n\tid: string;\n\tstatus: string;\n\tlinks: Array<{ href: string; rel: string; method: string }>;\n\tcreate_time: string;\n}\n\ninterface PayPalRefundRequest {\n\tamount?: {\n\t\tvalue: string;\n\t\tcurrency_code: string;\n\t};\n\tnote_to_payer?: string;\n}\n\ninterface PayPalRefundResponse {\n\tid: string;\n\tstatus: string;\n\tamount: { value: string; currency_code: string };\n\tnote_to_payer?: string;\n\tcreate_time: string;\n}\n\ninterface PayPalSubscriptionRequest {\n\tplan_id: string;\n\tstart_time: string;\n\tsubscriber?: {\n\t\temail_address: string;\n\t};\n}\n\ninterface PayPalSubscriptionResponse {\n\tid: string;\n\tstatus: string;\n\tcreate_time: string;\n\tplan_id?: string;\n}\n\ninterface PayPalAccessTokenResponse {\n\taccess_token: string;\n\texpires_in: number;\n}\n\ninterface PayPalErrorResponse {\n\tname?: string;\n\tmessage?: string;\n\tdetails?: Array<{ description?: string }>;\n}\n\ninterface PayPalWebhookResource {\n\tid: string;\n\tstate?: string;\n\tamount?: { total: string; currency: string };\n\tpayer?: { email_address?: string };\n\tcreate_time?: string;\n\t[key: string]: unknown;\n}\n\ninterface PayPalWebhookBody {\n\tid: string;\n\tevent_type: string;\n\tresource: PayPalWebhookResource;\n\tcreate_time: string;\n\tresource_type: string;\n\t[key: string]: unknown;\n}\n\n// ─── Base URLs ────────────────────────────────────────────────────────────────\n\nconst API_BASE_SANDBOX = \"https://api-m.sandbox.paypal.com\";\nconst API_BASE_PROD = \"https://api-m.paypal.com\";\n\n// ─── Driver ───────────────────────────────────────────────────────────────────\n\nexport class PayPalDriver implements PaymentDriver {\n\treadonly id = \"paypal\";\n\n\tprivate clientId: string;\n\tprivate clientSecret: string;\n\tprivate apiBase: string;\n\tprivate accessToken?: string;\n\tprivate tokenExpiry = 0;\n\n\tconstructor(config: PayPalDriverConfig) {\n\t\tif (!config.clientId || !config.clientSecret) {\n\t\t\tthrow new PaymentConfigurationError(\n\t\t\t\tthis.id,\n\t\t\t\t\"PayPal clientId and clientSecret are required\",\n\t\t\t);\n\t\t}\n\t\tthis.clientId = config.clientId;\n\t\tthis.clientSecret = config.clientSecret;\n\t\tthis.apiBase = config.isProduction ? API_BASE_PROD : API_BASE_SANDBOX;\n\t}\n\n\t// ─── Auth ─────────────────────────────────────────────────────────────\n\n\tprivate async getAccessToken(): Promise<string> {\n\t\tif (this.accessToken && Date.now() < this.tokenExpiry) {\n\t\t\treturn this.accessToken;\n\t\t}\n\n\t\tconst encoded = btoa(`${this.clientId}:${this.clientSecret}`);\n\t\tconst res = await fetch(`${this.apiBase}/v1/oauth2/token`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Basic ${encoded}`,\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t},\n\t\t\tbody: \"grant_type=client_credentials\",\n\t\t});\n\n\t\tconst data = (await res.json()) as PayPalAccessTokenResponse;\n\n\t\tif (!res.ok || !data.access_token) {\n\t\t\tthrow new PaymentProviderError(\n\t\t\t\tthis.id,\n\t\t\t\t\"AUTH_ERROR\",\n\t\t\t\t\"Failed to obtain PayPal access token\",\n\t\t\t);\n\t\t}\n\n\t\tthis.accessToken = data.access_token;\n\t\tthis.tokenExpiry = Date.now() + (data.expires_in - 300) * 1000;\n\n\t\treturn this.accessToken;\n\t}\n\n\t// ─── HTTP ──────────────────────────────────────────────────────────────\n\n\tprivate async request<T>(\n\t\tmethod: string,\n\t\tpath: string,\n\t\tbody?: PayPalOrderRequest | PayPalRefundRequest | PayPalSubscriptionRequest,\n\t): Promise<T> {\n\t\tconst url = `${this.apiBase}${path}`;\n\t\tconst token = await this.getAccessToken();\n\t\tconst headers: Record<string, string> = {\n\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tPrefer: \"return=representation\",\n\t\t};\n\n\t\tconst res = await fetch(url, {\n\t\t\tmethod,\n\t\t\theaders,\n\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t});\n\n\t\tif (res.status === 204) {\n\t\t\treturn {} as T;\n\t\t}\n\n\t\tconst data = (await res.json()) as Record<string, unknown>;\n\n\t\tif (!res.ok) {\n\t\t\tconst errData = data as unknown as PayPalErrorResponse;\n\t\t\tthrow new PaymentProviderError(\n\t\t\t\tthis.id,\n\t\t\t\terrData.name ?? \"api_error\",\n\t\t\t\terrData.message ??\n\t\t\t\t\terrData.details?.[0]?.description ??\n\t\t\t\t\t\"PayPal API error\",\n\t\t\t);\n\t\t}\n\n\t\treturn data as T;\n\t}\n\n\t// ─── Checkout (Order) ─────────────────────────────────────────────────\n\n\tasync createCheckout(\n\t\tinput: CreateCheckoutInput,\n\t\topts?: PaymentOptions,\n\t): Promise<CheckoutResult> {\n\t\tconst params: PayPalOrderRequest = {\n\t\t\tintent: \"CAPTURE\",\n\t\t\tpurchase_units: [\n\t\t\t\t{\n\t\t\t\t\tamount: {\n\t\t\t\t\t\tcurrency_code: input.currency.toUpperCase(),\n\t\t\t\t\t\tvalue: input.amount.toFixed(2),\n\t\t\t\t\t},\n\t\t\t\t\tdescription: input.description ?? \"Payment\",\n\t\t\t\t},\n\t\t\t],\n\t\t\tapplication_context: {\n\t\t\t\tbrand_name: \"Buntok Store\",\n\t\t\t\tlanding_page: \"BILLING\",\n\t\t\t\tuser_action: \"PAY_NOW\",\n\t\t\t},\n\t\t};\n\n\t\tif (input.successUrl) {\n\t\t\tparams.application_context.return_url = input.successUrl;\n\t\t}\n\t\tif (input.cancelUrl) {\n\t\t\tparams.application_context.cancel_url = input.cancelUrl;\n\t\t}\n\n\t\tconst res = await this.request<PayPalOrderResponse>(\n\t\t\t\"POST\",\n\t\t\t\"/v2/checkout/orders\",\n\t\t\tparams,\n\t\t);\n\n\t\tconst approveLink = res.links.find((l) => l.rel === \"approve\");\n\n\t\treturn {\n\t\t\tid: res.id,\n\t\t\tstatus: normalizeCheckoutStatus(this.id, res.status),\n\t\t\tamount: input.amount,\n\t\t\tcurrency: input.currency.toUpperCase(),\n\t\t\tprovider: this.id,\n\t\t\tcheckoutUrl: approveLink?.href,\n\t\t\tproviderPaymentId: res.id,\n\t\t\tmetadata: input.metadata,\n\t\t\tcreatedAt: res.create_time ? new Date(res.create_time) : new Date(),\n\t\t};\n\t}\n\n\t// ─── Refund ───────────────────────────────────────────────────────────\n\n\tasync createRefund(\n\t\tinput: CreateRefundInput,\n\t\topts?: PaymentOptions,\n\t): Promise<RefundResult> {\n\t\tconst params: PayPalRefundRequest = {};\n\t\tif (input.amount) {\n\t\t\tparams.amount = {\n\t\t\t\tvalue: input.amount.toFixed(2),\n\t\t\t\tcurrency_code: \"USD\",\n\t\t\t};\n\t\t}\n\t\tif (input.reason) {\n\t\t\tparams.note_to_payer = input.reason;\n\t\t}\n\n\t\tconst res = await this.request<PayPalRefundResponse>(\n\t\t\t\"POST\",\n\t\t\t`/v2/payments/captures/${input.paymentId}/refund`,\n\t\t\tparams,\n\t\t);\n\n\t\tconst refundAmount = res.amount?.value ? Number(res.amount.value) : 0;\n\n\t\treturn {\n\t\t\tid: res.id,\n\t\t\tstatus: normalizeRefundStatus(this.id, res.status),\n\t\t\tamount: refundAmount,\n\t\t\tcurrency: res.amount?.currency_code ?? \"USD\",\n\t\t\tprovider: this.id,\n\t\t\tpaymentId: input.paymentId,\n\t\t\treason: res.note_to_payer ?? input.reason,\n\t\t\tmetadata: input.metadata,\n\t\t\tcreatedAt: res.create_time ? new Date(res.create_time) : new Date(),\n\t\t};\n\t}\n\n\t// ─── Subscription ─────────────────────────────────────────────────────\n\n\tasync createSubscription(\n\t\tinput: CreateSubscriptionInput,\n\t\topts?: PaymentOptions,\n\t): Promise<SubscriptionResult> {\n\t\tconst params: PayPalSubscriptionRequest = {\n\t\t\tplan_id: input.planId,\n\t\t\tstart_time: new Date(Date.now() + 60000).toISOString(),\n\t\t};\n\n\t\tif (input.customerEmail) {\n\t\t\tparams.subscriber = {\n\t\t\t\temail_address: input.customerEmail,\n\t\t\t};\n\t\t}\n\n\t\tconst res = await this.request<PayPalSubscriptionResponse>(\n\t\t\t\"POST\",\n\t\t\t\"/v1/billing/subscriptions\",\n\t\t\tparams,\n\t\t);\n\n\t\treturn {\n\t\t\tid: res.id,\n\t\t\tstatus: res.status === \"ACTIVE\" ? \"active\" : res.status === \"CANCELLED\" ? \"cancelled\" : \"incomplete\",\n\t\t\tprovider: this.id,\n\t\t\tplanId: res.plan_id ?? input.planId,\n\t\t\tcustomerEmail: input.customerEmail,\n\t\t\tmetadata: input.metadata,\n\t\t\tcreatedAt: res.create_time ? new Date(res.create_time) : new Date(),\n\t\t};\n\t}\n\n\t// ─── Webhook Verification ─────────────────────────────────────────────\n\n\tasync verifyWebhookSignature(\n\t\tpayload: string,\n\t\tsignature: string,\n\t\tsecret: string,\n\t): Promise<boolean> {\n\t\t// PayPal webhook verification via API\n\t\t// In production, use PayPal's webhook verification API:\n\t\t// POST /v1/notifications/verify-webhook-signature\n\t\t// For now, basic check\n\t\ttry {\n\t\t\tJSON.parse(payload) as PayPalWebhookBody;\n\t\t\treturn signature.length > 0;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tparseWebhookEvent(payload: string): WebhookEvent {\n\t\tconst body = JSON.parse(payload) as PayPalWebhookBody;\n\n\t\tconst typeMap: Record<string, WebhookEvent[\"type\"]> = {\n\t\t\t\"PAYMENT.CAPTURE.COMPLETED\": \"payment.completed\",\n\t\t\t\"PAYMENT.CAPTURE.DECLINED\": \"payment.failed\",\n\t\t\t\"PAYMENT.CAPTURE.REFUNDED\": \"refund.completed\",\n\t\t\t\"PAYMENT.CAPTURE.PENDING\": \"payment.created\",\n\t\t\t\"CHECKOUT.ORDER.APPROVED\": \"payment.completed\",\n\t\t\t\"BILLING.SUBSCRIPTION.CREATED\": \"subscription.created\",\n\t\t\t\"BILLING.SUBSCRIPTION.CANCELLED\": \"subscription.cancelled\",\n\t\t\t\"BILLING.SUBSCRIPTION.SUSPENDED\": \"subscription.suspended\",\n\t\t\t\"BILLING.SUBSCRIPTION.PAYMENT.SUCCEEDED\": \"subscription.payment_succeeded\",\n\t\t\t\"BILLING.SUBSCRIPTION.PAYMENT.FAILED\": \"subscription.payment_failed\",\n\t\t\t\"PAYMENT.REFUND.FAILED\": \"refund.failed\",\n\t\t};\n\n\t\tconst normalizedType = typeMap[body.event_type] ?? \"payment.created\";\n\t\tconst amount = body.resource.amount?.total\n\t\t\t? Number(body.resource.amount.total)\n\t\t\t: undefined;\n\n\t\treturn {\n\t\t\tid: body.id,\n\t\t\ttype: normalizedType,\n\t\t\tprovider: this.id,\n\t\t\trawData: body,\n\t\t\tentityId: body.resource.id,\n\t\t\tamount,\n\t\t\tcurrency: body.resource.amount?.currency,\n\t\t\tstatus: body.resource.state,\n\t\t\tcreatedAt: body.create_time ? new Date(body.create_time) : new Date(),\n\t\t};\n\t}\n}\n","import { Cron } from \"croner\";\n\nexport interface SchedulerDriver {\n\tschedule(\n\t\tpattern: string,\n\t\thandler: () => void | Promise<void>,\n\t\toptions?: unknown,\n\t): unknown;\n\tstopAll(): void;\n}\n\nexport class MemorySchedulerDriver implements SchedulerDriver {\n\tprivate jobs: Cron[] = [];\n\n\tschedule(\n\t\tpattern: string,\n\t\thandler: () => void | Promise<void>,\n\t\toptions?: unknown,\n\t) {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Options are passed dynamically\n\t\tconst job = new Cron(pattern, options as any, async () => {\n\t\t\ttry {\n\t\t\t\tawait handler();\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[Scheduler] Job failed:\", err);\n\t\t\t}\n\t\t});\n\t\tthis.jobs.push(job);\n\t\treturn job;\n\t}\n\n\tstopAll() {\n\t\tfor (const job of this.jobs) {\n\t\t\tjob.stop();\n\t\t}\n\t}\n}\n\n/**\n * Scheduler driver that uses Bun's native `Bun.cron()` API.\n *\n * Jobs are registered with the OS scheduler (crontab on Linux, launchd on\n * macOS, Task Scheduler on Windows) - they survive process restarts and\n * don't rely on an in-memory timer.\n *\n * Requires Bun >= 1.3.11.\n *\n * @example\n * import { Scheduler, BunCronSchedulerDriver } from \"@buntok/core\";\n *\n * const scheduler = new Scheduler(new BunCronSchedulerDriver());\n * scheduler.schedule(\"0 0 * * *\", () => cleanup());\n */\nexport class BunCronSchedulerDriver implements SchedulerDriver {\n\tprivate jobs: { stop(): void }[] = [];\n\n\tschedule(\n\t\tpattern: string,\n\t\thandler: () => void | Promise<void>,\n\t\t_options?: unknown,\n\t) {\n\t\tconst job = Bun.cron(pattern, async () => {\n\t\t\ttry {\n\t\t\t\tawait handler();\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[Scheduler] Job failed:\", err);\n\t\t\t}\n\t\t});\n\t\tthis.jobs.push(job);\n\t\treturn job;\n\t}\n\n\tstopAll() {\n\t\tfor (const job of this.jobs) {\n\t\t\tjob.stop();\n\t\t}\n\t}\n}\n\n// Global default driver for the decorator\nexport let defaultSchedulerDriver: SchedulerDriver =\n\tnew MemorySchedulerDriver();\n\nexport function setDefaultSchedulerDriver(driver: SchedulerDriver) {\n\tdefaultSchedulerDriver = driver;\n}\n\nexport class Scheduler {\n\tconstructor(private driver: SchedulerDriver = new MemorySchedulerDriver()) {}\n\n\tschedule(\n\t\tpattern: string,\n\t\thandler: () => void | Promise<void>,\n\t\toptions?: unknown,\n\t) {\n\t\treturn this.driver.schedule(pattern, handler, options);\n\t}\n\n\tstopAll() {\n\t\tthis.driver.stopAll();\n\t}\n}\n\n/**\n * Decorator to schedule a controller/service method as a cron job.\n *\n * Uses `context.addInitializer` so the job is bound to the **class instance**\n * rather than being scheduled at class-definition time. This means:\n *   - `this` inside the method works correctly (can access injected services).\n *   - The job is only scheduled when the class is instantiated (e.g. via\n *     `app.registerController(new MyController())`).\n *\n * @param pattern - Standard cron expression (e.g. `\"0 0 * * *\"` for daily at midnight)\n *\n * @example\n * ```ts\n * @Controller(\"/tasks\")\n * export class TaskController {\n *   constructor(private readonly cache: Cache) {}\n *\n *   @CronJob(\"0 0 * * *\")\n *   async dailyCleanup() {\n *     // `this` is the TaskController instance - fully works!\n *     await this.cache.deletePattern(\"tmp:*\");\n *   }\n * }\n * ```\n */\nexport function CronJob(pattern: string, options?: unknown) {\n\treturn (\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Required for Decorator inference\n\t\toriginalMethod: (...args: any[]) => any,\n\t\tcontext: ClassMethodDecoratorContext,\n\t) => {\n\t\tif (context.kind !== \"method\") {\n\t\t\tthrow new Error(\"@CronJob can only decorate methods\");\n\t\t}\n\n\t\t// addInitializer runs after the class instance is constructed,\n\t\t// giving us `this` bound to the actual instance.\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Required for 'this' binding\n\t\tcontext.addInitializer(function (this: any) {\n\t\t\tdefaultSchedulerDriver.schedule(\n\t\t\t\tpattern,\n\t\t\t\tasync () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait originalMethod.call(this);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error(`[Cron:${String(context.name)}] Job failed:`, err);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\toptions,\n\t\t\t);\n\t\t});\n\t};\n}\n","import { mkdir, stat, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { Middleware } from \"./app\";\nimport type { Context } from \"./context\";\nimport { BadRequestError } from \"./helpers/async-handler\";\n\nexport interface UploadedFile {\n\t/** Original name of the file */\n\toriginalName: string;\n\t/** Generated filename without extension (e.g., \"avatar-123\") */\n\tname: string;\n\t/** File extension with dot (e.g., \".png\") */\n\text: string;\n\t/** Size of the file in bytes */\n\tsize: number;\n\t/** MIME type of the file */\n\ttype: string;\n\t/** For MemoryStorage: the actual file data as ArrayBuffer */\n\tbuffer?: ArrayBuffer;\n\t/** For LocalDiskStorage: the absolute path where it was saved */\n\tpath?: string;\n}\n\n/**\n * Extended UploadedFile for image files processed with Bun.Image.\n * Only available when `outputFormat` is set in UploadFieldConfig.\n */\nexport interface ImageUploadedFile extends UploadedFile {\n\t/** Discriminant for runtime type narrowing */\n\tkind: \"image\";\n\t/** Image width in pixels */\n\twidth: number;\n\t/** Image height in pixels */\n\theight: number;\n\t/** Detected image format (e.g., \"png\", \"jpeg\", \"webp\") */\n\tformat: string;\n\t/** MIME type before conversion (only set when outputFormat differs from input) */\n\toriginalType?: string;\n\t/** File extension before conversion (only set when outputFormat differs from input) */\n\toriginalExt?: string;\n}\n\n/** Image MIME types that Bun.Image can process */\nconst IMAGE_MIME_TYPES = new Set([\n\t\"image/jpeg\",\n\t\"image/png\",\n\t\"image/gif\",\n\t\"image/webp\",\n\t\"image/avif\",\n\t\"image/bmp\",\n\t\"image/tiff\",\n]);\n\n/** Output format → { ext, type } mapping */\nconst OUTPUT_FORMAT_MAP: Record<string, { ext: string; type: string }> = {\n\twebp: { ext: \".webp\", type: \"image/webp\" },\n\tpng: { ext: \".png\", type: \"image/png\" },\n\tjpeg: { ext: \".jpg\", type: \"image/jpeg\" },\n\tavif: { ext: \".avif\", type: \"image/avif\" },\n};\n\nfunction isImageMime(type: string): boolean {\n\treturn IMAGE_MIME_TYPES.has(type);\n}\n\nasync function getImageMetadata(\n\tfile: File,\n): Promise<{ width: number; height: number; format: string } | null> {\n\tif (!isImageMime(file.type)) return null;\n\ttry {\n\t\tconst image = new Bun.Image(file);\n\t\tconst metadata = await image.metadata();\n\t\treturn {\n\t\t\twidth: metadata.width,\n\t\t\theight: metadata.height,\n\t\t\tformat: metadata.format,\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function convertImage(\n\tfile: File,\n\toutputFormat: keyof typeof OUTPUT_FORMAT_MAP,\n): Promise<File> {\n\tconst image = new Bun.Image(file);\n\t// Bun.Image methods (.png(), .jpeg(), etc.) return Promise<Buffer> at runtime,\n\t// but @types/bun types them as returning Image. Cast to fix.\n\tlet buffer: Buffer;\n\n\tswitch (outputFormat) {\n\t\tcase \"png\":\n\t\t\tbuffer = (await image.png().toBuffer()) as Buffer;\n\t\t\tbreak;\n\t\tcase \"jpeg\":\n\t\t\tbuffer = (await image.jpeg().toBuffer()) as Buffer;\n\t\t\tbreak;\n\t\tcase \"webp\":\n\t\t\tbuffer = (await image.webp().toBuffer()) as Buffer;\n\t\t\tbreak;\n\t\tcase \"avif\":\n\t\t\tbuffer = (await image.avif().toBuffer()) as Buffer;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbuffer = (await image.png().toBuffer()) as Buffer;\n\t}\n\n\tconst info = OUTPUT_FORMAT_MAP[outputFormat]!;\n\treturn new File([buffer], file.name.replace(/\\.[^.]+$/, info.ext), {\n\t\ttype: info.type,\n\t});\n}\n\nexport interface StorageDriver {\n\t/** Handle a single file from the FormData stream */\n\thandleFile(\n\t\tfile: File,\n\t\tname: string,\n\t\text: string,\n\t): Promise<UploadedFile> | UploadedFile;\n\t/** Delete a file by its path or filename. Returns true if deleted. */\n\tdeleteFile?(path: string): Promise<boolean>;\n}\n\n// Single source of truth - all supported MIME types and their magic bytes signatures.\n// The MimeType type is inferred from the keys.\nconst MAGIC_BYTES = {\n\t// Images\n\t\"image/jpeg\": [[0xff, 0xd8, 0xff]],\n\t\"image/png\": [[0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]],\n\t\"image/gif\": [[0x47, 0x49, 0x46, 0x38]], // GIF8\n\t\"image/webp\": [[0x52, 0x49, 0x46, 0x46]], // RIFF\n\t\"image/svg+xml\": [], // XML-based, no reliable magic bytes\n\t\"image/bmp\": [[0x42, 0x4d]], // BM\n\t\"image/tiff\": [\n\t\t[0x49, 0x49, 0x2a, 0x00], // Little-endian\n\t\t[0x4d, 0x4d, 0x00, 0x2a], // Big-endian\n\t],\n\t\"image/x-icon\": [\n\t\t[0x00, 0x00, 0x01, 0x00], // ICO\n\t\t[0x00, 0x00, 0x02, 0x00], // CUR\n\t],\n\t\"image/avif\": [[0x00, 0x00, 0x00]], // ftyp avif/mif1\n\t\"image/heic\": [[0x00, 0x00, 0x00]], // ftyp heic/mif1\n\t\"image/heif\": [[0x00, 0x00, 0x00]], // ftyp heif/mif1\n\n\t// Videos\n\t\"video/mp4\": [[0x00, 0x00, 0x00]], // ftyp\n\t\"video/webm\": [[0x1a, 0x45, 0xdf, 0xa3]], // EBML\n\t\"video/ogg\": [[0x4f, 0x67, 0x67, 0x53]], // OggS\n\t\"video/quicktime\": [[0x00, 0x00, 0x00]], // ftyp qt\n\t\"video/x-msvideo\": [[0x52, 0x49, 0x46, 0x46]], // RIFF\n\t\"video/x-matroska\": [[0x1a, 0x45, 0xdf, 0xa3]], // EBML\n\t\"video/mpeg\": [\n\t\t[0x00, 0x00, 0x01, 0xba],\n\t\t[0x00, 0x00, 0x01, 0xb3],\n\t],\n\n\t// Audio\n\t\"audio/mpeg\": [\n\t\t[0xff, 0xfb],\n\t\t[0xff, 0xf3],\n\t\t[0xff, 0xf2],\n\t],\n\t\"audio/mp3\": [\n\t\t[0xff, 0xfb],\n\t\t[0xff, 0xf3],\n\t\t[0xff, 0xf2],\n\t],\n\t\"audio/wav\": [[0x52, 0x49, 0x46, 0x46]], // RIFF\n\t\"audio/ogg\": [[0x4f, 0x67, 0x67, 0x53]], // OggS\n\t\"audio/webm\": [[0x1a, 0x45, 0xdf, 0xa3]], // EBML\n\t\"audio/aac\": [\n\t\t[0xff, 0xf1],\n\t\t[0xff, 0xf9],\n\t], // ADTS\n\t\"audio/flac\": [[0x66, 0x4c, 0x61, 0x43]], // fLaC\n\t\"audio/mp4\": [[0x00, 0x00, 0x00]], // ftyp\n\t\"audio/x-m4a\": [[0x00, 0x00, 0x00]], // ftyp M4A\n\n\t// Documents\n\t\"application/pdf\": [[0x25, 0x50, 0x44, 0x46]], // %PDF\n\t\"application/rtf\": [[0x7b, 0x5c, 0x72, 0x74, 0x66]], // {\\rtf\n\t\"text/plain\": [],\n\t\"text/csv\": [],\n\t\"text/html\": [],\n\t\"text/css\": [],\n\t\"text/javascript\": [],\n\t\"application/javascript\": [],\n\t\"application/json\": [],\n\t\"application/xml\": [],\n\t\"text/xml\": [],\n\n\t// Microsoft Office (OLE2)\n\t\"application/msword\": [[0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1]],\n\t\"application/vnd.ms-excel\": [\n\t\t[0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1],\n\t],\n\t\"application/vnd.ms-powerpoint\": [\n\t\t[0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1],\n\t],\n\n\t// Microsoft Office (OOXML - ZIP based)\n\t\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\": [\n\t\t[0x50, 0x4b, 0x03, 0x04],\n\t],\n\t\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\": [\n\t\t[0x50, 0x4b, 0x03, 0x04],\n\t],\n\t\"application/vnd.openxmlformats-officedocument.presentationml.presentation\": [\n\t\t[0x50, 0x4b, 0x03, 0x04],\n\t],\n\n\t// OpenDocument (ZIP based)\n\t\"application/vnd.oasis.opendocument.text\": [[0x50, 0x4b, 0x03, 0x04]],\n\t\"application/vnd.oasis.opendocument.spreadsheet\": [[0x50, 0x4b, 0x03, 0x04]],\n\t\"application/vnd.oasis.opendocument.presentation\": [[0x50, 0x4b, 0x03, 0x04]],\n\n\t// Archives\n\t\"application/zip\": [[0x50, 0x4b, 0x03, 0x04]],\n\t\"application/x-7z-compressed\": [[0x37, 0x7a, 0xaf, 0x1d]],\n\t\"application/x-rar-compressed\": [[0x52, 0x61, 0x72, 0x21, 0x1a, 0x07]],\n\t\"application/gzip\": [[0x1f, 0x8b]],\n\t\"application/x-tar\": [], // Check at offset 257: \"ustar\"\n\t\"application/x-bzip2\": [[0x42, 0x5a, 0x68]], // BZh\n\n\t// Fonts\n\t\"font/woff\": [[0x77, 0x4f, 0x46, 0x46]], // wOFF\n\t\"font/woff2\": [[0x77, 0x4f, 0x46, 0x32]], // wOF2\n\t\"font/ttf\": [\n\t\t[0x00, 0x01, 0x00, 0x00], // TrueType\n\t\t[0x4f, 0x54, 0x54, 0x4f], // OTTO (OpenType)\n\t],\n\t\"font/otf\": [[0x4f, 0x54, 0x54, 0x4f]], // OTTO\n\n\t// Other\n\t\"application/octet-stream\": [],\n} as const;\n\n/** Supported MIME types - inferred from the MAGIC_BYTES keys. */\nexport type MimeType = keyof typeof MAGIC_BYTES;\n\nexport interface UploadFieldConfig {\n\t/** Whether this file field is required. Defaults to false. */\n\trequired?: boolean;\n\t/** Max file size in bytes for this field */\n\tmaxFileSize?: number;\n\t/** Allowed MIME types for this field */\n\tallowedMimeTypes?: MimeType[];\n\t/** Custom filename generator for this field (overrides global filename) */\n\tfilename?: (\n\t\toriginalName: string,\n\t\tfile: File,\n\t) => { name: string; ext: string };\n\t/**\n\t * Force image conversion to this format on upload.\n\t * When set, the returned file type narrows to `ImageUploadedFile`\n\t * with `width`, `height`, `format`, and optional `originalType`/`originalExt`.\n\t *\n\t * Only applies to image MIME types (image/jpeg, image/png, image/gif, etc.).\n\t * Non-image files ignore this option.\n\t */\n\toutputFormat?: \"webp\" | \"png\" | \"jpeg\" | \"avif\";\n}\n\nexport interface UploadOptions {\n\t/** Destination storage driver (e.g., LocalDiskStorage or MemoryStorage) */\n\tstorage: StorageDriver;\n\t/** Global default filename generator (overridden by per-field filename) */\n\tfilename?: (\n\t\toriginalName: string,\n\t\tfile: File,\n\t) => { name: string; ext: string };\n\t/**\n\t * Global max file size in bytes.\n\t * Applied to all fields unless overridden by per-field `maxFileSize`.\n\t */\n\tmaxFileSize?: number;\n\t/**\n\t * Global allowed MIME types.\n\t * Applied to all fields unless overridden by per-field `allowedMimeTypes`.\n\t */\n\tallowedMimeTypes?: MimeType[];\n\t/**\n\t * Whitelist of accepted file field names.\n\t * Files with a field name not listed here will be silently ignored.\n\t * Each field has its own maxFileSize, allowedMimeTypes, and filename config\n\t * that override the global defaults when set.\n\t *\n\t * @example\n\t * fields: {\n\t *   avatar: { required: true, maxFileSize: 2 * 1024 * 1024, allowedMimeTypes: ['image/png'] },\n\t *   document: { required: true, maxFileSize: 10 * 1024 * 1024 },\n\t * }\n\t */\n\tfields?: Record<string, UploadFieldConfig>;\n\t/** Verify file magic bytes against expected MIME type. Defaults to true. */\n\tverifyMagicBytes?: boolean;\n}\n\nexport type UploadOptionsWithFields<\n\tF extends Record<string, UploadFieldConfig>,\n> = Omit<UploadOptions, \"fields\"> & { fields?: F };\n\nexport interface ParseUploadResult<\n\tF extends Record<string, UploadFieldConfig> = Record<\n\t\tstring,\n\t\tUploadFieldConfig\n\t>,\n> {\n\t/**\n\t * All form fields - text fields are `string`, file fields are typed based on config.\n\t *\n\t * When `outputFormat` is set, the field narrows to `ImageUploadedFile`\n\t * with `width`, `height`, `format`, and optional `originalType`/`originalExt`.\n\t *\n\t * @example\n\t * result.fields.name      // string (text field)\n\t * result.fields.avatar    // ImageUploadedFile (outputFormat: \"webp\")\n\t * result.fields.document  // UploadedFile (no outputFormat)\n\t */\n\tfields: {\n\t\t[K in keyof F]: F[K] extends { outputFormat: any }\n\t\t\t? F[K] extends { required: true }\n\t\t\t\t? ImageUploadedFile\n\t\t\t\t: ImageUploadedFile | undefined\n\t\t\t: F[K] extends { required: true }\n\t\t\t\t? UploadedFile\n\t\t\t\t: F[K] extends { maxFileSize: any } | { allowedMimeTypes: any }\n\t\t\t\t\t? UploadedFile | undefined\n\t\t\t\t\t: UploadedFile | UploadedFile[] | undefined;\n\t} & Record<string, string>;\n\t/** Array of files that were successfully uploaded/processed (all files, flattened) */\n\tfiles: (UploadedFile | ImageUploadedFile)[];\n}\n\nexport class LocalDiskStorage implements StorageDriver {\n\tconstructor(private destination: string) {}\n\n\tasync handleFile(\n\t\tfile: File,\n\t\tname: string,\n\t\text: string,\n\t): Promise<UploadedFile> {\n\t\t// Ensure directory exists\n\t\ttry {\n\t\t\tawait stat(this.destination);\n\t\t} catch {\n\t\t\tawait mkdir(this.destination, { recursive: true });\n\t\t}\n\n\t\tconst filename = `${name}${ext}`;\n\t\tconst filePath = join(this.destination, filename);\n\t\tawait Bun.write(filePath, file);\n\n\t\treturn {\n\t\t\toriginalName: file.name,\n\t\t\tname,\n\t\t\text,\n\t\t\tsize: file.size,\n\t\t\ttype: file.type,\n\t\t\tpath: filePath,\n\t\t};\n\t}\n\n\tasync deleteFile(filePath: string): Promise<boolean> {\n\t\ttry {\n\t\t\tawait unlink(filePath);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n}\n\nexport class MemoryStorage implements StorageDriver {\n\tasync handleFile(\n\t\tfile: File,\n\t\tname: string,\n\t\text: string,\n\t): Promise<UploadedFile> {\n\t\tconst buffer = await file.arrayBuffer();\n\t\treturn {\n\t\t\toriginalName: file.name,\n\t\t\tname,\n\t\t\text,\n\t\t\tsize: file.size,\n\t\t\ttype: file.type,\n\t\t\tbuffer,\n\t\t};\n\t}\n\n\tasync deleteFile(_filePath: string): Promise<boolean> {\n\t\t// MemoryStorage holds files in memory - nothing to delete on disk.\n\t\treturn true;\n\t}\n}\n\nfunction getFileExtension(originalName: string): string {\n\tconst extIndex = originalName.lastIndexOf(\".\");\n\tif (extIndex !== -1) {\n\t\treturn originalName.substring(extIndex);\n\t}\n\treturn \"\";\n}\n\nconst defaultFilenameGenerator = (originalName: string) => {\n\tconst ext = getFileExtension(originalName);\n\tconst name = ext\n\t\t? originalName.substring(0, originalName.length - ext.length)\n\t\t: originalName;\n\treturn { name: `${name}-${crypto.randomUUID()}`, ext };\n};\n\nfunction resolveFilename(\n\toriginalName: string,\n\tfile: File,\n\tfieldFn?: (originalName: string, file: File) => { name: string; ext: string },\n\tglobalFn?: (\n\t\toriginalName: string,\n\t\tfile: File,\n\t) => { name: string; ext: string },\n): { name: string; ext: string } {\n\tconst ext = getFileExtension(originalName);\n\tconst generateFn = fieldFn ?? globalFn ?? defaultFilenameGenerator;\n\tconst result = generateFn(originalName, file);\n\n\t// Ensure ext always has the dot prefix\n\tconst finalExt = result.ext.startsWith(\".\") ? result.ext : ext;\n\n\treturn { name: result.name, ext: finalExt };\n}\n\nasync function verifyFileSignature(\n\tfile: File,\n\texpectedType: string,\n): Promise<boolean> {\n\tconst signatures = MAGIC_BYTES[expectedType as keyof typeof MAGIC_BYTES];\n\n\t// No magic bytes defined for this type → skip verification\n\tif (!signatures || signatures.length === 0) {\n\t\treturn true;\n\t}\n\n\t// Read first 16 bytes (covers most signatures)\n\tconst buffer = await file.arrayBuffer();\n\tconst bytes = new Uint8Array(buffer.slice(0, 16));\n\n\t// Check if any of the signatures match\n\treturn signatures.some((sig) => sig.every((byte, i) => bytes[i] === byte));\n}\n\n/**\n * Parses `multipart/form-data` request, separating standard fields from files.\n * Streams files into the configured storage driver with validation.\n *\n * Throws `BadRequestError` if validation fails (size, MIME type, or required fields).\n *\n * @example\n * const result = await handleUploads(ctx, {\n *   storage: new LocalDiskStorage('./uploads'),\n *   maxFileSize: 2 * 1024 * 1024,\n *   allowedMimeTypes: ['image/png', 'image/jpeg'],\n *   fields: {\n *     avatar: { required: true },\n *     document: { required: true, maxFileSize: 10 * 1024 * 1024 },\n *   },\n * });\n * // result.fields.avatar  → UploadedFile (required = true)\n * // result.fields.document → UploadedFile (required = true)\n */\nexport async function handleUploads<\n\tF extends Record<string, UploadFieldConfig> = Record<\n\t\tstring,\n\t\tUploadFieldConfig\n\t>,\n>(\n\t// biome-ignore lint/suspicious/noExplicitAny: Context is generic\n\tctx: Context<any, any>,\n\toptions: UploadOptionsWithFields<F>,\n): Promise<ParseUploadResult<F>> {\n\tconst contentType = ctx.request.headers.get(\"content-type\") || \"\";\n\tif (!contentType.includes(\"multipart/form-data\")) {\n\t\tthrow new BadRequestError(\n\t\t\t\"Invalid content-type. Must be multipart/form-data\",\n\t\t);\n\t}\n\n\t// biome-ignore lint/suspicious/noExplicitAny: Undici types conflict with lib.dom FormData\n\tlet formData: any;\n\ttry {\n\t\tformData = await ctx.formData();\n\t} catch (_err) {\n\t\tthrow new BadRequestError(\"Failed to parse form data\");\n\t}\n\n\tconst textFields: Record<string, string> = {};\n\tconst files: (UploadedFile | ImageUploadedFile)[] = [];\n\tconst fileMap: Record<string, UploadedFile | ImageUploadedFile | (UploadedFile | ImageUploadedFile)[]> = {};\n\n\tconst fieldWhitelist = options.fields;\n\n\tfor (const [key, value] of formData.entries()) {\n\t\tif (value instanceof File) {\n\t\t\t// If a fields whitelist is defined, ignore unknown file fields\n\t\t\tif (fieldWhitelist && !(key in fieldWhitelist)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Per-field config\n\t\t\tconst fieldConfig = fieldWhitelist?.[key];\n\n\t\t\t// Validation: Size - per-field config overrides global\n\t\t\tconst maxFileSize = fieldConfig?.maxFileSize ?? options.maxFileSize;\n\t\t\tif (maxFileSize && value.size > maxFileSize) {\n\t\t\t\tthrow new BadRequestError(\n\t\t\t\t\t`File \"${value.name}\" in field \"${key}\" exceeds max size of ${maxFileSize} bytes`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Validation: MIME Type - per-field config overrides global\n\t\t\tconst allowedMimeTypes =\n\t\t\t\tfieldConfig?.allowedMimeTypes ?? options.allowedMimeTypes;\n\t\t\tif (allowedMimeTypes && !allowedMimeTypes.includes(value.type as MimeType)) {\n\t\t\t\tthrow new BadRequestError(\n\t\t\t\t\t`File type \"${value.type}\" is not allowed for field \"${key}\" (file: \"${value.name}\")`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Validation: Magic Bytes - verify file signature matches claimed MIME type\n\t\t\tif (options.verifyMagicBytes !== false) {\n\t\t\t\tconst isValid = await verifyFileSignature(value, value.type);\n\t\t\t\tif (!isValid) {\n\t\t\t\t\tthrow new BadRequestError(\n\t\t\t\t\t\t`File \"${value.name}\" has invalid magic bytes for type \"${value.type}\"`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Process file\n\t\t\tconst { name, ext } = resolveFilename(\n\t\t\t\tvalue.name,\n\t\t\t\tvalue,\n\t\t\t\tfieldConfig?.filename,\n\t\t\t\toptions.filename,\n\t\t\t);\n\n\t\t\t// Check if image conversion is requested\n\t\t\tconst outputFormat = fieldConfig?.outputFormat;\n\t\t\tlet fileToStore = value;\n\t\t\tlet finalExt = ext;\n\t\t\tlet finalType = value.type;\n\n\t\t\tif (outputFormat && isImageMime(value.type)) {\n\t\t\t\tconst info = OUTPUT_FORMAT_MAP[outputFormat];\n\t\t\t\tif (info) {\n\t\t\t\t\tfileToStore = await convertImage(value, outputFormat);\n\t\t\t\t\tfinalExt = info.ext;\n\t\t\t\t\tfinalType = info.type;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst uploaded = await options.storage.handleFile(fileToStore, name, finalExt);\n\n\t\t\t// Image metadata extraction + type narrowing\n\t\t\tlet result: UploadedFile | ImageUploadedFile;\n\t\t\tif (outputFormat && isImageMime(value.type)) {\n\t\t\t\tconst metadata = await getImageMetadata(fileToStore);\n\t\t\t\tconst imgResult: ImageUploadedFile = {\n\t\t\t\t\t...uploaded,\n\t\t\t\t\tkind: \"image\",\n\t\t\t\t\twidth: metadata?.width ?? 0,\n\t\t\t\t\theight: metadata?.height ?? 0,\n\t\t\t\t\tformat: OUTPUT_FORMAT_MAP[outputFormat]?.ext.slice(1) ?? outputFormat,\n\t\t\t\t\ttype: finalType,\n\t\t\t\t\text: finalExt,\n\t\t\t\t};\n\t\t\t\t// Track original type if conversion happened\n\t\t\t\tif (value.type !== finalType) {\n\t\t\t\t\timgResult.originalType = value.type;\n\t\t\t\t\timgResult.originalExt = getFileExtension(value.name);\n\t\t\t\t}\n\t\t\t\tresult = imgResult;\n\t\t\t} else {\n\t\t\t\tresult = uploaded;\n\t\t\t}\n\n\t\t\tfiles.push(result);\n\n\t\t\t// Build fileMap: if same key appears multiple times → array\n\t\t\tif (key in fileMap) {\n\t\t\t\tconst existing = fileMap[key];\n\t\t\t\tif (Array.isArray(existing)) {\n\t\t\t\t\texisting.push(result);\n\t\t\t\t} else {\n\t\t\t\t\tfileMap[key] = [existing as UploadedFile, result];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfileMap[key] = result;\n\t\t\t}\n\t\t} else {\n\t\t\ttextFields[key] = value.toString();\n\t\t}\n\t}\n\n\t// Validate required fields\n\tif (fieldWhitelist) {\n\t\tfor (const [fieldName, config] of Object.entries(fieldWhitelist)) {\n\t\t\tif (config.required && !(fieldName in fileMap)) {\n\t\t\t\tthrow new BadRequestError(\n\t\t\t\t\t`Required file field \"${fieldName}\" is missing`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tfields: { ...textFields, ...fileMap },\n\t\tfiles,\n\t} as ParseUploadResult<F>;\n}\n\n/**\n * Middleware that automatically parses multipart uploads and populates\n * `ctx.store.files` and `ctx.store.fields`.\n *\n * ⚠️ Throws `BadRequestError` on validation failure - ensure your route\n * handler uses `asyncHandler()` or has try/catch to propagate the error\n * to the global error handler.\n */\nexport function uploader(options: UploadOptions): Middleware {\n\treturn async (ctx, next) => {\n\t\tconst result = await handleUploads(ctx, options);\n\n\t\tctx.store.files = result.files;\n\t\tctx.store.fields = result.fields;\n\n\t\treturn next();\n\t};\n}\n\n/**\n * Delete an uploaded file from the storage driver.\n *\n * @param storage - The StorageDriver instance used for the upload\n * @param file - The UploadedFile object (needs `.path` for LocalDiskStorage)\n * @returns true if deleted, false if not found or error\n *\n * @example\n * const result = await handleUploads(ctx, options);\n * const file = result.fileMap.avatar as UploadedFile;\n * await deleteUploadedFile(options.storage, file);\n */\nexport async function deleteUploadedFile(\n\tstorage: StorageDriver,\n\tfile: UploadedFile,\n): Promise<boolean> {\n\tif (!storage.deleteFile) {\n\t\treturn false;\n\t}\n\tconst target = file.path ?? `${file.name}${file.ext}`;\n\treturn storage.deleteFile(target);\n}\n","import type { ServerWebSocket } from \"bun\";\nimport { z } from \"zod\";\nimport type { WSData, WSHandler } from \"./app\";\n\n// Extended WSData with heartbeat\ninterface WSDataWithHeartbeat<DI> extends WSData<DI> {\n\theartbeat?: {\n\t\tinterval: number;\n\t\ttimer: ReturnType<typeof setInterval> | null;\n\t\talive: boolean;\n\t};\n}\n\n// ── Pluggable PubSub (mirip StorageDriver) ──\nexport interface WSPubSub {\n\t/** Publish ke channel - memory default, Redis pluggable */\n\tpublish(channel: string, message: string | object): Promise<void> | void;\n\t/** Subscribe - return unsubscribe */\n\tsubscribe(channel: string, handler: (message: string | object) => void): () => void;\n}\n\nexport class MemoryWSPubSub implements WSPubSub {\n\tprivate channels = new Map<string, Set<(m: string | object) => void>>();\n\tpublish(channel: string, message: string | object): 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 { cb(message); } catch {}\n\t\t}\n\t}\n\tsubscribe(channel: string, handler: (m: string | object) => void): () => void {\n\t\tlet set = this.channels.get(channel);\n\t\tif (!set) { set = new Set(); this.channels.set(channel, set); }\n\t\tset.add(handler);\n\t\treturn () => set!.delete(handler);\n\t}\n}\n\n// ── Rate limit store pluggable ──\nexport interface WSRateLimitStore {\n\tincr(key: string, windowMs: number): Promise<number> | number;\n}\n\nexport class MemoryWSRateLimitStore implements WSRateLimitStore {\n\tprivate map = new Map<string, { count: number; resetAt: number }>();\n\tincr(key: string, windowMs: number): number {\n\t\tconst now = Date.now();\n\t\tconst ent = this.map.get(key);\n\t\tif (!ent || now > ent.resetAt) {\n\t\t\tthis.map.set(key, { count: 1, resetAt: now + windowMs });\n\t\t\treturn 1;\n\t\t}\n\t\tent.count++;\n\t\treturn ent.count;\n\t}\n}\n\n/**\n * Validate a WebSocket message against a Zod schema.\n */\nexport function validateWSMessage<T>(\n\tschema: z.ZodSchema<T>,\n\tmessage: string | Buffer,\n): { success: true; data: T } | { success: false; errors: z.ZodError } {\n\tconst raw = typeof message === \"string\" ? message : message.toString();\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terrors: new z.ZodError([\n\t\t\t\t{\n\t\t\t\t\tcode: \"custom\",\n\t\t\t\t\tmessage: \"Invalid JSON\",\n\t\t\t\t\tpath: [],\n\t\t\t\t},\n\t\t\t]),\n\t\t};\n\t}\n\n\tconst result = schema.safeParse(parsed);\n\tif (result.success) {\n\t\treturn { success: true, data: result.data };\n\t}\n\treturn { success: false, errors: result.error };\n}\n\n/**\n * Room class - in-memory default, pluggable ke Redis via pubSub\n * Mirip LocalDiskStorage vs MemoryStorage pattern.\n *\n * @example Memory (default)\n * ```ts\n * const room = new Room(\"chat\");\n * app.ws(\"/chat\", { open: (ws)=> room.join(ws), message: (ws,msg)=> room.broadcast(msg, ws) })\n * ```\n * @example Redis (pluggable)\n * ```ts\n * class RedisWSPubSub implements WSPubSub { constructor(private redis: Redis){} publish(ch,msg){ redis.publish(ch, typeof msg===\"object\"?JSON.stringify(msg):msg as string)} subscribe(ch,cb){ redis.subscribe(ch,(m)=>cb(m)); return ()=>redis.unsubscribe(ch)} }\n * const room = new Room(\"chat\", { pubSub: new RedisWSPubSub(redis) })\n * ```\n */\nexport interface RoomOptions {\n\tpubSub?: WSPubSub;\n\tchannel?: string;\n}\nexport class Room<DI = Record<string, unknown>> {\n\tpublic readonly name: string;\n\tprivate members = new Set<ServerWebSocket<WSData<DI>>>();\n\tprivate pubSub?: WSPubSub;\n\tprivate channel: string;\n\tprivate unsubscribe?: () => void;\n\n\tconstructor(name: string, opts?: RoomOptions | WSPubSub) {\n\t\tthis.name = name;\n\t\tif (opts && typeof (opts as WSPubSub).publish === \"function\") {\n\t\t\tthis.pubSub = opts as WSPubSub;\n\t\t\tthis.channel = `buntok:ws:${name}`;\n\t\t} else {\n\t\t\tconst o = opts as RoomOptions | undefined;\n\t\t\tthis.pubSub = o?.pubSub;\n\t\t\tthis.channel = o?.channel ?? `buntok:ws:${name}`;\n\t\t}\n\t\tif (this.pubSub) {\n\t\t\tthis.unsubscribe = this.pubSub.subscribe(this.channel, (msg) => {\n\t\t\t\tconst data = typeof msg === \"object\" ? JSON.stringify(msg) : (msg as string);\n\t\t\t\tfor (const m of [...this.members]) {\n\t\t\t\t\tif (m.readyState === 1) {\n\t\t\t\t\t\ttry { m.send(data); } catch {}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tjoin(ws: ServerWebSocket<WSData<DI>>): void {\n\t\tthis.members.add(ws);\n\t\t// Also Bun native subscribe untuk fan-out kernel (optional, not required jika pakai pubSub)\n\t\ttry { (ws as unknown as { subscribe?: (c:string)=>void }).subscribe?.(this.channel); } catch {}\n\t}\n\n\tleave(ws: ServerWebSocket<WSData<DI>>): void {\n\t\tthis.members.delete(ws);\n\t\ttry { (ws as unknown as { unsubscribe?: (c:string)=>void }).unsubscribe?.(this.channel); } catch {}\n\t}\n\n\tbroadcast(message: string | object, exclude?: ServerWebSocket<WSData<DI>>): void {\n\t\tif (this.pubSub) {\n\t\t\t// via pubSub (Redis) - akan di-fanout ke semua instance termasuk self via subscribe\n\t\t\tconst r = this.pubSub.publish(this.channel, message);\n\t\t\tif (r instanceof Promise) r.catch(() => this.localBroadcast(message, exclude));\n\t\t\treturn;\n\t\t}\n\t\tthis.localBroadcast(message, exclude);\n\t}\n\n\tprivate localBroadcast(message: string | object, exclude?: ServerWebSocket<WSData<DI>>): void {\n\t\tconst data = typeof message === \"object\" ? JSON.stringify(message) : message;\n\t\t// Backpressure check: jika bufferedAmount tinggi, skip slow client\n\t\tfor (const member of [...this.members]) {\n\t\t\tif (member !== exclude && member.readyState === 1) {\n\t\t\t\ttry {\n\t\t\t\t\tconst buffered = (member as unknown as { getBufferedAmount?: () => number }).getBufferedAmount?.() ?? 0;\n\t\t\t\t\tif (buffered > 1024 * 1024) continue; // drop jika >1MB buffered\n\t\t\t\t\tmember.send(data);\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t}\n\t}\n\n\tsendAll(message: string | object): void {\n\t\tthis.broadcast(message);\n\t}\n\n\tgetMembers(): ServerWebSocket<WSData<DI>>[] {\n\t\treturn Array.from(this.members);\n\t}\n\n\tget size(): number {\n\t\treturn this.members.size;\n\t}\n\n\tget isEmpty(): boolean {\n\t\treturn this.members.size === 0;\n\t}\n\n\thas(ws: ServerWebSocket<WSData<DI>>): boolean {\n\t\treturn this.members.has(ws);\n\t}\n\n\tcloseAll(): void {\n\t\tif (this.unsubscribe) { try { this.unsubscribe(); } catch {} }\n\t\tfor (const member of [...this.members]) {\n\t\t\ttry { member.close(1000, \"Room closed\"); } catch {}\n\t\t}\n\t\tthis.members.clear();\n\t}\n\n\t/** Filtered broadcast mirip SSEBroadcaster.broadcastWhere */\n\tbroadcastWhere(predicate: (ws: ServerWebSocket<WSData<DI>>) => boolean, message: string | object): void {\n\t\tconst data = typeof message === \"object\" ? JSON.stringify(message) : message;\n\t\tfor (const member of [...this.members]) {\n\t\t\tif (member.readyState !== 1) continue;\n\t\t\tif (predicate(member)) {\n\t\t\t\ttry { member.send(data); } catch {}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * WebSocket heartbeat - 30s fixed, Bun-only\n * Fix: pong event reset alive (bukan message/drain)\n */\nexport function wsHeartbeat<DI = Record<string, unknown>>(\n\tinterval = 30_000,\n): WSHandler<DI> {\n\treturn {\n\t\topen: (ws: ServerWebSocket<WSData<DI>>) => {\n\t\t\tconst wsData = ws.data as WSDataWithHeartbeat<DI>;\n\t\t\twsData.heartbeat = {\n\t\t\t\tinterval,\n\t\t\t\ttimer: null as ReturnType<typeof setInterval> | null,\n\t\t\t\talive: true,\n\t\t\t};\n\t\t\twsData.heartbeat.timer = setInterval(() => {\n\t\t\t\tconst hb = (ws.data as WSDataWithHeartbeat<DI>).heartbeat;\n\t\t\t\tif (!hb) return;\n\t\t\t\tif (!hb.alive) {\n\t\t\t\t\ttry { ws.close(4000, \"Heartbeat timeout\"); } catch {}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\thb.alive = false;\n\t\t\t\ttry { ws.ping(); } catch {}\n\t\t\t}, interval);\n\t\t},\n\t\t// `pong` handler khusus - akan di-wire di app.ts websocket.pong\n\t\t// fallback untuk Bun versi lama: message juga reset (compat)\n\t\tmessage: (ws: ServerWebSocket<WSData<DI>>) => {\n\t\t\tconst wsData = ws.data as WSDataWithHeartbeat<DI>;\n\t\t\tif (wsData.heartbeat) wsData.heartbeat.alive = true;\n\t\t},\n\t\tclose: (ws: ServerWebSocket<WSData<DI>>) => {\n\t\t\tconst wsData = ws.data as WSDataWithHeartbeat<DI>;\n\t\t\tif (wsData.heartbeat?.timer) clearInterval(wsData.heartbeat.timer);\n\t\t},\n\t\t// drain tidak reset alive lagi (fix drain bug)\n\t} as unknown as WSHandler<DI>;\n}\n\n/** Internal helper untuk app.ts - reset pong */\nexport function wsHeartbeatPong<DI>(ws: ServerWebSocket<WSData<DI>>): void {\n\tconst wsData = ws.data as unknown as WSDataWithHeartbeat<DI>;\n\tif (wsData.heartbeat) wsData.heartbeat.alive = true;\n}\n\n/**\n * WebSocket rate limiter - in-memory default, pluggable ke Redis\n * @example\n * const limiter = wsRateLimit({ windowMs: 1000, max: 10 })\n * app.ws(\"/chat\", { ...limiter, message: (ws,msg)=>{} })\n */\nexport interface WSRateLimitOptions<DI = Record<string, unknown>> {\n\twindowMs?: number;\n\tmax?: number;\n\tstore?: WSRateLimitStore;\n\tkeyGenerator?: (ws: ServerWebSocket<WSData<DI>>) => string;\n\t/** Close code saat limit */\n\tcloseCode?: number;\n}\nexport function wsRateLimit<DI = Record<string, unknown>>(opts: WSRateLimitOptions<DI> = {}): WSHandler<DI> {\n\tconst windowMs = opts.windowMs ?? 1000;\n\tconst max = opts.max ?? 20;\n\tconst store = opts.store ?? new MemoryWSRateLimitStore();\n\tconst keyGen = opts.keyGenerator ?? ((ws: ServerWebSocket<WSData<DI>>) => (ws.data.ctx.ip || \"unknown\"));\n\tconst closeCode = opts.closeCode ?? 1013;\n\treturn {\n\t\tmessage: (ws: ServerWebSocket<WSData<DI>>) => {\n\t\t\tconst key = keyGen(ws);\n\t\t\tconst count = store.incr(key, windowMs);\n\t\t\tconst c = count instanceof Promise ? 0 : count;\n\t\t\t// async case handled via promise\n\t\t\tif (count instanceof Promise) {\n\t\t\t\tcount.then((n) => { if (n > max) try { ws.close(closeCode, \"Rate limited\"); } catch {} });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (c > max) {\n\t\t\t\ttry { ws.close(closeCode, \"Rate limited\"); } catch {}\n\t\t\t}\n\t\t},\n\t} as WSHandler<DI>;\n}\n\n/**\n * WebSocket authentication middleware - pluggable\n */\nexport function wsAuth<DI extends Record<string, unknown>, TAuth = unknown>(\n\tauthenticate: (ws: ServerWebSocket<WSData<DI>>) => Promise<TAuth | null>,\n): WSHandler<DI> {\n\treturn {\n\t\topen: async (ws) => {\n\t\t\ttry {\n\t\t\t\tconst authData = await authenticate(ws);\n\t\t\t\tif (authData === null) {\n\t\t\t\t\tws.close(4001, \"Unauthorized\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t(ws.data as unknown as Record<string, unknown>).auth = authData;\n\t\t\t} catch {\n\t\t\t\tws.close(4001, \"Unauthorized\");\n\t\t\t}\n\t\t},\n\t} as WSHandler<DI>;\n}\n"],"mappings":"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","names":["import_node_fs","import_node_path","import_zod","chunk","hash","import_node_path","result","LogLevel","findLib","result","EMPTY_PARAMS","ctx","startTime","SSE","base64UrlEncode","value","AUTHORIZATION_ENDPOINT","TOKEN_ENDPOINT","AUTHORIZATION_ENDPOINT","TOKEN_ENDPOINT","ISSUER","base64UrlEncode","groupBy","sep","hash","toHex","toArray","res","truncate","DEFAULT_OPTIONS","import_zod","delay","import_zod","API_BASE","API_BASE_PROD","import_node_path","import_zod","__dirname"]}