@coderbuzz/ken 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/dist/LICENSE +21 -0
- package/dist/README.md +41 -0
- package/dist/bun-GUK26ACN.js +281 -0
- package/dist/bun-GUK26ACN.js.map +1 -0
- package/dist/chunk-2BOPD5H7.js +34 -0
- package/dist/chunk-2BOPD5H7.js.map +1 -0
- package/dist/chunk-2MK26YDD.js +269 -0
- package/dist/chunk-2MK26YDD.js.map +1 -0
- package/dist/chunk-DPU3PBLP.js +815 -0
- package/dist/chunk-DPU3PBLP.js.map +1 -0
- package/dist/chunk-WTV4URUZ.js +122 -0
- package/dist/chunk-WTV4URUZ.js.map +1 -0
- package/dist/deno-LZU5JBGL.js +250 -0
- package/dist/deno-LZU5JBGL.js.map +1 -0
- package/dist/index.d.ts +2783 -0
- package/dist/index.js +2728 -0
- package/dist/index.js.map +1 -0
- package/dist/node-JLUTIPEN.js +816 -0
- package/dist/node-JLUTIPEN.js.map +1 -0
- package/dist/package.json +13 -0
- package/dist/uws-VNY2LPIZ.js +622 -0
- package/dist/uws-VNY2LPIZ.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/app.ts","../src/runtime/index.ts","../src/core/server.ts","../src/utils/encoding.ts","../src/utils/encryption.ts","../src/utils/memoize.ts","../src/utils/compress.ts","../src/utils/file.ts","../src/middleware/basic-auth.ts","../src/middleware/bearer-auth.ts","../src/middleware/body-limit.ts","../src/middleware/cache.ts","../src/middleware/compress.ts","../src/middleware/cors.ts","../src/middleware/csrf.ts","../src/middleware/etag.ts","../src/middleware/ip-restriction.ts","../src/middleware/jwk.ts","../src/middleware/jwt.ts","../src/middleware/logger.ts","../src/middleware/request-id.ts","../src/middleware/secure-headers.ts","../src/middleware/session.ts","../src/middleware/timeout.ts","../src/middleware/timing.ts","../src/ws/codec.ts","../src/middleware/ws-client-protocol.ts","../src/ws/client.ts"],"sourcesContent":["/**\n * Ken Framework - App\n * Type-safe routing with schema validation and middleware support\n * \n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport { Router, type Handler } from './router';\nimport {\n type Context,\n type Schema,\n type StateMiddleware,\n type MiddlewareHandler,\n type ErrorHandler,\n type Flatten,\n} from '../context/types';\nimport { type WsHandler, type WsOptions, type WsRoute } from '../ws/types';\n\n/**\n * Infer state shape from middleware definitions.\n * Excludes middleware with void return types.\n */\nexport type InferState<T extends StateMiddleware> = Flatten<{\n [K in keyof T as Awaited<ReturnType<T[K]>> extends void ? never : K]: Exclude<Awaited<ReturnType<T[K]>>, Response>;\n}>;\n\n/**\n * Typed handler function\n */\nexport type TypedHandler<\n S extends Schema = {},\n P extends string = string,\n TState = {}\n> = (ctx: Context<S, P, TState>) => any;\n\n/**\n * App - Type-safe router with schema validation\n * \n * Provides full type inference for:\n * - Route parameters from path patterns\n * - Query/headers/cookies/body from schema validators\n * - State from middleware definitions\n * \n * @template TState - Accumulated middleware state type\n */\nexport class App<TState extends StateMiddleware = {}> extends Router {\n // Middleware patterns\n private middleware: Array<{\n pattern: string;\n state: StateMiddleware;\n }> = [];\n\n /** App-level error handler */\n private _onError?: ErrorHandler;\n\n /** Not-found handler for this app */\n private _notFoundHandler?: Handler;\n\n /** Accumulated not-found entries from child apps (via .use() and .define()) */\n private _notFoundEntries: Array<{\n prefix: string;\n handler: Handler;\n schema?: Schema;\n }> = [];\n\n /** WebSocket route registrations */\n public wsRoutes: WsRoute<any>[] = [];\n\n /**\n * Set app-level error handler.\n * Called when route handlers or middleware throw errors.\n * Route-level onError (in schema) takes priority over app-level.\n *\n * @param handler - Error handler function\n *\n * @example\n * ```ts\n * app.onError((error, ctx) => {\n * console.error(ctx.method, ctx.url, error);\n * return Response.json(\n * { status: 500, message: error instanceof Error ? error.message : 'Internal Server Error' },\n * { status: 500 }\n * );\n * });\n * ```\n */\n onError(handler: ErrorHandler): void {\n this._onError = handler;\n }\n\n /**\n * Set custom 404 Not Found handler.\n * Called when no route matches the request.\n * Supports nested configuration via .use() prefix scoping.\n *\n * @param handler - Handler function that receives Context\n *\n * @example\n * ```ts\n * // App-level\n * app.notFound((ctx) => {\n * return Response.json({ error: 'Not Found', path: ctx.url }, { status: 404 });\n * });\n *\n * // Sub-app with prefix scoping\n * const api = new App();\n * api.notFound((ctx) => Response.json({ error: 'API Not Found' }, { status: 404 }));\n * app.use('/api', api);\n *\n * // Define scope with middleware state\n * app.define({ auth: (ctx) => verifyAuth(ctx) }, (app) => {\n * app.notFound((ctx) => Response.json({ error: 'Protected', user: ctx.state.auth }, { status: 404 }));\n * });\n * ```\n */\n notFound(handler: TypedHandler<{}, string, TState>): void {\n this._notFoundHandler = handler as Handler;\n }\n\n /**\n * Apply middleware to routes matching pattern.\n * Supports both side-effect middleware (function) and state-producing middleware (object).\n * \n * @param pattern - Route pattern (default \"/*\" for all routes)\n * @param stateOrHandler - State middleware object or handler function\n * \n * @example\n * ```ts\n * // Side-effect middleware (no state, just side effects)\n * app.apply('/*', (ctx) => { console.log(ctx.method, ctx.url); });\n * \n * // State-producing middleware (adds to ctx.state)\n * app.apply('/*', { auth: (ctx) => verifyAuth(ctx) });\n * ```\n */\n apply(pattern: string, handler: MiddlewareHandler): void;\n apply(pattern: string, state: StateMiddleware): void;\n apply(pattern: string = '/*', stateOrHandler: StateMiddleware | MiddlewareHandler): void {\n if (typeof stateOrHandler === 'function') {\n // Auto-generate random key for side-effect middleware\n const randomKey = `_mw_${Math.random().toString(36).substring(2, 11)}`;\n this.middleware.push({ pattern, state: { [randomKey]: stateOrHandler } });\n } else {\n this.middleware.push({ pattern, state: stateOrHandler });\n }\n }\n\n /**\n * Define middleware with lexical scoping and automatic type inference.\n * Routes registered in the callback inherit middleware state types.\n * \n * @param state - State middleware object\n * @param callback - Callback that receives scoped app with accumulated state types\n */\n define<S extends StateMiddleware>(\n state: S,\n callback: (app: App<Flatten<TState & InferState<S>>>) => void\n ): void {\n // Create child app with inherited middleware state type\n const childApp = new App<Flatten<TState & InferState<S>>>();\n\n // Copy parent middleware to child\n childApp.middleware = [...this.middleware];\n\n // Add new middleware to child\n childApp.apply('/*', state);\n\n // Execute callback with child app\n callback(childApp);\n\n // Merge child routes into parent with pre-merged middleware\n for (const route of childApp.routes) {\n const matchedMiddleware = childApp.matchMiddleware(route.path);\n const mergedSchema = childApp.mergeSchemas(matchedMiddleware, route.schema);\n\n this.routes.push({\n ...route,\n schema: mergedSchema,\n });\n }\n\n // Merge child's notFound handler with pre-merged middleware\n if (childApp._notFoundHandler) {\n const nfMiddleware = childApp.matchMiddleware('/*');\n const nfSchema = childApp.mergeSchemas(nfMiddleware, undefined);\n this._notFoundEntries.push({\n prefix: '',\n handler: childApp._notFoundHandler,\n schema: nfSchema,\n });\n }\n\n // Propagate child's accumulated notFound entries\n for (const entry of childApp._notFoundEntries) {\n this._notFoundEntries.push(entry);\n }\n }\n\n /**\n * Match middleware patterns against route path.\n */\n matchMiddleware(path: string): StateMiddleware[] {\n const matched: StateMiddleware[] = [];\n\n for (const { pattern, state } of this.middleware) {\n if (this.matchPattern(pattern, path)) {\n matched.push(state);\n }\n }\n\n return matched;\n }\n\n /**\n * Simple wildcard pattern matching.\n */\n private matchPattern(pattern: string, path: string): boolean {\n if (pattern === '/*') return true;\n\n if (pattern.endsWith('/*')) {\n const prefix = pattern.slice(0, -2);\n return path === prefix || path.startsWith(prefix + '/');\n }\n\n return pattern === path;\n }\n\n /**\n * Merge multiple middleware states with route schema.\n */\n mergeSchemas(\n middlewareStates: StateMiddleware[],\n routeSchema?: Schema\n ): Schema | undefined {\n if (middlewareStates.length === 0 && !routeSchema?.state) {\n // Inject app-level error handler as fallback\n if (this._onError && (!routeSchema || !routeSchema.onError)) {\n return { ...routeSchema, onError: this._onError };\n }\n return routeSchema;\n }\n\n const mergedState: StateMiddleware = {};\n\n // Add middleware states first (in order)\n for (const mwState of middlewareStates) {\n Object.assign(mergedState, mwState);\n }\n\n // Add route state last (can override)\n if (routeSchema?.state) {\n Object.assign(mergedState, routeSchema.state);\n }\n\n const result: Schema = {\n ...routeSchema,\n state: mergedState,\n };\n\n // Inject app-level error handler as fallback\n if (this._onError && !result.onError) {\n result.onError = this._onError;\n }\n\n return result;\n }\n\n /**\n * Store raw route registration\n */\n private storeRoute(\n method: string,\n path: string,\n schema: Schema | undefined,\n handler: Handler | undefined,\n staticValue: unknown | undefined\n ): void {\n this.routes.push({\n method,\n path,\n schema,\n handler,\n staticValue,\n });\n }\n\n /**\n * Internal route registration logic\n */\n private register<S extends Schema>(\n method: string,\n path: string,\n arg2: S | Handler | unknown,\n arg3?: Handler | unknown\n ): void {\n // Handler only: app.get(path, handler)\n if (typeof arg2 === 'function') {\n this.storeRoute(method, path, undefined, arg2 as Handler, undefined);\n return;\n }\n\n // Schema + Handler/Value: app.get(path, schema, handler/value)\n if (arg2 !== null && typeof arg2 === 'object' && arg3 !== undefined) {\n if (typeof arg3 === 'function') {\n this.storeRoute(method, path, arg2 as Schema, arg3 as Handler, undefined);\n } else {\n this.storeRoute(method, path, arg2 as Schema, undefined, arg3);\n }\n return;\n }\n\n // Static Value only: app.get(path, staticValue)\n this.storeRoute(method, path, undefined, undefined, arg2);\n }\n\n // ==================== HTTP Method Overloads ====================\n\n get<P extends string>(path: P, handler: TypedHandler<{}, P, TState>): void;\n get<S extends Schema, P extends string>(path: P, schema: S, handler: TypedHandler<S, P, TState>): void;\n get<P extends string, T = unknown>(path: P, staticValue: T): void;\n get<S extends Schema, P extends string, T = unknown>(path: P, schema: S, staticValue: T): void;\n get(arg1: any, arg2?: any, arg3?: any): void {\n this.register('GET', arg1, arg2, arg3);\n }\n\n post<P extends string>(path: P, handler: TypedHandler<{}, P, TState>): void;\n post<S extends Schema, P extends string>(path: P, schema: S, handler: TypedHandler<S, P, TState>): void;\n post<P extends string, T = unknown>(path: P, staticValue: T): void;\n post<S extends Schema, P extends string, T = unknown>(path: P, schema: S, staticValue: T): void;\n post(arg1: any, arg2?: any, arg3?: any): void {\n this.register('POST', arg1, arg2, arg3);\n }\n\n put<P extends string>(path: P, handler: TypedHandler<{}, P, TState>): void;\n put<S extends Schema, P extends string>(path: P, schema: S, handler: TypedHandler<S, P, TState>): void;\n put<P extends string, T = unknown>(path: P, staticValue: T): void;\n put<S extends Schema, P extends string, T = unknown>(path: P, schema: S, staticValue: T): void;\n put(arg1: any, arg2?: any, arg3?: any): void {\n this.register('PUT', arg1, arg2, arg3);\n }\n\n patch<P extends string>(path: P, handler: TypedHandler<{}, P, TState>): void;\n patch<S extends Schema, P extends string>(path: P, schema: S, handler: TypedHandler<S, P, TState>): void;\n patch<P extends string, T = unknown>(path: P, staticValue: T): void;\n patch<S extends Schema, P extends string, T = unknown>(path: P, schema: S, staticValue: T): void;\n patch(arg1: any, arg2?: any, arg3?: any): void {\n this.register('PATCH', arg1, arg2, arg3);\n }\n\n delete<P extends string>(path: P, handler: TypedHandler<{}, P, TState>): void;\n delete<S extends Schema, P extends string>(path: P, schema: S, handler: TypedHandler<S, P, TState>): void;\n delete<P extends string, T = unknown>(path: P, staticValue: T): void;\n delete<S extends Schema, P extends string, T = unknown>(path: P, schema: S, staticValue: T): void;\n delete(arg1: any, arg2?: any, arg3?: any): void {\n this.register('DELETE', arg1, arg2, arg3);\n }\n\n head<P extends string>(path: P, handler: TypedHandler<{}, P, TState>): void;\n head<S extends Schema, P extends string>(path: P, schema: S, handler: TypedHandler<S, P, TState>): void;\n head<P extends string, T = unknown>(path: P, staticValue: T): void;\n head<S extends Schema, P extends string, T = unknown>(path: P, schema: S, staticValue: T): void;\n head(arg1: any, arg2?: any, arg3?: any): void {\n this.register('HEAD', arg1, arg2, arg3);\n }\n\n options<P extends string>(path: P, handler: TypedHandler<{}, P, TState>): void;\n options<S extends Schema, P extends string>(path: P, schema: S, handler: TypedHandler<S, P, TState>): void;\n options<P extends string, T = unknown>(path: P, staticValue: T): void;\n options<S extends Schema, P extends string, T = unknown>(path: P, schema: S, staticValue: T): void;\n options(arg1: any, arg2?: any, arg3?: any): void {\n this.register('OPTIONS', arg1, arg2, arg3);\n }\n\n /**\n * Mount another App with optional prefix\n */\n use(app: App): void;\n use(prefix: string, app: App): void;\n use(arg1: string | App, arg2?: App): void {\n const prefix = typeof arg1 === 'string' ? arg1 : '';\n const other = typeof arg1 === 'string' ? arg2! : arg1;\n\n // Merge middleware with prefix\n for (const mw of other.middleware) {\n const combinedPattern = this.combinePath(prefix, mw.pattern);\n this.middleware.push({\n pattern: combinedPattern,\n state: mw.state,\n });\n }\n\n // Merge routes with prefix, preserving child app error handler\n for (const route of other.routes) {\n const combinedPath = this.combinePath(prefix, route.path);\n let schema = route.schema;\n\n // Inject child app's error handler into routes that don't have their own\n if (other._onError && (!schema || !schema.onError)) {\n schema = { ...schema, onError: other._onError };\n }\n\n this.routes.push({\n ...route,\n path: combinedPath,\n schema,\n });\n }\n\n // Propagate sub-app's notFound handler with prefix\n if (other._notFoundHandler) {\n const schema: Schema | undefined = other._onError ? { onError: other._onError } : undefined;\n this._notFoundEntries.push({\n prefix: prefix || '',\n handler: other._notFoundHandler,\n schema,\n });\n }\n\n // Propagate sub-app's accumulated notFound entries with combined prefix\n for (const entry of other._notFoundEntries) {\n let schema = entry.schema;\n if (other._onError && (!schema || !schema.onError)) {\n schema = { ...schema, onError: other._onError };\n }\n this._notFoundEntries.push({\n prefix: this.combinePath(prefix, entry.prefix),\n handler: entry.handler,\n schema,\n });\n }\n\n // Propagate sub-app's WebSocket routes with prefix\n for (const wsRoute of other.wsRoutes) {\n this.wsRoutes.push({\n ...wsRoute,\n path: this.combinePath(prefix, wsRoute.path),\n });\n }\n }\n\n /**\n * Register a WebSocket handler at the given path.\n * \n * The generic type parameter `T` defines per-connection data,\n * which is set in the `upgrade` handler and accessible via `peer.data`.\n * \n * @template T - Per-connection data type\n * @param path - URL path to handle WebSocket upgrades\n * @param handler - WebSocket event handlers\n * \n * @example\n * ```ts\n * // Simple echo server\n * app.ws('/ws', {\n * message(peer, message) {\n * peer.send(message);\n * },\n * });\n * \n * // Chat with authentication and pub/sub\n * app.ws<{ userId: string }>('/chat', {\n * upgrade(req) {\n * const token = req.headers.get('authorization');\n * return { userId: verifyToken(token) };\n * },\n * open(peer) {\n * peer.subscribe('chat');\n * peer.publish('chat', `${peer.data.userId} joined`);\n * },\n * message(peer, message) {\n * peer.publish('chat', `${peer.data.userId}: ${message}`);\n * },\n * close(peer) {\n * peer.publish('chat', `${peer.data.userId} left`);\n * },\n * });\n * \n * // With options\n * app.ws('/live', {\n * message(peer, message) { peer.send(message); },\n * }, {\n * pingInterval: 15,\n * maxPayloadLength: 1024 * 1024,\n * });\n * ```\n */\n ws<T = unknown>(path: string, handler: WsHandler<T>, options?: WsOptions): void {\n this.wsRoutes.push({ path, handler: handler as WsHandler<any>, options });\n }\n\n /**\n * Print all registered routes to the console with colored formatting.\n *\n * Each HTTP method is color-coded:\n * - GET (green), POST (blue), PUT (yellow), PATCH (cyan)\n * - DELETE (red), HEAD (magenta), OPTIONS (white)\n *\n * @example\n * ```ts\n * app.get('/', 'Hello!');\n * app.post('/users', handler);\n * app.get('/users/:id', handler);\n * app.ws('/chat', wsHandler);\n * app.printRoutes();\n * // ┌──────────┬────────────────────┐\n * // │ Method │ Path │\n * // ├──────────┼────────────────────┤\n * // │ GET │ / │\n * // │ POST │ /users │\n * // │ GET │ /users/:id │\n * // │ WS │ /chat │\n * // └──────────┴────────────────────┘\n * ```\n */\n printRoutes(): void {\n const routes = this.getRoutes();\n const hasHttp = routes.length > 0;\n const hasWs = this.wsRoutes.length > 0;\n\n if (!hasHttp && !hasWs) {\n console.log('No routes registered.');\n return;\n }\n\n // ANSI color codes\n const reset = '\\x1b[0m';\n const bold = '\\x1b[1m';\n const dim = '\\x1b[2m';\n const methodColors: Record<string, string> = {\n GET: '\\x1b[32m', // green\n POST: '\\x1b[34m', // blue\n PUT: '\\x1b[33m', // yellow\n PATCH: '\\x1b[36m', // cyan\n DELETE: '\\x1b[31m', // red\n HEAD: '\\x1b[35m', // magenta\n OPTIONS: '\\x1b[37m', // white\n WS: '\\x1b[35m', // magenta\n };\n\n // Combine HTTP routes and WS routes into a unified list\n const allRows: Array<{ method: string; path: string; }> = [\n ...routes.map(r => ({ method: r.method, path: r.path })),\n ...this.wsRoutes.map(r => ({ method: 'WS', path: r.path })),\n ];\n\n // Calculate inner content widths (padding is applied separately)\n const methodInnerWidth = Math.max(\n 'Method'.length,\n allRows.reduce((max, row) => Math.max(max, row.method.length), 0)\n );\n const pathInnerWidth = Math.max(\n 'Path'.length,\n allRows.reduce((max, row) => Math.max(max, row.path.length), 0)\n );\n\n // Cell widths include one space padding on left and right\n const methodCellWidth = methodInnerWidth + 2;\n const pathCellWidth = pathInnerWidth + 2;\n\n // Box drawing\n const top = `${dim}┌${'─'.repeat(methodCellWidth)}┬${'─'.repeat(pathCellWidth)}┐${reset}`;\n const headerSep = `${dim}├${'─'.repeat(methodCellWidth)}┼${'─'.repeat(pathCellWidth)}┤${reset}`;\n const bottom = `${dim}└${'─'.repeat(methodCellWidth)}┴${'─'.repeat(pathCellWidth)}┘${reset}`;\n\n const header =\n `${dim}│${reset} ${bold}${'Method'.padEnd(methodInnerWidth)}${reset} ` +\n `${dim}│${reset} ${bold}${'Path'.padEnd(pathInnerWidth)}${reset} ${dim}│${reset}`;\n\n const lines: string[] = [top, header, headerSep];\n\n for (const row of allRows) {\n const color = methodColors[row.method] || '';\n const method = `${color}${bold}${row.method}${reset}`;\n const methodPad = ' '.repeat(methodInnerWidth - row.method.length);\n const pathPad = ' '.repeat(pathInnerWidth - row.path.length);\n lines.push(\n `${dim}│${reset} ${method}${methodPad} ${dim}│${reset} ${row.path}${pathPad} ${dim}│${reset}`\n );\n }\n\n lines.push(bottom);\n console.log(lines.join('\\n'));\n }\n\n /**\n * Combine prefix with path\n */\n private combinePath(prefix: string, path: string): string {\n if (!prefix) return path;\n if (!path || path === '/') return prefix;\n let combined = prefix.endsWith('/') ? prefix : prefix + '/';\n combined += path.startsWith('/') ? path.substring(1) : path;\n if (!combined.startsWith('/')) combined = '/' + combined;\n return combined;\n }\n}\n","/**\n * Ken Framework - Runtime Adapters\n * Auto-detection with lazy loading for each runtime\n * \n * Detection order:\n * 1. Deno → loads deno runtime\n * 2. Bun → loads bun runtime\n * 3. Node.js → checks UWS env / uWebSockets.js availability\n * - UWS=1|true → use uWebSockets.js (error if not installed)\n * - UWS=0|false → use node:http\n * - Not set → try uWebSockets.js, fallback to node:http\n * \n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Router } from '../core/router';\n\n// ==================== Runtime Detection ====================\n\ndeclare const Deno: { version: { deno: string; }; };\ndeclare const Bun: { version: string; };\n\n/** True when running on Deno */\nexport const isDeno = typeof Deno !== 'undefined' && typeof Deno.version !== 'undefined';\n\n/** True when running on Bun */\nexport const isBun = typeof Bun !== 'undefined' && typeof Bun.version !== 'undefined';\n\n/** True when running on Node.js (excludes Bun which also exposes process) */\nexport const isNode = !isBun\n && typeof globalThis.process !== 'undefined'\n && globalThis.process.versions != null\n && globalThis.process.versions.node != null;\n\n// ==================== Types ====================\n\n/**\n * Server instance returned by all runtime adapters.\n */\nexport interface Server {\n /** Start listening. Returns the resolved hostname and port. */\n run(): Promise<{ hostname: string; port: number; }>;\n /** Gracefully stop the server. */\n stop(): void | Promise<void>;\n}\n\n/**\n * Options accepted by every server factory.\n */\nexport interface ServerOptions {\n port?: number;\n hostname?: string;\n router: Router;\n}\n\n/** Factory function signature for runtime-specific server creation. */\ntype ServerFactory = (options: ServerOptions) => Server;\n\n// ==================== Node.js + uWebSockets.js Resolution ====================\n\n/**\n * Resolve Node.js runtime: decide between uWebSockets.js and node:http.\n * \n * Priority:\n * 1. UWS=1|true → use uWs (throw if missing)\n * 2. UWS=0|false → use node:http\n * 3. Not set → try uWs, fallback to node:http\n */\nasync function resolveNodeRuntime(): Promise<ServerFactory> {\n const flag = globalThis.process?.env?.UWS;\n\n\n console.log('UWS flag:', flag);\n\n // Explicit disable\n // if (flag === '0' || flag === 'false') {\n // return (await import('./node')).server;\n // }\n\n // Explicit enable\n if (flag === '1' || flag === 'true') {\n try {\n await import('uWebSockets.js');\n return (await import('./uws')).server;\n } catch {\n throw new Error(\n 'UWS is enabled but uWebSockets.js is not installed. '\n + 'Install with: npm install uWebSockets.js'\n );\n }\n }\n\n // Auto-detect: try uWs first, fallback to node:http\n // try {\n // await import('uWebSockets.js');\n // return (await import('./uws')).server;\n // } catch {\n return (await import('./node')).server;\n // }\n}\n\n// ==================== Auto-Detection Server ====================\n\n/**\n * Create a server with automatic runtime detection.\n * Lazily loads only the runtime adapter needed for the current environment.\n * \n * @example\n * ```ts\n * import { App, server } from 'ken';\n * const app = new App();\n * app.get('/', 'Hello!');\n * const srv = await server({ port: 3000, router: app });\n * await srv.run();\n * ```\n */\nexport async function server(options: ServerOptions): Promise<Server> {\n if (isDeno) {\n const { server } = await import('./deno');\n return server(options);\n }\n if (isBun) {\n const { server } = await import('./bun');\n return server(options);\n }\n if (isNode) {\n const factory = await resolveNodeRuntime();\n return factory(options);\n }\n throw new Error(\n 'Unsupported runtime. Ken supports Bun, Deno, and Node.js '\n + '(with optional uWebSockets.js).'\n );\n}\n\n// ==================== Explicit Runtime Loaders ====================\n\n/**\n * Load Bun runtime explicitly.\n * Uses lazy import — safe to call from any environment.\n */\nexport async function bunServer(options: ServerOptions): Promise<Server> {\n const { server } = await import('./bun');\n return server(options);\n}\n\n/**\n * Load Deno runtime explicitly.\n * Uses lazy import — safe to call from any environment.\n */\nexport async function denoServer(options: ServerOptions): Promise<Server> {\n const { server } = await import('./deno');\n return server(options);\n}\n\n/**\n * Load Node.js (node:http) runtime explicitly.\n * Uses lazy import — safe to call from any environment.\n */\nexport async function nodeServer(options: ServerOptions): Promise<Server> {\n const { server } = await import('./node');\n return server(options);\n}\n\n/**\n * Load uWebSockets.js runtime explicitly.\n * Uses lazy import — safe to call from any environment.\n */\nexport async function uwsServer(options: ServerOptions): Promise<Server> {\n const { server } = await import('./uws');\n return server(options);\n}\n\n// ==================== Compiler (runtime-agnostic) ====================\n\nexport { createExecutor, createSyncExecutor, createAsyncExecutor, type ContextFactory } from './compiler';\n","/**\n * Ken Framework - AppServer\n * Combines App routing with automatic runtime detection and server lifecycle.\n * \n * Usage:\n * ```ts\n * import { AppServer } from 'ken';\n * const app = new AppServer({ port: 3000 });\n * app.get('/hello', 'Hello, World!');\n * await app.run();\n * ```\n * \n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport { App } from './app';\nimport { type StateMiddleware } from '../context/types';\nimport { server, type Server } from '../runtime/index';\n\n/**\n * AppServer initialization options.\n */\nexport interface AppServerInit {\n port?: number;\n hostname?: string;\n}\n\n/**\n * AppServer - App with built-in server lifecycle.\n * \n * Extends App with `run()` and `stop()` methods.\n * Automatically detects the current runtime (Bun, Deno, Node.js)\n * and lazily loads only the needed adapter.\n * \n * @template TState - Accumulated middleware state type\n */\nexport class AppServer<TState extends StateMiddleware = {}> extends App<TState> {\n /** Configured hostname */\n public hostname: string;\n /** Configured port */\n public port: number;\n\n private _server: Server | undefined;\n\n constructor(init: AppServerInit = {}) {\n super();\n this.hostname = init.hostname ?? '0.0.0.0';\n this.port = init.port ?? 3000;\n }\n\n /**\n * Start the server with automatic runtime detection.\n * Returns the resolved hostname and port.\n * \n * @example\n * ```ts\n * const app = new AppServer({ port: 3000 });\n * app.get('/', 'Hello!');\n * const { hostname, port } = await app.run();\n * console.log(`Listening on ${hostname}:${port}`);\n * ```\n */\n async run(): Promise<{ hostname: string; port: number; }> {\n // Stop previous instance if running\n await this.stop();\n\n this._server = await server({\n port: this.port,\n hostname: this.hostname,\n router: this,\n });\n\n return this._server.run();\n }\n\n /**\n * Stop the server gracefully.\n */\n async stop(): Promise<void> {\n if (this._server) {\n await this._server.stop();\n this._server = undefined;\n }\n }\n}\n","/**\n * Ken Framework - Base64 / Base64URL Encoding Utilities\n * High-performance, lookup-table-based encoding for cross-runtime use.\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\n// ==================== Shared Singletons ====================\n\n/** Pre-allocated TextEncoder — avoid per-call instantiation */\nexport const encoder = new TextEncoder();\n\n/** Pre-allocated TextDecoder — avoid per-call instantiation */\nexport const decoder = new TextDecoder();\n\n// ==================== Standard Base64 ====================\n\n// Base64 lookup table for fast encoding (avoids btoa + String.fromCharCode spread)\nconst B64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n// Reverse lookup table for fast base64 decoding (avoids atob + charCodeAt callback)\nconst B64_LOOKUP = new Uint8Array(128);\nfor (let i = 0; i < B64_CHARS.length; i++) B64_LOOKUP[B64_CHARS.charCodeAt(i)] = i;\n\n/**\n * Fast base64 encode a Uint8Array without btoa or String.fromCharCode spread.\n * Avoids temporary string allocation from spread operator on large arrays.\n */\nexport function toBase64(bytes: Uint8Array): string {\n const len = bytes.length;\n const pad = len % 3;\n const mainLen = len - pad;\n let result = '';\n\n for (let i = 0; i < mainLen; i += 3) {\n const b0 = bytes[i], b1 = bytes[i + 1], b2 = bytes[i + 2];\n result += B64_CHARS[(b0 >> 2)] +\n B64_CHARS[((b0 & 3) << 4) | (b1 >> 4)] +\n B64_CHARS[((b1 & 15) << 2) | (b2 >> 6)] +\n B64_CHARS[(b2 & 63)];\n }\n\n if (pad === 1) {\n const b0 = bytes[mainLen];\n result += B64_CHARS[(b0 >> 2)] + B64_CHARS[((b0 & 3) << 4)] + '==';\n } else if (pad === 2) {\n const b0 = bytes[mainLen], b1 = bytes[mainLen + 1];\n result += B64_CHARS[(b0 >> 2)] +\n B64_CHARS[((b0 & 3) << 4) | (b1 >> 4)] +\n B64_CHARS[((b1 & 15) << 2)] + '=';\n }\n\n return result;\n}\n\n/**\n * Fast base64 decode to Uint8Array without atob or callback.\n * Uses pre-computed lookup table for O(1) character mapping.\n */\nexport function fromBase64(str: string): Uint8Array<ArrayBuffer> {\n let len = str.length;\n // Strip padding\n let pad = 0;\n if (str.charCodeAt(len - 1) === 61) pad++; // '='\n if (str.charCodeAt(len - 2) === 61) pad++; // '='\n const byteLen = (len * 3 >> 2) - pad;\n const out = new Uint8Array(byteLen);\n let j = 0;\n\n for (let i = 0; i < len; i += 4) {\n const a = B64_LOOKUP[str.charCodeAt(i)];\n const b = B64_LOOKUP[str.charCodeAt(i + 1)];\n const c = B64_LOOKUP[str.charCodeAt(i + 2)];\n const d = B64_LOOKUP[str.charCodeAt(i + 3)];\n out[j++] = (a << 2) | (b >> 4);\n if (j < byteLen) out[j++] = ((b & 15) << 4) | (c >> 2);\n if (j < byteLen) out[j++] = ((c & 3) << 6) | d;\n }\n\n return out;\n}\n\n// ==================== Base64URL ====================\n\n// Base64url characters (URL-safe: - instead of +, _ instead of /)\nconst B64URL_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n\n// Reverse lookup table for fast O(1) base64url decoding\nconst B64URL_LOOKUP = new Uint8Array(128);\nfor (let i = 0; i < B64URL_CHARS.length; i++) B64URL_LOOKUP[B64URL_CHARS.charCodeAt(i)] = i;\n\n/**\n * Fast base64url encode a Uint8Array without padding.\n * Uses URL-safe characters — safe for cookies, URLs, and JSON values.\n */\nexport function encodeBase64Url(bytes: Uint8Array): string {\n const len = bytes.length;\n const rem = len % 3;\n const mainLen = len - rem;\n let result = '';\n\n for (let i = 0; i < mainLen; i += 3) {\n const b0 = bytes[i], b1 = bytes[i + 1], b2 = bytes[i + 2];\n result += B64URL_CHARS[b0 >> 2] +\n B64URL_CHARS[((b0 & 3) << 4) | (b1 >> 4)] +\n B64URL_CHARS[((b1 & 15) << 2) | (b2 >> 6)] +\n B64URL_CHARS[b2 & 63];\n }\n\n if (rem === 1) {\n const b0 = bytes[mainLen];\n result += B64URL_CHARS[b0 >> 2] + B64URL_CHARS[(b0 & 3) << 4];\n } else if (rem === 2) {\n const b0 = bytes[mainLen], b1 = bytes[mainLen + 1];\n result += B64URL_CHARS[b0 >> 2] +\n B64URL_CHARS[((b0 & 3) << 4) | (b1 >> 4)] +\n B64URL_CHARS[(b1 & 15) << 2];\n }\n\n return result;\n}\n\n/**\n * Fast base64url decode (handles unpadded input).\n * Uses pre-computed lookup table for O(1) character mapping.\n */\nexport function decodeBase64Url(str: string): Uint8Array<ArrayBuffer> {\n const len = str.length;\n const rem = len & 3;\n const fullGroups = (len - rem) >> 2;\n const byteLen = fullGroups * 3 + (rem === 2 ? 1 : rem === 3 ? 2 : 0);\n const out = new Uint8Array(byteLen);\n const mainLen = fullGroups << 2;\n let j = 0;\n\n for (let i = 0; i < mainLen; i += 4) {\n const a = B64URL_LOOKUP[str.charCodeAt(i)];\n const b = B64URL_LOOKUP[str.charCodeAt(i + 1)];\n const c = B64URL_LOOKUP[str.charCodeAt(i + 2)];\n const d = B64URL_LOOKUP[str.charCodeAt(i + 3)];\n out[j++] = (a << 2) | (b >> 4);\n out[j++] = ((b & 15) << 4) | (c >> 2);\n out[j++] = ((c & 3) << 6) | d;\n }\n\n if (rem === 2) {\n const a = B64URL_LOOKUP[str.charCodeAt(mainLen)];\n const b = B64URL_LOOKUP[str.charCodeAt(mainLen + 1)];\n out[j] = (a << 2) | (b >> 4);\n } else if (rem === 3) {\n const a = B64URL_LOOKUP[str.charCodeAt(mainLen)];\n const b = B64URL_LOOKUP[str.charCodeAt(mainLen + 1)];\n const c = B64URL_LOOKUP[str.charCodeAt(mainLen + 2)];\n out[j++] = (a << 2) | (b >> 4);\n out[j] = ((b & 15) << 4) | (c >> 2);\n }\n\n return out;\n}\n","/**\n * Ken Framework - Encryption Utilities\n * High-performance AES-GCM encryption with key caching\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport { encoder, decoder, toBase64, fromBase64 } from './encoding';\n\n// AES-GCM algorithm descriptor — reused across all calls\nconst AES_GCM: AesKeyAlgorithm = { name: 'AES-GCM', length: 256 };\n\n/**\n * LRU-bounded CryptoKey cache keyed by password string.\n * Avoids re-deriving the same key on repeated encrypt/decrypt calls.\n */\nconst KEY_CACHE_MAX = 64;\nconst keyCache = new Map<string, CryptoKey>();\n\n/**\n * Derive a CryptoKey from a string password using SHA-256.\n * Results are cached per password to avoid redundant derivation.\n */\nasync function deriveCryptoKey(password: string): Promise<CryptoKey> {\n const cached = keyCache.get(password);\n if (cached !== undefined) return cached;\n\n const keyData = await crypto.subtle.digest('SHA-256', encoder.encode(password));\n const key = await crypto.subtle.importKey('raw', keyData, AES_GCM, false, ['encrypt', 'decrypt']);\n\n // Evict oldest entry if cache is full (simple LRU via insertion order)\n if (keyCache.size >= KEY_CACHE_MAX) {\n const oldest = keyCache.keys().next().value!;\n keyCache.delete(oldest);\n }\n keyCache.set(password, key);\n\n return key;\n}\n\n/**\n * Generate a random 256-bit secret key as a base64 string\n */\nexport function generateSecretKey(): string {\n return toBase64(crypto.getRandomValues(new Uint8Array(32)));\n}\n\n/**\n * Encrypt a string using AES-GCM.\n * Returns base64-encoded: IV (12 bytes) + ciphertext.\n * Uses cached CryptoKeys and manual base64 for maximum throughput.\n */\nexport async function encryptString(value: string, password: string): Promise<string> {\n const key = await deriveCryptoKey(password);\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const ciphertext = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv },\n key,\n encoder.encode(value)\n );\n\n // Combine IV + ciphertext into single buffer\n const ctBytes = new Uint8Array(ciphertext);\n const combined = new Uint8Array(12 + ctBytes.byteLength);\n combined.set(iv, 0);\n combined.set(ctBytes, 12);\n\n return toBase64(combined);\n}\n\n/**\n * Decrypt a base64-encoded encrypted string using AES-GCM.\n * Uses cached CryptoKeys, manual base64 decode, and subarray (zero-copy) for IV/ciphertext split.\n */\nexport async function decryptString(encrypted: string, password: string): Promise<string> {\n const key = await deriveCryptoKey(password);\n\n // Decode base64 into combined buffer\n const combined = fromBase64(encrypted);\n\n // subarray creates a view, not a copy — avoids allocation\n const iv = combined.subarray(0, 12) as Uint8Array<ArrayBuffer>;\n const ciphertext = combined.subarray(12) as Uint8Array<ArrayBuffer>;\n\n const decrypted = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv },\n key,\n ciphertext\n );\n\n return decoder.decode(decrypted);\n}","/**\n * Ken Framework - Memoize Utility\n * High-performance function memoization with configurable cache strategy\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\n/**\n * Options for configuring memoize behavior.\n */\nexport interface MemoizeOptions<Args extends unknown[]> {\n /**\n * Maximum number of cached entries. When exceeded, the oldest entry is evicted (LRU via insertion order).\n * @default 256\n */\n maxSize?: number;\n\n /**\n * Time-to-live in milliseconds. Entries older than this are considered stale.\n * When set to 0 or omitted, entries never expire.\n * @default 0\n */\n ttl?: number;\n\n /**\n * Custom key resolver. Receives the same arguments as the memoized function\n * and must return a string or number to use as the cache key.\n * Defaults to using the first argument directly (fast path for single-arg functions).\n */\n key?: (...args: Args) => string | number;\n}\n\ninterface CacheEntry<T> {\n value: T;\n expiry: number; // 0 = no expiry\n}\n\n/** Memoized function with exposed cache and clear method */\ntype MemoizedSync<Args extends unknown[], R> =\n ((...args: Args) => R) & { cache: Map<string | number, CacheEntry<R>>; clear: () => void; };\n\n/** Memoized async function with exposed cache, inflight map, and clear method */\ntype MemoizedAsync<Args extends unknown[], R> =\n ((...args: Args) => Promise<R>) & { cache: Map<string | number, CacheEntry<R>>; inflight: Map<string | number, Promise<R>>; clear: () => void; };\n\n/**\n * Create a memoized version of a function. Auto-detects async functions\n * at creation time and selects the optimal strategy:\n *\n * - **Sync**: Map-based cache with LRU eviction and TTL expiry.\n * - **Async**: Same cache plus in-flight deduplication — concurrent calls\n * for the same key share a single Promise (thundering herd protection).\n *\n * Detection uses `fn.constructor.name === 'AsyncFunction'` (compile-time branch,\n * zero per-call overhead).\n *\n * @example\n * ```ts\n * // Sync — auto-detected\n * const expensive = memoize((id: string) => computeResult(id));\n * expensive('abc'); // computes\n * expensive('abc'); // cached\n *\n * // Async — auto-detected, with TTL and max size\n * const fetchUser = memoize(\n * async (id: string) => db.users.findById(id),\n * { ttl: 30_000, maxSize: 500 }\n * );\n *\n * // Multi-arg with custom key\n * const multi = memoize(\n * (a: number, b: number) => a + b,\n * { key: (a, b) => `${a}:${b}` }\n * );\n * ```\n */\nexport function memoize<Args extends unknown[], R>(\n fn: (...args: Args) => Promise<R>,\n options?: MemoizeOptions<Args>\n): MemoizedAsync<Args, R>;\nexport function memoize<Args extends unknown[], R>(\n fn: (...args: Args) => R,\n options?: MemoizeOptions<Args>\n): MemoizedSync<Args, R>;\nexport function memoize<Args extends unknown[], R>(\n fn: (...args: Args) => R | Promise<R>,\n options?: MemoizeOptions<Args>\n): MemoizedSync<Args, R> | MemoizedAsync<Args, R> {\n if (fn.constructor.name === 'AsyncFunction') {\n return createAsyncMemoized(fn as (...args: Args) => Promise<R>, options);\n }\n return createSyncMemoized(fn as (...args: Args) => R, options);\n}\n\n// ── Internal sync strategy ──────────────────────────────────────────\n\nfunction createSyncMemoized<Args extends unknown[], R>(\n fn: (...args: Args) => R,\n options?: MemoizeOptions<Args>\n): MemoizedSync<Args, R> {\n const maxSize = options?.maxSize ?? 256;\n const ttl = options?.ttl ?? 0;\n const keyFn = options?.key;\n const cache = new Map<string | number, CacheEntry<R>>();\n\n const memoized = (...args: Args): R => {\n const k = keyFn ? keyFn(...args) : args[0] as string | number;\n\n const entry = cache.get(k);\n if (entry !== undefined) {\n if (entry.expiry !== 0 && Date.now() > entry.expiry) {\n cache.delete(k);\n } else {\n return entry.value;\n }\n }\n\n const result = fn(...args);\n\n if (cache.size >= maxSize) {\n const oldest = cache.keys().next().value!;\n cache.delete(oldest);\n }\n\n cache.set(k, {\n value: result,\n expiry: ttl > 0 ? Date.now() + ttl : 0,\n });\n\n return result;\n };\n\n memoized.cache = cache;\n memoized.clear = () => cache.clear();\n\n return memoized as MemoizedSync<Args, R>;\n}\n\n// ── Internal async strategy ─────────────────────────────────────────\n\nfunction createAsyncMemoized<Args extends unknown[], R>(\n fn: (...args: Args) => Promise<R>,\n options?: MemoizeOptions<Args>\n): MemoizedAsync<Args, R> {\n const maxSize = options?.maxSize ?? 256;\n const ttl = options?.ttl ?? 0;\n const keyFn = options?.key;\n const cache = new Map<string | number, CacheEntry<R>>();\n const inflight = new Map<string | number, Promise<R>>();\n\n const memoized = (...args: Args): Promise<R> => {\n const k = keyFn ? keyFn(...args) : args[0] as string | number;\n\n const entry = cache.get(k);\n if (entry !== undefined) {\n if (entry.expiry !== 0 && Date.now() > entry.expiry) {\n cache.delete(k);\n } else {\n return Promise.resolve(entry.value);\n }\n }\n\n const pending = inflight.get(k);\n if (pending !== undefined) return pending;\n\n const promise = fn(...args).then(result => {\n inflight.delete(k);\n\n if (cache.size >= maxSize) {\n const oldest = cache.keys().next().value!;\n cache.delete(oldest);\n }\n\n cache.set(k, {\n value: result,\n expiry: ttl > 0 ? Date.now() + ttl : 0,\n });\n\n return result;\n }, err => {\n inflight.delete(k);\n throw err;\n });\n\n inflight.set(k, promise);\n return promise;\n };\n\n memoized.cache = cache;\n memoized.inflight = inflight;\n memoized.clear = () => { cache.clear(); inflight.clear(); };\n\n return memoized as MemoizedAsync<Args, R>;\n}\n","/**\n * Ken Framework - Compression Utilities\n * High-performance string compression for cookies and JSON storage.\n *\n * Uses Web Standard CompressionStream/DecompressionStream API\n * for cross-runtime compatibility (Bun, Node.js, Deno, Cloudflare Workers).\n * Output is base64url-encoded (no +, /, or = characters) — safe for\n * cookies, URLs, and JSON values without escaping.\n *\n * Default format is `brotli` — best compression ratio for cookie/session\n * storage where every byte counts.\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport { encoder, decoder, encodeBase64Url, decodeBase64Url } from './encoding';\n\n/** Supported compression formats — extends the Web Standard with brotli (supported by Bun, Node.js, Deno). */\ntype SupportedCompressionFormat = CompressionFormat | 'brotli';\n\n/**\n * Options for {@link compressString}.\n *\n * The `level` range depends on the chosen `encoding`:\n * - **`brotli`**: 0–11 (default: `11` — best compression, slowest)\n * - **`deflate` / `gzip` / `deflate-raw`**: 0–9 (default: runtime default, typically `6`)\n *\n * Lower values = faster encoding + larger output.\n * Higher values = slower encoding + smaller output.\n */\nexport interface CompressOptions {\n /** Compression format. Default: `'brotli'`. */\n encoding?: SupportedCompressionFormat;\n /**\n * Compression quality level.\n * - brotli: 0–11 (default 11)\n * - deflate / gzip / deflate-raw: 0–9 (default ~6)\n */\n level?: number;\n}\n\n/** Options for {@link decompressString}. */\nexport interface DecompressOptions {\n /** Compression format used during compression. Default: `'brotli'`. */\n encoding?: SupportedCompressionFormat;\n}\n\n/**\n * Read all bytes from a ReadableStream into a single Uint8Array.\n * Single-chunk fast path avoids copy for small data (common case).\n */\nasync function readAllBytes(readable: ReadableStream<Uint8Array>): Promise<Uint8Array> {\n const reader = readable.getReader();\n const chunks: Uint8Array[] = [];\n let totalLen = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n totalLen += value.byteLength;\n }\n\n // Single chunk — return directly without copying\n if (chunks.length === 1) return chunks[0];\n\n // Merge multiple chunks into contiguous buffer\n const result = new Uint8Array(totalLen);\n let offset = 0;\n for (let i = 0; i < chunks.length; i++) {\n result.set(chunks[i], offset);\n offset += chunks[i].byteLength;\n }\n\n return result;\n}\n\n/**\n * Compress a string and return a base64url-encoded result.\n * Output is safe for cookies, URLs, and JSON values (no +, /, or = characters).\n *\n * Uses `brotli` by default for best compression ratio — produces smaller\n * output than `deflate` or `gzip`, ideal for cookie/session storage.\n *\n * @param input - The string to compress\n * @param options - Compression options: `encoding` (default `'brotli'`) and optional `level`\n * @returns Base64url-encoded compressed string\n *\n * @example\n * ```ts\n * // Best compression (default brotli)\n * const compressed = await compressString('Hello, World!');\n *\n * // Faster, lighter brotli\n * const fast = await compressString('Hello, World!', { level: 4 });\n *\n * // gzip with max compression\n * const gz = await compressString('Hello, World!', { encoding: 'gzip', level: 9 });\n * ```\n */\nexport async function compressString(\n input: string,\n options?: CompressOptions,\n): Promise<string> {\n const encoding = options?.encoding ?? 'brotli';\n // Pass level to CompressionStream when provided. The level option is supported by\n // Bun, Node.js (v21.2+), and Deno but is not in the Web Standard TS types, so cast is required.\n const cs = options?.level !== undefined\n ? new (CompressionStream as any)(encoding, { level: options.level })\n : new CompressionStream(encoding as CompressionFormat);\n const writer = cs.writable.getWriter();\n // Fire-and-forget — readable side handles backpressure; .catch suppresses unhandled rejections\n writer.write(encoder.encode(input)).catch(() => { });\n writer.close().catch(() => { });\n return encodeBase64Url(await readAllBytes(cs.readable));\n}\n\n/**\n * Decompress a base64url-encoded compressed string back to the original.\n *\n * @param compressed - Base64url-encoded compressed string from {@link compressString}\n * @param options - Decompression options: `encoding` must match what was used to compress (default `'brotli'`)\n * @returns The original decompressed string\n *\n * @example\n * ```ts\n * const original = await decompressString(compressed);\n * // 'Hello, World!'\n *\n * const original = await decompressString(compressed, { encoding: 'gzip' });\n * ```\n */\nexport async function decompressString(\n compressed: string,\n options?: DecompressOptions,\n): Promise<string> {\n const encoding = options?.encoding ?? 'brotli';\n const ds = new DecompressionStream(encoding as CompressionFormat);\n const writer = ds.writable.getWriter();\n // Fire-and-forget — readable side handles backpressure; .catch suppresses unhandled rejections\n writer.write(decodeBase64Url(compressed)).catch(() => { });\n writer.close().catch(() => { });\n return decoder.decode(await readAllBytes(ds.readable));\n}\n","/**\n * Ken Framework - File Utilities\n * Cross-runtime file operations: serve, list, upload, save\n *\n * Optimized paths per runtime:\n * - Bun: Uses Bun.file() for zero-copy sendfile responses\n * - Node.js / Deno: Uses node:fs streams with backpressure-aware ReadableStream\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport { stat, readdir, writeFile, mkdir } from 'node:fs/promises';\nimport { createReadStream } from 'node:fs';\nimport { join, extname, dirname } from 'node:path';\n\n// ==================== Runtime Detection (inline to avoid circular imports) ====================\n\nconst _isBun = typeof (globalThis as any).Bun !== 'undefined'\n && typeof (globalThis as any).Bun.version !== 'undefined';\n\n// ==================== MIME Types ====================\n\n/** Pre-allocated MIME type map. Frozen for V8 optimization. */\nconst MIME_TYPES: Readonly<Record<string, string>> = Object.freeze({\n // Text\n '.html': 'text/html; charset=utf-8',\n '.htm': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.mjs': 'text/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.xml': 'application/xml; charset=utf-8',\n '.txt': 'text/plain; charset=utf-8',\n '.csv': 'text/csv; charset=utf-8',\n '.md': 'text/markdown; charset=utf-8',\n '.yaml': 'text/yaml; charset=utf-8',\n '.yml': 'text/yaml; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.ts': 'text/typescript; charset=utf-8',\n '.tsx': 'text/tsx; charset=utf-8',\n '.jsx': 'text/jsx; charset=utf-8',\n // Images\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.ico': 'image/x-icon',\n '.avif': 'image/avif',\n '.bmp': 'image/bmp',\n '.tiff': 'image/tiff',\n '.tif': 'image/tiff',\n // Fonts\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.otf': 'font/otf',\n '.eot': 'application/vnd.ms-fontobject',\n // Audio / Video\n '.mp3': 'audio/mpeg',\n '.mp4': 'video/mp4',\n '.webm': 'video/webm',\n '.ogg': 'audio/ogg',\n '.ogv': 'video/ogg',\n '.wav': 'audio/wav',\n '.flac': 'audio/flac',\n '.aac': 'audio/aac',\n '.m4a': 'audio/mp4',\n '.m4v': 'video/mp4',\n '.avi': 'video/x-msvideo',\n '.mov': 'video/quicktime',\n '.mkv': 'video/x-matroska',\n // Archives\n '.zip': 'application/zip',\n '.gz': 'application/gzip',\n '.tar': 'application/x-tar',\n '.bz2': 'application/x-bzip2',\n '.7z': 'application/x-7z-compressed',\n '.rar': 'application/vnd.rar',\n // Documents\n '.pdf': 'application/pdf',\n '.doc': 'application/msword',\n '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n '.xls': 'application/vnd.ms-excel',\n '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n '.ppt': 'application/vnd.ms-powerpoint',\n '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n // Other\n '.wasm': 'application/wasm',\n '.map': 'application/json',\n '.bin': 'application/octet-stream',\n});\n\n/**\n * Get MIME type from a file path or extension.\n * Falls back to `application/octet-stream` for unknown types.\n *\n * @example\n * ```ts\n * getMimeType('photo.jpg') // 'image/jpeg'\n * getMimeType('.css') // 'text/css; charset=utf-8'\n * ```\n */\nexport function getMimeType(filePath: string): string {\n return MIME_TYPES[extname(filePath).toLowerCase()] || 'application/octet-stream';\n}\n\n// ==================== Types ====================\n\n/**\n * Options for {@link sendFile}.\n */\nexport interface SendFileOptions {\n /** Override Content-Type (auto-detected from extension by default) */\n contentType?: string;\n /** Trigger browser download. `true` uses original filename, string sets a custom filename. */\n download?: boolean | string;\n /** Cache-Control header value (e.g., `'public, max-age=3600'`) */\n cacheControl?: string;\n /** Additional response headers */\n headers?: Record<string, string>;\n /** HTTP status code override for the full-file response (default: 200) */\n status?: number;\n /**\n * Incoming request headers for conditional and range request support.\n * Pass `ctx.headers` or the raw `Headers` object.\n * Enables ETag / If-None-Match, Last-Modified / If-Modified-Since,\n * and Range (206 Partial Content) handling.\n */\n reqHeaders?: Headers | Record<string, string>;\n}\n\n/**\n * Options for {@link listDirectory}.\n */\nexport interface ListDirectoryOptions {\n /** Recurse into subdirectories (default: `false`) */\n recursive?: boolean;\n /** Maximum recursion depth when `recursive` is `true` (default: `10`) */\n maxDepth?: number;\n /** Include file stats — size & modifiedAt (default: `true`) */\n stats?: boolean;\n /** Filter entries. Return `true` to include, `false` to skip. */\n filter?: (entry: FileEntry) => boolean;\n}\n\n/**\n * A single file or directory entry returned by {@link listDirectory}.\n */\nexport interface FileEntry {\n /** Filename (including extension) */\n name: string;\n /** Relative path from the listed directory root */\n path: string;\n /** `true` if the entry is a directory */\n isDirectory: boolean;\n /** Size in bytes (`0` for directories, `0` if stats disabled) */\n size: number;\n /** Last modified timestamp (epoch 0 if stats disabled) */\n modifiedAt: Date;\n}\n\n/**\n * Options for {@link receiveFiles}.\n */\nexport interface ReceiveFileOptions {\n /** Maximum individual file size in bytes */\n maxFileSize?: number;\n /** Maximum number of files to accept */\n maxFiles?: number;\n /** Allowed MIME types (e.g., `['image/png', 'image/jpeg']`) */\n allowedTypes?: string[];\n /** Only extract files from these form field names */\n fields?: string[];\n}\n\n/**\n * A file extracted by {@link receiveFiles}.\n */\nexport interface UploadedFile {\n /** Form field name the file was submitted under */\n fieldName: string;\n /** Original filename from the client */\n fileName: string;\n /** MIME type */\n type: string;\n /** Size in bytes */\n size: number;\n /** Raw file contents */\n data: ArrayBuffer;\n}\n\n// ==================== Internal Helpers ====================\n\n/** Read a header value from Headers or a plain object */\nfunction getHeader(\n headers: Headers | Record<string, string> | undefined,\n key: string,\n): string | null {\n if (!headers) return null;\n if (typeof (headers as Headers).get === 'function') return (headers as Headers).get(key);\n return (headers as Record<string, string>)[key] ?? null;\n}\n\n/**\n * Parse the first byte range from a Range header.\n * Returns `null` for malformed or unsatisfiable ranges.\n */\nfunction parseRange(header: string, size: number): { start: number; end: number; } | null {\n if (header.charCodeAt(0) !== 98 /* b */ || !header.startsWith('bytes=')) return null;\n const range = header.slice(6);\n // Only handle the first range (multi-range is rare and adds complexity)\n const comma = range.indexOf(',');\n const single = comma === -1 ? range : range.slice(0, comma);\n const dash = single.indexOf('-');\n if (dash === -1) return null;\n\n const startStr = single.slice(0, dash).trim();\n const endStr = single.slice(dash + 1).trim();\n\n let start: number;\n let end: number;\n\n if (startStr === '') {\n // Suffix range: bytes=-500 → last 500 bytes\n const suffix = parseInt(endStr, 10);\n if (isNaN(suffix) || suffix <= 0) return null;\n start = Math.max(0, size - suffix);\n end = size - 1;\n } else {\n start = parseInt(startStr, 10);\n if (isNaN(start) || start < 0) return null;\n end = endStr === '' ? size - 1 : parseInt(endStr, 10);\n if (isNaN(end)) return null;\n }\n\n if (start > end || start >= size) return null;\n end = Math.min(end, size - 1);\n return { start, end };\n}\n\n/**\n * Convert a Node.js readable stream to a Web ReadableStream\n * with backpressure support (pause/resume).\n */\nfunction nodeStreamToWeb(nodeStream: any): ReadableStream<Uint8Array> {\n return new ReadableStream({\n start(controller) {\n nodeStream.on('data', (chunk: any) => {\n controller.enqueue(chunk);\n // Pause when internal buffer fills up\n if (controller.desiredSize !== null && controller.desiredSize <= 0) {\n nodeStream.pause();\n }\n });\n nodeStream.on('end', () => controller.close());\n nodeStream.on('error', (err: any) => controller.error(err));\n },\n pull() {\n nodeStream.resume();\n },\n cancel() {\n nodeStream.destroy?.();\n },\n });\n}\n\n/**\n * Generate a weak ETag from file size and mtime (same strategy as nginx).\n * No content hashing — zero per-request crypto overhead.\n */\nfunction generateEtag(size: number, mtimeMs: number): string {\n return `W/\"${size.toString(16)}-${Math.floor(mtimeMs).toString(16)}\"`;\n}\n\n// ==================== Public API ====================\n\n/**\n * Serve a file as an HTTP `Response` with correct headers.\n *\n * Features:\n * - Auto-detected Content-Type from file extension\n * - Range request support (206 Partial Content) for streaming / resumable downloads\n * - Conditional requests (ETag, Last-Modified → 304 Not Modified)\n * - Content-Disposition for triggering downloads\n * - Uses `Bun.file()` on Bun for zero-copy `sendfile` performance\n *\n * Returns a **404** `Response` when the file does not exist (no throw).\n *\n * @example\n * ```ts\n * // Basic usage\n * app.get('/files/:name', (ctx) =>\n * sendFile(`./public/${ctx.params.name}`)\n * );\n *\n * // With caching and range support\n * app.get('/media/:file', (ctx) =>\n * sendFile(`./media/${ctx.params.file}`, {\n * reqHeaders: ctx.headers,\n * cacheControl: 'public, max-age=86400',\n * })\n * );\n *\n * // Force download\n * app.get('/download/:file', (ctx) =>\n * sendFile(`./files/${ctx.params.file}`, { download: true })\n * );\n * ```\n */\nexport async function sendFile(\n filePath: string,\n options?: SendFileOptions,\n): Promise<Response> {\n // --- Stat the file (all runtimes) ---\n let fileStats;\n try {\n fileStats = await stat(filePath);\n } catch (err: any) {\n if (err.code === 'ENOENT' || err.code === 'ENOTDIR') {\n return new Response('Not Found', { status: 404 });\n }\n throw err;\n }\n\n if (!fileStats.isFile()) {\n return new Response('Not Found', { status: 404 });\n }\n\n const size = fileStats.size;\n const mtimeMs = fileStats.mtimeMs;\n const etag = generateEtag(size, mtimeMs);\n const lastModified = new Date(mtimeMs).toUTCString();\n const contentType = options?.contentType || getMimeType(filePath);\n const reqHeaders = options?.reqHeaders;\n\n // --- Conditional headers shared by 304 responses ---\n const conditionalHeaders: Record<string, string> = {\n etag,\n 'last-modified': lastModified,\n };\n if (options?.cacheControl) conditionalHeaders['cache-control'] = options.cacheControl;\n\n // --- ETag: If-None-Match ---\n const ifNoneMatch = getHeader(reqHeaders, 'if-none-match');\n if (ifNoneMatch) {\n if (ifNoneMatch === etag || ifNoneMatch === '*') {\n return new Response(null, { status: 304, headers: conditionalHeaders });\n }\n // Comma-separated list (rare but spec-compliant)\n if (ifNoneMatch.indexOf(',') !== -1) {\n const tags = ifNoneMatch.split(',');\n for (let i = 0; i < tags.length; i++) {\n if (tags[i].trim() === etag) {\n return new Response(null, { status: 304, headers: conditionalHeaders });\n }\n }\n }\n }\n\n // --- Last-Modified: If-Modified-Since (only when no If-None-Match) ---\n if (!ifNoneMatch) {\n const ifModifiedSince = getHeader(reqHeaders, 'if-modified-since');\n if (ifModifiedSince) {\n const clientTime = Date.parse(ifModifiedSince);\n if (!isNaN(clientTime) && Math.floor(mtimeMs / 1000) <= Math.floor(clientTime / 1000)) {\n return new Response(null, { status: 304, headers: conditionalHeaders });\n }\n }\n }\n\n // --- Build response headers ---\n const headers: Record<string, string> = {\n 'content-type': contentType,\n etag,\n 'last-modified': lastModified,\n 'accept-ranges': 'bytes',\n };\n\n if (options?.cacheControl) headers['cache-control'] = options.cacheControl;\n\n // Content-Disposition for downloads\n if (options?.download) {\n const filename = typeof options.download === 'string'\n ? options.download\n : filePath.slice(Math.max(filePath.lastIndexOf('/'), filePath.lastIndexOf('\\\\')) + 1);\n headers['content-disposition'] = `attachment; filename=\"${filename}\"`;\n }\n\n // Merge custom headers last (user can override anything)\n if (options?.headers) {\n for (const key in options.headers) {\n headers[key] = options.headers[key];\n }\n }\n\n // --- Range request ---\n const rangeHeader = getHeader(reqHeaders, 'range');\n if (rangeHeader) {\n const range = parseRange(rangeHeader, size);\n if (range) {\n const { start, end } = range;\n headers['content-range'] = `bytes ${start}-${end}/${size}`;\n headers['content-length'] = String(end - start + 1);\n\n let body: BodyInit;\n if (_isBun) {\n body = (globalThis as any).Bun.file(filePath).slice(start, end + 1);\n } else {\n body = nodeStreamToWeb(createReadStream(filePath, { start, end }));\n }\n return new Response(body, { status: 206, headers });\n }\n // Range not satisfiable\n return new Response(null, {\n status: 416,\n headers: { 'content-range': `bytes */${size}` },\n });\n }\n\n // --- Full file response ---\n headers['content-length'] = String(size);\n\n let body: BodyInit;\n if (_isBun) {\n // Bun uses sendfile internally — zero-copy\n body = (globalThis as any).Bun.file(filePath);\n } else {\n body = nodeStreamToWeb(createReadStream(filePath));\n }\n\n return new Response(body, { status: options?.status || 200, headers });\n}\n\n/**\n * List the contents of a directory with optional metadata.\n *\n * Stat calls within each directory level are parallelized via `Promise.all`\n * for maximum throughput. Uses an iterative stack (no recursion overhead).\n *\n * @example\n * ```ts\n * // Flat listing\n * app.get('/browse', async () => {\n * return listDirectory('./data');\n * });\n *\n * // Recursive with filter\n * app.get('/browse/images', async () => {\n * return listDirectory('./public', {\n * recursive: true,\n * filter: (e) => e.isDirectory || e.name.endsWith('.png'),\n * });\n * });\n * ```\n */\nexport async function listDirectory(\n dirPath: string,\n options?: ListDirectoryOptions,\n): Promise<FileEntry[]> {\n const includeStats = options?.stats !== false;\n const recursive = options?.recursive === true;\n const maxDepth = options?.maxDepth ?? 10;\n const filter = options?.filter;\n\n const entries: FileEntry[] = [];\n\n // Iterative stack — avoids call-stack depth limits on deep trees\n const stack: Array<{ dir: string; relativePath: string; depth: number; }> = [\n { dir: dirPath, relativePath: '', depth: 0 },\n ];\n\n while (stack.length > 0) {\n const { dir, relativePath, depth } = stack.pop()!;\n\n let dirents;\n try {\n dirents = await readdir(dir, { withFileTypes: true });\n } catch {\n continue; // Skip inaccessible directories\n }\n\n if (includeStats) {\n // Parallelize stat calls for all entries in this directory\n const statResults = await Promise.all(\n dirents.map(async (dirent) => {\n try {\n return await stat(join(dir, dirent.name));\n } catch {\n return null;\n }\n }),\n );\n\n for (let i = 0; i < dirents.length; i++) {\n const dirent = dirents[i];\n const s = statResults[i];\n const name = dirent.name;\n const entryPath = relativePath ? `${relativePath}/${name}` : name;\n const isDir = dirent.isDirectory();\n\n const entry: FileEntry = {\n name,\n path: entryPath,\n isDirectory: isDir,\n size: isDir ? 0 : (s?.size ?? 0),\n modifiedAt: s ? s.mtime : new Date(0),\n };\n\n if (!filter || filter(entry)) entries.push(entry);\n if (isDir && recursive && depth < maxDepth) {\n stack.push({ dir: join(dir, name), relativePath: entryPath, depth: depth + 1 });\n }\n }\n } else {\n // Fast path — no stat calls\n for (const dirent of dirents) {\n const name = dirent.name;\n const entryPath = relativePath ? `${relativePath}/${name}` : name;\n const isDir = dirent.isDirectory();\n\n const entry: FileEntry = {\n name,\n path: entryPath,\n isDirectory: isDir,\n size: 0,\n modifiedAt: new Date(0),\n };\n\n if (!filter || filter(entry)) entries.push(entry);\n if (isDir && recursive && depth < maxDepth) {\n stack.push({ dir: join(dir, name), relativePath: entryPath, depth: depth + 1 });\n }\n }\n }\n }\n\n return entries;\n}\n\n/**\n * Extract uploaded files from `FormData` with validation.\n *\n * @example\n * ```ts\n * app.post('/upload', async (ctx) => {\n * const files = await receiveFiles(await ctx.form, {\n * maxFileSize: 10 * 1024 * 1024, // 10 MB\n * maxFiles: 5,\n * allowedTypes: ['image/png', 'image/jpeg'],\n * });\n *\n * for (const file of files) {\n * await saveFile(`./uploads/${file.fileName}`, file.data);\n * }\n * return { uploaded: files.length };\n * });\n * ```\n */\nexport async function receiveFiles(\n formData: FormData,\n options?: ReceiveFileOptions,\n): Promise<UploadedFile[]> {\n const maxSize = options?.maxFileSize ?? Infinity;\n const maxCount = options?.maxFiles ?? Infinity;\n const allowedTypes = options?.allowedTypes;\n const fields = options?.fields;\n const files: UploadedFile[] = [];\n\n for (const [key, value] of formData.entries()) {\n if (typeof value === 'string') continue;\n const file = value as File;\n if (fields && !fields.includes(key)) continue;\n if (files.length >= maxCount) break;\n\n if (file.size > maxSize) {\n throw new Error(`File \"${file.name}\" exceeds maximum size of ${maxSize} bytes`);\n }\n\n if (allowedTypes && !allowedTypes.includes(file.type)) {\n throw new Error(\n `File type \"${file.type}\" is not allowed. Allowed: ${allowedTypes.join(', ')}`,\n );\n }\n\n files.push({\n fieldName: key,\n fileName: file.name,\n type: file.type,\n size: file.size,\n data: await file.arrayBuffer(),\n });\n }\n\n return files;\n}\n\n/**\n * Save data to a file. Auto-creates parent directories when needed.\n * Works across Bun, Node.js, and Deno.\n *\n * @example\n * ```ts\n * await saveFile('./uploads/photo.jpg', file.data);\n * await saveFile('./data/config.json', JSON.stringify(config));\n * ```\n */\nexport async function saveFile(\n filePath: string,\n data: Blob | ArrayBuffer | Uint8Array | string,\n): Promise<void> {\n // Normalise to a type accepted by all runtimes\n let bytes: Uint8Array | string;\n if (data instanceof Blob) {\n bytes = new Uint8Array(await data.arrayBuffer());\n } else if (data instanceof ArrayBuffer) {\n bytes = new Uint8Array(data);\n } else {\n bytes = data; // string or Uint8Array — both accepted by writeFile\n }\n\n try {\n await writeFile(filePath, bytes);\n } catch (err: any) {\n if (err.code === 'ENOENT') {\n // Parent directory missing — create and retry\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, bytes);\n } else {\n throw err;\n }\n }\n}\n","/**\n * Ken Framework - Basic Authentication Middleware\n * Validates HTTP Basic Authentication credentials\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Options for the Basic Auth middleware.\n */\nexport interface BasicAuthOptions {\n /** Expected username (required if verifyUser is not provided) */\n username?: string;\n /** Expected password (required if verifyUser is not provided) */\n password?: string;\n /** Realm for WWW-Authenticate header (default: \"Secure Area\") */\n realm?: string;\n /** Custom verification function. Return true to allow access. */\n verifyUser?: (username: string, password: string, ctx: Context) => boolean | Promise<boolean>;\n}\n\n/**\n * Basic Authentication middleware.\n *\n * Validates the `Authorization: Basic <base64>` header.\n * Returns 401 Response if credentials are missing or invalid.\n *\n * @example\n * ```ts\n * // Static credentials\n * app.get(\"/admin\", {\n * state: { auth: basicAuth({ username: 'admin', password: 'secret' }) }\n * }, (ctx) => Response.json({ user: ctx.state.auth.username }));\n *\n * // Custom verification\n * app.get(\"/admin\", {\n * state: { auth: basicAuth({ verifyUser: (u, p) => u === 'admin' && p === 'secret' }) }\n * }, (ctx) => Response.json({ user: ctx.state.auth.username }));\n * ```\n */\nexport function basicAuth(options: BasicAuthOptions) {\n const realm = options.realm ?? 'Secure Area';\n const wwwAuth = `Basic realm=\"${realm}\"`;\n\n const unauthorizedResponse = () =>\n new Response('Unauthorized', {\n status: 401,\n headers: { 'WWW-Authenticate': wwwAuth },\n });\n\n if (options.verifyUser) {\n const verify = options.verifyUser;\n return async (ctx: Context): Promise<{ username: string; } | Response> => {\n const authorization = ctx.headers['authorization'];\n if (!authorization || !authorization.startsWith('Basic ')) {\n return unauthorizedResponse();\n }\n\n const decoded = atob(authorization.slice(6));\n const colonIndex = decoded.indexOf(':');\n if (colonIndex === -1) return unauthorizedResponse();\n\n const username = decoded.substring(0, colonIndex);\n const password = decoded.substring(colonIndex + 1);\n\n const valid = await verify(username, password, ctx);\n if (!valid) return unauthorizedResponse();\n\n return { username };\n };\n }\n\n const expectedUser = options.username;\n const expectedPass = options.password;\n\n return (ctx: Context): { username: string; } | Response => {\n const authorization = ctx.headers['authorization'];\n if (!authorization || !authorization.startsWith('Basic ')) {\n return unauthorizedResponse();\n }\n\n const decoded = atob(authorization.slice(6));\n const colonIndex = decoded.indexOf(':');\n if (colonIndex === -1) return unauthorizedResponse();\n\n const username = decoded.substring(0, colonIndex);\n const password = decoded.substring(colonIndex + 1);\n\n if (username !== expectedUser || password !== expectedPass) {\n return unauthorizedResponse();\n }\n\n return { username };\n };\n}\n","/**\n * Ken Framework - Bearer Authentication Middleware\n * Validates Bearer token in the Authorization header\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Options for the Bearer Auth middleware.\n */\nexport interface BearerAuthOptions {\n /** Expected token(s). Ignored if verifyToken is provided. */\n token?: string | string[];\n /** Custom token verification function. Return true to allow access. */\n verifyToken?: (token: string, ctx: Context) => boolean | Promise<boolean>;\n /** Realm for WWW-Authenticate header (default: \"\") */\n realm?: string;\n /** Prefix/scheme for the Authorization header (default: \"Bearer\") */\n prefix?: string;\n /** Header name to read token from (default: \"authorization\") */\n headerName?: string;\n}\n\n/**\n * Bearer Authentication middleware.\n *\n * Validates the `Authorization: Bearer <token>` header.\n * Returns 401 Response if token is missing or invalid.\n *\n * @example\n * ```ts\n * app.get(\"/api/data\", {\n * state: { auth: bearerAuth({ token: 'my-api-token' }) }\n * }, (ctx) => Response.json({ token: ctx.state.auth.token }));\n *\n * // Multiple valid tokens\n * app.get(\"/api/data\", {\n * state: { auth: bearerAuth({ token: ['token-a', 'token-b'] }) }\n * }, (ctx) => Response.json({ token: ctx.state.auth.token }));\n *\n * // Custom verification\n * app.get(\"/api/data\", {\n * state: { auth: bearerAuth({ verifyToken: async (t) => t === 'dynamic' }) }\n * }, (ctx) => Response.json({ token: ctx.state.auth.token }));\n * ```\n */\nexport function bearerAuth(options: BearerAuthOptions) {\n const realm = options.realm ?? '';\n const prefix = options.prefix ?? 'Bearer';\n const headerName = (options.headerName ?? 'authorization').toLowerCase();\n const prefixWithSpace = prefix + ' ';\n\n const unauthorizedResponse = (message: string = 'Unauthorized') =>\n new Response(message, {\n status: 401,\n headers: {\n 'WWW-Authenticate': `${prefix} realm=\"${realm}\"${realm ? '' : ', error=\"invalid_token\"'}`,\n },\n });\n\n if (options.verifyToken) {\n const verify = options.verifyToken;\n return async (ctx: Context): Promise<{ token: string; } | Response> => {\n const authHeader = ctx.headers[headerName];\n if (!authHeader || !authHeader.startsWith(prefixWithSpace)) {\n return unauthorizedResponse('No authentication token provided');\n }\n\n const token = authHeader.slice(prefixWithSpace.length).trim();\n if (!token) return unauthorizedResponse('No authentication token provided');\n\n const valid = await verify(token, ctx);\n if (!valid) return unauthorizedResponse('Invalid token');\n\n return { token };\n };\n }\n\n // Static token(s) verification\n const validTokens = Array.isArray(options.token)\n ? new Set(options.token)\n : new Set(options.token ? [options.token] : []);\n\n return (ctx: Context): { token: string; } | Response => {\n const authHeader = ctx.headers[headerName];\n if (!authHeader || !authHeader.startsWith(prefixWithSpace)) {\n return unauthorizedResponse('No authentication token provided');\n }\n\n const token = authHeader.slice(prefixWithSpace.length).trim();\n if (!token) return unauthorizedResponse('No authentication token provided');\n\n if (!validTokens.has(token)) {\n return unauthorizedResponse('Invalid token');\n }\n\n return { token };\n };\n}\n","/**\n * Ken Framework - Body Limit Middleware\n * Rejects requests with bodies exceeding the configured size limit\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Options for the Body Limit middleware.\n */\nexport interface BodyLimitOptions {\n /** Maximum body size in bytes */\n maxSize: number;\n /** Custom error handler. By default throws 413 Payload Too Large. */\n onError?: (ctx: Context) => Response;\n}\n\n/**\n * Body Limit middleware.\n *\n * Checks the `Content-Length` header and rejects requests exceeding the limit.\n * Returns 413 Payload Too Large response if the body is too large.\n *\n * @example\n * ```ts\n * // Limit body to 1MB\n * app.post(\"/upload\", {\n * state: { limit: bodyLimit({ maxSize: 1024 * 1024 }) }\n * }, async (ctx) => {\n * const body = await ctx.json;\n * return Response.json({ received: true });\n * });\n * ```\n */\nexport function bodyLimit(options: BodyLimitOptions) {\n const maxSize = options.maxSize;\n const onError = options.onError;\n\n return (ctx: Context): void | Response => {\n const contentLength = ctx.headers['content-length'];\n if (contentLength) {\n const size = parseInt(contentLength, 10);\n if (!isNaN(size) && size > maxSize) {\n if (onError) {\n return onError(ctx);\n }\n return new Response(`Payload Too Large. Max size: ${maxSize} bytes`, {\n status: 413,\n });\n }\n }\n };\n}\n","/**\n * Ken Framework - Cache Middleware\n * Sets Cache-Control and related caching headers on responses\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Options for the Cache middleware.\n */\nexport interface CacheOptions {\n /** Cache-Control max-age in seconds (default: 0) */\n maxAge?: number;\n /** Cache-Control s-maxage in seconds (for shared caches/CDNs) */\n sMaxAge?: number;\n /** Cache-Control stale-while-revalidate in seconds */\n staleWhileRevalidate?: number;\n /** Cache-Control stale-if-error in seconds */\n staleIfError?: number;\n /** Set `public` directive (default: false) */\n public?: boolean;\n /** Set `private` directive (default: false) */\n private?: boolean;\n /** Set `no-cache` directive (default: false) */\n noCache?: boolean;\n /** Set `no-store` directive (default: false) */\n noStore?: boolean;\n /** Set `must-revalidate` directive (default: false) */\n mustRevalidate?: boolean;\n /** Set `proxy-revalidate` directive (default: false) */\n proxyRevalidate?: boolean;\n /** Set `immutable` directive (default: false) */\n immutable?: boolean;\n /** Set `no-transform` directive (default: false) */\n noTransform?: boolean;\n /** Custom Vary header value */\n vary?: string;\n}\n\n/**\n * Cache middleware.\n *\n * Adds `Cache-Control` and optionally `Vary` headers to responses.\n *\n * @example\n * ```ts\n * // Cache for 1 hour\n * app.get(\"/static\", {\n * state: { caching: cache({ maxAge: 3600, public: true }) }\n * }, () => new Response(\"static content\"));\n *\n * // No caching\n * app.get(\"/dynamic\", {\n * state: { caching: cache({ noStore: true }) }\n * }, () => Response.json({ time: Date.now() }));\n * ```\n */\nexport function cache(options: CacheOptions = {}) {\n // Pre-build the Cache-Control header value at initialization (micro-optimization)\n const directives: string[] = [];\n\n if (options.public) directives.push('public');\n if (options.private) directives.push('private');\n if (options.noCache) directives.push('no-cache');\n if (options.noStore) directives.push('no-store');\n if (options.mustRevalidate) directives.push('must-revalidate');\n if (options.proxyRevalidate) directives.push('proxy-revalidate');\n if (options.immutable) directives.push('immutable');\n if (options.noTransform) directives.push('no-transform');\n\n if (options.maxAge !== undefined) directives.push(`max-age=${options.maxAge}`);\n if (options.sMaxAge !== undefined) directives.push(`s-maxage=${options.sMaxAge}`);\n if (options.staleWhileRevalidate !== undefined) directives.push(`stale-while-revalidate=${options.staleWhileRevalidate}`);\n if (options.staleIfError !== undefined) directives.push(`stale-if-error=${options.staleIfError}`);\n\n const cacheControl = directives.length > 0 ? directives.join(', ') : 'no-cache';\n const vary = options.vary;\n\n return (ctx: Context): void => {\n ctx.onFinish((resp) => {\n if (resp instanceof Response) {\n resp.headers.set('Cache-Control', cacheControl);\n if (vary) {\n resp.headers.set('Vary', vary);\n }\n }\n });\n };\n}\n","/**\n * Ken Framework - Compress Middleware\n * Detects client-supported compression and provides encoding information\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Supported compression encodings.\n */\nexport type CompressionEncoding = 'gzip' | 'deflate' | 'br';\n\n/**\n * Options for the Compress middleware.\n */\nexport interface CompressOptions {\n /** Preferred encoding order (default: ['br', 'gzip', 'deflate']) */\n preferred?: CompressionEncoding[];\n /** Minimum body size in bytes to compress (default: 1024) */\n threshold?: number;\n}\n\n/**\n * Compress middleware.\n *\n * Parses the `Accept-Encoding` header and returns the best encoding\n * in state. Adds `Vary: Accept-Encoding` to responses.\n *\n * Note: Ken delegates actual body compression to the runtime layer.\n * Bun, Deno, and most reverse proxies handle compression natively.\n * This middleware provides encoding preference in state and sets\n * appropriate response headers.\n *\n * @example\n * ```ts\n * app.get(\"/data\", {\n * state: { encoding: compress() }\n * }, (ctx) => {\n * // ctx.state.encoding.encoding is 'gzip' | 'deflate' | 'br' | null\n * return Response.json({ data: largePayload });\n * });\n * ```\n */\nexport function compress(options: CompressOptions = {}) {\n const preferred = options.preferred ?? ['br', 'gzip', 'deflate'];\n\n return (ctx: Context): { encoding: CompressionEncoding | null; } => {\n const acceptEncoding = ctx.headers['accept-encoding'] ?? '';\n\n // Find the best supported encoding\n let encoding: CompressionEncoding | null = null;\n for (let i = 0; i < preferred.length; i++) {\n if (acceptEncoding.indexOf(preferred[i]) !== -1) {\n encoding = preferred[i];\n break;\n }\n }\n\n // Add Vary header via onFinish\n ctx.onFinish((resp) => {\n if (resp instanceof Response) {\n resp.headers.append('Vary', 'Accept-Encoding');\n }\n });\n\n return { encoding };\n };\n}\n","/**\n * Ken Framework - CORS Middleware\n * Cross-Origin Resource Sharing headers\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport { App } from '../core/app';\nimport type { Context } from '../context/types';\n\n/**\n * Options for the CORS middleware.\n */\nexport interface CorsOptions {\n /**\n * Allowed origin(s).\n * - `'*'` allows all origins (default)\n * - A string matches exactly\n * - An array of strings matches any\n * - A function receives the origin and returns the allowed origin\n */\n origin?: string | string[] | ((origin: string, ctx: Context) => string);\n /** Allowed HTTP methods (default: ['GET','HEAD','PUT','POST','DELETE','PATCH']) */\n allowMethods?: string[];\n /** Allowed request headers */\n allowHeaders?: string[];\n /** Headers exposed to the client */\n exposeHeaders?: string[];\n /** Max age for preflight cache in seconds */\n maxAge?: number;\n /** Allow credentials (cookies, authorization headers) */\n credentials?: boolean;\n}\n\n/**\n * CORS middleware.\n *\n * Returns an App instance that automatically handles preflight OPTIONS requests\n * and adds CORS headers to all responses for the specified path pattern.\n *\n * @example.\n *\n * @example\n * ```ts\n * // Use CORS for all routes - mount at root\n * const corsApp = cors();\n * corsApp.get(\"/api/data\", () => Response.json({ data: 1 }));\n * app.use(corsApp);\n *\n * // Use CORS for specific path prefix\n * const apiCors = cors({ origin: 'https://example.com', credentials: true });\n * apiCors.get(\"/data\", () => Response.json({ data: 1 }));\n * app.use('/api', apiCors);\n * ```\n */\nexport function cors(options: CorsOptions = {}): App {\n const originOpt = options.origin ?? '*';\n const allowMethods = (options.allowMethods ?? ['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH']).join(',');\n const allowHeaders = options.allowHeaders?.join(',') ?? '';\n const exposeHeaders = options.exposeHeaders?.join(',') ?? '';\n const maxAge = options.maxAge !== undefined ? String(options.maxAge) : '';\n const credentials = options.credentials ?? false;\n const resolveOrigin = (requestOrigin: string, ctx: Context): string => {\n if (typeof originOpt === 'string') return originOpt;\n if (Array.isArray(originOpt)) {\n return originOpt.includes(requestOrigin) ? requestOrigin : originOpt[0];\n }\n return originOpt(requestOrigin, ctx);\n };\n\n // Create middleware function\n const corsMiddleware = (ctx: Context): void => {\n const requestOrigin = ctx.headers['origin'] ?? '';\n const allowedOrigin = resolveOrigin(requestOrigin, ctx);\n\n // Add CORS headers to responses via onFinish\n ctx.onFinish((resp) => {\n if (resp instanceof Response) {\n resp.headers.set('Access-Control-Allow-Origin', allowedOrigin);\n if (credentials) resp.headers.set('Access-Control-Allow-Credentials', 'true');\n if (exposeHeaders) resp.headers.set('Access-Control-Expose-Headers', exposeHeaders);\n }\n });\n };\n\n // Create preflight handler for OPTIONS\n const preflightHandler = (ctx: Context): Response => {\n const requestOrigin = ctx.headers['origin'] ?? '';\n const allowedOrigin = resolveOrigin(requestOrigin, ctx);\n\n const headers: Record<string, string> = {\n 'Access-Control-Allow-Origin': allowedOrigin,\n 'Access-Control-Allow-Methods': allowMethods,\n };\n\n if (allowHeaders) {\n headers['Access-Control-Allow-Headers'] = allowHeaders;\n } else {\n // Mirror requested headers\n const requestedHeaders = ctx.headers['access-control-request-headers'];\n if (requestedHeaders) {\n headers['Access-Control-Allow-Headers'] = requestedHeaders;\n }\n }\n\n if (maxAge) headers['Access-Control-Max-Age'] = maxAge;\n if (credentials) headers['Access-Control-Allow-Credentials'] = 'true';\n if (exposeHeaders) headers['Access-Control-Expose-Headers'] = exposeHeaders;\n\n return new Response(null, { status: 204, headers });\n };\n\n // Create App instance with middleware applied to wildcard and OPTIONS preflight handler\n const corsApp = new App();\n\n // Apply CORS middleware to all routes using wildcard pattern\n corsApp.apply('/*', corsMiddleware);\n\n // Register OPTIONS handler for preflight requests at both root and wildcard\n corsApp.options('/', preflightHandler);\n // corsApp.options('/*', preflightHandler);\n\n return corsApp;\n}\n","/**\n * Ken Framework - CSRF Protection Middleware\n * Cross-Site Request Forgery protection\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Options for the CSRF middleware.\n */\nexport interface CsrfOptions {\n /**\n * Allowed origin(s).\n * - A string matches exactly\n * - An array of strings matches any\n * - A function receives the origin and returns true to allow\n * - If not set, only same-origin requests are allowed\n */\n origin?: string | string[] | ((origin: string, ctx: Context) => boolean);\n}\n\n/** Unsafe HTTP methods that require CSRF validation */\nconst UNSAFE_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);\n\n/** Content types that can be sent by HTML forms (CSRF-vulnerable) */\nconst FORM_CONTENT_TYPES = ['application/x-www-form-urlencoded', 'multipart/form-data', 'text/plain'];\n\n/**\n * CSRF Protection middleware.\n *\n * Validates the `Origin` header on unsafe requests (POST, PUT, PATCH, DELETE)\n * with form-compatible content types. Returns 403 if the origin is not allowed.\n * Safe methods (GET, HEAD, OPTIONS) are always allowed.\n *\n * @example\n * ```ts\n * // Auto-detect same origin\n * app.define({ protection: csrf() }, (app) => {\n * app.post(\"/submit\", async (ctx) => {\n * const body = await ctx.json;\n * return Response.json({ success: true });\n * });\n * });\n *\n * // Specific origin\n * app.post(\"/submit\", {\n * state: { protection: csrf({ origin: 'https://myapp.example.com' }) }\n * }, async (ctx) => Response.json({ success: true }));\n * ```\n */\nexport function csrf(options: CsrfOptions = {}) {\n const originOpt = options.origin;\n\n return (ctx: Context): void | Response => {\n // Skip safe methods\n if (!UNSAFE_METHODS.has(ctx.method)) return;\n\n // Skip non-form content types (JSON APIs with proper content-type are safe)\n const contentType = (ctx.headers['content-type'] ?? '').toLowerCase();\n const isFormLike = FORM_CONTENT_TYPES.some((t) => contentType.startsWith(t));\n if (contentType && !isFormLike) return;\n\n const requestOrigin = ctx.headers['origin'] ?? '';\n\n // No Origin header — check Referer as fallback\n if (!requestOrigin) {\n const referer = ctx.headers['referer'];\n if (referer) {\n try {\n const refOrigin = new URL(referer).origin;\n if (isAllowed(refOrigin, ctx, originOpt)) return;\n } catch {\n // Invalid referer URL\n }\n }\n // No Origin or Referer — block\n return new Response('CSRF validation failed: missing Origin header', {\n status: 403,\n });\n }\n\n // Validate origin\n if (!isAllowed(requestOrigin, ctx, originOpt)) {\n return new Response('CSRF validation failed: origin not allowed', {\n status: 403,\n });\n }\n };\n}\n\n/**\n * Check if the request origin is allowed.\n */\nfunction isAllowed(\n origin: string,\n ctx: Context,\n originOpt: CsrfOptions['origin']\n): boolean {\n if (!originOpt) {\n // Same-origin check: compare with the request's host\n try {\n const requestUrl = new URL(ctx.url);\n const requestOrigin = requestUrl.origin;\n return origin === requestOrigin;\n } catch {\n return false;\n }\n }\n\n if (typeof originOpt === 'string') {\n return origin === originOpt;\n }\n\n if (Array.isArray(originOpt)) {\n return originOpt.includes(origin);\n }\n\n return originOpt(origin, ctx);\n}\n","/**\n * Ken Framework - ETag Middleware\n * Provides If-None-Match header value for conditional requests\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Options for the ETag middleware.\n */\nexport interface ETagOptions {\n /** Use weak ETags (prefixed with W/) (default: false) */\n weak?: boolean;\n}\n\n/**\n * ETag middleware.\n *\n * Reads the `If-None-Match` request header and returns its value in state.\n * The handler can compare this with its computed ETag to return 304.\n *\n * @example\n * ```ts\n * app.get(\"/data\", {\n * state: { etagValue: etag() }\n * }, (ctx) => {\n * const tag = '\"data-v1\"';\n * if (ctx.state.etagValue === tag) {\n * return new Response(null, { status: 304 });\n * }\n * return new Response(\"content\", { headers: { 'ETag': tag } });\n * });\n * ```\n */\nexport function etag(_options: ETagOptions = {}) {\n return (ctx: Context): string | null => {\n const ifNoneMatch = ctx.headers['if-none-match'] ?? null;\n return ifNoneMatch;\n };\n}\n","/**\n * Ken Framework - IP Restriction Middleware\n * Allow or deny requests based on client IP address\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Options for the IP Restriction middleware.\n */\nexport interface IpRestrictionOptions {\n /** List of allowed IP addresses. If set, only these IPs are allowed. */\n allowList?: string[];\n /** List of denied IP addresses. Checked after allowList. */\n denyList?: string[];\n /** Custom error response factory */\n onError?: (ctx: Context) => Response;\n}\n\n/**\n * IP Restriction middleware.\n *\n * Restricts access based on client IP address using the remote info.\n * Returns 403 if the IP is not in the allow list or is in the deny list.\n *\n * Remote IP detection checks proxy headers (CF-Connecting-IP, X-Real-IP,\n * X-Forwarded-For, True-Client-IP) before falling back to runtime info.\n *\n * @example\n * ```ts\n * // Allow only specific IPs\n * app.get(\"/admin\", {\n * state: { ipCheck: ipRestriction({ allowList: ['127.0.0.1', '::1'] }) }\n * }, () => Response.json({ admin: true }));\n *\n * // Deny specific IPs\n * app.get(\"/public\", {\n * state: { ipCheck: ipRestriction({ denyList: ['10.0.0.1'] }) }\n * }, () => new Response(\"public content\"));\n * ```\n */\nexport function ipRestriction(options: IpRestrictionOptions) {\n const allowSet = options.allowList ? new Set(options.allowList) : null;\n const denySet = options.denyList ? new Set(options.denyList) : null;\n const onError = options.onError;\n\n const forbiddenResponse = (ctx: Context) => {\n if (onError) return onError(ctx);\n return new Response('Forbidden', { status: 403 });\n };\n\n return (ctx: Context): void | Response => {\n const ip = ctx.remoteInfo.address;\n\n // Check allow list first\n if (allowSet && !allowSet.has(ip)) {\n return forbiddenResponse(ctx);\n }\n\n // Check deny list\n if (denySet && denySet.has(ip)) {\n return forbiddenResponse(ctx);\n }\n };\n}\n","/**\n * Ken Framework - JWK Middleware\n * JSON Web Key Set (JWKS) based JWT verification\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\nimport type { JWTPayload } from './jwt';\nimport { encoder, decoder, decodeBase64Url } from '../utils/encoding';\n\n/**\n * JWK key object\n */\nexport interface JWK {\n kty: string;\n kid?: string;\n use?: string;\n alg?: string;\n n?: string;\n e?: string;\n crv?: string;\n x?: string;\n y?: string;\n [key: string]: unknown;\n}\n\n/**\n * JWKS response\n */\nexport interface JWKS {\n keys: JWK[];\n}\n\n/**\n * Options for the JWK middleware.\n */\nexport interface JWKOptions {\n /** URL of the JWKS endpoint */\n jwksUrl?: string;\n /** Pre-loaded JWK keys (alternative to jwksUrl) */\n keys?: JWK[];\n /** Expected issuer claim */\n issuer?: string;\n /** Expected audience claim */\n audience?: string;\n /** Header name (default: 'authorization') */\n headerName?: string;\n /** Token prefix (default: 'Bearer') */\n prefix?: string;\n /** Clock tolerance in seconds for exp/nbf checks (default: 0) */\n clockTolerance?: number;\n /** Cache TTL for JWKS keys in milliseconds (default: 600000 = 10 min) */\n cacheTtl?: number;\n}\n\n// ==================== Algorithm Mapping ====================\n\nconst RSA_HASH_MAP: Record<string, string> = {\n 'RS256': 'SHA-256',\n 'RS384': 'SHA-384',\n 'RS512': 'SHA-512',\n};\n\nconst EC_HASH_MAP: Record<string, { hash: string; namedCurve: string; }> = {\n 'ES256': { hash: 'SHA-256', namedCurve: 'P-256' },\n 'ES384': { hash: 'SHA-384', namedCurve: 'P-384' },\n 'ES512': { hash: 'SHA-512', namedCurve: 'P-521' },\n};\n\n// ==================== JWKS Cache ====================\n\nlet cachedKeys: JWK[] | null = null;\nlet cacheExpiry = 0;\n\nasync function fetchJwks(url: string, ttl: number): Promise<JWK[]> {\n const now = Date.now();\n if (cachedKeys && now < cacheExpiry) {\n return cachedKeys;\n }\n\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch JWKS: ${response.status}`);\n }\n\n const jwks: JWKS = await response.json();\n cachedKeys = jwks.keys;\n cacheExpiry = now + ttl;\n return cachedKeys;\n}\n\n// ==================== JWK Verification ====================\n\nasync function verifyWithJwk(\n token: string,\n keys: JWK[],\n options: {\n issuer?: string;\n audience?: string;\n clockTolerance?: number;\n }\n): Promise<JWTPayload> {\n const parts = token.split('.');\n if (parts.length !== 3) throw new Error('Invalid JWT format');\n\n const headerJson = decoder.decode(decodeBase64Url(parts[0]));\n const header = JSON.parse(headerJson);\n const alg: string = header.alg;\n const kid: string | undefined = header.kid;\n\n // Find matching key\n let jwk: JWK | undefined;\n if (kid) {\n jwk = keys.find((k) => k.kid === kid);\n }\n if (!jwk) {\n // Try to find by algorithm\n jwk = keys.find((k) => k.alg === alg || (!k.alg && k.use === 'sig'));\n }\n if (!jwk) {\n throw new Error(`No matching JWK found for kid=${kid}, alg=${alg}`);\n }\n\n // Import key and verify\n const data = encoder.encode(`${parts[0]}.${parts[1]}`);\n const signature = decodeBase64Url(parts[2]);\n let key: CryptoKey;\n\n if (RSA_HASH_MAP[alg]) {\n key = await crypto.subtle.importKey(\n 'jwk',\n jwk as JsonWebKey,\n { name: 'RSASSA-PKCS1-v1_5', hash: RSA_HASH_MAP[alg] },\n false,\n ['verify']\n );\n const valid = await crypto.subtle.verify('RSASSA-PKCS1-v1_5', key, signature, data);\n if (!valid) throw new Error('Invalid JWT signature');\n } else if (EC_HASH_MAP[alg]) {\n const ecInfo = EC_HASH_MAP[alg];\n key = await crypto.subtle.importKey(\n 'jwk',\n jwk as JsonWebKey,\n { name: 'ECDSA', namedCurve: ecInfo.namedCurve },\n false,\n ['verify']\n );\n const valid = await crypto.subtle.verify(\n { name: 'ECDSA', hash: ecInfo.hash },\n key,\n signature,\n data\n );\n if (!valid) throw new Error('Invalid JWT signature');\n } else {\n throw new Error(`Unsupported algorithm: ${alg}`);\n }\n\n // Decode payload\n const payloadJson = decoder.decode(decodeBase64Url(parts[1]));\n const payload: JWTPayload = JSON.parse(payloadJson);\n\n // Validate claims\n const now = Math.floor(Date.now() / 1000);\n const tolerance = options.clockTolerance ?? 0;\n\n if (payload.exp !== undefined && now >= payload.exp + tolerance) {\n throw new Error('JWT expired');\n }\n\n if (payload.nbf !== undefined && now < payload.nbf - tolerance) {\n throw new Error('JWT not yet valid');\n }\n\n if (options.issuer && payload.iss !== options.issuer) {\n throw new Error(`Invalid issuer: expected ${options.issuer}`);\n }\n\n if (options.audience) {\n const aud = payload.aud;\n const validAudience = Array.isArray(aud) ? aud.includes(options.audience) : aud === options.audience;\n if (!validAudience) {\n throw new Error(`Invalid audience: expected ${options.audience}`);\n }\n }\n\n return payload;\n}\n\n// ==================== JWK Middleware ====================\n\n/**\n * JWK middleware.\n *\n * Verifies JWT tokens using JSON Web Key Set (JWKS).\n * Supports RSA (RS256/384/512) and ECDSA (ES256/384/512) algorithms.\n * Keys are cached and refreshed automatically.\n *\n * @example\n * ```ts\n * // With JWKS URL (e.g., from Auth0, Firebase, etc.)\n * app.get(\"/protected\", {\n * state: { auth: jwk({ jwksUrl: 'https://auth.example.com/.well-known/jwks.json' }) }\n * }, (ctx) => Response.json({ user: ctx.state.auth.sub }));\n *\n * // With pre-loaded keys\n * app.get(\"/protected\", {\n * state: { auth: jwk({ keys: [{ kty: 'RSA', n: '...', e: '...' }] }) }\n * }, (ctx) => Response.json({ user: ctx.state.auth.sub }));\n * ```\n */\nexport function jwk(options: JWKOptions) {\n const headerName = (options.headerName ?? 'authorization').toLowerCase();\n const prefix = options.prefix ?? 'Bearer';\n const prefixWithSpace = prefix + ' ';\n const cacheTtl = options.cacheTtl ?? 600_000;\n const verifyOpts = {\n issuer: options.issuer,\n audience: options.audience,\n clockTolerance: options.clockTolerance,\n };\n\n return async (ctx: Context): Promise<JWTPayload | Response> => {\n const authHeader = ctx.headers[headerName];\n if (!authHeader || !authHeader.startsWith(prefixWithSpace)) {\n return new Response('JWT token required', {\n status: 401,\n headers: { 'WWW-Authenticate': `Bearer realm=\"\", error=\"invalid_token\"` },\n });\n }\n\n const token = authHeader.slice(prefixWithSpace.length).trim();\n if (!token) {\n return new Response('JWT token required', {\n status: 401,\n headers: { 'WWW-Authenticate': `Bearer realm=\"\", error=\"invalid_token\"` },\n });\n }\n\n try {\n let keys: JWK[];\n if (options.keys) {\n keys = options.keys;\n } else if (options.jwksUrl) {\n keys = await fetchJwks(options.jwksUrl, cacheTtl);\n } else {\n throw new Error('Either jwksUrl or keys must be provided');\n }\n\n return await verifyWithJwk(token, keys, verifyOpts);\n } catch (err: any) {\n return new Response(`JWK verification failed: ${err.message}`, {\n status: 401,\n headers: { 'WWW-Authenticate': `Bearer realm=\"\", error=\"invalid_token\"` },\n });\n }\n };\n}\n","/**\n * Ken Framework - JWT Middleware\n * JSON Web Token verification using Web Crypto API\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\nimport { encoder, decoder, encodeBase64Url, decodeBase64Url } from '../utils/encoding';\n\n/**\n * JWT payload type\n */\nexport interface JWTPayload {\n /** Issuer */\n iss?: string;\n /** Subject */\n sub?: string;\n /** Audience */\n aud?: string | string[];\n /** Expiration time (seconds since epoch) */\n exp?: number;\n /** Not before (seconds since epoch) */\n nbf?: number;\n /** Issued at (seconds since epoch) */\n iat?: number;\n /** JWT ID */\n jti?: string;\n /** Custom claims */\n [key: string]: unknown;\n}\n\n/**\n * Supported HMAC algorithms\n */\nexport type JWTAlgorithm = 'HS256' | 'HS384' | 'HS512';\n\n/**\n * Options for the JWT middleware.\n */\nexport interface JWTOptions {\n /** HMAC secret key for signature verification */\n secret: string;\n /** Expected algorithm (default: 'HS256') */\n algorithm?: JWTAlgorithm;\n /** Expected issuer claim */\n issuer?: string;\n /** Expected audience claim */\n audience?: string;\n /** Header name (default: 'authorization') */\n headerName?: string;\n /** Token prefix (default: 'Bearer') */\n prefix?: string;\n /** Clock tolerance in seconds for exp/nbf checks (default: 0) */\n clockTolerance?: number;\n}\n\n// ==================== Algorithm Mapping ====================\n\nconst HASH_MAP: Record<string, string> = {\n 'HS256': 'SHA-256',\n 'HS384': 'SHA-384',\n 'HS512': 'SHA-512',\n};\n\n// ==================== JWT Verification ====================\n\n/**\n * Verify a JWT token and return the payload.\n *\n * @param token - The JWT token string\n * @param secret - The HMAC secret key\n * @param options - Verification options\n * @returns The decoded JWT payload\n * @throws Error if the token is invalid\n */\nexport async function verifyJwt(\n token: string,\n secret: string,\n options: {\n algorithm?: JWTAlgorithm;\n issuer?: string;\n audience?: string;\n clockTolerance?: number;\n } = {}\n): Promise<JWTPayload> {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Invalid JWT format');\n }\n\n // Decode header\n const headerJson = decoder.decode(decodeBase64Url(parts[0]));\n const header = JSON.parse(headerJson);\n\n // Verify algorithm\n const alg = header.alg;\n const expectedAlg = options.algorithm ?? 'HS256';\n if (alg !== expectedAlg) {\n throw new Error(`Algorithm mismatch: expected ${expectedAlg}, got ${alg}`);\n }\n\n const hash = HASH_MAP[alg];\n if (!hash) {\n throw new Error(`Unsupported algorithm: ${alg}`);\n }\n\n // Import key\n const keyData = encoder.encode(secret);\n const key = await crypto.subtle.importKey(\n 'raw',\n keyData,\n { name: 'HMAC', hash },\n false,\n ['verify']\n );\n\n // Verify signature\n const data = encoder.encode(`${parts[0]}.${parts[1]}`);\n const signature = decodeBase64Url(parts[2]);\n const valid = await crypto.subtle.verify('HMAC', key, signature, data);\n if (!valid) {\n throw new Error('Invalid JWT signature');\n }\n\n // Decode payload\n const payloadJson = decoder.decode(decodeBase64Url(parts[1]));\n const payload: JWTPayload = JSON.parse(payloadJson);\n\n // Validate claims\n const now = Math.floor(Date.now() / 1000);\n const tolerance = options.clockTolerance ?? 0;\n\n if (payload.exp !== undefined && now >= payload.exp + tolerance) {\n throw new Error('JWT expired');\n }\n\n if (payload.nbf !== undefined && now < payload.nbf - tolerance) {\n throw new Error('JWT not yet valid');\n }\n\n if (options.issuer && payload.iss !== options.issuer) {\n throw new Error(`Invalid issuer: expected ${options.issuer}, got ${payload.iss}`);\n }\n\n if (options.audience) {\n const aud = payload.aud;\n const validAudience = Array.isArray(aud)\n ? aud.includes(options.audience)\n : aud === options.audience;\n if (!validAudience) {\n throw new Error(`Invalid audience: expected ${options.audience}`);\n }\n }\n\n return payload;\n}\n\n/**\n * Sign a JWT payload and return the token string.\n *\n * @param payload - The JWT payload\n * @param secret - The HMAC secret key\n * @param algorithm - The algorithm to use (default: 'HS256')\n * @returns The signed JWT token string\n */\nexport async function signJwt(\n payload: JWTPayload,\n secret: string,\n algorithm: JWTAlgorithm = 'HS256'\n): Promise<string> {\n const header = { alg: algorithm, typ: 'JWT' };\n\n const headerB64 = encodeBase64Url(encoder.encode(JSON.stringify(header)));\n const payloadB64 = encodeBase64Url(encoder.encode(JSON.stringify(payload)));\n\n const hash = HASH_MAP[algorithm];\n const keyData = encoder.encode(secret);\n const key = await crypto.subtle.importKey(\n 'raw',\n keyData,\n { name: 'HMAC', hash },\n false,\n ['sign']\n );\n\n const data = encoder.encode(`${headerB64}.${payloadB64}`);\n const signature = await crypto.subtle.sign('HMAC', key, data);\n const signatureB64 = encodeBase64Url(new Uint8Array(signature));\n\n return `${headerB64}.${payloadB64}.${signatureB64}`;\n}\n\n/**\n * Decode a JWT token without verification (unsafe - for debugging only).\n */\nexport function decodeJwt(token: string): { header: any; payload: JWTPayload; } {\n const parts = token.split('.');\n if (parts.length !== 3) throw new Error('Invalid JWT format');\n\n const header = JSON.parse(decoder.decode(decodeBase64Url(parts[0])));\n const payload = JSON.parse(decoder.decode(decodeBase64Url(parts[1])));\n\n return { header, payload };\n}\n\n// ==================== JWT Middleware ====================\n\n/**\n * JWT middleware.\n *\n * Verifies the JWT token from the Authorization header using HMAC.\n * Returns 401 if the token is missing, invalid, or expired.\n * Returns the decoded payload.\n *\n * @example\n * ```ts\n * app.get(\"/protected\", {\n * state: { auth: jwt({ secret: 'my-secret-key' }) }\n * }, (ctx) => Response.json({ user: ctx.state.auth.sub }));\n * ```\n */\nexport function jwt(options: JWTOptions) {\n const secret = options.secret;\n const algorithm = options.algorithm ?? 'HS256';\n const headerName = (options.headerName ?? 'authorization').toLowerCase();\n const prefix = options.prefix ?? 'Bearer';\n const prefixWithSpace = prefix + ' ';\n const verifyOpts = {\n algorithm,\n issuer: options.issuer,\n audience: options.audience,\n clockTolerance: options.clockTolerance,\n };\n\n return async (ctx: Context): Promise<JWTPayload | Response> => {\n const authHeader = ctx.headers[headerName];\n if (!authHeader || !authHeader.startsWith(prefixWithSpace)) {\n return new Response('JWT token required', {\n status: 401,\n headers: { 'WWW-Authenticate': `Bearer realm=\"\", error=\"invalid_token\"` },\n });\n }\n\n const token = authHeader.slice(prefixWithSpace.length).trim();\n if (!token) {\n return new Response('JWT token required', {\n status: 401,\n headers: { 'WWW-Authenticate': `Bearer realm=\"\", error=\"invalid_token\"` },\n });\n }\n\n try {\n return await verifyJwt(token, secret, verifyOpts);\n } catch (err: any) {\n return new Response(`JWT verification failed: ${err.message}`, {\n status: 401,\n headers: { 'WWW-Authenticate': `Bearer realm=\"\", error=\"invalid_token\"` },\n });\n }\n };\n}\n","/**\n * Ken Framework - Logger Middleware\n * Logs request/response information\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport { App } from '../core/app';\nimport type { Context } from '../context/types';\n\n/**\n * Options for the Logger middleware.\n */\nexport interface LoggerOptions {\n /** Custom log function (default: console.log) */\n logFn?: (message: string) => void;\n /**\n * Custom log format function.\n * Receives request info and returns the log message.\n */\n format?: (info: {\n method: string;\n url: string;\n status: number;\n duration: number;\n }) => string;\n}\n\n/**\n * Logger middleware.\n *\n * Returns an App instance that logs all requests for all HTTP methods.\n * Captures method, URL, status code, and response time.\n *\n * @example\n * ```ts\n * // Use logger for all routes (default console.log with colors)\n * app.use(logger());\n * app.get(\"/api/data\", () => Response.json({ data: 1 }));\n *\n * // Use logger for specific path prefix\n * app.use('/api', logger());\n *\n * // Custom log function\n * const logs: string[] = [];\n * app.use(logger({ logFn: (msg) => logs.push(msg) }));\n * ```\n */\nexport function logger(options: LoggerOptions = {}): App {\n const logFn = options.logFn ?? console.log;\n\n // Micro-optimization: cache the formatter function to avoid repeated 'if' checks\n const formatter = options.format\n ? (method: string, url: string, status: number, duration: number) =>\n options.format!({ method, url, status, duration })\n : (method: string, url: string, status: number, duration: number) => {\n // Default formatter with colors (ANSI escape codes)\n const methodColor = '\\x1b[36m'; // cyan\n const statusColor = status >= 500 ? '\\x1b[31m' : status >= 400 ? '\\x1b[33m' : status >= 300 ? '\\x1b[36m' : '\\x1b[32m'; // red/yellow/cyan/green\n const reset = '\\x1b[0m';\n return `${methodColor}${method}${reset} ${url} - ${statusColor}${status}${reset} - ${duration}ms`;\n };\n\n // Create middleware function\n const loggerMiddleware = (ctx: Context): void => {\n const start = Date.now();\n\n ctx.onFinish((resp) => {\n const duration = Date.now() - start;\n const status = resp instanceof Response ? resp.status : 200;\n logFn(formatter(ctx.method, ctx.url, status, duration));\n });\n };\n\n // Create App instance with logger middleware applied to all routes\n const loggerApp = new App();\n\n // Apply logger middleware to all routes using wildcard pattern\n loggerApp.apply('/*', loggerMiddleware);\n\n return loggerApp;\n}\n","/**\n * Ken Framework - Request ID Middleware\n * Generates a unique request identifier\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Options for the Request ID middleware.\n */\nexport interface RequestIdOptions {\n /** Custom ID generator (default: crypto.randomUUID) */\n generator?: () => string;\n /** Header name to set on the response (default: 'X-Request-Id') */\n headerName?: string;\n /** Header name to read from the incoming request. If present, reuses the ID. */\n requestHeaderName?: string;\n}\n\n/**\n * Request ID middleware.\n *\n * Generates a unique ID for each request and returns it in state.\n * Also adds the ID to the response via the specified header.\n *\n * @example\n * ```ts\n * app.get(\"/api/data\", {\n * state: { reqId: requestId() }\n * }, (ctx) => Response.json({ id: ctx.state.reqId }));\n * ```\n */\nexport function requestId(options: RequestIdOptions = {}) {\n const generator = options.generator ?? (() => crypto.randomUUID());\n const responseHeader = options.headerName ?? 'X-Request-Id';\n const requestHeader = options.requestHeaderName;\n\n return (ctx: Context): string => {\n // Reuse incoming request ID if configured and present\n let id: string | undefined;\n if (requestHeader) {\n id = ctx.headers[requestHeader.toLowerCase()] || undefined;\n }\n if (!id) {\n id = generator();\n }\n\n // Add to response headers via onFinish\n ctx.onFinish((resp) => {\n if (resp instanceof Response) {\n resp.headers.set(responseHeader, id!);\n }\n });\n\n return id;\n };\n}\n","/**\n * Ken Framework - Secure Headers Middleware\n * Adds security-related HTTP headers to responses\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Options for the Secure Headers middleware.\n * Set a header to `false` to disable it, or a string to override its value.\n */\nexport interface SecureHeadersOptions {\n /** Content-Security-Policy (default: not set) */\n contentSecurityPolicy?: string | false;\n /** Cross-Origin-Embedder-Policy (default: not set) */\n crossOriginEmbedderPolicy?: string | false;\n /** Cross-Origin-Opener-Policy (default: 'same-origin') */\n crossOriginOpenerPolicy?: string | false;\n /** Cross-Origin-Resource-Policy (default: 'same-origin') */\n crossOriginResourcePolicy?: string | false;\n /** Origin-Agent-Cluster (default: '?1') */\n originAgentCluster?: string | false;\n /** Referrer-Policy (default: 'no-referrer') */\n referrerPolicy?: string | false;\n /** Strict-Transport-Security (default: 'max-age=15552000; includeSubDomains') */\n strictTransportSecurity?: string | false;\n /** X-Content-Type-Options (default: 'nosniff') */\n xContentTypeOptions?: string | false;\n /** X-DNS-Prefetch-Control (default: 'off') */\n xDnsPrefetchControl?: string | false;\n /** X-Download-Options (default: 'noopen') */\n xDownloadOptions?: string | false;\n /** X-Frame-Options (default: 'SAMEORIGIN') */\n xFrameOptions?: string | false;\n /** X-Permitted-Cross-Domain-Policies (default: 'none') */\n xPermittedCrossDomainPolicies?: string | false;\n /** X-XSS-Protection (default: '0') */\n xXssProtection?: string | false;\n /** Remove X-Powered-By header (default: true) */\n removePoweredBy?: boolean;\n}\n\n/**\n * Default secure header values.\n */\nconst DEFAULTS: Record<string, string> = {\n 'Cross-Origin-Opener-Policy': 'same-origin',\n 'Cross-Origin-Resource-Policy': 'same-origin',\n 'Origin-Agent-Cluster': '?1',\n 'Referrer-Policy': 'no-referrer',\n 'Strict-Transport-Security': 'max-age=15552000; includeSubDomains',\n 'X-Content-Type-Options': 'nosniff',\n 'X-DNS-Prefetch-Control': 'off',\n 'X-Download-Options': 'noopen',\n 'X-Frame-Options': 'SAMEORIGIN',\n 'X-Permitted-Cross-Domain-Policies': 'none',\n 'X-XSS-Protection': '0',\n};\n\n/** Maps option key to header name */\nconst OPTION_TO_HEADER: Record<string, string> = {\n contentSecurityPolicy: 'Content-Security-Policy',\n crossOriginEmbedderPolicy: 'Cross-Origin-Embedder-Policy',\n crossOriginOpenerPolicy: 'Cross-Origin-Opener-Policy',\n crossOriginResourcePolicy: 'Cross-Origin-Resource-Policy',\n originAgentCluster: 'Origin-Agent-Cluster',\n referrerPolicy: 'Referrer-Policy',\n strictTransportSecurity: 'Strict-Transport-Security',\n xContentTypeOptions: 'X-Content-Type-Options',\n xDnsPrefetchControl: 'X-DNS-Prefetch-Control',\n xDownloadOptions: 'X-Download-Options',\n xFrameOptions: 'X-Frame-Options',\n xPermittedCrossDomainPolicies: 'X-Permitted-Cross-Domain-Policies',\n xXssProtection: 'X-XSS-Protection',\n};\n\n/**\n * Secure Headers middleware.\n *\n * Adds security-related HTTP headers to responses. Uses sensible\n * defaults inspired by Helmet. Individual headers can be overridden\n * or disabled.\n *\n * @example\n * ```ts\n * // Use sensible defaults\n * app.define({ sec: secureHeaders() }, (app) => {\n * app.get(\"/\", () => new Response(\"secure\"));\n * });\n *\n * // Customize\n * app.define({ sec: secureHeaders({\n * xFrameOptions: 'DENY',\n * contentSecurityPolicy: \"default-src 'self'\",\n * }) }, (app) => {\n * app.get(\"/\", () => new Response(\"secure\"));\n * });\n * ```\n */\nexport function secureHeaders(options: SecureHeadersOptions = {}) {\n const removePoweredBy = options.removePoweredBy !== false;\n\n // Pre-build the headers map at initialization (micro-optimization)\n const headers: Array<[string, string]> = [];\n\n for (const [optKey, headerName] of Object.entries(OPTION_TO_HEADER)) {\n const optValue = (options as any)[optKey];\n\n if (optValue === false) {\n // Explicitly disabled\n continue;\n }\n\n if (typeof optValue === 'string') {\n // Custom value\n headers.push([headerName, optValue]);\n } else if (DEFAULTS[headerName]) {\n // Use default\n headers.push([headerName, DEFAULTS[headerName]]);\n }\n }\n\n return (ctx: Context): void => {\n ctx.onFinish((resp) => {\n if (resp instanceof Response) {\n for (let i = 0; i < headers.length; i++) {\n resp.headers.set(headers[i][0], headers[i][1]);\n }\n if (removePoweredBy) {\n resp.headers.delete('X-Powered-By');\n }\n }\n });\n };\n}\n","/**\n * Ken Framework - Session Middleware\n * Flexible session management with customizable validation logic.\n * Auto-detects sync vs async validation at initialization time.\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Options for the Session middleware.\n */\nexport interface SessionOptions<T = any> {\n /** Name of the cookie to read session from */\n cookieName: string;\n /**\n * Custom validation function.\n * Receives the cookie value and context.\n * Return session data on success, or throw/return a Response to deny access.\n * Returning null/undefined also triggers the unauthorized handler.\n */\n validate: (cookieValue: string, ctx: Context) => T | Response | Promise<T | Response>;\n /**\n * Custom unauthorized response factory.\n * Called when cookie is missing, validation returns null, or throws a non-Response error.\n * Defaults to `new Response('Unauthorized', { status: 401 })`.\n */\n onUnauthorized?: (ctx: Context) => Response;\n}\n\n/** Pre-allocated 401 body to avoid per-request string allocation */\nconst UNAUTHORIZED_BODY = 'Unauthorized';\n\n/**\n * Session middleware with auto-detection of sync vs async validation.\n *\n * Reads a cookie, passes it to a user-supplied `validate` function,\n * and either returns session data into `ctx.state` or short-circuits\n * with a `Response`. The sync/async branch is resolved once at\n * initialization time via `constructor.name` check — zero per-request overhead.\n *\n * @example\n * ```ts\n * // Sync — in-memory lookup\n * const auth = session({\n * cookieName: '_sid',\n * validate: (sid) => {\n * const user = USERS.get(sid);\n * if (!user) throw new Response('Unauthorized', { status: 401 });\n * return user;\n * },\n * });\n *\n * // Async — encrypted cookie + DB lookup\n * const auth = session({\n * cookieName: '_ak',\n * validate: async (cookieValue, ctx) => {\n * const apiKey = await decryptString(cookieValue, secretKey);\n * if (!MEDIA_OWNERS[apiKey]?.active) {\n * throw new Response(null, {\n * status: 302,\n * headers: { 'Location': '/auth?redirect=' + ctx.url },\n * });\n * }\n * return apiKey;\n * },\n * });\n *\n * app.get('/', { state: { session: auth } }, (ctx) => {\n * return Response.json({ key: ctx.state.session });\n * });\n * ```\n */\nexport function session<T = any>(options: SessionOptions<T>) {\n const { cookieName, validate, onUnauthorized } = options;\n\n // Hoist the unauthorized factory — avoid re-reading options per request\n const unauthorized = onUnauthorized\n ?? (() => new Response(UNAUTHORIZED_BODY, { status: 401 }));\n\n // Branch once at init — the compiler will see either a sync or async\n // middleware function and select the matching executor path.\n if (validate.constructor.name === 'AsyncFunction') {\n return async (ctx: Context): Promise<T | Response> => {\n const cookie = ctx.cookies[cookieName];\n if (!cookie) return unauthorized(ctx);\n\n try {\n const result = await validate(cookie, ctx);\n if (result == null || result instanceof Response) {\n return result ?? unauthorized(ctx);\n }\n return result;\n } catch (e) {\n return e instanceof Response ? e : unauthorized(ctx);\n }\n };\n }\n\n // Sync path — no Promise wrapper, no await\n return (ctx: Context): T | Response => {\n const cookie = ctx.cookies[cookieName];\n if (!cookie) return unauthorized(ctx);\n\n try {\n const result = validate(cookie, ctx) as T | Response;\n if (result == null || result instanceof Response) {\n return result ?? unauthorized(ctx);\n }\n return result;\n } catch (e) {\n return e instanceof Response ? e : unauthorized(ctx);\n }\n };\n}\n","/**\n * Ken Framework - Timeout Middleware\n * Provides request timeout capabilities via AbortSignal\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Options for the Timeout middleware.\n */\nexport interface TimeoutOptions {\n /** Timeout duration in milliseconds */\n duration: number;\n /** Custom timeout response (default: 408 Request Timeout) */\n onTimeout?: (ctx: Context) => Response;\n}\n\n/**\n * Timeout middleware.\n *\n * Creates an AbortController with a timeout. Returns the AbortSignal\n * in state so the handler can check for timeout or pass it to fetch calls.\n * The timer is automatically cleared when the response finishes.\n *\n * @example\n * ```ts\n * app.get(\"/slow-endpoint\", {\n * state: { timeoutSig: timeout({ duration: 5000 }) }\n * }, async (ctx) => {\n * // Pass signal to downstream fetch calls\n * const data = await fetch('https://api.example.com/data', {\n * signal: ctx.state.timeoutSig.signal,\n * });\n * return Response.json(await data.json());\n * });\n * ```\n */\nexport function timeout(options: TimeoutOptions) {\n const duration = options.duration;\n const onTimeout = options.onTimeout;\n\n return (ctx: Context): { signal: AbortSignal; } | Response => {\n const controller = new AbortController();\n\n const timer = setTimeout(() => {\n controller.abort();\n if (onTimeout) {\n // Return timeout response (will be handled by executor)\n return onTimeout(ctx);\n }\n }, duration);\n\n // Clear the timer when the response finishes\n ctx.onFinish(() => {\n clearTimeout(timer);\n });\n\n return { signal: controller.signal };\n };\n}\n","/**\n * Ken Framework - Timing Middleware\n * Server-Timing header for performance monitoring\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { Context } from '../context/types';\n\n/**\n * Options for the Timing middleware.\n */\nexport interface TimingOptions {\n /** Metric name (default: 'total') */\n name?: string;\n /** Description for the Server-Timing entry */\n description?: string;\n /** Whether to include the timing header (default: true) */\n enabled?: boolean;\n}\n\n/**\n * Timing middleware.\n *\n * Measures request processing time and adds a `Server-Timing` header\n * to the response. Useful for performance monitoring.\n *\n * @example\n * ```ts\n * app.define({ perf: timing() }, (app) => {\n * app.get(\"/api/data\", () => Response.json({ data: 1 }));\n * });\n * // Response header: Server-Timing: total;dur=2.5\n *\n * // Custom metric name\n * app.get(\"/api/data\", {\n * state: { perf: timing({ name: 'app', description: 'Application processing' }) }\n * }, () => Response.json({ data: 1 }));\n * // Response header: Server-Timing: app;desc=\"Application processing\";dur=2.5\n * ```\n */\nexport function timing(options: TimingOptions = {}) {\n const name = options.name ?? 'total';\n const description = options.description;\n const enabled = options.enabled !== false;\n\n return (ctx: Context): void => {\n if (!enabled) return;\n\n const start = performance.now();\n\n ctx.onFinish((resp) => {\n if (resp instanceof Response) {\n const dur = (performance.now() - start).toFixed(2);\n let value = `${name};dur=${dur}`;\n if (description) {\n value = `${name};desc=\"${description}\";dur=${dur}`;\n }\n\n // Append to existing Server-Timing header if present\n const existing = resp.headers.get('Server-Timing');\n if (existing) {\n resp.headers.set('Server-Timing', `${existing}, ${value}`);\n } else {\n resp.headers.set('Server-Timing', value);\n }\n }\n });\n };\n}\n","/**\n * Ken Framework - Binary WebSocket Protocol Codec (KBWP)\n *\n * Compact binary framing for WebSocket messages optimized for bandwidth-\n * constrained environments (4G, IoT, mobile). Eliminates JSON protocol\n * overhead while preserving full pub/sub and request-response semantics.\n *\n * Frame layout (all multi-byte integers are big-endian):\n *\n * ┌──────────┬──────────────────────────────────────────┐\n * │ Type (1B)│ Type-specific fields (variable) │\n * └──────────┴──────────────────────────────────────────┘\n *\n * Message types:\n * 0x01 PING [] 1 byte\n * 0x02 PONG [] 1 byte\n * 0x03 REQUEST [corrId:u32] [payload…] 5+ bytes\n * 0x04 RESPONSE [corrId:u32] [payload…] 5+ bytes\n * 0x05 SUBSCRIBE [topicLen:u8] [topic…] 2+ bytes\n * 0x06 UNSUBSCRIBE [topicLen:u8] [topic…] 2+ bytes\n * 0x07 PUBLISH [topicLen:u8] [topic…] [payload…] 2+ bytes\n * 0x08 MESSAGE [topicLen:u8] [topic…] [payload…] 2+ bytes\n * 0x09 AUTH [payload…] 1+ bytes\n * 0x0A AUTH_OK [payload…] 1+ bytes\n * 0x0B AUTH_FAIL [payload…] 1+ bytes\n *\n * Payload is the remaining bytes after fixed-length fields — no length\n * prefix needed because WebSocket frames are already length-delimited.\n *\n * Bandwidth comparison vs JSON:\n * Ping: 1 byte vs 15 bytes ({\"type\":\"ping\"}) → 93% reduction\n * Subscribe: ~6 bytes vs ~35 bytes → 83% reduction\n * Request: 5 + N vs 20 + N (JSON _kid overhead) → significant\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Message type constants\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Binary protocol message type identifiers */\nexport const MsgType = {\n PING: 0x01,\n PONG: 0x02,\n REQUEST: 0x03,\n RESPONSE: 0x04,\n SUBSCRIBE: 0x05,\n UNSUBSCRIBE: 0x06,\n PUBLISH: 0x07,\n MESSAGE: 0x08,\n AUTH: 0x09,\n AUTH_OK: 0x0a,\n AUTH_FAIL: 0x0b,\n} as const;\n\nexport type MsgTypeValue = (typeof MsgType)[keyof typeof MsgType];\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Module-scope singletons — zero per-call allocation\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\n/** Pre-allocated 1-byte PING frame — shared immutable buffer */\nconst PING_BUF = new Uint8Array([MsgType.PING]);\n\n/** Pre-allocated 1-byte PONG frame — shared immutable buffer */\nconst PONG_BUF = new Uint8Array([MsgType.PONG]);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Decoded message types (discriminated union)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface DecodedPing { readonly type: typeof MsgType.PING; }\nexport interface DecodedPong { readonly type: typeof MsgType.PONG; }\nexport interface DecodedRequest {\n readonly type: typeof MsgType.REQUEST;\n readonly corrId: number;\n /** Raw JSON string payload (caller parses if needed) */\n readonly payload: string;\n}\nexport interface DecodedResponse {\n readonly type: typeof MsgType.RESPONSE;\n readonly corrId: number;\n /** Raw JSON string payload (caller parses if needed) */\n readonly payload: string;\n}\nexport interface DecodedSubscribe {\n readonly type: typeof MsgType.SUBSCRIBE;\n readonly topic: string;\n}\nexport interface DecodedUnsubscribe {\n readonly type: typeof MsgType.UNSUBSCRIBE;\n readonly topic: string;\n}\nexport interface DecodedPublish {\n readonly type: typeof MsgType.PUBLISH;\n readonly topic: string;\n /** Raw JSON string payload (caller parses if needed) */\n readonly payload: string;\n}\nexport interface DecodedMessage {\n readonly type: typeof MsgType.MESSAGE;\n readonly topic: string;\n /** Raw JSON string payload (caller parses if needed) */\n readonly payload: string;\n}\n\nexport interface DecodedAuth {\n readonly type: typeof MsgType.AUTH;\n /** Auth token */\n readonly payload: string;\n}\n\nexport interface DecodedAuthOk {\n readonly type: typeof MsgType.AUTH_OK;\n /** Optional data from server (may be empty) */\n readonly payload: string;\n}\n\nexport interface DecodedAuthFail {\n readonly type: typeof MsgType.AUTH_FAIL;\n /** Reason string */\n readonly payload: string;\n}\n\nexport type DecodedFrame =\n | DecodedPing\n | DecodedPong\n | DecodedRequest\n | DecodedResponse\n | DecodedSubscribe\n | DecodedUnsubscribe\n | DecodedPublish\n | DecodedMessage\n | DecodedAuth\n | DecodedAuthOk\n | DecodedAuthFail;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Encode functions\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Returns the pre-allocated 1-byte PING frame. Do NOT mutate. */\nexport function encodePing(): Uint8Array {\n return PING_BUF;\n}\n\n/** Returns the pre-allocated 1-byte PONG frame. Do NOT mutate. */\nexport function encodePong(): Uint8Array {\n return PONG_BUF;\n}\n\n/**\n * Encode a REQUEST frame: [0x03][corrId:u32][payload UTF-8…]\n *\n * @param corrId - Correlation ID (uint32, 0–4294967295)\n * @param payload - JSON string payload\n */\nexport function encodeRequest(corrId: number, payload: string): Uint8Array {\n const payloadBytes = encoder.encode(payload);\n const buf = new Uint8Array(5 + payloadBytes.length);\n buf[0] = MsgType.REQUEST;\n // Big-endian uint32 — manual write avoids DataView allocation\n buf[1] = (corrId >>> 24) & 0xff;\n buf[2] = (corrId >>> 16) & 0xff;\n buf[3] = (corrId >>> 8) & 0xff;\n buf[4] = corrId & 0xff;\n buf.set(payloadBytes, 5);\n return buf;\n}\n\n/**\n * Encode a RESPONSE frame: [0x04][corrId:u32][payload UTF-8…]\n *\n * @param corrId - Correlation ID echoed from the REQUEST\n * @param payload - Response data (string or binary)\n */\nexport function encodeResponse(corrId: number, payload: string | Uint8Array): Uint8Array {\n const payloadBytes = typeof payload === 'string' ? encoder.encode(payload) : payload;\n const buf = new Uint8Array(5 + payloadBytes.length);\n buf[0] = MsgType.RESPONSE;\n buf[1] = (corrId >>> 24) & 0xff;\n buf[2] = (corrId >>> 16) & 0xff;\n buf[3] = (corrId >>> 8) & 0xff;\n buf[4] = corrId & 0xff;\n buf.set(payloadBytes, 5);\n return buf;\n}\n\n/**\n * Encode a SUBSCRIBE frame: [0x05][topicLen:u8][topic UTF-8…]\n *\n * @param topic - Topic name (max 255 UTF-8 bytes)\n */\nexport function encodeSubscribe(topic: string): Uint8Array {\n const topicBytes = encoder.encode(topic);\n const buf = new Uint8Array(2 + topicBytes.length);\n buf[0] = MsgType.SUBSCRIBE;\n buf[1] = topicBytes.length;\n buf.set(topicBytes, 2);\n return buf;\n}\n\n/**\n * Encode an UNSUBSCRIBE frame: [0x06][topicLen:u8][topic UTF-8…]\n *\n * @param topic - Topic name (max 255 UTF-8 bytes)\n */\nexport function encodeUnsubscribe(topic: string): Uint8Array {\n const topicBytes = encoder.encode(topic);\n const buf = new Uint8Array(2 + topicBytes.length);\n buf[0] = MsgType.UNSUBSCRIBE;\n buf[1] = topicBytes.length;\n buf.set(topicBytes, 2);\n return buf;\n}\n\n/**\n * Encode a PUBLISH frame: [0x07][topicLen:u8][topic UTF-8…][payload UTF-8…]\n *\n * @param topic - Topic name (max 255 UTF-8 bytes)\n * @param payload - JSON string payload\n */\nexport function encodePublish(topic: string, payload: string): Uint8Array {\n const topicBytes = encoder.encode(topic);\n const payloadBytes = encoder.encode(payload);\n const buf = new Uint8Array(2 + topicBytes.length + payloadBytes.length);\n buf[0] = MsgType.PUBLISH;\n buf[1] = topicBytes.length;\n buf.set(topicBytes, 2);\n buf.set(payloadBytes, 2 + topicBytes.length);\n return buf;\n}\n\n/**\n * Encode a MESSAGE frame: [0x08][topicLen:u8][topic UTF-8…][payload UTF-8…]\n *\n * @param topic - Topic name (max 255 UTF-8 bytes)\n * @param payload - JSON string payload\n */\nexport function encodeMessage(topic: string, payload: string): Uint8Array {\n const topicBytes = encoder.encode(topic);\n const payloadBytes = encoder.encode(payload);\n const buf = new Uint8Array(2 + topicBytes.length + payloadBytes.length);\n buf[0] = MsgType.MESSAGE;\n buf[1] = topicBytes.length;\n buf.set(topicBytes, 2);\n buf.set(payloadBytes, 2 + topicBytes.length);\n return buf;\n}\n\n/**\n * Encode an AUTH frame: [0x09][token UTF-8…]\n *\n * @param token - Auth token string\n */\nexport function encodeAuth(token: string): Uint8Array {\n const tokenBytes = encoder.encode(token);\n const buf = new Uint8Array(1 + tokenBytes.length);\n buf[0] = MsgType.AUTH;\n buf.set(tokenBytes, 1);\n return buf;\n}\n\n/**\n * Encode an AUTH_OK frame: [0x0A][payload UTF-8…]\n *\n * @param payload - Optional data to send back to client (may be empty)\n */\nexport function encodeAuthOk(payload = ''): Uint8Array {\n if (payload.length === 0) return new Uint8Array([MsgType.AUTH_OK]);\n const payloadBytes = encoder.encode(payload);\n const buf = new Uint8Array(1 + payloadBytes.length);\n buf[0] = MsgType.AUTH_OK;\n buf.set(payloadBytes, 1);\n return buf;\n}\n\n/**\n * Encode an AUTH_FAIL frame: [0x0B][reason UTF-8…]\n *\n * @param reason - Failure reason string\n */\nexport function encodeAuthFail(reason: string): Uint8Array {\n const reasonBytes = encoder.encode(reason);\n const buf = new Uint8Array(1 + reasonBytes.length);\n buf[0] = MsgType.AUTH_FAIL;\n buf.set(reasonBytes, 1);\n return buf;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Decode\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Decode a binary WebSocket frame into a typed message.\n *\n * @param data - Raw binary data (ArrayBuffer or Uint8Array)\n * @returns Decoded frame, or `null` if the type byte is unrecognized or\n * the frame is too short for the declared type.\n */\nexport function decode(data: ArrayBuffer | Uint8Array): DecodedFrame | null {\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);\n if (bytes.length === 0) return null;\n\n const type = bytes[0];\n\n switch (type) {\n // ── Ping / Pong ───────────────────────────────────────────────────────\n case MsgType.PING:\n return { type: MsgType.PING };\n\n case MsgType.PONG:\n return { type: MsgType.PONG };\n\n // ── Request / Response ────────────────────────────────────────────────\n case MsgType.REQUEST:\n case MsgType.RESPONSE: {\n if (bytes.length < 5) return null;\n const corrId =\n ((bytes[1] << 24) | (bytes[2] << 16) | (bytes[3] << 8) | bytes[4]) >>> 0;\n const payload = bytes.length > 5 ? decoder.decode(bytes.subarray(5)) : '';\n return type === MsgType.REQUEST\n ? { type: MsgType.REQUEST, corrId, payload }\n : { type: MsgType.RESPONSE, corrId, payload };\n }\n\n // ── Subscribe / Unsubscribe ───────────────────────────────────────────\n case MsgType.SUBSCRIBE:\n case MsgType.UNSUBSCRIBE: {\n if (bytes.length < 2) return null;\n const topicLen = bytes[1];\n if (bytes.length < 2 + topicLen) return null;\n const topic = decoder.decode(bytes.subarray(2, 2 + topicLen));\n return type === MsgType.SUBSCRIBE\n ? { type: MsgType.SUBSCRIBE, topic }\n : { type: MsgType.UNSUBSCRIBE, topic };\n }\n\n // ── Publish / Message ─────────────────────────────────────────────────\n case MsgType.PUBLISH:\n case MsgType.MESSAGE: {\n if (bytes.length < 2) return null;\n const topicLen = bytes[1];\n if (bytes.length < 2 + topicLen) return null;\n const topic = decoder.decode(bytes.subarray(2, 2 + topicLen));\n const payloadOffset = 2 + topicLen;\n const payload = bytes.length > payloadOffset\n ? decoder.decode(bytes.subarray(payloadOffset))\n : '';\n return type === MsgType.PUBLISH\n ? { type: MsgType.PUBLISH, topic, payload }\n : { type: MsgType.MESSAGE, topic, payload };\n }\n\n // ── Auth ───────────────────────────────────────────────────────────────\n case MsgType.AUTH:\n case MsgType.AUTH_OK:\n case MsgType.AUTH_FAIL: {\n const payload = bytes.length > 1 ? decoder.decode(bytes.subarray(1)) : '';\n return type === MsgType.AUTH\n ? { type: MsgType.AUTH, payload }\n : type === MsgType.AUTH_OK\n ? { type: MsgType.AUTH_OK, payload }\n : { type: MsgType.AUTH_FAIL, payload };\n }\n\n default:\n return null;\n }\n}\n\n/**\n * Check if a binary buffer starts with a known Ken protocol type byte.\n * Use this as a fast pre-check before calling `decode()`.\n *\n * @param data - Binary data (first byte is checked)\n * @returns true if byte 0 is a recognized MsgType\n */\nexport function isKenBinaryFrame(data: ArrayBuffer | Uint8Array): boolean {\n const firstByte = data instanceof Uint8Array ? data[0] : new Uint8Array(data, 0, 1)[0];\n return firstByte !== undefined && firstByte >= MsgType.PING && firstByte <= MsgType.AUTH_FAIL;\n}\n","/**\n * Ken Framework - WSClient Protocol Middleware\n * Transparently handles the Ken Binary WebSocket Protocol (KBWP) for WSClient users.\n *\n * Includes:\n * - wsClientProtocol: registers a WebSocket route with full KBWP support\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport { App } from '../core/app';\nimport type { WsPeer, WsHandler, WsOptions, WsMessageData } from '../ws/types';\nimport {\n MsgType,\n decode,\n encodePong,\n encodeResponse,\n encodeAuthOk,\n encodeAuthFail,\n} from '../ws/codec';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Module-scope constants — hoisted, zero per-request allocation\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Pre-allocated 1-byte binary PONG frame */\nconst PONG_BIN = encodePong();\n\n/** Pre-allocated 1-byte binary AUTH_OK frame */\nconst AUTHOK_BIN = encodeAuthOk();\n\n/** Protocol message type string — hoisted to avoid per-call string allocation */\nconst PROTO_MESSAGE = 'message';\n\n/** WebSocket close code for auth failures */\nconst AUTH_CLOSE_CODE = 4001;\n\n/** Pre-encoded AUTH_FAIL frame — zero per-call allocation */\nconst AUTH_FAIL_INVALID_BIN = encodeAuthFail('Invalid token');\n\n/**\n * Sentinel value for unauthenticated peers.\n * Stored as `peer.data` — O(1) reference equality replaces `Set.has()`.\n */\nconst UNAUTHED: unique symbol = Symbol('unauthed');\n\n// ─────────────────────────────────────────────────────────────────────────────\n// WsDefinition\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Combined handler + options definition passed to {@link wsClientProtocol}.\n *\n * Merges all {@link WsHandler} callbacks and {@link WsOptions} fields into\n * a single object so there is only one place to configure a WebSocket route.\n *\n * @template T - Per-connection data type\n */\nexport interface WsDefinition<T = unknown> extends WsHandler<T> {\n /** @see WsOptions.maxPayloadLength */\n maxPayloadLength?: number;\n /** @see WsOptions.backpressureLimit */\n backpressureLimit?: number;\n /** @see WsOptions.pingInterval */\n pingInterval?: number;\n /** @see WsOptions.pongTimeout */\n pongTimeout?: number;\n /** @see WsOptions.perMessageDeflate */\n perMessageDeflate?: boolean;\n /** @see WsOptions.idleTimeout */\n idleTimeout?: number;\n\n /**\n * Authentication handler. When provided, all connections must authenticate\n * via post-connect AUTH binary frame or URL query parameter (dev/staging).\n *\n * Called with the token string. Return user data (`T`) on success,\n * or `null` to reject the connection.\n *\n * When not provided, auth is disabled — all connections pass through.\n *\n * @example\n * ```ts\n * wsClientProtocol<{ userId: string }>({\n * authenticate: async (token) => {\n * const user = await verifyJwt(token);\n * if (!user) return null;\n * return { userId: user.id };\n * },\n * message(peer, msg) {\n * // peer.data.userId is available here\n * },\n * });\n * ```\n */\n authenticate?: (token: string) => T | null | Promise<T | null>;\n\n /**\n * URL query parameter name for token-based auth (dev/staging support).\n * When a connection URL contains this parameter, the token is validated\n * during upgrade and the connection is pre-authenticated.\n * Only used when `authenticate` is provided.\n * @default 'token'\n */\n tokenParam?: string;\n}\n\n\n\n// ─────────────────────────────────────────────────────────────────────────────\n// wsClientProtocol\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * WebSocket middleware with full WSClient binary protocol (KBWP) support.\n *\n * Registers a WebSocket route at '/' and transparently handles the Ken\n * Binary WebSocket Protocol — heartbeat (ping/pong), pub/sub, and\n * request-response — so your `message` handler only receives domain messages.\n *\n * Returns an `App` instance so it composes naturally with `app.use()`.\n * The path is supplied via the `app.use()` call, which prepends it to the\n * WebSocket route.\n *\n * **Binary protocol messages intercepted (client → server):**\n * - PING (0x01) → responds with PONG (0x02)\n * - SUBSCRIBE (0x05) → calls `peer.subscribe(topic)`\n * - UNSUBSCRIBE (0x06) → calls `peer.unsubscribe(topic)`\n * - PUBLISH (0x07) → calls `peer.publish(topic, jsonEnvelope)`\n * so all topic subscribers receive a `{\"type\":\"message\",...}` envelope\n * that `WSClient` knows how to route.\n * - REQUEST (0x03) → calls user `message` handler with decoded payload;\n * the first `peer.send()` is automatically wrapped in a RESPONSE (0x04)\n * frame echoing the correlation ID.\n *\n * **Non-binary messages** (plain strings) are forwarded directly to the\n * user `message` handler without any protocol interception.\n *\n * All `WsOptions` fields can be co-located in the `config` object.\n *\n * @example\n * ```ts\n * // Mount at a path (no auth)\n * app.use('/chat', wsClientProtocol({\n * pingInterval: 20,\n * idleTimeout: 60,\n * upgrade(req) {\n * const name = new URL(req.url).searchParams.get('name') ?? 'anon';\n * return { username: name };\n * },\n * open(peer) { peer.subscribe('chat'); },\n * message(peer, msg) { peer.send(`echo: ${msg}`); },\n * close(peer) { peer.unsubscribe('chat'); },\n * }));\n *\n * // With post-connect binary auth (secure, invisible in logs)\n * app.use('/ws', wsClientProtocol<{ userId: string }>({\n * authenticate: async (token) => {\n * const user = await verifyJwt(token);\n * return user ? { userId: user.id } : null;\n * },\n * // tokenParam: 'token', // also accepts ?token= in URL (for Insomnia/dev)\n * open(peer) { console.log('authed:', peer.data.userId); },\n * message(peer, msg) { peer.send(msg); },\n * }));\n * ```\n *\n * @template T - Per-connection data type\n * @param config - Handler callbacks and optional WsOptions, co-located in one object\n * @returns An `App` instance ready to be passed to `app.use()`\n */\nexport function wsClientProtocol<T = unknown>(\n config: WsDefinition<T>,\n): App {\n // ── Destructure handler callbacks and WsOptions fields ──────────────────\n\n const {\n upgrade: userUpgrade,\n open: userOpen,\n message: userMessage,\n close: userClose,\n ping,\n pong,\n error,\n authenticate,\n tokenParam,\n maxPayloadLength,\n backpressureLimit,\n pingInterval,\n pongTimeout,\n perMessageDeflate,\n idleTimeout,\n } = config;\n\n const authTokenParam = tokenParam ?? 'token';\n\n // ── Build WsOptions (only set defined values) ────────────────────────────\n\n const options: WsOptions = {};\n if (maxPayloadLength !== undefined) options.maxPayloadLength = maxPayloadLength;\n if (backpressureLimit !== undefined) options.backpressureLimit = backpressureLimit;\n if (pingInterval !== undefined) options.pingInterval = pingInterval;\n if (pongTimeout !== undefined) options.pongTimeout = pongTimeout;\n if (perMessageDeflate !== undefined) options.perMessageDeflate = perMessageDeflate;\n if (idleTimeout !== undefined) options.idleTimeout = idleTimeout;\n\n // ── Auth state tracking (only allocated when authenticate is provided) ──\n\n // Pre-auth tracking: peers that authenticated via URL param during upgrade.\n // Uses WeakSet<object> to link upgrade return → open handler without leaking.\n const preAuthPeers = authenticate ? new WeakSet<object>() : null;\n\n // ── KBWP message handler (shared by both auth and no-auth paths) ────────\n\n const handleKbwp = (peer: WsPeer<T>, message: WsMessageData): void | Promise<void> => {\n // ── Binary protocol handling (KBWP) ──────────────────────────────────\n if (typeof message !== 'string') {\n const bytes = message instanceof Uint8Array ? message : new Uint8Array(message as ArrayBuffer);\n if (bytes.length === 0) return userMessage(peer, message);\n\n // Fast-path: 1-byte frames (PING/PONG) — skip full decode.\n // With 1M connections × 30s heartbeat ≈ 33K pings/sec on hot path.\n if (bytes.length === 1) {\n if (bytes[0] === MsgType.PING) { peer.send(PONG_BIN); return; }\n if (bytes[0] === MsgType.PONG) return;\n return userMessage(peer, message);\n }\n\n const frame = decode(bytes);\n if (frame === null) return userMessage(peer, message);\n\n switch (frame.type) {\n // ── Binary pub/sub ────────────────────────────────────────────────\n case MsgType.SUBSCRIBE:\n peer.subscribe(frame.topic);\n return;\n\n case MsgType.UNSUBSCRIBE:\n peer.unsubscribe(frame.topic);\n return;\n\n case MsgType.PUBLISH:\n if (frame.topic) {\n // Direct string construction — avoids JSON.parse + JSON.stringify cycle.\n // frame.payload is already valid JSON from the client encoder.\n peer.publish(\n frame.topic,\n '{\"type\":\"' + PROTO_MESSAGE + '\",\"topic\":' + JSON.stringify(frame.topic) + ',\"data\":' + frame.payload + '}',\n );\n }\n return;\n\n // ── Binary request-response ───────────────────────────────────────\n case MsgType.REQUEST: {\n const { corrId, payload } = frame;\n const origSend = peer.send;\n\n // Monkey-patch send for transparent RESPONSE wrapping.\n // Arrow fn avoids named-function object allocation.\n // Restores original on first call — no `responded` boolean needed.\n (peer as { send: typeof origSend; }).send = (\n data: WsMessageData, compress?: boolean,\n ): number => {\n (peer as { send: typeof origSend; }).send = origSend;\n return origSend.call(\n peer,\n typeof data === 'string'\n ? encodeResponse(corrId, data)\n : encodeResponse(corrId, data as unknown as Uint8Array),\n compress,\n );\n };\n\n const result = userMessage(peer, payload);\n\n if (result && typeof (result as Promise<void>).then === 'function') {\n return (result as Promise<void>).finally(() => {\n if ((peer as any).send !== origSend) {\n (peer as { send: typeof origSend; }).send = origSend;\n }\n });\n }\n if ((peer as any).send !== origSend) {\n (peer as { send: typeof origSend; }).send = origSend;\n }\n return result;\n }\n\n // ── Binary message / response (server→server, handle gracefully) ──\n case MsgType.MESSAGE:\n case MsgType.RESPONSE:\n return userMessage(peer, message);\n }\n }\n\n // Non-binary message — forward directly to user handler\n return userMessage(peer, message);\n };\n\n // ── Build handler based on auth mode (compile-time branching) ───────────\n\n let wrappedUpgrade: WsHandler<T>['upgrade'];\n let wrappedOpen: WsHandler<T>['open'];\n let wrappedClose: WsHandler<T>['close'];\n let wrappedMessage: WsHandler<T>['message'];\n\n if (authenticate) {\n // ════════════════════════════════════════════════════════════════════════\n // AUTH ENABLED — gate all handlers behind authentication\n // ════════════════════════════════════════════════════════════════════════\n\n /** Handle successful authentication for a peer */\n const authSuccess = (peer: WsPeer<T>, data: T): void => {\n (peer as { data: T; }).data = data;\n peer.send(AUTHOK_BIN);\n userOpen?.(peer);\n };\n\n /** Handle AUTH frame from an unauthenticated peer */\n const handleAuth = (peer: WsPeer<T>, token: string): void | Promise<void> => {\n const result = authenticate(token);\n\n // Async authenticate\n if (result !== null && typeof (result as Promise<T | null>).then === 'function') {\n return (result as Promise<T | null>).then(data => {\n if (data === null || data === undefined) {\n peer.send(AUTH_FAIL_INVALID_BIN);\n peer.close(AUTH_CLOSE_CODE, 'Invalid token');\n return;\n }\n authSuccess(peer, data);\n });\n }\n\n // Sync authenticate\n if (result === null || result === undefined) {\n peer.send(AUTH_FAIL_INVALID_BIN);\n peer.close(AUTH_CLOSE_CODE, 'Invalid token');\n return;\n }\n\n authSuccess(peer, result as T);\n };\n\n // ── Wrapped upgrade: check URL param token for dev/staging ─────────\n wrappedUpgrade = (req: Request): T | Response | Promise<T | Response> => {\n const url = new URL(req.url);\n const token = url.searchParams.get(authTokenParam);\n\n if (token) {\n // URL param auth (dev/staging/Insomnia)\n const result = authenticate(token);\n\n if (result !== null && typeof (result as Promise<T | null>).then === 'function') {\n return (result as Promise<T | null>).then(data => {\n if (data === null || data === undefined) {\n return new Response('Unauthorized', { status: 401 });\n }\n // Mark as pre-authenticated for detection in wrappedOpen\n if (typeof data === 'object' && data !== null) {\n preAuthPeers!.add(data as object);\n }\n return data;\n });\n }\n\n if (result === null || result === undefined) {\n return new Response('Unauthorized', { status: 401 });\n }\n\n // Mark as pre-authenticated\n const data = result as T;\n if (typeof data === 'object' && data !== null) {\n preAuthPeers!.add(data as object);\n }\n return data;\n }\n\n // No URL token — run user's upgrade handler (if any)\n if (userUpgrade) return userUpgrade(req);\n return undefined as unknown as T;\n };\n\n // ── Wrapped open: mark unauthenticated or fire user open ──────────\n wrappedOpen = (peer: WsPeer<T>): void => {\n // Check if pre-authenticated via URL param\n if (peer.data && typeof peer.data === 'object' && preAuthPeers!.has(peer.data as object)) {\n preAuthPeers!.delete(peer.data as object);\n userOpen?.(peer);\n return;\n }\n\n // Not pre-authenticated — mark as unauthenticated via sentinel.\n // No server-side timer: the client's auth timeout disconnects on\n // deadline; idleTimeout catches rogue clients that send nothing.\n (peer as { data: unknown; }).data = UNAUTHED;\n };\n\n // ── Wrapped close: forward to user handler ─────────────────────────\n wrappedClose = userClose;\n\n // ── Wrapped message: gate behind auth + handle AUTH frames ─────────\n wrappedMessage = (peer: WsPeer<T>, message: WsMessageData): void | Promise<void> => {\n // Fast path: authenticated peers — O(1) sentinel reference comparison\n // replaces Set.has() hash lookup per message\n if ((peer as { data: unknown; }).data !== UNAUTHED) {\n return handleKbwp(peer, message);\n }\n\n // Unauthenticated: only accept binary AUTH frames — reject everything else\n if (typeof message !== 'string') {\n const bytes = message instanceof Uint8Array ? message : new Uint8Array(message as ArrayBuffer);\n if (bytes.length > 0 && bytes[0] === MsgType.AUTH) {\n const frame = decode(bytes);\n if (frame && frame.type === MsgType.AUTH) {\n return handleAuth(peer, frame.payload);\n }\n }\n }\n\n // Non-AUTH message from unauthenticated peer — disconnect immediately\n peer.close(AUTH_CLOSE_CODE, 'Not authenticated');\n };\n } else {\n // ════════════════════════════════════════════════════════════════════════\n // NO AUTH — zero overhead, pass through directly\n // ════════════════════════════════════════════════════════════════════════\n wrappedUpgrade = userUpgrade;\n wrappedOpen = userOpen;\n wrappedClose = userClose;\n wrappedMessage = handleKbwp;\n }\n\n // ── Assemble handler (only include defined callbacks) ────────────────────\n\n const handler: WsHandler<T> = { message: wrappedMessage };\n if (wrappedUpgrade !== undefined) handler.upgrade = wrappedUpgrade;\n if (wrappedOpen !== undefined) handler.open = wrappedOpen;\n if (wrappedClose !== undefined) handler.close = wrappedClose;\n if (ping !== undefined) handler.ping = ping;\n if (pong !== undefined) handler.pong = pong;\n if (error !== undefined) handler.error = error;\n\n // ── Create app with WebSocket route at root ──────────────────────────────\n\n const wsApp = new App();\n wsApp.ws('/', handler, options);\n\n return wsApp;\n}\n","/**\n * Ken Framework - WSClient\n * High-performance, fault-tolerant WebSocket client with binary protocol.\n * Zero-dependency. Works on Bun, Deno, and Node.js.\n *\n * Uses the Ken Binary WebSocket Protocol (KBWP) for minimal bandwidth\n * overhead — optimized for 24/7 operation on bandwidth-constrained devices.\n *\n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport {\n MsgType,\n encodePing,\n encodeAuth,\n encodeRequest,\n encodeSubscribe,\n encodeUnsubscribe,\n encodePublish,\n decode,\n type DecodedFrame,\n} from './codec';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Constants — hoisted to module scope, zero per-request overhead\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst DEFAULT_MAX_RETRIES = Infinity;\nconst DEFAULT_BACKOFF_BASE = 500; // ms\nconst DEFAULT_BACKOFF_MAX = 30_000; // ms\nconst DEFAULT_BACKOFF_FACTOR = 2;\nconst DEFAULT_HEARTBEAT_INTERVAL = 30_000; // ms\nconst DEFAULT_REQUEST_TIMEOUT = 10_000; // ms\nconst DEFAULT_AUTH_TIMEOUT = 10_000; // ms\n\n/** Pre-encoded 1-byte binary PING frame — zero per-call allocation */\nconst PING_FRAME = encodePing();\n\n/**\n * Send a Uint8Array over a WebSocket as its underlying ArrayBuffer.\n * Avoids TS strict-mode errors with Uint8Array<ArrayBufferLike>.\n */\nfunction sendBinary(ws: WebSocket, data: Uint8Array): void {\n ws.send(data.buffer as ArrayBuffer);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// State Machine\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Connection state enum — use numeric values for fast comparison */\nexport const WsClientState = {\n CONNECTING: 0,\n OPEN: 1,\n CLOSING: 2,\n CLOSED: 3,\n RECONNECTING: 4,\n} as const;\n\nexport type WsClientStateValue = (typeof WsClientState)[keyof typeof WsClientState];\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Pending request entry stored in the correlation registry */\ninterface PendingRequest {\n resolve: (data: unknown) => void;\n reject: (err: Error) => void;\n /** Timer handle — cleared on response or timeout */\n timer: ReturnType<typeof setTimeout>;\n}\n\n/**\n * WSClient configuration options\n */\nexport interface WsClientOptions {\n /**\n * Auth token. Sent as a binary AUTH frame (post-connect, secure)\n * or as a `?token=` URL param depending on `authMode`.\n */\n token?: string;\n\n /**\n * How to send the auth token:\n * - `'message'` — Post-connect binary AUTH frame (secure, invisible in logs). Default.\n * - `'query'` — URL query parameter (visible in logs, for dev tools like Insomnia).\n *\n * Only relevant when `token` is set. Ignored otherwise.\n * @default 'message'\n */\n authMode?: 'message' | 'query';\n\n /**\n * Milliseconds to wait for AUTH_OK after sending AUTH frame.\n * Only used when `authMode` is `'message'`.\n * @default 10_000\n */\n authTimeout?: number;\n\n /**\n * Maximum number of reconnect attempts. Default: Infinity.\n */\n maxRetries?: number;\n\n /**\n * Multiplier applied to the backoff delay after each failed attempt.\n * Default: 2\n */\n backoffFactor?: number;\n\n /**\n * Maximum backoff delay in ms. Default: 30_000\n */\n backoffMax?: number;\n\n /**\n * Base reconnect delay in ms. Default: 500\n */\n backoffBase?: number;\n\n /**\n * Milliseconds between application-level heartbeat pings.\n * Set to 0 to disable. Default: 30_000\n */\n heartbeatInterval?: number;\n\n /**\n * Milliseconds before a `sendWait()` call times out. Default: 10_000\n */\n requestTimeout?: number;\n\n /**\n * Event hook — called for every incoming binary protocol frame.\n * Receives the decoded frame object. Fires after internal routing\n * (REQUEST/RESPONSE correlation, pub/sub dispatch) has been applied.\n */\n onFrame?: (frame: DecodedFrame) => void;\n\n /**\n * Event hook — called when the connection is established.\n */\n\n onConnect?: () => void;\n\n /**\n * Event hook — called when the connection is lost.\n * Receives the WebSocket close code and reason.\n */\n onDisconnect?: (code: number, reason: string) => void;\n\n /**\n * Event hook — called before each reconnect attempt.\n * Receives the attempt number (1-based) and the delay in ms.\n */\n onReconnectAttempt?: (attempt: number, delay: number) => void;\n\n /**\n * Event hook — called for every incoming message.\n */\n onData?: (data: string | ArrayBuffer) => void;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// WSClient\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Ken WSClient — A fault-tolerant, high-performance WebSocket client\n * with binary protocol transport.\n *\n * Features:\n * - Ken Binary WebSocket Protocol (KBWP) — 80-93% bandwidth reduction\n * over JSON for protocol messages (ping/pong, subscribe, publish)\n * - State machine (CONNECTING / OPEN / CLOSING / CLOSED / RECONNECTING)\n * - Exponential backoff + jitter reconnection\n * - 1-byte binary heartbeat (ping/pong)\n * - Request-response via `sendWait()` with uint32 correlation IDs\n * (no field collision — corrId lives in binary header, not payload)\n * - Pub/sub with binary framing (subscribe/unsubscribe/publish/message)\n * - Full lifecycle hooks: onConnect, onDisconnect, onReconnectAttempt, onData\n * - Zero memory leaks — all timers and listeners are strictly cleaned up\n *\n * @example\n * ```ts\n * const client = new WSClient('wss://api.example.com/ws', {\n * token: 'my-jwt',\n * onConnect: () => console.log('Connected'),\n * onDisconnect: (code) => console.log('Disconnected', code),\n * });\n *\n * await client.connect();\n *\n * // Fire-and-forget (raw string — not wrapped in binary protocol)\n * client.send('hello');\n *\n * // Request-response (binary REQUEST frame, no _kid collision)\n * const result = await client.sendWait({ type: 'getData', id: 42 });\n *\n * // Pub/sub (binary SUBSCRIBE/PUBLISH frames)\n * client.subscribe('events', (data) => console.log(data));\n * client.publish('events', { action: 'click' });\n *\n * await client.close();\n * ```\n */\nexport class WSClient {\n // ── Public state ────────────────────────────────────────────────────────\n\n /** Current state of the connection */\n state: WsClientStateValue = WsClientState.CLOSED;\n\n // ── Private fields — all initialized here for V8 monomorphic shape ──────\n\n private readonly _url: string;\n private readonly _authTimeout: number;\n private readonly _maxRetries: number;\n private readonly _backoffFactor: number;\n private readonly _backoffMax: number;\n private readonly _backoffBase: number;\n private readonly _heartbeatInterval: number;\n private readonly _requestTimeout: number;\n private readonly _onConnect: (() => void) | undefined;\n private readonly _onDisconnect: ((code: number, reason: string) => void) | undefined;\n private readonly _onReconnectAttempt: ((attempt: number, delay: number) => void) | undefined;\n private readonly _onData: ((data: string | ArrayBuffer) => void) | undefined;\n private readonly _onFrame: ((frame: DecodedFrame) => void) | undefined;\n\n /** Active WebSocket instance */\n private _ws: WebSocket | null = null;\n\n /** Number of consecutive failed reconnect attempts */\n private _retries = 0;\n\n /** Correlation registry: corrId (uint32) → PendingRequest */\n private _pending: Map<number, PendingRequest> = new Map();\n\n /**\n * Active pub/sub subscriptions: topic → callback.\n * Persists across reconnects so topics are re-sent in _onOpen.\n */\n private _subscriptions: Map<string, (data: unknown) => void> = new Map();\n\n /** Heartbeat timer handle */\n private _heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n\n /** Reconnect delay timer handle */\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n /** Whether destroy() / close() was explicitly called */\n private _destroyed = false;\n\n /** Post-connect auth resolve/reject for the connect() promise */\n private _authResolve: (() => void) | null = null;\n private _authReject: ((err: Error) => void) | null = null;\n\n /** Auth timeout timer handle */\n private _authTimer: ReturnType<typeof setTimeout> | null = null;\n\n /** Whether auth is pending (post-connect, waiting for AUTH_OK/AUTH_FAIL) */\n private _authPending = false;\n\n /** Pre-encoded AUTH frame — zero per-reconnect allocation */\n private readonly _authFrame: Uint8Array | null;\n\n /**\n * Monotonically increasing uint32 counter for correlation IDs.\n * Wraps at 0xFFFFFFFF to stay within 4-byte range.\n */\n private _idCounter = 0;\n\n // ── Bound event handlers — created once, reused per connection ───────────\n\n private readonly _handleOpen: () => void;\n private readonly _handleMessage: (event: MessageEvent) => void;\n private readonly _handleClose: (event: CloseEvent) => void;\n private readonly _handleError: (event: Event) => void;\n\n constructor(url: string, options: WsClientOptions = {}) {\n const token = options.token;\n const authMode = options.authMode ?? 'message';\n this._authTimeout = options.authTimeout ?? DEFAULT_AUTH_TIMEOUT;\n\n // Only append token to URL when using query mode\n this._url = (token && authMode === 'query')\n ? `${url}${url.includes('?') ? '&' : '?'}token=${encodeURIComponent(token)}`\n : url;\n\n // Capture config once — closure captures for zero per-request lookups\n this._maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n this._backoffFactor = options.backoffFactor ?? DEFAULT_BACKOFF_FACTOR;\n this._backoffMax = options.backoffMax ?? DEFAULT_BACKOFF_MAX;\n this._backoffBase = options.backoffBase ?? DEFAULT_BACKOFF_BASE;\n this._heartbeatInterval = options.heartbeatInterval ?? DEFAULT_HEARTBEAT_INTERVAL;\n this._requestTimeout = options.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT;\n this._onConnect = options.onConnect;\n this._onDisconnect = options.onDisconnect;\n this._onReconnectAttempt = options.onReconnectAttempt;\n this._onData = options.onData;\n this._onFrame = options.onFrame;\n\n // Pre-encode AUTH frame if needed — zero per-reconnect allocation\n const needsAuth = !!(token && authMode === 'message');\n this._authFrame = needsAuth ? encodeAuth(token!) : null;\n\n // Bind handlers once — avoids creating new closures on every reconnect\n // Branch _onOpen at construction time to eliminate per-connect check\n this._handleOpen = needsAuth ? this._onOpenAuth.bind(this) : this._onOpenNoAuth.bind(this);\n this._handleMessage = this._onMessage.bind(this);\n this._handleClose = this._onClose.bind(this);\n this._handleError = this._onError.bind(this);\n }\n\n // ── Public API ────────────────────────────────────────────────────────────\n\n /**\n * Connect to the WebSocket server.\n * Returns a Promise that resolves when the connection is established.\n * Safe to call multiple times — subsequent calls while already OPEN are no-ops.\n */\n connect(): Promise<void> {\n if (this.state === WsClientState.OPEN) return Promise.resolve();\n return this._openConnection();\n }\n\n /**\n * Send a raw string or binary message. The connection must be OPEN.\n * For fire-and-forget use cases.\n *\n * @returns true if sent, false if not connected.\n */\n send(data: string | ArrayBuffer | Uint8Array<ArrayBuffer>): boolean {\n if (this.state !== WsClientState.OPEN || this._ws === null) return false;\n this._ws.send(data as string | ArrayBuffer);\n return true;\n }\n\n /**\n * Send a JSON message and wait for a correlated response.\n *\n * Uses the binary REQUEST frame format: [0x03][corrId:u32][JSON payload].\n * The correlation ID is carried in the binary header — NOT mixed into the\n * user payload — eliminating the previous `_kid` field collision issue.\n *\n * The server must respond with a binary RESPONSE frame echoing the same\n * corrId. When using `defineWsHandler`, this is handled automatically.\n *\n * @param data - Object to JSON-serialize and send.\n * @param timeout - Override the default `requestTimeout` for this request.\n * @returns Promise resolving with the parsed response payload.\n * @throws If the connection is not open, the request times out, or the\n * connection closes before a response arrives.\n */\n sendWait<T = unknown>(data: Record<string, unknown>, timeout?: number): Promise<T> {\n if (this.state !== WsClientState.OPEN || this._ws === null) {\n return Promise.reject(new Error('WSClient: not connected'));\n }\n\n const corrId = this._nextId();\n const payload = JSON.stringify(data);\n const frame = encodeRequest(corrId, payload);\n const ms = timeout ?? this._requestTimeout;\n\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n this._pending.delete(corrId);\n reject(new Error(`WSClient: request ${corrId} timed out after ${ms}ms`));\n }, ms);\n\n this._pending.set(corrId, {\n resolve: resolve as (v: unknown) => void,\n reject,\n timer,\n });\n\n sendBinary(this._ws!, frame);\n });\n }\n\n // ── Pub/Sub API ──────────────────────────────────────────────────────────\n\n /**\n * Subscribe to a server-side topic.\n * Sends `{\"type\":\"subscribe\",\"topic\":\"...\"}` to the server and registers a\n * local callback invoked for each `{\"type\":\"message\",\"topic\":\"...\",\"data\":...}`\n * frame received on that topic.\n *\n * Safe to call before `connect()` — the subscription is registered locally\n * and sent once the connection opens (or re-opens after reconnect).\n *\n * Calling with the same topic replaces the existing callback.\n *\n * @param topic - Topic name to subscribe to\n * @param callback - Called with the `data` field from each topic message\n */\n subscribe(topic: string, callback: (data: unknown) => void): void {\n this._subscriptions.set(topic, callback);\n if (this.state === WsClientState.OPEN && this._ws !== null) {\n sendBinary(this._ws, encodeSubscribe(topic));\n }\n }\n\n /**\n * Unsubscribe from a server-side topic.\n * Sends `{\"type\":\"unsubscribe\",\"topic\":\"...\"}` if currently connected.\n * The local callback is removed regardless of connection state.\n *\n * @param topic - Topic name to unsubscribe from\n */\n unsubscribe(topic: string): void {\n if (this._subscriptions.delete(topic)) {\n if (this.state === WsClientState.OPEN && this._ws !== null) {\n sendBinary(this._ws, encodeUnsubscribe(topic));\n }\n }\n }\n\n /**\n * Publish a message to a server-side topic.\n * Sends `{\"type\":\"publish\",\"topic\":\"...\",\"data\":...}` to the server.\n * The server (when using `defineWsHandler`) re-broadcasts the message to all\n * topic subscribers as `{\"type\":\"message\",\"topic\":\"...\",\"data\":...}`.\n *\n * @param topic - Topic to publish to\n * @param data - Payload (JSON-serializable)\n * @returns true if sent, false if not connected\n */\n publish(topic: string, data: unknown): boolean {\n if (this.state !== WsClientState.OPEN || this._ws === null) return false;\n sendBinary(this._ws, encodePublish(topic, JSON.stringify(data)));\n return true;\n }\n\n /**\n * Gracefully close the connection.\n * Does NOT reconnect. Cleans up all resources.\n */\n close(code = 1000, reason = ''): Promise<void> {\n this._destroyed = true;\n this._clearReconnectTimer();\n\n // Clean up auth state\n this._authPending = false;\n if (this._authTimer !== null) {\n clearTimeout(this._authTimer);\n this._authTimer = null;\n }\n this._authResolve = null;\n this._authReject = null;\n\n if (this._ws === null || this.state === WsClientState.CLOSED) {\n this.state = WsClientState.CLOSED;\n return Promise.resolve();\n }\n\n return new Promise<void>((resolve) => {\n const ws = this._ws!;\n const onClose = () => {\n ws.removeEventListener('close', onClose);\n resolve();\n };\n ws.addEventListener('close', onClose);\n this.state = WsClientState.CLOSING;\n ws.close(code, reason);\n });\n }\n\n // ── Private: Connection lifecycle ─────────────────────────────────────────\n\n private _openConnection(): Promise<void> {\n this._destroyed = false;\n this.state = WsClientState.CONNECTING;\n\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n\n const ws = new WebSocket(this._url);\n ws.binaryType = 'arraybuffer';\n this._ws = ws;\n\n // Attach bound handlers — avoids per-connect closure allocation\n ws.addEventListener('open', this._handleOpen);\n ws.addEventListener('message', this._handleMessage);\n ws.addEventListener('close', this._handleClose);\n ws.addEventListener('error', this._handleError);\n\n // One-shot open/error for the initial connection Promise\n const onOpenOnce = () => {\n if (settled) return;\n settled = true;\n ws.removeEventListener('open', onOpenOnce);\n ws.removeEventListener('error', onErrorOnce);\n\n // If post-connect auth is needed, defer resolution to AUTH_OK/AUTH_FAIL\n if (this._authFrame !== null) {\n this._authResolve = resolve;\n this._authReject = reject;\n return;\n }\n\n resolve();\n };\n\n const onErrorOnce = (e: Event) => {\n if (settled) return;\n settled = true;\n ws.removeEventListener('open', onOpenOnce);\n ws.removeEventListener('error', onErrorOnce);\n reject(new Error(`WSClient: connection failed — ${(e as ErrorEvent).message ?? 'unknown error'}`));\n };\n\n ws.addEventListener('open', onOpenOnce);\n ws.addEventListener('error', onErrorOnce);\n });\n }\n\n /** Open handler for auth mode — sends pre-encoded AUTH frame */\n private _onOpenAuth(): void {\n // Set state synchronously BEFORE any async continuation.\n // Bun dispatches close in the same event-loop batch if the server closes\n // immediately — state must be visible to _onClose.\n this.state = WsClientState.OPEN;\n this._retries = 0;\n this._authPending = true;\n\n // Send pre-encoded AUTH frame — zero per-reconnect encoding\n sendBinary(this._ws!, this._authFrame!);\n\n // Start auth timeout — close if no AUTH_OK within deadline\n this._authTimer = setTimeout(() => {\n this._authTimer = null;\n this._authPending = false;\n const reject = this._authReject;\n this._authResolve = null;\n this._authReject = null;\n reject?.(new Error('WSClient: auth timeout'));\n this._ws?.close(4001, 'Auth timeout');\n }, this._authTimeout);\n }\n\n /** Open handler for no-auth mode — proceeds directly to _finishOpen */\n private _onOpenNoAuth(): void {\n this.state = WsClientState.OPEN;\n this._retries = 0;\n this._finishOpen();\n }\n\n /**\n * Complete the open sequence: re-subscribe, start heartbeat, fire onConnect.\n * Called directly from _onOpen (no auth) or from _onMessage after AUTH_OK.\n */\n private _finishOpen(): void {\n // Re-subscribe to all active topics after (re)connect.\n if (this._subscriptions.size > 0) {\n for (const topic of this._subscriptions.keys()) {\n sendBinary(this._ws!, encodeSubscribe(topic));\n }\n }\n\n this._startHeartbeat();\n this._onConnect?.();\n }\n\n private _onMessage(event: MessageEvent): void {\n const raw = event.data as string | ArrayBuffer;\n\n // Invoke user hook first — minimal branching on hot path\n this._onData?.(raw);\n\n // ── Binary protocol handling ──────────────────────────────────────────\n if (raw instanceof ArrayBuffer) {\n if (raw.byteLength === 0) return;\n\n const frame = decode(raw);\n if (frame === null) return;\n\n // Invoke frame hook\n this._onFrame?.(frame);\n\n switch (frame.type) {\n // ── Auth response handling ────────────────────────────────────\n case MsgType.AUTH_OK: {\n if (!this._authPending) return;\n this._authPending = false;\n if (this._authTimer !== null) {\n clearTimeout(this._authTimer);\n this._authTimer = null;\n }\n const resolve = this._authResolve;\n this._authResolve = null;\n this._authReject = null;\n\n // Auth succeeded — complete the open sequence\n this._finishOpen();\n resolve?.();\n return;\n }\n\n case MsgType.AUTH_FAIL: {\n if (!this._authPending) return;\n this._authPending = false;\n if (this._authTimer !== null) {\n clearTimeout(this._authTimer);\n this._authTimer = null;\n }\n const reject = this._authReject;\n this._authResolve = null;\n this._authReject = null;\n\n const reason = frame.payload || 'Authentication failed';\n reject?.(new Error(`WSClient: auth failed — ${reason}`));\n // Server will close the connection\n return;\n }\n\n // ── Response correlation ───────────────────────────────────────\n case MsgType.RESPONSE: {\n const pending = this._pending.get(frame.corrId);\n if (pending !== undefined) {\n this._pending.delete(frame.corrId);\n clearTimeout(pending.timer);\n // Parse the JSON payload and resolve\n let parsed: unknown;\n try { parsed = JSON.parse(frame.payload); } catch { parsed = frame.payload; }\n pending.resolve(parsed);\n }\n return;\n }\n\n // ── Pub/sub topic message ─────────────────────────────────────\n case MsgType.MESSAGE: {\n const cb = this._subscriptions.get(frame.topic);\n if (cb !== undefined) {\n let data: unknown;\n try { data = JSON.parse(frame.payload); } catch { data = frame.payload; }\n cb(data);\n }\n return;\n }\n\n // ── Pong (heartbeat ack) — no action needed ───────────────────\n case MsgType.PONG:\n return;\n\n // Other binary frame types are not expected client-side\n default:\n return;\n }\n }\n\n // ── Text message fallback (pub/sub JSON routing) ───────────────────────\n // Pub/sub broadcasts arrive as JSON text because peer.publish() sends\n // the same data to all subscribers (binary + plain WebSocket clients).\n // Route {\"type\":\"message\",\"topic\":\"...\",\"data\":...} to subscription callbacks.\n if (typeof raw === 'string' && this._subscriptions.size > 0) {\n // Fast pre-check: skip parse if it doesn't look like a protocol message\n if (raw.charCodeAt(0) === 0x7b /* '{' */ && raw.includes('\"message\"')) {\n let msg: { type?: string; topic?: string; data?: unknown; } | null = null;\n try { msg = JSON.parse(raw) as { type?: string; topic?: string; data?: unknown; }; } catch { /* ignore */ }\n if (msg?.type === 'message' && typeof msg.topic === 'string') {\n const cb = this._subscriptions.get(msg.topic);\n cb?.(msg.data);\n }\n }\n }\n }\n\n private _onClose(event: CloseEvent): void {\n this._stopHeartbeat();\n this._detachHandlers();\n this._ws = null;\n\n // Clean up auth state\n this._authPending = false;\n if (this._authTimer !== null) {\n clearTimeout(this._authTimer);\n this._authTimer = null;\n }\n if (this._authReject) {\n const reject = this._authReject;\n this._authResolve = null;\n this._authReject = null;\n reject(new Error(`WSClient: connection closed during auth (${event.code})`));\n }\n\n const code = event.code;\n const reason = event.reason ?? '';\n\n // Reject all in-flight requests with their corrIds for debuggability\n if (this._pending.size > 0) {\n const err = new Error(`WSClient: connection closed (${code})`);\n for (const pending of this._pending.values()) {\n clearTimeout(pending.timer);\n pending.reject(err);\n }\n this._pending.clear();\n }\n\n this._onDisconnect?.(code, reason);\n\n // Do not reconnect if we deliberately closed or destroyed\n if (this._destroyed || code === 1000 || code === 1001) {\n this.state = WsClientState.CLOSED;\n return;\n }\n\n this._scheduleReconnect();\n }\n\n private _onError(_event: Event): void {\n // Errors are followed by a close event — reconnect logic lives in _onClose.\n // Nothing to do here except let the close handler kick in.\n }\n\n // ── Private: Reconnect ────────────────────────────────────────────────────\n\n private _scheduleReconnect(): void {\n if (this._retries >= this._maxRetries) {\n this.state = WsClientState.CLOSED;\n return;\n }\n\n this.state = WsClientState.RECONNECTING;\n this._retries++;\n\n const delay = this._computeBackoff(this._retries);\n this._onReconnectAttempt?.(this._retries, delay);\n\n this._reconnectTimer = setTimeout(async () => {\n this._reconnectTimer = null;\n if (this._destroyed) return;\n try {\n await this._openConnection();\n } catch {\n // _onClose will schedule the next attempt via the socket close event\n }\n }, delay);\n }\n\n /**\n * Exponential backoff with full jitter to avoid thundering-herd reconnects.\n * delay = random(0, min(backoffMax, backoffBase * backoffFactor^attempt))\n */\n private _computeBackoff(attempt: number): number {\n const cap = Math.min(this._backoffMax, this._backoffBase * Math.pow(this._backoffFactor, attempt - 1));\n // Full jitter: random value in [0, cap]\n return Math.floor(Math.random() * cap);\n }\n\n private _clearReconnectTimer(): void {\n if (this._reconnectTimer !== null) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n }\n\n // ── Private: Heartbeat ────────────────────────────────────────────────────\n\n private _startHeartbeat(): void {\n if (this._heartbeatInterval <= 0) return;\n this._stopHeartbeat();\n this._heartbeatTimer = setInterval(() => {\n if (this.state === WsClientState.OPEN && this._ws !== null) {\n sendBinary(this._ws, PING_FRAME);\n }\n }, this._heartbeatInterval);\n }\n\n private _stopHeartbeat(): void {\n if (this._heartbeatTimer !== null) {\n clearInterval(this._heartbeatTimer);\n this._heartbeatTimer = null;\n }\n }\n\n // ── Private: Handler cleanup ──────────────────────────────────────────────\n\n private _detachHandlers(): void {\n if (this._ws === null) return;\n this._ws.removeEventListener('open', this._handleOpen);\n this._ws.removeEventListener('message', this._handleMessage);\n this._ws.removeEventListener('close', this._handleClose);\n this._ws.removeEventListener('error', this._handleError);\n }\n\n // ── Private: Utilities ────────────────────────────────────────────────────\n\n /**\n * Returns a monotonically increasing uint32 correlation ID.\n * Wraps at 0xFFFFFFFF back to 1 (zero is reserved).\n * No random component needed — IDs are scoped to a single connection\n * and the uint32 space (4B values) far exceeds concurrent in-flight requests.\n */\n private _nextId(): number {\n this._idCounter = (this._idCounter + 1) & 0xffffffff;\n if (this._idCounter === 0) this._idCounter = 1;\n return this._idCounter;\n }\n}\n"],"mappings":"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","names":["server","cache","etag","body","jwk","encoder","decoder","compress","data","timeout"]}
|