@replit/river 0.23.12 → 0.23.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 (75) hide show
  1. package/dist/{chunk-3AW3IXVD.js → chunk-4PVU7J25.js} +1 -21
  2. package/dist/chunk-4PVU7J25.js.map +1 -0
  3. package/dist/{chunk-HDBVL7EF.js → chunk-BEALFLCB.js} +2 -2
  4. package/dist/chunk-D2DHRRBN.js +476 -0
  5. package/dist/chunk-D2DHRRBN.js.map +1 -0
  6. package/dist/{chunk-7RUKEUKE.js → chunk-GCCRVSMR.js} +33 -4
  7. package/dist/chunk-GCCRVSMR.js.map +1 -0
  8. package/dist/{chunk-XZ6IOBM5.js → chunk-GN4YEXT7.js} +2 -2
  9. package/dist/chunk-GN4YEXT7.js.map +1 -0
  10. package/dist/chunk-O2AVDJCQ.js +335 -0
  11. package/dist/chunk-O2AVDJCQ.js.map +1 -0
  12. package/dist/chunk-OTVTKAN6.js +451 -0
  13. package/dist/chunk-OTVTKAN6.js.map +1 -0
  14. package/dist/chunk-WUL63FR6.js +335 -0
  15. package/dist/chunk-WUL63FR6.js.map +1 -0
  16. package/dist/{chunk-H6KTH6W6.js → chunk-YCLZWES2.js} +2 -2
  17. package/dist/client-e13979ac.d.ts +52 -0
  18. package/dist/codec/index.js +20 -2
  19. package/dist/codec/index.js.map +1 -1
  20. package/dist/{connection-8debd45f.d.ts → connection-5d0978ce.d.ts} +1 -1
  21. package/dist/{connection-581558f8.d.ts → connection-e57e98ea.d.ts} +1 -1
  22. package/dist/{transport-47af1c81.d.ts → handshake-5665ffd3.d.ts} +101 -153
  23. package/dist/{index-60f03cb7.d.ts → index-ea74cdbb.d.ts} +1 -1
  24. package/dist/logging/index.d.cts +1 -1
  25. package/dist/logging/index.d.ts +1 -1
  26. package/dist/router/index.cjs +16 -1
  27. package/dist/router/index.cjs.map +1 -1
  28. package/dist/router/index.d.cts +8 -6
  29. package/dist/router/index.d.ts +8 -6
  30. package/dist/router/index.js +2 -2
  31. package/dist/server-1cfc88d1.d.ts +24 -0
  32. package/dist/{services-ca72c9f8.d.ts → services-86c4d10d.d.ts} +3 -2
  33. package/dist/transport/impls/uds/client.cjs +303 -180
  34. package/dist/transport/impls/uds/client.cjs.map +1 -1
  35. package/dist/transport/impls/uds/client.d.cts +6 -5
  36. package/dist/transport/impls/uds/client.d.ts +6 -5
  37. package/dist/transport/impls/uds/client.js +6 -4
  38. package/dist/transport/impls/uds/client.js.map +1 -1
  39. package/dist/transport/impls/uds/server.cjs +396 -234
  40. package/dist/transport/impls/uds/server.cjs.map +1 -1
  41. package/dist/transport/impls/uds/server.d.cts +6 -5
  42. package/dist/transport/impls/uds/server.d.ts +6 -5
  43. package/dist/transport/impls/uds/server.js +8 -6
  44. package/dist/transport/impls/uds/server.js.map +1 -1
  45. package/dist/transport/impls/ws/client.cjs +305 -182
  46. package/dist/transport/impls/ws/client.cjs.map +1 -1
  47. package/dist/transport/impls/ws/client.d.cts +6 -5
  48. package/dist/transport/impls/ws/client.d.ts +6 -5
  49. package/dist/transport/impls/ws/client.js +6 -4
  50. package/dist/transport/impls/ws/client.js.map +1 -1
  51. package/dist/transport/impls/ws/server.cjs +350 -188
  52. package/dist/transport/impls/ws/server.cjs.map +1 -1
  53. package/dist/transport/impls/ws/server.d.cts +4 -3
  54. package/dist/transport/impls/ws/server.d.ts +4 -3
  55. package/dist/transport/impls/ws/server.js +8 -6
  56. package/dist/transport/impls/ws/server.js.map +1 -1
  57. package/dist/transport/index.cjs +338 -142
  58. package/dist/transport/index.cjs.map +1 -1
  59. package/dist/transport/index.d.cts +4 -2
  60. package/dist/transport/index.d.ts +4 -2
  61. package/dist/transport/index.js +14 -8
  62. package/dist/util/testHelpers.cjs +10 -6
  63. package/dist/util/testHelpers.cjs.map +1 -1
  64. package/dist/util/testHelpers.d.cts +5 -4
  65. package/dist/util/testHelpers.d.ts +5 -4
  66. package/dist/util/testHelpers.js +4 -5
  67. package/dist/util/testHelpers.js.map +1 -1
  68. package/package.json +13 -14
  69. package/dist/chunk-3AW3IXVD.js.map +0 -1
  70. package/dist/chunk-7RUKEUKE.js.map +0 -1
  71. package/dist/chunk-VRU4IKRT.js +0 -1392
  72. package/dist/chunk-VRU4IKRT.js.map +0 -1
  73. package/dist/chunk-XZ6IOBM5.js.map +0 -1
  74. /package/dist/{chunk-HDBVL7EF.js.map → chunk-BEALFLCB.js.map} +0 -0
  75. /package/dist/{chunk-H6KTH6W6.js.map → chunk-YCLZWES2.js.map} +0 -0
@@ -24,8 +24,8 @@ __export(server_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(server_exports);
26
26
 
27
- // transport/transport.ts
28
- var import_value = require("@sinclair/typebox/value");
27
+ // transport/session.ts
28
+ var import_nanoid2 = require("nanoid");
29
29
 
30
30
  // transport/message.ts
31
31
  var import_typebox = require("@sinclair/typebox");
@@ -59,6 +59,21 @@ var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
59
59
  type: import_typebox.Type.Literal("HANDSHAKE_REQ"),
60
60
  protocolVersion: import_typebox.Type.String(),
61
61
  sessionId: import_typebox.Type.String(),
62
+ /**
63
+ * Specifies what the server's expected session state (from the pov of the client). This can be
64
+ * used by the server to know whether this is a new or a reestablished connection, and whether it
65
+ * is compatible with what it already has.
66
+ */
67
+ expectedSessionState: import_typebox.Type.Optional(
68
+ import_typebox.Type.Object({
69
+ /**
70
+ * reconnect is set to true if the client explicitly wants to reestablish an existing
71
+ * connection.
72
+ */
73
+ reconnect: import_typebox.Type.Boolean(),
74
+ nextExpectedSeq: import_typebox.Type.Integer()
75
+ })
76
+ ),
62
77
  metadata: import_typebox.Type.Optional(import_typebox.Type.Unknown())
63
78
  });
64
79
  var ControlMessageHandshakeResponseSchema = import_typebox.Type.Object({
@@ -83,7 +98,12 @@ var ControlMessagePayloadSchema = import_typebox.Type.Union([
83
98
  var OpaqueTransportMessageSchema = TransportMessageSchema(
84
99
  import_typebox.Type.Unknown()
85
100
  );
86
- function handshakeResponseMessage(from, to, status) {
101
+ var SESSION_STATE_MISMATCH = "session state mismatch";
102
+ function handshakeResponseMessage({
103
+ from,
104
+ to,
105
+ status
106
+ }) {
87
107
  return {
88
108
  id: (0, import_nanoid.nanoid)(),
89
109
  from,
@@ -102,104 +122,11 @@ function isAck(controlFlag) {
102
122
  return (controlFlag & 1 /* AckBit */) === 1 /* AckBit */;
103
123
  }
104
124
 
105
- // logging/log.ts
106
- var LoggingLevels = {
107
- debug: -1,
108
- info: 0,
109
- warn: 1,
110
- error: 2
111
- };
112
- var cleanedLogFn = (log) => {
113
- return (msg, metadata) => {
114
- if (!metadata?.transportMessage) {
115
- log(msg, metadata);
116
- return;
117
- }
118
- const { payload, ...rest } = metadata.transportMessage;
119
- metadata.transportMessage = rest;
120
- log(msg, metadata);
121
- };
122
- };
123
- var BaseLogger = class {
124
- minLevel;
125
- output;
126
- constructor(output, minLevel = "info") {
127
- this.minLevel = minLevel;
128
- this.output = output;
129
- }
130
- debug(msg, metadata) {
131
- if (LoggingLevels[this.minLevel] <= LoggingLevels.debug) {
132
- this.output(msg, metadata ?? {}, "debug");
133
- }
134
- }
135
- info(msg, metadata) {
136
- if (LoggingLevels[this.minLevel] <= LoggingLevels.info) {
137
- this.output(msg, metadata ?? {}, "info");
138
- }
139
- }
140
- warn(msg, metadata) {
141
- if (LoggingLevels[this.minLevel] <= LoggingLevels.warn) {
142
- this.output(msg, metadata ?? {}, "warn");
143
- }
144
- }
145
- error(msg, metadata) {
146
- if (LoggingLevels[this.minLevel] <= LoggingLevels.error) {
147
- this.output(msg, metadata ?? {}, "error");
148
- }
149
- }
150
- };
151
- var createLogProxy = (log) => ({
152
- debug: cleanedLogFn(log.debug.bind(log)),
153
- info: cleanedLogFn(log.info.bind(log)),
154
- warn: cleanedLogFn(log.warn.bind(log)),
155
- error: cleanedLogFn(log.error.bind(log))
156
- });
157
-
158
- // transport/events.ts
159
- var ProtocolError = {
160
- RetriesExceeded: "conn_retry_exceeded",
161
- HandshakeFailed: "handshake_failed",
162
- MessageOrderingViolated: "message_ordering_violated"
163
- };
164
- var EventDispatcher = class {
165
- eventListeners = {};
166
- removeAllListeners() {
167
- this.eventListeners = {};
168
- }
169
- numberOfListeners(eventType) {
170
- return this.eventListeners[eventType]?.size ?? 0;
171
- }
172
- addEventListener(eventType, handler) {
173
- if (!this.eventListeners[eventType]) {
174
- this.eventListeners[eventType] = /* @__PURE__ */ new Set();
175
- }
176
- this.eventListeners[eventType]?.add(handler);
177
- }
178
- removeEventListener(eventType, handler) {
179
- const handlers = this.eventListeners[eventType];
180
- if (handlers) {
181
- this.eventListeners[eventType]?.delete(handler);
182
- }
183
- }
184
- dispatchEvent(eventType, event) {
185
- const handlers = this.eventListeners[eventType];
186
- if (handlers) {
187
- const copy = [...handlers];
188
- for (const handler of copy) {
189
- handler(event);
190
- }
191
- }
192
- }
193
- };
194
-
195
- // transport/session.ts
196
- var import_nanoid2 = require("nanoid");
197
-
198
125
  // tracing/index.ts
199
126
  var import_api = require("@opentelemetry/api");
200
127
 
201
128
  // package.json
202
- var version = "0.23.12";
129
+ var version = "0.23.14";
203
130
 
204
131
  // tracing/index.ts
205
132
  function createSessionTelemetryInfo(session, propagationCtx) {
@@ -504,9 +431,17 @@ var Session = class {
504
431
  get connected() {
505
432
  return this.connection !== void 0;
506
433
  }
434
+ get nextExpectedAck() {
435
+ return this.seq;
436
+ }
507
437
  get nextExpectedSeq() {
508
438
  return this.ack;
509
439
  }
440
+ // This is only used in tests to make the session misbehave.
441
+ /* @internal */
442
+ advanceAckForTesting(by) {
443
+ this.ack += by;
444
+ }
510
445
  constructMsg(partialMsg) {
511
446
  const msg = {
512
447
  ...partialMsg,
@@ -525,13 +460,59 @@ var Session = class {
525
460
  }
526
461
  };
527
462
 
528
- // util/stringify.ts
529
- function coerceErrorString(err) {
530
- if (err instanceof Error) {
531
- return err.message || "unknown reason";
463
+ // transport/impls/ws/connection.ts
464
+ var WebSocketConnection = class extends Connection {
465
+ errorCb = null;
466
+ closeCb = null;
467
+ ws;
468
+ constructor(ws) {
469
+ super();
470
+ this.ws = ws;
471
+ this.ws.binaryType = "arraybuffer";
472
+ let didError = false;
473
+ this.ws.onerror = () => {
474
+ didError = true;
475
+ };
476
+ this.ws.onclose = ({ code, reason }) => {
477
+ if (didError && this.errorCb) {
478
+ this.errorCb(
479
+ new Error(
480
+ `websocket closed with code and reason: ${code} - ${reason}`
481
+ )
482
+ );
483
+ }
484
+ if (this.closeCb) {
485
+ this.closeCb();
486
+ }
487
+ };
532
488
  }
533
- return `[coerced to error] ${String(err)}`;
534
- }
489
+ addDataListener(cb) {
490
+ this.ws.onmessage = (msg) => cb(msg.data);
491
+ }
492
+ removeDataListener() {
493
+ this.ws.onmessage = null;
494
+ }
495
+ addCloseListener(cb) {
496
+ this.closeCb = cb;
497
+ }
498
+ addErrorListener(cb) {
499
+ this.errorCb = cb;
500
+ }
501
+ send(payload) {
502
+ if (this.ws.readyState === this.ws.OPEN) {
503
+ this.ws.send(payload);
504
+ return true;
505
+ } else {
506
+ return false;
507
+ }
508
+ }
509
+ close() {
510
+ this.ws.close();
511
+ }
512
+ };
513
+
514
+ // transport/server.ts
515
+ var import_api4 = require("@opentelemetry/api");
535
516
 
536
517
  // codec/json.ts
537
518
  var encoder = new TextEncoder();
@@ -585,8 +566,7 @@ var NaiveJsonCodec = {
585
566
  }
586
567
  };
587
568
 
588
- // transport/transport.ts
589
- var import_api3 = require("@opentelemetry/api");
569
+ // transport/options.ts
590
570
  var defaultTransportOptions = {
591
571
  heartbeatIntervalMs: 1e3,
592
572
  heartbeatsUntilDead: 2,
@@ -607,6 +587,102 @@ var defaultClientTransportOptions = {
607
587
  var defaultServerTransportOptions = {
608
588
  ...defaultTransportOptions
609
589
  };
590
+
591
+ // transport/transport.ts
592
+ var import_value = require("@sinclair/typebox/value");
593
+
594
+ // logging/log.ts
595
+ var LoggingLevels = {
596
+ debug: -1,
597
+ info: 0,
598
+ warn: 1,
599
+ error: 2
600
+ };
601
+ var cleanedLogFn = (log) => {
602
+ return (msg, metadata) => {
603
+ if (!metadata?.transportMessage) {
604
+ log(msg, metadata);
605
+ return;
606
+ }
607
+ const { payload, ...rest } = metadata.transportMessage;
608
+ metadata.transportMessage = rest;
609
+ log(msg, metadata);
610
+ };
611
+ };
612
+ var BaseLogger = class {
613
+ minLevel;
614
+ output;
615
+ constructor(output, minLevel = "info") {
616
+ this.minLevel = minLevel;
617
+ this.output = output;
618
+ }
619
+ debug(msg, metadata) {
620
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.debug) {
621
+ this.output(msg, metadata ?? {}, "debug");
622
+ }
623
+ }
624
+ info(msg, metadata) {
625
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.info) {
626
+ this.output(msg, metadata ?? {}, "info");
627
+ }
628
+ }
629
+ warn(msg, metadata) {
630
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.warn) {
631
+ this.output(msg, metadata ?? {}, "warn");
632
+ }
633
+ }
634
+ error(msg, metadata) {
635
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.error) {
636
+ this.output(msg, metadata ?? {}, "error");
637
+ }
638
+ }
639
+ };
640
+ var createLogProxy = (log) => ({
641
+ debug: cleanedLogFn(log.debug.bind(log)),
642
+ info: cleanedLogFn(log.info.bind(log)),
643
+ warn: cleanedLogFn(log.warn.bind(log)),
644
+ error: cleanedLogFn(log.error.bind(log))
645
+ });
646
+
647
+ // transport/events.ts
648
+ var ProtocolError = {
649
+ RetriesExceeded: "conn_retry_exceeded",
650
+ HandshakeFailed: "handshake_failed",
651
+ MessageOrderingViolated: "message_ordering_violated"
652
+ };
653
+ var EventDispatcher = class {
654
+ eventListeners = {};
655
+ removeAllListeners() {
656
+ this.eventListeners = {};
657
+ }
658
+ numberOfListeners(eventType) {
659
+ return this.eventListeners[eventType]?.size ?? 0;
660
+ }
661
+ addEventListener(eventType, handler) {
662
+ if (!this.eventListeners[eventType]) {
663
+ this.eventListeners[eventType] = /* @__PURE__ */ new Set();
664
+ }
665
+ this.eventListeners[eventType]?.add(handler);
666
+ }
667
+ removeEventListener(eventType, handler) {
668
+ const handlers = this.eventListeners[eventType];
669
+ if (handlers) {
670
+ this.eventListeners[eventType]?.delete(handler);
671
+ }
672
+ }
673
+ dispatchEvent(eventType, event) {
674
+ const handlers = this.eventListeners[eventType];
675
+ if (handlers) {
676
+ const copy = [...handlers];
677
+ for (const handler of copy) {
678
+ handler(event);
679
+ }
680
+ }
681
+ }
682
+ };
683
+
684
+ // transport/transport.ts
685
+ var import_api3 = require("@opentelemetry/api");
610
686
  var Transport = class {
611
687
  /**
612
688
  * The status of the transport.
@@ -697,6 +773,49 @@ var Transport = class {
697
773
  });
698
774
  return session;
699
775
  }
776
+ createNewSession({
777
+ to,
778
+ conn,
779
+ sessionId,
780
+ propagationCtx
781
+ }) {
782
+ let session = this.sessions.get(to);
783
+ if (session !== void 0) {
784
+ this.log?.info(
785
+ `session for ${to} already exists, replacing it with a new session as requested`,
786
+ session.loggingMetadata
787
+ );
788
+ this.deleteSession({
789
+ session,
790
+ closeHandshakingConnection: false
791
+ });
792
+ session = void 0;
793
+ }
794
+ session = this.createSession(to, conn, propagationCtx);
795
+ session.advertisedSessionId = sessionId;
796
+ this.log?.info(`created new session for ${to}`, session.loggingMetadata);
797
+ return session;
798
+ }
799
+ getExistingSession({
800
+ to,
801
+ sessionId,
802
+ nextExpectedSeq
803
+ }) {
804
+ const session = this.sessions.get(to);
805
+ if (
806
+ // reject this request if there was no previous session to replace
807
+ session === void 0 || // or if both parties do not agree about the next expected sequence number
808
+ session.nextExpectedAck < nextExpectedSeq || // or if both parties do not agree on the advertised session id
809
+ session.advertisedSessionId !== sessionId
810
+ ) {
811
+ return false;
812
+ }
813
+ this.log?.info(
814
+ `reused existing session for ${to}`,
815
+ session.loggingMetadata
816
+ );
817
+ return session;
818
+ }
700
819
  getOrCreateSession({
701
820
  to,
702
821
  conn,
@@ -761,6 +880,16 @@ var Transport = class {
761
880
  * @param connectedTo The peer we are connected to.
762
881
  */
763
882
  onDisconnect(conn, session) {
883
+ if (session.connection !== void 0 && session.connection.id !== conn.id) {
884
+ session.telemetry.span.addEvent("onDisconnect race");
885
+ this.log?.warn("onDisconnect race", {
886
+ clientId: this.clientId,
887
+ ...session.loggingMetadata,
888
+ ...conn.loggingMetadata,
889
+ tags: ["invariant-violation"]
890
+ });
891
+ return;
892
+ }
764
893
  conn.telemetry?.span.end();
765
894
  this.eventDispatcher.dispatchEvent("connectionStatus", {
766
895
  status: "disconnect",
@@ -768,6 +897,16 @@ var Transport = class {
768
897
  });
769
898
  session.connection = void 0;
770
899
  session.beginGrace(() => {
900
+ if (session.connection !== void 0) {
901
+ session.telemetry.span.addEvent("session grace period race");
902
+ this.log?.warn("session grace period race", {
903
+ clientId: this.clientId,
904
+ ...session.loggingMetadata,
905
+ ...conn.loggingMetadata,
906
+ tags: ["invariant-violation"]
907
+ });
908
+ return;
909
+ }
771
910
  session.telemetry.span.addEvent("session grace period expired");
772
911
  this.deleteSession({
773
912
  session,
@@ -935,6 +1074,17 @@ var Transport = class {
935
1074
  return this.status;
936
1075
  }
937
1076
  };
1077
+
1078
+ // util/stringify.ts
1079
+ function coerceErrorString(err) {
1080
+ if (err instanceof Error) {
1081
+ return err.message || "unknown reason";
1082
+ }
1083
+ return `[coerced to error] ${String(err)}`;
1084
+ }
1085
+
1086
+ // transport/server.ts
1087
+ var import_value2 = require("@sinclair/typebox/value");
938
1088
  var ServerTransport = class extends Transport {
939
1089
  /**
940
1090
  * The options for this transport.
@@ -983,7 +1133,7 @@ var ServerTransport = class extends Transport {
983
1133
  }
984
1134
  );
985
1135
  conn.telemetry?.span.setStatus({
986
- code: import_api3.SpanStatusCode.ERROR,
1136
+ code: import_api4.SpanStatusCode.ERROR,
987
1137
  message: "handshake timeout"
988
1138
  });
989
1139
  conn.close();
@@ -1034,7 +1184,7 @@ var ServerTransport = class extends Transport {
1034
1184
  });
1035
1185
  conn.addErrorListener((err) => {
1036
1186
  conn.telemetry?.span.setStatus({
1037
- code: import_api3.SpanStatusCode.ERROR,
1187
+ code: import_api4.SpanStatusCode.ERROR,
1038
1188
  message: "connection error"
1039
1189
  });
1040
1190
  if (!session)
@@ -1048,22 +1198,26 @@ var ServerTransport = class extends Transport {
1048
1198
  async validateHandshakeMetadata(conn, session, rawMetadata, from) {
1049
1199
  let parsedMetadata = {};
1050
1200
  if (this.handshakeExtensions) {
1051
- if (!import_value.Value.Check(this.handshakeExtensions.schema, rawMetadata)) {
1201
+ if (!import_value2.Value.Check(this.handshakeExtensions.schema, rawMetadata)) {
1052
1202
  conn.telemetry?.span.setStatus({
1053
- code: import_api3.SpanStatusCode.ERROR,
1203
+ code: import_api4.SpanStatusCode.ERROR,
1054
1204
  message: "malformed handshake meta"
1055
1205
  });
1056
1206
  const reason = "received malformed handshake metadata";
1057
- const responseMsg = handshakeResponseMessage(this.clientId, from, {
1058
- ok: false,
1059
- reason
1207
+ const responseMsg = handshakeResponseMessage({
1208
+ from: this.clientId,
1209
+ to: from,
1210
+ status: {
1211
+ ok: false,
1212
+ reason
1213
+ }
1060
1214
  });
1061
1215
  conn.send(this.codec.toBuffer(responseMsg));
1062
1216
  this.log?.warn(`received malformed handshake metadata from ${from}`, {
1063
1217
  ...conn.loggingMetadata,
1064
1218
  clientId: this.clientId,
1065
1219
  validationErrors: [
1066
- ...import_value.Value.Errors(this.handshakeExtensions.schema, rawMetadata)
1220
+ ...import_value2.Value.Errors(this.handshakeExtensions.schema, rawMetadata)
1067
1221
  ]
1068
1222
  });
1069
1223
  this.protocolError(ProtocolError.HandshakeFailed, reason);
@@ -1077,12 +1231,16 @@ var ServerTransport = class extends Transport {
1077
1231
  if (parsedMetadata === false) {
1078
1232
  const reason = "rejected by handshake handler";
1079
1233
  conn.telemetry?.span.setStatus({
1080
- code: import_api3.SpanStatusCode.ERROR,
1234
+ code: import_api4.SpanStatusCode.ERROR,
1081
1235
  message: reason
1082
1236
  });
1083
- const responseMsg = handshakeResponseMessage(this.clientId, from, {
1084
- ok: false,
1085
- reason
1237
+ const responseMsg = handshakeResponseMessage({
1238
+ from: this.clientId,
1239
+ to: from,
1240
+ status: {
1241
+ ok: false,
1242
+ reason
1243
+ }
1086
1244
  });
1087
1245
  conn.send(this.codec.toBuffer(responseMsg));
1088
1246
  this.log?.warn(`rejected handshake from ${from}`, {
@@ -1099,7 +1257,7 @@ var ServerTransport = class extends Transport {
1099
1257
  const parsed = this.parseMsg(data, conn);
1100
1258
  if (!parsed) {
1101
1259
  conn.telemetry?.span.setStatus({
1102
- code: import_api3.SpanStatusCode.ERROR,
1260
+ code: import_api4.SpanStatusCode.ERROR,
1103
1261
  message: "non-transport message"
1104
1262
  });
1105
1263
  this.protocolError(
@@ -1108,15 +1266,19 @@ var ServerTransport = class extends Transport {
1108
1266
  );
1109
1267
  return false;
1110
1268
  }
1111
- if (!import_value.Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
1269
+ if (!import_value2.Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
1112
1270
  conn.telemetry?.span.setStatus({
1113
- code: import_api3.SpanStatusCode.ERROR,
1271
+ code: import_api4.SpanStatusCode.ERROR,
1114
1272
  message: "invalid handshake request"
1115
1273
  });
1116
1274
  const reason = "received invalid handshake msg";
1117
- const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1118
- ok: false,
1119
- reason
1275
+ const responseMsg2 = handshakeResponseMessage({
1276
+ from: this.clientId,
1277
+ to: parsed.from,
1278
+ status: {
1279
+ ok: false,
1280
+ reason
1281
+ }
1120
1282
  });
1121
1283
  conn.send(this.codec.toBuffer(responseMsg2));
1122
1284
  this.log?.warn(reason, {
@@ -1126,7 +1288,7 @@ var ServerTransport = class extends Transport {
1126
1288
  // before passing it to user-land
1127
1289
  transportMessage: parsed,
1128
1290
  validationErrors: [
1129
- ...import_value.Value.Errors(ControlMessageHandshakeRequestSchema, parsed.payload)
1291
+ ...import_value2.Value.Errors(ControlMessageHandshakeRequestSchema, parsed.payload)
1130
1292
  ]
1131
1293
  });
1132
1294
  this.protocolError(
@@ -1138,13 +1300,17 @@ var ServerTransport = class extends Transport {
1138
1300
  const gotVersion = parsed.payload.protocolVersion;
1139
1301
  if (gotVersion !== PROTOCOL_VERSION) {
1140
1302
  conn.telemetry?.span.setStatus({
1141
- code: import_api3.SpanStatusCode.ERROR,
1303
+ code: import_api4.SpanStatusCode.ERROR,
1142
1304
  message: "incorrect protocol version"
1143
1305
  });
1144
1306
  const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
1145
- const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1146
- ok: false,
1147
- reason
1307
+ const responseMsg2 = handshakeResponseMessage({
1308
+ from: this.clientId,
1309
+ to: parsed.from,
1310
+ status: {
1311
+ ok: false,
1312
+ reason
1313
+ }
1148
1314
  });
1149
1315
  conn.send(this.codec.toBuffer(responseMsg2));
1150
1316
  this.log?.warn(
@@ -1164,20 +1330,67 @@ var ServerTransport = class extends Transport {
1164
1330
  if (parsedMetadata === false) {
1165
1331
  return false;
1166
1332
  }
1167
- const { session, isTransparentReconnect } = this.getOrCreateSession({
1168
- to: parsed.from,
1169
- conn,
1170
- sessionId: parsed.payload.sessionId,
1171
- propagationCtx: parsed.tracing
1172
- });
1333
+ let session;
1334
+ let isTransparentReconnect;
1335
+ if (!parsed.payload.expectedSessionState) {
1336
+ ({ session, isTransparentReconnect } = this.getOrCreateSession({
1337
+ to: parsed.from,
1338
+ conn,
1339
+ sessionId: parsed.payload.sessionId,
1340
+ propagationCtx: parsed.tracing
1341
+ }));
1342
+ } else if (parsed.payload.expectedSessionState.reconnect) {
1343
+ const existingSession = this.getExistingSession({
1344
+ to: parsed.from,
1345
+ sessionId: parsed.payload.sessionId,
1346
+ nextExpectedSeq: parsed.payload.expectedSessionState.nextExpectedSeq
1347
+ });
1348
+ if (existingSession === false) {
1349
+ conn.telemetry?.span.setStatus({
1350
+ code: import_api4.SpanStatusCode.ERROR,
1351
+ message: SESSION_STATE_MISMATCH
1352
+ });
1353
+ const reason = SESSION_STATE_MISMATCH;
1354
+ const responseMsg2 = handshakeResponseMessage({
1355
+ from: this.clientId,
1356
+ to: parsed.from,
1357
+ status: {
1358
+ ok: false,
1359
+ reason
1360
+ }
1361
+ });
1362
+ conn.send(this.codec.toBuffer(responseMsg2));
1363
+ this.log?.warn(
1364
+ `'received handshake msg with incompatible existing session state: ${parsed.payload.sessionId}`,
1365
+ { ...conn.loggingMetadata, clientId: this.clientId }
1366
+ );
1367
+ this.protocolError(ProtocolError.HandshakeFailed, reason);
1368
+ return false;
1369
+ }
1370
+ session = existingSession;
1371
+ isTransparentReconnect = false;
1372
+ } else {
1373
+ const createdSession = this.createNewSession({
1374
+ to: parsed.from,
1375
+ conn,
1376
+ sessionId: parsed.payload.sessionId,
1377
+ propagationCtx: parsed.tracing
1378
+ });
1379
+ session = createdSession;
1380
+ isTransparentReconnect = false;
1381
+ }
1173
1382
  this.sessionHandshakeMetadata.set(session, parsedMetadata);
1174
1383
  this.log?.debug(
1175
1384
  `handshake from ${parsed.from} ok, responding with handshake success`,
1176
1385
  conn.loggingMetadata
1177
1386
  );
1178
- const responseMsg = handshakeResponseMessage(this.clientId, parsed.from, {
1179
- ok: true,
1180
- sessionId: session.id
1387
+ const responseMsg = handshakeResponseMessage({
1388
+ from: this.clientId,
1389
+ to: parsed.from,
1390
+ status: {
1391
+ ok: true,
1392
+ sessionId: session.id
1393
+ }
1181
1394
  });
1182
1395
  conn.send(this.codec.toBuffer(responseMsg));
1183
1396
  this.onConnect(conn, session, isTransparentReconnect);
@@ -1185,57 +1398,6 @@ var ServerTransport = class extends Transport {
1185
1398
  }
1186
1399
  };
1187
1400
 
1188
- // transport/impls/ws/connection.ts
1189
- var WebSocketConnection = class extends Connection {
1190
- errorCb = null;
1191
- closeCb = null;
1192
- ws;
1193
- constructor(ws) {
1194
- super();
1195
- this.ws = ws;
1196
- this.ws.binaryType = "arraybuffer";
1197
- let didError = false;
1198
- this.ws.onerror = () => {
1199
- didError = true;
1200
- };
1201
- this.ws.onclose = ({ code, reason }) => {
1202
- if (didError && this.errorCb) {
1203
- this.errorCb(
1204
- new Error(
1205
- `websocket closed with code and reason: ${code} - ${reason}`
1206
- )
1207
- );
1208
- }
1209
- if (this.closeCb) {
1210
- this.closeCb();
1211
- }
1212
- };
1213
- }
1214
- addDataListener(cb) {
1215
- this.ws.onmessage = (msg) => cb(msg.data);
1216
- }
1217
- removeDataListener() {
1218
- this.ws.onmessage = null;
1219
- }
1220
- addCloseListener(cb) {
1221
- this.closeCb = cb;
1222
- }
1223
- addErrorListener(cb) {
1224
- this.errorCb = cb;
1225
- }
1226
- send(payload) {
1227
- if (this.ws.readyState === this.ws.OPEN) {
1228
- this.ws.send(payload);
1229
- return true;
1230
- } else {
1231
- return false;
1232
- }
1233
- }
1234
- close() {
1235
- this.ws.close();
1236
- }
1237
- };
1238
-
1239
1401
  // transport/impls/ws/server.ts
1240
1402
  var WebSocketServerTransport = class extends ServerTransport {
1241
1403
  wss;