@meshagent/meshagent 0.37.2 → 0.38.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.
Files changed (77) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/browser/agent.js +74 -10
  3. package/dist/browser/developer-client.js +3 -0
  4. package/dist/browser/helpers.d.ts +2 -2
  5. package/dist/browser/helpers.js +1 -1
  6. package/dist/browser/meshagent-client.d.ts +25 -0
  7. package/dist/browser/meshagent-client.js +65 -0
  8. package/dist/browser/messaging-client.d.ts +29 -16
  9. package/dist/browser/messaging-client.js +256 -154
  10. package/dist/browser/participant.d.ts +7 -2
  11. package/dist/browser/participant.js +9 -9
  12. package/dist/browser/protocol.d.ts +85 -28
  13. package/dist/browser/protocol.js +356 -119
  14. package/dist/browser/room-client.d.ts +165 -29
  15. package/dist/browser/room-client.js +1114 -74
  16. package/dist/browser/room-event.d.ts +11 -0
  17. package/dist/browser/room-event.js +21 -1
  18. package/dist/browser/room-server-client.d.ts +2 -0
  19. package/dist/browser/room-server-client.js +6 -0
  20. package/dist/browser/runtime.d.ts +1 -1
  21. package/dist/browser/runtime.js +3 -1
  22. package/dist/browser/secrets-client.js +6 -2
  23. package/dist/browser/storage-client.d.ts +1 -0
  24. package/dist/browser/storage-client.js +9 -0
  25. package/dist/browser/sync-client.d.ts +16 -14
  26. package/dist/browser/sync-client.js +195 -116
  27. package/dist/esm/agent.js +74 -10
  28. package/dist/esm/developer-client.js +3 -0
  29. package/dist/esm/helpers.d.ts +2 -2
  30. package/dist/esm/helpers.js +1 -1
  31. package/dist/esm/meshagent-client.d.ts +25 -0
  32. package/dist/esm/meshagent-client.js +65 -0
  33. package/dist/esm/messaging-client.d.ts +29 -16
  34. package/dist/esm/messaging-client.js +256 -154
  35. package/dist/esm/participant.d.ts +7 -2
  36. package/dist/esm/participant.js +9 -9
  37. package/dist/esm/protocol.d.ts +85 -28
  38. package/dist/esm/protocol.js +352 -118
  39. package/dist/esm/room-client.d.ts +165 -29
  40. package/dist/esm/room-client.js +1112 -73
  41. package/dist/esm/room-event.d.ts +11 -0
  42. package/dist/esm/room-event.js +19 -0
  43. package/dist/esm/room-server-client.d.ts +2 -0
  44. package/dist/esm/room-server-client.js +7 -1
  45. package/dist/esm/runtime.d.ts +1 -1
  46. package/dist/esm/runtime.js +1 -1
  47. package/dist/esm/secrets-client.js +6 -2
  48. package/dist/esm/storage-client.d.ts +1 -0
  49. package/dist/esm/storage-client.js +9 -0
  50. package/dist/esm/sync-client.d.ts +16 -14
  51. package/dist/esm/sync-client.js +196 -117
  52. package/dist/node/agent.js +74 -10
  53. package/dist/node/developer-client.js +3 -0
  54. package/dist/node/helpers.d.ts +2 -2
  55. package/dist/node/helpers.js +1 -1
  56. package/dist/node/meshagent-client.d.ts +25 -0
  57. package/dist/node/meshagent-client.js +65 -0
  58. package/dist/node/messaging-client.d.ts +29 -16
  59. package/dist/node/messaging-client.js +256 -154
  60. package/dist/node/participant.d.ts +7 -2
  61. package/dist/node/participant.js +9 -9
  62. package/dist/node/protocol.d.ts +85 -28
  63. package/dist/node/protocol.js +356 -119
  64. package/dist/node/room-client.d.ts +165 -29
  65. package/dist/node/room-client.js +1114 -74
  66. package/dist/node/room-event.d.ts +11 -0
  67. package/dist/node/room-event.js +21 -1
  68. package/dist/node/room-server-client.d.ts +2 -0
  69. package/dist/node/room-server-client.js +6 -0
  70. package/dist/node/runtime.d.ts +1 -1
  71. package/dist/node/runtime.js +3 -1
  72. package/dist/node/secrets-client.js +6 -2
  73. package/dist/node/storage-client.d.ts +1 -0
  74. package/dist/node/storage-client.js +9 -0
  75. package/dist/node/sync-client.d.ts +16 -14
  76. package/dist/node/sync-client.js +195 -116
  77. package/package.json +6 -3
@@ -3,10 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.WebSocketClientProtocol = exports.Protocol = exports.ProtocolMessageStream = exports.WebSocketProtocolChannel = exports.StreamProtocolChannel = void 0;
6
+ exports.WebSocketClientProtocol = exports.Protocol = exports.ProtocolMessageStream = exports.WebSocketProtocolChannel = exports.StreamProtocolChannel = exports.ProtocolHandshakeException = exports.ProtocolCloseException = exports.ProtocolReconnectUnsupportedException = exports.ProtocolCloseKind = void 0;
7
7
  const isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));
8
- const utils_1 = require("./utils");
9
8
  const completer_1 = require("./completer");
9
+ const utils_1 = require("./utils");
10
10
  class ProtocolMessage {
11
11
  constructor({ id, type, data }) {
12
12
  this.id = id;
@@ -15,8 +15,45 @@ class ProtocolMessage {
15
15
  this.sent = new completer_1.Completer();
16
16
  }
17
17
  }
18
+ var ProtocolCloseKind;
19
+ (function (ProtocolCloseKind) {
20
+ ProtocolCloseKind["CLIENT"] = "client";
21
+ ProtocolCloseKind["SERVER"] = "server";
22
+ ProtocolCloseKind["ERROR"] = "error";
23
+ })(ProtocolCloseKind || (exports.ProtocolCloseKind = ProtocolCloseKind = {}));
24
+ class ProtocolReconnectUnsupportedException extends Error {
25
+ constructor(message) {
26
+ super(message);
27
+ this.name = "ProtocolReconnectUnsupportedException";
28
+ }
29
+ }
30
+ exports.ProtocolReconnectUnsupportedException = ProtocolReconnectUnsupportedException;
31
+ class ProtocolCloseException extends Error {
32
+ constructor({ closeCode, reason }) {
33
+ super(reason == null || reason.trim().length === 0 ? `connection closed with status ${closeCode}` : reason);
34
+ this.name = "ProtocolCloseException";
35
+ this.closeCode = closeCode;
36
+ this.reason = reason;
37
+ }
38
+ }
39
+ exports.ProtocolCloseException = ProtocolCloseException;
40
+ class ProtocolHandshakeException extends Error {
41
+ constructor({ statusCode, statusText }) {
42
+ const normalizedStatusText = statusText?.trim();
43
+ super(normalizedStatusText == null || normalizedStatusText.length === 0
44
+ ? `websocket connect failed with status ${statusCode}`
45
+ : `websocket connect failed with status ${statusCode}: ${normalizedStatusText}`);
46
+ this.name = "ProtocolHandshakeException";
47
+ this.statusCode = statusCode;
48
+ this.statusText = normalizedStatusText;
49
+ }
50
+ }
51
+ exports.ProtocolHandshakeException = ProtocolHandshakeException;
52
+ function isNodeRuntime() {
53
+ return typeof process !== "undefined" && process.release?.name === "node";
54
+ }
18
55
  class StreamProtocolChannel {
19
- constructor({ input, output }) {
56
+ constructor({ input, output, }) {
20
57
  this.started = false;
21
58
  this._iterator = null;
22
59
  this.input = input;
@@ -28,29 +65,24 @@ class StreamProtocolChannel {
28
65
  }
29
66
  this.started = true;
30
67
  (async () => {
31
- this._iterator?.return(null);
68
+ this._iterator?.return(undefined);
32
69
  try {
33
70
  this._iterator = this.input.stream();
34
71
  for await (const message of this._iterator) {
35
- if (message) {
36
- onDataReceived(message);
37
- }
72
+ onDataReceived(message);
38
73
  }
74
+ onDone?.();
39
75
  }
40
76
  catch (error) {
41
- if (onError) {
42
- onError(error);
43
- }
44
- }
45
- finally {
46
- if (onDone) {
47
- onDone();
48
- }
77
+ onError?.(error);
49
78
  }
50
- })();
79
+ })().catch((error) => {
80
+ onError?.(error);
81
+ });
51
82
  }
52
83
  dispose() {
53
- this._iterator?.return(null);
84
+ this.started = false;
85
+ this._iterator?.return(undefined);
54
86
  this._iterator = null;
55
87
  this.input.close();
56
88
  }
@@ -63,54 +95,115 @@ class WebSocketProtocolChannel {
63
95
  constructor({ url, jwt }) {
64
96
  this.webSocket = null;
65
97
  this._opened = new completer_1.Completer();
66
- this._onOpen = () => this._opened.resolve();
67
- this._onData = (event) => {
98
+ this._finished = false;
99
+ this._onUnexpectedResponse = (_request, response) => {
100
+ const statusCode = response.statusCode;
101
+ if (statusCode == null) {
102
+ this._finish("error", new Error("websocket connect failed"));
103
+ return;
104
+ }
105
+ this._finish("error", new ProtocolHandshakeException({
106
+ statusCode,
107
+ statusText: response.statusMessage,
108
+ }));
109
+ };
110
+ this._onOpen = () => {
111
+ if (!this._opened.completed) {
112
+ this._opened.complete();
113
+ }
114
+ };
115
+ this._onMessage = (event) => {
68
116
  const data = event.data;
69
117
  if (data instanceof Blob) {
70
- data.arrayBuffer().then((buffer) => {
71
- if (this.onDataReceived) {
72
- this.onDataReceived(new Uint8Array(buffer));
73
- }
118
+ void data.arrayBuffer().then((buffer) => {
119
+ this._onDataReceived?.(new Uint8Array(buffer));
74
120
  });
121
+ return;
75
122
  }
76
- else if (typeof (data) == "string") {
77
- if (this.onDataReceived) {
78
- this.onDataReceived(new Uint8Array(utils_1.encoder.encode(data)));
79
- }
123
+ if (typeof data === "string") {
124
+ this._onDataReceived?.(utils_1.encoder.encode(data));
125
+ return;
80
126
  }
81
- else if (data instanceof ArrayBuffer || data instanceof Buffer) {
82
- if (this.onDataReceived) {
83
- this.onDataReceived(new Uint8Array(data));
84
- }
127
+ if (data instanceof ArrayBuffer) {
128
+ this._onDataReceived?.(new Uint8Array(data));
129
+ return;
130
+ }
131
+ if (data instanceof Uint8Array) {
132
+ this._onDataReceived?.(data);
133
+ return;
134
+ }
135
+ if (ArrayBuffer.isView(data)) {
136
+ this._onDataReceived?.(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
85
137
  }
86
138
  };
139
+ this._onClose = (event) => {
140
+ if (event.code === 1000) {
141
+ this._finish("done");
142
+ return;
143
+ }
144
+ const reason = typeof event.reason === "string" ? event.reason : event.reason.toString();
145
+ this._finish("error", new ProtocolCloseException({ closeCode: event.code, reason }));
146
+ };
147
+ this._onError = (event) => {
148
+ this._finish("error", event instanceof Error ? event : new Error("websocket error"));
149
+ };
87
150
  this.url = url;
88
151
  this.jwt = jwt;
89
152
  }
90
153
  start(onDataReceived, { onDone, onError }) {
91
- if (typeof (onDataReceived) != "function") {
92
- throw new Error("onDataReceived must be a function");
93
- }
94
154
  const url = new URL(this.url);
95
155
  url.searchParams.set("token", this.jwt);
96
- this.onDataReceived = onDataReceived;
97
- this.webSocket = new isomorphic_ws_1.default(url.toString());
98
- this.webSocket.addEventListener("open", this._onOpen);
99
- this.webSocket.addEventListener("message", this._onData);
100
- if (onDone) {
101
- this.webSocket.addEventListener("close", onDone);
156
+ this._opened = new completer_1.Completer();
157
+ this._finished = false;
158
+ this._onDataReceived = onDataReceived;
159
+ this._doneHandler = onDone;
160
+ this._errorHandler = onError;
161
+ const socket = new isomorphic_ws_1.default(url.toString());
162
+ this.webSocket = socket;
163
+ if (isNodeRuntime()) {
164
+ socket.on("unexpected-response", this._onUnexpectedResponse);
102
165
  }
103
- if (onError) {
104
- this.webSocket.addEventListener("error", onError);
166
+ socket.addEventListener("open", this._onOpen);
167
+ socket.addEventListener("message", this._onMessage);
168
+ socket.addEventListener("close", this._onClose);
169
+ socket.addEventListener("error", this._onError);
170
+ }
171
+ _finish(kind, error) {
172
+ if (this._finished) {
173
+ return;
105
174
  }
175
+ this._finished = true;
176
+ if (kind === "done") {
177
+ this._doneHandler?.();
178
+ return;
179
+ }
180
+ this._errorHandler?.(error);
106
181
  }
107
182
  dispose() {
108
- this.webSocket?.close();
183
+ const socket = this.webSocket;
109
184
  this.webSocket = null;
185
+ this._onDataReceived = undefined;
186
+ if (socket == null) {
187
+ return;
188
+ }
189
+ socket.removeEventListener("open", this._onOpen);
190
+ socket.removeEventListener("message", this._onMessage);
191
+ socket.removeEventListener("close", this._onClose);
192
+ socket.removeEventListener("error", this._onError);
193
+ if (isNodeRuntime()) {
194
+ socket.off("unexpected-response", this._onUnexpectedResponse);
195
+ }
196
+ if (socket.readyState === isomorphic_ws_1.default.CONNECTING || socket.readyState === isomorphic_ws_1.default.OPEN) {
197
+ socket.close(1000);
198
+ }
110
199
  }
111
200
  async sendData(data) {
112
201
  await this._opened.fut;
113
- this.webSocket?.send(data);
202
+ const socket = this.webSocket;
203
+ if (socket == null) {
204
+ throw new Error("websocket is closed");
205
+ }
206
+ socket.send(data);
114
207
  }
115
208
  }
116
209
  exports.WebSocketProtocolChannel = WebSocketProtocolChannel;
@@ -120,15 +213,15 @@ class ProtocolMessageStream {
120
213
  this._messageAdded = new completer_1.Completer();
121
214
  this._closed = false;
122
215
  }
123
- async add(message) {
216
+ add(message) {
124
217
  this._messages.push(message);
125
218
  if (!this._messageAdded.completed) {
126
219
  this._messageAdded.complete();
127
220
  }
128
221
  }
129
222
  close() {
223
+ this._closed = true;
130
224
  if (!this._messageAdded.completed) {
131
- this._closed = true;
132
225
  this._messageAdded.complete();
133
226
  }
134
227
  }
@@ -137,9 +230,9 @@ class ProtocolMessageStream {
137
230
  await this._messageAdded.fut;
138
231
  this._messageAdded = new completer_1.Completer();
139
232
  while (this._messages.length > 0 && !this._closed) {
140
- const msg = this._messages.shift();
141
- if (msg) {
142
- yield msg;
233
+ const message = this._messages.shift();
234
+ if (message !== undefined) {
235
+ yield message;
143
236
  }
144
237
  }
145
238
  }
@@ -151,26 +244,87 @@ class Protocol {
151
244
  this.handlers = {};
152
245
  this._id = 0;
153
246
  this._send = new ProtocolMessageStream();
247
+ this._done = new completer_1.Completer();
248
+ this._sendLoop = null;
249
+ this._open = false;
250
+ this._closed = false;
251
+ this._closeKind = null;
252
+ this._closeReason = null;
154
253
  this._recvPacketId = 0;
155
254
  this._recvState = "ready";
156
255
  this._recvPacketTotal = 0;
157
256
  this._recvMessageId = -1;
158
257
  this._recvType = "";
159
258
  this._recvPackets = [];
160
- this._iterator = null;
161
259
  this.channel = channel;
162
260
  }
261
+ get url() {
262
+ return null;
263
+ }
264
+ get token() {
265
+ return null;
266
+ }
267
+ get isOpen() {
268
+ return this._open;
269
+ }
270
+ get isClosed() {
271
+ return this._closed;
272
+ }
273
+ get closeKind() {
274
+ return this._closeKind;
275
+ }
276
+ get closeReason() {
277
+ return this._closeReason;
278
+ }
279
+ get done() {
280
+ return this._done.fut;
281
+ }
282
+ async waitForClose() {
283
+ await this.done;
284
+ }
285
+ static createFactory(...args) {
286
+ const ProtocolCtor = this;
287
+ if (ProtocolCtor === Protocol) {
288
+ let used = false;
289
+ return () => {
290
+ if (used) {
291
+ throw new ProtocolReconnectUnsupportedException("protocolFactory was not configured for reconnecting this protocol");
292
+ }
293
+ used = true;
294
+ return new ProtocolCtor(...args);
295
+ };
296
+ }
297
+ return () => new ProtocolCtor(...args);
298
+ }
299
+ _setCloseState({ kind, reason, }) {
300
+ if (this._closeKind == null) {
301
+ this._closeKind = kind;
302
+ }
303
+ if (this._closeReason == null && reason != null && reason.trim().length > 0) {
304
+ this._closeReason = reason.trim();
305
+ }
306
+ }
163
307
  addHandler(type, handler) {
308
+ if (this.handlers[type] !== undefined) {
309
+ throw new Error(`already registered handler for ${type}`);
310
+ }
164
311
  this.handlers[type] = handler;
165
312
  }
166
- removeHandler(type) {
313
+ removeHandler(type, handler) {
314
+ const current = this.handlers[type];
315
+ if (current !== handler) {
316
+ throw new Error(`handler mismatch for ${type}`);
317
+ }
167
318
  delete this.handlers[type];
168
319
  }
320
+ getHandler(type) {
321
+ return this.handlers[type];
322
+ }
169
323
  async handleMessage(messageId, type, data) {
170
324
  const handler = this.handlers[type] ?? this.handlers["*"];
171
- if (!handler) {
172
- const d = data ? (0, utils_1.unpackMessage)(data) : null;
173
- console.warn(`No handler for message type ${type}; data: ${d}`);
325
+ if (handler == null) {
326
+ const unpacked = (0, utils_1.unpackMessage)(data);
327
+ console.warn(`No handler for message type ${type}; data:`, unpacked);
174
328
  return;
175
329
  }
176
330
  await handler(this, messageId, type, data);
@@ -178,69 +332,139 @@ class Protocol {
178
332
  getNextMessageId() {
179
333
  return this._id++;
180
334
  }
335
+ sendNowait(type, data, { id } = {}) {
336
+ if (this._sendError != null) {
337
+ throw this._sendError;
338
+ }
339
+ if (this._closed) {
340
+ throw new Error("protocol is closed");
341
+ }
342
+ const message = new ProtocolMessage({ id: id ?? this.getNextMessageId(), type, data });
343
+ this._send.add(message);
344
+ return message.id;
345
+ }
181
346
  async send(type, data, id) {
182
- const msg = new ProtocolMessage({ id: id ?? this.getNextMessageId(), type: type, data: data });
183
- this._send.add(msg);
184
- await msg.sent.fut;
347
+ const message = new ProtocolMessage({ id: id ?? this.getNextMessageId(), type, data });
348
+ if (this._sendError != null) {
349
+ throw this._sendError;
350
+ }
351
+ if (this._closed) {
352
+ throw new Error("protocol is closed");
353
+ }
354
+ this._send.add(message);
355
+ await message.sent.fut;
185
356
  }
186
357
  async sendJson(object) {
187
- return await this.send("application/json", utils_1.encoder.encode(JSON.stringify(object)));
358
+ await this.send("application/json", utils_1.encoder.encode(JSON.stringify(object)));
188
359
  }
189
- start({ onMessage, onDone, onError } = {}) {
360
+ start({ onMessage, onDone, onError, } = {}) {
361
+ if (this._sendLoop != null) {
362
+ throw new Error("protocol already started");
363
+ }
190
364
  if (onMessage != null) {
191
365
  this.addHandler("*", onMessage);
192
366
  }
193
- this.channel.start(this.onDataReceived.bind(this), { onDone, onError });
194
- this._iterator?.return(null);
195
- (async () => {
196
- this._iterator = this._send.stream();
197
- for await (const message of this._iterator) {
198
- if (message) {
199
- const packets = Math.ceil((message.data.length / 1024));
200
- const header = new Uint8Array(4 * 4);
201
- const dataView = new DataView(header.buffer);
202
- dataView.setUint32(0, (message.id & 0x000fffff00000000) / Math.pow(2, 32), false);
203
- dataView.setUint32(4, message.id & 0xffffffff, false);
204
- dataView.setUint32(8, 0, false);
205
- dataView.setUint32(12, packets, false);
206
- const headerPacket = (0, utils_1.mergeUint8Arrays)(header, utils_1.encoder.encode(message.type));
207
- await this.channel.sendData(headerPacket);
208
- for (var i = 0; i < packets; i++) {
209
- const packetHeader = new Uint8Array(3 * 4);
210
- const dataView = new DataView(packetHeader.buffer);
211
- dataView.setUint32(0, (message.id & 0x000fffff00000000) / Math.pow(2, 32), false);
212
- dataView.setUint32(4, message.id & 0xffffffff, false);
213
- dataView.setUint32(8, i + 1, false);
214
- const packet = (0, utils_1.mergeUint8Arrays)(packetHeader, message.data.subarray(i * 1024, Math.min((i + 1) * 1024, message.data.length)));
215
- await this.channel.sendData(packet);
216
- }
217
- message.sent.resolve();
367
+ this._open = true;
368
+ this.channel.start(this.onDataReceived.bind(this), {
369
+ onDone: () => {
370
+ this._setCloseState({ kind: ProtocolCloseKind.SERVER });
371
+ this._shutdown();
372
+ if (!this._done.completed) {
373
+ this._done.complete(null);
218
374
  }
219
- }
220
- })();
375
+ onDone?.();
376
+ },
377
+ onError: (error) => {
378
+ this._setCloseState({
379
+ kind: ProtocolCloseKind.ERROR,
380
+ reason: error instanceof Error ? error.message : String(error),
381
+ });
382
+ this._shutdown();
383
+ if (!this._done.completed) {
384
+ this._done.complete(error);
385
+ }
386
+ onError?.(error);
387
+ },
388
+ });
389
+ this._sendLoop = this._runSendLoop(onError);
221
390
  }
222
- dispose() {
391
+ close() {
392
+ this._setCloseState({ kind: ProtocolCloseKind.CLIENT });
393
+ this._shutdown();
223
394
  this.channel.dispose();
224
- this._iterator?.return(null);
225
- this._iterator = null;
395
+ if (!this._done.completed) {
396
+ this._done.complete(null);
397
+ }
398
+ }
399
+ dispose() {
400
+ this.close();
401
+ }
402
+ _shutdown() {
403
+ if (this._closed) {
404
+ return;
405
+ }
406
+ this._closed = true;
407
+ this._open = false;
408
+ this._send.close();
409
+ }
410
+ async _runSendLoop(onError) {
411
+ for await (const message of this._send.stream()) {
412
+ try {
413
+ const packets = Math.ceil(message.data.length / 1024);
414
+ const header = new Uint8Array(16);
415
+ const headerView = new DataView(header.buffer);
416
+ headerView.setUint32(0, Math.floor(message.id / 2 ** 32), false);
417
+ headerView.setUint32(4, message.id & 0xffffffff, false);
418
+ headerView.setUint32(8, 0, false);
419
+ headerView.setUint32(12, packets, false);
420
+ await this.channel.sendData((0, utils_1.mergeUint8Arrays)(header, utils_1.encoder.encode(message.type)));
421
+ for (let i = 0; i < packets; i += 1) {
422
+ const packetHeader = new Uint8Array(12);
423
+ const packetHeaderView = new DataView(packetHeader.buffer);
424
+ packetHeaderView.setUint32(0, Math.floor(message.id / 2 ** 32), false);
425
+ packetHeaderView.setUint32(4, message.id & 0xffffffff, false);
426
+ packetHeaderView.setUint32(8, i + 1, false);
427
+ await this.channel.sendData((0, utils_1.mergeUint8Arrays)(packetHeader, message.data.subarray(i * 1024, Math.min((i + 1) * 1024, message.data.length))));
428
+ }
429
+ if (!message.sent.completed) {
430
+ message.sent.complete();
431
+ }
432
+ }
433
+ catch (error) {
434
+ this._sendError = error;
435
+ this._setCloseState({
436
+ kind: ProtocolCloseKind.ERROR,
437
+ reason: error instanceof Error ? error.message : String(error),
438
+ });
439
+ if (!message.sent.completed) {
440
+ message.sent.completeError(error);
441
+ }
442
+ this._shutdown();
443
+ if (!this._done.completed) {
444
+ this._done.complete(error);
445
+ }
446
+ onError?.(error);
447
+ return;
448
+ }
449
+ }
226
450
  }
227
451
  onDataReceived(dataPacket) {
228
- const dataView = new DataView(dataPacket.buffer);
229
- const messageId = dataView.getUint32(4, false) + dataView.getUint32(0, false) * Math.pow(2, 32);
452
+ const dataView = new DataView(dataPacket.buffer, dataPacket.byteOffset, dataPacket.byteLength);
453
+ const messageId = dataView.getUint32(4, false) + dataView.getUint32(0, false) * 2 ** 32;
230
454
  const packet = dataView.getUint32(8, false);
231
- if (packet != this._recvPacketId) {
455
+ if (packet !== this._recvPacketId) {
232
456
  this._recvState = "error";
233
457
  }
234
- if (packet == 0) {
235
- if (this._recvState == "ready" || this._recvState == "error") {
458
+ if (packet === 0) {
459
+ if (this._recvState === "ready" || this._recvState === "error") {
236
460
  this._recvPacketTotal = dataView.getUint32(12, false);
237
461
  this._recvMessageId = messageId;
238
462
  this._recvType = utils_1.decoder.decode(dataPacket.subarray(16));
239
- if (this._recvPacketTotal == 0) {
463
+ if (this._recvPacketTotal === 0) {
240
464
  try {
241
465
  const merged = (0, utils_1.mergeUint8Arrays)(...this._recvPackets);
242
466
  this._recvPackets.length = 0;
243
- this.handleMessage(messageId, this._recvType, merged);
467
+ this._dispatchMessage({ messageId, type: this._recvType, data: merged });
244
468
  }
245
469
  finally {
246
470
  this._recvState = "ready";
@@ -258,41 +482,54 @@ class Protocol {
258
482
  this._recvState = "error";
259
483
  this._recvPacketId = 0;
260
484
  }
485
+ return;
261
486
  }
262
- else if (this._recvState != "processing") {
487
+ if (this._recvState !== "processing") {
263
488
  this._recvState = "error";
264
489
  this._recvPacketId = 0;
490
+ return;
265
491
  }
266
- else {
267
- if (messageId != this._recvMessageId) {
268
- this._recvState = "error";
269
- this._recvPacketId = 0;
270
- }
271
- this._recvPackets.push(dataPacket.subarray(12));
272
- if (this._recvPacketTotal == this._recvPacketId) {
273
- try {
274
- const merged = (0, utils_1.mergeUint8Arrays)(...this._recvPackets);
275
- this._recvPackets.length = 0;
276
- this.handleMessage(messageId, this._recvType, merged);
277
- }
278
- finally {
279
- this._recvState = "ready";
280
- this._recvPacketId = 0;
281
- this._recvType = "";
282
- this._recvMessageId = -1;
283
- }
492
+ if (messageId !== this._recvMessageId) {
493
+ this._recvState = "error";
494
+ this._recvPacketId = 0;
495
+ }
496
+ this._recvPackets.push(dataPacket.subarray(12));
497
+ if (this._recvPacketTotal === this._recvPacketId) {
498
+ try {
499
+ const merged = (0, utils_1.mergeUint8Arrays)(...this._recvPackets);
500
+ this._recvPackets.length = 0;
501
+ this._dispatchMessage({ messageId, type: this._recvType, data: merged });
284
502
  }
285
- else {
286
- this._recvPacketId += 1;
503
+ finally {
504
+ this._recvState = "ready";
505
+ this._recvPacketId = 0;
506
+ this._recvType = "";
507
+ this._recvMessageId = -1;
287
508
  }
509
+ return;
288
510
  }
511
+ this._recvPacketId += 1;
512
+ }
513
+ _dispatchMessage({ messageId, type, data, }) {
514
+ void this.handleMessage(messageId, type, data).catch((error) => {
515
+ console.error("unhandled protocol message handler error", error);
516
+ });
289
517
  }
290
518
  }
291
519
  exports.Protocol = Protocol;
292
520
  class WebSocketClientProtocol extends Protocol {
293
521
  constructor({ url, token }) {
294
- const channel = new WebSocketProtocolChannel({ url, jwt: token });
295
- super({ channel });
522
+ super({
523
+ channel: new WebSocketProtocolChannel({ url, jwt: token }),
524
+ });
525
+ this._url = url;
526
+ this._token = token;
527
+ }
528
+ get url() {
529
+ return this._url;
530
+ }
531
+ get token() {
532
+ return this._token;
296
533
  }
297
534
  }
298
535
  exports.WebSocketClientProtocol = WebSocketClientProtocol;