@replit/river 0.207.2 → 0.208.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.
Files changed (65) hide show
  1. package/dist/adapter-ChksXKVN.d.ts +46 -0
  2. package/dist/adapter-Cuc4JtfV.d.cts +46 -0
  3. package/dist/chunk-2JNVDUMN.js +2238 -0
  4. package/dist/chunk-2JNVDUMN.js.map +1 -0
  5. package/dist/{chunk-4HE7UYRL.js → chunk-DKW3GC3M.js} +6 -5
  6. package/dist/{chunk-4HE7UYRL.js.map → chunk-DKW3GC3M.js.map} +1 -1
  7. package/dist/{chunk-46IVOKJU.js → chunk-ETZAHFGQ.js} +80 -61
  8. package/dist/chunk-ETZAHFGQ.js.map +1 -0
  9. package/dist/codec/index.cjs +157 -23
  10. package/dist/codec/index.cjs.map +1 -1
  11. package/dist/codec/index.d.cts +5 -1
  12. package/dist/codec/index.d.ts +5 -1
  13. package/dist/codec/index.js +6 -20
  14. package/dist/codec/index.js.map +1 -1
  15. package/dist/connection-BF4zg6Qv.d.cts +35 -0
  16. package/dist/{connection-a18e31d5.d.ts → connection-Donr3JRB.d.ts} +4 -3
  17. package/dist/index-C9tpZjBN.d.cts +37 -0
  18. package/dist/index-D8IOd3LG.d.ts +37 -0
  19. package/dist/logging/index.d.cts +2 -1
  20. package/dist/logging/index.d.ts +2 -1
  21. package/dist/{message-ffacb98a.d.ts → message-Di94OL80.d.cts} +1 -35
  22. package/dist/message-Di94OL80.d.ts +108 -0
  23. package/dist/router/index.cjs +62 -43
  24. package/dist/router/index.cjs.map +1 -1
  25. package/dist/router/index.d.cts +27 -7
  26. package/dist/router/index.d.ts +27 -7
  27. package/dist/router/index.js +1 -1
  28. package/dist/testUtil/index.cjs +828 -725
  29. package/dist/testUtil/index.cjs.map +1 -1
  30. package/dist/testUtil/index.d.cts +5 -4
  31. package/dist/testUtil/index.d.ts +5 -4
  32. package/dist/testUtil/index.js +23 -25
  33. package/dist/testUtil/index.js.map +1 -1
  34. package/dist/transport/impls/ws/client.cjs +293 -233
  35. package/dist/transport/impls/ws/client.cjs.map +1 -1
  36. package/dist/transport/impls/ws/client.d.cts +6 -5
  37. package/dist/transport/impls/ws/client.d.ts +6 -5
  38. package/dist/transport/impls/ws/client.js +5 -7
  39. package/dist/transport/impls/ws/client.js.map +1 -1
  40. package/dist/transport/impls/ws/server.cjs +269 -200
  41. package/dist/transport/impls/ws/server.cjs.map +1 -1
  42. package/dist/transport/impls/ws/server.d.cts +6 -5
  43. package/dist/transport/impls/ws/server.d.ts +6 -5
  44. package/dist/transport/impls/ws/server.js +5 -7
  45. package/dist/transport/impls/ws/server.js.map +1 -1
  46. package/dist/transport/index.cjs +438 -342
  47. package/dist/transport/index.cjs.map +1 -1
  48. package/dist/transport/index.d.cts +7 -6
  49. package/dist/transport/index.d.ts +7 -6
  50. package/dist/transport/index.js +5 -10
  51. package/dist/transport-CCaWx1Rb.d.cts +1566 -0
  52. package/dist/{services-43528f4b.d.ts → transport-CZb3vdB4.d.ts} +294 -293
  53. package/dist/{wslike-e0b32dd5.d.ts → wslike-Dng9H1C7.d.cts} +1 -1
  54. package/dist/wslike-Dng9H1C7.d.ts +40 -0
  55. package/package.json +3 -3
  56. package/dist/chunk-24EWYOGK.js +0 -1287
  57. package/dist/chunk-24EWYOGK.js.map +0 -1
  58. package/dist/chunk-46IVOKJU.js.map +0 -1
  59. package/dist/chunk-A7RGOVRV.js +0 -438
  60. package/dist/chunk-A7RGOVRV.js.map +0 -1
  61. package/dist/chunk-AJGIY2UB.js +0 -56
  62. package/dist/chunk-AJGIY2UB.js.map +0 -1
  63. package/dist/chunk-XV4RQ62N.js +0 -377
  64. package/dist/chunk-XV4RQ62N.js.map +0 -1
  65. package/dist/types-3e5768ec.d.ts +0 -20
@@ -1,1287 +0,0 @@
1
- import {
2
- OpaqueTransportMessageSchema,
3
- createConnectionTelemetryInfo,
4
- createSessionTelemetryInfo,
5
- generateId,
6
- getTracer,
7
- isAck
8
- } from "./chunk-46IVOKJU.js";
9
- import {
10
- BaseLogger,
11
- createLogProxy
12
- } from "./chunk-CC7RN7GI.js";
13
- import {
14
- NaiveJsonCodec
15
- } from "./chunk-AJGIY2UB.js";
16
-
17
- // transport/options.ts
18
- var defaultTransportOptions = {
19
- heartbeatIntervalMs: 1e3,
20
- heartbeatsUntilDead: 2,
21
- sessionDisconnectGraceMs: 5e3,
22
- connectionTimeoutMs: 2e3,
23
- handshakeTimeoutMs: 1e3,
24
- enableTransparentSessionReconnects: true,
25
- codec: NaiveJsonCodec
26
- };
27
- var defaultConnectionRetryOptions = {
28
- baseIntervalMs: 150,
29
- maxJitterMs: 200,
30
- maxBackoffMs: 32e3,
31
- attemptBudgetCapacity: 5,
32
- budgetRestoreIntervalMs: 200
33
- };
34
- var defaultClientTransportOptions = {
35
- ...defaultTransportOptions,
36
- ...defaultConnectionRetryOptions
37
- };
38
- var defaultServerTransportOptions = {
39
- ...defaultTransportOptions
40
- };
41
-
42
- // transport/sessionStateMachine/common.ts
43
- import { Value } from "@sinclair/typebox/value";
44
- var SessionState = /* @__PURE__ */ ((SessionState2) => {
45
- SessionState2["NoConnection"] = "NoConnection";
46
- SessionState2["BackingOff"] = "BackingOff";
47
- SessionState2["Connecting"] = "Connecting";
48
- SessionState2["Handshaking"] = "Handshaking";
49
- SessionState2["Connected"] = "Connected";
50
- SessionState2["WaitingForHandshake"] = "WaitingForHandshake";
51
- return SessionState2;
52
- })(SessionState || {});
53
- var ERR_CONSUMED = `session state has been consumed and is no longer valid`;
54
- var StateMachineState = class {
55
- /*
56
- * Whether this state has been consumed
57
- * and we've moved on to another state
58
- */
59
- _isConsumed;
60
- /**
61
- * Cleanup this state machine state and mark it as consumed.
62
- * After calling close, it is an error to access any properties on the state.
63
- * You should never need to call this as a consumer.
64
- *
65
- * If you're looking to close the session from the client,
66
- * use `.hardDisconnect` on the client transport.
67
- */
68
- close() {
69
- this._handleClose();
70
- }
71
- constructor() {
72
- this._isConsumed = false;
73
- return new Proxy(this, {
74
- get(target, prop) {
75
- if (prop === "_isConsumed" || prop === "id" || prop === "state") {
76
- return Reflect.get(target, prop);
77
- }
78
- if (prop === "_handleStateExit") {
79
- return () => {
80
- target._isConsumed = true;
81
- target._handleStateExit();
82
- };
83
- }
84
- if (prop === "_handleClose") {
85
- return () => {
86
- target._isConsumed = true;
87
- target._handleStateExit();
88
- target._handleClose();
89
- };
90
- }
91
- if (target._isConsumed) {
92
- throw new Error(
93
- `${ERR_CONSUMED}: getting ${prop.toString()} on consumed state`
94
- );
95
- }
96
- return Reflect.get(target, prop);
97
- },
98
- set(target, prop, value) {
99
- if (target._isConsumed) {
100
- throw new Error(
101
- `${ERR_CONSUMED}: setting ${prop.toString()} on consumed state`
102
- );
103
- }
104
- return Reflect.set(target, prop, value);
105
- }
106
- });
107
- }
108
- };
109
- var CommonSession = class extends StateMachineState {
110
- from;
111
- options;
112
- tracer;
113
- log;
114
- constructor({ from, options, log, tracer }) {
115
- super();
116
- this.from = from;
117
- this.options = options;
118
- this.log = log;
119
- this.tracer = tracer;
120
- }
121
- parseMsg(msg) {
122
- const parsedMsg = this.options.codec.fromBuffer(msg);
123
- if (parsedMsg === null) {
124
- this.log?.error(
125
- `received malformed msg: ${Buffer.from(msg).toString("base64")}`,
126
- this.loggingMetadata
127
- );
128
- return null;
129
- }
130
- if (!Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
131
- this.log?.error(`received invalid msg: ${JSON.stringify(parsedMsg)}`, {
132
- ...this.loggingMetadata,
133
- validationErrors: [
134
- ...Value.Errors(OpaqueTransportMessageSchema, parsedMsg)
135
- ]
136
- });
137
- return null;
138
- }
139
- return parsedMsg;
140
- }
141
- };
142
- var IdentifiedSession = class extends CommonSession {
143
- id;
144
- telemetry;
145
- to;
146
- protocolVersion;
147
- /**
148
- * Index of the message we will send next (excluding handshake)
149
- */
150
- seq;
151
- /**
152
- * Last seq we sent over the wire this session (excluding handshake) and retransmissions
153
- */
154
- seqSent;
155
- /**
156
- * Number of unique messages we've received this session (excluding handshake)
157
- */
158
- ack;
159
- sendBuffer;
160
- constructor(props) {
161
- const {
162
- id,
163
- to,
164
- seq,
165
- ack,
166
- sendBuffer,
167
- telemetry,
168
- log,
169
- protocolVersion,
170
- seqSent: messagesSent
171
- } = props;
172
- super(props);
173
- this.id = id;
174
- this.to = to;
175
- this.seq = seq;
176
- this.ack = ack;
177
- this.sendBuffer = sendBuffer;
178
- this.telemetry = telemetry;
179
- this.log = log;
180
- this.protocolVersion = protocolVersion;
181
- this.seqSent = messagesSent;
182
- }
183
- get loggingMetadata() {
184
- const metadata = {
185
- clientId: this.from,
186
- connectedTo: this.to,
187
- sessionId: this.id
188
- };
189
- if (this.telemetry.span.isRecording()) {
190
- const spanContext = this.telemetry.span.spanContext();
191
- metadata.telemetry = {
192
- traceId: spanContext.traceId,
193
- spanId: spanContext.spanId
194
- };
195
- }
196
- return metadata;
197
- }
198
- constructMsg(partialMsg) {
199
- if (this._isConsumed) {
200
- throw new Error(ERR_CONSUMED);
201
- }
202
- const msg = {
203
- ...partialMsg,
204
- id: generateId(),
205
- to: this.to,
206
- from: this.from,
207
- seq: this.seq,
208
- ack: this.ack
209
- };
210
- this.seq++;
211
- return msg;
212
- }
213
- nextSeq() {
214
- return this.sendBuffer.length > 0 ? this.sendBuffer[0].seq : this.seq;
215
- }
216
- send(msg) {
217
- const constructedMsg = this.constructMsg(msg);
218
- this.sendBuffer.push(constructedMsg);
219
- return constructedMsg.id;
220
- }
221
- _handleStateExit() {
222
- }
223
- _handleClose() {
224
- this.sendBuffer.length = 0;
225
- this.telemetry.span.end();
226
- }
227
- };
228
- var IdentifiedSessionWithGracePeriod = class extends IdentifiedSession {
229
- graceExpiryTime;
230
- gracePeriodTimeout;
231
- listeners;
232
- constructor(props) {
233
- super(props);
234
- this.listeners = props.listeners;
235
- this.graceExpiryTime = props.graceExpiryTime;
236
- this.gracePeriodTimeout = setTimeout(() => {
237
- this.listeners.onSessionGracePeriodElapsed();
238
- }, this.graceExpiryTime - Date.now());
239
- }
240
- _handleStateExit() {
241
- super._handleStateExit();
242
- if (this.gracePeriodTimeout) {
243
- clearTimeout(this.gracePeriodTimeout);
244
- this.gracePeriodTimeout = void 0;
245
- }
246
- }
247
- _handleClose() {
248
- super._handleClose();
249
- }
250
- };
251
-
252
- // transport/sessionStateMachine/SessionConnecting.ts
253
- var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
254
- state = "Connecting" /* Connecting */;
255
- connPromise;
256
- listeners;
257
- connectionTimeout;
258
- constructor(props) {
259
- super(props);
260
- this.connPromise = props.connPromise;
261
- this.listeners = props.listeners;
262
- this.connPromise.then(
263
- (conn) => {
264
- if (this._isConsumed)
265
- return;
266
- this.listeners.onConnectionEstablished(conn);
267
- },
268
- (err) => {
269
- if (this._isConsumed)
270
- return;
271
- this.listeners.onConnectionFailed(err);
272
- }
273
- );
274
- this.connectionTimeout = setTimeout(() => {
275
- this.listeners.onConnectionTimeout();
276
- }, this.options.connectionTimeoutMs);
277
- }
278
- // close a pending connection if it resolves, ignore errors if the promise
279
- // ends up rejected anyways
280
- bestEffortClose() {
281
- const logger = this.log;
282
- const metadata = this.loggingMetadata;
283
- this.connPromise.then((conn) => {
284
- conn.close();
285
- logger?.info(
286
- "connection eventually resolved but session has transitioned, closed connection",
287
- {
288
- ...metadata,
289
- ...conn.loggingMetadata
290
- }
291
- );
292
- }).catch(() => {
293
- });
294
- }
295
- _handleStateExit() {
296
- super._handleStateExit();
297
- if (this.connectionTimeout) {
298
- clearTimeout(this.connectionTimeout);
299
- this.connectionTimeout = void 0;
300
- }
301
- }
302
- _handleClose() {
303
- this.bestEffortClose();
304
- super._handleClose();
305
- }
306
- };
307
-
308
- // transport/sessionStateMachine/SessionNoConnection.ts
309
- var SessionNoConnection = class extends IdentifiedSessionWithGracePeriod {
310
- state = "NoConnection" /* NoConnection */;
311
- _handleClose() {
312
- super._handleClose();
313
- }
314
- _handleStateExit() {
315
- super._handleStateExit();
316
- }
317
- };
318
-
319
- // transport/sessionStateMachine/SessionWaitingForHandshake.ts
320
- var SessionWaitingForHandshake = class extends CommonSession {
321
- state = "WaitingForHandshake" /* WaitingForHandshake */;
322
- conn;
323
- listeners;
324
- handshakeTimeout;
325
- constructor(props) {
326
- super(props);
327
- this.conn = props.conn;
328
- this.listeners = props.listeners;
329
- this.handshakeTimeout = setTimeout(() => {
330
- this.listeners.onHandshakeTimeout();
331
- }, this.options.handshakeTimeoutMs);
332
- this.conn.addDataListener(this.onHandshakeData);
333
- this.conn.addErrorListener(this.listeners.onConnectionErrored);
334
- this.conn.addCloseListener(this.listeners.onConnectionClosed);
335
- }
336
- get loggingMetadata() {
337
- return {
338
- clientId: this.from,
339
- connId: this.conn.id,
340
- ...this.conn.loggingMetadata
341
- };
342
- }
343
- onHandshakeData = (msg) => {
344
- const parsedMsg = this.parseMsg(msg);
345
- if (parsedMsg === null) {
346
- this.listeners.onInvalidHandshake(
347
- "could not parse message",
348
- "MALFORMED_HANDSHAKE"
349
- );
350
- return;
351
- }
352
- this.listeners.onHandshake(parsedMsg);
353
- };
354
- sendHandshake(msg) {
355
- return this.conn.send(this.options.codec.toBuffer(msg));
356
- }
357
- _handleStateExit() {
358
- this.conn.removeDataListener(this.onHandshakeData);
359
- this.conn.removeErrorListener(this.listeners.onConnectionErrored);
360
- this.conn.removeCloseListener(this.listeners.onConnectionClosed);
361
- clearTimeout(this.handshakeTimeout);
362
- this.handshakeTimeout = void 0;
363
- }
364
- _handleClose() {
365
- this.conn.close();
366
- }
367
- };
368
-
369
- // transport/sessionStateMachine/SessionHandshaking.ts
370
- var SessionHandshaking = class extends IdentifiedSessionWithGracePeriod {
371
- state = "Handshaking" /* Handshaking */;
372
- conn;
373
- listeners;
374
- handshakeTimeout;
375
- constructor(props) {
376
- super(props);
377
- this.conn = props.conn;
378
- this.listeners = props.listeners;
379
- this.handshakeTimeout = setTimeout(() => {
380
- this.listeners.onHandshakeTimeout();
381
- }, this.options.handshakeTimeoutMs);
382
- this.conn.addDataListener(this.onHandshakeData);
383
- this.conn.addErrorListener(this.listeners.onConnectionErrored);
384
- this.conn.addCloseListener(this.listeners.onConnectionClosed);
385
- }
386
- get loggingMetadata() {
387
- return {
388
- ...super.loggingMetadata,
389
- ...this.conn.loggingMetadata
390
- };
391
- }
392
- onHandshakeData = (msg) => {
393
- const parsedMsg = this.parseMsg(msg);
394
- if (parsedMsg === null) {
395
- this.listeners.onInvalidHandshake(
396
- "could not parse message",
397
- "MALFORMED_HANDSHAKE"
398
- );
399
- return;
400
- }
401
- this.listeners.onHandshake(parsedMsg);
402
- };
403
- sendHandshake(msg) {
404
- return this.conn.send(this.options.codec.toBuffer(msg));
405
- }
406
- _handleStateExit() {
407
- super._handleStateExit();
408
- this.conn.removeDataListener(this.onHandshakeData);
409
- this.conn.removeErrorListener(this.listeners.onConnectionErrored);
410
- this.conn.removeCloseListener(this.listeners.onConnectionClosed);
411
- if (this.handshakeTimeout) {
412
- clearTimeout(this.handshakeTimeout);
413
- this.handshakeTimeout = void 0;
414
- }
415
- }
416
- _handleClose() {
417
- super._handleClose();
418
- this.conn.close();
419
- }
420
- };
421
-
422
- // transport/sessionStateMachine/SessionConnected.ts
423
- import { SpanStatusCode } from "@opentelemetry/api";
424
- var SessionConnected = class extends IdentifiedSession {
425
- state = "Connected" /* Connected */;
426
- conn;
427
- listeners;
428
- heartbeatHandle;
429
- heartbeatMisses = 0;
430
- isActivelyHeartbeating;
431
- lastConstructedMsgs = [];
432
- pushLastConstructedMsgs = (msg) => {
433
- const trackedMsg = {
434
- id: msg.id,
435
- seq: msg.seq,
436
- streamId: msg.streamId,
437
- stack: new Error().stack
438
- };
439
- this.lastConstructedMsgs.push(trackedMsg);
440
- if (this.lastConstructedMsgs.length > 10) {
441
- this.lastConstructedMsgs.shift();
442
- }
443
- };
444
- updateBookkeeping(ack, seq) {
445
- this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
446
- this.ack = seq + 1;
447
- this.heartbeatMisses = 0;
448
- }
449
- assertSendOrdering(constructedMsg) {
450
- if (constructedMsg.seq > this.seqSent + 1) {
451
- const msg = `invariant violation: would have sent out of order msg (seq: ${constructedMsg.seq}, expected: ${this.seqSent} + 1)`;
452
- this.log?.error(msg, {
453
- ...this.loggingMetadata,
454
- transportMessage: constructedMsg,
455
- tags: ["invariant-violation"],
456
- extras: {
457
- lastConstructedMsgs: this.lastConstructedMsgs
458
- }
459
- });
460
- throw new Error(msg);
461
- }
462
- }
463
- send(msg) {
464
- const constructedMsg = this.constructMsg(msg);
465
- this.pushLastConstructedMsgs(constructedMsg);
466
- this.assertSendOrdering(constructedMsg);
467
- this.sendBuffer.push(constructedMsg);
468
- this.conn.send(this.options.codec.toBuffer(constructedMsg));
469
- this.seqSent = constructedMsg.seq;
470
- return constructedMsg.id;
471
- }
472
- constructor(props) {
473
- super(props);
474
- this.conn = props.conn;
475
- this.listeners = props.listeners;
476
- this.conn.addDataListener(this.onMessageData);
477
- this.conn.addCloseListener(this.listeners.onConnectionClosed);
478
- this.conn.addErrorListener(this.listeners.onConnectionErrored);
479
- if (this.sendBuffer.length > 0) {
480
- this.log?.info(
481
- `sending ${this.sendBuffer.length} buffered messages, starting at seq ${this.nextSeq()}`,
482
- this.loggingMetadata
483
- );
484
- for (const msg of this.sendBuffer) {
485
- this.assertSendOrdering(msg);
486
- this.conn.send(this.options.codec.toBuffer(msg));
487
- this.seqSent = msg.seq;
488
- }
489
- }
490
- this.isActivelyHeartbeating = false;
491
- this.heartbeatHandle = setInterval(() => {
492
- const misses = this.heartbeatMisses;
493
- const missDuration = misses * this.options.heartbeatIntervalMs;
494
- if (misses >= this.options.heartbeatsUntilDead) {
495
- this.log?.info(
496
- `closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
497
- this.loggingMetadata
498
- );
499
- this.telemetry.span.addEvent("closing connection due to inactivity");
500
- this.conn.close();
501
- clearInterval(this.heartbeatHandle);
502
- this.heartbeatHandle = void 0;
503
- return;
504
- }
505
- if (this.isActivelyHeartbeating) {
506
- this.sendHeartbeat();
507
- }
508
- this.heartbeatMisses++;
509
- }, this.options.heartbeatIntervalMs);
510
- }
511
- get loggingMetadata() {
512
- return {
513
- ...super.loggingMetadata,
514
- ...this.conn.loggingMetadata
515
- };
516
- }
517
- startActiveHeartbeat() {
518
- this.isActivelyHeartbeating = true;
519
- }
520
- sendHeartbeat() {
521
- this.log?.debug("sending heartbeat", this.loggingMetadata);
522
- this.send({
523
- streamId: "heartbeat",
524
- controlFlags: 1 /* AckBit */,
525
- payload: {
526
- type: "ACK"
527
- }
528
- });
529
- }
530
- onMessageData = (msg) => {
531
- const parsedMsg = this.parseMsg(msg);
532
- if (parsedMsg === null) {
533
- this.listeners.onInvalidMessage("could not parse message");
534
- return;
535
- }
536
- if (parsedMsg.seq !== this.ack) {
537
- if (parsedMsg.seq < this.ack) {
538
- this.log?.debug(
539
- `received duplicate msg (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack}), discarding`,
540
- {
541
- ...this.loggingMetadata,
542
- transportMessage: parsedMsg
543
- }
544
- );
545
- } else {
546
- const reason = `received out-of-order msg, closing connection (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack})`;
547
- this.log?.error(reason, {
548
- ...this.loggingMetadata,
549
- transportMessage: parsedMsg,
550
- tags: ["invariant-violation"]
551
- });
552
- this.telemetry.span.setStatus({
553
- code: SpanStatusCode.ERROR,
554
- message: reason
555
- });
556
- this.conn.close();
557
- }
558
- return;
559
- }
560
- this.log?.debug(`received msg`, {
561
- ...this.loggingMetadata,
562
- transportMessage: parsedMsg
563
- });
564
- this.updateBookkeeping(parsedMsg.ack, parsedMsg.seq);
565
- if (!isAck(parsedMsg.controlFlags)) {
566
- this.listeners.onMessage(parsedMsg);
567
- return;
568
- }
569
- this.log?.debug(`discarding msg (ack bit set)`, {
570
- ...this.loggingMetadata,
571
- transportMessage: parsedMsg
572
- });
573
- if (!this.isActivelyHeartbeating) {
574
- void Promise.resolve().then(() => {
575
- this.sendHeartbeat();
576
- });
577
- }
578
- };
579
- _handleStateExit() {
580
- super._handleStateExit();
581
- this.conn.removeDataListener(this.onMessageData);
582
- this.conn.removeCloseListener(this.listeners.onConnectionClosed);
583
- this.conn.removeErrorListener(this.listeners.onConnectionErrored);
584
- if (this.heartbeatHandle) {
585
- clearInterval(this.heartbeatHandle);
586
- this.heartbeatHandle = void 0;
587
- }
588
- }
589
- _handleClose() {
590
- super._handleClose();
591
- this.conn.close();
592
- }
593
- };
594
-
595
- // transport/sessionStateMachine/SessionBackingOff.ts
596
- var SessionBackingOff = class extends IdentifiedSessionWithGracePeriod {
597
- state = "BackingOff" /* BackingOff */;
598
- listeners;
599
- backoffTimeout;
600
- constructor(props) {
601
- super(props);
602
- this.listeners = props.listeners;
603
- this.backoffTimeout = setTimeout(() => {
604
- this.listeners.onBackoffFinished();
605
- }, props.backoffMs);
606
- }
607
- _handleClose() {
608
- super._handleClose();
609
- }
610
- _handleStateExit() {
611
- super._handleStateExit();
612
- if (this.backoffTimeout) {
613
- clearTimeout(this.backoffTimeout);
614
- this.backoffTimeout = void 0;
615
- }
616
- }
617
- };
618
-
619
- // transport/sessionStateMachine/transitions.ts
620
- function inheritSharedSession(session) {
621
- return {
622
- id: session.id,
623
- from: session.from,
624
- to: session.to,
625
- seq: session.seq,
626
- ack: session.ack,
627
- seqSent: session.seqSent,
628
- sendBuffer: session.sendBuffer,
629
- telemetry: session.telemetry,
630
- options: session.options,
631
- log: session.log,
632
- tracer: session.tracer,
633
- protocolVersion: session.protocolVersion
634
- };
635
- }
636
- function inheritSharedSessionWithGrace(session) {
637
- return {
638
- ...inheritSharedSession(session),
639
- graceExpiryTime: session.graceExpiryTime
640
- };
641
- }
642
- var SessionStateGraph = {
643
- entrypoints: {
644
- NoConnection: (to, from, listeners, options, protocolVersion, tracer, log) => {
645
- const id = `session-${generateId()}`;
646
- const telemetry = createSessionTelemetryInfo(tracer, id, to, from);
647
- const sendBuffer = [];
648
- const session = new SessionNoConnection({
649
- listeners,
650
- id,
651
- from,
652
- to,
653
- seq: 0,
654
- ack: 0,
655
- seqSent: 0,
656
- graceExpiryTime: Date.now() + options.sessionDisconnectGraceMs,
657
- sendBuffer,
658
- telemetry,
659
- options,
660
- protocolVersion,
661
- tracer,
662
- log
663
- });
664
- session.log?.info(`session ${session.id} created in NoConnection state`, {
665
- ...session.loggingMetadata,
666
- tags: ["state-transition"]
667
- });
668
- return session;
669
- },
670
- WaitingForHandshake: (from, conn, listeners, options, tracer, log) => {
671
- const session = new SessionWaitingForHandshake({
672
- conn,
673
- listeners,
674
- from,
675
- options,
676
- tracer,
677
- log
678
- });
679
- session.log?.info(`session created in WaitingForHandshake state`, {
680
- ...session.loggingMetadata,
681
- tags: ["state-transition"]
682
- });
683
- return session;
684
- }
685
- },
686
- // All of the transitions 'move'/'consume' the old session and return a new one.
687
- // After a session is transitioned, any usage of the old session will throw.
688
- transition: {
689
- // happy path transitions
690
- NoConnectionToBackingOff: (oldSession, backoffMs, listeners) => {
691
- const carriedState = inheritSharedSessionWithGrace(oldSession);
692
- oldSession._handleStateExit();
693
- const session = new SessionBackingOff({
694
- backoffMs,
695
- listeners,
696
- ...carriedState
697
- });
698
- session.log?.info(
699
- `session ${session.id} transition from NoConnection to BackingOff`,
700
- {
701
- ...session.loggingMetadata,
702
- tags: ["state-transition"]
703
- }
704
- );
705
- return session;
706
- },
707
- BackingOffToConnecting: (oldSession, connPromise, listeners) => {
708
- const carriedState = inheritSharedSessionWithGrace(oldSession);
709
- oldSession._handleStateExit();
710
- const session = new SessionConnecting({
711
- connPromise,
712
- listeners,
713
- ...carriedState
714
- });
715
- session.log?.info(
716
- `session ${session.id} transition from BackingOff to Connecting`,
717
- {
718
- ...session.loggingMetadata,
719
- tags: ["state-transition"]
720
- }
721
- );
722
- return session;
723
- },
724
- ConnectingToHandshaking: (oldSession, conn, listeners) => {
725
- const carriedState = inheritSharedSessionWithGrace(oldSession);
726
- oldSession._handleStateExit();
727
- const session = new SessionHandshaking({
728
- conn,
729
- listeners,
730
- ...carriedState
731
- });
732
- conn.telemetry = createConnectionTelemetryInfo(
733
- session.tracer,
734
- conn,
735
- session.telemetry
736
- );
737
- session.log?.info(
738
- `session ${session.id} transition from Connecting to Handshaking`,
739
- {
740
- ...session.loggingMetadata,
741
- tags: ["state-transition"]
742
- }
743
- );
744
- return session;
745
- },
746
- HandshakingToConnected: (oldSession, listeners) => {
747
- const carriedState = inheritSharedSession(oldSession);
748
- const conn = oldSession.conn;
749
- oldSession._handleStateExit();
750
- const session = new SessionConnected({
751
- conn,
752
- listeners,
753
- ...carriedState
754
- });
755
- session.log?.info(
756
- `session ${session.id} transition from Handshaking to Connected`,
757
- {
758
- ...session.loggingMetadata,
759
- tags: ["state-transition"]
760
- }
761
- );
762
- return session;
763
- },
764
- WaitingForHandshakeToConnected: (pendingSession, oldSession, sessionId, to, propagationCtx, listeners, protocolVersion) => {
765
- const conn = pendingSession.conn;
766
- const { from, options } = pendingSession;
767
- const carriedState = oldSession ? (
768
- // old session exists, inherit state
769
- inheritSharedSession(oldSession)
770
- ) : (
771
- // old session does not exist, create new state
772
- {
773
- id: sessionId,
774
- from,
775
- to,
776
- seq: 0,
777
- ack: 0,
778
- seqSent: 0,
779
- sendBuffer: [],
780
- telemetry: createSessionTelemetryInfo(
781
- pendingSession.tracer,
782
- sessionId,
783
- to,
784
- from,
785
- propagationCtx
786
- ),
787
- options,
788
- tracer: pendingSession.tracer,
789
- log: pendingSession.log,
790
- protocolVersion
791
- }
792
- );
793
- pendingSession._handleStateExit();
794
- oldSession?._handleStateExit();
795
- const session = new SessionConnected({
796
- conn,
797
- listeners,
798
- ...carriedState
799
- });
800
- conn.telemetry = createConnectionTelemetryInfo(
801
- session.tracer,
802
- conn,
803
- session.telemetry
804
- );
805
- session.log?.info(
806
- `session ${session.id} transition from WaitingForHandshake to Connected`,
807
- {
808
- ...session.loggingMetadata,
809
- tags: ["state-transition"]
810
- }
811
- );
812
- return session;
813
- },
814
- // disconnect paths
815
- BackingOffToNoConnection: (oldSession, listeners) => {
816
- const carriedState = inheritSharedSessionWithGrace(oldSession);
817
- oldSession._handleStateExit();
818
- const session = new SessionNoConnection({
819
- listeners,
820
- ...carriedState
821
- });
822
- session.log?.info(
823
- `session ${session.id} transition from BackingOff to NoConnection`,
824
- {
825
- ...session.loggingMetadata,
826
- tags: ["state-transition"]
827
- }
828
- );
829
- return session;
830
- },
831
- ConnectingToNoConnection: (oldSession, listeners) => {
832
- const carriedState = inheritSharedSessionWithGrace(oldSession);
833
- oldSession.bestEffortClose();
834
- oldSession._handleStateExit();
835
- const session = new SessionNoConnection({
836
- listeners,
837
- ...carriedState
838
- });
839
- session.log?.info(
840
- `session ${session.id} transition from Connecting to NoConnection`,
841
- {
842
- ...session.loggingMetadata,
843
- tags: ["state-transition"]
844
- }
845
- );
846
- return session;
847
- },
848
- HandshakingToNoConnection: (oldSession, listeners) => {
849
- const carriedState = inheritSharedSessionWithGrace(oldSession);
850
- oldSession.conn.close();
851
- oldSession._handleStateExit();
852
- const session = new SessionNoConnection({
853
- listeners,
854
- ...carriedState
855
- });
856
- session.log?.info(
857
- `session ${session.id} transition from Handshaking to NoConnection`,
858
- {
859
- ...session.loggingMetadata,
860
- tags: ["state-transition"]
861
- }
862
- );
863
- return session;
864
- },
865
- ConnectedToNoConnection: (oldSession, listeners) => {
866
- const carriedState = inheritSharedSession(oldSession);
867
- const graceExpiryTime = Date.now() + oldSession.options.sessionDisconnectGraceMs;
868
- oldSession.conn.close();
869
- oldSession._handleStateExit();
870
- const session = new SessionNoConnection({
871
- listeners,
872
- graceExpiryTime,
873
- ...carriedState
874
- });
875
- session.log?.info(
876
- `session ${session.id} transition from Connected to NoConnection`,
877
- {
878
- ...session.loggingMetadata,
879
- tags: ["state-transition"]
880
- }
881
- );
882
- return session;
883
- }
884
- }
885
- };
886
- var transitions = SessionStateGraph.transition;
887
- var ClientSessionStateGraph = {
888
- entrypoint: SessionStateGraph.entrypoints.NoConnection,
889
- transition: {
890
- // happy paths
891
- // NoConnection -> BackingOff: attempt to connect
892
- NoConnectionToBackingOff: transitions.NoConnectionToBackingOff,
893
- // BackingOff -> Connecting: backoff period elapsed, start connection
894
- BackingOffToConnecting: transitions.BackingOffToConnecting,
895
- // Connecting -> Handshaking: connection established, start handshake
896
- ConnectingToHandshaking: transitions.ConnectingToHandshaking,
897
- // Handshaking -> Connected: handshake complete, session ready
898
- HandshakingToConnected: transitions.HandshakingToConnected,
899
- // disconnect paths
900
- // BackingOff -> NoConnection: unused
901
- BackingOffToNoConnection: transitions.BackingOffToNoConnection,
902
- // Connecting -> NoConnection: connection failed or connection timeout
903
- ConnectingToNoConnection: transitions.ConnectingToNoConnection,
904
- // Handshaking -> NoConnection: connection closed or handshake timeout
905
- HandshakingToNoConnection: transitions.HandshakingToNoConnection,
906
- // Connected -> NoConnection: connection closed
907
- ConnectedToNoConnection: transitions.ConnectedToNoConnection
908
- // destroy/close paths
909
- // NoConnection -> x: grace period elapsed
910
- // BackingOff -> x: grace period elapsed
911
- // Connecting -> x: grace period elapsed
912
- // Handshaking -> x: grace period elapsed or invalid handshake message or handshake rejection
913
- // Connected -> x: grace period elapsed or invalid message
914
- }
915
- };
916
- var ServerSessionStateGraph = {
917
- entrypoint: SessionStateGraph.entrypoints.WaitingForHandshake,
918
- transition: {
919
- // happy paths
920
- // WaitingForHandshake -> Connected: handshake complete, session ready
921
- WaitingForHandshakeToConnected: transitions.WaitingForHandshakeToConnected,
922
- // disconnect paths
923
- // Connected -> NoConnection: connection closed
924
- ConnectedToNoConnection: transitions.ConnectedToNoConnection
925
- // destroy/close paths
926
- // WaitingForHandshake -> x: handshake timeout elapsed or invalid handshake message or handshake rejection or connection closed
927
- }
928
- };
929
-
930
- // transport/events.ts
931
- var ProtocolError = {
932
- RetriesExceeded: "conn_retry_exceeded",
933
- HandshakeFailed: "handshake_failed",
934
- MessageOrderingViolated: "message_ordering_violated",
935
- InvalidMessage: "invalid_message"
936
- };
937
- var EventDispatcher = class {
938
- eventListeners = {};
939
- removeAllListeners() {
940
- this.eventListeners = {};
941
- }
942
- numberOfListeners(eventType) {
943
- return this.eventListeners[eventType]?.size ?? 0;
944
- }
945
- addEventListener(eventType, handler) {
946
- if (!this.eventListeners[eventType]) {
947
- this.eventListeners[eventType] = /* @__PURE__ */ new Set();
948
- }
949
- this.eventListeners[eventType]?.add(handler);
950
- }
951
- removeEventListener(eventType, handler) {
952
- const handlers = this.eventListeners[eventType];
953
- if (handlers) {
954
- this.eventListeners[eventType]?.delete(handler);
955
- }
956
- }
957
- dispatchEvent(eventType, event) {
958
- const handlers = this.eventListeners[eventType];
959
- if (handlers) {
960
- const copy = [...handlers];
961
- for (const handler of copy) {
962
- handler(event);
963
- }
964
- }
965
- }
966
- };
967
-
968
- // transport/transport.ts
969
- var Transport = class {
970
- /**
971
- * The status of the transport.
972
- */
973
- status;
974
- /**
975
- * The client ID of this transport.
976
- */
977
- clientId;
978
- /**
979
- * The event dispatcher for handling events of type EventTypes.
980
- */
981
- eventDispatcher;
982
- /**
983
- * The options for this transport.
984
- */
985
- options;
986
- log;
987
- tracer;
988
- sessions;
989
- /**
990
- * Creates a new Transport instance.
991
- * @param codec The codec used to encode and decode messages.
992
- * @param clientId The client ID of this transport.
993
- */
994
- constructor(clientId, providedOptions) {
995
- this.options = { ...defaultTransportOptions, ...providedOptions };
996
- this.eventDispatcher = new EventDispatcher();
997
- this.clientId = clientId;
998
- this.status = "open";
999
- this.sessions = /* @__PURE__ */ new Map();
1000
- this.tracer = getTracer();
1001
- }
1002
- bindLogger(fn, level) {
1003
- if (typeof fn === "function") {
1004
- this.log = createLogProxy(new BaseLogger(fn, level));
1005
- return;
1006
- }
1007
- this.log = createLogProxy(fn);
1008
- }
1009
- /**
1010
- * Called when a message is received by this transport.
1011
- * You generally shouldn't need to override this in downstream transport implementations.
1012
- * @param message The received message.
1013
- */
1014
- handleMsg(message) {
1015
- if (this.getStatus() !== "open")
1016
- return;
1017
- this.eventDispatcher.dispatchEvent("message", message);
1018
- }
1019
- /**
1020
- * Adds a listener to this transport.
1021
- * @param the type of event to listen for
1022
- * @param handler The message handler to add.
1023
- */
1024
- addEventListener(type, handler) {
1025
- this.eventDispatcher.addEventListener(type, handler);
1026
- }
1027
- /**
1028
- * Removes a listener from this transport.
1029
- * @param the type of event to un-listen on
1030
- * @param handler The message handler to remove.
1031
- */
1032
- removeEventListener(type, handler) {
1033
- this.eventDispatcher.removeEventListener(type, handler);
1034
- }
1035
- protocolError(message) {
1036
- this.eventDispatcher.dispatchEvent("protocolError", message);
1037
- }
1038
- /**
1039
- * Default close implementation for transports. You should override this in the downstream
1040
- * implementation if you need to do any additional cleanup and call super.close() at the end.
1041
- * Closes the transport. Any messages sent while the transport is closed will be silently discarded.
1042
- */
1043
- close() {
1044
- this.status = "closed";
1045
- const sessions = Array.from(this.sessions.values());
1046
- for (const session of sessions) {
1047
- this.deleteSession(session);
1048
- }
1049
- this.eventDispatcher.dispatchEvent("transportStatus", {
1050
- status: this.status
1051
- });
1052
- this.eventDispatcher.removeAllListeners();
1053
- this.log?.info(`manually closed transport`, { clientId: this.clientId });
1054
- }
1055
- getStatus() {
1056
- return this.status;
1057
- }
1058
- // state transitions
1059
- createSession(session) {
1060
- const activeSession = this.sessions.get(session.to);
1061
- if (activeSession) {
1062
- const msg = `attempt to create session for ${session.to} but active session (${activeSession.id}) already exists`;
1063
- this.log?.error(msg, {
1064
- ...session.loggingMetadata,
1065
- tags: ["invariant-violation"]
1066
- });
1067
- throw new Error(msg);
1068
- }
1069
- this.sessions.set(session.to, session);
1070
- this.eventDispatcher.dispatchEvent("sessionStatus", {
1071
- status: "created",
1072
- session
1073
- });
1074
- this.eventDispatcher.dispatchEvent("sessionTransition", {
1075
- state: session.state,
1076
- id: session.id
1077
- });
1078
- }
1079
- updateSession(session) {
1080
- const activeSession = this.sessions.get(session.to);
1081
- if (!activeSession) {
1082
- const msg = `attempt to transition session for ${session.to} but no active session exists`;
1083
- this.log?.error(msg, {
1084
- ...session.loggingMetadata,
1085
- tags: ["invariant-violation"]
1086
- });
1087
- throw new Error(msg);
1088
- }
1089
- if (activeSession.id !== session.id) {
1090
- const msg = `attempt to transition active session for ${session.to} but active session (${activeSession.id}) is different from handle (${session.id})`;
1091
- this.log?.error(msg, {
1092
- ...session.loggingMetadata,
1093
- tags: ["invariant-violation"]
1094
- });
1095
- throw new Error(msg);
1096
- }
1097
- this.sessions.set(session.to, session);
1098
- this.eventDispatcher.dispatchEvent("sessionTransition", {
1099
- state: session.state,
1100
- id: session.id
1101
- });
1102
- }
1103
- deleteSession(session, options) {
1104
- if (session._isConsumed)
1105
- return;
1106
- const loggingMetadata = session.loggingMetadata;
1107
- if (loggingMetadata.tags && options?.unhealthy) {
1108
- loggingMetadata.tags.push("unhealthy-session");
1109
- }
1110
- session.log?.info(`closing session ${session.id}`, loggingMetadata);
1111
- this.eventDispatcher.dispatchEvent("sessionStatus", {
1112
- status: "closing",
1113
- session
1114
- });
1115
- const to = session.to;
1116
- session.close();
1117
- this.sessions.delete(to);
1118
- this.eventDispatcher.dispatchEvent("sessionStatus", {
1119
- status: "closed",
1120
- session: { id: session.id, to }
1121
- });
1122
- }
1123
- // common listeners
1124
- onSessionGracePeriodElapsed(session) {
1125
- this.log?.warn(
1126
- `session to ${session.to} grace period elapsed, closing`,
1127
- session.loggingMetadata
1128
- );
1129
- this.deleteSession(session);
1130
- }
1131
- onConnectingFailed(session) {
1132
- const noConnectionSession = SessionStateGraph.transition.ConnectingToNoConnection(session, {
1133
- onSessionGracePeriodElapsed: () => {
1134
- this.onSessionGracePeriodElapsed(noConnectionSession);
1135
- }
1136
- });
1137
- this.updateSession(noConnectionSession);
1138
- return noConnectionSession;
1139
- }
1140
- onConnClosed(session) {
1141
- let noConnectionSession;
1142
- if (session.state === "Handshaking" /* Handshaking */) {
1143
- noConnectionSession = SessionStateGraph.transition.HandshakingToNoConnection(session, {
1144
- onSessionGracePeriodElapsed: () => {
1145
- this.onSessionGracePeriodElapsed(noConnectionSession);
1146
- }
1147
- });
1148
- } else {
1149
- noConnectionSession = SessionStateGraph.transition.ConnectedToNoConnection(session, {
1150
- onSessionGracePeriodElapsed: () => {
1151
- this.onSessionGracePeriodElapsed(noConnectionSession);
1152
- }
1153
- });
1154
- }
1155
- this.updateSession(noConnectionSession);
1156
- return noConnectionSession;
1157
- }
1158
- /**
1159
- * Gets a send closure scoped to a specific session. Sending using the returned
1160
- * closure after the session has transitioned to a different state will be a noop.
1161
- *
1162
- * Session objects themselves can become stale as they transition between
1163
- * states. As stale sessions cannot be used again (and will throw), holding
1164
- * onto a session object is not recommended.
1165
- */
1166
- getSessionBoundSendFn(to, sessionId) {
1167
- if (this.getStatus() !== "open") {
1168
- throw new Error("cannot get a bound send function on a closed transport");
1169
- }
1170
- return (msg) => {
1171
- const session = this.sessions.get(to);
1172
- if (!session) {
1173
- throw new Error(
1174
- `session scope for ${sessionId} has ended (close), can't send`
1175
- );
1176
- }
1177
- const sameSession = session.id === sessionId;
1178
- if (!sameSession) {
1179
- throw new Error(
1180
- `session scope for ${sessionId} has ended (transition), can't send`
1181
- );
1182
- }
1183
- return session.send(msg);
1184
- };
1185
- }
1186
- };
1187
-
1188
- // transport/connection.ts
1189
- var Connection = class {
1190
- id;
1191
- telemetry;
1192
- constructor() {
1193
- this.id = `conn-${generateId()}`;
1194
- }
1195
- get loggingMetadata() {
1196
- const metadata = { connId: this.id };
1197
- if (this.telemetry?.span.isRecording()) {
1198
- const spanContext = this.telemetry.span.spanContext();
1199
- metadata.telemetry = {
1200
- traceId: spanContext.traceId,
1201
- spanId: spanContext.spanId
1202
- };
1203
- }
1204
- return metadata;
1205
- }
1206
- // can't use event emitter because we need this to work in both node + browser
1207
- _dataListeners = /* @__PURE__ */ new Set();
1208
- _closeListeners = /* @__PURE__ */ new Set();
1209
- _errorListeners = /* @__PURE__ */ new Set();
1210
- get dataListeners() {
1211
- return [...this._dataListeners];
1212
- }
1213
- get closeListeners() {
1214
- return [...this._closeListeners];
1215
- }
1216
- get errorListeners() {
1217
- return [...this._errorListeners];
1218
- }
1219
- onData(msg) {
1220
- for (const cb of this.dataListeners) {
1221
- cb(msg);
1222
- }
1223
- }
1224
- onError(err) {
1225
- for (const cb of this.errorListeners) {
1226
- cb(err);
1227
- }
1228
- }
1229
- onClose() {
1230
- for (const cb of this.closeListeners) {
1231
- cb();
1232
- }
1233
- this.telemetry?.span.end();
1234
- }
1235
- /**
1236
- * Handle adding a callback for when a message is received.
1237
- * @param msg The message that was received.
1238
- */
1239
- addDataListener(cb) {
1240
- this._dataListeners.add(cb);
1241
- }
1242
- removeDataListener(cb) {
1243
- this._dataListeners.delete(cb);
1244
- }
1245
- /**
1246
- * Handle adding a callback for when the connection is closed.
1247
- * This should also be called if an error happens and after notifying all the error listeners.
1248
- * @param cb The callback to call when the connection is closed.
1249
- */
1250
- addCloseListener(cb) {
1251
- this._closeListeners.add(cb);
1252
- }
1253
- removeCloseListener(cb) {
1254
- this._closeListeners.delete(cb);
1255
- }
1256
- /**
1257
- * Handle adding a callback for when an error is received.
1258
- * This should only be used for this.logging errors, all cleanup
1259
- * should be delegated to addCloseListener.
1260
- *
1261
- * The implementer should take care such that the implemented
1262
- * connection will call both the close and error callbacks
1263
- * on an error.
1264
- *
1265
- * @param cb The callback to call when an error is received.
1266
- */
1267
- addErrorListener(cb) {
1268
- this._errorListeners.add(cb);
1269
- }
1270
- removeErrorListener(cb) {
1271
- this._errorListeners.delete(cb);
1272
- }
1273
- };
1274
-
1275
- export {
1276
- defaultTransportOptions,
1277
- defaultClientTransportOptions,
1278
- defaultServerTransportOptions,
1279
- SessionState,
1280
- SessionStateGraph,
1281
- ClientSessionStateGraph,
1282
- ServerSessionStateGraph,
1283
- ProtocolError,
1284
- Transport,
1285
- Connection
1286
- };
1287
- //# sourceMappingURL=chunk-24EWYOGK.js.map