@replit/river 0.23.13 → 0.23.15

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 (62) hide show
  1. package/dist/{chunk-2FNLANTJ.js → chunk-5HK7ZQYH.js} +10 -2
  2. package/dist/{chunk-2FNLANTJ.js.map → chunk-5HK7ZQYH.js.map} +1 -1
  3. package/dist/{chunk-KFTGQ3QC.js → chunk-AEY7BBOZ.js} +2 -2
  4. package/dist/{chunk-S4DUN7KK.js → chunk-IJTGEBLG.js} +41 -20
  5. package/dist/chunk-IJTGEBLG.js.map +1 -0
  6. package/dist/{chunk-ZUKDZY54.js → chunk-JMVKSGND.js} +89 -25
  7. package/dist/chunk-JMVKSGND.js.map +1 -0
  8. package/dist/{chunk-XM656KMN.js → chunk-MD4S7GO2.js} +71 -3
  9. package/dist/chunk-MD4S7GO2.js.map +1 -0
  10. package/dist/{chunk-ES4XO2XD.js → chunk-OXVWMLID.js} +33 -4
  11. package/dist/chunk-OXVWMLID.js.map +1 -0
  12. package/dist/{chunk-SX6HI63Q.js → chunk-RQQZUQGE.js} +2 -2
  13. package/dist/{chunk-4QZOW4DH.js → chunk-XYEOXPZQ.js} +2 -2
  14. package/dist/{client-dd5c9dd0.d.ts → client-e13979ac.d.ts} +1 -1
  15. package/dist/{connection-39816c00.d.ts → connection-5d0978ce.d.ts} +1 -1
  16. package/dist/{connection-40318f22.d.ts → connection-e57e98ea.d.ts} +1 -1
  17. package/dist/{handshake-e428d1c8.d.ts → handshake-5665ffd3.d.ts} +13 -0
  18. package/dist/router/index.cjs +16 -1
  19. package/dist/router/index.cjs.map +1 -1
  20. package/dist/router/index.d.cts +7 -7
  21. package/dist/router/index.d.ts +7 -7
  22. package/dist/router/index.js +2 -2
  23. package/dist/{server-ebf80863.d.ts → server-1cfc88d1.d.ts} +1 -1
  24. package/dist/{services-f406b3aa.d.ts → services-86c4d10d.d.ts} +2 -2
  25. package/dist/transport/impls/uds/client.cjs +138 -18
  26. package/dist/transport/impls/uds/client.cjs.map +1 -1
  27. package/dist/transport/impls/uds/client.d.cts +3 -3
  28. package/dist/transport/impls/uds/client.d.ts +3 -3
  29. package/dist/transport/impls/uds/client.js +5 -5
  30. package/dist/transport/impls/uds/server.cjs +182 -23
  31. package/dist/transport/impls/uds/server.cjs.map +1 -1
  32. package/dist/transport/impls/uds/server.d.cts +3 -3
  33. package/dist/transport/impls/uds/server.d.ts +3 -3
  34. package/dist/transport/impls/uds/server.js +5 -5
  35. package/dist/transport/impls/ws/client.cjs +138 -18
  36. package/dist/transport/impls/ws/client.cjs.map +1 -1
  37. package/dist/transport/impls/ws/client.d.cts +3 -3
  38. package/dist/transport/impls/ws/client.d.ts +3 -3
  39. package/dist/transport/impls/ws/client.js +5 -5
  40. package/dist/transport/impls/ws/server.cjs +182 -23
  41. package/dist/transport/impls/ws/server.cjs.map +1 -1
  42. package/dist/transport/impls/ws/server.d.cts +3 -3
  43. package/dist/transport/impls/ws/server.d.ts +3 -3
  44. package/dist/transport/impls/ws/server.js +5 -5
  45. package/dist/transport/index.cjs +227 -40
  46. package/dist/transport/index.cjs.map +1 -1
  47. package/dist/transport/index.d.cts +3 -3
  48. package/dist/transport/index.d.ts +3 -3
  49. package/dist/transport/index.js +5 -5
  50. package/dist/util/testHelpers.cjs +9 -1
  51. package/dist/util/testHelpers.cjs.map +1 -1
  52. package/dist/util/testHelpers.d.cts +3 -3
  53. package/dist/util/testHelpers.d.ts +3 -3
  54. package/dist/util/testHelpers.js +3 -3
  55. package/package.json +13 -14
  56. package/dist/chunk-ES4XO2XD.js.map +0 -1
  57. package/dist/chunk-S4DUN7KK.js.map +0 -1
  58. package/dist/chunk-XM656KMN.js.map +0 -1
  59. package/dist/chunk-ZUKDZY54.js.map +0 -1
  60. /package/dist/{chunk-KFTGQ3QC.js.map → chunk-AEY7BBOZ.js.map} +0 -0
  61. /package/dist/{chunk-SX6HI63Q.js.map → chunk-RQQZUQGE.js.map} +0 -0
  62. /package/dist/{chunk-4QZOW4DH.js.map → chunk-XYEOXPZQ.js.map} +0 -0
@@ -59,6 +59,21 @@ var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
59
59
  type: import_typebox.Type.Literal("HANDSHAKE_REQ"),
60
60
  protocolVersion: import_typebox.Type.String(),
61
61
  sessionId: import_typebox.Type.String(),
62
+ /**
63
+ * Specifies what the server's expected session state (from the pov of the client). This can be
64
+ * used by the server to know whether this is a new or a reestablished connection, and whether it
65
+ * is compatible with what it already has.
66
+ */
67
+ expectedSessionState: import_typebox.Type.Optional(
68
+ import_typebox.Type.Object({
69
+ /**
70
+ * reconnect is set to true if the client explicitly wants to reestablish an existing
71
+ * connection.
72
+ */
73
+ reconnect: import_typebox.Type.Boolean(),
74
+ nextExpectedSeq: import_typebox.Type.Integer()
75
+ })
76
+ ),
62
77
  metadata: import_typebox.Type.Optional(import_typebox.Type.Unknown())
63
78
  });
64
79
  var ControlMessageHandshakeResponseSchema = import_typebox.Type.Object({
@@ -83,7 +98,12 @@ var ControlMessagePayloadSchema = import_typebox.Type.Union([
83
98
  var OpaqueTransportMessageSchema = TransportMessageSchema(
84
99
  import_typebox.Type.Unknown()
85
100
  );
86
- function handshakeResponseMessage(from, to, status) {
101
+ var SESSION_STATE_MISMATCH = "session state mismatch";
102
+ function handshakeResponseMessage({
103
+ from,
104
+ to,
105
+ status
106
+ }) {
87
107
  return {
88
108
  id: (0, import_nanoid.nanoid)(),
89
109
  from,
@@ -106,7 +126,7 @@ function isAck(controlFlag) {
106
126
  var import_api = require("@opentelemetry/api");
107
127
 
108
128
  // package.json
109
- var version = "0.23.13";
129
+ var version = "0.23.15";
110
130
 
111
131
  // tracing/index.ts
112
132
  function createSessionTelemetryInfo(session, propagationCtx) {
@@ -411,9 +431,17 @@ var Session = class {
411
431
  get connected() {
412
432
  return this.connection !== void 0;
413
433
  }
434
+ get nextExpectedAck() {
435
+ return this.seq;
436
+ }
414
437
  get nextExpectedSeq() {
415
438
  return this.ack;
416
439
  }
440
+ // This is only used in tests to make the session misbehave.
441
+ /* @internal */
442
+ advanceAckForTesting(by) {
443
+ this.ack += by;
444
+ }
417
445
  constructMsg(partialMsg) {
418
446
  const msg = {
419
447
  ...partialMsg,
@@ -738,6 +766,20 @@ var Transport = class {
738
766
  if (this.log) {
739
767
  session.bindLogger(this.log);
740
768
  }
769
+ const currentSession = this.sessions.get(session.to);
770
+ if (currentSession) {
771
+ this.log?.warn(
772
+ `session ${session.id} from ${session.to} surreptitiously replacing ${currentSession.id}`,
773
+ {
774
+ ...currentSession.loggingMetadata,
775
+ tags: ["invariant-violation"]
776
+ }
777
+ );
778
+ this.deleteSession({
779
+ session: currentSession,
780
+ closeHandshakingConnection: false
781
+ });
782
+ }
741
783
  this.sessions.set(session.to, session);
742
784
  this.eventDispatcher.dispatchEvent("sessionStatus", {
743
785
  status: "connect",
@@ -745,6 +787,49 @@ var Transport = class {
745
787
  });
746
788
  return session;
747
789
  }
790
+ createNewSession({
791
+ to,
792
+ conn,
793
+ sessionId,
794
+ propagationCtx
795
+ }) {
796
+ let session = this.sessions.get(to);
797
+ if (session !== void 0) {
798
+ this.log?.info(
799
+ `session for ${to} already exists, replacing it with a new session as requested`,
800
+ session.loggingMetadata
801
+ );
802
+ this.deleteSession({
803
+ session,
804
+ closeHandshakingConnection: false
805
+ });
806
+ session = void 0;
807
+ }
808
+ session = this.createSession(to, conn, propagationCtx);
809
+ session.advertisedSessionId = sessionId;
810
+ this.log?.info(`created new session for ${to}`, session.loggingMetadata);
811
+ return session;
812
+ }
813
+ getExistingSession({
814
+ to,
815
+ sessionId,
816
+ nextExpectedSeq
817
+ }) {
818
+ const session = this.sessions.get(to);
819
+ if (
820
+ // reject this request if there was no previous session to replace
821
+ session === void 0 || // or if both parties do not agree about the next expected sequence number
822
+ session.nextExpectedAck < nextExpectedSeq || // or if both parties do not agree on the advertised session id
823
+ session.advertisedSessionId !== sessionId
824
+ ) {
825
+ return false;
826
+ }
827
+ this.log?.info(
828
+ `reused existing session for ${to}`,
829
+ session.loggingMetadata
830
+ );
831
+ return session;
832
+ }
748
833
  getOrCreateSession({
749
834
  to,
750
835
  conn,
@@ -793,6 +878,17 @@ var Transport = class {
793
878
  }
794
879
  session.close();
795
880
  session.telemetry.span.end();
881
+ const currentSession = this.sessions.get(session.to);
882
+ if (currentSession && currentSession.id !== session.id) {
883
+ this.log?.warn(
884
+ `session ${session.id} disconnect from ${session.to}, mismatch with ${currentSession.id}`,
885
+ {
886
+ ...session.loggingMetadata,
887
+ tags: ["invariant-violation"]
888
+ }
889
+ );
890
+ return;
891
+ }
796
892
  this.sessions.delete(session.to);
797
893
  this.log?.info(
798
894
  `session ${session.id} disconnect from ${session.to}`,
@@ -1133,9 +1229,13 @@ var ServerTransport = class extends Transport {
1133
1229
  message: "malformed handshake meta"
1134
1230
  });
1135
1231
  const reason = "received malformed handshake metadata";
1136
- const responseMsg = handshakeResponseMessage(this.clientId, from, {
1137
- ok: false,
1138
- reason
1232
+ const responseMsg = handshakeResponseMessage({
1233
+ from: this.clientId,
1234
+ to: from,
1235
+ status: {
1236
+ ok: false,
1237
+ reason
1238
+ }
1139
1239
  });
1140
1240
  conn.send(this.codec.toBuffer(responseMsg));
1141
1241
  this.log?.warn(`received malformed handshake metadata from ${from}`, {
@@ -1159,9 +1259,13 @@ var ServerTransport = class extends Transport {
1159
1259
  code: import_api4.SpanStatusCode.ERROR,
1160
1260
  message: reason
1161
1261
  });
1162
- const responseMsg = handshakeResponseMessage(this.clientId, from, {
1163
- ok: false,
1164
- reason
1262
+ const responseMsg = handshakeResponseMessage({
1263
+ from: this.clientId,
1264
+ to: from,
1265
+ status: {
1266
+ ok: false,
1267
+ reason
1268
+ }
1165
1269
  });
1166
1270
  conn.send(this.codec.toBuffer(responseMsg));
1167
1271
  this.log?.warn(`rejected handshake from ${from}`, {
@@ -1193,9 +1297,13 @@ var ServerTransport = class extends Transport {
1193
1297
  message: "invalid handshake request"
1194
1298
  });
1195
1299
  const reason = "received invalid handshake msg";
1196
- const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1197
- ok: false,
1198
- reason
1300
+ const responseMsg2 = handshakeResponseMessage({
1301
+ from: this.clientId,
1302
+ to: parsed.from,
1303
+ status: {
1304
+ ok: false,
1305
+ reason
1306
+ }
1199
1307
  });
1200
1308
  conn.send(this.codec.toBuffer(responseMsg2));
1201
1309
  this.log?.warn(reason, {
@@ -1221,9 +1329,13 @@ var ServerTransport = class extends Transport {
1221
1329
  message: "incorrect protocol version"
1222
1330
  });
1223
1331
  const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
1224
- const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1225
- ok: false,
1226
- reason
1332
+ const responseMsg2 = handshakeResponseMessage({
1333
+ from: this.clientId,
1334
+ to: parsed.from,
1335
+ status: {
1336
+ ok: false,
1337
+ reason
1338
+ }
1227
1339
  });
1228
1340
  conn.send(this.codec.toBuffer(responseMsg2));
1229
1341
  this.log?.warn(
@@ -1243,20 +1355,67 @@ var ServerTransport = class extends Transport {
1243
1355
  if (parsedMetadata === false) {
1244
1356
  return false;
1245
1357
  }
1246
- const { session, isTransparentReconnect } = this.getOrCreateSession({
1247
- to: parsed.from,
1248
- conn,
1249
- sessionId: parsed.payload.sessionId,
1250
- propagationCtx: parsed.tracing
1251
- });
1358
+ let session;
1359
+ let isTransparentReconnect;
1360
+ if (!parsed.payload.expectedSessionState) {
1361
+ ({ session, isTransparentReconnect } = this.getOrCreateSession({
1362
+ to: parsed.from,
1363
+ conn,
1364
+ sessionId: parsed.payload.sessionId,
1365
+ propagationCtx: parsed.tracing
1366
+ }));
1367
+ } else if (parsed.payload.expectedSessionState.reconnect) {
1368
+ const existingSession = this.getExistingSession({
1369
+ to: parsed.from,
1370
+ sessionId: parsed.payload.sessionId,
1371
+ nextExpectedSeq: parsed.payload.expectedSessionState.nextExpectedSeq
1372
+ });
1373
+ if (existingSession === false) {
1374
+ conn.telemetry?.span.setStatus({
1375
+ code: import_api4.SpanStatusCode.ERROR,
1376
+ message: SESSION_STATE_MISMATCH
1377
+ });
1378
+ const reason = SESSION_STATE_MISMATCH;
1379
+ const responseMsg2 = handshakeResponseMessage({
1380
+ from: this.clientId,
1381
+ to: parsed.from,
1382
+ status: {
1383
+ ok: false,
1384
+ reason
1385
+ }
1386
+ });
1387
+ conn.send(this.codec.toBuffer(responseMsg2));
1388
+ this.log?.warn(
1389
+ `'received handshake msg with incompatible existing session state: ${parsed.payload.sessionId}`,
1390
+ { ...conn.loggingMetadata, clientId: this.clientId }
1391
+ );
1392
+ this.protocolError(ProtocolError.HandshakeFailed, reason);
1393
+ return false;
1394
+ }
1395
+ session = existingSession;
1396
+ isTransparentReconnect = false;
1397
+ } else {
1398
+ const createdSession = this.createNewSession({
1399
+ to: parsed.from,
1400
+ conn,
1401
+ sessionId: parsed.payload.sessionId,
1402
+ propagationCtx: parsed.tracing
1403
+ });
1404
+ session = createdSession;
1405
+ isTransparentReconnect = false;
1406
+ }
1252
1407
  this.sessionHandshakeMetadata.set(session, parsedMetadata);
1253
1408
  this.log?.debug(
1254
1409
  `handshake from ${parsed.from} ok, responding with handshake success`,
1255
1410
  conn.loggingMetadata
1256
1411
  );
1257
- const responseMsg = handshakeResponseMessage(this.clientId, parsed.from, {
1258
- ok: true,
1259
- sessionId: session.id
1412
+ const responseMsg = handshakeResponseMessage({
1413
+ from: this.clientId,
1414
+ to: parsed.from,
1415
+ status: {
1416
+ ok: true,
1417
+ sessionId: session.id
1418
+ }
1260
1419
  });
1261
1420
  conn.send(this.codec.toBuffer(responseMsg));
1262
1421
  this.onConnect(conn, session, isTransparentReconnect);