@replit/river 0.16.2 → 0.17.1

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 (38) hide show
  1. package/dist/{chunk-HZWCU4ZI.js → chunk-4A7FDC2C.js} +1 -1
  2. package/dist/{chunk-SKH3JYHN.js → chunk-7IQO434V.js} +1 -1
  3. package/dist/{chunk-CJGD7CNG.js → chunk-F6KWMEPR.js} +87 -88
  4. package/dist/{chunk-HKVP6XEL.js → chunk-MSAS5CVJ.js} +1 -1
  5. package/dist/{chunk-GFRAOY75.js → chunk-VH3NGOXQ.js} +8 -17
  6. package/dist/{connection-2db95d74.d.ts → connection-0767dc6b.d.ts} +1 -1
  7. package/dist/{connection-c97da681.d.ts → connection-f31edbcd.d.ts} +1 -1
  8. package/dist/{index-c9e9977f.d.ts → index-8df0bdfb.d.ts} +14 -21
  9. package/dist/{procedures-d295c1a5.d.ts → procedures-b5ddb54d.d.ts} +1 -1
  10. package/dist/router/index.cjs +2 -2
  11. package/dist/router/index.d.cts +3 -3
  12. package/dist/router/index.d.ts +3 -3
  13. package/dist/router/index.js +2 -2
  14. package/dist/transport/impls/uds/client.cjs +66 -60
  15. package/dist/transport/impls/uds/client.d.cts +2 -2
  16. package/dist/transport/impls/uds/client.d.ts +2 -2
  17. package/dist/transport/impls/uds/client.js +3 -3
  18. package/dist/transport/impls/uds/server.cjs +78 -91
  19. package/dist/transport/impls/uds/server.d.cts +2 -2
  20. package/dist/transport/impls/uds/server.d.ts +2 -2
  21. package/dist/transport/impls/uds/server.js +3 -3
  22. package/dist/transport/impls/ws/client.cjs +66 -60
  23. package/dist/transport/impls/ws/client.d.cts +2 -2
  24. package/dist/transport/impls/ws/client.d.ts +2 -2
  25. package/dist/transport/impls/ws/client.js +3 -3
  26. package/dist/transport/impls/ws/server.cjs +78 -91
  27. package/dist/transport/impls/ws/server.d.cts +2 -2
  28. package/dist/transport/impls/ws/server.d.ts +2 -2
  29. package/dist/transport/impls/ws/server.js +3 -3
  30. package/dist/transport/index.cjs +93 -106
  31. package/dist/transport/index.d.cts +1 -1
  32. package/dist/transport/index.d.ts +1 -1
  33. package/dist/transport/index.js +2 -2
  34. package/dist/util/testHelpers.cjs +46 -19
  35. package/dist/util/testHelpers.d.cts +4 -9
  36. package/dist/util/testHelpers.d.ts +4 -9
  37. package/dist/util/testHelpers.js +8 -14
  38. package/package.json +1 -1
@@ -55,18 +55,18 @@ var ControlMessageAckSchema = import_typebox.Type.Object({
55
55
  var ControlMessageCloseSchema = import_typebox.Type.Object({
56
56
  type: import_typebox.Type.Literal("CLOSE")
57
57
  });
58
- var PROTOCOL_VERSION = "v1";
58
+ var PROTOCOL_VERSION = "v1.1";
59
59
  var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
60
60
  type: import_typebox.Type.Literal("HANDSHAKE_REQ"),
61
61
  protocolVersion: import_typebox.Type.String(),
62
- instanceId: import_typebox.Type.String()
62
+ sessionId: import_typebox.Type.String()
63
63
  });
64
64
  var ControlMessageHandshakeResponseSchema = import_typebox.Type.Object({
65
65
  type: import_typebox.Type.Literal("HANDSHAKE_RESP"),
66
66
  status: import_typebox.Type.Union([
67
67
  import_typebox.Type.Object({
68
68
  ok: import_typebox.Type.Literal(true),
69
- instanceId: import_typebox.Type.String()
69
+ sessionId: import_typebox.Type.String()
70
70
  }),
71
71
  import_typebox.Type.Object({
72
72
  ok: import_typebox.Type.Literal(false),
@@ -83,7 +83,7 @@ var ControlMessagePayloadSchema = import_typebox.Type.Union([
83
83
  var OpaqueTransportMessageSchema = TransportMessageSchema(
84
84
  import_typebox.Type.Unknown()
85
85
  );
86
- function handshakeRequestMessage(from, to, instanceId) {
86
+ function handshakeRequestMessage(from, to, sessionId) {
87
87
  return {
88
88
  id: (0, import_nanoid.nanoid)(),
89
89
  from,
@@ -95,11 +95,11 @@ function handshakeRequestMessage(from, to, instanceId) {
95
95
  payload: {
96
96
  type: "HANDSHAKE_REQ",
97
97
  protocolVersion: PROTOCOL_VERSION,
98
- instanceId
98
+ sessionId
99
99
  }
100
100
  };
101
101
  }
102
- function handshakeResponseMessage(from, instanceId, to, ok, reason) {
102
+ function handshakeResponseMessage(from, to, status) {
103
103
  return {
104
104
  id: (0, import_nanoid.nanoid)(),
105
105
  from,
@@ -108,18 +108,9 @@ function handshakeResponseMessage(from, instanceId, to, ok, reason) {
108
108
  ack: 0,
109
109
  streamId: (0, import_nanoid.nanoid)(),
110
110
  controlFlags: 0,
111
- payload: ok ? {
112
- type: "HANDSHAKE_RESP",
113
- status: {
114
- ok: true,
115
- instanceId
116
- }
117
- } : {
111
+ payload: {
118
112
  type: "HANDSHAKE_RESP",
119
- status: {
120
- ok: false,
121
- reason: reason ?? "Unknown reason"
122
- }
113
+ status
123
114
  }
124
115
  };
125
116
  }
@@ -190,7 +181,12 @@ var Session = class {
190
181
  /**
191
182
  * The unique ID of this session.
192
183
  */
193
- debugId;
184
+ id;
185
+ /**
186
+ * What the other side advertised as their session ID
187
+ * for this session.
188
+ */
189
+ advertisedSessionId;
194
190
  /**
195
191
  * Number of messages we've sent along this session (excluding handshake and acks)
196
192
  */
@@ -212,11 +208,11 @@ var Session = class {
212
208
  * The interval for sending heartbeats.
213
209
  */
214
210
  heartbeat;
215
- constructor(from, connectedTo, conn, options) {
211
+ constructor(conn, from, to, options) {
212
+ this.id = `session-${nanoid2(12)}`;
216
213
  this.options = options;
217
- this.debugId = `sess-${unsafeId()}`;
218
214
  this.from = from;
219
- this.to = connectedTo;
215
+ this.to = to;
220
216
  this.connection = conn;
221
217
  this.codec = options.codec;
222
218
  this.heartbeatMisses = 0;
@@ -256,7 +252,7 @@ var Session = class {
256
252
  log?.info(
257
253
  `${this.from} -- closing connection (id: ${this.connection.debugId}) to ${this.to} due to inactivity`
258
254
  );
259
- this.closeStaleConnection(this.connection);
255
+ this.closeStaleConnection();
260
256
  }
261
257
  return;
262
258
  }
@@ -287,33 +283,37 @@ var Session = class {
287
283
  log?.debug(`${this.from} -- resending ${msg.id} (seq: ${msg.seq})`);
288
284
  const ok = this.connection.send(this.codec.toBuffer(msg));
289
285
  if (!ok) {
290
- const msg2 = `${this.from} -- failed to send buffered message to ${this.to} in session (id: ${this.debugId}) (if you hit this code path something is seriously wrong)`;
286
+ const msg2 = `${this.from} -- failed to send buffered message to ${this.to} in session (id: ${this.id}) (if you hit this code path something is seriously wrong)`;
291
287
  log?.error(msg2);
292
288
  throw new Error(msg2);
293
289
  }
294
290
  }
295
291
  }
296
292
  updateBookkeeping(ack, seq) {
297
- this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq > ack);
293
+ if (seq + 1 < this.ack) {
294
+ log?.error(`${this.from} -- received stale seq ${seq} + 1 < ${this.ack}`);
295
+ return;
296
+ }
297
+ this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
298
298
  this.ack = seq + 1;
299
299
  }
300
300
  closeStaleConnection(conn) {
301
- if (!this.connection || this.connection !== conn)
301
+ if (this.connection === void 0 || this.connection === conn)
302
302
  return;
303
303
  log?.info(
304
- `${this.from} -- closing old inner connection (id: ${this.connection.debugId}) from session (id: ${this.debugId}) to ${this.to}`
304
+ `${this.from} -- closing old inner connection (id: ${this.connection.debugId}) from session (id: ${this.id}) to ${this.to}`
305
305
  );
306
306
  this.connection.close();
307
307
  this.connection = void 0;
308
308
  }
309
309
  replaceWithNewConnection(newConn) {
310
- this.closeStaleConnection(this.connection);
310
+ this.closeStaleConnection(newConn);
311
311
  this.cancelGrace();
312
312
  this.connection = newConn;
313
313
  }
314
314
  beginGrace(cb) {
315
315
  log?.info(
316
- `${this.from} -- starting ${this.options.sessionDisconnectGraceMs}ms grace period until session (id: ${this.debugId}) to ${this.to} is closed`
316
+ `${this.from} -- starting ${this.options.sessionDisconnectGraceMs}ms grace period until session (id: ${this.id}) to ${this.to} is closed`
317
317
  );
318
318
  this.disconnectionGrace = setTimeout(() => {
319
319
  this.close();
@@ -324,11 +324,12 @@ var Session = class {
324
324
  cancelGrace() {
325
325
  this.heartbeatMisses = 0;
326
326
  clearTimeout(this.disconnectionGrace);
327
+ this.disconnectionGrace = void 0;
327
328
  }
328
329
  // closed when we want to discard the whole session
329
330
  // (i.e. shutdown or session disconnect)
330
331
  close() {
331
- this.closeStaleConnection(this.connection);
332
+ this.closeStaleConnection();
332
333
  this.cancelGrace();
333
334
  this.resetBufferedMessages();
334
335
  clearInterval(this.heartbeat);
@@ -357,9 +358,6 @@ var Session = class {
357
358
  }
358
359
  };
359
360
 
360
- // transport/transport.ts
361
- var import_nanoid3 = require("nanoid");
362
-
363
361
  // util/stringify.ts
364
362
  function coerceErrorString(err) {
365
363
  if (err instanceof Error) {
@@ -510,13 +508,6 @@ var defaultClientTransportOptions = {
510
508
  ...defaultConnectionRetryOptions
511
509
  };
512
510
  var Transport = class {
513
- /**
514
- * Unique per instance of the transport.
515
- * This allows us to distinguish reconnects to different
516
- * transports.
517
- */
518
- instanceId = (0, import_nanoid3.nanoid)();
519
- connectedInstanceIds = /* @__PURE__ */ new Map();
520
511
  /**
521
512
  * A flag indicating whether the transport has been destroyed.
522
513
  * A destroyed transport will not attempt to reconnect and cannot be used again.
@@ -569,41 +560,41 @@ var Transport = class {
569
560
  * and we know the identity of the connected client.
570
561
  * @param conn The connection object.
571
562
  */
572
- onConnect(conn, connectedTo, instanceId) {
563
+ onConnect(conn, connectedTo, advertisedSessionId) {
573
564
  this.eventDispatcher.dispatchEvent("connectionStatus", {
574
565
  status: "connect",
575
566
  conn
576
567
  });
577
568
  let oldSession = this.sessions.get(connectedTo);
578
- const lastInstanceId = this.connectedInstanceIds.get(connectedTo);
579
- if (oldSession && lastInstanceId !== void 0 && lastInstanceId !== instanceId) {
569
+ if (oldSession?.advertisedSessionId && oldSession.advertisedSessionId !== advertisedSessionId) {
580
570
  log?.warn(
581
- `${this.clientId} -- connection from ${connectedTo} is a different instance (got: ${instanceId}, last connected to: ${lastInstanceId}), starting a new session`
571
+ `${this.clientId} -- connection from ${connectedTo} is a different session (id: ${advertisedSessionId}, last connected to: ${oldSession.advertisedSessionId}), starting a new session`
582
572
  );
583
573
  oldSession.close();
584
574
  this.deleteSession(oldSession);
585
575
  oldSession = void 0;
586
576
  }
587
- this.connectedInstanceIds.set(connectedTo, instanceId);
588
577
  if (oldSession === void 0) {
589
578
  const newSession = this.createSession(connectedTo, conn);
579
+ newSession.advertisedSessionId = advertisedSessionId;
590
580
  log?.info(
591
- `${this.clientId} -- new connection (id: ${conn.debugId}) for new session (id: ${newSession.debugId}) to ${connectedTo}`
581
+ `${this.clientId} -- new connection (id: ${conn.debugId}) for new session (id: ${newSession.id}) to ${connectedTo}`
592
582
  );
593
583
  return newSession;
594
584
  }
595
585
  log?.info(
596
- `${this.clientId} -- new connection (id: ${conn.debugId}) for existing session (id: ${oldSession.debugId}) to ${connectedTo}`
586
+ `${this.clientId} -- new connection (id: ${conn.debugId}) for existing session (id: ${oldSession.id}) to ${connectedTo}`
597
587
  );
598
588
  oldSession.replaceWithNewConnection(conn);
599
589
  oldSession.sendBufferedMessages();
590
+ oldSession.advertisedSessionId = advertisedSessionId;
600
591
  return oldSession;
601
592
  }
602
- createSession(connectedTo, conn) {
593
+ createSession(to, conn) {
603
594
  const session = new Session(
604
- this.clientId,
605
- connectedTo,
606
595
  conn,
596
+ this.clientId,
597
+ to,
607
598
  this.options
608
599
  );
609
600
  this.sessions.set(session.to, session);
@@ -613,10 +604,20 @@ var Transport = class {
613
604
  });
614
605
  return session;
615
606
  }
607
+ getOrCreateSession(to, conn) {
608
+ let session = this.sessions.get(to);
609
+ if (!session) {
610
+ session = this.createSession(to, conn);
611
+ log?.info(
612
+ `${this.clientId} -- no session for ${to}, created a new one (id: ${session.id})`
613
+ );
614
+ }
615
+ return session;
616
+ }
616
617
  deleteSession(session) {
617
618
  this.sessions.delete(session.to);
618
619
  log?.info(
619
- `${this.clientId} -- session ${session.debugId} disconnect from ${session.to}`
620
+ `${this.clientId} -- session ${session.id} disconnect from ${session.to}`
620
621
  );
621
622
  this.eventDispatcher.dispatchEvent("sessionStatus", {
622
623
  status: "disconnect",
@@ -686,9 +687,12 @@ var Transport = class {
686
687
  } else {
687
688
  const errMsg = `received out-of-order msg (got seq: ${msg.seq}, wanted seq: ${session.nextExpectedSeq})`;
688
689
  log?.error(
689
- `${this.clientId} -- ${errMsg}, marking connection as dead: ${JSON.stringify(msg)}`
690
+ `${this.clientId} -- fatal: ${errMsg}, marking connection as dead: ${JSON.stringify(
691
+ msg
692
+ )}`
690
693
  );
691
694
  this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
695
+ session.close();
692
696
  }
693
697
  return;
694
698
  }
@@ -735,14 +739,7 @@ var Transport = class {
735
739
  );
736
740
  return void 0;
737
741
  }
738
- let session = this.sessions.get(to);
739
- if (!session) {
740
- session = this.createSession(to, void 0);
741
- log?.info(
742
- `${this.clientId} -- no session for ${to}, created a new one (id: ${session.debugId})`
743
- );
744
- }
745
- return session.send(msg);
742
+ return this.getOrCreateSession(to).send(msg);
746
743
  }
747
744
  // control helpers
748
745
  sendCloseStream(to, streamId) {
@@ -815,12 +812,13 @@ var ClientTransport = class extends Transport {
815
812
  return;
816
813
  let session = void 0;
817
814
  const handshakeHandler = (data) => {
818
- const handshake = this.receiveHandshakeResponseMessage(data);
819
- if (!handshake) {
815
+ const maybeSession = this.receiveHandshakeResponseMessage(data, conn);
816
+ if (!maybeSession) {
820
817
  conn.close();
821
818
  return;
819
+ } else {
820
+ session = maybeSession;
822
821
  }
823
- session = this.onConnect(conn, handshake.from, handshake.instanceId);
824
822
  conn.removeDataListener(handshakeHandler);
825
823
  conn.addDataListener((data2) => {
826
824
  const parsed = this.parseMsg(data2);
@@ -850,7 +848,7 @@ var ClientTransport = class extends Transport {
850
848
  );
851
849
  });
852
850
  }
853
- receiveHandshakeResponseMessage(data) {
851
+ receiveHandshakeResponseMessage(data, conn) {
854
852
  const parsed = this.parseMsg(data);
855
853
  if (!parsed) {
856
854
  this.protocolError(
@@ -883,12 +881,14 @@ var ClientTransport = class extends Transport {
883
881
  );
884
882
  return false;
885
883
  }
886
- const instanceId = parsed.payload.status.instanceId;
887
- log?.debug(
888
- `${this.clientId} -- handshake from ${parsed.from} ok (instance: ${instanceId})`
884
+ log?.debug(`${this.clientId} -- handshake from ${parsed.from} ok`);
885
+ const session = this.onConnect(
886
+ conn,
887
+ parsed.from,
888
+ parsed.payload.status.sessionId
889
889
  );
890
890
  this.retryBudget.startRestoringBudget(parsed.from);
891
- return { instanceId, from: parsed.from };
891
+ return session;
892
892
  }
893
893
  /**
894
894
  * Manually attempts to connect to a client.
@@ -957,11 +957,8 @@ var ClientTransport = class extends Transport {
957
957
  }
958
958
  }
959
959
  sendHandshake(to, conn) {
960
- const requestMsg = handshakeRequestMessage(
961
- this.clientId,
962
- to,
963
- this.instanceId
964
- );
960
+ const session = this.getOrCreateSession(to, conn);
961
+ const requestMsg = handshakeRequestMessage(this.clientId, to, session.id);
965
962
  log?.debug(`${this.clientId} -- sending handshake request to ${to}`);
966
963
  conn.send(this.codec.toBuffer(requestMsg));
967
964
  }
@@ -974,7 +971,7 @@ var ServerTransport = class extends Transport {
974
971
  constructor(clientId, providedOptions) {
975
972
  super(clientId, providedOptions);
976
973
  log?.info(
977
- `${this.clientId} -- initiated server transport (instance id: ${this.instanceId}, protocol: ${PROTOCOL_VERSION})`
974
+ `${this.clientId} -- initiated server transport (protocol: ${PROTOCOL_VERSION})`
978
975
  );
979
976
  }
980
977
  handleConnection(conn) {
@@ -986,12 +983,13 @@ var ServerTransport = class extends Transport {
986
983
  let session = void 0;
987
984
  const client = () => session?.to ?? "unknown";
988
985
  const handshakeHandler = (data) => {
989
- const handshake = this.receiveHandshakeRequestMessage(data, conn);
990
- if (!handshake) {
986
+ const maybeSession = this.receiveHandshakeRequestMessage(data, conn);
987
+ if (!maybeSession) {
991
988
  conn.close();
992
989
  return;
990
+ } else {
991
+ session = maybeSession;
993
992
  }
994
- session = this.onConnect(conn, handshake.from, handshake.instanceId);
995
993
  conn.removeDataListener(handshakeHandler);
996
994
  conn.addDataListener((data2) => {
997
995
  const parsed = this.parseMsg(data2);
@@ -1029,18 +1027,13 @@ var ServerTransport = class extends Transport {
1029
1027
  return false;
1030
1028
  }
1031
1029
  if (!import_value.Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
1032
- const responseMsg2 = handshakeResponseMessage(
1033
- this.clientId,
1034
- this.instanceId,
1035
- parsed.from,
1036
- false
1037
- );
1030
+ const reason = "received invalid handshake msg";
1031
+ const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1032
+ ok: false,
1033
+ reason
1034
+ });
1038
1035
  conn.send(this.codec.toBuffer(responseMsg2));
1039
- log?.warn(
1040
- `${this.clientId} -- received invalid handshake msg: ${JSON.stringify(
1041
- parsed
1042
- )}`
1043
- );
1036
+ log?.warn(`${this.clientId} -- ${reason}: ${JSON.stringify(parsed)}`);
1044
1037
  this.protocolError(
1045
1038
  ProtocolError.HandshakeFailed,
1046
1039
  "invalid handshake request"
@@ -1049,34 +1042,28 @@ var ServerTransport = class extends Transport {
1049
1042
  }
1050
1043
  const gotVersion = parsed.payload.protocolVersion;
1051
1044
  if (gotVersion !== PROTOCOL_VERSION) {
1052
- const responseMsg2 = handshakeResponseMessage(
1053
- this.clientId,
1054
- this.instanceId,
1055
- parsed.from,
1056
- false
1057
- );
1045
+ const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
1046
+ const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1047
+ ok: false,
1048
+ reason
1049
+ });
1058
1050
  conn.send(this.codec.toBuffer(responseMsg2));
1059
1051
  log?.warn(
1060
1052
  `${this.clientId} -- received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`
1061
1053
  );
1062
- this.protocolError(
1063
- ProtocolError.HandshakeFailed,
1064
- `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`
1065
- );
1054
+ this.protocolError(ProtocolError.HandshakeFailed, reason);
1066
1055
  return false;
1067
1056
  }
1068
- const instanceId = parsed.payload.instanceId;
1057
+ const session = this.getOrCreateSession(parsed.from, conn);
1069
1058
  log?.debug(
1070
- `${this.clientId} -- handshake from ${parsed.from} ok (instance id: ${instanceId}), responding with handshake success`
1071
- );
1072
- const responseMsg = handshakeResponseMessage(
1073
- this.clientId,
1074
- this.instanceId,
1075
- parsed.from,
1076
- true
1059
+ `${this.clientId} -- handshake from ${parsed.from} ok, responding with handshake success`
1077
1060
  );
1061
+ const responseMsg = handshakeResponseMessage(this.clientId, parsed.from, {
1062
+ ok: true,
1063
+ sessionId: session.id
1064
+ });
1078
1065
  conn.send(this.codec.toBuffer(responseMsg));
1079
- return { instanceId, from: parsed.from };
1066
+ return this.onConnect(conn, parsed.from, parsed.payload.sessionId);
1080
1067
  }
1081
1068
  };
1082
1069
  // Annotate the CommonJS export names for ESM import in node:
@@ -1,3 +1,3 @@
1
- export { a as ClientTransport, c as ClientTransportOptions, C as Connection, m as EventHandler, E as EventMap, l as EventTypes, O as OpaqueTransportMessage, h as OpaqueTransportMessageSchema, n as ProtocolError, o as ProtocolErrorType, S as ServerTransport, e as Session, T as Transport, b as TransportClientId, i as TransportMessage, g as TransportMessageSchema, d as TransportOptions, f as TransportStatus, k as isStreamClose, j as isStreamOpen } from '../index-c9e9977f.js';
1
+ export { a as ClientTransport, c as ClientTransportOptions, C as Connection, n as EventHandler, E as EventMap, m as EventTypes, O as OpaqueTransportMessage, i as OpaqueTransportMessageSchema, o as ProtocolError, p as ProtocolErrorType, d as ServerTransport, f as Session, T as Transport, b as TransportClientId, j as TransportMessage, h as TransportMessageSchema, e as TransportOptions, g as TransportStatus, l as isStreamClose, k as isStreamOpen } from '../index-8df0bdfb.js';
2
2
  import '../types-3e5768ec.js';
3
3
  import '@sinclair/typebox';
@@ -1,3 +1,3 @@
1
- export { a as ClientTransport, c as ClientTransportOptions, C as Connection, m as EventHandler, E as EventMap, l as EventTypes, O as OpaqueTransportMessage, h as OpaqueTransportMessageSchema, n as ProtocolError, o as ProtocolErrorType, S as ServerTransport, e as Session, T as Transport, b as TransportClientId, i as TransportMessage, g as TransportMessageSchema, d as TransportOptions, f as TransportStatus, k as isStreamClose, j as isStreamOpen } from '../index-c9e9977f.js';
1
+ export { a as ClientTransport, c as ClientTransportOptions, C as Connection, n as EventHandler, E as EventMap, m as EventTypes, O as OpaqueTransportMessage, i as OpaqueTransportMessageSchema, o as ProtocolError, p as ProtocolErrorType, d as ServerTransport, f as Session, T as Transport, b as TransportClientId, j as TransportMessage, h as TransportMessageSchema, e as TransportOptions, g as TransportStatus, l as isStreamClose, k as isStreamOpen } from '../index-8df0bdfb.js';
2
2
  import '../types-3e5768ec.js';
3
3
  import '@sinclair/typebox';
@@ -6,11 +6,11 @@ import {
6
6
  ServerTransport,
7
7
  Session,
8
8
  Transport
9
- } from "../chunk-CJGD7CNG.js";
9
+ } from "../chunk-F6KWMEPR.js";
10
10
  import {
11
11
  OpaqueTransportMessageSchema,
12
12
  TransportMessageSchema
13
- } from "../chunk-GFRAOY75.js";
13
+ } from "../chunk-VH3NGOXQ.js";
14
14
  import "../chunk-H4BYJELI.js";
15
15
  import "../chunk-GZ7HCLLM.js";
16
16
  export {
@@ -49,6 +49,9 @@ module.exports = __toCommonJS(testHelpers_exports);
49
49
  var import_isomorphic_ws = __toESM(require("isomorphic-ws"), 1);
50
50
  var import_ws = require("ws");
51
51
 
52
+ // transport/transport.ts
53
+ var import_value = require("@sinclair/typebox/value");
54
+
52
55
  // logging/index.ts
53
56
  var log;
54
57
 
@@ -72,7 +75,12 @@ var Session = class {
72
75
  /**
73
76
  * The unique ID of this session.
74
77
  */
75
- debugId;
78
+ id;
79
+ /**
80
+ * What the other side advertised as their session ID
81
+ * for this session.
82
+ */
83
+ advertisedSessionId;
76
84
  /**
77
85
  * Number of messages we've sent along this session (excluding handshake and acks)
78
86
  */
@@ -94,11 +102,11 @@ var Session = class {
94
102
  * The interval for sending heartbeats.
95
103
  */
96
104
  heartbeat;
97
- constructor(from, connectedTo, conn, options) {
105
+ constructor(conn, from, to, options) {
106
+ this.id = `session-${nanoid(12)}`;
98
107
  this.options = options;
99
- this.debugId = `sess-${unsafeId()}`;
100
108
  this.from = from;
101
- this.to = connectedTo;
109
+ this.to = to;
102
110
  this.connection = conn;
103
111
  this.codec = options.codec;
104
112
  this.heartbeatMisses = 0;
@@ -138,7 +146,7 @@ var Session = class {
138
146
  log?.info(
139
147
  `${this.from} -- closing connection (id: ${this.connection.debugId}) to ${this.to} due to inactivity`
140
148
  );
141
- this.closeStaleConnection(this.connection);
149
+ this.closeStaleConnection();
142
150
  }
143
151
  return;
144
152
  }
@@ -169,33 +177,37 @@ var Session = class {
169
177
  log?.debug(`${this.from} -- resending ${msg.id} (seq: ${msg.seq})`);
170
178
  const ok = this.connection.send(this.codec.toBuffer(msg));
171
179
  if (!ok) {
172
- const msg2 = `${this.from} -- failed to send buffered message to ${this.to} in session (id: ${this.debugId}) (if you hit this code path something is seriously wrong)`;
180
+ const msg2 = `${this.from} -- failed to send buffered message to ${this.to} in session (id: ${this.id}) (if you hit this code path something is seriously wrong)`;
173
181
  log?.error(msg2);
174
182
  throw new Error(msg2);
175
183
  }
176
184
  }
177
185
  }
178
186
  updateBookkeeping(ack, seq) {
179
- this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq > ack);
187
+ if (seq + 1 < this.ack) {
188
+ log?.error(`${this.from} -- received stale seq ${seq} + 1 < ${this.ack}`);
189
+ return;
190
+ }
191
+ this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
180
192
  this.ack = seq + 1;
181
193
  }
182
194
  closeStaleConnection(conn) {
183
- if (!this.connection || this.connection !== conn)
195
+ if (this.connection === void 0 || this.connection === conn)
184
196
  return;
185
197
  log?.info(
186
- `${this.from} -- closing old inner connection (id: ${this.connection.debugId}) from session (id: ${this.debugId}) to ${this.to}`
198
+ `${this.from} -- closing old inner connection (id: ${this.connection.debugId}) from session (id: ${this.id}) to ${this.to}`
187
199
  );
188
200
  this.connection.close();
189
201
  this.connection = void 0;
190
202
  }
191
203
  replaceWithNewConnection(newConn) {
192
- this.closeStaleConnection(this.connection);
204
+ this.closeStaleConnection(newConn);
193
205
  this.cancelGrace();
194
206
  this.connection = newConn;
195
207
  }
196
208
  beginGrace(cb) {
197
209
  log?.info(
198
- `${this.from} -- starting ${this.options.sessionDisconnectGraceMs}ms grace period until session (id: ${this.debugId}) to ${this.to} is closed`
210
+ `${this.from} -- starting ${this.options.sessionDisconnectGraceMs}ms grace period until session (id: ${this.id}) to ${this.to} is closed`
199
211
  );
200
212
  this.disconnectionGrace = setTimeout(() => {
201
213
  this.close();
@@ -206,11 +218,12 @@ var Session = class {
206
218
  cancelGrace() {
207
219
  this.heartbeatMisses = 0;
208
220
  clearTimeout(this.disconnectionGrace);
221
+ this.disconnectionGrace = void 0;
209
222
  }
210
223
  // closed when we want to discard the whole session
211
224
  // (i.e. shutdown or session disconnect)
212
225
  close() {
213
- this.closeStaleConnection(this.connection);
226
+ this.closeStaleConnection();
214
227
  this.cancelGrace();
215
228
  this.resetBufferedMessages();
216
229
  clearInterval(this.heartbeat);
@@ -299,6 +312,25 @@ var NaiveJsonCodec = {
299
312
  }
300
313
  };
301
314
 
315
+ // transport/transport.ts
316
+ var defaultTransportOptions = {
317
+ heartbeatIntervalMs: 1e3,
318
+ heartbeatsUntilDead: 2,
319
+ sessionDisconnectGraceMs: 5e3,
320
+ codec: NaiveJsonCodec
321
+ };
322
+ var defaultConnectionRetryOptions = {
323
+ baseIntervalMs: 250,
324
+ maxJitterMs: 200,
325
+ maxBackoffMs: 32e3,
326
+ attemptBudgetCapacity: 5,
327
+ budgetRestoreIntervalMs: 200
328
+ };
329
+ var defaultClientTransportOptions = {
330
+ ...defaultTransportOptions,
331
+ ...defaultConnectionRetryOptions
332
+ };
333
+
302
334
  // node_modules/p-defer/index.js
303
335
  function pDefer() {
304
336
  const deferred = {};
@@ -663,17 +695,12 @@ function catchProcError(err) {
663
695
  }
664
696
  };
665
697
  }
666
- var testingSessionOptions = {
667
- heartbeatIntervalMs: 1e3,
668
- heartbeatsUntilDead: 2,
669
- sessionDisconnectGraceMs: 5e3,
670
- codec: NaiveJsonCodec
671
- };
698
+ var testingSessionOptions = defaultTransportOptions;
672
699
  function dummyCtx(state, extendedContext) {
673
700
  const session = new Session(
701
+ void 0,
674
702
  "client",
675
703
  "SERVER",
676
- void 0,
677
704
  testingSessionOptions
678
705
  );
679
706
  return {
@@ -1,11 +1,11 @@
1
1
  import { Static } from '@sinclair/typebox';
2
- import { P as PayloadType, R as RiverError, a as Procedure, S as ServiceContext, b as Result, c as RiverUncaughtSchema, d as ProcedureResult } from '../procedures-d295c1a5.js';
3
- import { P as PartialTransportMessage, T as Transport, C as Connection, O as OpaqueTransportMessage } from '../index-c9e9977f.js';
2
+ import { P as PayloadType, R as RiverError, a as Procedure, S as ServiceContext, b as Result, c as RiverUncaughtSchema, d as ProcedureResult } from '../procedures-b5ddb54d.js';
3
+ import { P as PartialTransportMessage, T as Transport, C as Connection, O as OpaqueTransportMessage, S as SessionOptions } from '../index-8df0bdfb.js';
4
4
  import * as it_pushable from 'it-pushable';
5
- import { C as Codec } from '../types-3e5768ec.js';
6
5
  import WebSocket from 'isomorphic-ws';
7
6
  import http from 'node:http';
8
7
  import net from 'node:net';
8
+ import '../types-3e5768ec.js';
9
9
 
10
10
  /**
11
11
  * Creates a WebSocket server instance using the provided HTTP server.
@@ -48,12 +48,7 @@ declare function createDummyTransportMessage(): PartialTransportMessage<{
48
48
  * @returns A promise that resolves with the payload of the first message that passes the filter.
49
49
  */
50
50
  declare function waitForMessage(t: Transport<Connection>, filter?: (msg: OpaqueTransportMessage) => boolean, rejectMismatch?: boolean): Promise<unknown>;
51
- declare const testingSessionOptions: {
52
- heartbeatIntervalMs: number;
53
- heartbeatsUntilDead: number;
54
- sessionDisconnectGraceMs: number;
55
- codec: Codec;
56
- };
51
+ declare const testingSessionOptions: SessionOptions;
57
52
  declare function asClientRpc<State extends object, I extends PayloadType, O extends PayloadType, E extends RiverError, Init extends PayloadType | null = null>(state: State, proc: Procedure<State, 'rpc', I, O, E, Init>, extendedContext?: Omit<ServiceContext, 'state'>): (msg: Static<I>) => Promise<Result<Static<O>, Static<E> | Static<typeof RiverUncaughtSchema>>>;
58
53
  declare function asClientStream<State extends object, I extends PayloadType, O extends PayloadType, E extends RiverError, Init extends PayloadType | null = null>(state: State, proc: Procedure<State, 'stream', I, O, E, Init>, init?: Init extends PayloadType ? Static<Init> : null, extendedContext?: Omit<ServiceContext, 'state'>): readonly [it_pushable.Pushable<Static<I>, void, unknown>, it_pushable.Pushable<Result<Static<O>, Static<E>>, void, unknown>];
59
54
  declare function asClientSubscription<State extends object, I extends PayloadType, O extends PayloadType, E extends RiverError>(state: State, proc: Procedure<State, 'subscription', I, O, E>, extendedContext?: Omit<ServiceContext, 'state'>): (msg: Static<I>) => it_pushable.Pushable<Result<Static<O>, Static<E>>, void, unknown>;