@replit/river 0.207.2 → 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-4HE7UYRL.js → chunk-B7REV3ZV.js} +6 -5
  3. package/dist/{chunk-4HE7UYRL.js.map → chunk-B7REV3ZV.js.map} +1 -1
  4. package/dist/{chunk-24EWYOGK.js → chunk-BO7MFCO6.js} +1136 -143
  5. package/dist/chunk-BO7MFCO6.js.map +1 -0
  6. package/dist/{chunk-46IVOKJU.js → chunk-QGPYCXV4.js} +2 -2
  7. package/dist/{chunk-46IVOKJU.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-a18e31d5.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-43528f4b.d.ts → services-87887bc5.d.ts} +16 -12
  25. package/dist/testUtil/index.cjs +809 -657
  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 -204
  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 -128
  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 -270
  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-24EWYOGK.js.map +0 -1
  50. package/dist/chunk-A7RGOVRV.js +0 -438
  51. package/dist/chunk-A7RGOVRV.js.map +0 -1
  52. package/dist/chunk-AJGIY2UB.js +0 -56
  53. package/dist/chunk-AJGIY2UB.js.map +0 -1
  54. package/dist/chunk-XV4RQ62N.js +0 -377
  55. package/dist/chunk-XV4RQ62N.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.2";
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,25 +832,15 @@ var SessionConnected = class extends IdentifiedSession {
836
832
  conn;
837
833
  listeners;
838
834
  heartbeatHandle;
839
- heartbeatMisses = 0;
840
- isActivelyHeartbeating;
841
- lastConstructedMsgs = [];
842
- pushLastConstructedMsgs = (msg) => {
843
- const trackedMsg = {
844
- id: msg.id,
845
- seq: msg.seq,
846
- streamId: msg.streamId,
847
- stack: new Error().stack
848
- };
849
- this.lastConstructedMsgs.push(trackedMsg);
850
- if (this.lastConstructedMsgs.length > 10) {
851
- this.lastConstructedMsgs.shift();
852
- }
853
- };
835
+ heartbeatMissTimeout;
836
+ isActivelyHeartbeating = false;
854
837
  updateBookkeeping(ack, seq) {
855
838
  this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
856
839
  this.ack = seq + 1;
857
- this.heartbeatMisses = 0;
840
+ if (this.heartbeatMissTimeout) {
841
+ clearTimeout(this.heartbeatMissTimeout);
842
+ }
843
+ this.startMissingHeartbeatTimeout();
858
844
  }
859
845
  assertSendOrdering(constructedMsg) {
860
846
  if (constructedMsg.seq > this.seqSent + 1) {
@@ -862,22 +848,22 @@ var SessionConnected = class extends IdentifiedSession {
862
848
  this.log?.error(msg, {
863
849
  ...this.loggingMetadata,
864
850
  transportMessage: constructedMsg,
865
- tags: ["invariant-violation"],
866
- extras: {
867
- lastConstructedMsgs: this.lastConstructedMsgs
868
- }
851
+ tags: ["invariant-violation"]
869
852
  });
870
853
  throw new Error(msg);
871
854
  }
872
855
  }
873
856
  send(msg) {
874
857
  const constructedMsg = this.constructMsg(msg);
875
- this.pushLastConstructedMsgs(constructedMsg);
876
858
  this.assertSendOrdering(constructedMsg);
877
859
  this.sendBuffer.push(constructedMsg);
878
- 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
+ }
879
865
  this.seqSent = constructedMsg.seq;
880
- return constructedMsg.id;
866
+ return res;
881
867
  }
882
868
  constructor(props) {
883
869
  super(props);
@@ -886,6 +872,8 @@ var SessionConnected = class extends IdentifiedSession {
886
872
  this.conn.addDataListener(this.onMessageData);
887
873
  this.conn.addCloseListener(this.listeners.onConnectionClosed);
888
874
  this.conn.addErrorListener(this.listeners.onConnectionErrored);
875
+ }
876
+ sendBufferedMessages() {
889
877
  if (this.sendBuffer.length > 0) {
890
878
  this.log?.info(
891
879
  `sending ${this.sendBuffer.length} buffered messages, starting at seq ${this.nextSeq()}`,
@@ -893,30 +881,15 @@ var SessionConnected = class extends IdentifiedSession {
893
881
  );
894
882
  for (const msg of this.sendBuffer) {
895
883
  this.assertSendOrdering(msg);
896
- 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
+ }
897
889
  this.seqSent = msg.seq;
898
890
  }
899
891
  }
900
- this.isActivelyHeartbeating = false;
901
- this.heartbeatHandle = setInterval(() => {
902
- const misses = this.heartbeatMisses;
903
- const missDuration = misses * this.options.heartbeatIntervalMs;
904
- if (misses >= this.options.heartbeatsUntilDead) {
905
- this.log?.info(
906
- `closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
907
- this.loggingMetadata
908
- );
909
- this.telemetry.span.addEvent("closing connection due to inactivity");
910
- this.conn.close();
911
- clearInterval(this.heartbeatHandle);
912
- this.heartbeatHandle = void 0;
913
- return;
914
- }
915
- if (this.isActivelyHeartbeating) {
916
- this.sendHeartbeat();
917
- }
918
- this.heartbeatMisses++;
919
- }, this.options.heartbeatIntervalMs);
892
+ return { ok: true, value: void 0 };
920
893
  }
921
894
  get loggingMetadata() {
922
895
  return {
@@ -924,25 +897,46 @@ var SessionConnected = class extends IdentifiedSession {
924
897
  ...this.conn.loggingMetadata
925
898
  };
926
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
+ }
927
914
  startActiveHeartbeat() {
928
915
  this.isActivelyHeartbeating = true;
916
+ this.heartbeatHandle = setInterval(() => {
917
+ this.sendHeartbeat();
918
+ }, this.options.heartbeatIntervalMs);
929
919
  }
930
920
  sendHeartbeat() {
931
921
  this.log?.debug("sending heartbeat", this.loggingMetadata);
932
- this.send({
922
+ const heartbeat = {
933
923
  streamId: "heartbeat",
934
924
  controlFlags: 1 /* AckBit */,
935
925
  payload: {
936
926
  type: "ACK"
937
927
  }
938
- });
928
+ };
929
+ this.send(heartbeat);
939
930
  }
940
931
  onMessageData = (msg) => {
941
- const parsedMsg = this.parseMsg(msg);
942
- if (parsedMsg === null) {
943
- 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
+ );
944
937
  return;
945
938
  }
939
+ const parsedMsg = parsedMsgRes.value;
946
940
  if (parsedMsg.seq !== this.ack) {
947
941
  if (parsedMsg.seq < this.ack) {
948
942
  this.log?.debug(
@@ -981,9 +975,7 @@ var SessionConnected = class extends IdentifiedSession {
981
975
  transportMessage: parsedMsg
982
976
  });
983
977
  if (!this.isActivelyHeartbeating) {
984
- void Promise.resolve().then(() => {
985
- this.sendHeartbeat();
986
- });
978
+ this.sendHeartbeat();
987
979
  }
988
980
  };
989
981
  _handleStateExit() {
@@ -995,6 +987,10 @@ var SessionConnected = class extends IdentifiedSession {
995
987
  clearInterval(this.heartbeatHandle);
996
988
  this.heartbeatHandle = void 0;
997
989
  }
990
+ if (this.heartbeatMissTimeout) {
991
+ clearTimeout(this.heartbeatMissTimeout);
992
+ this.heartbeatMissTimeout = void 0;
993
+ }
998
994
  }
999
995
  _handleClose() {
1000
996
  super._handleClose();
@@ -1026,6 +1022,136 @@ var SessionBackingOff = class extends IdentifiedSessionWithGracePeriod {
1026
1022
  }
1027
1023
  };
1028
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
+
1029
1155
  // transport/sessionStateMachine/transitions.ts
1030
1156
  function inheritSharedSession(session) {
1031
1157
  return {
@@ -1040,7 +1166,8 @@ function inheritSharedSession(session) {
1040
1166
  options: session.options,
1041
1167
  log: session.log,
1042
1168
  tracer: session.tracer,
1043
- protocolVersion: session.protocolVersion
1169
+ protocolVersion: session.protocolVersion,
1170
+ codec: session.codec
1044
1171
  };
1045
1172
  }
1046
1173
  function inheritSharedSessionWithGrace(session) {
@@ -1069,7 +1196,8 @@ var SessionStateGraph = {
1069
1196
  options,
1070
1197
  protocolVersion,
1071
1198
  tracer,
1072
- log
1199
+ log,
1200
+ codec: new CodecMessageAdapter(options.codec)
1073
1201
  });
1074
1202
  session.log?.info(`session ${session.id} created in NoConnection state`, {
1075
1203
  ...session.loggingMetadata,
@@ -1084,7 +1212,8 @@ var SessionStateGraph = {
1084
1212
  from,
1085
1213
  options,
1086
1214
  tracer,
1087
- log
1215
+ log,
1216
+ codec: new CodecMessageAdapter(options.codec)
1088
1217
  });
1089
1218
  session.log?.info(`session created in WaitingForHandshake state`, {
1090
1219
  ...session.loggingMetadata,
@@ -1162,6 +1291,7 @@ var SessionStateGraph = {
1162
1291
  listeners,
1163
1292
  ...carriedState
1164
1293
  });
1294
+ session.startMissingHeartbeatTimeout();
1165
1295
  session.log?.info(
1166
1296
  `session ${session.id} transition from Handshaking to Connected`,
1167
1297
  {
@@ -1197,7 +1327,8 @@ var SessionStateGraph = {
1197
1327
  options,
1198
1328
  tracer: pendingSession.tracer,
1199
1329
  log: pendingSession.log,
1200
- protocolVersion
1330
+ protocolVersion,
1331
+ codec: new CodecMessageAdapter(options.codec)
1201
1332
  }
1202
1333
  );
1203
1334
  pendingSession._handleStateExit();
@@ -1207,6 +1338,7 @@ var SessionStateGraph = {
1207
1338
  listeners,
1208
1339
  ...carriedState
1209
1340
  });
1341
+ session.startMissingHeartbeatTimeout();
1210
1342
  conn.telemetry = createConnectionTelemetryInfo(
1211
1343
  session.tracer,
1212
1344
  conn,
@@ -1547,12 +1679,16 @@ var Transport = class {
1547
1679
  );
1548
1680
  }
1549
1681
  const sameSession = session.id === sessionId;
1550
- if (!sameSession) {
1682
+ if (!sameSession || session._isConsumed) {
1551
1683
  throw new Error(
1552
1684
  `session scope for ${sessionId} has ended (transition), can't send`
1553
1685
  );
1554
1686
  }
1555
- 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;
1556
1692
  };
1557
1693
  }
1558
1694
  };
@@ -1753,13 +1889,41 @@ var ClientTransport = class extends Transport {
1753
1889
  this.handleMsg(msg2);
1754
1890
  },
1755
1891
  onInvalidMessage: (reason) => {
1756
- this.deleteSession(connectedSession, { unhealthy: true });
1892
+ this.log?.error(`invalid message: ${reason}`, {
1893
+ ...connectedSession.loggingMetadata,
1894
+ transportMessage: msg
1895
+ });
1757
1896
  this.protocolError({
1758
1897
  type: ProtocolError.InvalidMessage,
1759
1898
  message: reason
1760
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 });
1761
1912
  }
1762
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
+ }
1763
1927
  this.updateSession(connectedSession);
1764
1928
  this.retryBudget.startRestoringBudget();
1765
1929
  }
@@ -1898,7 +2062,18 @@ var ClientTransport = class extends Transport {
1898
2062
  ...session.loggingMetadata,
1899
2063
  transportMessage: requestMsg
1900
2064
  });
1901
- 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
+ }
1902
2077
  }
1903
2078
  close() {
1904
2079
  this.retryBudget.close();
@@ -1906,93 +2081,6 @@ var ClientTransport = class extends Transport {
1906
2081
  }
1907
2082
  };
1908
2083
 
1909
- // transport/connection.ts
1910
- var Connection = class {
1911
- id;
1912
- telemetry;
1913
- constructor() {
1914
- this.id = `conn-${generateId()}`;
1915
- }
1916
- get loggingMetadata() {
1917
- const metadata = { connId: this.id };
1918
- if (this.telemetry?.span.isRecording()) {
1919
- const spanContext = this.telemetry.span.spanContext();
1920
- metadata.telemetry = {
1921
- traceId: spanContext.traceId,
1922
- spanId: spanContext.spanId
1923
- };
1924
- }
1925
- return metadata;
1926
- }
1927
- // can't use event emitter because we need this to work in both node + browser
1928
- _dataListeners = /* @__PURE__ */ new Set();
1929
- _closeListeners = /* @__PURE__ */ new Set();
1930
- _errorListeners = /* @__PURE__ */ new Set();
1931
- get dataListeners() {
1932
- return [...this._dataListeners];
1933
- }
1934
- get closeListeners() {
1935
- return [...this._closeListeners];
1936
- }
1937
- get errorListeners() {
1938
- return [...this._errorListeners];
1939
- }
1940
- onData(msg) {
1941
- for (const cb of this.dataListeners) {
1942
- cb(msg);
1943
- }
1944
- }
1945
- onError(err) {
1946
- for (const cb of this.errorListeners) {
1947
- cb(err);
1948
- }
1949
- }
1950
- onClose() {
1951
- for (const cb of this.closeListeners) {
1952
- cb();
1953
- }
1954
- this.telemetry?.span.end();
1955
- }
1956
- /**
1957
- * Handle adding a callback for when a message is received.
1958
- * @param msg The message that was received.
1959
- */
1960
- addDataListener(cb) {
1961
- this._dataListeners.add(cb);
1962
- }
1963
- removeDataListener(cb) {
1964
- this._dataListeners.delete(cb);
1965
- }
1966
- /**
1967
- * Handle adding a callback for when the connection is closed.
1968
- * This should also be called if an error happens and after notifying all the error listeners.
1969
- * @param cb The callback to call when the connection is closed.
1970
- */
1971
- addCloseListener(cb) {
1972
- this._closeListeners.add(cb);
1973
- }
1974
- removeCloseListener(cb) {
1975
- this._closeListeners.delete(cb);
1976
- }
1977
- /**
1978
- * Handle adding a callback for when an error is received.
1979
- * This should only be used for this.logging errors, all cleanup
1980
- * should be delegated to addCloseListener.
1981
- *
1982
- * The implementer should take care such that the implemented
1983
- * connection will call both the close and error callbacks
1984
- * on an error.
1985
- *
1986
- * @param cb The callback to call when an error is received.
1987
- */
1988
- addErrorListener(cb) {
1989
- this._errorListeners.add(cb);
1990
- }
1991
- removeErrorListener(cb) {
1992
- this._errorListeners.delete(cb);
1993
- }
1994
- };
1995
-
1996
2084
  // transport/impls/ws/connection.ts
1997
2085
  var WS_HEALTHY_CLOSE_CODE = 1e3;
1998
2086
  var WebSocketConnection = class extends Connection {
@@ -2028,11 +2116,12 @@ var WebSocketConnection = class extends Connection {
2028
2116
  };
2029
2117
  }
2030
2118
  send(payload) {
2031
- if (this.ws.readyState !== this.ws.OPEN) {
2119
+ try {
2120
+ this.ws.send(payload);
2121
+ return true;
2122
+ } catch {
2032
2123
  return false;
2033
2124
  }
2034
- this.ws.send(payload);
2035
- return true;
2036
2125
  }
2037
2126
  close() {
2038
2127
  this.ws.close(WS_HEALTHY_CLOSE_CODE);