@milaboratories/pl-client 2.16.12 → 2.16.14

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 (74) hide show
  1. package/dist/__external/.pnpm/{@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3 → @rollup_plugin-typescript@12.3.0_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3}/__external/tslib/tslib.es6.cjs.map +1 -1
  2. package/dist/__external/.pnpm/{@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3 → @rollup_plugin-typescript@12.3.0_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3}/__external/tslib/tslib.es6.js.map +1 -1
  3. package/dist/core/client.cjs +31 -16
  4. package/dist/core/client.cjs.map +1 -1
  5. package/dist/core/client.d.ts +3 -2
  6. package/dist/core/client.d.ts.map +1 -1
  7. package/dist/core/client.js +31 -16
  8. package/dist/core/client.js.map +1 -1
  9. package/dist/core/default_client.cjs +1 -1
  10. package/dist/core/default_client.cjs.map +1 -1
  11. package/dist/core/default_client.js +1 -1
  12. package/dist/core/default_client.js.map +1 -1
  13. package/dist/core/driver.cjs +1 -1
  14. package/dist/core/driver.cjs.map +1 -1
  15. package/dist/core/driver.js +1 -1
  16. package/dist/core/driver.js.map +1 -1
  17. package/dist/core/errors.cjs +15 -4
  18. package/dist/core/errors.cjs.map +1 -1
  19. package/dist/core/errors.d.ts.map +1 -1
  20. package/dist/core/errors.js +15 -4
  21. package/dist/core/errors.js.map +1 -1
  22. package/dist/core/ll_client.cjs +61 -21
  23. package/dist/core/ll_client.cjs.map +1 -1
  24. package/dist/core/ll_client.d.ts +12 -3
  25. package/dist/core/ll_client.d.ts.map +1 -1
  26. package/dist/core/ll_client.js +62 -22
  27. package/dist/core/ll_client.js.map +1 -1
  28. package/dist/core/transaction.cjs +1 -1
  29. package/dist/core/transaction.js +1 -1
  30. package/dist/core/unauth_client.cjs +6 -2
  31. package/dist/core/unauth_client.cjs.map +1 -1
  32. package/dist/core/unauth_client.d.ts +2 -1
  33. package/dist/core/unauth_client.d.ts.map +1 -1
  34. package/dist/core/unauth_client.js +6 -2
  35. package/dist/core/unauth_client.js.map +1 -1
  36. package/dist/core/websocket_stream.cjs +147 -129
  37. package/dist/core/websocket_stream.cjs.map +1 -1
  38. package/dist/core/websocket_stream.d.ts +29 -22
  39. package/dist/core/websocket_stream.d.ts.map +1 -1
  40. package/dist/core/websocket_stream.js +148 -130
  41. package/dist/core/websocket_stream.js.map +1 -1
  42. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs +136 -0
  43. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs.map +1 -1
  44. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts +75 -1
  45. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts.map +1 -1
  46. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js +135 -1
  47. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js.map +1 -1
  48. package/dist/proto-rest/index.cjs +16 -2
  49. package/dist/proto-rest/index.cjs.map +1 -1
  50. package/dist/proto-rest/index.d.ts.map +1 -1
  51. package/dist/proto-rest/index.js +16 -2
  52. package/dist/proto-rest/index.js.map +1 -1
  53. package/dist/test/test_config.cjs +13 -3
  54. package/dist/test/test_config.cjs.map +1 -1
  55. package/dist/test/test_config.d.ts +4 -0
  56. package/dist/test/test_config.d.ts.map +1 -1
  57. package/dist/test/test_config.js +12 -4
  58. package/dist/test/test_config.js.map +1 -1
  59. package/package.json +6 -6
  60. package/src/core/client.ts +40 -21
  61. package/src/core/default_client.ts +1 -1
  62. package/src/core/driver.ts +1 -1
  63. package/src/core/errors.ts +14 -4
  64. package/src/core/ll_client.test.ts +9 -3
  65. package/src/core/ll_client.ts +81 -26
  66. package/src/core/unauth_client.test.ts +4 -4
  67. package/src/core/unauth_client.ts +7 -2
  68. package/src/core/websocket_stream.test.ts +19 -8
  69. package/src/core/websocket_stream.ts +173 -164
  70. package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.ts +179 -1
  71. package/src/proto-rest/index.ts +17 -2
  72. package/src/test/test_config.ts +13 -4
  73. /package/dist/__external/.pnpm/{@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3 → @rollup_plugin-typescript@12.3.0_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3}/__external/tslib/tslib.es6.cjs +0 -0
  74. /package/dist/__external/.pnpm/{@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3 → @rollup_plugin-typescript@12.3.0_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3}/__external/tslib/tslib.es6.js +0 -0
@@ -1,181 +1,182 @@
1
1
  'use strict';
2
2
 
3
3
  var undici = require('undici');
4
- var api = require('../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs');
5
4
  var Denque = require('denque');
6
5
  var retry_strategy = require('../helpers/retry_strategy.cjs');
6
+ var errors = require('./errors.cjs');
7
7
 
8
+ var ConnectionState;
9
+ (function (ConnectionState) {
10
+ ConnectionState[ConnectionState["NEW"] = 0] = "NEW";
11
+ ConnectionState[ConnectionState["CONNECTING"] = 1] = "CONNECTING";
12
+ ConnectionState[ConnectionState["CONNECTED"] = 2] = "CONNECTED";
13
+ ConnectionState[ConnectionState["CLOSING"] = 3] = "CLOSING";
14
+ ConnectionState[ConnectionState["CLOSED"] = 4] = "CLOSED";
15
+ })(ConnectionState || (ConnectionState = {}));
8
16
  /**
9
17
  * WebSocket-based bidirectional stream implementation for LLTransaction.
10
18
  * Implements BiDiStream interface which is compatible with DuplexStreamingCall.
11
19
  */
12
20
  class WebSocketBiDiStream {
21
+ url;
22
+ serializeClientMessage;
23
+ parseServerMessage;
24
+ options;
13
25
  // Connection
14
26
  ws = null;
15
- connectionState = 'disconnected';
16
- url;
17
- jwtToken;
18
- abortSignal;
27
+ connectionState = ConnectionState.NEW;
19
28
  reconnection;
20
29
  // Send management
21
30
  sendQueue = new Denque();
22
31
  sendCompleted = false;
32
+ onComplete;
23
33
  // Response management
24
34
  responseQueue = new Denque();
25
35
  responseResolvers = [];
26
36
  // Error tracking
27
- connectionError = null;
37
+ lastError;
28
38
  // === Public API ===
29
39
  requests = {
30
40
  send: async (message) => {
31
- this.validateSendState();
32
- return this.enqueueSend(message);
41
+ return await this.enqueueSend(message);
33
42
  },
34
43
  complete: async () => {
35
44
  if (this.sendCompleted)
36
45
  return;
46
+ await this.drainSendQueue(); // ensure we sent all already queued messages before closing the stream
47
+ try {
48
+ await this.onComplete(this); // custom onComplete may send additional messages
49
+ }
50
+ catch (_) {
51
+ // When 'complete' gets called concurrently with connection break or over a broken
52
+ // transaction stream (server decided it should drop transaction), server would close
53
+ // connection anyway on its end. We can safely ignore error here and just continue working.
54
+ }
37
55
  this.sendCompleted = true;
38
- await this.drainSendQueue();
39
- this.closeConnection();
40
56
  },
41
57
  };
42
58
  responses = {
43
59
  [Symbol.asyncIterator]: () => this.createResponseIterator(),
44
60
  };
45
- constructor(url, abortSignal, jwtToken, retryConfig = {}) {
61
+ close() {
62
+ this.reconnection.cancel();
63
+ if (this.connectionState < ConnectionState.CONNECTED) {
64
+ // Never reached CONNECTED state. ws.close() will never trigger 'close' event.
65
+ this.ws?.close();
66
+ this.onClose();
67
+ return;
68
+ }
69
+ if (!this.progressConnectionState(ConnectionState.CLOSING))
70
+ return;
71
+ this.ws.close();
72
+ }
73
+ constructor(url, serializeClientMessage, parseServerMessage, options = {}) {
46
74
  this.url = url;
47
- this.jwtToken = jwtToken;
48
- this.abortSignal = abortSignal;
75
+ this.serializeClientMessage = serializeClientMessage;
76
+ this.parseServerMessage = parseServerMessage;
77
+ this.options = options;
78
+ this.onComplete = this.options.onComplete ?? ((stream) => stream.close());
79
+ const retryConfig = this.options.retryConfig ?? {};
49
80
  this.reconnection = new retry_strategy.RetryStrategy(retryConfig, {
50
81
  onRetry: () => { void this.connect(); },
51
82
  onMaxAttemptsReached: (error) => this.handleError(error),
52
83
  });
53
- if (abortSignal.aborted) {
54
- this.connectionState = 'closed';
84
+ if (this.options.abortSignal?.aborted) {
85
+ this.progressConnectionState(ConnectionState.CLOSED);
55
86
  return;
56
87
  }
57
- this.attachAbortSignalHandler();
58
- void this.connect();
88
+ this.options.abortSignal?.addEventListener('abort', () => this.close());
89
+ this.connect();
59
90
  }
60
91
  // === Connection Lifecycle ===
61
92
  connect() {
62
- if (this.isConnectingOrConnected() || this.abortSignal.aborted)
93
+ if (this.options.abortSignal?.aborted)
94
+ return;
95
+ // Prevent reconnecting after first successful connection.
96
+ if (!this.progressConnectionState(ConnectionState.CONNECTING))
63
97
  return;
64
- this.connectionState = 'connecting';
65
- this.connectionError = null;
66
98
  try {
67
99
  this.ws = this.createWebSocket();
68
- this.attachWebSocketHandlers();
100
+ this.ws.addEventListener('open', () => this.onOpen());
101
+ this.ws.addEventListener('message', (event) => this.onMessage(event.data));
102
+ this.ws.addEventListener('error', (error) => this.onError(error));
103
+ this.ws.addEventListener('close', () => this.onClose());
69
104
  }
70
105
  catch (error) {
71
- this.connectionError = this.toError(error);
72
- this.connectionState = 'disconnected';
106
+ this.lastError = this.toError(error);
73
107
  this.reconnection.schedule();
74
108
  }
75
109
  }
76
110
  createWebSocket() {
77
- const options = this.jwtToken
78
- ? { headers: { authorization: `Bearer ${this.jwtToken}` } }
79
- : undefined;
111
+ const options = {};
112
+ if (this.options.jwtToken)
113
+ options.headers = { authorization: `Bearer ${this.options.jwtToken}` };
114
+ if (this.options.dispatcher)
115
+ options.dispatcher = this.options.dispatcher;
80
116
  const ws = new undici.WebSocket(this.url, options);
81
- if (ws) {
82
- ws.binaryType = 'arraybuffer';
83
- }
117
+ ws.binaryType = 'arraybuffer';
84
118
  return ws;
85
119
  }
86
- attachWebSocketHandlers() {
87
- if (!this.ws)
88
- return;
89
- this.ws.addEventListener('open', () => this.onOpen());
90
- this.ws.addEventListener('message', (event) => this.onMessage(event.data));
91
- this.ws.addEventListener('error', (error) => this.onError(error));
92
- this.ws.addEventListener('close', () => this.onClose());
93
- }
94
- attachAbortSignalHandler() {
95
- this.abortSignal.addEventListener('abort', () => this.close());
96
- }
97
120
  onOpen() {
98
- this.connectionState = 'connected';
99
- this.reconnection.reset();
100
- void this.processSendQueue();
121
+ this.progressConnectionState(ConnectionState.CONNECTED);
122
+ this.processSendQueue();
101
123
  }
102
- onClose() {
103
- this.ws = null;
104
- if (this.isClosed() || this.abortSignal.aborted)
124
+ onMessage(data) {
125
+ if (!(data instanceof ArrayBuffer)) {
126
+ this.handleError(new Error(`Unexpected WS message format: ${typeof data}`));
105
127
  return;
106
- if (this.sendCompleted) {
107
- this.finalizeStream();
108
- }
109
- else {
110
- this.connectionState = 'disconnected';
111
- this.reconnection.schedule();
112
128
  }
113
- }
114
- onError(error) {
115
- this.handleError(this.toError(error));
116
- }
117
- onMessage(data) {
118
129
  try {
119
- const message = this.parseMessage(data);
130
+ const message = this.parseServerMessage(new Uint8Array(data));
120
131
  this.deliverResponse(message);
121
132
  }
122
133
  catch (error) {
123
134
  this.handleError(this.toError(error));
124
135
  }
125
136
  }
126
- closeConnection() {
127
- if (this.ws?.readyState === undici.WebSocket.OPEN) {
128
- this.ws.close();
129
- }
130
- }
131
- close() {
132
- if (this.isClosed())
133
- return;
134
- this.connectionState = 'closed';
135
- this.reconnection.cancel();
136
- this.closeWebSocket();
137
- this.rejectAllPendingOperations();
138
- }
139
- closeWebSocket() {
140
- if (!this.ws)
137
+ onError(error) {
138
+ if (this.connectionState < ConnectionState.CONNECTED) {
139
+ // Try to connect several times until we succeed or run out of attempts.
140
+ this.lastError = this.toError(error);
141
+ this.reconnection.schedule();
141
142
  return;
142
- try {
143
- this.ws.close();
144
- }
145
- catch {
146
- // Suppress close errors
147
143
  }
148
- this.ws = null;
149
- }
150
- finalizeStream() {
151
- this.connectionState = 'closed';
152
- this.resolveAllPendingResponses();
144
+ this.handleError(this.toError(error));
153
145
  }
154
- resolveAllPendingResponses() {
155
- while (this.responseResolvers.length > 0) {
156
- const resolver = this.responseResolvers.shift();
157
- resolver.resolve({ value: undefined, done: true });
146
+ onClose() {
147
+ this.progressConnectionState(ConnectionState.CLOSED);
148
+ // If abort signal was triggered, use that as the error source
149
+ if (this.options.abortSignal?.aborted && !this.lastError) {
150
+ const reason = this.options.abortSignal.reason;
151
+ if (reason instanceof Error) {
152
+ this.lastError = reason;
153
+ }
154
+ else if (reason !== undefined) {
155
+ this.lastError = new Error(String(reason), { cause: reason });
156
+ }
157
+ else {
158
+ this.lastError = this.createStreamClosedError();
159
+ }
158
160
  }
159
- }
160
- parseMessage(data) {
161
- if (data instanceof ArrayBuffer) {
162
- return api.TxAPI_ServerMessage.fromBinary(new Uint8Array(data));
161
+ if (!this.lastError) {
162
+ this.rejectAllSendOperations(this.createStreamClosedError());
163
+ this.resolveAllPendingResponses(); // unblock active async iterator
164
+ }
165
+ else {
166
+ this.rejectAllPendingOperations(this.lastError);
163
167
  }
164
- throw new Error(`Unsupported message format: ${typeof data}`);
165
168
  }
166
169
  // === Send Queue Management ===
167
- validateSendState() {
170
+ enqueueSend(message) {
168
171
  if (this.sendCompleted) {
169
172
  throw new Error('Cannot send: stream already completed');
170
173
  }
171
- if (this.abortSignal.aborted) {
174
+ if (this.options.abortSignal?.aborted) {
172
175
  throw new Error('Cannot send: stream aborted');
173
176
  }
174
- }
175
- enqueueSend(message) {
176
177
  return new Promise((resolve, reject) => {
177
178
  this.sendQueue.push({ message, resolve, reject });
178
- void this.processSendQueue();
179
+ this.processSendQueue();
179
180
  });
180
181
  }
181
182
  processSendQueue() {
@@ -187,7 +188,7 @@ class WebSocketBiDiStream {
187
188
  }
188
189
  }
189
190
  canSendMessages() {
190
- return this.connectionState === 'connected' && this.ws !== null;
191
+ return this.connectionState === ConnectionState.CONNECTED;
191
192
  }
192
193
  sendQueuedMessage(queued) {
193
194
  try {
@@ -199,7 +200,7 @@ class WebSocketBiDiStream {
199
200
  if (ws.readyState !== undici.WebSocket.OPEN) {
200
201
  throw new Error(`WebSocket is not open (readyState: ${ws.readyState})`);
201
202
  }
202
- const binary = api.TxAPI_ClientMessage.toBinary(queued.message);
203
+ const binary = this.serializeClientMessage(queued.message);
203
204
  ws.send(binary);
204
205
  queued.resolve();
205
206
  }
@@ -208,25 +209,25 @@ class WebSocketBiDiStream {
208
209
  }
209
210
  }
210
211
  async drainSendQueue() {
211
- const POLL_INTERVAL_MS = 10;
212
+ const POLL_INTERVAL_MS = 5;
212
213
  while (this.sendQueue.length > 0) {
213
214
  await this.waitForCondition(() => this.sendQueue.length === 0, POLL_INTERVAL_MS);
214
215
  }
215
216
  }
216
217
  waitForCondition(condition, intervalMs) {
217
218
  return new Promise((resolve, reject) => {
218
- if (this.abortSignal.aborted) {
219
- return reject(this.toError(this.abortSignal.reason) ?? new Error('Stream aborted'));
219
+ if (this.options.abortSignal?.aborted) {
220
+ return reject(this.toError(this.options.abortSignal.reason) ?? new Error('Stream aborted'));
220
221
  }
221
222
  let timeoutId;
222
223
  const onAbort = () => {
223
224
  clearTimeout(timeoutId);
224
- reject(this.toError(this.abortSignal.reason) ?? new Error('Stream aborted'));
225
+ reject(this.toError(this.options.abortSignal?.reason) ?? new Error('Stream aborted'));
225
226
  };
226
- this.abortSignal.addEventListener('abort', onAbort, { once: true });
227
+ this.options.abortSignal?.addEventListener('abort', onAbort, { once: true });
227
228
  const check = () => {
228
229
  if (condition() || this.isStreamEnded()) {
229
- this.abortSignal.removeEventListener('abort', onAbort);
230
+ this.options.abortSignal?.removeEventListener('abort', onAbort);
230
231
  resolve();
231
232
  }
232
233
  else {
@@ -264,8 +265,8 @@ class WebSocketBiDiStream {
264
265
  }
265
266
  // Stream ended
266
267
  if (this.isStreamEnded()) {
267
- if (this.connectionError) {
268
- reject(this.connectionError);
268
+ if (this.lastError) {
269
+ reject(this.lastError);
269
270
  }
270
271
  else {
271
272
  resolve({ value: undefined, done: true });
@@ -276,20 +277,20 @@ class WebSocketBiDiStream {
276
277
  this.responseResolvers.push({ resolve, reject });
277
278
  });
278
279
  }
280
+ resolveAllPendingResponses() {
281
+ while (this.responseResolvers.length > 0) {
282
+ const resolver = this.responseResolvers.shift();
283
+ resolver.resolve({ value: undefined, done: true });
284
+ }
285
+ }
279
286
  // === Error Handling ===
280
287
  handleError(error) {
281
- if (this.isClosed())
282
- return;
283
- this.connectionState = 'closed';
284
- this.connectionError = error;
285
- this.reconnection.cancel();
286
- this.closeWebSocket();
287
- this.rejectAllPendingOperations(error);
288
+ this.lastError = error;
289
+ this.close();
288
290
  }
289
291
  rejectAllPendingOperations(error) {
290
- const err = error ?? this.createStreamClosedError();
291
- this.rejectAllSendOperations(err);
292
- this.rejectAllResponseResolvers(err);
292
+ this.rejectAllSendOperations(error);
293
+ this.rejectAllResponseResolvers(error);
293
294
  }
294
295
  rejectAllSendOperations(error) {
295
296
  while (this.sendQueue.length > 0) {
@@ -304,8 +305,8 @@ class WebSocketBiDiStream {
304
305
  }
305
306
  }
306
307
  createStreamClosedError() {
307
- if (this.abortSignal.aborted) {
308
- const reason = this.abortSignal.reason;
308
+ if (this.options.abortSignal?.aborted) {
309
+ const reason = this.options.abortSignal.reason;
309
310
  if (reason instanceof Error) {
310
311
  return reason;
311
312
  }
@@ -313,19 +314,36 @@ class WebSocketBiDiStream {
313
314
  }
314
315
  return new Error('Stream closed');
315
316
  }
316
- // === State Checks ===
317
- isConnectingOrConnected() {
318
- return this.connectionState === 'connecting'
319
- || this.connectionState === 'connected';
320
- }
321
- isClosed() {
322
- return this.connectionState === 'closed';
323
- }
317
+ // === Helpers ===
324
318
  isStreamEnded() {
325
- return this.isClosed() || this.abortSignal.aborted;
319
+ return this.connectionState === ConnectionState.CLOSED || this.options.abortSignal?.aborted || false;
326
320
  }
327
321
  toError(error) {
328
- return error instanceof Error ? error : new Error(String(error));
322
+ if (error instanceof Error)
323
+ return error;
324
+ if (error instanceof undici.ErrorEvent) {
325
+ const err = error.error;
326
+ // undici WebSocket throws TypeError with empty message on socket close
327
+ // (e.g., when connection is lost or server disconnects)
328
+ if (err instanceof TypeError && !err.message) {
329
+ return new errors.DisconnectedError('WebSocket connection closed unexpectedly');
330
+ }
331
+ return err instanceof Error ? err : new Error('WebSocket error', { cause: error });
332
+ }
333
+ return new Error(String(error));
334
+ }
335
+ /**
336
+ * Connection state progresses linearly from NEW to CLOSED and never goes back.
337
+ * This internal contract dramatically simplifies the internal stream state management.
338
+ *
339
+ * If you ever feel the need to make this contract less strict, think twice.
340
+ */
341
+ progressConnectionState(newState) {
342
+ if (newState < this.connectionState) {
343
+ return false;
344
+ }
345
+ this.connectionState = newState;
346
+ return true;
329
347
  }
330
348
  }
331
349
 
@@ -1 +1 @@
1
- {"version":3,"file":"websocket_stream.cjs","sources":["../../src/core/websocket_stream.ts"],"sourcesContent":["import { WebSocket } from 'undici';\nimport {\n TxAPI_ClientMessage as ClientMessageType,\n TxAPI_ServerMessage as ServerMessageType,\n} from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';\nimport type { BiDiStream } from './abstract_stream';\nimport Denque from 'denque';\nimport type { RetryConfig } from '../helpers/retry_strategy';\nimport { RetryStrategy } from '../helpers/retry_strategy';\n\ntype ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'closing' | 'closed';\n\ninterface QueuedMessage {\n message: ClientMessageType;\n resolve: () => void;\n reject: (error: Error) => void;\n}\n\ninterface ResponseResolver {\n resolve: (value: IteratorResult<ServerMessageType>) => void;\n reject: (error: Error) => void;\n}\n\n/**\n * WebSocket-based bidirectional stream implementation for LLTransaction.\n * Implements BiDiStream interface which is compatible with DuplexStreamingCall.\n */\nexport class WebSocketBiDiStream implements BiDiStream<ClientMessageType, ServerMessageType> {\n // Connection\n private ws: WebSocket | null = null;\n private connectionState: ConnectionState = 'disconnected';\n private readonly url: string;\n private readonly jwtToken?: string;\n private readonly abortSignal: AbortSignal;\n private readonly reconnection: RetryStrategy;\n\n // Send management\n private readonly sendQueue = new Denque<QueuedMessage>();\n private sendCompleted = false;\n\n // Response management\n private readonly responseQueue = new Denque<ServerMessageType>();\n private responseResolvers: ResponseResolver[] = [];\n\n // Error tracking\n private connectionError: Error | null = null;\n\n // === Public API ===\n\n public readonly requests = {\n send: async (message: ClientMessageType): Promise<void> => {\n this.validateSendState();\n return this.enqueueSend(message);\n },\n\n complete: async (): Promise<void> => {\n if (this.sendCompleted) return;\n\n this.sendCompleted = true;\n await this.drainSendQueue();\n this.closeConnection();\n },\n };\n\n public readonly responses: AsyncIterable<ServerMessageType> = {\n [Symbol.asyncIterator]: () => this.createResponseIterator(),\n };\n\n constructor(\n url: string,\n abortSignal: AbortSignal,\n jwtToken?: string,\n retryConfig: Partial<RetryConfig> = {},\n ) {\n this.url = url;\n this.jwtToken = jwtToken;\n this.abortSignal = abortSignal;\n\n this.reconnection = new RetryStrategy(retryConfig, {\n onRetry: () => { void this.connect(); },\n onMaxAttemptsReached: (error) => this.handleError(error),\n });\n\n if (abortSignal.aborted) {\n this.connectionState = 'closed';\n return;\n }\n\n this.attachAbortSignalHandler();\n void this.connect();\n }\n\n // === Connection Lifecycle ===\n\n private connect(): void {\n if (this.isConnectingOrConnected() || this.abortSignal.aborted) return;\n\n this.connectionState = 'connecting';\n this.connectionError = null;\n\n try {\n this.ws = this.createWebSocket();\n this.attachWebSocketHandlers();\n } catch (error) {\n this.connectionError = this.toError(error);\n this.connectionState = 'disconnected';\n this.reconnection.schedule();\n }\n }\n\n private createWebSocket(): WebSocket {\n const options = this.jwtToken\n ? { headers: { authorization: `Bearer ${this.jwtToken}` } }\n : undefined;\n\n const ws = new (WebSocket as any)(this.url, options);\n if (ws) {\n ws.binaryType = 'arraybuffer';\n }\n return ws;\n }\n\n private attachWebSocketHandlers(): void {\n if (!this.ws) return;\n\n this.ws.addEventListener('open', () => this.onOpen());\n this.ws.addEventListener('message', (event) => this.onMessage(event.data));\n this.ws.addEventListener('error', (error) => this.onError(error));\n this.ws.addEventListener('close', () => this.onClose());\n }\n\n private attachAbortSignalHandler(): void {\n this.abortSignal.addEventListener('abort', () => this.close());\n }\n\n private onOpen(): void {\n this.connectionState = 'connected';\n this.reconnection.reset();\n void this.processSendQueue();\n }\n\n private onClose(): void {\n this.ws = null;\n\n if (this.isClosed() || this.abortSignal.aborted) return;\n\n if (this.sendCompleted) {\n this.finalizeStream();\n } else {\n this.connectionState = 'disconnected';\n this.reconnection.schedule();\n }\n }\n\n private onError(error: unknown): void {\n this.handleError(this.toError(error));\n }\n\n private onMessage(data: unknown): void {\n try {\n const message = this.parseMessage(data);\n this.deliverResponse(message);\n } catch (error) {\n this.handleError(this.toError(error));\n }\n }\n\n private closeConnection(): void {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.ws.close();\n }\n }\n\n private close(): void {\n if (this.isClosed()) return;\n\n this.connectionState = 'closed';\n this.reconnection.cancel();\n this.closeWebSocket();\n this.rejectAllPendingOperations();\n }\n\n private closeWebSocket(): void {\n if (!this.ws) return;\n\n try {\n this.ws.close();\n } catch {\n // Suppress close errors\n }\n\n this.ws = null;\n }\n\n private finalizeStream(): void {\n this.connectionState = 'closed';\n this.resolveAllPendingResponses();\n }\n\n private resolveAllPendingResponses(): void {\n while (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.resolve({ value: undefined as any, done: true });\n }\n }\n\n private parseMessage(data: unknown): ServerMessageType {\n if (data instanceof ArrayBuffer) {\n return ServerMessageType.fromBinary(new Uint8Array(data));\n }\n\n throw new Error(`Unsupported message format: ${typeof data}`);\n }\n\n // === Send Queue Management ===\n\n private validateSendState(): void {\n if (this.sendCompleted) {\n throw new Error('Cannot send: stream already completed');\n }\n\n if (this.abortSignal.aborted) {\n throw new Error('Cannot send: stream aborted');\n }\n }\n\n private enqueueSend(message: ClientMessageType): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push({ message, resolve, reject });\n void this.processSendQueue();\n });\n }\n\n private processSendQueue(): void {\n if (!this.canSendMessages()) return;\n\n while (this.sendQueue.length > 0) {\n const queued = this.sendQueue.shift()!;\n this.sendQueuedMessage(queued);\n }\n }\n\n private canSendMessages(): boolean {\n return this.connectionState === 'connected' && this.ws !== null;\n }\n\n private sendQueuedMessage(queued: QueuedMessage): void {\n try {\n const ws = this.ws;\n if (!ws) {\n throw new Error('WebSocket is not connected');\n }\n\n // Check if WebSocket is in a valid state for sending\n if (ws.readyState !== WebSocket.OPEN) {\n throw new Error(`WebSocket is not open (readyState: ${ws.readyState})`);\n }\n\n const binary = ClientMessageType.toBinary(queued.message);\n ws.send(binary);\n queued.resolve();\n } catch (error) {\n queued.reject(this.toError(error));\n }\n }\n\n private async drainSendQueue(): Promise<void> {\n const POLL_INTERVAL_MS = 10;\n\n while (this.sendQueue.length > 0) {\n await this.waitForCondition(\n () => this.sendQueue.length === 0,\n POLL_INTERVAL_MS,\n );\n }\n }\n\n private waitForCondition(\n condition: () => boolean,\n intervalMs: number,\n ): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (this.abortSignal.aborted) {\n return reject(this.toError(this.abortSignal.reason) ?? new Error('Stream aborted'));\n }\n\n let timeoutId: ReturnType<typeof setTimeout>;\n const onAbort = () => {\n clearTimeout(timeoutId);\n reject(this.toError(this.abortSignal.reason) ?? new Error('Stream aborted'));\n };\n\n this.abortSignal.addEventListener('abort', onAbort, { once: true });\n\n const check = () => {\n if (condition() || this.isStreamEnded()) {\n this.abortSignal.removeEventListener('abort', onAbort);\n resolve();\n } else {\n timeoutId = setTimeout(check, intervalMs);\n }\n };\n\n check();\n });\n }\n\n // === Response Delivery ===\n\n private deliverResponse(message: ServerMessageType): void {\n if (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.resolve({ value: message, done: false });\n } else {\n this.responseQueue.push(message);\n }\n }\n\n private async *createResponseIterator(): AsyncIterator<ServerMessageType> {\n while (true) {\n const result = await this.nextResponse();\n\n if (result.done) break;\n\n yield result.value;\n }\n }\n\n private nextResponse(): Promise<IteratorResult<ServerMessageType>> {\n return new Promise<IteratorResult<ServerMessageType>>((resolve, reject) => {\n // Fast path: message already available\n if (this.responseQueue.length > 0) {\n const message = this.responseQueue.shift()!;\n resolve({ value: message, done: false });\n return;\n }\n\n // Stream ended\n if (this.isStreamEnded()) {\n if (this.connectionError) {\n reject(this.connectionError);\n } else {\n resolve({ value: undefined as any, done: true });\n }\n return;\n }\n\n // Wait for next message\n this.responseResolvers.push({ resolve, reject });\n });\n }\n\n // === Error Handling ===\n private handleError(error: Error): void {\n if (this.isClosed()) return;\n\n this.connectionState = 'closed';\n this.connectionError = error;\n this.reconnection.cancel();\n this.closeWebSocket();\n this.rejectAllPendingOperations(error);\n }\n\n private rejectAllPendingOperations(error?: Error): void {\n const err = error ?? this.createStreamClosedError();\n this.rejectAllSendOperations(err);\n this.rejectAllResponseResolvers(err);\n }\n\n private rejectAllSendOperations(error: Error): void {\n while (this.sendQueue.length > 0) {\n const queued = this.sendQueue.shift()!;\n queued.reject(error);\n }\n }\n\n private rejectAllResponseResolvers(error: Error): void {\n while (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.reject(error);\n }\n }\n\n private createStreamClosedError(): Error {\n if (this.abortSignal.aborted) {\n const reason = this.abortSignal.reason;\n if (reason instanceof Error) {\n return reason;\n }\n return new Error('Stream aborted', { cause: reason });\n }\n return new Error('Stream closed');\n }\n // === State Checks ===\n\n private isConnectingOrConnected(): boolean {\n return this.connectionState === 'connecting'\n || this.connectionState === 'connected';\n }\n\n private isClosed(): boolean {\n return this.connectionState === 'closed';\n }\n\n private isStreamEnded(): boolean {\n return this.isClosed() || this.abortSignal.aborted;\n }\n\n private toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n }\n}\n"],"names":["RetryStrategy","WebSocket","ServerMessageType","ClientMessageType"],"mappings":"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"}
1
+ {"version":3,"file":"websocket_stream.cjs","sources":["../../src/core/websocket_stream.ts"],"sourcesContent":["import { WebSocket, type WebSocketInit, type Dispatcher, ErrorEvent } from 'undici';\nimport type { BiDiStream } from './abstract_stream';\nimport Denque from 'denque';\nimport type { RetryConfig } from '../helpers/retry_strategy';\nimport { RetryStrategy } from '../helpers/retry_strategy';\nimport { DisconnectedError } from './errors';\n\ninterface QueuedMessage<InType extends object> {\n message: InType;\n resolve: () => void;\n reject: (error: Error) => void;\n}\n\ninterface ResponseResolver<OutType extends object> {\n resolve: (value: IteratorResult<OutType>) => void;\n reject: (error: Error) => void;\n}\n\nenum ConnectionState {\n NEW = 0,\n CONNECTING = 1,\n CONNECTED = 2,\n CLOSING = 3,\n CLOSED = 4,\n}\n\nexport type WSStreamOptions<ClientMsg extends object, ServerMsg extends object> = {\n abortSignal?: AbortSignal;\n\n dispatcher?: Dispatcher;\n jwtToken?: string;\n retryConfig?: Partial<RetryConfig>;\n\n onComplete?: (stream: WebSocketBiDiStream<ClientMsg, ServerMsg>) => void | Promise<void>;\n};\n\n/**\n * WebSocket-based bidirectional stream implementation for LLTransaction.\n * Implements BiDiStream interface which is compatible with DuplexStreamingCall.\n */\nexport class WebSocketBiDiStream<ClientMsg extends object, ServerMsg extends object> implements BiDiStream<ClientMsg, ServerMsg> {\n // Connection\n private ws: WebSocket | null = null;\n private connectionState: ConnectionState = ConnectionState.NEW;\n private readonly reconnection: RetryStrategy;\n\n // Send management\n private readonly sendQueue = new Denque<QueuedMessage<ClientMsg>>();\n private sendCompleted = false;\n private readonly onComplete: (stream: WebSocketBiDiStream<ClientMsg, ServerMsg>) => void | Promise<void>;\n\n // Response management\n private readonly responseQueue = new Denque<ServerMsg>();\n private responseResolvers: ResponseResolver<ServerMsg>[] = [];\n\n // Error tracking\n private lastError?: Error;\n\n // === Public API ===\n\n public readonly requests = {\n send: async (message: ClientMsg): Promise<void> => {\n return await this.enqueueSend(message);\n },\n\n complete: async (): Promise<void> => {\n if (this.sendCompleted) return;\n\n await this.drainSendQueue(); // ensure we sent all already queued messages before closing the stream\n try {\n await this.onComplete(this); // custom onComplete may send additional messages\n } catch (_: unknown) {\n // When 'complete' gets called concurrently with connection break or over a broken\n // transaction stream (server decided it should drop transaction), server would close\n // connection anyway on its end. We can safely ignore error here and just continue working.\n }\n this.sendCompleted = true;\n },\n };\n\n public readonly responses: AsyncIterable<ServerMsg> = {\n [Symbol.asyncIterator]: () => this.createResponseIterator(),\n };\n\n public close(): void {\n this.reconnection.cancel();\n\n if (this.connectionState < ConnectionState.CONNECTED) {\n // Never reached CONNECTED state. ws.close() will never trigger 'close' event.\n this.ws?.close();\n this.onClose();\n return;\n }\n\n if (!this.progressConnectionState(ConnectionState.CLOSING)) return;\n this.ws!.close();\n }\n\n constructor(\n private readonly url: string,\n private readonly serializeClientMessage: (message: ClientMsg) => Uint8Array,\n private readonly parseServerMessage: (data: Uint8Array) => ServerMsg,\n private readonly options: WSStreamOptions<ClientMsg, ServerMsg> = {},\n ) {\n this.onComplete = this.options.onComplete ?? ((stream) => stream.close());\n\n const retryConfig = this.options.retryConfig ?? {};\n this.reconnection = new RetryStrategy(retryConfig, {\n onRetry: () => { void this.connect(); },\n onMaxAttemptsReached: (error) => this.handleError(error),\n });\n\n if (this.options.abortSignal?.aborted) {\n this.progressConnectionState(ConnectionState.CLOSED);\n return;\n }\n\n this.options.abortSignal?.addEventListener('abort', () => this.close());\n this.connect();\n }\n\n // === Connection Lifecycle ===\n\n private connect(): void {\n if (this.options.abortSignal?.aborted) return;\n\n // Prevent reconnecting after first successful connection.\n if (!this.progressConnectionState(ConnectionState.CONNECTING)) return;\n\n try {\n this.ws = this.createWebSocket();\n\n this.ws.addEventListener('open', () => this.onOpen());\n this.ws.addEventListener('message', (event) => this.onMessage(event.data));\n this.ws.addEventListener('error', (error) => this.onError(error));\n this.ws.addEventListener('close', () => this.onClose());\n } catch (error) {\n this.lastError = this.toError(error);\n this.reconnection.schedule();\n }\n }\n\n private createWebSocket(): WebSocket {\n const options: WebSocketInit = {};\n\n if (this.options.jwtToken) options.headers = { authorization: `Bearer ${this.options.jwtToken}` };\n if (this.options.dispatcher) options.dispatcher = this.options.dispatcher;\n\n const ws = new WebSocket(this.url, options);\n ws.binaryType = 'arraybuffer';\n return ws;\n }\n\n private onOpen(): void {\n this.progressConnectionState(ConnectionState.CONNECTED);\n this.processSendQueue();\n }\n\n private onMessage(data: unknown): void {\n if (!(data instanceof ArrayBuffer)) {\n this.handleError(new Error(`Unexpected WS message format: ${typeof data}`));\n return;\n }\n\n try {\n const message = this.parseServerMessage(new Uint8Array(data));\n this.deliverResponse(message);\n } catch (error) {\n this.handleError(this.toError(error));\n }\n }\n\n private onError(error: unknown): void {\n if (this.connectionState < ConnectionState.CONNECTED) {\n // Try to connect several times until we succeed or run out of attempts.\n this.lastError = this.toError(error);\n this.reconnection.schedule();\n return;\n }\n\n this.handleError(this.toError(error));\n }\n\n private onClose(): void {\n this.progressConnectionState(ConnectionState.CLOSED);\n\n // If abort signal was triggered, use that as the error source\n if (this.options.abortSignal?.aborted && !this.lastError) {\n const reason = this.options.abortSignal.reason;\n if (reason instanceof Error) {\n this.lastError = reason;\n } else if (reason !== undefined) {\n this.lastError = new Error(String(reason), { cause: reason });\n } else {\n this.lastError = this.createStreamClosedError();\n }\n }\n\n if (!this.lastError) {\n this.rejectAllSendOperations(this.createStreamClosedError());\n this.resolveAllPendingResponses(); // unblock active async iterator\n } else {\n this.rejectAllPendingOperations(this.lastError);\n }\n }\n\n // === Send Queue Management ===\n\n private enqueueSend(message: ClientMsg): Promise<void> {\n if (this.sendCompleted) {\n throw new Error('Cannot send: stream already completed');\n }\n\n if (this.options.abortSignal?.aborted) {\n throw new Error('Cannot send: stream aborted');\n }\n\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push({ message, resolve, reject });\n this.processSendQueue();\n });\n }\n\n private processSendQueue(): void {\n if (!this.canSendMessages()) return;\n\n while (this.sendQueue.length > 0) {\n const queued = this.sendQueue.shift()!;\n this.sendQueuedMessage(queued);\n }\n }\n\n private canSendMessages(): boolean {\n return this.connectionState === ConnectionState.CONNECTED;\n }\n\n private sendQueuedMessage(queued: QueuedMessage<ClientMsg>): void {\n try {\n const ws = this.ws;\n if (!ws) {\n throw new Error('WebSocket is not connected');\n }\n\n // Check if WebSocket is in a valid state for sending\n if (ws.readyState !== WebSocket.OPEN) {\n throw new Error(`WebSocket is not open (readyState: ${ws.readyState})`);\n }\n\n const binary = this.serializeClientMessage(queued.message);\n ws.send(binary);\n queued.resolve();\n } catch (error) {\n queued.reject(this.toError(error));\n }\n }\n\n private async drainSendQueue(): Promise<void> {\n const POLL_INTERVAL_MS = 5;\n\n while (this.sendQueue.length > 0) {\n await this.waitForCondition(\n () => this.sendQueue.length === 0,\n POLL_INTERVAL_MS,\n );\n }\n }\n\n private waitForCondition(\n condition: () => boolean,\n intervalMs: number,\n ): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (this.options.abortSignal?.aborted) {\n return reject(this.toError(this.options.abortSignal.reason) ?? new Error('Stream aborted'));\n }\n\n let timeoutId: ReturnType<typeof setTimeout>;\n const onAbort = () => {\n clearTimeout(timeoutId);\n reject(this.toError(this.options.abortSignal?.reason) ?? new Error('Stream aborted'));\n };\n\n this.options.abortSignal?.addEventListener('abort', onAbort, { once: true });\n\n const check = () => {\n if (condition() || this.isStreamEnded()) {\n this.options.abortSignal?.removeEventListener('abort', onAbort);\n resolve();\n } else {\n timeoutId = setTimeout(check, intervalMs);\n }\n };\n\n check();\n });\n }\n\n // === Response Delivery ===\n\n private deliverResponse(message: ServerMsg): void {\n if (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.resolve({ value: message, done: false });\n } else {\n this.responseQueue.push(message);\n }\n }\n\n private async *createResponseIterator(): AsyncIterator<ServerMsg> {\n while (true) {\n const result = await this.nextResponse();\n\n if (result.done) break;\n\n yield result.value;\n }\n }\n\n private nextResponse(): Promise<IteratorResult<ServerMsg>> {\n return new Promise<IteratorResult<ServerMsg>>((resolve, reject) => {\n // Fast path: message already available\n if (this.responseQueue.length > 0) {\n const message = this.responseQueue.shift()!;\n resolve({ value: message, done: false });\n return;\n }\n\n // Stream ended\n if (this.isStreamEnded()) {\n if (this.lastError) {\n reject(this.lastError);\n } else {\n resolve({ value: undefined as any, done: true });\n }\n return;\n }\n\n // Wait for next message\n this.responseResolvers.push({ resolve, reject });\n });\n }\n\n private resolveAllPendingResponses(): void {\n while (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.resolve({ value: undefined as any, done: true });\n }\n }\n\n // === Error Handling ===\n\n private handleError(error: Error): void {\n this.lastError = error;\n this.close();\n }\n\n private rejectAllPendingOperations(error: Error): void {\n this.rejectAllSendOperations(error);\n this.rejectAllResponseResolvers(error);\n }\n\n private rejectAllSendOperations(error: Error): void {\n while (this.sendQueue.length > 0) {\n const queued = this.sendQueue.shift()!;\n queued.reject(error);\n }\n }\n\n private rejectAllResponseResolvers(error: Error): void {\n while (this.responseResolvers.length > 0) {\n const resolver = this.responseResolvers.shift()!;\n resolver.reject(error);\n }\n }\n\n private createStreamClosedError(): Error {\n if (this.options.abortSignal?.aborted) {\n const reason = this.options.abortSignal.reason;\n if (reason instanceof Error) {\n return reason;\n }\n return new Error('Stream aborted', { cause: reason });\n }\n\n return new Error('Stream closed');\n }\n\n // === Helpers ===\n\n private isStreamEnded(): boolean {\n return this.connectionState === ConnectionState.CLOSED || this.options.abortSignal?.aborted || false;\n }\n\n private toError(error: unknown): Error {\n if (error instanceof Error) return error;\n if (error instanceof ErrorEvent) {\n const err = error.error;\n // undici WebSocket throws TypeError with empty message on socket close\n // (e.g., when connection is lost or server disconnects)\n if (err instanceof TypeError && !err.message) {\n return new DisconnectedError('WebSocket connection closed unexpectedly');\n }\n return err instanceof Error ? err : new Error('WebSocket error', { cause: error });\n }\n return new Error(String(error));\n }\n\n /**\n * Connection state progresses linearly from NEW to CLOSED and never goes back.\n * This internal contract dramatically simplifies the internal stream state management.\n *\n * If you ever feel the need to make this contract less strict, think twice.\n */\n private progressConnectionState(newState: ConnectionState): boolean {\n if (newState < this.connectionState) {\n return false;\n }\n this.connectionState = newState;\n return true;\n }\n}\n"],"names":["RetryStrategy","WebSocket","ErrorEvent","DisconnectedError"],"mappings":"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"}
@@ -1,43 +1,44 @@
1
- import { TxAPI_ClientMessage as ClientMessageType, TxAPI_ServerMessage as ServerMessageType } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';
1
+ import { type Dispatcher } from 'undici';
2
2
  import type { BiDiStream } from './abstract_stream';
3
3
  import type { RetryConfig } from '../helpers/retry_strategy';
4
+ export type WSStreamOptions<ClientMsg extends object, ServerMsg extends object> = {
5
+ abortSignal?: AbortSignal;
6
+ dispatcher?: Dispatcher;
7
+ jwtToken?: string;
8
+ retryConfig?: Partial<RetryConfig>;
9
+ onComplete?: (stream: WebSocketBiDiStream<ClientMsg, ServerMsg>) => void | Promise<void>;
10
+ };
4
11
  /**
5
12
  * WebSocket-based bidirectional stream implementation for LLTransaction.
6
13
  * Implements BiDiStream interface which is compatible with DuplexStreamingCall.
7
14
  */
8
- export declare class WebSocketBiDiStream implements BiDiStream<ClientMessageType, ServerMessageType> {
15
+ export declare class WebSocketBiDiStream<ClientMsg extends object, ServerMsg extends object> implements BiDiStream<ClientMsg, ServerMsg> {
16
+ private readonly url;
17
+ private readonly serializeClientMessage;
18
+ private readonly parseServerMessage;
19
+ private readonly options;
9
20
  private ws;
10
21
  private connectionState;
11
- private readonly url;
12
- private readonly jwtToken?;
13
- private readonly abortSignal;
14
22
  private readonly reconnection;
15
23
  private readonly sendQueue;
16
24
  private sendCompleted;
25
+ private readonly onComplete;
17
26
  private readonly responseQueue;
18
27
  private responseResolvers;
19
- private connectionError;
28
+ private lastError?;
20
29
  readonly requests: {
21
- send: (message: ClientMessageType) => Promise<void>;
30
+ send: (message: ClientMsg) => Promise<void>;
22
31
  complete: () => Promise<void>;
23
32
  };
24
- readonly responses: AsyncIterable<ServerMessageType>;
25
- constructor(url: string, abortSignal: AbortSignal, jwtToken?: string, retryConfig?: Partial<RetryConfig>);
33
+ readonly responses: AsyncIterable<ServerMsg>;
34
+ close(): void;
35
+ constructor(url: string, serializeClientMessage: (message: ClientMsg) => Uint8Array, parseServerMessage: (data: Uint8Array) => ServerMsg, options?: WSStreamOptions<ClientMsg, ServerMsg>);
26
36
  private connect;
27
37
  private createWebSocket;
28
- private attachWebSocketHandlers;
29
- private attachAbortSignalHandler;
30
38
  private onOpen;
31
- private onClose;
32
- private onError;
33
39
  private onMessage;
34
- private closeConnection;
35
- private close;
36
- private closeWebSocket;
37
- private finalizeStream;
38
- private resolveAllPendingResponses;
39
- private parseMessage;
40
- private validateSendState;
40
+ private onError;
41
+ private onClose;
41
42
  private enqueueSend;
42
43
  private processSendQueue;
43
44
  private canSendMessages;
@@ -47,14 +48,20 @@ export declare class WebSocketBiDiStream implements BiDiStream<ClientMessageType
47
48
  private deliverResponse;
48
49
  private createResponseIterator;
49
50
  private nextResponse;
51
+ private resolveAllPendingResponses;
50
52
  private handleError;
51
53
  private rejectAllPendingOperations;
52
54
  private rejectAllSendOperations;
53
55
  private rejectAllResponseResolvers;
54
56
  private createStreamClosedError;
55
- private isConnectingOrConnected;
56
- private isClosed;
57
57
  private isStreamEnded;
58
58
  private toError;
59
+ /**
60
+ * Connection state progresses linearly from NEW to CLOSED and never goes back.
61
+ * This internal contract dramatically simplifies the internal stream state management.
62
+ *
63
+ * If you ever feel the need to make this contract less strict, think twice.
64
+ */
65
+ private progressConnectionState;
59
66
  }
60
67
  //# sourceMappingURL=websocket_stream.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"websocket_stream.d.ts","sourceRoot":"","sources":["../../src/core/websocket_stream.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,IAAI,iBAAiB,EACxC,mBAAmB,IAAI,iBAAiB,EACzC,MAAM,+DAA+D,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAgB7D;;;GAGG;AACH,qBAAa,mBAAoB,YAAW,UAAU,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAE1F,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,eAAe,CAAmC;IAC1D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAG7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;IACzD,OAAO,CAAC,aAAa,CAAS;IAG9B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmC;IACjE,OAAO,CAAC,iBAAiB,CAA0B;IAGnD,OAAO,CAAC,eAAe,CAAsB;IAI7C,SAAgB,QAAQ;wBACA,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAAC;wBAKnC,OAAO,CAAC,IAAI,CAAC;MAOjC;IAEF,SAAgB,SAAS,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAEzD;gBAGA,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,WAAW,EACxB,QAAQ,CAAC,EAAE,MAAM,EACjB,WAAW,GAAE,OAAO,CAAC,WAAW,CAAM;IAsBxC,OAAO,CAAC,OAAO;IAgBf,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,wBAAwB;IAIhC,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,OAAO;IAaf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,KAAK;IASb,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,iBAAiB;YAoBX,cAAc;IAW5B,OAAO,CAAC,gBAAgB;IAgCxB,OAAO,CAAC,eAAe;YASR,sBAAsB;IAUrC,OAAO,CAAC,YAAY;IAyBpB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,0BAA0B;IAMlC,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,uBAAuB;IAK/B,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,OAAO;CAGhB"}
1
+ {"version":3,"file":"websocket_stream.d.ts","sourceRoot":"","sources":["../../src/core/websocket_stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,KAAK,UAAU,EAAc,MAAM,QAAQ,CAAC;AACpF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAuB7D,MAAM,MAAM,eAAe,CAAC,SAAS,SAAS,MAAM,EAAE,SAAS,SAAS,MAAM,IAAI;IAChF,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAEnC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1F,CAAC;AAEF;;;GAGG;AACH,qBAAa,mBAAmB,CAAC,SAAS,SAAS,MAAM,EAAE,SAAS,SAAS,MAAM,CAAE,YAAW,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC;IA2D5H,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO;IA5D1B,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,eAAe,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAG7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0C;IACpE,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA8E;IAGzG,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA2B;IACzD,OAAO,CAAC,iBAAiB,CAAqC;IAG9D,OAAO,CAAC,SAAS,CAAC,CAAQ;IAI1B,SAAgB,QAAQ;wBACA,SAAS,KAAG,OAAO,CAAC,IAAI,CAAC;wBAI3B,OAAO,CAAC,IAAI,CAAC;MAajC;IAEF,SAAgB,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC,CAEjD;IAEK,KAAK,IAAI,IAAI;gBAeD,GAAG,EAAE,MAAM,EACX,sBAAsB,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,UAAU,EAC1D,kBAAkB,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,SAAS,EACnD,OAAO,GAAE,eAAe,CAAC,SAAS,EAAE,SAAS,CAAM;IAqBtE,OAAO,CAAC,OAAO;IAmBf,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,SAAS;IAcjB,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,OAAO;IAyBf,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,iBAAiB;YAoBX,cAAc;IAW5B,OAAO,CAAC,gBAAgB;IAgCxB,OAAO,CAAC,eAAe;YASR,sBAAsB;IAUrC,OAAO,CAAC,YAAY;IAwBpB,OAAO,CAAC,0BAA0B;IASlC,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,0BAA0B;IAKlC,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,uBAAuB;IAc/B,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,OAAO;IAcf;;;;;OAKG;IACH,OAAO,CAAC,uBAAuB;CAOhC"}