@kyneta/websocket-transport 1.3.1 → 1.5.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/dist/browser.d.ts CHANGED
@@ -1,50 +1,50 @@
1
- import { Program } from '@kyneta/machine';
2
- import { ReconnectOptions } from '@kyneta/transport';
3
- import { W as WebsocketClientState } from './types-D0lbeevu.js';
4
- export { D as DisconnectReason, R as READY_STATE, S as Socket, a as SocketReadyState, T as TransitionListener, b as WebSocketCloseEvent, c as WebSocketConstructor, d as WebSocketLike, e as WebSocketMessageEvent, f as WebsocketClientStateTransition } from './types-D0lbeevu.js';
5
- export { D as DEFAULT_FRAGMENT_THRESHOLD, W as WebsocketClientLifecycleEvents, a as WebsocketClientOptions, b as WebsocketClientTransport, c as createWebsocketClient } from './client-transport-DUAFjVbh.js';
1
+ import { a as SocketReadyState, c as WebSocketConstructor, d as WebsocketClientState, f as WebsocketClientStateTransition, i as Socket, l as WebSocketLike, o as TransitionListener, r as READY_STATE, s as WebSocketCloseEvent, t as DisconnectReason, u as WebSocketMessageEvent } from "./types-c1S_xIRG.js";
2
+ import { a as createWebsocketClient, i as WebsocketClientTransport, n as WebsocketClientLifecycleEvents, r as WebsocketClientOptions, t as DEFAULT_FRAGMENT_THRESHOLD } from "./client-transport-D3tYQYrS.js";
3
+ import { ReconnectOptions } from "@kyneta/transport";
4
+ import { Program } from "@kyneta/machine";
6
5
 
6
+ //#region src/client-program.d.ts
7
7
  type WsClientMsg = {
8
- type: "start";
8
+ type: "start";
9
9
  } | {
10
- type: "socket-opened";
10
+ type: "socket-opened";
11
11
  } | {
12
- type: "server-ready";
12
+ type: "server-ready";
13
13
  } | {
14
- type: "socket-closed";
15
- code: number;
16
- reason: string;
14
+ type: "socket-closed";
15
+ code: number;
16
+ reason: string;
17
17
  } | {
18
- type: "socket-error";
19
- error: Error;
18
+ type: "socket-error";
19
+ error: Error;
20
20
  } | {
21
- type: "reconnect-timer-fired";
21
+ type: "reconnect-timer-fired";
22
22
  } | {
23
- type: "stop";
23
+ type: "stop";
24
24
  };
25
25
  type WsClientEffect = {
26
- type: "create-websocket";
27
- attempt: number;
26
+ type: "create-websocket";
27
+ attempt: number;
28
28
  } | {
29
- type: "close-websocket";
29
+ type: "close-websocket";
30
30
  } | {
31
- type: "add-channel-and-establish";
31
+ type: "add-channel-and-establish";
32
32
  } | {
33
- type: "remove-channel";
33
+ type: "remove-channel";
34
34
  } | {
35
- type: "start-reconnect-timer";
36
- delayMs: number;
35
+ type: "start-reconnect-timer";
36
+ delayMs: number;
37
37
  } | {
38
- type: "cancel-reconnect-timer";
38
+ type: "cancel-reconnect-timer";
39
39
  } | {
40
- type: "start-keepalive";
40
+ type: "start-keepalive";
41
41
  } | {
42
- type: "stop-keepalive";
42
+ type: "stop-keepalive";
43
43
  };
44
44
  interface WsClientProgramOptions {
45
- reconnect?: Partial<ReconnectOptions>;
46
- /** Inject jitter source for deterministic testing. Default: () => Math.random() * 1000 */
47
- jitterFn?: () => number;
45
+ reconnect?: Partial<ReconnectOptions>;
46
+ /** Inject jitter source for deterministic testing. Default: () => Math.random() * 1000 */
47
+ jitterFn?: () => number;
48
48
  }
49
49
  /**
50
50
  * Create the websocket client connection lifecycle program — a pure Mealy machine.
@@ -54,5 +54,6 @@ interface WsClientProgramOptions {
54
54
  * shell interprets `WsClientEffect` as actual I/O.
55
55
  */
56
56
  declare function createWsClientProgram(options?: WsClientProgramOptions): Program<WsClientMsg, WebsocketClientState, WsClientEffect>;
57
-
58
- export { WebsocketClientState, type WsClientEffect, type WsClientMsg, type WsClientProgramOptions, createWsClientProgram };
57
+ //#endregion
58
+ export { DEFAULT_FRAGMENT_THRESHOLD, type DisconnectReason, READY_STATE, type Socket, type SocketReadyState, type TransitionListener, type WebSocketCloseEvent, type WebSocketConstructor, type WebSocketLike, type WebSocketMessageEvent, type WebsocketClientLifecycleEvents, type WebsocketClientOptions, type WebsocketClientState, type WebsocketClientStateTransition, WebsocketClientTransport, type WsClientEffect, type WsClientMsg, type WsClientProgramOptions, createWebsocketClient, createWsClientProgram };
59
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","names":[],"sources":["../src/client-program.ts"],"mappings":";;;;;;KA4BY,WAAA;EACN,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;EAAuB,IAAA;EAAc,MAAA;AAAA;EACrC,IAAA;EAAsB,KAAA,EAAO,KAAA;AAAA;EAC7B,IAAA;AAAA;EACA,IAAA;AAAA;AAAA,KAMM,cAAA;EACN,IAAA;EAA0B,OAAA;AAAA;EAC1B,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;EAA+B,OAAA;AAAA;EAC/B,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;AAAA;AAAA,UAMW,sBAAA;EACf,SAAA,GAAY,OAAA,CAAQ,gBAAA;EAAD;EAEnB,QAAA;AAAA;;;;;AAUF;;;iBAAgB,qBAAA,CACd,OAAA,GAAS,sBAAA,GACR,OAAA,CAAQ,WAAA,EAAa,oBAAA,EAAsB,cAAA"}
package/dist/browser.js CHANGED
@@ -1,15 +1,2 @@
1
- import {
2
- DEFAULT_FRAGMENT_THRESHOLD,
3
- READY_STATE,
4
- WebsocketClientTransport,
5
- createWebsocketClient,
6
- createWsClientProgram
7
- } from "./chunk-YZQF5RLV.js";
8
- export {
9
- DEFAULT_FRAGMENT_THRESHOLD,
10
- READY_STATE,
11
- WebsocketClientTransport,
12
- createWebsocketClient,
13
- createWsClientProgram
14
- };
15
- //# sourceMappingURL=browser.js.map
1
+ import { i as READY_STATE, n as WebsocketClientTransport, r as createWebsocketClient, s as createWsClientProgram, t as DEFAULT_FRAGMENT_THRESHOLD } from "./client-transport-B2V7s2VP.js";
2
+ export { DEFAULT_FRAGMENT_THRESHOLD, READY_STATE, WebsocketClientTransport, createWebsocketClient, createWsClientProgram };
package/dist/bun.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- import { ServerWebSocket } from 'bun';
2
- import { S as Socket } from './types-D0lbeevu.js';
3
- export { D as DisconnectReason, a as SocketReadyState } from './types-D0lbeevu.js';
4
- import '@kyneta/transport';
1
+ import { a as SocketReadyState, i as Socket, t as DisconnectReason } from "./types-c1S_xIRG.js";
2
+ import { ServerWebSocket } from "bun";
5
3
 
4
+ //#region src/bun-websocket.d.ts
6
5
  /**
7
6
  * Data structure stored in `ws.data` for handler callbacks.
8
7
  * Use this type when defining your `Bun.serve()` generic.
@@ -15,10 +14,10 @@ import '@kyneta/transport';
15
14
  * ```
16
15
  */
17
16
  type BunWebsocketData = {
18
- handlers: {
19
- onMessage?: (data: Uint8Array | string) => void;
20
- onClose?: (code: number, reason: string) => void;
21
- };
17
+ handlers: {
18
+ onMessage?: (data: Uint8Array<ArrayBuffer> | string) => void;
19
+ onClose?: (code: number, reason: string) => void;
20
+ };
22
21
  };
23
22
  /**
24
23
  * Wrap Bun's `ServerWebSocket` to match the `Socket` interface.
@@ -77,15 +76,16 @@ declare function wrapBunWebsocket(ws: ServerWebSocket<BunWebsocketData>): Socket
77
76
  * ```
78
77
  */
79
78
  declare function createBunWebsocketHandlers(wsAdapter: {
80
- handleConnection: (opts: {
81
- socket: Socket;
82
- }) => {
83
- start: () => void;
84
- };
79
+ handleConnection: (opts: {
80
+ socket: Socket;
81
+ }) => {
82
+ start: () => void;
83
+ };
85
84
  }): {
86
- open(ws: ServerWebSocket<BunWebsocketData>): void;
87
- message(ws: ServerWebSocket<BunWebsocketData>, msg: string | ArrayBuffer | Buffer): void;
88
- close(ws: ServerWebSocket<BunWebsocketData>, code: number, reason: string): void;
85
+ open(ws: ServerWebSocket<BunWebsocketData>): void;
86
+ message(ws: ServerWebSocket<BunWebsocketData>, msg: string | ArrayBuffer | Buffer): void;
87
+ close(ws: ServerWebSocket<BunWebsocketData>, code: number, reason: string): void;
89
88
  };
90
-
91
- export { type BunWebsocketData, Socket, createBunWebsocketHandlers, wrapBunWebsocket };
89
+ //#endregion
90
+ export { type BunWebsocketData, type DisconnectReason, type Socket, type SocketReadyState, createBunWebsocketHandlers, wrapBunWebsocket };
91
+ //# sourceMappingURL=bun.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bun.d.ts","names":[],"sources":["../src/bun-websocket.ts"],"mappings":";;;;;;AA+BA;;;;;;;;;KAAY,gBAAA;EACV,QAAA;IACE,SAAA,IAAa,IAAA,EAAM,UAAA,CAAW,WAAA;IAC9B,OAAA,IAAW,IAAA,UAAc,MAAA;EAAA;AAAA;;;;;;;;;;;;;;AAyG7B;;;;;;;;;;;;;;;;;;;iBAjEgB,gBAAA,CACd,EAAA,EAAI,eAAA,CAAgB,gBAAA,IACnB,MAAA;;;;;;;;;;;;;;;;;;;;;;;;iBA+Da,0BAAA,CAA2B,SAAA;EACzC,gBAAA,GAAmB,IAAA;IAAQ,MAAA,EAAQ,MAAA;EAAA;IAAe,KAAA;EAAA;AAAA;WAGvC,eAAA,CAAgB,gBAAA;cAInB,eAAA,CAAgB,gBAAA,GAAiB,GAAA,WACvB,WAAA,GAAc,MAAA;YAUpB,eAAA,CAAgB,gBAAA,GAAiB,IAAA,UAAc,MAAA;AAAA"}
package/dist/bun.js CHANGED
@@ -1,48 +1,100 @@
1
- // src/bun-websocket.ts
1
+ //#region src/bun-websocket.ts
2
+ /**
3
+ * Wrap Bun's `ServerWebSocket` to match the `Socket` interface.
4
+ *
5
+ * Bun's WebSocket API uses server-level callbacks (`websocket: { message, close }`)
6
+ * rather than per-socket event handlers. This wrapper bridges that gap by
7
+ * storing handlers in `ws.data` and having the server-level callbacks delegate
8
+ * to them.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { WebsocketServerTransport } from "@kyneta/websocket-transport/server"
13
+ * import { wrapBunWebsocket, type BunWebsocketData } from "@kyneta/websocket-transport/bun"
14
+ *
15
+ * const serverAdapter = new WebsocketServerTransport()
16
+ *
17
+ * Bun.serve<BunWebsocketData>({
18
+ * websocket: {
19
+ * open(ws) {
20
+ * const socket = wrapBunWebsocket(ws)
21
+ * serverAdapter.handleConnection({ socket }).start()
22
+ * },
23
+ * message(ws, msg) {
24
+ * const data = msg instanceof ArrayBuffer ? new Uint8Array(msg) : msg
25
+ * ws.data?.handlers?.onMessage?.(data)
26
+ * },
27
+ * close(ws, code, reason) {
28
+ * ws.data?.handlers?.onClose?.(code, reason)
29
+ * },
30
+ * },
31
+ * })
32
+ * ```
33
+ */
2
34
  function wrapBunWebsocket(ws) {
3
- ws.data = { handlers: {} };
4
- return {
5
- send(data) {
6
- ws.send(data);
7
- },
8
- close(code, reason) {
9
- ws.close(code, reason);
10
- },
11
- onMessage(handler) {
12
- ws.data.handlers.onMessage = handler;
13
- },
14
- onClose(handler) {
15
- ws.data.handlers.onClose = handler;
16
- },
17
- onError(_handler) {
18
- },
19
- get readyState() {
20
- const states = [
21
- "connecting",
22
- "open",
23
- "closing",
24
- "closed"
25
- ];
26
- return states[ws.readyState] ?? "closed";
27
- }
28
- };
35
+ ws.data = { handlers: {} };
36
+ return {
37
+ send(data) {
38
+ ws.send(data);
39
+ },
40
+ close(code, reason) {
41
+ ws.close(code, reason);
42
+ },
43
+ onMessage(handler) {
44
+ ws.data.handlers.onMessage = handler;
45
+ },
46
+ onClose(handler) {
47
+ ws.data.handlers.onClose = handler;
48
+ },
49
+ onError(_handler) {},
50
+ get readyState() {
51
+ return [
52
+ "connecting",
53
+ "open",
54
+ "closing",
55
+ "closed"
56
+ ][ws.readyState] ?? "closed";
57
+ }
58
+ };
29
59
  }
60
+ /**
61
+ * Create Bun Websocket handlers that integrate with `WebsocketServerTransport`.
62
+ *
63
+ * This helper eliminates boilerplate by providing pre-configured handlers
64
+ * for `open`, `message`, and `close` events that automatically wire up
65
+ * to the adapter's `handleConnection()` method.
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * import { WebsocketServerTransport } from "@kyneta/websocket-transport/server"
70
+ * import { createBunWebsocketHandlers, type BunWebsocketData } from "@kyneta/websocket-transport/bun"
71
+ *
72
+ * const serverAdapter = new WebsocketServerTransport()
73
+ *
74
+ * Bun.serve<BunWebsocketData>({
75
+ * fetch(req, server) {
76
+ * server.upgrade(req)
77
+ * return new Response("upgrade failed", { status: 400 })
78
+ * },
79
+ * websocket: createBunWebsocketHandlers(serverAdapter),
80
+ * })
81
+ * ```
82
+ */
30
83
  function createBunWebsocketHandlers(wsAdapter) {
31
- return {
32
- open(ws) {
33
- wsAdapter.handleConnection({ socket: wrapBunWebsocket(ws) }).start();
34
- },
35
- message(ws, msg) {
36
- const data = msg instanceof ArrayBuffer ? new Uint8Array(msg) : Buffer.isBuffer(msg) ? new Uint8Array(msg) : msg;
37
- ws.data.handlers.onMessage?.(data);
38
- },
39
- close(ws, code, reason) {
40
- ws.data.handlers.onClose?.(code, reason);
41
- }
42
- };
84
+ return {
85
+ open(ws) {
86
+ wsAdapter.handleConnection({ socket: wrapBunWebsocket(ws) }).start();
87
+ },
88
+ message(ws, msg) {
89
+ const data = msg instanceof ArrayBuffer ? new Uint8Array(msg) : Buffer.isBuffer(msg) ? new Uint8Array(msg) : msg;
90
+ ws.data.handlers.onMessage?.(data);
91
+ },
92
+ close(ws, code, reason) {
93
+ ws.data.handlers.onClose?.(code, reason);
94
+ }
95
+ };
43
96
  }
44
- export {
45
- createBunWebsocketHandlers,
46
- wrapBunWebsocket
47
- };
97
+ //#endregion
98
+ export { createBunWebsocketHandlers, wrapBunWebsocket };
99
+
48
100
  //# sourceMappingURL=bun.js.map
package/dist/bun.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bun-websocket.ts"],"sourcesContent":["// bun-websocket — Bun-specific Websocket wrapper for @kyneta/websocket-transport.\n//\n// Provides a wrapper to adapt Bun's ServerWebSocket to the Socket interface\n// expected by WebsocketServerTransport.\n//\n// Bun's WebSocket API is callback-based at the server level (not per-socket),\n// so we bridge that gap by storing handlers in ws.data.\n//\n// Ported from @loro-extended/adapter-websocket's bun.ts with kyneta\n// naming conventions applied.\n\n/// <reference types=\"bun-types\" />\n\nimport type { ServerWebSocket } from \"bun\"\nimport type { Socket, SocketReadyState } from \"./types.js\"\n\n// ---------------------------------------------------------------------------\n// BunWebsocketData — stored in ws.data for per-socket handler callbacks\n// ---------------------------------------------------------------------------\n\n/**\n * Data structure stored in `ws.data` for handler callbacks.\n * Use this type when defining your `Bun.serve()` generic.\n *\n * @example\n * ```typescript\n * Bun.serve<BunWebsocketData>({\n * websocket: { ... }\n * })\n * ```\n */\nexport type BunWebsocketData = {\n handlers: {\n onMessage?: (data: Uint8Array | string) => void\n onClose?: (code: number, reason: string) => void\n }\n}\n\n// ---------------------------------------------------------------------------\n// wrapBunWebsocket\n// ---------------------------------------------------------------------------\n\n/**\n * Wrap Bun's `ServerWebSocket` to match the `Socket` interface.\n *\n * Bun's WebSocket API uses server-level callbacks (`websocket: { message, close }`)\n * rather than per-socket event handlers. This wrapper bridges that gap by\n * storing handlers in `ws.data` and having the server-level callbacks delegate\n * to them.\n *\n * @example\n * ```typescript\n * import { WebsocketServerTransport } from \"@kyneta/websocket-transport/server\"\n * import { wrapBunWebsocket, type BunWebsocketData } from \"@kyneta/websocket-transport/bun\"\n *\n * const serverAdapter = new WebsocketServerTransport()\n *\n * Bun.serve<BunWebsocketData>({\n * websocket: {\n * open(ws) {\n * const socket = wrapBunWebsocket(ws)\n * serverAdapter.handleConnection({ socket }).start()\n * },\n * message(ws, msg) {\n * const data = msg instanceof ArrayBuffer ? new Uint8Array(msg) : msg\n * ws.data?.handlers?.onMessage?.(data)\n * },\n * close(ws, code, reason) {\n * ws.data?.handlers?.onClose?.(code, reason)\n * },\n * },\n * })\n * ```\n */\nexport function wrapBunWebsocket(\n ws: ServerWebSocket<BunWebsocketData>,\n): Socket {\n ws.data = { handlers: {} }\n\n return {\n send(data: Uint8Array | string): void {\n ws.send(data)\n },\n\n close(code?: number, reason?: string): void {\n ws.close(code, reason)\n },\n\n onMessage(handler: (data: Uint8Array | string) => void): void {\n ws.data.handlers.onMessage = handler\n },\n\n onClose(handler: (code: number, reason: string) => void): void {\n ws.data.handlers.onClose = handler\n },\n\n onError(_handler: (error: Error) => void): void {\n // Bun handles errors at the server level, not per-socket\n },\n\n get readyState(): SocketReadyState {\n const states: SocketReadyState[] = [\n \"connecting\",\n \"open\",\n \"closing\",\n \"closed\",\n ]\n return states[ws.readyState] ?? \"closed\"\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// createBunWebsocketHandlers\n// ---------------------------------------------------------------------------\n\n/**\n * Create Bun Websocket handlers that integrate with `WebsocketServerTransport`.\n *\n * This helper eliminates boilerplate by providing pre-configured handlers\n * for `open`, `message`, and `close` events that automatically wire up\n * to the adapter's `handleConnection()` method.\n *\n * @example\n * ```typescript\n * import { WebsocketServerTransport } from \"@kyneta/websocket-transport/server\"\n * import { createBunWebsocketHandlers, type BunWebsocketData } from \"@kyneta/websocket-transport/bun\"\n *\n * const serverAdapter = new WebsocketServerTransport()\n *\n * Bun.serve<BunWebsocketData>({\n * fetch(req, server) {\n * server.upgrade(req)\n * return new Response(\"upgrade failed\", { status: 400 })\n * },\n * websocket: createBunWebsocketHandlers(serverAdapter),\n * })\n * ```\n */\nexport function createBunWebsocketHandlers(wsAdapter: {\n handleConnection: (opts: { socket: Socket }) => { start: () => void }\n}) {\n return {\n open(ws: ServerWebSocket<BunWebsocketData>) {\n wsAdapter.handleConnection({ socket: wrapBunWebsocket(ws) }).start()\n },\n message(\n ws: ServerWebSocket<BunWebsocketData>,\n msg: string | ArrayBuffer | Buffer,\n ) {\n const data =\n msg instanceof ArrayBuffer\n ? new Uint8Array(msg)\n : Buffer.isBuffer(msg)\n ? new Uint8Array(msg)\n : msg\n ws.data.handlers.onMessage?.(data)\n },\n close(ws: ServerWebSocket<BunWebsocketData>, code: number, reason: string) {\n ws.data.handlers.onClose?.(code, reason)\n },\n }\n}\n"],"mappings":";AA0EO,SAAS,iBACd,IACQ;AACR,KAAG,OAAO,EAAE,UAAU,CAAC,EAAE;AAEzB,SAAO;AAAA,IACL,KAAK,MAAiC;AACpC,SAAG,KAAK,IAAI;AAAA,IACd;AAAA,IAEA,MAAM,MAAe,QAAuB;AAC1C,SAAG,MAAM,MAAM,MAAM;AAAA,IACvB;AAAA,IAEA,UAAU,SAAoD;AAC5D,SAAG,KAAK,SAAS,YAAY;AAAA,IAC/B;AAAA,IAEA,QAAQ,SAAuD;AAC7D,SAAG,KAAK,SAAS,UAAU;AAAA,IAC7B;AAAA,IAEA,QAAQ,UAAwC;AAAA,IAEhD;AAAA,IAEA,IAAI,aAA+B;AACjC,YAAM,SAA6B;AAAA,QACjC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,OAAO,GAAG,UAAU,KAAK;AAAA,IAClC;AAAA,EACF;AACF;AA6BO,SAAS,2BAA2B,WAExC;AACD,SAAO;AAAA,IACL,KAAK,IAAuC;AAC1C,gBAAU,iBAAiB,EAAE,QAAQ,iBAAiB,EAAE,EAAE,CAAC,EAAE,MAAM;AAAA,IACrE;AAAA,IACA,QACE,IACA,KACA;AACA,YAAM,OACJ,eAAe,cACX,IAAI,WAAW,GAAG,IAClB,OAAO,SAAS,GAAG,IACjB,IAAI,WAAW,GAAG,IAClB;AACR,SAAG,KAAK,SAAS,YAAY,IAAI;AAAA,IACnC;AAAA,IACA,MAAM,IAAuC,MAAc,QAAgB;AACzE,SAAG,KAAK,SAAS,UAAU,MAAM,MAAM;AAAA,IACzC;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"file":"bun.js","names":[],"sources":["../src/bun-websocket.ts"],"sourcesContent":["// bun-websocket — Bun-specific Websocket wrapper for @kyneta/websocket-transport.\n//\n// Provides a wrapper to adapt Bun's ServerWebSocket to the Socket interface\n// expected by WebsocketServerTransport.\n//\n// Bun's WebSocket API is callback-based at the server level (not per-socket),\n// so we bridge that gap by storing handlers in ws.data.\n//\n// Ported from @loro-extended/adapter-websocket's bun.ts with kyneta\n// naming conventions applied.\n\n/// <reference types=\"bun-types\" />\n\nimport type { ServerWebSocket } from \"bun\"\nimport type { Socket, SocketReadyState } from \"./types.js\"\n\n// ---------------------------------------------------------------------------\n// BunWebsocketData — stored in ws.data for per-socket handler callbacks\n// ---------------------------------------------------------------------------\n\n/**\n * Data structure stored in `ws.data` for handler callbacks.\n * Use this type when defining your `Bun.serve()` generic.\n *\n * @example\n * ```typescript\n * Bun.serve<BunWebsocketData>({\n * websocket: { ... }\n * })\n * ```\n */\nexport type BunWebsocketData = {\n handlers: {\n onMessage?: (data: Uint8Array<ArrayBuffer> | string) => void\n onClose?: (code: number, reason: string) => void\n }\n}\n\n// ---------------------------------------------------------------------------\n// wrapBunWebsocket\n// ---------------------------------------------------------------------------\n\n/**\n * Wrap Bun's `ServerWebSocket` to match the `Socket` interface.\n *\n * Bun's WebSocket API uses server-level callbacks (`websocket: { message, close }`)\n * rather than per-socket event handlers. This wrapper bridges that gap by\n * storing handlers in `ws.data` and having the server-level callbacks delegate\n * to them.\n *\n * @example\n * ```typescript\n * import { WebsocketServerTransport } from \"@kyneta/websocket-transport/server\"\n * import { wrapBunWebsocket, type BunWebsocketData } from \"@kyneta/websocket-transport/bun\"\n *\n * const serverAdapter = new WebsocketServerTransport()\n *\n * Bun.serve<BunWebsocketData>({\n * websocket: {\n * open(ws) {\n * const socket = wrapBunWebsocket(ws)\n * serverAdapter.handleConnection({ socket }).start()\n * },\n * message(ws, msg) {\n * const data = msg instanceof ArrayBuffer ? new Uint8Array(msg) : msg\n * ws.data?.handlers?.onMessage?.(data)\n * },\n * close(ws, code, reason) {\n * ws.data?.handlers?.onClose?.(code, reason)\n * },\n * },\n * })\n * ```\n */\nexport function wrapBunWebsocket(\n ws: ServerWebSocket<BunWebsocketData>,\n): Socket {\n ws.data = { handlers: {} }\n\n return {\n send(data: Uint8Array<ArrayBuffer> | string): void {\n ws.send(data)\n },\n\n close(code?: number, reason?: string): void {\n ws.close(code, reason)\n },\n\n onMessage(handler: (data: Uint8Array<ArrayBuffer> | string) => void): void {\n ws.data.handlers.onMessage = handler\n },\n\n onClose(handler: (code: number, reason: string) => void): void {\n ws.data.handlers.onClose = handler\n },\n\n onError(_handler: (error: Error) => void): void {\n // Bun handles errors at the server level, not per-socket\n },\n\n get readyState(): SocketReadyState {\n const states: SocketReadyState[] = [\n \"connecting\",\n \"open\",\n \"closing\",\n \"closed\",\n ]\n return states[ws.readyState] ?? \"closed\"\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// createBunWebsocketHandlers\n// ---------------------------------------------------------------------------\n\n/**\n * Create Bun Websocket handlers that integrate with `WebsocketServerTransport`.\n *\n * This helper eliminates boilerplate by providing pre-configured handlers\n * for `open`, `message`, and `close` events that automatically wire up\n * to the adapter's `handleConnection()` method.\n *\n * @example\n * ```typescript\n * import { WebsocketServerTransport } from \"@kyneta/websocket-transport/server\"\n * import { createBunWebsocketHandlers, type BunWebsocketData } from \"@kyneta/websocket-transport/bun\"\n *\n * const serverAdapter = new WebsocketServerTransport()\n *\n * Bun.serve<BunWebsocketData>({\n * fetch(req, server) {\n * server.upgrade(req)\n * return new Response(\"upgrade failed\", { status: 400 })\n * },\n * websocket: createBunWebsocketHandlers(serverAdapter),\n * })\n * ```\n */\nexport function createBunWebsocketHandlers(wsAdapter: {\n handleConnection: (opts: { socket: Socket }) => { start: () => void }\n}) {\n return {\n open(ws: ServerWebSocket<BunWebsocketData>) {\n wsAdapter.handleConnection({ socket: wrapBunWebsocket(ws) }).start()\n },\n message(\n ws: ServerWebSocket<BunWebsocketData>,\n msg: string | ArrayBuffer | Buffer,\n ) {\n const data =\n msg instanceof ArrayBuffer\n ? new Uint8Array(msg)\n : Buffer.isBuffer(msg)\n ? new Uint8Array(msg)\n : msg\n ws.data.handlers.onMessage?.(data)\n },\n close(ws: ServerWebSocket<BunWebsocketData>, code: number, reason: string) {\n ws.data.handlers.onClose?.(code, reason)\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0EA,SAAgB,iBACd,IACQ;AACR,IAAG,OAAO,EAAE,UAAU,EAAE,EAAE;AAE1B,QAAO;EACL,KAAK,MAA8C;AACjD,MAAG,KAAK,KAAK;;EAGf,MAAM,MAAe,QAAuB;AAC1C,MAAG,MAAM,MAAM,OAAO;;EAGxB,UAAU,SAAiE;AACzE,MAAG,KAAK,SAAS,YAAY;;EAG/B,QAAQ,SAAuD;AAC7D,MAAG,KAAK,SAAS,UAAU;;EAG7B,QAAQ,UAAwC;EAIhD,IAAI,aAA+B;AAOjC,UANmC;IACjC;IACA;IACA;IACA;IACD,CACa,GAAG,eAAe;;EAEnC;;;;;;;;;;;;;;;;;;;;;;;;;AA8BH,SAAgB,2BAA2B,WAExC;AACD,QAAO;EACL,KAAK,IAAuC;AAC1C,aAAU,iBAAiB,EAAE,QAAQ,iBAAiB,GAAG,EAAE,CAAC,CAAC,OAAO;;EAEtE,QACE,IACA,KACA;GACA,MAAM,OACJ,eAAe,cACX,IAAI,WAAW,IAAI,GACnB,OAAO,SAAS,IAAI,GAClB,IAAI,WAAW,IAAI,GACnB;AACR,MAAG,KAAK,SAAS,YAAY,KAAK;;EAEpC,MAAM,IAAuC,MAAc,QAAgB;AACzE,MAAG,KAAK,SAAS,UAAU,MAAM,OAAO;;EAE3C"}