@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,
@@ -785,6 +813,20 @@ var Transport = class {
785
813
  if (this.log) {
786
814
  session.bindLogger(this.log);
787
815
  }
816
+ const currentSession = this.sessions.get(session.to);
817
+ if (currentSession) {
818
+ this.log?.warn(
819
+ `session ${session.id} from ${session.to} surreptitiously replacing ${currentSession.id}`,
820
+ {
821
+ ...currentSession.loggingMetadata,
822
+ tags: ["invariant-violation"]
823
+ }
824
+ );
825
+ this.deleteSession({
826
+ session: currentSession,
827
+ closeHandshakingConnection: false
828
+ });
829
+ }
788
830
  this.sessions.set(session.to, session);
789
831
  this.eventDispatcher.dispatchEvent("sessionStatus", {
790
832
  status: "connect",
@@ -792,6 +834,49 @@ var Transport = class {
792
834
  });
793
835
  return session;
794
836
  }
837
+ createNewSession({
838
+ to,
839
+ conn,
840
+ sessionId,
841
+ propagationCtx
842
+ }) {
843
+ let session = this.sessions.get(to);
844
+ if (session !== void 0) {
845
+ this.log?.info(
846
+ `session for ${to} already exists, replacing it with a new session as requested`,
847
+ session.loggingMetadata
848
+ );
849
+ this.deleteSession({
850
+ session,
851
+ closeHandshakingConnection: false
852
+ });
853
+ session = void 0;
854
+ }
855
+ session = this.createSession(to, conn, propagationCtx);
856
+ session.advertisedSessionId = sessionId;
857
+ this.log?.info(`created new session for ${to}`, session.loggingMetadata);
858
+ return session;
859
+ }
860
+ getExistingSession({
861
+ to,
862
+ sessionId,
863
+ nextExpectedSeq
864
+ }) {
865
+ const session = this.sessions.get(to);
866
+ if (
867
+ // reject this request if there was no previous session to replace
868
+ session === void 0 || // or if both parties do not agree about the next expected sequence number
869
+ session.nextExpectedAck < nextExpectedSeq || // or if both parties do not agree on the advertised session id
870
+ session.advertisedSessionId !== sessionId
871
+ ) {
872
+ return false;
873
+ }
874
+ this.log?.info(
875
+ `reused existing session for ${to}`,
876
+ session.loggingMetadata
877
+ );
878
+ return session;
879
+ }
795
880
  getOrCreateSession({
796
881
  to,
797
882
  conn,
@@ -840,6 +925,17 @@ var Transport = class {
840
925
  }
841
926
  session.close();
842
927
  session.telemetry.span.end();
928
+ const currentSession = this.sessions.get(session.to);
929
+ if (currentSession && currentSession.id !== session.id) {
930
+ this.log?.warn(
931
+ `session ${session.id} disconnect from ${session.to}, mismatch with ${currentSession.id}`,
932
+ {
933
+ ...session.loggingMetadata,
934
+ tags: ["invariant-violation"]
935
+ }
936
+ );
937
+ return;
938
+ }
843
939
  this.sessions.delete(session.to);
844
940
  this.log?.info(
845
941
  `session ${session.id} disconnect from ${session.to}`,
@@ -1180,9 +1276,13 @@ var ServerTransport = class extends Transport {
1180
1276
  message: "malformed handshake meta"
1181
1277
  });
1182
1278
  const reason = "received malformed handshake metadata";
1183
- const responseMsg = handshakeResponseMessage(this.clientId, from, {
1184
- ok: false,
1185
- reason
1279
+ const responseMsg = handshakeResponseMessage({
1280
+ from: this.clientId,
1281
+ to: from,
1282
+ status: {
1283
+ ok: false,
1284
+ reason
1285
+ }
1186
1286
  });
1187
1287
  conn.send(this.codec.toBuffer(responseMsg));
1188
1288
  this.log?.warn(`received malformed handshake metadata from ${from}`, {
@@ -1206,9 +1306,13 @@ var ServerTransport = class extends Transport {
1206
1306
  code: import_api4.SpanStatusCode.ERROR,
1207
1307
  message: reason
1208
1308
  });
1209
- const responseMsg = handshakeResponseMessage(this.clientId, from, {
1210
- ok: false,
1211
- reason
1309
+ const responseMsg = handshakeResponseMessage({
1310
+ from: this.clientId,
1311
+ to: from,
1312
+ status: {
1313
+ ok: false,
1314
+ reason
1315
+ }
1212
1316
  });
1213
1317
  conn.send(this.codec.toBuffer(responseMsg));
1214
1318
  this.log?.warn(`rejected handshake from ${from}`, {
@@ -1240,9 +1344,13 @@ var ServerTransport = class extends Transport {
1240
1344
  message: "invalid handshake request"
1241
1345
  });
1242
1346
  const reason = "received invalid handshake msg";
1243
- const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1244
- ok: false,
1245
- reason
1347
+ const responseMsg2 = handshakeResponseMessage({
1348
+ from: this.clientId,
1349
+ to: parsed.from,
1350
+ status: {
1351
+ ok: false,
1352
+ reason
1353
+ }
1246
1354
  });
1247
1355
  conn.send(this.codec.toBuffer(responseMsg2));
1248
1356
  this.log?.warn(reason, {
@@ -1268,9 +1376,13 @@ var ServerTransport = class extends Transport {
1268
1376
  message: "incorrect protocol version"
1269
1377
  });
1270
1378
  const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
1271
- const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1272
- ok: false,
1273
- reason
1379
+ const responseMsg2 = handshakeResponseMessage({
1380
+ from: this.clientId,
1381
+ to: parsed.from,
1382
+ status: {
1383
+ ok: false,
1384
+ reason
1385
+ }
1274
1386
  });
1275
1387
  conn.send(this.codec.toBuffer(responseMsg2));
1276
1388
  this.log?.warn(
@@ -1290,20 +1402,67 @@ var ServerTransport = class extends Transport {
1290
1402
  if (parsedMetadata === false) {
1291
1403
  return false;
1292
1404
  }
1293
- const { session, isTransparentReconnect } = this.getOrCreateSession({
1294
- to: parsed.from,
1295
- conn,
1296
- sessionId: parsed.payload.sessionId,
1297
- propagationCtx: parsed.tracing
1298
- });
1405
+ let session;
1406
+ let isTransparentReconnect;
1407
+ if (!parsed.payload.expectedSessionState) {
1408
+ ({ session, isTransparentReconnect } = this.getOrCreateSession({
1409
+ to: parsed.from,
1410
+ conn,
1411
+ sessionId: parsed.payload.sessionId,
1412
+ propagationCtx: parsed.tracing
1413
+ }));
1414
+ } else if (parsed.payload.expectedSessionState.reconnect) {
1415
+ const existingSession = this.getExistingSession({
1416
+ to: parsed.from,
1417
+ sessionId: parsed.payload.sessionId,
1418
+ nextExpectedSeq: parsed.payload.expectedSessionState.nextExpectedSeq
1419
+ });
1420
+ if (existingSession === false) {
1421
+ conn.telemetry?.span.setStatus({
1422
+ code: import_api4.SpanStatusCode.ERROR,
1423
+ message: SESSION_STATE_MISMATCH
1424
+ });
1425
+ const reason = SESSION_STATE_MISMATCH;
1426
+ const responseMsg2 = handshakeResponseMessage({
1427
+ from: this.clientId,
1428
+ to: parsed.from,
1429
+ status: {
1430
+ ok: false,
1431
+ reason
1432
+ }
1433
+ });
1434
+ conn.send(this.codec.toBuffer(responseMsg2));
1435
+ this.log?.warn(
1436
+ `'received handshake msg with incompatible existing session state: ${parsed.payload.sessionId}`,
1437
+ { ...conn.loggingMetadata, clientId: this.clientId }
1438
+ );
1439
+ this.protocolError(ProtocolError.HandshakeFailed, reason);
1440
+ return false;
1441
+ }
1442
+ session = existingSession;
1443
+ isTransparentReconnect = false;
1444
+ } else {
1445
+ const createdSession = this.createNewSession({
1446
+ to: parsed.from,
1447
+ conn,
1448
+ sessionId: parsed.payload.sessionId,
1449
+ propagationCtx: parsed.tracing
1450
+ });
1451
+ session = createdSession;
1452
+ isTransparentReconnect = false;
1453
+ }
1299
1454
  this.sessionHandshakeMetadata.set(session, parsedMetadata);
1300
1455
  this.log?.debug(
1301
1456
  `handshake from ${parsed.from} ok, responding with handshake success`,
1302
1457
  conn.loggingMetadata
1303
1458
  );
1304
- const responseMsg = handshakeResponseMessage(this.clientId, parsed.from, {
1305
- ok: true,
1306
- sessionId: session.id
1459
+ const responseMsg = handshakeResponseMessage({
1460
+ from: this.clientId,
1461
+ to: parsed.from,
1462
+ status: {
1463
+ ok: true,
1464
+ sessionId: session.id
1465
+ }
1307
1466
  });
1308
1467
  conn.send(this.codec.toBuffer(responseMsg));
1309
1468
  this.onConnect(conn, session, isTransparentReconnect);