@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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/node.ts","../src/context/node.ts","../src/ws/node.ts"],"sourcesContent":["/**\n * Ken Framework - Node.js Runtime\n * Uses Node.js native HTTP APIs without Web conversion\n * \n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport { createServer, type Server, type IncomingMessage, type ServerResponse } from 'http';\nimport { Router } from '../core/router';\nimport { NodeContext } from '../context/node';\nimport { type Schema, type GetRemoteInfo } from '../context/types';\nimport { createExecutor, createNotFoundExecutor, type ContextFactory } from './compiler';\nimport { toResponse } from '../utils/response';\nimport { type WsRoute } from '../ws/types';\nimport { createNodeWsHandler } from '../ws/node';\n\n/**\n * Send Web Response to Node.js ServerResponse\n * Optimized for streaming and buffered responses\n */\nasync function sendResponse(nodeRes: ServerResponse, response: Response): Promise<void> {\n // Write status\n nodeRes.statusCode = response.status;\n\n // Write headers (optimized iteration)\n // Special handling for Set-Cookie headers (can have multiple values)\n const setCookies = response.headers.getSetCookie();\n if (setCookies.length > 0) {\n nodeRes.setHeader('Set-Cookie', setCookies);\n }\n\n // Write all other headers\n response.headers.forEach((value, key) => {\n if (key.toLowerCase() !== 'set-cookie') {\n nodeRes.setHeader(key, value);\n }\n });\n\n const body = response.body;\n\n if (!body) {\n nodeRes.end();\n return;\n }\n\n // Stream the body\n const reader = body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n // Write chunk with backpressure handling\n if (!nodeRes.write(value)) {\n await new Promise<void>(resolve => nodeRes.once('drain', resolve));\n }\n }\n } finally {\n reader.releaseLock();\n nodeRes.end();\n }\n}\n\n/**\n * Extract pathname from URL (fast path for Node.js)\n */\nfunction getPathnameFromUrl(url: string | undefined): string {\n if (!url) return '/';\n const idx = url.indexOf('?');\n return idx === -1 ? url : url.slice(0, idx);\n}\n\n/**\n * NodeContext factory for Node.js runtime\n */\nconst nodeContextFactory: ContextFactory<IncomingMessage, NodeContext> = (\n req: IncomingMessage,\n params: Record<string, string>,\n getRemoteInfo: GetRemoteInfo,\n schema?: Schema,\n url?: string\n) => new NodeContext(req, url || req.url || '/', params, getRemoteInfo, schema);\n\nexport function server({ port, hostname, router }: {\n port?: number;\n hostname?: string;\n router: Router;\n}) {\n let httpServer: Server | undefined = undefined;\n\n // Compile routes with Node executors\n const compiledRouter = new Router();\n\n for (const route of router.routes) {\n // Get merged schema\n let mergedSchema = route.schema;\n if (typeof (router as any).matchMiddleware === 'function' && typeof (router as any).mergeSchemas === 'function') {\n const matchedMiddleware = (router as any).matchMiddleware(route.path);\n mergedSchema = (router as any).mergeSchemas(matchedMiddleware, route.schema);\n }\n\n if (route.handler) {\n // Create executor using compiler\n const executor = createExecutor(nodeContextFactory, route.handler, mergedSchema);\n\n // Wrap executor to handle request/response conversion\n const nodeHandler = async (req: IncomingMessage, res: ServerResponse, params: Record<string, string>, getRemoteInfo: GetRemoteInfo) => {\n const url = req.url || '/';\n try {\n const result = await executor(req, params, getRemoteInfo, url);\n const response = toResponse(result);\n await sendResponse(res, response);\n } catch (error) {\n const errResponse = error instanceof Response\n ? error\n : new Response(error instanceof Error ? error.message : String(error), { status: 500 });\n await sendResponse(res, errResponse);\n }\n };\n\n compiledRouter.registerCompiled(route.method, route.path, nodeHandler as any, mergedSchema);\n } else if (route.staticValue !== undefined) {\n // Static value - cache response with pre-extracted body\n const cachedResponse = toResponse(route.staticValue);\n const statusCode = cachedResponse.status;\n\n // Pre-extract body and encode to Buffer (avoids per-request string→bytes conversion)\n cachedResponse.text().then(body => {\n const bodyBuffer = Buffer.from(body);\n\n // Pre-build headers with content-length for optimal Node.js response\n const headersObj: Record<string, string> = {};\n cachedResponse.headers.forEach((v, k) => { headersObj[k] = v; });\n headersObj['content-length'] = String(bodyBuffer.length);\n\n // Sync executor: writeHead() + pre-encoded Buffer = fastest Node response path\n const staticExecutor = (_req: IncomingMessage, res: ServerResponse) => {\n res.writeHead(statusCode, headersObj);\n res.end(bodyBuffer);\n };\n\n compiledRouter.registerCompiled(route.method, route.path, staticExecutor as any, mergedSchema, cachedResponse);\n });\n }\n }\n\n // Hoist matcher\n const match = compiledRouter.matcher();\n\n // Pre-compile 404 handler with global middleware\n const notFoundExecutor = createNotFoundExecutor(router, nodeContextFactory);\n const NOT_FOUND_BODY = 'Not Found';\n\n // WebSocket routes\n const wsRoutes: WsRoute<any>[] = (router as any).wsRoutes || [];\n const wsHandlers = new Map<string, ReturnType<typeof createNodeWsHandler>>();\n for (const wsRoute of wsRoutes) {\n wsHandlers.set(wsRoute.path, createNodeWsHandler(wsRoute.handler, wsRoute.options));\n }\n\n return {\n async run(): Promise<{ hostname: string; port: number; }> {\n httpServer?.close();\n\n return new Promise((resolve, reject) => {\n httpServer = createServer((req, res) => {\n const pathname = getPathnameFromUrl(req.url);\n const method = req.method || 'GET';\n const matchResult = match(method, pathname);\n\n if (matchResult !== undefined) {\n // Fast path: static route (sync, no getRemoteInfo needed)\n if (matchResult.response !== undefined) {\n matchResult.handler(req, res);\n return;\n }\n\n // Dynamic route\n const getRemoteInfo: GetRemoteInfo = () => ({\n address: req.socket.remoteAddress || '0.0.0.0',\n port: req.socket.remotePort || 0,\n });\n\n const result = matchResult.handler(req, res, matchResult.params, getRemoteInfo);\n\n // Handle async handler results without blocking\n if (result && typeof result.then === 'function') {\n result.catch((error: any) => {\n if (!res.headersSent) {\n res.statusCode = 500;\n res.end(error instanceof Error ? error.message : String(error));\n }\n });\n }\n return;\n }\n\n // Execute 404 with middleware if available\n if (notFoundExecutor) {\n const getRemoteInfo: GetRemoteInfo = () => ({\n address: req.socket.remoteAddress || '0.0.0.0',\n port: req.socket.remotePort || 0,\n });\n const url = req.url || '/';\n const result = notFoundExecutor(req, getRemoteInfo, pathname, url);\n if (result && typeof result.then === 'function') {\n result.then(async (resp: any) => {\n const response = toResponse(resp);\n await sendResponse(res, response);\n }).catch((error: any) => {\n if (!res.headersSent) {\n res.statusCode = 500;\n res.end(error instanceof Error ? error.message : String(error));\n }\n });\n } else {\n const response = toResponse(result);\n sendResponse(res, response).catch((error: any) => {\n if (!res.headersSent) {\n res.statusCode = 500;\n res.end(error instanceof Error ? error.message : String(error));\n }\n });\n }\n return;\n }\n\n // 404 Not Found\n res.statusCode = 404;\n res.end(NOT_FOUND_BODY);\n });\n\n httpServer.on('error', reject);\n\n // Register WebSocket upgrade handler\n if (wsHandlers.size > 0) {\n httpServer.on('upgrade', (req, socket, head) => {\n const pathname = getPathnameFromUrl(req.url);\n const wsHandler = wsHandlers.get(pathname);\n\n if (wsHandler) {\n wsHandler.handleUpgrade(req, socket as any, head as any);\n } else {\n socket.write('HTTP/1.1 404 Not Found\\r\\n\\r\\n');\n socket.destroy();\n }\n });\n\n // Start heartbeat for all WS handlers\n for (const wsHandler of wsHandlers.values()) {\n wsHandler.startHeartbeat();\n }\n }\n\n httpServer.listen(port || 3000, hostname || '0.0.0.0', () => {\n const addr = httpServer?.address();\n if (addr && typeof addr !== 'string') {\n resolve({ hostname: addr.address, port: addr.port });\n } else {\n resolve({ hostname: hostname || '0.0.0.0', port: port || 3000 });\n }\n });\n });\n },\n\n stop() {\n // Stop heartbeat for all WS handlers\n for (const wsHandler of wsHandlers.values()) {\n wsHandler.stopHeartbeat();\n }\n\n return new Promise<void>((resolve, reject) => {\n if (httpServer) {\n httpServer.close((err) => {\n if (err) reject(err);\n else resolve();\n });\n httpServer = undefined;\n } else {\n resolve();\n }\n });\n }\n };\n}\n\n// console.log('Node.js runtime module loaded.');","/**\n * Ken Framework - Node.js Context\n * Uses IncomingMessage directly without Web Standard conversion\n * \n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport type { IncomingMessage } from 'node:http';\nimport { BaseContext, type HeadersLike } from './base';\nimport {\n type Schema,\n type GetRemoteInfo,\n type InferObject,\n type InferValidator,\n EMPTY_PARAMS,\n} from './types';\n\n/**\n * NodeContext - For Node.js http module\n * Uses IncomingMessage directly - no Web Request conversion overhead\n * \n * @template S - Schema type for validation\n * @template Path - Route path string for param extraction\n * @template TState - Accumulated state from middleware\n */\nexport class NodeContext<S extends Schema = {}, Path extends string = string, TState = {}>\n extends BaseContext<S, Path, TState> {\n\n public readonly req: IncomingMessage;\n private readonly _url: string;\n private _bodyBuffer: Buffer | null = null;\n\n constructor(\n req: IncomingMessage,\n url: string,\n params: Record<string, string> = EMPTY_PARAMS,\n getRemoteInfo: GetRemoteInfo,\n schema?: S\n ) {\n super(params, getRemoteInfo, schema);\n this.req = req;\n this._url = url;\n }\n\n get url(): string {\n return this._url;\n }\n\n get method(): string {\n return this.req.method || 'GET';\n }\n\n get body(): IncomingMessage {\n return this.req;\n }\n\n protected _getRawHeaders(): HeadersLike {\n return this.req.headers as HeadersLike;\n }\n\n protected _getRawUrl(): string {\n return this._url;\n }\n\n /**\n * Lazily parses and validates headers.\n */\n get headers(): InferObject<S['headers'], Record<string, string>> {\n let cached = this._headers;\n if (cached !== null) return cached;\n\n const schema = this._schema?.headers;\n const nodeHeaders = this.req.headers;\n\n if (schema !== undefined) {\n const result: any = {};\n for (const key in schema) {\n const validator = schema[key];\n const value = nodeHeaders[key.toLowerCase()];\n result[key] = validator(Array.isArray(value) ? value[0] : (value || ''));\n }\n this._headers = result;\n return result;\n }\n\n const h: Record<string, string> = {};\n for (const key in nodeHeaders) {\n const value = nodeHeaders[key];\n h[key] = Array.isArray(value) ? value[0] : (value || '');\n }\n this._headers = h;\n return h as any;\n }\n\n /**\n * Read body buffer from IncomingMessage stream\n */\n private async _readBody(): Promise<Buffer> {\n if (this._bodyBuffer !== null) return this._bodyBuffer;\n\n return new Promise<Buffer>((resolve, reject) => {\n const chunks: Buffer[] = [];\n this.req.on('data', (chunk: Buffer) => chunks.push(chunk));\n this.req.on('end', () => {\n this._bodyBuffer = Buffer.concat(chunks);\n resolve(this._bodyBuffer);\n });\n this.req.on('error', reject);\n });\n }\n\n /**\n * Lazily parses and validates JSON body.\n */\n get json(): Promise<InferValidator<S['json'], any>> {\n if (this._json) return this._json;\n\n const validator = this._schema?.json;\n if (validator) {\n this._json = (async () => {\n const buffer = await this._readBody();\n const data = JSON.parse(buffer.toString('utf8'));\n try {\n return validator(data);\n } catch (err: any) {\n throw new Error(`JSON Body validation failed: ${err.message}`);\n }\n })();\n } else {\n this._json = (async () => {\n try {\n const buffer = await this._readBody();\n return JSON.parse(buffer.toString('utf8'));\n } catch {\n return null;\n }\n })();\n }\n return this._json;\n }\n\n /**\n * Lazily parses and validates text body.\n */\n get text(): Promise<InferValidator<S['text'], string>> {\n if (this._text) return this._text;\n\n const validator = this._schema?.text;\n if (validator) {\n this._text = (async () => {\n const buffer = await this._readBody();\n const data = buffer.toString('utf8');\n try {\n return validator(data);\n } catch (err: any) {\n throw new Error(`Text Body validation failed: ${err.message}`);\n }\n })();\n } else {\n this._text = (async () => {\n const buffer = await this._readBody();\n return buffer.toString('utf8');\n })();\n }\n return this._text;\n }\n\n /**\n * Lazily parses and validates form body.\n * Supports both application/x-www-form-urlencoded and multipart/form-data\n */\n get form(): Promise<InferObject<S['form'], FormData>> {\n if (this._form) return this._form;\n\n const schema = this._schema?.form;\n this._form = (async () => {\n const buffer = await this._readBody();\n const contentType = this.req.headers['content-type'] || '';\n\n // Check if multipart/form-data\n if (contentType.startsWith('multipart/form-data')) {\n // Use Web Request API for multipart parsing\n // Convert IncomingMessage to Request\n const protocol = (this.req.socket as any).encrypted ? 'https:' : 'http:';\n const host = this.req.headers.host || 'localhost';\n const fullUrl = `${protocol}//${host}${this._url}`;\n\n const headers = new Headers();\n for (const key in this.req.headers) {\n const value = this.req.headers[key];\n if (value) {\n headers.set(key, Array.isArray(value) ? value[0] : value);\n }\n }\n\n const request = new Request(fullUrl, {\n method: this.method,\n headers,\n body: new Uint8Array(buffer),\n // @ts-ignore - duplex is needed for streaming\n duplex: 'half'\n });\n\n const formData = await request.formData();\n\n if (schema) {\n const result: any = {};\n for (const key in schema) {\n try {\n result[key] = schema[key](formData.get(key));\n } catch (err: any) {\n throw new Error(`Form Body validation failed for \"${key}\": ${err.message}`);\n }\n }\n return result;\n }\n\n return formData as any;\n }\n\n // URL-encoded form data\n const text = buffer.toString('utf8');\n const formData = new Map<string, string>();\n const pairs = text.split('&');\n for (const pair of pairs) {\n const [key, value] = pair.split('=');\n if (key) {\n formData.set(\n decodeURIComponent(key),\n value ? decodeURIComponent(value.replace(/\\+/g, ' ')) : ''\n );\n }\n }\n\n if (schema) {\n const result: any = {};\n for (const key in schema) {\n try {\n result[key] = schema[key](formData.get(key) ?? null);\n } catch (err: any) {\n throw new Error(`Form Body validation failed for \"${key}\": ${err.message}`);\n }\n }\n return result;\n }\n\n // Return as pseudo-FormData object\n return formData as any;\n })();\n\n return this._form;\n }\n}\n","/**\n * Ken Framework - Node.js Native WebSocket Server\n * RFC 6455 compliant WebSocket implementation using only Node.js built-in modules.\n * No third-party dependencies.\n * \n * Features:\n * - Full RFC 6455 frame parsing and serialization\n * - Server-initiated ping/pong heartbeat\n * - Pub/Sub via PubSubHub\n * - Backpressure handling\n * - Per-message deflate (optional)\n * \n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport { createHash } from 'crypto';\nimport type { IncomingMessage } from 'http';\nimport type { Socket } from 'net';\nimport {\n type WsPeer,\n type WsHandler,\n type WsOptions,\n type WsMessageData,\n type WsReadyStateValue,\n WsReadyState,\n WS_DEFAULTS,\n} from './types';\nimport { PubSubHub, type PubSubPeer } from './pubsub';\n\n// ==================== Constants ====================\n\n/** WebSocket GUID for handshake */\nconst WS_GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';\n\n/** WebSocket opcodes */\nconst OPCODE_CONTINUATION = 0x0;\nconst OPCODE_TEXT = 0x1;\nconst OPCODE_BINARY = 0x2;\nconst OPCODE_CLOSE = 0x8;\nconst OPCODE_PING = 0x9;\nconst OPCODE_PONG = 0xA;\n\n/** Frame header constants */\nconst FIN_BIT = 0x80;\nconst MASK_BIT = 0x80;\nconst OPCODE_MASK = 0x0F;\nconst LENGTH_MASK = 0x7F;\n\n// ==================== Frame Utilities ====================\n\n/**\n * Unmask a WebSocket frame payload in-place.\n * Client frames are always masked per RFC 6455.\n */\nfunction unmaskPayload(payload: Buffer, mask: Buffer): void {\n const len = payload.length;\n // Unroll for common small payloads\n for (let i = 0; i < len; i++) {\n payload[i] ^= mask[i & 3];\n }\n}\n\n/**\n * Create a WebSocket frame buffer.\n * Server-to-client frames are NOT masked per RFC 6455.\n */\nfunction createFrame(opcode: number, payload: Buffer | Uint8Array, fin: boolean = true): Buffer {\n const payloadLen = payload.length;\n let headerLen: number;\n let extendedOffset: number;\n\n if (payloadLen < 126) {\n headerLen = 2;\n extendedOffset = -1;\n } else if (payloadLen < 65536) {\n headerLen = 4;\n extendedOffset = 2;\n } else {\n headerLen = 10;\n extendedOffset = 2;\n }\n\n const frame = Buffer.allocUnsafe(headerLen + payloadLen);\n\n // First byte: FIN + opcode\n frame[0] = (fin ? FIN_BIT : 0) | opcode;\n\n // Second byte: payload length (no mask for server frames)\n if (payloadLen < 126) {\n frame[1] = payloadLen;\n } else if (payloadLen < 65536) {\n frame[1] = 126;\n frame.writeUInt16BE(payloadLen, extendedOffset);\n } else {\n frame[1] = 127;\n // Write 64-bit length (high 32 bits first, then low 32 bits)\n frame.writeUInt32BE(0, extendedOffset);\n frame.writeUInt32BE(payloadLen, extendedOffset + 4);\n }\n\n // Copy payload\n if (payloadLen > 0) {\n if (Buffer.isBuffer(payload)) {\n payload.copy(frame, headerLen);\n } else {\n frame.set(payload, headerLen);\n }\n }\n\n return frame;\n}\n\n/**\n * Encode string or ArrayBuffer to Buffer.\n */\nfunction toBuffer(data: WsMessageData): Buffer {\n if (Buffer.isBuffer(data)) return data;\n if (typeof data === 'string') return Buffer.from(data);\n if (data instanceof ArrayBuffer) return Buffer.from(data);\n if (data instanceof Uint8Array) return Buffer.from(data.buffer, data.byteOffset, data.byteLength);\n return Buffer.from(String(data));\n}\n\n// ==================== NodeWsPeer ====================\n\n/**\n * Node.js WebSocket peer implementation.\n * Manages a single WebSocket connection over a raw TCP socket.\n */\nclass NodeWsPeer<T> implements WsPeer<T>, PubSubPeer {\n public data: T;\n public readyState: WsReadyStateValue = WsReadyState.OPEN;\n public remoteAddress: string;\n\n private socket: Socket;\n private hub: PubSubHub;\n private handler: WsHandler<T>;\n private opts: Required<WsOptions>;\n\n // Frame parsing state\n private frameBuffer: Buffer | null = null;\n private fragments: Buffer[] = [];\n private fragmentOpcode: number = 0;\n\n // Ping/pong tracking\n private lastPongReceived: number = Date.now();\n\n constructor(\n socket: Socket,\n data: T,\n hub: PubSubHub,\n handler: WsHandler<T>,\n opts: Required<WsOptions>,\n ) {\n this.socket = socket;\n this.data = data;\n this.hub = hub;\n this.handler = handler;\n this.opts = opts;\n this.remoteAddress = socket.remoteAddress || '0.0.0.0';\n\n this.setupSocket();\n }\n\n private setupSocket(): void {\n const socket = this.socket;\n\n socket.on('data', (chunk: Buffer) => {\n this.onData(chunk);\n });\n\n socket.on('close', () => {\n if (this.readyState !== WsReadyState.CLOSED) {\n this.readyState = WsReadyState.CLOSED;\n this.hub.removeAll(this);\n try {\n this.handler.close?.(this, 1006, 'Connection closed abnormally');\n } catch { /* ignore */ }\n }\n });\n\n socket.on('error', (err: Error) => {\n try {\n this.handler.error?.(this, err);\n } catch { /* ignore */ }\n });\n\n // Fire open event\n try {\n this.handler.open?.(this);\n } catch { /* ignore */ }\n }\n\n private onData(chunk: Buffer): void {\n // Append to existing buffer or use chunk directly\n let buffer: Buffer;\n if (this.frameBuffer) {\n buffer = Buffer.concat([this.frameBuffer, chunk]);\n this.frameBuffer = null;\n } else {\n buffer = chunk;\n }\n\n let offset = 0;\n\n while (offset < buffer.length) {\n // Need at least 2 bytes for the header\n if (buffer.length - offset < 2) {\n this.frameBuffer = buffer.subarray(offset);\n return;\n }\n\n const firstByte = buffer[offset];\n const secondByte = buffer[offset + 1];\n\n const isFin = (firstByte & FIN_BIT) !== 0;\n const opcode = firstByte & OPCODE_MASK;\n const isMasked = (secondByte & MASK_BIT) !== 0;\n let payloadLen = secondByte & LENGTH_MASK;\n\n let headerSize = 2;\n if (payloadLen === 126) headerSize += 2;\n else if (payloadLen === 127) headerSize += 8;\n if (isMasked) headerSize += 4;\n\n if (buffer.length - offset < headerSize) {\n this.frameBuffer = buffer.subarray(offset);\n return;\n }\n\n let extOffset = offset + 2;\n if (payloadLen === 126) {\n payloadLen = buffer.readUInt16BE(extOffset);\n extOffset += 2;\n } else if (payloadLen === 127) {\n // Read 64-bit length (skip high 32 bits, they should be 0 for sane payloads)\n const high = buffer.readUInt32BE(extOffset);\n if (high > 0) {\n this.closeInternal(1009, 'Message too large');\n return;\n }\n payloadLen = buffer.readUInt32BE(extOffset + 4);\n extOffset += 8;\n }\n\n // Check max payload\n if (payloadLen > this.opts.maxPayloadLength) {\n this.closeInternal(1009, 'Message too large');\n return;\n }\n\n let mask: Buffer | null = null;\n if (isMasked) {\n mask = buffer.subarray(extOffset, extOffset + 4);\n extOffset += 4;\n }\n\n const totalFrameSize = extOffset - offset + payloadLen;\n if (buffer.length - offset < totalFrameSize) {\n this.frameBuffer = buffer.subarray(offset);\n return;\n }\n\n // Extract payload\n const payload = Buffer.from(buffer.subarray(extOffset, extOffset + payloadLen));\n if (mask) {\n unmaskPayload(payload, mask);\n }\n\n offset += totalFrameSize;\n\n // Process frame\n this.processFrame(opcode, payload, isFin);\n }\n }\n\n private processFrame(opcode: number, payload: Buffer, isFin: boolean): void {\n // Control frames (opcode >= 0x8)\n if (opcode >= 0x8) {\n switch (opcode) {\n case OPCODE_CLOSE:\n this.handleClose(payload);\n break;\n case OPCODE_PING:\n this.handlePing(payload);\n break;\n case OPCODE_PONG:\n this.handlePong(payload);\n break;\n }\n return;\n }\n\n // Data frames\n if (opcode === OPCODE_CONTINUATION) {\n this.fragments.push(payload);\n if (isFin) {\n const fullPayload = Buffer.concat(this.fragments);\n this.fragments = [];\n this.dispatchMessage(this.fragmentOpcode, fullPayload);\n }\n } else {\n // New message\n if (isFin) {\n this.dispatchMessage(opcode, payload);\n } else {\n this.fragmentOpcode = opcode;\n this.fragments = [payload];\n }\n }\n }\n\n private dispatchMessage(opcode: number, payload: Buffer): void {\n try {\n const message: WsMessageData = opcode === OPCODE_TEXT\n ? payload.toString('utf8')\n : payload;\n this.handler.message(this, message);\n } catch { /* ignore user handler errors */ }\n }\n\n private handleClose(payload: Buffer): void {\n let code = 1000;\n let reason = '';\n\n if (payload.length >= 2) {\n code = payload.readUInt16BE(0);\n if (payload.length > 2) {\n reason = payload.subarray(2).toString('utf8');\n }\n }\n\n // Send close frame back\n if (this.readyState === WsReadyState.OPEN) {\n this.readyState = WsReadyState.CLOSING;\n const closePayload = Buffer.allocUnsafe(2);\n closePayload.writeUInt16BE(code, 0);\n this.sendFrame(OPCODE_CLOSE, closePayload);\n }\n\n this.readyState = WsReadyState.CLOSED;\n this.hub.removeAll(this);\n\n try {\n this.handler.close?.(this, code, reason);\n } catch { /* ignore */ }\n\n this.socket.end();\n }\n\n private handlePing(payload: Buffer): void {\n // Auto-respond with pong\n this.sendFrame(OPCODE_PONG, payload);\n try {\n this.handler.ping?.(this, payload);\n } catch { /* ignore */ }\n }\n\n private handlePong(payload: Buffer): void {\n this.lastPongReceived = Date.now();\n // Update hub liveness — drives hub.pruneDeadPeers() / hub.isPeerAlive()\n this.hub.markAlive(this);\n try {\n this.handler.pong?.(this, payload);\n } catch { /* ignore */ }\n }\n\n // ==================== Public API ====================\n\n send(data: WsMessageData, _compress?: boolean): number {\n if (this.readyState !== WsReadyState.OPEN) return -1;\n\n const buf = toBuffer(data);\n const opcode = typeof data === 'string' ? OPCODE_TEXT : OPCODE_BINARY;\n return this.sendFrame(opcode, buf);\n }\n\n close(code: number = 1000, reason?: string): void {\n if (this.readyState !== WsReadyState.OPEN) return;\n\n this.readyState = WsReadyState.CLOSING;\n const reasonBuf = reason ? Buffer.from(reason) : Buffer.alloc(0);\n const payload = Buffer.allocUnsafe(2 + reasonBuf.length);\n payload.writeUInt16BE(code, 0);\n if (reasonBuf.length > 0) reasonBuf.copy(payload, 2);\n\n this.sendFrame(OPCODE_CLOSE, payload);\n this.hub.removeAll(this);\n\n try {\n this.handler.close?.(this, code, reason || '');\n } catch { /* ignore */ }\n\n // Give time for the close frame to be sent before destroying\n setTimeout(() => {\n if (this.readyState !== WsReadyState.CLOSED) {\n this.readyState = WsReadyState.CLOSED;\n this.socket.end();\n }\n }, 1000);\n }\n\n subscribe(topic: string): void {\n this.hub.subscribe(this, topic);\n }\n\n unsubscribe(topic: string): void {\n this.hub.unsubscribe(this, topic);\n }\n\n publish(topic: string, data: WsMessageData, compress?: boolean): void {\n this.hub.publish(this, topic, data, compress);\n }\n\n isSubscribed(topic: string): boolean {\n return this.hub.isSubscribed(this, topic);\n }\n\n ping(data?: WsMessageData): void {\n if (this.readyState !== WsReadyState.OPEN) return;\n const buf = data ? toBuffer(data) : Buffer.alloc(0);\n this.sendFrame(OPCODE_PING, buf);\n }\n\n pong(data?: WsMessageData): void {\n if (this.readyState !== WsReadyState.OPEN) return;\n const buf = data ? toBuffer(data) : Buffer.alloc(0);\n this.sendFrame(OPCODE_PONG, buf);\n }\n\n /** Check if pong was received within timeout */\n isAlive(pongTimeout: number): boolean {\n return (Date.now() - this.lastPongReceived) < (pongTimeout * 1000);\n }\n\n // ==================== Internal ====================\n\n private sendFrame(opcode: number, payload: Buffer): number {\n if (this.socket.destroyed) return -1;\n const frame = createFrame(opcode, payload);\n this.socket.write(frame);\n return frame.length;\n }\n\n private closeInternal(code: number, reason: string): void {\n if (this.readyState === WsReadyState.OPEN) {\n this.close(code, reason);\n }\n }\n\n /** Force-destroy the underlying socket */\n destroy(): void {\n this.readyState = WsReadyState.CLOSED;\n this.hub.removeAll(this);\n this.socket.destroy();\n }\n}\n\n// ==================== WebSocket Upgrade Handler ====================\n\n/**\n * Perform the WebSocket upgrade handshake.\n * Returns the accept key for the Sec-WebSocket-Accept header.\n */\nfunction computeAcceptKey(key: string): string {\n return createHash('sha1').update(key + WS_GUID).digest('base64');\n}\n\n/**\n * Create an upgrade handler for a Node.js HTTP server.\n * Called by the Node.js runtime adapter.\n */\nexport function createNodeWsHandler<T>(\n handler: WsHandler<T>,\n options: WsOptions = {},\n): {\n hub: PubSubHub;\n peers: Set<NodeWsPeer<T>>;\n handleUpgrade: (req: IncomingMessage, socket: Socket, head: Buffer) => Promise<void>;\n startHeartbeat: () => void;\n stopHeartbeat: () => void;\n} {\n const opts: Required<WsOptions> = { ...WS_DEFAULTS, ...options };\n const hub = new PubSubHub();\n const peers = new Set<NodeWsPeer<T>>();\n\n let heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n\n async function handleUpgrade(req: IncomingMessage, socket: Socket, head: Buffer): Promise<void> {\n // Validate WebSocket upgrade headers\n const key = req.headers['sec-websocket-key'];\n const version = req.headers['sec-websocket-version'];\n\n if (!key || version !== '13') {\n socket.write('HTTP/1.1 400 Bad Request\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n\n // Run upgrade handler if provided\n let data: T = undefined as T;\n if (handler.upgrade) {\n try {\n // Build a Request object from IncomingMessage for the upgrade handler\n const url = `http://${req.headers.host || 'localhost'}${req.url || '/'}`;\n const headers = new Headers();\n for (const [k, v] of Object.entries(req.headers)) {\n if (v) headers.set(k, Array.isArray(v) ? v.join(', ') : v);\n }\n const request = new Request(url, {\n method: req.method || 'GET',\n headers,\n });\n\n const result = await handler.upgrade(request);\n\n // If Response returned, reject the upgrade\n if (result instanceof Response) {\n const status = result.status;\n const body = await result.text();\n socket.write(`HTTP/1.1 ${status} ${result.statusText || 'Error'}\\r\\n`);\n result.headers.forEach((v, k) => {\n socket.write(`${k}: ${v}\\r\\n`);\n });\n socket.write(`Content-Length: ${Buffer.byteLength(body)}\\r\\n`);\n socket.write('\\r\\n');\n socket.write(body);\n socket.destroy();\n return;\n }\n\n data = result;\n } catch (err) {\n socket.write('HTTP/1.1 500 Internal Server Error\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n }\n\n // Compute accept key and send upgrade response\n const acceptKey = computeAcceptKey(key);\n const upgradeResponse =\n 'HTTP/1.1 101 Switching Protocols\\r\\n' +\n 'Upgrade: websocket\\r\\n' +\n 'Connection: Upgrade\\r\\n' +\n `Sec-WebSocket-Accept: ${acceptKey}\\r\\n` +\n '\\r\\n';\n\n socket.write(upgradeResponse);\n\n // Create peer\n const peer = new NodeWsPeer<T>(socket, data, hub, handler, opts);\n peers.add(peer);\n\n // Handle socket close -> cleanup\n socket.on('close', () => {\n peers.delete(peer);\n });\n\n // If there's remaining data from the initial HTTP request, feed it\n if (head && head.length > 0) {\n (peer as any).onData(head);\n }\n }\n\n function startHeartbeat(): void {\n if (opts.pingInterval <= 0) return;\n if (heartbeatInterval) return;\n\n heartbeatInterval = setInterval(() => {\n for (const peer of peers) {\n if (peer.readyState !== WsReadyState.OPEN) continue;\n\n // Check if pong timed out\n if (opts.pongTimeout > 0 && !peer.isAlive(opts.pingInterval + opts.pongTimeout)) {\n peer.destroy();\n peers.delete(peer);\n continue;\n }\n\n // Send ping\n peer.ping();\n }\n }, opts.pingInterval * 1000);\n\n // Don't block process exit\n if (heartbeatInterval && typeof heartbeatInterval === 'object' && 'unref' in heartbeatInterval) {\n (heartbeatInterval as any).unref();\n }\n }\n\n function stopHeartbeat(): void {\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = null;\n }\n }\n\n return { hub, peers, handleUpgrade, startHeartbeat, stopHeartbeat };\n}\n"],"mappings":"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","names":["formData"]}
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "@coderbuzz/ken",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./index.js",
6
+ "types": "./index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./index.d.ts",
10
+ "import": "./index.js"
11
+ }
12
+ }
13
+ }