@replit/river 0.207.1 → 0.207.3

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 (56) hide show
  1. package/dist/adapter-f2b6e211.d.ts +46 -0
  2. package/dist/{chunk-7LMZNSVC.js → chunk-B7REV3ZV.js} +6 -5
  3. package/dist/{chunk-7LMZNSVC.js.map → chunk-B7REV3ZV.js.map} +1 -1
  4. package/dist/{chunk-QMAVXV4Z.js → chunk-BO7MFCO6.js} +1136 -132
  5. package/dist/chunk-BO7MFCO6.js.map +1 -0
  6. package/dist/{chunk-BCCZA7SX.js → chunk-QGPYCXV4.js} +2 -2
  7. package/dist/{chunk-BCCZA7SX.js.map → chunk-QGPYCXV4.js.map} +1 -1
  8. package/dist/codec/index.cjs +157 -23
  9. package/dist/codec/index.cjs.map +1 -1
  10. package/dist/codec/index.d.cts +5 -1
  11. package/dist/codec/index.d.ts +5 -1
  12. package/dist/codec/index.js +6 -20
  13. package/dist/codec/index.js.map +1 -1
  14. package/dist/{connection-933c87b2.d.ts → connection-06d72f2e.d.ts} +3 -2
  15. package/dist/index-02554794.d.ts +37 -0
  16. package/dist/logging/index.d.cts +2 -1
  17. package/dist/logging/index.d.ts +2 -1
  18. package/dist/{message-ffacb98a.d.ts → message-01c3e85a.d.ts} +1 -35
  19. package/dist/router/index.cjs +1 -1
  20. package/dist/router/index.cjs.map +1 -1
  21. package/dist/router/index.d.cts +6 -5
  22. package/dist/router/index.d.ts +6 -5
  23. package/dist/router/index.js +1 -1
  24. package/dist/{services-4cd29829.d.ts → services-87887bc5.d.ts} +16 -11
  25. package/dist/testUtil/index.cjs +992 -829
  26. package/dist/testUtil/index.cjs.map +1 -1
  27. package/dist/testUtil/index.d.cts +4 -3
  28. package/dist/testUtil/index.d.ts +4 -3
  29. package/dist/testUtil/index.js +18 -13
  30. package/dist/testUtil/index.js.map +1 -1
  31. package/dist/transport/impls/ws/client.cjs +293 -193
  32. package/dist/transport/impls/ws/client.cjs.map +1 -1
  33. package/dist/transport/impls/ws/client.d.cts +5 -4
  34. package/dist/transport/impls/ws/client.d.ts +5 -4
  35. package/dist/transport/impls/ws/client.js +5 -7
  36. package/dist/transport/impls/ws/client.js.map +1 -1
  37. package/dist/transport/impls/ws/server.cjs +230 -117
  38. package/dist/transport/impls/ws/server.cjs.map +1 -1
  39. package/dist/transport/impls/ws/server.d.cts +5 -4
  40. package/dist/transport/impls/ws/server.d.ts +5 -4
  41. package/dist/transport/impls/ws/server.js +5 -7
  42. package/dist/transport/impls/ws/server.js.map +1 -1
  43. package/dist/transport/index.cjs +408 -259
  44. package/dist/transport/index.cjs.map +1 -1
  45. package/dist/transport/index.d.cts +7 -6
  46. package/dist/transport/index.d.ts +7 -6
  47. package/dist/transport/index.js +4 -9
  48. package/package.json +1 -1
  49. package/dist/chunk-AJGIY2UB.js +0 -56
  50. package/dist/chunk-AJGIY2UB.js.map +0 -1
  51. package/dist/chunk-CRD3HDVN.js +0 -438
  52. package/dist/chunk-CRD3HDVN.js.map +0 -1
  53. package/dist/chunk-I27WBSMZ.js +0 -377
  54. package/dist/chunk-I27WBSMZ.js.map +0 -1
  55. package/dist/chunk-QMAVXV4Z.js.map +0 -1
  56. package/dist/types-3e5768ec.d.ts +0 -20
@@ -186,23 +186,20 @@ var NaiveJsonCodec = {
186
186
  );
187
187
  },
188
188
  fromBuffer: (buff) => {
189
- try {
190
- const parsed = JSON.parse(
191
- decoder.decode(buff),
192
- function reviver(_key, val) {
193
- if (val?.$t) {
194
- return base64ToUint8Array(val.$t);
195
- } else {
196
- return val;
197
- }
189
+ const parsed = JSON.parse(
190
+ decoder.decode(buff),
191
+ function reviver(_key, val) {
192
+ if (val?.$t) {
193
+ return base64ToUint8Array(val.$t);
194
+ } else {
195
+ return val;
198
196
  }
199
- );
200
- if (typeof parsed === "object")
201
- return parsed;
202
- return null;
203
- } catch {
204
- return null;
197
+ }
198
+ );
199
+ if (typeof parsed !== "object" || parsed === null) {
200
+ throw new Error("unpacked msg is not an object");
205
201
  }
202
+ return parsed;
206
203
  }
207
204
  };
208
205
 
@@ -366,7 +363,8 @@ var ProtocolError = {
366
363
  RetriesExceeded: "conn_retry_exceeded",
367
364
  HandshakeFailed: "handshake_failed",
368
365
  MessageOrderingViolated: "message_ordering_violated",
369
- InvalidMessage: "invalid_message"
366
+ InvalidMessage: "invalid_message",
367
+ MessageSendFailure: "message_send_failure"
370
368
  };
371
369
  var EventDispatcher = class {
372
370
  eventListeners = {};
@@ -400,7 +398,6 @@ var EventDispatcher = class {
400
398
  };
401
399
 
402
400
  // transport/sessionStateMachine/common.ts
403
- var import_value = require("@sinclair/typebox/value");
404
401
  var ERR_CONSUMED = `session state has been consumed and is no longer valid`;
405
402
  var StateMachineState = class {
406
403
  /*
@@ -460,34 +457,16 @@ var StateMachineState = class {
460
457
  var CommonSession = class extends StateMachineState {
461
458
  from;
462
459
  options;
460
+ codec;
463
461
  tracer;
464
462
  log;
465
- constructor({ from, options, log, tracer }) {
463
+ constructor({ from, options, log, tracer, codec }) {
466
464
  super();
467
465
  this.from = from;
468
466
  this.options = options;
469
467
  this.log = log;
470
468
  this.tracer = tracer;
471
- }
472
- parseMsg(msg) {
473
- const parsedMsg = this.options.codec.fromBuffer(msg);
474
- if (parsedMsg === null) {
475
- this.log?.error(
476
- `received malformed msg: ${Buffer.from(msg).toString("base64")}`,
477
- this.loggingMetadata
478
- );
479
- return null;
480
- }
481
- if (!import_value.Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
482
- this.log?.error(`received invalid msg: ${JSON.stringify(parsedMsg)}`, {
483
- ...this.loggingMetadata,
484
- validationErrors: [
485
- ...import_value.Value.Errors(OpaqueTransportMessageSchema, parsedMsg)
486
- ]
487
- });
488
- return null;
489
- }
490
- return parsedMsg;
469
+ this.codec = codec;
491
470
  }
492
471
  };
493
472
  var IdentifiedSession = class extends CommonSession {
@@ -547,9 +526,6 @@ var IdentifiedSession = class extends CommonSession {
547
526
  return metadata;
548
527
  }
549
528
  constructMsg(partialMsg) {
550
- if (this._isConsumed) {
551
- throw new Error(ERR_CONSUMED);
552
- }
553
529
  const msg = {
554
530
  ...partialMsg,
555
531
  id: generateId(),
@@ -567,7 +543,10 @@ var IdentifiedSession = class extends CommonSession {
567
543
  send(msg) {
568
544
  const constructedMsg = this.constructMsg(msg);
569
545
  this.sendBuffer.push(constructedMsg);
570
- return constructedMsg.id;
546
+ return {
547
+ ok: true,
548
+ value: constructedMsg.id
549
+ };
571
550
  }
572
551
  _handleStateExit() {
573
552
  }
@@ -599,6 +578,23 @@ var IdentifiedSessionWithGracePeriod = class extends IdentifiedSession {
599
578
  super._handleClose();
600
579
  }
601
580
  };
581
+ function sendMessage(conn, codec, msg) {
582
+ const buff = codec.toBuffer(msg);
583
+ if (!buff.ok) {
584
+ return buff;
585
+ }
586
+ const sent = conn.send(buff.value);
587
+ if (!sent) {
588
+ return {
589
+ ok: false,
590
+ reason: "failed to send message"
591
+ };
592
+ }
593
+ return {
594
+ ok: true,
595
+ value: msg.id
596
+ };
597
+ }
602
598
 
603
599
  // transport/sessionStateMachine/SessionConnecting.ts
604
600
  var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
@@ -651,8 +647,8 @@ var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
651
647
  }
652
648
  }
653
649
  _handleClose() {
654
- this.bestEffortClose();
655
650
  super._handleClose();
651
+ this.bestEffortClose();
656
652
  }
657
653
  };
658
654
 
@@ -679,7 +675,7 @@ function coerceErrorString(err) {
679
675
  }
680
676
 
681
677
  // package.json
682
- var version = "0.207.1";
678
+ var version = "0.207.3";
683
679
 
684
680
  // tracing/index.ts
685
681
  function getPropagationContext(ctx) {
@@ -751,18 +747,18 @@ var SessionWaitingForHandshake = class extends CommonSession {
751
747
  };
752
748
  }
753
749
  onHandshakeData = (msg) => {
754
- const parsedMsg = this.parseMsg(msg);
755
- if (parsedMsg === null) {
750
+ const parsedMsgRes = this.codec.fromBuffer(msg);
751
+ if (!parsedMsgRes.ok) {
756
752
  this.listeners.onInvalidHandshake(
757
- "could not parse message",
753
+ `could not parse handshake message: ${parsedMsgRes.reason}`,
758
754
  "MALFORMED_HANDSHAKE"
759
755
  );
760
756
  return;
761
757
  }
762
- this.listeners.onHandshake(parsedMsg);
758
+ this.listeners.onHandshake(parsedMsgRes.value);
763
759
  };
764
760
  sendHandshake(msg) {
765
- return this.conn.send(this.options.codec.toBuffer(msg));
761
+ return sendMessage(this.conn, this.codec, msg);
766
762
  }
767
763
  _handleStateExit() {
768
764
  this.conn.removeDataListener(this.onHandshakeData);
@@ -800,18 +796,18 @@ var SessionHandshaking = class extends IdentifiedSessionWithGracePeriod {
800
796
  };
801
797
  }
802
798
  onHandshakeData = (msg) => {
803
- const parsedMsg = this.parseMsg(msg);
804
- if (parsedMsg === null) {
799
+ const parsedMsgRes = this.codec.fromBuffer(msg);
800
+ if (!parsedMsgRes.ok) {
805
801
  this.listeners.onInvalidHandshake(
806
- "could not parse message",
802
+ `could not parse handshake message: ${parsedMsgRes.reason}`,
807
803
  "MALFORMED_HANDSHAKE"
808
804
  );
809
805
  return;
810
806
  }
811
- this.listeners.onHandshake(parsedMsg);
807
+ this.listeners.onHandshake(parsedMsgRes.value);
812
808
  };
813
809
  sendHandshake(msg) {
814
- return this.conn.send(this.options.codec.toBuffer(msg));
810
+ return sendMessage(this.conn, this.codec, msg);
815
811
  }
816
812
  _handleStateExit() {
817
813
  super._handleStateExit();
@@ -836,12 +832,15 @@ var SessionConnected = class extends IdentifiedSession {
836
832
  conn;
837
833
  listeners;
838
834
  heartbeatHandle;
839
- heartbeatMisses = 0;
840
- isActivelyHeartbeating;
835
+ heartbeatMissTimeout;
836
+ isActivelyHeartbeating = false;
841
837
  updateBookkeeping(ack, seq) {
842
838
  this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
843
839
  this.ack = seq + 1;
844
- this.heartbeatMisses = 0;
840
+ if (this.heartbeatMissTimeout) {
841
+ clearTimeout(this.heartbeatMissTimeout);
842
+ }
843
+ this.startMissingHeartbeatTimeout();
845
844
  }
846
845
  assertSendOrdering(constructedMsg) {
847
846
  if (constructedMsg.seq > this.seqSent + 1) {
@@ -858,9 +857,13 @@ var SessionConnected = class extends IdentifiedSession {
858
857
  const constructedMsg = this.constructMsg(msg);
859
858
  this.assertSendOrdering(constructedMsg);
860
859
  this.sendBuffer.push(constructedMsg);
861
- this.conn.send(this.options.codec.toBuffer(constructedMsg));
860
+ const res = sendMessage(this.conn, this.codec, constructedMsg);
861
+ if (!res.ok) {
862
+ this.listeners.onMessageSendFailure(constructedMsg, res.reason);
863
+ return res;
864
+ }
862
865
  this.seqSent = constructedMsg.seq;
863
- return constructedMsg.id;
866
+ return res;
864
867
  }
865
868
  constructor(props) {
866
869
  super(props);
@@ -869,6 +872,8 @@ var SessionConnected = class extends IdentifiedSession {
869
872
  this.conn.addDataListener(this.onMessageData);
870
873
  this.conn.addCloseListener(this.listeners.onConnectionClosed);
871
874
  this.conn.addErrorListener(this.listeners.onConnectionErrored);
875
+ }
876
+ sendBufferedMessages() {
872
877
  if (this.sendBuffer.length > 0) {
873
878
  this.log?.info(
874
879
  `sending ${this.sendBuffer.length} buffered messages, starting at seq ${this.nextSeq()}`,
@@ -876,30 +881,15 @@ var SessionConnected = class extends IdentifiedSession {
876
881
  );
877
882
  for (const msg of this.sendBuffer) {
878
883
  this.assertSendOrdering(msg);
879
- this.conn.send(this.options.codec.toBuffer(msg));
884
+ const res = sendMessage(this.conn, this.codec, msg);
885
+ if (!res.ok) {
886
+ this.listeners.onMessageSendFailure(msg, res.reason);
887
+ return res;
888
+ }
880
889
  this.seqSent = msg.seq;
881
890
  }
882
891
  }
883
- this.isActivelyHeartbeating = false;
884
- this.heartbeatHandle = setInterval(() => {
885
- const misses = this.heartbeatMisses;
886
- const missDuration = misses * this.options.heartbeatIntervalMs;
887
- if (misses >= this.options.heartbeatsUntilDead) {
888
- this.log?.info(
889
- `closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
890
- this.loggingMetadata
891
- );
892
- this.telemetry.span.addEvent("closing connection due to inactivity");
893
- this.conn.close();
894
- clearInterval(this.heartbeatHandle);
895
- this.heartbeatHandle = void 0;
896
- return;
897
- }
898
- if (this.isActivelyHeartbeating) {
899
- this.sendHeartbeat();
900
- }
901
- this.heartbeatMisses++;
902
- }, this.options.heartbeatIntervalMs);
892
+ return { ok: true, value: void 0 };
903
893
  }
904
894
  get loggingMetadata() {
905
895
  return {
@@ -907,31 +897,46 @@ var SessionConnected = class extends IdentifiedSession {
907
897
  ...this.conn.loggingMetadata
908
898
  };
909
899
  }
900
+ startMissingHeartbeatTimeout() {
901
+ const maxMisses = this.options.heartbeatsUntilDead;
902
+ const missDuration = maxMisses * this.options.heartbeatIntervalMs;
903
+ this.heartbeatMissTimeout = setTimeout(() => {
904
+ this.log?.info(
905
+ `closing connection to ${this.to} due to inactivity (missed ${maxMisses} heartbeats which is ${missDuration}ms)`,
906
+ this.loggingMetadata
907
+ );
908
+ this.telemetry.span.addEvent(
909
+ "closing connection due to missing heartbeat"
910
+ );
911
+ this.conn.close();
912
+ }, missDuration);
913
+ }
910
914
  startActiveHeartbeat() {
911
915
  this.isActivelyHeartbeating = true;
916
+ this.heartbeatHandle = setInterval(() => {
917
+ this.sendHeartbeat();
918
+ }, this.options.heartbeatIntervalMs);
912
919
  }
913
920
  sendHeartbeat() {
914
921
  this.log?.debug("sending heartbeat", this.loggingMetadata);
915
- this.send({
922
+ const heartbeat = {
916
923
  streamId: "heartbeat",
917
924
  controlFlags: 1 /* AckBit */,
918
925
  payload: {
919
926
  type: "ACK"
920
927
  }
921
- });
922
- }
923
- closeConnection() {
924
- this.conn.removeDataListener(this.onMessageData);
925
- this.conn.removeCloseListener(this.listeners.onConnectionClosed);
926
- this.conn.removeErrorListener(this.listeners.onConnectionErrored);
927
- this.conn.close();
928
+ };
929
+ this.send(heartbeat);
928
930
  }
929
931
  onMessageData = (msg) => {
930
- const parsedMsg = this.parseMsg(msg);
931
- if (parsedMsg === null) {
932
- this.listeners.onInvalidMessage("could not parse message");
932
+ const parsedMsgRes = this.codec.fromBuffer(msg);
933
+ if (!parsedMsgRes.ok) {
934
+ this.listeners.onInvalidMessage(
935
+ `could not parse message: ${parsedMsgRes.reason}`
936
+ );
933
937
  return;
934
938
  }
939
+ const parsedMsg = parsedMsgRes.value;
935
940
  if (parsedMsg.seq !== this.ack) {
936
941
  if (parsedMsg.seq < this.ack) {
937
942
  this.log?.debug(
@@ -952,7 +957,7 @@ var SessionConnected = class extends IdentifiedSession {
952
957
  code: import_api3.SpanStatusCode.ERROR,
953
958
  message: reason
954
959
  });
955
- this.closeConnection();
960
+ this.conn.close();
956
961
  }
957
962
  return;
958
963
  }
@@ -970,9 +975,7 @@ var SessionConnected = class extends IdentifiedSession {
970
975
  transportMessage: parsedMsg
971
976
  });
972
977
  if (!this.isActivelyHeartbeating) {
973
- void Promise.resolve().then(() => {
974
- this.sendHeartbeat();
975
- });
978
+ this.sendHeartbeat();
976
979
  }
977
980
  };
978
981
  _handleStateExit() {
@@ -984,6 +987,10 @@ var SessionConnected = class extends IdentifiedSession {
984
987
  clearInterval(this.heartbeatHandle);
985
988
  this.heartbeatHandle = void 0;
986
989
  }
990
+ if (this.heartbeatMissTimeout) {
991
+ clearTimeout(this.heartbeatMissTimeout);
992
+ this.heartbeatMissTimeout = void 0;
993
+ }
987
994
  }
988
995
  _handleClose() {
989
996
  super._handleClose();
@@ -1015,6 +1022,136 @@ var SessionBackingOff = class extends IdentifiedSessionWithGracePeriod {
1015
1022
  }
1016
1023
  };
1017
1024
 
1025
+ // codec/adapter.ts
1026
+ var import_value = require("@sinclair/typebox/value");
1027
+
1028
+ // transport/connection.ts
1029
+ var Connection = class {
1030
+ id;
1031
+ telemetry;
1032
+ constructor() {
1033
+ this.id = `conn-${generateId()}`;
1034
+ }
1035
+ get loggingMetadata() {
1036
+ const metadata = { connId: this.id };
1037
+ if (this.telemetry?.span.isRecording()) {
1038
+ const spanContext = this.telemetry.span.spanContext();
1039
+ metadata.telemetry = {
1040
+ traceId: spanContext.traceId,
1041
+ spanId: spanContext.spanId
1042
+ };
1043
+ }
1044
+ return metadata;
1045
+ }
1046
+ // can't use event emitter because we need this to work in both node + browser
1047
+ _dataListeners = /* @__PURE__ */ new Set();
1048
+ _closeListeners = /* @__PURE__ */ new Set();
1049
+ _errorListeners = /* @__PURE__ */ new Set();
1050
+ get dataListeners() {
1051
+ return [...this._dataListeners];
1052
+ }
1053
+ get closeListeners() {
1054
+ return [...this._closeListeners];
1055
+ }
1056
+ get errorListeners() {
1057
+ return [...this._errorListeners];
1058
+ }
1059
+ onData(msg) {
1060
+ for (const cb of this.dataListeners) {
1061
+ cb(msg);
1062
+ }
1063
+ }
1064
+ onError(err) {
1065
+ for (const cb of this.errorListeners) {
1066
+ cb(err);
1067
+ }
1068
+ }
1069
+ onClose() {
1070
+ for (const cb of this.closeListeners) {
1071
+ cb();
1072
+ }
1073
+ this.telemetry?.span.end();
1074
+ }
1075
+ /**
1076
+ * Handle adding a callback for when a message is received.
1077
+ * @param msg The message that was received.
1078
+ */
1079
+ addDataListener(cb) {
1080
+ this._dataListeners.add(cb);
1081
+ }
1082
+ removeDataListener(cb) {
1083
+ this._dataListeners.delete(cb);
1084
+ }
1085
+ /**
1086
+ * Handle adding a callback for when the connection is closed.
1087
+ * This should also be called if an error happens and after notifying all the error listeners.
1088
+ * @param cb The callback to call when the connection is closed.
1089
+ */
1090
+ addCloseListener(cb) {
1091
+ this._closeListeners.add(cb);
1092
+ }
1093
+ removeCloseListener(cb) {
1094
+ this._closeListeners.delete(cb);
1095
+ }
1096
+ /**
1097
+ * Handle adding a callback for when an error is received.
1098
+ * This should only be used for this.logging errors, all cleanup
1099
+ * should be delegated to addCloseListener.
1100
+ *
1101
+ * The implementer should take care such that the implemented
1102
+ * connection will call both the close and error callbacks
1103
+ * on an error.
1104
+ *
1105
+ * @param cb The callback to call when an error is received.
1106
+ */
1107
+ addErrorListener(cb) {
1108
+ this._errorListeners.add(cb);
1109
+ }
1110
+ removeErrorListener(cb) {
1111
+ this._errorListeners.delete(cb);
1112
+ }
1113
+ };
1114
+
1115
+ // codec/adapter.ts
1116
+ var CodecMessageAdapter = class {
1117
+ constructor(codec) {
1118
+ this.codec = codec;
1119
+ }
1120
+ toBuffer(msg) {
1121
+ try {
1122
+ return {
1123
+ ok: true,
1124
+ value: this.codec.toBuffer(msg)
1125
+ };
1126
+ } catch (e) {
1127
+ return {
1128
+ ok: false,
1129
+ reason: coerceErrorString(e)
1130
+ };
1131
+ }
1132
+ }
1133
+ fromBuffer(buf) {
1134
+ try {
1135
+ const parsedMsg = this.codec.fromBuffer(buf);
1136
+ if (!import_value.Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
1137
+ return {
1138
+ ok: false,
1139
+ reason: "transport message schema mismatch"
1140
+ };
1141
+ }
1142
+ return {
1143
+ ok: true,
1144
+ value: parsedMsg
1145
+ };
1146
+ } catch (e) {
1147
+ return {
1148
+ ok: false,
1149
+ reason: coerceErrorString(e)
1150
+ };
1151
+ }
1152
+ }
1153
+ };
1154
+
1018
1155
  // transport/sessionStateMachine/transitions.ts
1019
1156
  function inheritSharedSession(session) {
1020
1157
  return {
@@ -1029,7 +1166,8 @@ function inheritSharedSession(session) {
1029
1166
  options: session.options,
1030
1167
  log: session.log,
1031
1168
  tracer: session.tracer,
1032
- protocolVersion: session.protocolVersion
1169
+ protocolVersion: session.protocolVersion,
1170
+ codec: session.codec
1033
1171
  };
1034
1172
  }
1035
1173
  function inheritSharedSessionWithGrace(session) {
@@ -1058,7 +1196,8 @@ var SessionStateGraph = {
1058
1196
  options,
1059
1197
  protocolVersion,
1060
1198
  tracer,
1061
- log
1199
+ log,
1200
+ codec: new CodecMessageAdapter(options.codec)
1062
1201
  });
1063
1202
  session.log?.info(`session ${session.id} created in NoConnection state`, {
1064
1203
  ...session.loggingMetadata,
@@ -1073,7 +1212,8 @@ var SessionStateGraph = {
1073
1212
  from,
1074
1213
  options,
1075
1214
  tracer,
1076
- log
1215
+ log,
1216
+ codec: new CodecMessageAdapter(options.codec)
1077
1217
  });
1078
1218
  session.log?.info(`session created in WaitingForHandshake state`, {
1079
1219
  ...session.loggingMetadata,
@@ -1151,6 +1291,7 @@ var SessionStateGraph = {
1151
1291
  listeners,
1152
1292
  ...carriedState
1153
1293
  });
1294
+ session.startMissingHeartbeatTimeout();
1154
1295
  session.log?.info(
1155
1296
  `session ${session.id} transition from Handshaking to Connected`,
1156
1297
  {
@@ -1186,7 +1327,8 @@ var SessionStateGraph = {
1186
1327
  options,
1187
1328
  tracer: pendingSession.tracer,
1188
1329
  log: pendingSession.log,
1189
- protocolVersion
1330
+ protocolVersion,
1331
+ codec: new CodecMessageAdapter(options.codec)
1190
1332
  }
1191
1333
  );
1192
1334
  pendingSession._handleStateExit();
@@ -1196,6 +1338,7 @@ var SessionStateGraph = {
1196
1338
  listeners,
1197
1339
  ...carriedState
1198
1340
  });
1341
+ session.startMissingHeartbeatTimeout();
1199
1342
  conn.telemetry = createConnectionTelemetryInfo(
1200
1343
  session.tracer,
1201
1344
  conn,
@@ -1536,12 +1679,16 @@ var Transport = class {
1536
1679
  );
1537
1680
  }
1538
1681
  const sameSession = session.id === sessionId;
1539
- if (!sameSession) {
1682
+ if (!sameSession || session._isConsumed) {
1540
1683
  throw new Error(
1541
1684
  `session scope for ${sessionId} has ended (transition), can't send`
1542
1685
  );
1543
1686
  }
1544
- return session.send(msg);
1687
+ const res = session.send(msg);
1688
+ if (!res.ok) {
1689
+ throw new Error(res.reason);
1690
+ }
1691
+ return res.value;
1545
1692
  };
1546
1693
  }
1547
1694
  };
@@ -1742,13 +1889,41 @@ var ClientTransport = class extends Transport {
1742
1889
  this.handleMsg(msg2);
1743
1890
  },
1744
1891
  onInvalidMessage: (reason) => {
1745
- this.deleteSession(connectedSession, { unhealthy: true });
1892
+ this.log?.error(`invalid message: ${reason}`, {
1893
+ ...connectedSession.loggingMetadata,
1894
+ transportMessage: msg
1895
+ });
1746
1896
  this.protocolError({
1747
1897
  type: ProtocolError.InvalidMessage,
1748
1898
  message: reason
1749
1899
  });
1900
+ this.deleteSession(connectedSession, { unhealthy: true });
1901
+ },
1902
+ onMessageSendFailure: (msg2, reason) => {
1903
+ this.log?.error(`failed to send message: ${reason}`, {
1904
+ ...connectedSession.loggingMetadata,
1905
+ transportMessage: msg2
1906
+ });
1907
+ this.protocolError({
1908
+ type: ProtocolError.MessageSendFailure,
1909
+ message: reason
1910
+ });
1911
+ this.deleteSession(connectedSession, { unhealthy: true });
1750
1912
  }
1751
1913
  });
1914
+ const res = connectedSession.sendBufferedMessages();
1915
+ if (!res.ok) {
1916
+ this.log?.error(`failed to send buffered messages: ${res.reason}`, {
1917
+ ...connectedSession.loggingMetadata,
1918
+ transportMessage: msg
1919
+ });
1920
+ this.protocolError({
1921
+ type: ProtocolError.MessageSendFailure,
1922
+ message: res.reason
1923
+ });
1924
+ this.deleteSession(connectedSession, { unhealthy: true });
1925
+ return;
1926
+ }
1752
1927
  this.updateSession(connectedSession);
1753
1928
  this.retryBudget.startRestoringBudget();
1754
1929
  }
@@ -1887,7 +2062,18 @@ var ClientTransport = class extends Transport {
1887
2062
  ...session.loggingMetadata,
1888
2063
  transportMessage: requestMsg
1889
2064
  });
1890
- session.sendHandshake(requestMsg);
2065
+ const res = session.sendHandshake(requestMsg);
2066
+ if (!res.ok) {
2067
+ this.log?.error(`failed to send handshake request: ${res.reason}`, {
2068
+ ...session.loggingMetadata,
2069
+ transportMessage: requestMsg
2070
+ });
2071
+ this.protocolError({
2072
+ type: ProtocolError.MessageSendFailure,
2073
+ message: res.reason
2074
+ });
2075
+ this.deleteSession(session, { unhealthy: true });
2076
+ }
1891
2077
  }
1892
2078
  close() {
1893
2079
  this.retryBudget.close();
@@ -1895,93 +2081,6 @@ var ClientTransport = class extends Transport {
1895
2081
  }
1896
2082
  };
1897
2083
 
1898
- // transport/connection.ts
1899
- var Connection = class {
1900
- id;
1901
- telemetry;
1902
- constructor() {
1903
- this.id = `conn-${generateId()}`;
1904
- }
1905
- get loggingMetadata() {
1906
- const metadata = { connId: this.id };
1907
- if (this.telemetry?.span.isRecording()) {
1908
- const spanContext = this.telemetry.span.spanContext();
1909
- metadata.telemetry = {
1910
- traceId: spanContext.traceId,
1911
- spanId: spanContext.spanId
1912
- };
1913
- }
1914
- return metadata;
1915
- }
1916
- // can't use event emitter because we need this to work in both node + browser
1917
- _dataListeners = /* @__PURE__ */ new Set();
1918
- _closeListeners = /* @__PURE__ */ new Set();
1919
- _errorListeners = /* @__PURE__ */ new Set();
1920
- get dataListeners() {
1921
- return [...this._dataListeners];
1922
- }
1923
- get closeListeners() {
1924
- return [...this._closeListeners];
1925
- }
1926
- get errorListeners() {
1927
- return [...this._errorListeners];
1928
- }
1929
- onData(msg) {
1930
- for (const cb of this.dataListeners) {
1931
- cb(msg);
1932
- }
1933
- }
1934
- onError(err) {
1935
- for (const cb of this.errorListeners) {
1936
- cb(err);
1937
- }
1938
- }
1939
- onClose() {
1940
- for (const cb of this.closeListeners) {
1941
- cb();
1942
- }
1943
- this.telemetry?.span.end();
1944
- }
1945
- /**
1946
- * Handle adding a callback for when a message is received.
1947
- * @param msg The message that was received.
1948
- */
1949
- addDataListener(cb) {
1950
- this._dataListeners.add(cb);
1951
- }
1952
- removeDataListener(cb) {
1953
- this._dataListeners.delete(cb);
1954
- }
1955
- /**
1956
- * Handle adding a callback for when the connection is closed.
1957
- * This should also be called if an error happens and after notifying all the error listeners.
1958
- * @param cb The callback to call when the connection is closed.
1959
- */
1960
- addCloseListener(cb) {
1961
- this._closeListeners.add(cb);
1962
- }
1963
- removeCloseListener(cb) {
1964
- this._closeListeners.delete(cb);
1965
- }
1966
- /**
1967
- * Handle adding a callback for when an error is received.
1968
- * This should only be used for this.logging errors, all cleanup
1969
- * should be delegated to addCloseListener.
1970
- *
1971
- * The implementer should take care such that the implemented
1972
- * connection will call both the close and error callbacks
1973
- * on an error.
1974
- *
1975
- * @param cb The callback to call when an error is received.
1976
- */
1977
- addErrorListener(cb) {
1978
- this._errorListeners.add(cb);
1979
- }
1980
- removeErrorListener(cb) {
1981
- this._errorListeners.delete(cb);
1982
- }
1983
- };
1984
-
1985
2084
  // transport/impls/ws/connection.ts
1986
2085
  var WS_HEALTHY_CLOSE_CODE = 1e3;
1987
2086
  var WebSocketConnection = class extends Connection {
@@ -2017,11 +2116,12 @@ var WebSocketConnection = class extends Connection {
2017
2116
  };
2018
2117
  }
2019
2118
  send(payload) {
2020
- if (this.ws.readyState !== this.ws.OPEN) {
2119
+ try {
2120
+ this.ws.send(payload);
2121
+ return true;
2122
+ } catch {
2021
2123
  return false;
2022
2124
  }
2023
- this.ws.send(payload);
2024
- return true;
2025
2125
  }
2026
2126
  close() {
2027
2127
  this.ws.close(WS_HEALTHY_CLOSE_CODE);