@replit/river 0.200.0-rc.7 → 0.200.0-rc.8

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 (54) hide show
  1. package/dist/{chunk-BZBEE2VR.js → chunk-3ROTSXAO.js} +14 -4
  2. package/dist/chunk-3ROTSXAO.js.map +1 -0
  3. package/dist/{chunk-VLW5OKZG.js → chunk-B5VE44UX.js} +2 -2
  4. package/dist/{chunk-CXPZSAU4.js → chunk-FAIV2RO2.js} +62 -36
  5. package/dist/chunk-FAIV2RO2.js.map +1 -0
  6. package/dist/{chunk-U4W75CMT.js → chunk-J54ZWTQM.js} +7 -6
  7. package/dist/chunk-J54ZWTQM.js.map +1 -0
  8. package/dist/{chunk-F2E7ILHW.js → chunk-XV5WUEIR.js} +70 -59
  9. package/dist/chunk-XV5WUEIR.js.map +1 -0
  10. package/dist/{chunk-3XKJOFZA.js → chunk-Y3JHOIJ7.js} +141 -50
  11. package/dist/chunk-Y3JHOIJ7.js.map +1 -0
  12. package/dist/{chunk-XIJVDPYY.js → chunk-Y4DP7WHM.js} +2 -2
  13. package/dist/{chunk-XIJVDPYY.js.map → chunk-Y4DP7WHM.js.map} +1 -1
  14. package/dist/{client-829bf1f9.d.ts → client-22a47343.d.ts} +3 -5
  15. package/dist/{connection-5e67d641.d.ts → connection-260e45a8.d.ts} +1 -1
  16. package/dist/{context-9eabf54f.d.ts → context-b4aff18f.d.ts} +90 -43
  17. package/dist/logging/index.d.cts +1 -1
  18. package/dist/logging/index.d.ts +1 -1
  19. package/dist/{message-fd349b27.d.ts → message-7d135e38.d.ts} +3 -1
  20. package/dist/router/index.cjs +12 -3
  21. package/dist/router/index.cjs.map +1 -1
  22. package/dist/router/index.d.cts +9 -8
  23. package/dist/router/index.d.ts +9 -8
  24. package/dist/router/index.js +2 -2
  25. package/dist/{server-d82a2d9b.d.ts → server-dd6a9853.d.ts} +27 -6
  26. package/dist/{services-6a446f04.d.ts → services-bd2c50c0.d.ts} +3 -3
  27. package/dist/transport/impls/ws/client.cjs +216 -88
  28. package/dist/transport/impls/ws/client.cjs.map +1 -1
  29. package/dist/transport/impls/ws/client.d.cts +5 -4
  30. package/dist/transport/impls/ws/client.d.ts +5 -4
  31. package/dist/transport/impls/ws/client.js +8 -7
  32. package/dist/transport/impls/ws/client.js.map +1 -1
  33. package/dist/transport/impls/ws/server.cjs +220 -109
  34. package/dist/transport/impls/ws/server.cjs.map +1 -1
  35. package/dist/transport/impls/ws/server.d.cts +5 -4
  36. package/dist/transport/impls/ws/server.d.ts +5 -4
  37. package/dist/transport/impls/ws/server.js +5 -5
  38. package/dist/transport/index.cjs +278 -141
  39. package/dist/transport/index.cjs.map +1 -1
  40. package/dist/transport/index.d.cts +5 -4
  41. package/dist/transport/index.d.ts +5 -4
  42. package/dist/transport/index.js +5 -5
  43. package/dist/util/testHelpers.cjs +151 -51
  44. package/dist/util/testHelpers.cjs.map +1 -1
  45. package/dist/util/testHelpers.d.cts +5 -4
  46. package/dist/util/testHelpers.d.ts +5 -4
  47. package/dist/util/testHelpers.js +3 -3
  48. package/package.json +1 -1
  49. package/dist/chunk-3XKJOFZA.js.map +0 -1
  50. package/dist/chunk-BZBEE2VR.js.map +0 -1
  51. package/dist/chunk-CXPZSAU4.js.map +0 -1
  52. package/dist/chunk-F2E7ILHW.js.map +0 -1
  53. package/dist/chunk-U4W75CMT.js.map +0 -1
  54. /package/dist/{chunk-VLW5OKZG.js.map → chunk-B5VE44UX.js.map} +0 -0
@@ -197,11 +197,20 @@ var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
197
197
  var HandshakeErrorRetriableResponseCodes = import_typebox.Type.Union([
198
198
  import_typebox.Type.Literal("SESSION_STATE_MISMATCH")
199
199
  ]);
200
+ var HandshakeErrorCustomHandlerFatalResponseCodes = import_typebox.Type.Union([
201
+ // The custom validation handler rejected the handler because the client is unsupported.
202
+ import_typebox.Type.Literal("REJECTED_UNSUPPORTED_CLIENT"),
203
+ // The custom validation handler rejected the handshake.
204
+ import_typebox.Type.Literal("REJECTED_BY_CUSTOM_HANDLER")
205
+ ]);
200
206
  var HandshakeErrorFatalResponseCodes = import_typebox.Type.Union([
207
+ HandshakeErrorCustomHandlerFatalResponseCodes,
208
+ // The ciient sent a handshake that doesn't comply with the extended handshake metadata.
201
209
  import_typebox.Type.Literal("MALFORMED_HANDSHAKE_META"),
210
+ // The ciient sent a handshake that doesn't comply with ControlMessageHandshakeRequestSchema.
202
211
  import_typebox.Type.Literal("MALFORMED_HANDSHAKE"),
203
- import_typebox.Type.Literal("PROTOCOL_VERSION_MISMATCH"),
204
- import_typebox.Type.Literal("REJECTED_BY_CUSTOM_HANDLER")
212
+ // The client's protocol version does not match the server's.
213
+ import_typebox.Type.Literal("PROTOCOL_VERSION_MISMATCH")
205
214
  ]);
206
215
  var HandshakeErrorResponseCodes = import_typebox.Type.Union([
207
216
  HandshakeErrorRetriableResponseCodes,
@@ -314,6 +323,7 @@ var defaultTransportOptions = {
314
323
  sessionDisconnectGraceMs: 5e3,
315
324
  connectionTimeoutMs: 2e3,
316
325
  handshakeTimeoutMs: 1e3,
326
+ enableTransparentSessionReconnects: true,
317
327
  codec: NaiveJsonCodec
318
328
  };
319
329
  var defaultConnectionRetryOptions = {
@@ -448,6 +458,7 @@ var StateMachineState = class {
448
458
  }
449
459
  if (prop === "_handleClose") {
450
460
  return () => {
461
+ target._isConsumed = true;
451
462
  target._handleStateExit();
452
463
  target._handleClose();
453
464
  };
@@ -530,15 +541,18 @@ var IdentifiedSession = class extends CommonSession {
530
541
  }
531
542
  get loggingMetadata() {
532
543
  const spanContext = this.telemetry.span.spanContext();
533
- return {
544
+ const metadata = {
534
545
  clientId: this.from,
535
546
  connectedTo: this.to,
536
- sessionId: this.id,
537
- telemetry: {
547
+ sessionId: this.id
548
+ };
549
+ if (this.telemetry.span.isRecording()) {
550
+ metadata.telemetry = {
538
551
  traceId: spanContext.traceId,
539
552
  spanId: spanContext.spanId
540
- }
541
- };
553
+ };
554
+ }
555
+ return metadata;
542
556
  }
543
557
  constructMsg(partialMsg) {
544
558
  const msg = {
@@ -567,9 +581,32 @@ var IdentifiedSession = class extends CommonSession {
567
581
  this.telemetry.span.end();
568
582
  }
569
583
  };
584
+ var IdentifiedSessionWithGracePeriod = class extends IdentifiedSession {
585
+ graceExpiryTime;
586
+ gracePeriodTimeout;
587
+ listeners;
588
+ constructor(props) {
589
+ super(props);
590
+ this.listeners = props.listeners;
591
+ this.graceExpiryTime = props.graceExpiryTime;
592
+ this.gracePeriodTimeout = setTimeout(() => {
593
+ this.listeners.onSessionGracePeriodElapsed();
594
+ }, this.graceExpiryTime - Date.now());
595
+ }
596
+ _handleStateExit() {
597
+ super._handleStateExit();
598
+ if (this.gracePeriodTimeout) {
599
+ clearTimeout(this.gracePeriodTimeout);
600
+ this.gracePeriodTimeout = void 0;
601
+ }
602
+ }
603
+ _handleClose() {
604
+ super._handleClose();
605
+ }
606
+ };
570
607
 
571
608
  // transport/sessionStateMachine/SessionConnecting.ts
572
- var SessionConnecting = class extends IdentifiedSession {
609
+ var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
573
610
  state = "Connecting" /* Connecting */;
574
611
  connPromise;
575
612
  listeners;
@@ -578,9 +615,6 @@ var SessionConnecting = class extends IdentifiedSession {
578
615
  super(props);
579
616
  this.connPromise = props.connPromise;
580
617
  this.listeners = props.listeners;
581
- this.connectionTimeout = setTimeout(() => {
582
- this.listeners.onConnectionTimeout();
583
- }, this.options.connectionTimeoutMs);
584
618
  this.connPromise.then(
585
619
  (conn) => {
586
620
  if (this._isConsumed)
@@ -593,17 +627,33 @@ var SessionConnecting = class extends IdentifiedSession {
593
627
  this.listeners.onConnectionFailed(err);
594
628
  }
595
629
  );
630
+ this.connectionTimeout = setTimeout(() => {
631
+ this.listeners.onConnectionTimeout();
632
+ }, this.options.connectionTimeoutMs);
596
633
  }
597
634
  // close a pending connection if it resolves, ignore errors if the promise
598
635
  // ends up rejected anyways
599
636
  bestEffortClose() {
600
- void this.connPromise.then((conn) => conn.close()).catch(() => {
637
+ const logger = this.log;
638
+ const metadata = this.loggingMetadata;
639
+ this.connPromise.then((conn) => {
640
+ conn.close();
641
+ logger?.info(
642
+ "connection eventually resolved but session has transitioned, closed connection",
643
+ {
644
+ ...metadata,
645
+ ...conn.loggingMetadata
646
+ }
647
+ );
648
+ }).catch(() => {
601
649
  });
602
650
  }
603
651
  _handleStateExit() {
604
652
  super._handleStateExit();
605
- clearTimeout(this.connectionTimeout);
606
- this.connectionTimeout = void 0;
653
+ if (this.connectionTimeout) {
654
+ clearTimeout(this.connectionTimeout);
655
+ this.connectionTimeout = void 0;
656
+ }
607
657
  }
608
658
  _handleClose() {
609
659
  this.bestEffortClose();
@@ -612,26 +662,13 @@ var SessionConnecting = class extends IdentifiedSession {
612
662
  };
613
663
 
614
664
  // transport/sessionStateMachine/SessionNoConnection.ts
615
- var SessionNoConnection = class extends IdentifiedSession {
665
+ var SessionNoConnection = class extends IdentifiedSessionWithGracePeriod {
616
666
  state = "NoConnection" /* NoConnection */;
617
- listeners;
618
- gracePeriodTimeout;
619
- constructor(props) {
620
- super(props);
621
- this.listeners = props.listeners;
622
- this.gracePeriodTimeout = setTimeout(() => {
623
- this.listeners.onSessionGracePeriodElapsed();
624
- }, this.options.sessionDisconnectGraceMs);
625
- }
626
667
  _handleClose() {
627
668
  super._handleClose();
628
669
  }
629
670
  _handleStateExit() {
630
671
  super._handleStateExit();
631
- if (this.gracePeriodTimeout) {
632
- clearTimeout(this.gracePeriodTimeout);
633
- this.gracePeriodTimeout = void 0;
634
- }
635
672
  }
636
673
  };
637
674
 
@@ -639,7 +676,7 @@ var SessionNoConnection = class extends IdentifiedSession {
639
676
  var import_api = require("@opentelemetry/api");
640
677
 
641
678
  // package.json
642
- var version = "0.200.0-rc.7";
679
+ var version = "0.200.0-rc.8";
643
680
 
644
681
  // tracing/index.ts
645
682
  function createSessionTelemetryInfo(sessionId, to, from, propagationCtx) {
@@ -678,20 +715,24 @@ var SessionWaitingForHandshake = class extends CommonSession {
678
715
  this.conn.addErrorListener(this.listeners.onConnectionErrored);
679
716
  this.conn.addCloseListener(this.listeners.onConnectionClosed);
680
717
  }
718
+ get loggingMetadata() {
719
+ return {
720
+ clientId: this.from,
721
+ connId: this.conn.id,
722
+ ...this.conn.loggingMetadata
723
+ };
724
+ }
681
725
  onHandshakeData = (msg) => {
682
726
  const parsedMsg = this.parseMsg(msg);
683
727
  if (parsedMsg === null) {
684
- this.listeners.onInvalidHandshake("could not parse message");
728
+ this.listeners.onInvalidHandshake(
729
+ "could not parse message",
730
+ "MALFORMED_HANDSHAKE"
731
+ );
685
732
  return;
686
733
  }
687
734
  this.listeners.onHandshake(parsedMsg);
688
735
  };
689
- get loggingMetadata() {
690
- return {
691
- clientId: this.from,
692
- connId: this.conn.id
693
- };
694
- }
695
736
  sendHandshake(msg) {
696
737
  return this.conn.send(this.options.codec.toBuffer(msg));
697
738
  }
@@ -708,7 +749,7 @@ var SessionWaitingForHandshake = class extends CommonSession {
708
749
  };
709
750
 
710
751
  // transport/sessionStateMachine/SessionHandshaking.ts
711
- var SessionHandshaking = class extends IdentifiedSession {
752
+ var SessionHandshaking = class extends IdentifiedSessionWithGracePeriod {
712
753
  state = "Handshaking" /* Handshaking */;
713
754
  conn;
714
755
  listeners;
@@ -724,10 +765,19 @@ var SessionHandshaking = class extends IdentifiedSession {
724
765
  this.conn.addErrorListener(this.listeners.onConnectionErrored);
725
766
  this.conn.addCloseListener(this.listeners.onConnectionClosed);
726
767
  }
768
+ get loggingMetadata() {
769
+ return {
770
+ ...super.loggingMetadata,
771
+ ...this.conn.loggingMetadata
772
+ };
773
+ }
727
774
  onHandshakeData = (msg) => {
728
775
  const parsedMsg = this.parseMsg(msg);
729
776
  if (parsedMsg === null) {
730
- this.listeners.onInvalidHandshake("could not parse message");
777
+ this.listeners.onInvalidHandshake(
778
+ "could not parse message",
779
+ "MALFORMED_HANDSHAKE"
780
+ );
731
781
  return;
732
782
  }
733
783
  this.listeners.onHandshake(parsedMsg);
@@ -740,7 +790,10 @@ var SessionHandshaking = class extends IdentifiedSession {
740
790
  this.conn.removeDataListener(this.onHandshakeData);
741
791
  this.conn.removeErrorListener(this.listeners.onConnectionErrored);
742
792
  this.conn.removeCloseListener(this.listeners.onConnectionClosed);
743
- clearTimeout(this.handshakeTimeout);
793
+ if (this.handshakeTimeout) {
794
+ clearTimeout(this.handshakeTimeout);
795
+ this.handshakeTimeout = void 0;
796
+ }
744
797
  }
745
798
  _handleClose() {
746
799
  super._handleClose();
@@ -805,6 +858,12 @@ var SessionConnected = class extends IdentifiedSession {
805
858
  this.heartbeatMisses++;
806
859
  }, this.options.heartbeatIntervalMs);
807
860
  }
861
+ get loggingMetadata() {
862
+ return {
863
+ ...super.loggingMetadata,
864
+ ...this.conn.loggingMetadata
865
+ };
866
+ }
808
867
  startActiveHeartbeat() {
809
868
  this.isActivelyHeartbeating = true;
810
869
  }
@@ -820,8 +879,10 @@ var SessionConnected = class extends IdentifiedSession {
820
879
  }
821
880
  onMessageData = (msg) => {
822
881
  const parsedMsg = this.parseMsg(msg);
823
- if (parsedMsg === null)
882
+ if (parsedMsg === null) {
883
+ this.listeners.onInvalidMessage("could not parse message");
824
884
  return;
885
+ }
825
886
  if (parsedMsg.seq !== this.ack) {
826
887
  if (parsedMsg.seq < this.ack) {
827
888
  this.log?.debug(
@@ -878,7 +939,7 @@ var SessionConnected = class extends IdentifiedSession {
878
939
  };
879
940
 
880
941
  // transport/sessionStateMachine/SessionBackingOff.ts
881
- var SessionBackingOff = class extends IdentifiedSession {
942
+ var SessionBackingOff = class extends IdentifiedSessionWithGracePeriod {
882
943
  state = "BackingOff" /* BackingOff */;
883
944
  listeners;
884
945
  backoffTimeout;
@@ -916,6 +977,12 @@ function inheritSharedSession(session) {
916
977
  protocolVersion: session.protocolVersion
917
978
  };
918
979
  }
980
+ function inheritSharedSessionWithGrace(session) {
981
+ return {
982
+ ...inheritSharedSession(session),
983
+ graceExpiryTime: session.graceExpiryTime
984
+ };
985
+ }
919
986
  var SessionStateGraph = {
920
987
  entrypoints: {
921
988
  NoConnection: (to, from, listeners, options, protocolVersion, log) => {
@@ -929,6 +996,7 @@ var SessionStateGraph = {
929
996
  to,
930
997
  seq: 0,
931
998
  ack: 0,
999
+ graceExpiryTime: Date.now() + options.sessionDisconnectGraceMs,
932
1000
  sendBuffer,
933
1001
  telemetry,
934
1002
  options,
@@ -961,7 +1029,7 @@ var SessionStateGraph = {
961
1029
  transition: {
962
1030
  // happy path transitions
963
1031
  NoConnectionToBackingOff: (oldSession, backoffMs, listeners) => {
964
- const carriedState = inheritSharedSession(oldSession);
1032
+ const carriedState = inheritSharedSessionWithGrace(oldSession);
965
1033
  oldSession._handleStateExit();
966
1034
  const session = new SessionBackingOff({
967
1035
  backoffMs,
@@ -978,7 +1046,7 @@ var SessionStateGraph = {
978
1046
  return session;
979
1047
  },
980
1048
  BackingOffToConnecting: (oldSession, connPromise, listeners) => {
981
- const carriedState = inheritSharedSession(oldSession);
1049
+ const carriedState = inheritSharedSessionWithGrace(oldSession);
982
1050
  oldSession._handleStateExit();
983
1051
  const session = new SessionConnecting({
984
1052
  connPromise,
@@ -995,7 +1063,7 @@ var SessionStateGraph = {
995
1063
  return session;
996
1064
  },
997
1065
  ConnectingToHandshaking: (oldSession, conn, listeners) => {
998
- const carriedState = inheritSharedSession(oldSession);
1066
+ const carriedState = inheritSharedSessionWithGrace(oldSession);
999
1067
  oldSession._handleStateExit();
1000
1068
  const session = new SessionHandshaking({
1001
1069
  conn,
@@ -1073,9 +1141,12 @@ var SessionStateGraph = {
1073
1141
  },
1074
1142
  // disconnect paths
1075
1143
  BackingOffToNoConnection: (oldSession, listeners) => {
1076
- const carriedState = inheritSharedSession(oldSession);
1144
+ const carriedState = inheritSharedSessionWithGrace(oldSession);
1077
1145
  oldSession._handleStateExit();
1078
- const session = new SessionNoConnection({ listeners, ...carriedState });
1146
+ const session = new SessionNoConnection({
1147
+ listeners,
1148
+ ...carriedState
1149
+ });
1079
1150
  session.log?.info(
1080
1151
  `session ${session.id} transition from BackingOff to NoConnection`,
1081
1152
  {
@@ -1086,10 +1157,13 @@ var SessionStateGraph = {
1086
1157
  return session;
1087
1158
  },
1088
1159
  ConnectingToNoConnection: (oldSession, listeners) => {
1089
- const carriedState = inheritSharedSession(oldSession);
1160
+ const carriedState = inheritSharedSessionWithGrace(oldSession);
1090
1161
  oldSession.bestEffortClose();
1091
1162
  oldSession._handleStateExit();
1092
- const session = new SessionNoConnection({ listeners, ...carriedState });
1163
+ const session = new SessionNoConnection({
1164
+ listeners,
1165
+ ...carriedState
1166
+ });
1093
1167
  session.log?.info(
1094
1168
  `session ${session.id} transition from Connecting to NoConnection`,
1095
1169
  {
@@ -1100,10 +1174,13 @@ var SessionStateGraph = {
1100
1174
  return session;
1101
1175
  },
1102
1176
  HandshakingToNoConnection: (oldSession, listeners) => {
1103
- const carriedState = inheritSharedSession(oldSession);
1177
+ const carriedState = inheritSharedSessionWithGrace(oldSession);
1104
1178
  oldSession.conn.close();
1105
1179
  oldSession._handleStateExit();
1106
- const session = new SessionNoConnection({ listeners, ...carriedState });
1180
+ const session = new SessionNoConnection({
1181
+ listeners,
1182
+ ...carriedState
1183
+ });
1107
1184
  session.log?.info(
1108
1185
  `session ${session.id} transition from Handshaking to NoConnection`,
1109
1186
  {
@@ -1115,9 +1192,14 @@ var SessionStateGraph = {
1115
1192
  },
1116
1193
  ConnectedToNoConnection: (oldSession, listeners) => {
1117
1194
  const carriedState = inheritSharedSession(oldSession);
1195
+ const graceExpiryTime = Date.now() + oldSession.options.sessionDisconnectGraceMs;
1118
1196
  oldSession.conn.close();
1119
1197
  oldSession._handleStateExit();
1120
- const session = new SessionNoConnection({ listeners, ...carriedState });
1198
+ const session = new SessionNoConnection({
1199
+ listeners,
1200
+ graceExpiryTime,
1201
+ ...carriedState
1202
+ });
1121
1203
  session.log?.info(
1122
1204
  `session ${session.id} transition from Connected to NoConnection`,
1123
1205
  {
@@ -1134,24 +1216,42 @@ var ClientSessionStateGraph = {
1134
1216
  entrypoint: SessionStateGraph.entrypoints.NoConnection,
1135
1217
  transition: {
1136
1218
  // happy paths
1219
+ // NoConnection -> BackingOff: attempt to connect
1137
1220
  NoConnectionToBackingOff: transitions.NoConnectionToBackingOff,
1221
+ // BackingOff -> Connecting: backoff period elapsed, start connection
1138
1222
  BackingOffToConnecting: transitions.BackingOffToConnecting,
1223
+ // Connecting -> Handshaking: connection established, start handshake
1139
1224
  ConnectingToHandshaking: transitions.ConnectingToHandshaking,
1225
+ // Handshaking -> Connected: handshake complete, session ready
1140
1226
  HandshakingToConnected: transitions.HandshakingToConnected,
1141
1227
  // disconnect paths
1228
+ // BackingOff -> NoConnection: unused
1142
1229
  BackingOffToNoConnection: transitions.BackingOffToNoConnection,
1230
+ // Connecting -> NoConnection: connection failed or connection timeout
1143
1231
  ConnectingToNoConnection: transitions.ConnectingToNoConnection,
1232
+ // Handshaking -> NoConnection: connection closed or handshake timeout
1144
1233
  HandshakingToNoConnection: transitions.HandshakingToNoConnection,
1234
+ // Connected -> NoConnection: connection closed
1145
1235
  ConnectedToNoConnection: transitions.ConnectedToNoConnection
1236
+ // destroy/close paths
1237
+ // NoConnection -> x: grace period elapsed
1238
+ // BackingOff -> x: grace period elapsed
1239
+ // Connecting -> x: grace period elapsed
1240
+ // Handshaking -> x: grace period elapsed or invalid handshake message or handshake rejection
1241
+ // Connected -> x: grace period elapsed or invalid message
1146
1242
  }
1147
1243
  };
1148
1244
  var ServerSessionStateGraph = {
1149
1245
  entrypoint: SessionStateGraph.entrypoints.WaitingForHandshake,
1150
1246
  transition: {
1151
1247
  // happy paths
1248
+ // WaitingForHandshake -> Connected: handshake complete, session ready
1152
1249
  WaitingForHandshakeToConnected: transitions.WaitingForHandshakeToConnected,
1153
1250
  // disconnect paths
1251
+ // Connected -> NoConnection: connection closed
1154
1252
  ConnectedToNoConnection: transitions.ConnectedToNoConnection
1253
+ // destroy/close paths
1254
+ // WaitingForHandshake -> x: handshake timeout elapsed or invalid handshake message or handshake rejection or connection closed
1155
1255
  }
1156
1256
  };
1157
1257
 
@@ -1220,8 +1320,8 @@ var Transport = class {
1220
1320
  removeEventListener(type, handler) {
1221
1321
  this.eventDispatcher.removeEventListener(type, handler);
1222
1322
  }
1223
- protocolError(type, message) {
1224
- this.eventDispatcher.dispatchEvent("protocolError", { type, message });
1323
+ protocolError(message) {
1324
+ this.eventDispatcher.dispatchEvent("protocolError", message);
1225
1325
  }
1226
1326
  /**
1227
1327
  * Default close implementation for transports. You should override this in the downstream
@@ -1268,8 +1368,9 @@ var Transport = class {
1268
1368
  status: "disconnect",
1269
1369
  session
1270
1370
  });
1371
+ const to = session.to;
1271
1372
  session.close();
1272
- this.sessions.delete(session.to);
1373
+ this.sessions.delete(to);
1273
1374
  }
1274
1375
  // common listeners
1275
1376
  onSessionGracePeriodElapsed(session) {
@@ -1426,13 +1527,17 @@ var ServerTransport = class extends Transport {
1426
1527
  receivedHandshake = true;
1427
1528
  void this.onHandshakeRequest(pendingSession, msg);
1428
1529
  },
1429
- onInvalidHandshake: (reason) => {
1530
+ onInvalidHandshake: (reason, code) => {
1430
1531
  this.log?.error(
1431
1532
  `invalid handshake: ${reason}`,
1432
1533
  pendingSession.loggingMetadata
1433
1534
  );
1434
1535
  this.deletePendingSession(pendingSession);
1435
- this.protocolError(ProtocolError.HandshakeFailed, reason);
1536
+ this.protocolError({
1537
+ type: ProtocolError.HandshakeFailed,
1538
+ code,
1539
+ message: reason
1540
+ });
1436
1541
  }
1437
1542
  },
1438
1543
  this.options,
@@ -1457,7 +1562,11 @@ var ServerTransport = class extends Transport {
1457
1562
  }
1458
1563
  })
1459
1564
  );
1460
- this.protocolError(ProtocolError.HandshakeFailed, reason);
1565
+ this.protocolError({
1566
+ type: ProtocolError.HandshakeFailed,
1567
+ code,
1568
+ message: reason
1569
+ });
1461
1570
  this.deletePendingSession(session);
1462
1571
  }
1463
1572
  async onHandshakeRequest(session, msg) {
@@ -1494,19 +1603,58 @@ var ServerTransport = class extends Transport {
1494
1603
  return;
1495
1604
  }
1496
1605
  let oldSession = this.sessions.get(msg.from);
1497
- const parsedMetadata = await this.validateHandshakeMetadata(
1498
- session,
1499
- oldSession,
1500
- msg.payload.metadata,
1501
- msg.from
1502
- );
1503
- if (parsedMetadata === false) {
1504
- return;
1606
+ let parsedMetadata = {};
1607
+ if (this.handshakeExtensions) {
1608
+ if (!import_value2.Value.Check(this.handshakeExtensions.schema, msg.payload.metadata)) {
1609
+ this.rejectHandshakeRequest(
1610
+ session,
1611
+ msg.from,
1612
+ "received malformed handshake metadata",
1613
+ "MALFORMED_HANDSHAKE_META",
1614
+ {
1615
+ ...session.loggingMetadata,
1616
+ connectedTo: msg.from,
1617
+ validationErrors: [
1618
+ ...import_value2.Value.Errors(
1619
+ this.handshakeExtensions.schema,
1620
+ msg.payload.metadata
1621
+ )
1622
+ ]
1623
+ }
1624
+ );
1625
+ return;
1626
+ }
1627
+ const previousParsedMetadata = oldSession ? this.sessionHandshakeMetadata.get(oldSession.to) : void 0;
1628
+ const parsedMetadataOrFailureCode = await this.handshakeExtensions.validate(
1629
+ msg.payload.metadata,
1630
+ previousParsedMetadata
1631
+ );
1632
+ if (session._isConsumed) {
1633
+ return;
1634
+ }
1635
+ if (import_value2.Value.Check(
1636
+ HandshakeErrorCustomHandlerFatalResponseCodes,
1637
+ parsedMetadataOrFailureCode
1638
+ )) {
1639
+ this.rejectHandshakeRequest(
1640
+ session,
1641
+ msg.from,
1642
+ "rejected by handshake handler",
1643
+ parsedMetadataOrFailureCode,
1644
+ {
1645
+ ...session.loggingMetadata,
1646
+ connectedTo: msg.from,
1647
+ clientId: this.clientId
1648
+ }
1649
+ );
1650
+ return;
1651
+ }
1652
+ parsedMetadata = parsedMetadataOrFailureCode;
1505
1653
  }
1506
1654
  let connectCase = "new session";
1507
1655
  const clientNextExpectedSeq = msg.payload.expectedSessionState.nextExpectedSeq;
1508
1656
  const clientNextSentSeq = msg.payload.expectedSessionState.nextSentSeq ?? 0;
1509
- if (oldSession && oldSession.id === msg.payload.sessionId) {
1657
+ if (this.options.enableTransparentSessionReconnects && oldSession && oldSession.id === msg.payload.sessionId) {
1510
1658
  connectCase = "transparent reconnection";
1511
1659
  const ourNextSeq = oldSession.nextSeq();
1512
1660
  const ourAck = oldSession.ack;
@@ -1565,10 +1713,11 @@ var ServerTransport = class extends Transport {
1565
1713
  }
1566
1714
  if (!oldSession && (clientNextSentSeq > 0 || clientNextExpectedSeq > 0)) {
1567
1715
  connectCase = "unknown session";
1716
+ const rejectionMessage = this.options.enableTransparentSessionReconnects ? `client is trying to reconnect to a session the server don't know about: ${msg.payload.sessionId}` : `client is attempting a transparent reconnect to a session but the server does not support it: ${msg.payload.sessionId}`;
1568
1717
  this.rejectHandshakeRequest(
1569
1718
  session,
1570
1719
  msg.from,
1571
- `client is trying to reconnect to a session the server don't know about: ${msg.payload.sessionId}`,
1720
+ rejectionMessage,
1572
1721
  "SESSION_STATE_MISMATCH",
1573
1722
  {
1574
1723
  ...session.loggingMetadata,
@@ -1619,7 +1768,10 @@ var ServerTransport = class extends Transport {
1619
1768
  },
1620
1769
  onMessage: (msg2) => this.handleMsg(msg2),
1621
1770
  onInvalidMessage: (reason) => {
1622
- this.protocolError(ProtocolError.MessageOrderingViolated, reason);
1771
+ this.protocolError({
1772
+ type: ProtocolError.MessageOrderingViolated,
1773
+ message: reason
1774
+ });
1623
1775
  this.deleteSession(connectedSession);
1624
1776
  }
1625
1777
  },
@@ -1630,47 +1782,6 @@ var ServerTransport = class extends Transport {
1630
1782
  this.pendingSessions.delete(session);
1631
1783
  connectedSession.startActiveHeartbeat();
1632
1784
  }
1633
- async validateHandshakeMetadata(handshakingSession, existingSession, rawMetadata, from) {
1634
- let parsedMetadata = {};
1635
- if (this.handshakeExtensions) {
1636
- if (!import_value2.Value.Check(this.handshakeExtensions.schema, rawMetadata)) {
1637
- this.rejectHandshakeRequest(
1638
- handshakingSession,
1639
- from,
1640
- "received malformed handshake metadata",
1641
- "MALFORMED_HANDSHAKE_META",
1642
- {
1643
- ...handshakingSession.loggingMetadata,
1644
- connectedTo: from,
1645
- validationErrors: [
1646
- ...import_value2.Value.Errors(this.handshakeExtensions.schema, rawMetadata)
1647
- ]
1648
- }
1649
- );
1650
- return false;
1651
- }
1652
- const previousParsedMetadata = existingSession ? this.sessionHandshakeMetadata.get(existingSession.to) : void 0;
1653
- parsedMetadata = await this.handshakeExtensions.validate(
1654
- rawMetadata,
1655
- previousParsedMetadata
1656
- );
1657
- if (parsedMetadata === false) {
1658
- this.rejectHandshakeRequest(
1659
- handshakingSession,
1660
- from,
1661
- "rejected by handshake handler",
1662
- "REJECTED_BY_CUSTOM_HANDLER",
1663
- {
1664
- ...handshakingSession.loggingMetadata,
1665
- connectedTo: from,
1666
- clientId: this.clientId
1667
- }
1668
- );
1669
- return false;
1670
- }
1671
- }
1672
- return parsedMetadata;
1673
- }
1674
1785
  };
1675
1786
 
1676
1787
  // transport/impls/ws/server.ts