@kyneta/websocket-transport 1.3.0 → 1.4.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 +28 -15
- package/dist/browser.d.ts +59 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +2 -0
- package/dist/bun.d.ts +22 -22
- package/dist/bun.d.ts.map +1 -0
- package/dist/bun.js +95 -43
- package/dist/bun.js.map +1 -1
- package/dist/client-transport-CKjXedwS.d.ts +134 -0
- package/dist/client-transport-CKjXedwS.d.ts.map +1 -0
- package/dist/client-transport-DIZ-LJxs.js +510 -0
- package/dist/client-transport-DIZ-LJxs.js.map +1 -0
- package/dist/server.d.ts +154 -115
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +298 -296
- package/dist/server.js.map +1 -1
- package/dist/types-CJAcr1Df.d.ts +199 -0
- package/dist/types-CJAcr1Df.d.ts.map +1 -0
- package/package.json +15 -15
- package/src/__tests__/client-transport.test.ts +167 -0
- package/src/{client.ts → browser.ts} +15 -10
- package/src/bun-websocket.ts +5 -5
- package/src/bun.ts +1 -1
- package/src/client-transport.ts +42 -67
- package/src/connection.ts +1 -1
- package/src/server-transport.ts +10 -10
- package/src/server.ts +22 -4
- package/src/service-client.ts +52 -0
- package/src/types.ts +74 -6
- package/dist/chunk-PSG3LLT5.js +0 -111
- package/dist/chunk-PSG3LLT5.js.map +0 -1
- package/dist/client.d.ts +0 -207
- package/dist/client.js +0 -508
- package/dist/client.js.map +0 -1
- package/dist/types-DdNb8cAz.d.ts +0 -149
package/dist/server.js
CHANGED
|
@@ -1,304 +1,306 @@
|
|
|
1
|
-
import {
|
|
2
|
-
wrapNodeWebsocket,
|
|
3
|
-
wrapStandardWebsocket
|
|
4
|
-
} from "./chunk-PSG3LLT5.js";
|
|
5
|
-
|
|
6
|
-
// src/server-transport.ts
|
|
1
|
+
import { a as wrapNodeWebsocket, i as READY_STATE, n as WebsocketClientTransport, o as wrapStandardWebsocket } from "./client-transport-DIZ-LJxs.js";
|
|
7
2
|
import { Transport } from "@kyneta/transport";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
import { FragmentReassembler, decodeBinaryMessages, encodeBinaryAndSend } from "@kyneta/wire";
|
|
4
|
+
//#region src/connection.ts
|
|
5
|
+
/**
|
|
6
|
+
* Default fragment threshold in bytes.
|
|
7
|
+
* Messages larger than this are fragmented for cloud infrastructure compatibility.
|
|
8
|
+
* AWS API Gateway has a 128KB limit, so 100KB provides a safe margin.
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_FRAGMENT_THRESHOLD = 100 * 1024;
|
|
11
|
+
/**
|
|
12
|
+
* Represents a single Websocket connection to a peer (server-side).
|
|
13
|
+
*
|
|
14
|
+
* Manages encoding, framing, fragmentation, and reassembly for one
|
|
15
|
+
* connected client. Created by `WebsocketServerTransport.handleConnection()`.
|
|
16
|
+
*
|
|
17
|
+
* The connection uses the CBOR codec for binary transport — this is
|
|
18
|
+
* the natural choice for Websocket's binary frame support.
|
|
19
|
+
*/
|
|
16
20
|
var WebsocketConnection = class {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
} catch (error) {
|
|
122
|
-
console.error("Failed to decode wire message:", error);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Handle a decoded channel message.
|
|
127
|
-
*
|
|
128
|
-
* Delivers messages synchronously. The Synchronizer's receive queue
|
|
129
|
-
* handles recursion prevention by queuing messages and processing
|
|
130
|
-
* them iteratively.
|
|
131
|
-
*/
|
|
132
|
-
#handleChannelMessage(msg) {
|
|
133
|
-
if (!this.#channel) {
|
|
134
|
-
console.error("Cannot handle message: channel not set");
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
this.#channel.onReceive(msg);
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Handle keepalive ping/pong messages.
|
|
141
|
-
*/
|
|
142
|
-
#handleKeepalive(text) {
|
|
143
|
-
if (text === "ping") {
|
|
144
|
-
this.#socket.send("pong");
|
|
145
|
-
}
|
|
146
|
-
}
|
|
21
|
+
peerId;
|
|
22
|
+
channelId;
|
|
23
|
+
#socket;
|
|
24
|
+
#channel = null;
|
|
25
|
+
#started = false;
|
|
26
|
+
#fragmentThreshold;
|
|
27
|
+
#reassembler;
|
|
28
|
+
constructor(peerId, channelId, socket, config) {
|
|
29
|
+
this.peerId = peerId;
|
|
30
|
+
this.channelId = channelId;
|
|
31
|
+
this.#socket = socket;
|
|
32
|
+
this.#fragmentThreshold = config?.fragmentThreshold ?? 102400;
|
|
33
|
+
this.#reassembler = new FragmentReassembler({
|
|
34
|
+
timeoutMs: 1e4,
|
|
35
|
+
onTimeout: (frameId) => {
|
|
36
|
+
console.warn(`[WebsocketConnection] Fragment batch timed out: ${frameId}`);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Set the channel reference.
|
|
42
|
+
* Called by the adapter when the channel is created.
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
_setChannel(channel) {
|
|
46
|
+
this.#channel = channel;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Start processing messages on this connection.
|
|
50
|
+
*
|
|
51
|
+
* Sets up the message handler on the socket. Must be called after
|
|
52
|
+
* the connection is fully set up (channel assigned, stored in adapter).
|
|
53
|
+
*/
|
|
54
|
+
start() {
|
|
55
|
+
if (this.#started) return;
|
|
56
|
+
this.#started = true;
|
|
57
|
+
this.#socket.onMessage((data) => {
|
|
58
|
+
this.#handleMessage(data);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Send a ChannelMsg through the Websocket.
|
|
63
|
+
*
|
|
64
|
+
* Encodes via CBOR codec → frame → fragment if needed → socket.send().
|
|
65
|
+
*/
|
|
66
|
+
send(msg) {
|
|
67
|
+
if (this.#socket.readyState !== "open") return;
|
|
68
|
+
encodeBinaryAndSend(msg, this.#fragmentThreshold, (data) => this.#socket.send(data));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Send a "ready" signal to the client.
|
|
72
|
+
*
|
|
73
|
+
* This is a transport-level text message that tells the client the
|
|
74
|
+
* server is ready to receive protocol messages. The client creates
|
|
75
|
+
* its channel and sends establish after receiving this.
|
|
76
|
+
*/
|
|
77
|
+
sendReady() {
|
|
78
|
+
if (this.#socket.readyState !== "open") return;
|
|
79
|
+
this.#socket.send("ready");
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Close the connection and clean up resources.
|
|
83
|
+
*/
|
|
84
|
+
close(code, reason) {
|
|
85
|
+
this.#reassembler.dispose();
|
|
86
|
+
this.#socket.close(code, reason);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Handle an incoming message from the Websocket.
|
|
90
|
+
*/
|
|
91
|
+
#handleMessage(data) {
|
|
92
|
+
if (typeof data === "string") {
|
|
93
|
+
this.#handleKeepalive(data);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const messages = decodeBinaryMessages(data, this.#reassembler);
|
|
98
|
+
if (messages) for (const msg of messages) this.#handleChannelMessage(msg);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error("Failed to decode wire message:", error);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Handle a decoded channel message.
|
|
105
|
+
*
|
|
106
|
+
* Delivers messages synchronously. The Synchronizer's receive queue
|
|
107
|
+
* handles recursion prevention by queuing messages and processing
|
|
108
|
+
* them iteratively.
|
|
109
|
+
*/
|
|
110
|
+
#handleChannelMessage(msg) {
|
|
111
|
+
if (!this.#channel) {
|
|
112
|
+
console.error("Cannot handle message: channel not set");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
this.#channel.onReceive(msg);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Handle keepalive ping/pong messages.
|
|
119
|
+
*/
|
|
120
|
+
#handleKeepalive(text) {
|
|
121
|
+
if (text === "ping") this.#socket.send("pong");
|
|
122
|
+
}
|
|
147
123
|
};
|
|
148
|
-
|
|
149
|
-
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/server-transport.ts
|
|
126
|
+
/**
|
|
127
|
+
* Generate a random peer ID for connections that don't provide one.
|
|
128
|
+
*/
|
|
150
129
|
function generatePeerId() {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
return result;
|
|
130
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
131
|
+
let result = "ws-";
|
|
132
|
+
for (let i = 0; i < 12; i++) result += chars.charAt(Math.floor(Math.random() * 62));
|
|
133
|
+
return result;
|
|
157
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* Websocket server network adapter.
|
|
137
|
+
*
|
|
138
|
+
* Framework-agnostic — works with any Websocket library through the
|
|
139
|
+
* `Socket` interface. Use `handleConnection()` to integrate with your
|
|
140
|
+
* framework's Websocket upgrade handler.
|
|
141
|
+
*
|
|
142
|
+
* Each client connection is tracked as a `WebsocketConnection` keyed
|
|
143
|
+
* by peer ID. The adapter creates a channel per connection and routes
|
|
144
|
+
* outbound messages through the connection's send method.
|
|
145
|
+
*
|
|
146
|
+
* The connection handshake follows a two-phase protocol:
|
|
147
|
+
* 1. Server sends text `"ready"` signal (transport-level)
|
|
148
|
+
* 2. Client sends `establish` (protocol-level)
|
|
149
|
+
* 3. Server upgrades channel and sends present (handled by Synchronizer)
|
|
150
|
+
*
|
|
151
|
+
* The server does NOT call `establishChannel()` — it waits for the
|
|
152
|
+
* client's establish to avoid a race condition where the binary
|
|
153
|
+
* establish could arrive before the client has processed "ready".
|
|
154
|
+
*/
|
|
158
155
|
var WebsocketServerTransport = class extends Transport {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
const connection = this.#connections.get(peerId);
|
|
277
|
-
if (connection) {
|
|
278
|
-
this.removeChannel(connection.channelId);
|
|
279
|
-
this.#connections.delete(peerId);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Broadcast a message to all connected peers.
|
|
284
|
-
*/
|
|
285
|
-
broadcast(msg) {
|
|
286
|
-
for (const connection of this.#connections.values()) {
|
|
287
|
-
connection.send(msg);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
|
-
* Get the number of connected peers.
|
|
292
|
-
*/
|
|
293
|
-
get connectionCount() {
|
|
294
|
-
return this.#connections.size;
|
|
295
|
-
}
|
|
296
|
-
};
|
|
297
|
-
export {
|
|
298
|
-
DEFAULT_FRAGMENT_THRESHOLD,
|
|
299
|
-
WebsocketConnection,
|
|
300
|
-
WebsocketServerTransport,
|
|
301
|
-
wrapNodeWebsocket,
|
|
302
|
-
wrapStandardWebsocket
|
|
156
|
+
#connections = /* @__PURE__ */ new Map();
|
|
157
|
+
#fragmentThreshold;
|
|
158
|
+
constructor(options) {
|
|
159
|
+
super({ transportType: "websocket-server" });
|
|
160
|
+
this.#fragmentThreshold = options?.fragmentThreshold ?? 102400;
|
|
161
|
+
}
|
|
162
|
+
generate(peerId) {
|
|
163
|
+
return {
|
|
164
|
+
transportType: this.transportType,
|
|
165
|
+
send: (msg) => {
|
|
166
|
+
const connection = this.#connections.get(peerId);
|
|
167
|
+
if (connection) connection.send(msg);
|
|
168
|
+
},
|
|
169
|
+
stop: () => {
|
|
170
|
+
this.unregisterConnection(peerId);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
async onStart() {}
|
|
175
|
+
async onStop() {
|
|
176
|
+
for (const connection of this.#connections.values()) connection.close(1001, "Server shutting down");
|
|
177
|
+
this.#connections.clear();
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Handle a new Websocket connection.
|
|
181
|
+
*
|
|
182
|
+
* Call this from your framework's Websocket upgrade handler.
|
|
183
|
+
* Returns a connection handle and a `start()` function that begins
|
|
184
|
+
* message processing and sends the "ready" signal.
|
|
185
|
+
*
|
|
186
|
+
* @param options - Connection options including the Socket and optional peer ID
|
|
187
|
+
* @returns A connection handle and start function
|
|
188
|
+
*
|
|
189
|
+
* @example Bun
|
|
190
|
+
* ```typescript
|
|
191
|
+
* const { start } = serverAdapter.handleConnection({
|
|
192
|
+
* socket: wrapBunWebsocket(ws),
|
|
193
|
+
* })
|
|
194
|
+
* start()
|
|
195
|
+
* ```
|
|
196
|
+
*
|
|
197
|
+
* @example Node.js ws
|
|
198
|
+
* ```typescript
|
|
199
|
+
* wss.on("connection", (ws) => {
|
|
200
|
+
* const { start } = serverAdapter.handleConnection({
|
|
201
|
+
* socket: wrapNodeWebsocket(ws),
|
|
202
|
+
* })
|
|
203
|
+
* start()
|
|
204
|
+
* })
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
handleConnection(options) {
|
|
208
|
+
const { socket, peerId: providedPeerId } = options;
|
|
209
|
+
const peerId = providedPeerId ?? generatePeerId();
|
|
210
|
+
const existingConnection = this.#connections.get(peerId);
|
|
211
|
+
if (existingConnection) {
|
|
212
|
+
existingConnection.close(1e3, "Replaced by new connection");
|
|
213
|
+
this.unregisterConnection(peerId);
|
|
214
|
+
}
|
|
215
|
+
const channel = this.addChannel(peerId);
|
|
216
|
+
const connection = new WebsocketConnection(peerId, channel.channelId, socket, { fragmentThreshold: this.#fragmentThreshold });
|
|
217
|
+
connection._setChannel(channel);
|
|
218
|
+
this.#connections.set(peerId, connection);
|
|
219
|
+
socket.onClose((_code, _reason) => {
|
|
220
|
+
this.unregisterConnection(peerId);
|
|
221
|
+
});
|
|
222
|
+
socket.onError((_error) => {
|
|
223
|
+
this.unregisterConnection(peerId);
|
|
224
|
+
});
|
|
225
|
+
return {
|
|
226
|
+
connection,
|
|
227
|
+
start: () => {
|
|
228
|
+
connection.start();
|
|
229
|
+
connection.sendReady();
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get an active connection by peer ID.
|
|
235
|
+
*/
|
|
236
|
+
getConnection(peerId) {
|
|
237
|
+
return this.#connections.get(peerId);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Get all active connections.
|
|
241
|
+
*/
|
|
242
|
+
getAllConnections() {
|
|
243
|
+
return Array.from(this.#connections.values());
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Check if a peer is connected.
|
|
247
|
+
*/
|
|
248
|
+
isConnected(peerId) {
|
|
249
|
+
return this.#connections.has(peerId);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Unregister a connection, removing its channel and cleaning up state.
|
|
253
|
+
*/
|
|
254
|
+
unregisterConnection(peerId) {
|
|
255
|
+
const connection = this.#connections.get(peerId);
|
|
256
|
+
if (connection) {
|
|
257
|
+
this.removeChannel(connection.channelId);
|
|
258
|
+
this.#connections.delete(peerId);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Broadcast a message to all connected peers.
|
|
263
|
+
*/
|
|
264
|
+
broadcast(msg) {
|
|
265
|
+
for (const connection of this.#connections.values()) connection.send(msg);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Get the number of connected peers.
|
|
269
|
+
*/
|
|
270
|
+
get connectionCount() {
|
|
271
|
+
return this.#connections.size;
|
|
272
|
+
}
|
|
303
273
|
};
|
|
274
|
+
//#endregion
|
|
275
|
+
//#region src/service-client.ts
|
|
276
|
+
/**
|
|
277
|
+
* Create a Websocket client transport for service-to-service connections.
|
|
278
|
+
*
|
|
279
|
+
* This factory is for backend environments (Bun, Node.js) where you need
|
|
280
|
+
* to pass authentication headers during the Websocket upgrade.
|
|
281
|
+
*
|
|
282
|
+
* Note: Headers are a Bun/Node-specific extension. The browser WebSocket API
|
|
283
|
+
* does not support custom headers. For browser clients, use
|
|
284
|
+
* `createWebsocketClient()` and authenticate via URL query parameters.
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```typescript
|
|
288
|
+
* import { createServiceWebsocketClient } from "@kyneta/websocket-transport/server"
|
|
289
|
+
*
|
|
290
|
+
* const exchange = new Exchange({
|
|
291
|
+
* transports: [createServiceWebsocketClient({
|
|
292
|
+
* url: "ws://primary-server:3000/ws",
|
|
293
|
+
* WebSocket,
|
|
294
|
+
* headers: { Authorization: "Bearer token" },
|
|
295
|
+
* reconnect: { enabled: true },
|
|
296
|
+
* })],
|
|
297
|
+
* })
|
|
298
|
+
* ```
|
|
299
|
+
*/
|
|
300
|
+
function createServiceWebsocketClient(options) {
|
|
301
|
+
return () => new WebsocketClientTransport(options);
|
|
302
|
+
}
|
|
303
|
+
//#endregion
|
|
304
|
+
export { DEFAULT_FRAGMENT_THRESHOLD, READY_STATE, WebsocketConnection, WebsocketServerTransport, createServiceWebsocketClient, wrapNodeWebsocket, wrapStandardWebsocket };
|
|
305
|
+
|
|
304
306
|
//# sourceMappingURL=server.js.map
|