@nexusts/ws 0.9.0 → 0.9.1

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/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `nexusjs/ws` — Hono WebSocket integration.
2
+ * `@nexusts/ws` — Hono WebSocket integration.
3
3
  *
4
4
  * Provides a single API for WebSocket gateways that works on both
5
5
  * Bun (primary, via `hono/adapter/bun/websocket`) and Node (via
package/dist/index.js.map CHANGED
@@ -5,10 +5,10 @@
5
5
  "/**\n * `WebSocketService` — connection registry, rooms, broadcasting.\n *\n * The service is the central state for all open WebSocket\n * connections. It is registered in the DI container as a singleton\n * and consumed by `@WebSocketGateway` classes.\n *\n * Features:\n * - **Connection registry** — `getConnections()` returns all\n * currently-open clients.\n * - **Per-connection lookup** — `getConnection(id)`.\n * - **Rooms** — `joinRoom`, `leaveRoom`, `broadcastToRoom`. Rooms\n * are auto-cleaned when empty.\n * - **Broadcast** — `broadcast(data)` sends to all open clients.\n * - **Targeted send** — `sendTo(id, data)`.\n * - **Lifecycle tracking** — `onConnect` / `onDisconnect` callbacks\n * for metrics, audit logging, etc.\n */\n\nimport type { WebSocketClient, WsMessage, WsClientData } from \"./types.js\";\nimport { WebSocketClientImpl } from \"./client.js\";\n\nexport const WEBSOCKET_SERVICE_TOKEN = Symbol.for(\"nexus:WebSocketService\");\n\nexport class WebSocketService {\n\t/** id -> client */\n\tprivate clients = new Map<string, WebSocketClientImpl>();\n\t/** room -> Set<id> */\n\tprivate rooms = new Map<string, Set<string>>();\n\t/** Lifecycle callbacks. */\n\tprivate onConnectListeners: Array<(c: WebSocketClient) => void> = [];\n\tprivate onDisconnectListeners: Array<(c: WebSocketClient) => void> = [];\n\n\t/* ---------------- registry ---------------- */\n\n\t/** Register a new client. Returns the framework id. */\n\tregister(client: WebSocketClientImpl): string {\n\t\tthis.clients.set(client.id, client);\n\t\tfor (const cb of this.onConnectListeners) {\n\t\t\ttry {\n\t\t\t\tcb(client);\n\t\t\t} catch {\n\t\t\t\t/* ignore listener errors */\n\t\t\t}\n\t\t}\n\t\treturn client.id;\n\t}\n\n\t/** Remove a client from the registry. Auto-cleans empty rooms. */\n\tunregister(client: WebSocketClientImpl): void {\n\t\tthis.clients.delete(client.id);\n\t\tfor (const room of client.rooms) {\n\t\t\tconst set = this.rooms.get(room);\n\t\t\tif (set) {\n\t\t\t\tset.delete(client.id);\n\t\t\t\tif (set.size === 0) this.rooms.delete(room);\n\t\t\t}\n\t\t}\n\t\tfor (const cb of this.onDisconnectListeners) {\n\t\t\ttry {\n\t\t\t\tcb(client);\n\t\t\t} catch {\n\t\t\t\t/* ignore listener errors */\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Number of currently-open connections. */\n\tget size(): number {\n\t\treturn this.clients.size;\n\t}\n\n\t/** Get all open connections. */\n\tgetConnections(): WebSocketClient[] {\n\t\treturn [...this.clients.values()];\n\t}\n\n\t/** Get a connection by id. */\n\tgetConnection(id: string): WebSocketClient | undefined {\n\t\treturn this.clients.get(id);\n\t}\n\n\t/* ---------------- rooms ---------------- */\n\n\t/** Join a room. */\n\tjoinRoom(client: WebSocketClient, room: string): void {\n\t\tconst impl = client as WebSocketClientImpl;\n\t\timpl.joinRoom(room);\n\t\tlet set = this.rooms.get(room);\n\t\tif (!set) {\n\t\t\tset = new Set();\n\t\t\tthis.rooms.set(room, set);\n\t\t}\n\t\tset.add(client.id);\n\t}\n\n\t/** Leave a room. */\n\tleaveRoom(client: WebSocketClient, room: string): void {\n\t\tconst impl = client as WebSocketClientImpl;\n\t\timpl.leaveRoom(room);\n\t\tconst set = this.rooms.get(room);\n\t\tif (set) {\n\t\t\tset.delete(client.id);\n\t\t\tif (set.size === 0) this.rooms.delete(room);\n\t\t}\n\t}\n\n\t/** Leave all rooms. */\n\tleaveAllRooms(client: WebSocketClient): void {\n\t\tconst impl = client as WebSocketClientImpl;\n\t\tfor (const room of impl.rooms) {\n\t\t\tconst set = this.rooms.get(room);\n\t\t\tif (set) {\n\t\t\t\tset.delete(client.id);\n\t\t\t\tif (set.size === 0) this.rooms.delete(room);\n\t\t\t}\n\t\t}\n\t\timpl.rooms.clear();\n\t}\n\n\t/** All client ids in a room. */\n\tgetRoomMembers(room: string): WebSocketClient[] {\n\t\tconst ids = this.rooms.get(room);\n\t\tif (!ids) return [];\n\t\tconst out: WebSocketClient[] = [];\n\t\tfor (const id of ids) {\n\t\t\tconst c = this.clients.get(id);\n\t\t\tif (c) out.push(c);\n\t\t}\n\t\treturn out;\n\t}\n\n\t/** All room names currently in use. */\n\tgetRooms(): string[] {\n\t\treturn [...this.rooms.keys()];\n\t}\n\n\t/** Whether a room has any members. */\n\thasRoom(room: string): boolean {\n\t\tconst set = this.rooms.get(room);\n\t\treturn !!set && set.size > 0;\n\t}\n\n\t/* ---------------- broadcast ---------------- */\n\n\t/** Send to all open clients. */\n\tbroadcast(data: WsMessage, filter?: (client: WebSocketClient) => boolean): void {\n\t\tfor (const client of this.clients.values()) {\n\t\t\tif (filter && !filter(client)) continue;\n\t\t\ttry {\n\t\t\t\tclient.send(data);\n\t\t\t} catch {\n\t\t\t\t/* ignore send errors */\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Send to all clients in a room. */\n\tbroadcastToRoom(room: string, data: WsMessage): void {\n\t\tconst ids = this.rooms.get(room);\n\t\tif (!ids) return;\n\t\tfor (const id of ids) {\n\t\t\tconst client = this.clients.get(id);\n\t\t\tif (!client) continue;\n\t\t\ttry {\n\t\t\t\tclient.send(data);\n\t\t\t} catch {\n\t\t\t\t/* ignore send errors */\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Send to a single client by id. */\n\tsendTo(id: string, data: WsMessage): boolean {\n\t\tconst client = this.clients.get(id);\n\t\tif (!client) return false;\n\t\ttry {\n\t\t\tclient.send(data);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/** Close all connections (graceful shutdown). */\n\tcloseAll(code = 1001, reason = \"Server shutting down\"): void {\n\t\tfor (const client of this.clients.values()) {\n\t\t\ttry {\n\t\t\t\tclient.close(code, reason);\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t}\n\t}\n\n\t/* ---------------- lifecycle listeners ---------------- */\n\n\t/** Register a callback for new connections. */\n\tonConnect(cb: (client: WebSocketClient) => void): void {\n\t\tthis.onConnectListeners.push(cb);\n\t}\n\n\t/** Register a callback for closed connections. */\n\tonDisconnect(cb: (client: WebSocketClient) => void): void {\n\t\tthis.onDisconnectListeners.push(cb);\n\t}\n}\n",
6
6
  "/**\n * `WebSocketClient` — the framework's per-connection wrapper.\n *\n * Hono's `WSContext` is a thin wrapper over the underlying\n * WebSocket. `WebSocketClient` adds:\n * - A unique connection id (UUID-ish).\n * - Room membership tracking.\n * - User-attached data (auth userId, custom keys).\n * - A stable `send()` API that JSON-encodes objects.\n *\n * Constructed by the runtime adapter (`runtime/bun.ts` or\n * `runtime/node.ts`) and passed to the gateway's lifecycle hooks.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport type { WsMessage, WsReadyState, WsClientData } from \"./types.js\";\n\n/** Minimal interface that the wrapper needs from the underlying WSContext. */\nexport interface UnderlyingWs {\n\tsend(data: string | ArrayBuffer | Uint8Array, options?: { compress?: boolean }): void;\n\tclose(code?: number, reason?: string): void;\n\treadonly readyState: number;\n\treadonly url: string | null;\n\treadonly protocol: string | null;\n}\n\nexport class WebSocketClientImpl {\n\treadonly id: string;\n\treadonly rooms: Set<string> = new Set();\n\tdata: WsClientData = {};\n\tprivate _underlying: UnderlyingWs;\n\n\tconstructor(underlying: UnderlyingWs, id?: string) {\n\t\tthis.id = id ?? randomUUID();\n\t\tthis._underlying = underlying;\n\t}\n\n\tget url(): string | null {\n\t\treturn this._underlying.url;\n\t}\n\n\tget protocol(): string | null {\n\t\treturn this._underlying.protocol;\n\t}\n\n\tget readyState(): WsReadyState {\n\t\treturn this._underlying.readyState as WsReadyState;\n\t}\n\n\tsend(data: WsMessage): void {\n\t\tif (typeof data === \"object\" && !(data instanceof ArrayBuffer) && !(data instanceof Uint8Array)) {\n\t\t\tthis._underlying.send(JSON.stringify(data));\n\t\t} else {\n\t\t\tthis._underlying.send(data as string | ArrayBuffer | Uint8Array);\n\t\t}\n\t}\n\n\tclose(code?: number, reason?: string): void {\n\t\tthis._underlying.close(code, reason);\n\t}\n\n\tsetData(data: Partial<WsClientData>): void {\n\t\tObject.assign(this.data, data);\n\t}\n\n\tjoinRoom(room: string): void {\n\t\tthis.rooms.add(room);\n\t}\n\n\tleaveRoom(room: string): void {\n\t\tthis.rooms.delete(room);\n\t}\n\n\t/** Internal: get the underlying WSContext (for the runtime layer). */\n\traw(): UnderlyingWs {\n\t\treturn this._underlying;\n\t}\n}\n",
7
7
  "/**\n * `WebSocketModule` — wires `WebSocketService` into the DI container\n * and provides runtime-specific helpers for the application.\n *\n * Usage (Bun):\n *\n * @Module({\n * imports: [\n * WebSocketModule.forRoot({\n * gateways: [ChatGateway],\n * path: '/ws',\n * }),\n * ],\n * })\n * class AppModule {}\n *\n * const app = new Application(AppModule);\n * const { websocket } = await app.wireWebSocket();\n * Bun.serve({\n * port: 3000,\n * fetch: app.fetch,\n * websocket,\n * });\n *\n * Usage (Node):\n *\n * const app = new Application(AppModule);\n * const { server, wss } = await app.serveNodeWebSocket(3000);\n */\n\nimport { Inject, Module } from \"@nexusts/core\";\nimport { WebSocketService, WEBSOCKET_SERVICE_TOKEN } from \"./service.js\";\nimport type { WebSocketConfig } from \"./types.js\";\nimport { detectRuntime } from \"./runtime/index.js\";\nimport type { GatewayClass } from \"./runtime/types.js\";\n\n@Module({\n\tproviders: [\n\t\tWebSocketService,\n\t\t{ provide: WEBSOCKET_SERVICE_TOKEN, useExisting: WebSocketService },\n\t],\n\texports: [WebSocketService, WEBSOCKET_SERVICE_TOKEN],\n})\nexport class WebSocketModule {\n\tstatic forRoot(config: WebSocketConfig & { gateways?: GatewayClass[] } = {}) {\n\t\tconst fullConfig: Required<WebSocketConfig> & { gateways: GatewayClass[] } = {\n\t\t\tpath: config.path ?? \"/ws\",\n\t\t\tjson: config.json ?? true,\n\t\t\theartbeatSeconds: config.heartbeatSeconds ?? 30,\n\t\t\tonUnknownRuntime: config.onUnknownRuntime ?? \"throw\",\n\t\t\tgateways: config.gateways ?? [],\n\t\t};\n\n\t\t@Module({\n\t\t\tproviders: [\n\t\t\t\tWebSocketService,\n\t\t\t\t{ provide: WEBSOCKET_SERVICE_TOKEN, useExisting: WebSocketService },\n\t\t\t\t{ provide: \"WS_CONFIG\", useValue: fullConfig },\n\t\t\t],\n\t\t\texports: [WebSocketService, WEBSOCKET_SERVICE_TOKEN, \"WS_CONFIG\"],\n\t\t})\n\t\tclass ConfiguredWebSocketModule {\n\t\t\tconstructor(@Inject(WEBSOCKET_SERVICE_TOKEN) readonly service: WebSocketService) {}\n\n\t\t\t/** Detect the runtime at boot time. */\n\t\t\tdetectRuntime() {\n\t\t\t\treturn detectRuntime();\n\t\t\t}\n\t\t}\n\t\tObject.defineProperty(ConfiguredWebSocketModule, \"name\", {\n\t\t\tvalue: \"ConfiguredWebSocketModule\",\n\t\t});\n\n\t\treturn ConfiguredWebSocketModule as unknown as typeof ConfiguredWebSocketModule & {\n\t\t\treadonly config: typeof fullConfig;\n\t\t};\n\t}\n}\n",
8
- "/**\n * Runtime detection & helper for `nexusjs/ws`.\n */\n\nexport type WsRuntime = \"bun\" | \"node\" | \"cloudflare\" | \"unknown\";\n\n/**\n * Detect the current JavaScript runtime.\n *\n * - `bun` — Bun (native `Bun.serve` WebSocket)\n * - `node` — Node.js (uses the `ws` package)\n * - `cloudflare` — Cloudflare Workers / Pages (Durable Objects only)\n * - `unknown` — fall-through; no adapter auto-installed\n */\nexport function detectRuntime(): WsRuntime {\n\tif (typeof (globalThis as { Bun?: unknown }).Bun !== \"undefined\") return \"bun\";\n\tif (typeof process !== \"undefined\" && process.versions?.node) return \"node\";\n\t// Cloudflare: `caches` global + absence of `process.versions.node` is a strong signal.\n\tif (\n\t\ttypeof (globalThis as { caches?: unknown }).caches !== \"undefined\" &&\n\t\ttypeof (globalThis as { WebSocketPair?: unknown }).WebSocketPair !== \"undefined\"\n\t) {\n\t\treturn \"cloudflare\";\n\t}\n\treturn \"unknown\";\n}\n",
8
+ "/**\n * Runtime detection & helper for `@nexusts/ws`.\n */\n\nexport type WsRuntime = \"bun\" | \"node\" | \"cloudflare\" | \"unknown\";\n\n/**\n * Detect the current JavaScript runtime.\n *\n * - `bun` — Bun (native `Bun.serve` WebSocket)\n * - `node` — Node.js (uses the `ws` package)\n * - `cloudflare` — Cloudflare Workers / Pages (Durable Objects only)\n * - `unknown` — fall-through; no adapter auto-installed\n */\nexport function detectRuntime(): WsRuntime {\n\tif (typeof (globalThis as { Bun?: unknown }).Bun !== \"undefined\") return \"bun\";\n\tif (typeof process !== \"undefined\" && process.versions?.node) return \"node\";\n\t// Cloudflare: `caches` global + absence of `process.versions.node` is a strong signal.\n\tif (\n\t\ttypeof (globalThis as { caches?: unknown }).caches !== \"undefined\" &&\n\t\ttypeof (globalThis as { WebSocketPair?: unknown }).WebSocketPair !== \"undefined\"\n\t) {\n\t\treturn \"cloudflare\";\n\t}\n\treturn \"unknown\";\n}\n",
9
9
  "/**\n * WebSocket decorators.\n *\n * Two layers:\n * 1. `@WebSocketGateway(path)` — class-level. Marks the class as a\n * WebSocket gateway. The framework scans for these and registers\n * a Hono `upgradeWebSocket` handler at `<path>`.\n * 2. `@OnWebSocketOpen()`, `@OnWebSocketMessage()`, etc. —\n * method-level. Wire lifecycle events to specific methods on\n * the gateway class.\n *\n * Implementation note: lifecycle decorators store metadata on the\n * method function itself (via a `Symbol.for` key). The class-level\n * `@WebSocketGateway` walks the prototype to collect them. This\n * pattern is robust regardless of the target passed by the TS\n * decorator transform.\n */\n\nimport type { WsLifecycle } from \"./types.js\";\n\nconst GATEWAY_KEY = Symbol.for(\"nexus:ws:gateway\");\nconst LIFECYCLE_KEY = Symbol.for(\"nexus:ws:lifecycle\");\n\ninterface GatewayMetadata {\n\tpath: string;\n\thandlers: Record<string, string>;\n}\n\n/**\n * Mark a class as a WebSocket gateway. `path` is the URL path the\n * gateway listens on (e.g. `/ws`, `/chat`).\n *\n * @Injectable()\n * @WebSocketGateway('/ws')\n * class ChatGateway { ... }\n */\nexport function WebSocketGateway(path: string): ClassDecorator {\n\treturn function (target: Function) {\n\t\tconst ctor = target as unknown as { prototype: object };\n\t\tconst proto = ctor.prototype ?? (target as unknown as object);\n\t\t// Collect lifecycle handlers from method-level decorators.\n\t\tconst handlers: Record<string, string> = {};\n\t\tfor (const name of Object.getOwnPropertyNames(proto)) {\n\t\t\tif (name === \"constructor\") continue;\n\t\t\tconst m = (proto as any)[name];\n\t\t\tif (typeof m === \"function\" && (m as any)[LIFECYCLE_KEY]) {\n\t\t\t\tObject.assign(handlers, (m as any)[LIFECYCLE_KEY]);\n\t\t\t}\n\t\t}\n\t\t(proto as any)[GATEWAY_KEY] = { path, handlers } satisfies GatewayMetadata;\n\t};\n}\n\n/** Read the gateway path. Internal — used by the framework. */\nexport function getGatewayPath(target: object): string | undefined {\n\tconst t = target as any;\n\tconst meta: GatewayMetadata | undefined = t[GATEWAY_KEY];\n\treturn meta?.path;\n}\n\n/* ------------------------------------------------------------------ *\n * Lifecycle method decorators\n * ------------------------------------------------------------------ */\n\nfunction makeLifecycleDecorator(lifecycle: WsLifecycle) {\n\treturn function (\n\t\t_target: object,\n\t\tpropertyKey: string | symbol,\n\t\tdescriptor: PropertyDescriptor,\n\t) {\n\t\tconst fn = descriptor.value as Function & { [LIFECYCLE_KEY]?: Record<string, string> };\n\t\tif (typeof fn !== \"function\") return descriptor;\n\t\tfn[LIFECYCLE_KEY] = fn[LIFECYCLE_KEY] ?? {};\n\t\tfn[LIFECYCLE_KEY][lifecycle] = String(propertyKey);\n\t\treturn descriptor;\n\t};\n}\n\n/** Method decorator factory: bind to `onOpen` lifecycle. */\nexport function OnWebSocketOpen(): MethodDecorator {\n\treturn makeLifecycleDecorator(\"open\");\n}\n/** Method decorator factory: bind to `onMessage` lifecycle. */\nexport function OnWebSocketMessage(): MethodDecorator {\n\treturn makeLifecycleDecorator(\"message\");\n}\n/** Method decorator factory: bind to `onClose` lifecycle. */\nexport function OnWebSocketClose(): MethodDecorator {\n\treturn makeLifecycleDecorator(\"close\");\n}\n/** Method decorator factory: bind to `onError` lifecycle. */\nexport function OnWebSocketError(): MethodDecorator {\n\treturn makeLifecycleDecorator(\"error\");\n}\n\n/** Read the bound lifecycle methods. Internal — used by the framework. */\nexport function getLifecycleHandlers(target: object): {\n\topen?: string;\n\tmessage?: string;\n\tclose?: string;\n\terror?: string;\n} {\n\tconst t = target as any;\n\t// 1. Prefer the metadata stored by @WebSocketGateway.\n\tif (t[GATEWAY_KEY]?.handlers) return t[GATEWAY_KEY].handlers;\n\t// 2. Walk the prototype and collect from method functions.\n\tconst out: Record<string, string> = {};\n\tconst proto = t.prototype ?? t;\n\tfor (const name of Object.getOwnPropertyNames(proto)) {\n\t\tif (name === \"constructor\") continue;\n\t\tconst m = (proto as any)[name];\n\t\tif (typeof m === \"function\" && (m as any)[LIFECYCLE_KEY]) {\n\t\t\tObject.assign(out, (m as any)[LIFECYCLE_KEY]);\n\t\t}\n\t}\n\treturn out;\n}\n",
10
- "/**\n * Bun runtime adapter for `nexusjs/ws`.\n *\n * Uses Hono's `createBunWebSocket` to bridge Hono's `WSEvents`\n * to Bun's native WebSocket API.\n *\n * The user wires the returned `websocket` config into\n * `Bun.serve({ websocket, fetch: app.fetch })`. The framework\n * also calls `Bun.serve` automatically if `serve` is provided\n * to `WebSocketModule.forRoot({ serve: { port: 3000 } })`.\n */\n\nimport type { Hono } from \"hono\";\nimport { getGatewayPath, getLifecycleHandlers } from \"../decorators.js\";\nimport type { WebSocketService } from \"../service.js\";\nimport { WebSocketClientImpl } from \"../client.js\";\nimport type { WebSocketGatewayOptions, GatewayClass } from \"./types.js\";\n\n/** Adapter that wires `@WebSocketGateway` classes to Bun's WebSocket. */\nexport class BunWsAdapter {\n\treadonly service: WebSocketService;\n\tprivate readonly options: WebSocketGatewayOptions;\n\n\tconstructor(service: WebSocketService, options: WebSocketGatewayOptions = {}) {\n\t\tthis.service = service;\n\t\tthis.options = options;\n\t}\n\n\t/**\n\t * Returns the `websocket` config object that the user passes to\n\t * `Bun.serve({ websocket, fetch: app.fetch })`.\n\t *\n\t * The `upgradeWebSocket` middleware is also installed on the\n\t * Hono app at every registered gateway's path.\n\t */\n\tasync install(app: Hono, gateways: GatewayClass[]): Promise<{ websocket: BunWebSocketConfig }> {\n\t\t// Lazy-import Hono's Bun adapter to keep Node builds from breaking.\n\t\t// @ts-ignore - bun adapter is Bun-only\n\t\tconst { createBunWebSocket } = await import(\"hono/bun\");\n\t\tconst { upgradeWebSocket, websocket } = createBunWebSocket();\n\n\t\tfor (const Gateway of gateways) {\n\t\t\tconst path = getGatewayPath(Gateway.prototype);\n\t\t\tif (!path) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`WebSocket gateway ${Gateway.name} is missing @WebSocketGateway(path)`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst handlers = getLifecycleHandlers(Gateway.prototype);\n\t\t\tconst opts = this.options;\n\n\t\t\tapp.get(\n\t\t\t\tpath,\n\t\t\t\tupgradeWebSocket((_c: unknown) => {\n\t\t\t\t\t// Build the gateway instance per-connection. (DI happens\n\t\t\t\t\t// via the service — the gateway pulls dependencies from\n\t\t\t\t\t// the container through the service.)\n\t\t\t\t\tconst gateway = new Gateway();\n\t\t\t\t\t// Inject the service if the gateway has a setter / field.\n\t\t\t\t\tif (gateway && \"setService\" in (gateway as any) && typeof (gateway as any).setService === \"function\") {\n\t\t\t\t\t\t(gateway as any).setService(this.service);\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tonOpen: (_evt: Event, ws: any) => {\n\t\t\t\t\t\t\tconst client = new WebSocketClientImpl(ws);\n\t\t\t\t\t\t\tthis.service.register(client);\n\t\t\t\t\t\t\t(opts.onOpen ?? this.defaultOnOpen)(client);\n\t\t\t\t\t\t\tif (handlers.open) {\n\t\t\t\t\t\t\t\tPromise.resolve((gateway as any)[handlers.open](client)).catch(\n\t\t\t\t\t\t\t\t\t(err) => opts.onError?.(client, err as Error),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonMessage: (evt: MessageEvent, ws: any) => {\n\t\t\t\t\t\t\tconst id = (ws as any).__clientId as string | undefined;\n\t\t\t\t\t\t\tconst client = id ? this.service.getConnection(id) as WebSocketClientImpl | undefined : undefined;\n\t\t\t\t\t\t\tif (!client) return;\n\t\t\t\t\t\t\tconst raw = evt.data;\n\t\t\t\t\t\t\tconst data = this.parseMessage(raw);\n\t\t\t\t\t\t\tif (handlers.message) {\n\t\t\t\t\t\t\t\tPromise.resolve((gateway as any)[handlers.message](client, data)).catch(\n\t\t\t\t\t\t\t\t\t(err) => opts.onError?.(client, err as Error),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonClose: (evt: CloseEvent, ws: any) => {\n\t\t\t\t\t\t\tconst id = (ws as any).__clientId as string | undefined;\n\t\t\t\t\t\t\tconst client = id ? this.service.getConnection(id) as WebSocketClientImpl | undefined : undefined;\n\t\t\t\t\t\t\tif (!client) return;\n\t\t\t\t\t\t\tthis.service.unregister(client);\n\t\t\t\t\t\t\t(opts.onClose ?? this.defaultOnClose)(client, evt.code, evt.reason);\n\t\t\t\t\t\t\tif (handlers.close) {\n\t\t\t\t\t\t\t\tPromise.resolve((gateway as any)[handlers.close](client, evt.code, evt.reason)).catch(\n\t\t\t\t\t\t\t\t\t(err) => opts.onError?.(client, err as Error),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonError: (evt: Event, ws: any) => {\n\t\t\t\t\t\t\tconst id = (ws as any).__clientId as string | undefined;\n\t\t\t\t\t\t\tconst client = id ? this.service.getConnection(id) as WebSocketClientImpl | undefined : undefined;\n\t\t\t\t\t\t\tif (!client) return;\n\t\t\t\t\t\t\tconst err = (evt as any).error ?? new Error(\"WebSocket error\");\n\t\t\t\t\t\t\tif (handlers.error) {\n\t\t\t\t\t\t\t\tPromise.resolve((gateway as any)[handlers.error](client, err)).catch(() => {});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\topts.onError?.(client, err);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\treturn { websocket };\n\t}\n\n\tprivate parseMessage(raw: unknown): unknown {\n\t\tif (this.options.json === false) return raw;\n\t\tif (typeof raw === \"string\") {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(raw);\n\t\t\t} catch {\n\t\t\t\treturn raw;\n\t\t\t}\n\t\t}\n\t\treturn raw;\n\t}\n\n\tprivate defaultOnOpen(_client: any): void {}\n\tprivate defaultOnClose(_client: any, _code: number, _reason: string): void {}\n}\n\n\n/** Bun's `websocket` config shape (subset we use). */\nexport interface BunWebSocketConfig {\n\topen?: (ws: any) => void;\n\tmessage?: (ws: any, message: any) => void;\n\tclose?: (ws: any, code: number, reason: string) => void;\n\terror?: (ws: any, error: Error) => void;\n\t// ... other Bun WS options\n}\n",
11
- "/**\n * Node runtime adapter for `nexusjs/ws`.\n *\n * Uses the `ws` package directly. The user provides a\n * `WebSocketServer` (or one is created automatically) and the\n * framework wires connection events to the gateway's lifecycle\n * handlers.\n *\n * The `ws` package is an optional peer dependency. Apps targeting\n * Bun don't need to install it.\n *\n * Usage (with auto-server):\n *\n * const mod = WebSocketModule.forRoot({ path: '/ws' });\n * const { app, wsServer } = await mod.mountNode(gateways);\n * const server = createServer(app.fetch);\n * server.listen(3000);\n * wsServer.emit('connection', ws, req); // via the framework\n *\n * Usage (with existing `http.Server`):\n *\n * const server = http.createServer(app.fetch);\n * const wss = new WebSocketServer({ server });\n * mod.bindNode(wss, gateways);\n * server.listen(3000);\n */\n\nimport type { Hono } from \"hono\";\nimport { getGatewayPath, getLifecycleHandlers } from \"../decorators.js\";\nimport type { WebSocketService } from \"../service.js\";\nimport { WebSocketClientImpl } from \"../client.js\";\nimport type { WebSocketGatewayOptions, GatewayClass } from \"./types.js\";\n\n/** Adapter that wires `@WebSocketGateway` classes to a `ws.WebSocketServer`. */\nexport class NodeWsAdapter {\n\treadonly service: WebSocketService;\n\tprivate readonly options: WebSocketGatewayOptions;\n\n\tconstructor(service: WebSocketService, options: WebSocketGatewayOptions = {}) {\n\t\tthis.service = service;\n\t\tthis.options = options;\n\t}\n\n\t/**\n\t * Create a `WebSocketServer` that upgrades at the given gateway\n\t * paths. The user is responsible for binding it to an HTTP\n\t * server.\n\t */\n\tasync bind(gateways: GatewayClass[]): Promise<NodeWsServer> {\n\t\t// Lazy-import `ws` to keep Bun builds clean.\n\t\tlet WS: typeof import(\"ws\");\n\t\ttry {\n\t\t\tWS = (await import(\"ws\")).default ? await import(\"ws\") : (await import(\"ws\"));\n\t\t\t// @ts-ignore - ws exports shape varies\n\t\t\tconst WebSocketServer = (WS as any).WebSocketServer ?? (WS as any).Server ?? (WS as any).default?.WebSocketServer;\n\t\t\tif (!WebSocketServer) throw new Error(\"no WebSocketServer export\");\n\t\t} catch (err) {\n\t\t\tthrow new Error(\n\t\t\t\t\"WebSocketModule.forRoot() on Node requires the `ws` package. \" +\n\t\t\t\t\t\"Install with: bun add ws\",\n\t\t\t);\n\t\t}\n\n\t\t// Build the per-path upgrade handlers map.\n\t\tconst handlers = new Map<string, (req: any) => boolean>();\n\t\tconst gatewayInstances = new Map<string, GatewayClass>();\n\t\tfor (const Gateway of gateways) {\n\t\t\tconst path = getGatewayPath(Gateway.prototype);\n\t\t\tif (!path) continue;\n\t\t\tgatewayInstances.set(path, Gateway);\n\t\t\thandlers.set(path, (req: any) => {\n\t\t\t\tconst url = new URL(req.url ?? \"/\", \"http://localhost\");\n\t\t\t\treturn url.pathname === path;\n\t\t\t});\n\t\t}\n\n\t\t// @ts-ignore - WS is dynamically imported\n\t\tconst wss = new (WS as any).WebSocketServer({ noServer: true });\n\t\tconst opts = this.options;\n\t\tconst service = this.service;\n\n\t\twss.on(\"connection\", (ws: any, req: any) => {\n\t\t\tconst url = new URL(req.url ?? \"/\", \"http://localhost\");\n\t\t\tconst path = url.pathname;\n\t\t\tconst Gateway = gatewayInstances.get(path);\n\t\t\tif (!Gateway) {\n\t\t\t\tws.close(1008, \"Unknown path\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst gateway = new Gateway();\n\t\t\tif (gateway && \"setService\" in (gateway as any) && typeof (gateway as any).setService === \"function\") {\n\t\t\t\t(gateway as any).setService(service);\n\t\t\t}\n\t\t\tconst client = new WebSocketClientImpl(adaptUnderlying(ws, req));\n\t\t\tservice.register(client);\n\t\t\t(opts.onOpen ?? (() => {}))(client);\n\n\t\t\tconst handlers = getLifecycleHandlers(Gateway.prototype);\n\n\t\t\tws.on(\"message\", (data: any) => {\n\t\t\t\tconst parsed = this.parseMessage(data);\n\t\t\t\tif (handlers.message) {\n\t\t\t\t\tPromise.resolve((gateway as any)[handlers.message](client, parsed)).catch(\n\t\t\t\t\t\t(err) => opts.onError?.(client, err as Error),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tws.on(\"close\", (code: number, reasonBuf: any) => {\n\t\t\t\tconst reason = reasonBuf?.toString?.() ?? \"\";\n\t\t\t\tservice.unregister(client);\n\t\t\t\t(opts.onClose ?? (() => {}))(client, code, reason);\n\t\t\t\tif (handlers.close) {\n\t\t\t\t\tPromise.resolve((gateway as any)[handlers.close](client, code, reason)).catch(\n\t\t\t\t\t\t(err) => opts.onError?.(client, err as Error),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tws.on(\"error\", (err: Error) => {\n\t\t\t\tif (handlers.error) {\n\t\t\t\t\tPromise.resolve((gateway as any)[handlers.error](client, err)).catch(() => {});\n\t\t\t\t} else {\n\t\t\t\t\topts.onError?.(client, err);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\treturn {\n\t\t\thandleUpgrade(req: any, socket: any, head: any, callback?: (ws: any) => void) {\n\t\t\t\tconst url = new URL(req.url ?? \"/\", \"http://localhost\");\n\t\t\t\tconst handler = handlers.get(url.pathname);\n\t\t\t\tif (!handler || !handler(req)) {\n\t\t\t\t\tsocket.write(\"HTTP/1.1 404 Not Found\\r\\n\\r\\n\");\n\t\t\t\t\tsocket.destroy();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\twss.handleUpgrade(req, socket, head, callback ?? (() => {}));\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate parseMessage(raw: unknown): unknown {\n\t\tif (this.options.json === false) return raw;\n\t\tif (typeof raw === \"string\") {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(raw);\n\t\t\t} catch {\n\t\t\t\treturn raw;\n\t\t\t}\n\t\t}\n\t\tif (raw && typeof raw === \"object\" && \"toString\" in raw) {\n\t\t\t// ws sometimes gives Buffer\n\t\t\tconst s = (raw as any).toString();\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(s);\n\t\t\t} catch {\n\t\t\t\treturn s;\n\t\t\t}\n\t\t}\n\t\treturn raw;\n\t}\n}\n\n/** Adapts a `ws.WebSocket` to the `UnderlyingWs` interface. */\nfunction adaptUnderlying(ws: any, req: any) {\n\treturn {\n\t\tsend(data: string | ArrayBuffer | Uint8Array, _options?: { compress?: boolean }) {\n\t\t\t// ws accepts string | Buffer | ArrayBuffer | Buffer[]\n\t\t\tws.send(data as any);\n\t\t},\n\t\tclose(code?: number, reason?: string) {\n\t\t\tws.close(code, reason);\n\t\t},\n\t\tget readyState() {\n\t\t\treturn ws.readyState;\n\t\t},\n\t\tget url() {\n\t\t\treturn req.url ?? null;\n\t\t},\n\t\tget protocol() {\n\t\t\treturn ws.protocol ?? null;\n\t\t},\n\t};\n}\n\n/** A handle to attach the WS upgrade to a Node HTTP server. */\nexport interface NodeWsServer {\n\thandleUpgrade(req: any, socket: any, head: any, callback?: (ws: any) => void): void;\n}\n"
10
+ "/**\n * Bun runtime adapter for `@nexusts/ws`.\n *\n * Uses Hono's `createBunWebSocket` to bridge Hono's `WSEvents`\n * to Bun's native WebSocket API.\n *\n * The user wires the returned `websocket` config into\n * `Bun.serve({ websocket, fetch: app.fetch })`. The framework\n * also calls `Bun.serve` automatically if `serve` is provided\n * to `WebSocketModule.forRoot({ serve: { port: 3000 } })`.\n */\n\nimport type { Hono } from \"hono\";\nimport { getGatewayPath, getLifecycleHandlers } from \"../decorators.js\";\nimport type { WebSocketService } from \"../service.js\";\nimport { WebSocketClientImpl } from \"../client.js\";\nimport type { WebSocketGatewayOptions, GatewayClass } from \"./types.js\";\n\n/** Adapter that wires `@WebSocketGateway` classes to Bun's WebSocket. */\nexport class BunWsAdapter {\n\treadonly service: WebSocketService;\n\tprivate readonly options: WebSocketGatewayOptions;\n\n\tconstructor(service: WebSocketService, options: WebSocketGatewayOptions = {}) {\n\t\tthis.service = service;\n\t\tthis.options = options;\n\t}\n\n\t/**\n\t * Returns the `websocket` config object that the user passes to\n\t * `Bun.serve({ websocket, fetch: app.fetch })`.\n\t *\n\t * The `upgradeWebSocket` middleware is also installed on the\n\t * Hono app at every registered gateway's path.\n\t */\n\tasync install(app: Hono, gateways: GatewayClass[]): Promise<{ websocket: BunWebSocketConfig }> {\n\t\t// Lazy-import Hono's Bun adapter to keep Node builds from breaking.\n\t\t// @ts-ignore - bun adapter is Bun-only\n\t\tconst { createBunWebSocket } = await import(\"hono/bun\");\n\t\tconst { upgradeWebSocket, websocket } = createBunWebSocket();\n\n\t\tfor (const Gateway of gateways) {\n\t\t\tconst path = getGatewayPath(Gateway.prototype);\n\t\t\tif (!path) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`WebSocket gateway ${Gateway.name} is missing @WebSocketGateway(path)`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst handlers = getLifecycleHandlers(Gateway.prototype);\n\t\t\tconst opts = this.options;\n\n\t\t\tapp.get(\n\t\t\t\tpath,\n\t\t\t\tupgradeWebSocket((_c: unknown) => {\n\t\t\t\t\t// Build the gateway instance per-connection. (DI happens\n\t\t\t\t\t// via the service — the gateway pulls dependencies from\n\t\t\t\t\t// the container through the service.)\n\t\t\t\t\tconst gateway = new Gateway();\n\t\t\t\t\t// Inject the service if the gateway has a setter / field.\n\t\t\t\t\tif (gateway && \"setService\" in (gateway as any) && typeof (gateway as any).setService === \"function\") {\n\t\t\t\t\t\t(gateway as any).setService(this.service);\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tonOpen: (_evt: Event, ws: any) => {\n\t\t\t\t\t\t\tconst client = new WebSocketClientImpl(ws);\n\t\t\t\t\t\t\tthis.service.register(client);\n\t\t\t\t\t\t\t(opts.onOpen ?? this.defaultOnOpen)(client);\n\t\t\t\t\t\t\tif (handlers.open) {\n\t\t\t\t\t\t\t\tPromise.resolve((gateway as any)[handlers.open](client)).catch(\n\t\t\t\t\t\t\t\t\t(err) => opts.onError?.(client, err as Error),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonMessage: (evt: MessageEvent, ws: any) => {\n\t\t\t\t\t\t\tconst id = (ws as any).__clientId as string | undefined;\n\t\t\t\t\t\t\tconst client = id ? this.service.getConnection(id) as WebSocketClientImpl | undefined : undefined;\n\t\t\t\t\t\t\tif (!client) return;\n\t\t\t\t\t\t\tconst raw = evt.data;\n\t\t\t\t\t\t\tconst data = this.parseMessage(raw);\n\t\t\t\t\t\t\tif (handlers.message) {\n\t\t\t\t\t\t\t\tPromise.resolve((gateway as any)[handlers.message](client, data)).catch(\n\t\t\t\t\t\t\t\t\t(err) => opts.onError?.(client, err as Error),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonClose: (evt: CloseEvent, ws: any) => {\n\t\t\t\t\t\t\tconst id = (ws as any).__clientId as string | undefined;\n\t\t\t\t\t\t\tconst client = id ? this.service.getConnection(id) as WebSocketClientImpl | undefined : undefined;\n\t\t\t\t\t\t\tif (!client) return;\n\t\t\t\t\t\t\tthis.service.unregister(client);\n\t\t\t\t\t\t\t(opts.onClose ?? this.defaultOnClose)(client, evt.code, evt.reason);\n\t\t\t\t\t\t\tif (handlers.close) {\n\t\t\t\t\t\t\t\tPromise.resolve((gateway as any)[handlers.close](client, evt.code, evt.reason)).catch(\n\t\t\t\t\t\t\t\t\t(err) => opts.onError?.(client, err as Error),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonError: (evt: Event, ws: any) => {\n\t\t\t\t\t\t\tconst id = (ws as any).__clientId as string | undefined;\n\t\t\t\t\t\t\tconst client = id ? this.service.getConnection(id) as WebSocketClientImpl | undefined : undefined;\n\t\t\t\t\t\t\tif (!client) return;\n\t\t\t\t\t\t\tconst err = (evt as any).error ?? new Error(\"WebSocket error\");\n\t\t\t\t\t\t\tif (handlers.error) {\n\t\t\t\t\t\t\t\tPromise.resolve((gateway as any)[handlers.error](client, err)).catch(() => {});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\topts.onError?.(client, err);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\treturn { websocket };\n\t}\n\n\tprivate parseMessage(raw: unknown): unknown {\n\t\tif (this.options.json === false) return raw;\n\t\tif (typeof raw === \"string\") {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(raw);\n\t\t\t} catch {\n\t\t\t\treturn raw;\n\t\t\t}\n\t\t}\n\t\treturn raw;\n\t}\n\n\tprivate defaultOnOpen(_client: any): void {}\n\tprivate defaultOnClose(_client: any, _code: number, _reason: string): void {}\n}\n\n\n/** Bun's `websocket` config shape (subset we use). */\nexport interface BunWebSocketConfig {\n\topen?: (ws: any) => void;\n\tmessage?: (ws: any, message: any) => void;\n\tclose?: (ws: any, code: number, reason: string) => void;\n\terror?: (ws: any, error: Error) => void;\n\t// ... other Bun WS options\n}\n",
11
+ "/**\n * Node runtime adapter for `@nexusts/ws`.\n *\n * Uses the `ws` package directly. The user provides a\n * `WebSocketServer` (or one is created automatically) and the\n * framework wires connection events to the gateway's lifecycle\n * handlers.\n *\n * The `ws` package is an optional peer dependency. Apps targeting\n * Bun don't need to install it.\n *\n * Usage (with auto-server):\n *\n * const mod = WebSocketModule.forRoot({ path: '/ws' });\n * const { app, wsServer } = await mod.mountNode(gateways);\n * const server = createServer(app.fetch);\n * server.listen(3000);\n * wsServer.emit('connection', ws, req); // via the framework\n *\n * Usage (with existing `http.Server`):\n *\n * const server = http.createServer(app.fetch);\n * const wss = new WebSocketServer({ server });\n * mod.bindNode(wss, gateways);\n * server.listen(3000);\n */\n\nimport type { Hono } from \"hono\";\nimport { getGatewayPath, getLifecycleHandlers } from \"../decorators.js\";\nimport type { WebSocketService } from \"../service.js\";\nimport { WebSocketClientImpl } from \"../client.js\";\nimport type { WebSocketGatewayOptions, GatewayClass } from \"./types.js\";\n\n/** Adapter that wires `@WebSocketGateway` classes to a `ws.WebSocketServer`. */\nexport class NodeWsAdapter {\n\treadonly service: WebSocketService;\n\tprivate readonly options: WebSocketGatewayOptions;\n\n\tconstructor(service: WebSocketService, options: WebSocketGatewayOptions = {}) {\n\t\tthis.service = service;\n\t\tthis.options = options;\n\t}\n\n\t/**\n\t * Create a `WebSocketServer` that upgrades at the given gateway\n\t * paths. The user is responsible for binding it to an HTTP\n\t * server.\n\t */\n\tasync bind(gateways: GatewayClass[]): Promise<NodeWsServer> {\n\t\t// Lazy-import `ws` to keep Bun builds clean.\n\t\tlet WS: typeof import(\"ws\");\n\t\ttry {\n\t\t\tWS = (await import(\"ws\")).default ? await import(\"ws\") : (await import(\"ws\"));\n\t\t\t// @ts-ignore - ws exports shape varies\n\t\t\tconst WebSocketServer = (WS as any).WebSocketServer ?? (WS as any).Server ?? (WS as any).default?.WebSocketServer;\n\t\t\tif (!WebSocketServer) throw new Error(\"no WebSocketServer export\");\n\t\t} catch (err) {\n\t\t\tthrow new Error(\n\t\t\t\t\"WebSocketModule.forRoot() on Node requires the `ws` package. \" +\n\t\t\t\t\t\"Install with: bun add ws\",\n\t\t\t);\n\t\t}\n\n\t\t// Build the per-path upgrade handlers map.\n\t\tconst handlers = new Map<string, (req: any) => boolean>();\n\t\tconst gatewayInstances = new Map<string, GatewayClass>();\n\t\tfor (const Gateway of gateways) {\n\t\t\tconst path = getGatewayPath(Gateway.prototype);\n\t\t\tif (!path) continue;\n\t\t\tgatewayInstances.set(path, Gateway);\n\t\t\thandlers.set(path, (req: any) => {\n\t\t\t\tconst url = new URL(req.url ?? \"/\", \"http://localhost\");\n\t\t\t\treturn url.pathname === path;\n\t\t\t});\n\t\t}\n\n\t\t// @ts-ignore - WS is dynamically imported\n\t\tconst wss = new (WS as any).WebSocketServer({ noServer: true });\n\t\tconst opts = this.options;\n\t\tconst service = this.service;\n\n\t\twss.on(\"connection\", (ws: any, req: any) => {\n\t\t\tconst url = new URL(req.url ?? \"/\", \"http://localhost\");\n\t\t\tconst path = url.pathname;\n\t\t\tconst Gateway = gatewayInstances.get(path);\n\t\t\tif (!Gateway) {\n\t\t\t\tws.close(1008, \"Unknown path\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst gateway = new Gateway();\n\t\t\tif (gateway && \"setService\" in (gateway as any) && typeof (gateway as any).setService === \"function\") {\n\t\t\t\t(gateway as any).setService(service);\n\t\t\t}\n\t\t\tconst client = new WebSocketClientImpl(adaptUnderlying(ws, req));\n\t\t\tservice.register(client);\n\t\t\t(opts.onOpen ?? (() => {}))(client);\n\n\t\t\tconst handlers = getLifecycleHandlers(Gateway.prototype);\n\n\t\t\tws.on(\"message\", (data: any) => {\n\t\t\t\tconst parsed = this.parseMessage(data);\n\t\t\t\tif (handlers.message) {\n\t\t\t\t\tPromise.resolve((gateway as any)[handlers.message](client, parsed)).catch(\n\t\t\t\t\t\t(err) => opts.onError?.(client, err as Error),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tws.on(\"close\", (code: number, reasonBuf: any) => {\n\t\t\t\tconst reason = reasonBuf?.toString?.() ?? \"\";\n\t\t\t\tservice.unregister(client);\n\t\t\t\t(opts.onClose ?? (() => {}))(client, code, reason);\n\t\t\t\tif (handlers.close) {\n\t\t\t\t\tPromise.resolve((gateway as any)[handlers.close](client, code, reason)).catch(\n\t\t\t\t\t\t(err) => opts.onError?.(client, err as Error),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tws.on(\"error\", (err: Error) => {\n\t\t\t\tif (handlers.error) {\n\t\t\t\t\tPromise.resolve((gateway as any)[handlers.error](client, err)).catch(() => {});\n\t\t\t\t} else {\n\t\t\t\t\topts.onError?.(client, err);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\treturn {\n\t\t\thandleUpgrade(req: any, socket: any, head: any, callback?: (ws: any) => void) {\n\t\t\t\tconst url = new URL(req.url ?? \"/\", \"http://localhost\");\n\t\t\t\tconst handler = handlers.get(url.pathname);\n\t\t\t\tif (!handler || !handler(req)) {\n\t\t\t\t\tsocket.write(\"HTTP/1.1 404 Not Found\\r\\n\\r\\n\");\n\t\t\t\t\tsocket.destroy();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\twss.handleUpgrade(req, socket, head, callback ?? (() => {}));\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate parseMessage(raw: unknown): unknown {\n\t\tif (this.options.json === false) return raw;\n\t\tif (typeof raw === \"string\") {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(raw);\n\t\t\t} catch {\n\t\t\t\treturn raw;\n\t\t\t}\n\t\t}\n\t\tif (raw && typeof raw === \"object\" && \"toString\" in raw) {\n\t\t\t// ws sometimes gives Buffer\n\t\t\tconst s = (raw as any).toString();\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(s);\n\t\t\t} catch {\n\t\t\t\treturn s;\n\t\t\t}\n\t\t}\n\t\treturn raw;\n\t}\n}\n\n/** Adapts a `ws.WebSocket` to the `UnderlyingWs` interface. */\nfunction adaptUnderlying(ws: any, req: any) {\n\treturn {\n\t\tsend(data: string | ArrayBuffer | Uint8Array, _options?: { compress?: boolean }) {\n\t\t\t// ws accepts string | Buffer | ArrayBuffer | Buffer[]\n\t\t\tws.send(data as any);\n\t\t},\n\t\tclose(code?: number, reason?: string) {\n\t\t\tws.close(code, reason);\n\t\t},\n\t\tget readyState() {\n\t\t\treturn ws.readyState;\n\t\t},\n\t\tget url() {\n\t\t\treturn req.url ?? null;\n\t\t},\n\t\tget protocol() {\n\t\t\treturn ws.protocol ?? null;\n\t\t},\n\t};\n}\n\n/** A handle to attach the WS upgrade to a Node HTTP server. */\nexport interface NodeWsServer {\n\thandleUpgrade(req: any, socket: any, head: any, callback?: (ws: any) => void): void;\n}\n"
12
12
  ],
13
13
  "mappings": "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",
14
14
  "debugId": "C3F476FBC2F288E464756E2164756E21",
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Bun runtime adapter for `nexusjs/ws`.
2
+ * Bun runtime adapter for `@nexusts/ws`.
3
3
  *
4
4
  * Uses Hono's `createBunWebSocket` to bridge Hono's `WSEvents`
5
5
  * to Bun's native WebSocket API.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Runtime detection & helper for `nexusjs/ws`.
2
+ * Runtime detection & helper for `@nexusts/ws`.
3
3
  */
4
4
  export type WsRuntime = "bun" | "node" | "cloudflare" | "unknown";
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Node runtime adapter for `nexusjs/ws`.
2
+ * Node runtime adapter for `@nexusts/ws`.
3
3
  *
4
4
  * Uses the `ws` package directly. The user provides a
5
5
  * `WebSocketServer` (or one is created automatically) and the
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Runtime adapter types for `nexusjs/ws`.
2
+ * Runtime adapter types for `@nexusts/ws`.
3
3
  */
4
4
  import type { WebSocketClient } from "../types.js";
5
5
  /** Options shared by all runtime adapters. */
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Public types for `nexusjs/ws`.
2
+ * Public types for `@nexusts/ws`.
3
3
  *
4
- * `nexusjs/ws` is a thin abstraction over Hono's runtime-specific
4
+ * `@nexusts/ws` is a thin abstraction over Hono's runtime-specific
5
5
  * WebSocket support. The same `@WebSocketGateway` / `@OnWebSocketMessage`
6
6
  * pattern works on Bun (via `hono/adapter/bun/websocket`) and Node
7
7
  * (via the `ws` package).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexusts/ws",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "WebSockets (Bun native, Node fallback via ws)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -34,7 +34,7 @@
34
34
  }
35
35
  },
36
36
  "dependencies": {
37
- "@nexusts/core": "^0.9.0"
37
+ "@nexusts/core": "^0.9.1"
38
38
  },
39
39
  "repository": {
40
40
  "type": "git",