@coderbuzz/ken 0.1.5 → 0.2.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 +683 -56
- package/dist/README.md +683 -56
- package/dist/{deno-LZU5JBGL.js → deno-DV3633IH.js} +8 -2
- package/dist/deno-DV3633IH.js.map +1 -0
- package/dist/index.d.ts +15 -17
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/package.json +1 -1
- package/dist/deno-LZU5JBGL.js.map +0 -1
|
@@ -75,6 +75,12 @@ function createDenoWsHandler(handler, options = {}) {
|
|
|
75
75
|
const peers = /* @__PURE__ */ new Set();
|
|
76
76
|
let heartbeatInterval = null;
|
|
77
77
|
async function handleUpgrade(req, info) {
|
|
78
|
+
let clientHostname;
|
|
79
|
+
try {
|
|
80
|
+
clientHostname = info.remoteAddr.hostname;
|
|
81
|
+
} catch {
|
|
82
|
+
clientHostname = "unknown";
|
|
83
|
+
}
|
|
78
84
|
let data = void 0;
|
|
79
85
|
if (handler.upgrade) {
|
|
80
86
|
try {
|
|
@@ -88,7 +94,7 @@ function createDenoWsHandler(handler, options = {}) {
|
|
|
88
94
|
}
|
|
89
95
|
}
|
|
90
96
|
const { socket, response } = Deno.upgradeWebSocket(req);
|
|
91
|
-
const peer = new DenoWsPeer(socket, data, hub,
|
|
97
|
+
const peer = new DenoWsPeer(socket, data, hub, clientHostname);
|
|
92
98
|
peers.add(peer);
|
|
93
99
|
socket.onopen = () => {
|
|
94
100
|
try {
|
|
@@ -247,4 +253,4 @@ function server({ port, hostname, router }) {
|
|
|
247
253
|
export {
|
|
248
254
|
server
|
|
249
255
|
};
|
|
250
|
-
//# sourceMappingURL=deno-
|
|
256
|
+
//# sourceMappingURL=deno-DV3633IH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ws/deno.ts","../src/runtime/deno.ts"],"sourcesContent":["/**\n * Ken Framework - Deno WebSocket Adapter\n * Uses Deno's native WebSocket upgrade support\n * \n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport {\n type WsPeer,\n type WsHandler,\n type WsOptions,\n type WsMessageData,\n type WsReadyStateValue,\n WsReadyState,\n WS_DEFAULTS,\n} from './types';\n\ndeclare const Deno: any;\nimport { PubSubHub, type PubSubPeer } from './pubsub';\n\n// ==================== DenoWsPeer ====================\n\n/** Pre-allocated app-level ping payload — reused across all heartbeat calls */\nconst DENO_PING_MSG = '{\"type\":\"ping\"}';\n\n/**\n * Deno WebSocket peer.\n * Wraps a standard WebSocket instance with Ken's peer interface and pub/sub.\n *\n * NOTE: Deno's WebSocket follows the DOM spec which does not expose protocol-level\n * ping/pong control frames. As a result:\n * - ping() sends an application-level {\"type\":\"ping\"} message (app-level keepalive)\n * - pong() is a no-op (no protocol pong to send)\n * - WsHandler.ping / WsHandler.pong callbacks are NEVER called on Deno\n */\nclass DenoWsPeer<T> implements WsPeer<T>, PubSubPeer {\n public data: T;\n public remoteAddress: string;\n /** Timestamp of last received message — used for heartbeat dead-peer detection */\n public lastActivity: number = Date.now();\n\n private ws: WebSocket;\n private hub: PubSubHub;\n\n constructor(ws: WebSocket, data: T, hub: PubSubHub, remoteAddress: string) {\n this.ws = ws;\n this.data = data;\n this.hub = hub;\n this.remoteAddress = remoteAddress;\n }\n\n get readyState(): WsReadyStateValue {\n return this.ws.readyState as WsReadyStateValue;\n }\n\n send(data: WsMessageData, _compress?: boolean): number {\n try {\n this.ws.send(data as any);\n return typeof data === 'string' ? data.length : (data as ArrayBuffer | Uint8Array).byteLength;\n } catch {\n return -1;\n }\n }\n\n close(code?: number, reason?: string): void {\n try {\n this.ws.close(code, reason);\n } catch { /* ignore */ }\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 // Deno's DOM WebSocket does not expose protocol-level PING frames.\n // Send an application-level keepalive message. Clients using Ken's WSClient\n // (or any client that handles {\"type\":\"ping\"}) will respond with {\"type\":\"pong\"}.\n if (this.ws.readyState !== 1 /* OPEN */) return;\n try {\n this.ws.send(DENO_PING_MSG);\n } catch { /* ignore */ }\n }\n\n pong(_data?: WsMessageData): void {\n // Deno's DOM WebSocket does not expose protocol-level PONG frames.\n // handler.pong is never triggered on Deno — see class comment.\n }\n}\n\n// ==================== Deno WebSocket Handler ====================\n\n/**\n * Create a Deno WebSocket upgrade handler.\n * Called by the Deno runtime adapter.\n */\nexport function createDenoWsHandler<T>(\n handler: WsHandler<T>,\n options: WsOptions = {},\n): {\n hub: PubSubHub;\n peers: Set<DenoWsPeer<T>>;\n handleUpgrade: (req: Request, info: { remoteAddr: { hostname: string; }; }) => Promise<Response>;\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<DenoWsPeer<T>>();\n\n let heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n\n async function handleUpgrade(req: Request, info: { remoteAddr: { hostname: string; }; }): Promise<Response> {\n // Capture remoteAddr early before upgradeWebSocket closes the request\n let clientHostname: string;\n try {\n clientHostname = info.remoteAddr.hostname;\n } catch {\n clientHostname = 'unknown';\n }\n\n // Run upgrade handler if provided\n let data: T = undefined as T;\n if (handler.upgrade) {\n try {\n const result = await handler.upgrade(req);\n if (result instanceof Response) {\n return result;\n }\n data = result;\n } catch {\n return new Response('Upgrade failed', { status: 500 });\n }\n }\n\n // Perform the upgrade using Deno.upgradeWebSocket\n const { socket, response } = (Deno as any).upgradeWebSocket(req);\n\n const peer = new DenoWsPeer<T>(socket, data, hub, clientHostname);\n peers.add(peer);\n\n socket.onopen = () => {\n try {\n handler.open?.(peer);\n } catch { /* ignore */ }\n };\n\n socket.onmessage = (event: MessageEvent) => {\n // Update last-activity timestamp for dead peer detection\n peer.lastActivity = Date.now();\n // Update hub liveness — on Deno any inbound message counts as alive\n // since protocol-level pong is unavailable\n hub.markAlive(peer);\n try {\n handler.message(peer, event.data);\n } catch { /* ignore */ }\n };\n\n socket.onclose = (event: CloseEvent) => {\n peers.delete(peer);\n hub.removeAll(peer);\n try {\n handler.close?.(peer, event.code, event.reason);\n } catch { /* ignore */ }\n };\n\n socket.onerror = (_event: Event) => {\n try {\n handler.error?.(peer, new Error('WebSocket error'));\n } catch { /* ignore */ }\n };\n\n return response;\n }\n\n function startHeartbeat(): void {\n if (opts.pingInterval <= 0) return;\n if (heartbeatInterval) return;\n\n // Dead peer threshold: no message received within pingInterval + pongTimeout seconds.\n // Since Deno cannot do protocol ping/pong, we track last inbound message time.\n const deadThresholdMs = (opts.pingInterval + opts.pongTimeout) * 1000;\n\n heartbeatInterval = setInterval(() => {\n const now = Date.now();\n for (const peer of peers) {\n if (peer.readyState !== WsReadyState.OPEN) {\n peers.delete(peer);\n hub.removeAll(peer);\n continue;\n }\n // Close peers that have been silent longer than the dead threshold.\n // Note: this only catches peers that never send messages; a purely\n // listening peer is indistinguishable from a dead one on Deno without\n // protocol-level ping/pong. Use Ken's WSClient for reliable liveness.\n if (now - peer.lastActivity > deadThresholdMs) {\n try { peer.close(1001, 'ping timeout'); } catch { /* ignore */ }\n peers.delete(peer);\n hub.removeAll(peer);\n continue;\n }\n // Send app-level ping — clients can reply with {\"type\":\"pong\"}\n peer.ping();\n }\n }, opts.pingInterval * 1000);\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","/**\n * Ken Framework - Deno Runtime\n * Uses Web Standard APIs natively\n * \n * MIT License - Copyright (c) 2025 Indra Gunawan\n */\n\nimport { Router } from '../core/router';\nimport { WebContext } from '../context/web';\nimport { type Schema, type GetRemoteInfo } from '../context/types';\nimport { createExecutor, createNotFoundExecutor, type ContextFactory } from './compiler';\nimport { toResponse } from '../utils/response';\nimport { getPathname } from '../utils/pathname';\nimport { type WsRoute } from '../ws/types';\nimport { createDenoWsHandler } from '../ws/deno';\n\ndeclare const Deno: {\n serve(options: {\n port?: number;\n hostname?: string;\n signal?: AbortSignal;\n onListen?: (event: { hostname: string; port: number; }) => void;\n }, handler: (request: Request, info: { remoteAddr: { hostname: string; port: number; }; }) => Response | Promise<Response>): void;\n};\n\n/**\n * WebContext factory for Deno runtime\n */\nconst webContextFactory: ContextFactory<Request, WebContext> = (\n req: Request,\n params: Record<string, string>,\n getRemoteInfo: GetRemoteInfo,\n schema?: Schema\n) => new WebContext(req, params, getRemoteInfo, schema);\n\nexport function server({ port, hostname, router }: {\n port?: number;\n hostname?: string;\n router: Router;\n}) {\n let ac: AbortController | undefined = undefined;\n\n // Compile routes with 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 const nativeHandler = createExecutor(webContextFactory, route.handler, mergedSchema);\n compiledRouter.registerCompiled(route.method, route.path, nativeHandler, mergedSchema);\n } else if (route.staticValue !== undefined) {\n const cachedResponse = toResponse(route.staticValue);\n compiledRouter.registerCompiled(route.method, route.path, () => cachedResponse.clone(), mergedSchema, cachedResponse);\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, webContextFactory);\n const NOT_FOUND_RESPONSE = new Response('Not Found', { status: 404 });\n\n // WebSocket routes\n const wsRoutes: WsRoute<any>[] = (router as any).wsRoutes || [];\n const wsHandlers = new Map<string, ReturnType<typeof createDenoWsHandler>>();\n for (const wsRoute of wsRoutes) {\n wsHandlers.set(wsRoute.path, createDenoWsHandler(wsRoute.handler, wsRoute.options));\n }\n\n return {\n async run(): Promise<{ hostname: string; port: number; }> {\n ac?.abort();\n ac = new AbortController();\n\n // Start heartbeat for all WS handlers\n for (const wsHandler of wsHandlers.values()) {\n wsHandler.startHeartbeat();\n }\n\n return new Promise((resolve) => {\n Deno.serve({\n port,\n hostname,\n signal: ac?.signal,\n onListen: ({ hostname, port }) => {\n resolve({ hostname, port });\n },\n }, (request, info) => {\n const pathname = getPathname(request.url);\n\n // Check for WebSocket upgrade\n if (request.headers.get('upgrade') === 'websocket') {\n const wsHandler = wsHandlers.get(pathname);\n if (wsHandler) {\n return wsHandler.handleUpgrade(request, info);\n }\n return new Response('Not Found', { status: 404 });\n }\n\n const matchResult = match(request.method, pathname);\n\n if (matchResult !== undefined) {\n // Fast path: static route (skip getRemoteInfo, handler call, toResponse)\n if (matchResult.response !== undefined) {\n return matchResult.response.clone();\n }\n\n // Dynamic route\n const getRemoteInfo: GetRemoteInfo = () => ({\n address: info.remoteAddr.hostname,\n port: info.remoteAddr.port,\n });\n\n const result = matchResult.handler(request, matchResult.params, getRemoteInfo);\n\n // Handle async results\n if (result && typeof result.then === 'function') {\n return result.then(toResponse);\n }\n return toResponse(result);\n }\n\n // Execute 404 with middleware if available\n if (notFoundExecutor) {\n const getRemoteInfo: GetRemoteInfo = () => ({\n address: info.remoteAddr.hostname,\n port: info.remoteAddr.port,\n });\n const result = notFoundExecutor(request, getRemoteInfo, pathname);\n if (result && typeof result.then === 'function') {\n return result.then(toResponse);\n }\n return toResponse(result);\n }\n\n return NOT_FOUND_RESPONSE.clone();\n });\n });\n },\n\n stop() {\n for (const wsHandler of wsHandlers.values()) {\n wsHandler.stopHeartbeat();\n }\n ac?.abort('STOP');\n ac = undefined;\n }\n };\n}\n\n// console.log('Deno runtime module loaded.');"],"mappings":"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","names":["hostname","port"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -905,59 +905,57 @@ declare function memoize<Args extends unknown[], R>(fn: (...args: Args) => R, op
|
|
|
905
905
|
* Output is base64url-encoded (no +, /, or = characters) — safe for
|
|
906
906
|
* cookies, URLs, and JSON values without escaping.
|
|
907
907
|
*
|
|
908
|
-
* Default format is `
|
|
909
|
-
*
|
|
908
|
+
* Default format is `gzip` — standard Web API `CompressionFormat`,
|
|
909
|
+
* compatible with all runtimes including Deno Deploy.
|
|
910
910
|
*
|
|
911
911
|
* MIT License - Copyright (c) 2025 Indra Gunawan
|
|
912
912
|
*/
|
|
913
|
-
/** Supported compression formats —
|
|
914
|
-
type SupportedCompressionFormat = CompressionFormat
|
|
913
|
+
/** Supported compression formats — standard Web API `CompressionFormat`. */
|
|
914
|
+
type SupportedCompressionFormat = CompressionFormat;
|
|
915
915
|
/**
|
|
916
916
|
* Options for {@link compressString}.
|
|
917
917
|
*
|
|
918
918
|
* The `level` range depends on the chosen `encoding`:
|
|
919
|
-
* - **`brotli`**: 0–11 (default: `11` — best compression, slowest)
|
|
920
919
|
* - **`deflate` / `gzip` / `deflate-raw`**: 0–9 (default: runtime default, typically `6`)
|
|
921
920
|
*
|
|
922
921
|
* Lower values = faster encoding + larger output.
|
|
923
922
|
* Higher values = slower encoding + smaller output.
|
|
924
923
|
*/
|
|
925
924
|
interface CompressOptions$1 {
|
|
926
|
-
/** Compression format. Default: `'
|
|
925
|
+
/** Compression format. Default: `'gzip'`. */
|
|
927
926
|
encoding?: SupportedCompressionFormat;
|
|
928
927
|
/**
|
|
929
928
|
* Compression quality level.
|
|
930
|
-
* - brotli: 0–11 (default 11)
|
|
931
929
|
* - deflate / gzip / deflate-raw: 0–9 (default ~6)
|
|
932
930
|
*/
|
|
933
931
|
level?: number;
|
|
934
932
|
}
|
|
935
933
|
/** Options for {@link decompressString}. */
|
|
936
934
|
interface DecompressOptions {
|
|
937
|
-
/** Compression format used during compression. Default: `'
|
|
935
|
+
/** Compression format used during compression. Default: `'gzip'`. */
|
|
938
936
|
encoding?: SupportedCompressionFormat;
|
|
939
937
|
}
|
|
940
938
|
/**
|
|
941
939
|
* Compress a string and return a base64url-encoded result.
|
|
942
940
|
* Output is safe for cookies, URLs, and JSON values (no +, /, or = characters).
|
|
943
941
|
*
|
|
944
|
-
* Uses `
|
|
945
|
-
*
|
|
942
|
+
* Uses `gzip` by default — a standard Web API `CompressionFormat`
|
|
943
|
+
* compatible with all runtimes including Deno Deploy.
|
|
946
944
|
*
|
|
947
945
|
* @param input - The string to compress
|
|
948
|
-
* @param options - Compression options: `encoding` (default `'
|
|
946
|
+
* @param options - Compression options: `encoding` (default `'gzip'`) and optional `level`
|
|
949
947
|
* @returns Base64url-encoded compressed string
|
|
950
948
|
*
|
|
951
949
|
* @example
|
|
952
950
|
* ```ts
|
|
953
|
-
* //
|
|
951
|
+
* // Default gzip
|
|
954
952
|
* const compressed = await compressString('Hello, World!');
|
|
955
953
|
*
|
|
956
|
-
* // Faster, lighter brotli
|
|
957
|
-
* const fast = await compressString('Hello, World!', { level: 4 });
|
|
958
|
-
*
|
|
959
954
|
* // gzip with max compression
|
|
960
955
|
* const gz = await compressString('Hello, World!', { encoding: 'gzip', level: 9 });
|
|
956
|
+
*
|
|
957
|
+
* // deflate
|
|
958
|
+
* const df = await compressString('Hello, World!', { encoding: 'deflate' });
|
|
961
959
|
* ```
|
|
962
960
|
*/
|
|
963
961
|
declare function compressString(input: string, options?: CompressOptions$1): Promise<string>;
|
|
@@ -965,7 +963,7 @@ declare function compressString(input: string, options?: CompressOptions$1): Pro
|
|
|
965
963
|
* Decompress a base64url-encoded compressed string back to the original.
|
|
966
964
|
*
|
|
967
965
|
* @param compressed - Base64url-encoded compressed string from {@link compressString}
|
|
968
|
-
* @param options - Decompression options: `encoding` must match what was used to compress (default `'
|
|
966
|
+
* @param options - Decompression options: `encoding` must match what was used to compress (default `'gzip'`)
|
|
969
967
|
* @returns The original decompressed string
|
|
970
968
|
*
|
|
971
969
|
* @example
|
|
@@ -973,7 +971,7 @@ declare function compressString(input: string, options?: CompressOptions$1): Pro
|
|
|
973
971
|
* const original = await decompressString(compressed);
|
|
974
972
|
* // 'Hello, World!'
|
|
975
973
|
*
|
|
976
|
-
* const original = await decompressString(compressed, { encoding: '
|
|
974
|
+
* const original = await decompressString(compressed, { encoding: 'deflate' });
|
|
977
975
|
* ```
|
|
978
976
|
*/
|
|
979
977
|
declare function decompressString(compressed: string, options?: DecompressOptions): Promise<string>;
|
package/dist/index.js
CHANGED
|
@@ -425,7 +425,7 @@ async function resolveNodeRuntime() {
|
|
|
425
425
|
}
|
|
426
426
|
async function server(options) {
|
|
427
427
|
if (isDeno) {
|
|
428
|
-
const { server: server2 } = await import("./deno-
|
|
428
|
+
const { server: server2 } = await import("./deno-DV3633IH.js");
|
|
429
429
|
return server2(options);
|
|
430
430
|
}
|
|
431
431
|
if (isBun) {
|
|
@@ -729,7 +729,7 @@ async function readAllBytes(readable) {
|
|
|
729
729
|
return result;
|
|
730
730
|
}
|
|
731
731
|
async function compressString(input, options) {
|
|
732
|
-
const encoding = options?.encoding ?? "
|
|
732
|
+
const encoding = options?.encoding ?? "gzip";
|
|
733
733
|
const cs = options?.level !== void 0 ? new CompressionStream(encoding, { level: options.level }) : new CompressionStream(encoding);
|
|
734
734
|
const writer = cs.writable.getWriter();
|
|
735
735
|
writer.write(encoder.encode(input)).catch(() => {
|
|
@@ -739,7 +739,7 @@ async function compressString(input, options) {
|
|
|
739
739
|
return encodeBase64Url(await readAllBytes(cs.readable));
|
|
740
740
|
}
|
|
741
741
|
async function decompressString(compressed, options) {
|
|
742
|
-
const encoding = options?.encoding ?? "
|
|
742
|
+
const encoding = options?.encoding ?? "gzip";
|
|
743
743
|
const ds = new DecompressionStream(encoding);
|
|
744
744
|
const writer = ds.writable.getWriter();
|
|
745
745
|
writer.write(decodeBase64Url(compressed)).catch(() => {
|