@replit/river 0.23.12 → 0.23.14

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 (75) hide show
  1. package/dist/{chunk-3AW3IXVD.js → chunk-4PVU7J25.js} +1 -21
  2. package/dist/chunk-4PVU7J25.js.map +1 -0
  3. package/dist/{chunk-HDBVL7EF.js → chunk-BEALFLCB.js} +2 -2
  4. package/dist/chunk-D2DHRRBN.js +476 -0
  5. package/dist/chunk-D2DHRRBN.js.map +1 -0
  6. package/dist/{chunk-7RUKEUKE.js → chunk-GCCRVSMR.js} +33 -4
  7. package/dist/chunk-GCCRVSMR.js.map +1 -0
  8. package/dist/{chunk-XZ6IOBM5.js → chunk-GN4YEXT7.js} +2 -2
  9. package/dist/chunk-GN4YEXT7.js.map +1 -0
  10. package/dist/chunk-O2AVDJCQ.js +335 -0
  11. package/dist/chunk-O2AVDJCQ.js.map +1 -0
  12. package/dist/chunk-OTVTKAN6.js +451 -0
  13. package/dist/chunk-OTVTKAN6.js.map +1 -0
  14. package/dist/chunk-WUL63FR6.js +335 -0
  15. package/dist/chunk-WUL63FR6.js.map +1 -0
  16. package/dist/{chunk-H6KTH6W6.js → chunk-YCLZWES2.js} +2 -2
  17. package/dist/client-e13979ac.d.ts +52 -0
  18. package/dist/codec/index.js +20 -2
  19. package/dist/codec/index.js.map +1 -1
  20. package/dist/{connection-8debd45f.d.ts → connection-5d0978ce.d.ts} +1 -1
  21. package/dist/{connection-581558f8.d.ts → connection-e57e98ea.d.ts} +1 -1
  22. package/dist/{transport-47af1c81.d.ts → handshake-5665ffd3.d.ts} +101 -153
  23. package/dist/{index-60f03cb7.d.ts → index-ea74cdbb.d.ts} +1 -1
  24. package/dist/logging/index.d.cts +1 -1
  25. package/dist/logging/index.d.ts +1 -1
  26. package/dist/router/index.cjs +16 -1
  27. package/dist/router/index.cjs.map +1 -1
  28. package/dist/router/index.d.cts +8 -6
  29. package/dist/router/index.d.ts +8 -6
  30. package/dist/router/index.js +2 -2
  31. package/dist/server-1cfc88d1.d.ts +24 -0
  32. package/dist/{services-ca72c9f8.d.ts → services-86c4d10d.d.ts} +3 -2
  33. package/dist/transport/impls/uds/client.cjs +303 -180
  34. package/dist/transport/impls/uds/client.cjs.map +1 -1
  35. package/dist/transport/impls/uds/client.d.cts +6 -5
  36. package/dist/transport/impls/uds/client.d.ts +6 -5
  37. package/dist/transport/impls/uds/client.js +6 -4
  38. package/dist/transport/impls/uds/client.js.map +1 -1
  39. package/dist/transport/impls/uds/server.cjs +396 -234
  40. package/dist/transport/impls/uds/server.cjs.map +1 -1
  41. package/dist/transport/impls/uds/server.d.cts +6 -5
  42. package/dist/transport/impls/uds/server.d.ts +6 -5
  43. package/dist/transport/impls/uds/server.js +8 -6
  44. package/dist/transport/impls/uds/server.js.map +1 -1
  45. package/dist/transport/impls/ws/client.cjs +305 -182
  46. package/dist/transport/impls/ws/client.cjs.map +1 -1
  47. package/dist/transport/impls/ws/client.d.cts +6 -5
  48. package/dist/transport/impls/ws/client.d.ts +6 -5
  49. package/dist/transport/impls/ws/client.js +6 -4
  50. package/dist/transport/impls/ws/client.js.map +1 -1
  51. package/dist/transport/impls/ws/server.cjs +350 -188
  52. package/dist/transport/impls/ws/server.cjs.map +1 -1
  53. package/dist/transport/impls/ws/server.d.cts +4 -3
  54. package/dist/transport/impls/ws/server.d.ts +4 -3
  55. package/dist/transport/impls/ws/server.js +8 -6
  56. package/dist/transport/impls/ws/server.js.map +1 -1
  57. package/dist/transport/index.cjs +338 -142
  58. package/dist/transport/index.cjs.map +1 -1
  59. package/dist/transport/index.d.cts +4 -2
  60. package/dist/transport/index.d.ts +4 -2
  61. package/dist/transport/index.js +14 -8
  62. package/dist/util/testHelpers.cjs +10 -6
  63. package/dist/util/testHelpers.cjs.map +1 -1
  64. package/dist/util/testHelpers.d.cts +5 -4
  65. package/dist/util/testHelpers.d.ts +5 -4
  66. package/dist/util/testHelpers.js +4 -5
  67. package/dist/util/testHelpers.js.map +1 -1
  68. package/package.json +13 -14
  69. package/dist/chunk-3AW3IXVD.js.map +0 -1
  70. package/dist/chunk-7RUKEUKE.js.map +0 -1
  71. package/dist/chunk-VRU4IKRT.js +0 -1392
  72. package/dist/chunk-VRU4IKRT.js.map +0 -1
  73. package/dist/chunk-XZ6IOBM5.js.map +0 -1
  74. /package/dist/{chunk-HDBVL7EF.js.map → chunk-BEALFLCB.js.map} +0 -0
  75. /package/dist/{chunk-H6KTH6W6.js.map → chunk-YCLZWES2.js.map} +0 -0
@@ -24,8 +24,8 @@ __export(server_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(server_exports);
26
26
 
27
- // transport/transport.ts
28
- var import_value = require("@sinclair/typebox/value");
27
+ // transport/session.ts
28
+ var import_nanoid2 = require("nanoid");
29
29
 
30
30
  // transport/message.ts
31
31
  var import_typebox = require("@sinclair/typebox");
@@ -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,
@@ -102,104 +122,11 @@ function isAck(controlFlag) {
102
122
  return (controlFlag & 1 /* AckBit */) === 1 /* AckBit */;
103
123
  }
104
124
 
105
- // logging/log.ts
106
- var LoggingLevels = {
107
- debug: -1,
108
- info: 0,
109
- warn: 1,
110
- error: 2
111
- };
112
- var cleanedLogFn = (log) => {
113
- return (msg, metadata) => {
114
- if (!metadata?.transportMessage) {
115
- log(msg, metadata);
116
- return;
117
- }
118
- const { payload, ...rest } = metadata.transportMessage;
119
- metadata.transportMessage = rest;
120
- log(msg, metadata);
121
- };
122
- };
123
- var BaseLogger = class {
124
- minLevel;
125
- output;
126
- constructor(output, minLevel = "info") {
127
- this.minLevel = minLevel;
128
- this.output = output;
129
- }
130
- debug(msg, metadata) {
131
- if (LoggingLevels[this.minLevel] <= LoggingLevels.debug) {
132
- this.output(msg, metadata ?? {}, "debug");
133
- }
134
- }
135
- info(msg, metadata) {
136
- if (LoggingLevels[this.minLevel] <= LoggingLevels.info) {
137
- this.output(msg, metadata ?? {}, "info");
138
- }
139
- }
140
- warn(msg, metadata) {
141
- if (LoggingLevels[this.minLevel] <= LoggingLevels.warn) {
142
- this.output(msg, metadata ?? {}, "warn");
143
- }
144
- }
145
- error(msg, metadata) {
146
- if (LoggingLevels[this.minLevel] <= LoggingLevels.error) {
147
- this.output(msg, metadata ?? {}, "error");
148
- }
149
- }
150
- };
151
- var createLogProxy = (log) => ({
152
- debug: cleanedLogFn(log.debug.bind(log)),
153
- info: cleanedLogFn(log.info.bind(log)),
154
- warn: cleanedLogFn(log.warn.bind(log)),
155
- error: cleanedLogFn(log.error.bind(log))
156
- });
157
-
158
- // transport/events.ts
159
- var ProtocolError = {
160
- RetriesExceeded: "conn_retry_exceeded",
161
- HandshakeFailed: "handshake_failed",
162
- MessageOrderingViolated: "message_ordering_violated"
163
- };
164
- var EventDispatcher = class {
165
- eventListeners = {};
166
- removeAllListeners() {
167
- this.eventListeners = {};
168
- }
169
- numberOfListeners(eventType) {
170
- return this.eventListeners[eventType]?.size ?? 0;
171
- }
172
- addEventListener(eventType, handler) {
173
- if (!this.eventListeners[eventType]) {
174
- this.eventListeners[eventType] = /* @__PURE__ */ new Set();
175
- }
176
- this.eventListeners[eventType]?.add(handler);
177
- }
178
- removeEventListener(eventType, handler) {
179
- const handlers = this.eventListeners[eventType];
180
- if (handlers) {
181
- this.eventListeners[eventType]?.delete(handler);
182
- }
183
- }
184
- dispatchEvent(eventType, event) {
185
- const handlers = this.eventListeners[eventType];
186
- if (handlers) {
187
- const copy = [...handlers];
188
- for (const handler of copy) {
189
- handler(event);
190
- }
191
- }
192
- }
193
- };
194
-
195
- // transport/session.ts
196
- var import_nanoid2 = require("nanoid");
197
-
198
125
  // tracing/index.ts
199
126
  var import_api = require("@opentelemetry/api");
200
127
 
201
128
  // package.json
202
- var version = "0.23.12";
129
+ var version = "0.23.14";
203
130
 
204
131
  // tracing/index.ts
205
132
  function createSessionTelemetryInfo(session, propagationCtx) {
@@ -504,9 +431,17 @@ var Session = class {
504
431
  get connected() {
505
432
  return this.connection !== void 0;
506
433
  }
434
+ get nextExpectedAck() {
435
+ return this.seq;
436
+ }
507
437
  get nextExpectedSeq() {
508
438
  return this.ack;
509
439
  }
440
+ // This is only used in tests to make the session misbehave.
441
+ /* @internal */
442
+ advanceAckForTesting(by) {
443
+ this.ack += by;
444
+ }
510
445
  constructMsg(partialMsg) {
511
446
  const msg = {
512
447
  ...partialMsg,
@@ -525,13 +460,106 @@ var Session = class {
525
460
  }
526
461
  };
527
462
 
528
- // util/stringify.ts
529
- function coerceErrorString(err) {
530
- if (err instanceof Error) {
531
- return err.message || "unknown reason";
463
+ // transport/transforms/messageFraming.ts
464
+ var import_node_stream = require("stream");
465
+ var Uint32LengthPrefixFraming = class extends import_node_stream.Transform {
466
+ receivedBuffer;
467
+ maxBufferSizeBytes;
468
+ constructor({ maxBufferSizeBytes, ...options }) {
469
+ super(options);
470
+ this.maxBufferSizeBytes = maxBufferSizeBytes;
471
+ this.receivedBuffer = Buffer.alloc(0);
532
472
  }
533
- return `[coerced to error] ${String(err)}`;
473
+ _transform(chunk, _encoding, cb) {
474
+ if (this.receivedBuffer.byteLength + chunk.byteLength > this.maxBufferSizeBytes) {
475
+ const err = new Error(
476
+ `buffer overflow: ${this.receivedBuffer.byteLength}B > ${this.maxBufferSizeBytes}B`
477
+ );
478
+ this.emit("error", err);
479
+ cb(err);
480
+ return;
481
+ }
482
+ this.receivedBuffer = Buffer.concat([this.receivedBuffer, chunk]);
483
+ while (this.receivedBuffer.length > 4) {
484
+ const claimedMessageLength = this.receivedBuffer.readUInt32BE(0) + 4;
485
+ if (this.receivedBuffer.length >= claimedMessageLength) {
486
+ const message = this.receivedBuffer.subarray(4, claimedMessageLength);
487
+ this.push(message);
488
+ this.receivedBuffer = this.receivedBuffer.subarray(claimedMessageLength);
489
+ } else {
490
+ break;
491
+ }
492
+ }
493
+ cb();
494
+ }
495
+ _flush(cb) {
496
+ if (this.receivedBuffer.length) {
497
+ this.emit("error", new Error("got incomplete message while flushing"));
498
+ }
499
+ this.receivedBuffer = Buffer.alloc(0);
500
+ cb();
501
+ }
502
+ _destroy(error, callback) {
503
+ this.receivedBuffer = Buffer.alloc(0);
504
+ super._destroy(error, callback);
505
+ }
506
+ };
507
+ function createLengthEncodedStream(options) {
508
+ return new Uint32LengthPrefixFraming({
509
+ maxBufferSizeBytes: options?.maxBufferSizeBytes ?? 16 * 1024 * 1024
510
+ // 16MB
511
+ });
534
512
  }
513
+ var MessageFramer = {
514
+ createFramedStream: createLengthEncodedStream,
515
+ write: (buf) => {
516
+ const lengthPrefix = Buffer.alloc(4);
517
+ lengthPrefix.writeUInt32BE(buf.length, 0);
518
+ return Buffer.concat([lengthPrefix, buf]);
519
+ }
520
+ };
521
+
522
+ // transport/impls/uds/connection.ts
523
+ var UdsConnection = class extends Connection {
524
+ sock;
525
+ input;
526
+ framer;
527
+ constructor(sock) {
528
+ super();
529
+ this.framer = MessageFramer.createFramedStream();
530
+ this.sock = sock;
531
+ this.input = sock.pipe(this.framer);
532
+ }
533
+ addDataListener(cb) {
534
+ this.input.on("data", cb);
535
+ }
536
+ removeDataListener(cb) {
537
+ this.input.off("data", cb);
538
+ }
539
+ addCloseListener(cb) {
540
+ this.sock.on("close", cb);
541
+ }
542
+ addErrorListener(cb) {
543
+ this.sock.on("error", (err) => {
544
+ if (err instanceof Error && "code" in err && err.code === "EPIPE") {
545
+ return;
546
+ }
547
+ cb(err);
548
+ });
549
+ }
550
+ send(payload) {
551
+ if (this.framer.destroyed || !this.sock.writable)
552
+ return false;
553
+ return this.sock.write(MessageFramer.write(payload));
554
+ }
555
+ close() {
556
+ this.sock.destroy();
557
+ this.framer.destroy();
558
+ }
559
+ };
560
+
561
+ // transport/server.ts
562
+ var import_api4 = require("@opentelemetry/api");
535
563
 
536
564
  // codec/json.ts
537
565
  var encoder = new TextEncoder();
@@ -585,8 +613,7 @@ var NaiveJsonCodec = {
585
613
  }
586
614
  };
587
615
 
588
- // transport/transport.ts
589
- var import_api3 = require("@opentelemetry/api");
616
+ // transport/options.ts
590
617
  var defaultTransportOptions = {
591
618
  heartbeatIntervalMs: 1e3,
592
619
  heartbeatsUntilDead: 2,
@@ -607,6 +634,102 @@ var defaultClientTransportOptions = {
607
634
  var defaultServerTransportOptions = {
608
635
  ...defaultTransportOptions
609
636
  };
637
+
638
+ // transport/transport.ts
639
+ var import_value = require("@sinclair/typebox/value");
640
+
641
+ // logging/log.ts
642
+ var LoggingLevels = {
643
+ debug: -1,
644
+ info: 0,
645
+ warn: 1,
646
+ error: 2
647
+ };
648
+ var cleanedLogFn = (log) => {
649
+ return (msg, metadata) => {
650
+ if (!metadata?.transportMessage) {
651
+ log(msg, metadata);
652
+ return;
653
+ }
654
+ const { payload, ...rest } = metadata.transportMessage;
655
+ metadata.transportMessage = rest;
656
+ log(msg, metadata);
657
+ };
658
+ };
659
+ var BaseLogger = class {
660
+ minLevel;
661
+ output;
662
+ constructor(output, minLevel = "info") {
663
+ this.minLevel = minLevel;
664
+ this.output = output;
665
+ }
666
+ debug(msg, metadata) {
667
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.debug) {
668
+ this.output(msg, metadata ?? {}, "debug");
669
+ }
670
+ }
671
+ info(msg, metadata) {
672
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.info) {
673
+ this.output(msg, metadata ?? {}, "info");
674
+ }
675
+ }
676
+ warn(msg, metadata) {
677
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.warn) {
678
+ this.output(msg, metadata ?? {}, "warn");
679
+ }
680
+ }
681
+ error(msg, metadata) {
682
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.error) {
683
+ this.output(msg, metadata ?? {}, "error");
684
+ }
685
+ }
686
+ };
687
+ var createLogProxy = (log) => ({
688
+ debug: cleanedLogFn(log.debug.bind(log)),
689
+ info: cleanedLogFn(log.info.bind(log)),
690
+ warn: cleanedLogFn(log.warn.bind(log)),
691
+ error: cleanedLogFn(log.error.bind(log))
692
+ });
693
+
694
+ // transport/events.ts
695
+ var ProtocolError = {
696
+ RetriesExceeded: "conn_retry_exceeded",
697
+ HandshakeFailed: "handshake_failed",
698
+ MessageOrderingViolated: "message_ordering_violated"
699
+ };
700
+ var EventDispatcher = class {
701
+ eventListeners = {};
702
+ removeAllListeners() {
703
+ this.eventListeners = {};
704
+ }
705
+ numberOfListeners(eventType) {
706
+ return this.eventListeners[eventType]?.size ?? 0;
707
+ }
708
+ addEventListener(eventType, handler) {
709
+ if (!this.eventListeners[eventType]) {
710
+ this.eventListeners[eventType] = /* @__PURE__ */ new Set();
711
+ }
712
+ this.eventListeners[eventType]?.add(handler);
713
+ }
714
+ removeEventListener(eventType, handler) {
715
+ const handlers = this.eventListeners[eventType];
716
+ if (handlers) {
717
+ this.eventListeners[eventType]?.delete(handler);
718
+ }
719
+ }
720
+ dispatchEvent(eventType, event) {
721
+ const handlers = this.eventListeners[eventType];
722
+ if (handlers) {
723
+ const copy = [...handlers];
724
+ for (const handler of copy) {
725
+ handler(event);
726
+ }
727
+ }
728
+ }
729
+ };
730
+
731
+ // transport/transport.ts
732
+ var import_api3 = require("@opentelemetry/api");
610
733
  var Transport = class {
611
734
  /**
612
735
  * The status of the transport.
@@ -697,6 +820,49 @@ var Transport = class {
697
820
  });
698
821
  return session;
699
822
  }
823
+ createNewSession({
824
+ to,
825
+ conn,
826
+ sessionId,
827
+ propagationCtx
828
+ }) {
829
+ let session = this.sessions.get(to);
830
+ if (session !== void 0) {
831
+ this.log?.info(
832
+ `session for ${to} already exists, replacing it with a new session as requested`,
833
+ session.loggingMetadata
834
+ );
835
+ this.deleteSession({
836
+ session,
837
+ closeHandshakingConnection: false
838
+ });
839
+ session = void 0;
840
+ }
841
+ session = this.createSession(to, conn, propagationCtx);
842
+ session.advertisedSessionId = sessionId;
843
+ this.log?.info(`created new session for ${to}`, session.loggingMetadata);
844
+ return session;
845
+ }
846
+ getExistingSession({
847
+ to,
848
+ sessionId,
849
+ nextExpectedSeq
850
+ }) {
851
+ const session = this.sessions.get(to);
852
+ if (
853
+ // reject this request if there was no previous session to replace
854
+ session === void 0 || // or if both parties do not agree about the next expected sequence number
855
+ session.nextExpectedAck < nextExpectedSeq || // or if both parties do not agree on the advertised session id
856
+ session.advertisedSessionId !== sessionId
857
+ ) {
858
+ return false;
859
+ }
860
+ this.log?.info(
861
+ `reused existing session for ${to}`,
862
+ session.loggingMetadata
863
+ );
864
+ return session;
865
+ }
700
866
  getOrCreateSession({
701
867
  to,
702
868
  conn,
@@ -761,6 +927,16 @@ var Transport = class {
761
927
  * @param connectedTo The peer we are connected to.
762
928
  */
763
929
  onDisconnect(conn, session) {
930
+ if (session.connection !== void 0 && session.connection.id !== conn.id) {
931
+ session.telemetry.span.addEvent("onDisconnect race");
932
+ this.log?.warn("onDisconnect race", {
933
+ clientId: this.clientId,
934
+ ...session.loggingMetadata,
935
+ ...conn.loggingMetadata,
936
+ tags: ["invariant-violation"]
937
+ });
938
+ return;
939
+ }
764
940
  conn.telemetry?.span.end();
765
941
  this.eventDispatcher.dispatchEvent("connectionStatus", {
766
942
  status: "disconnect",
@@ -768,6 +944,16 @@ var Transport = class {
768
944
  });
769
945
  session.connection = void 0;
770
946
  session.beginGrace(() => {
947
+ if (session.connection !== void 0) {
948
+ session.telemetry.span.addEvent("session grace period race");
949
+ this.log?.warn("session grace period race", {
950
+ clientId: this.clientId,
951
+ ...session.loggingMetadata,
952
+ ...conn.loggingMetadata,
953
+ tags: ["invariant-violation"]
954
+ });
955
+ return;
956
+ }
771
957
  session.telemetry.span.addEvent("session grace period expired");
772
958
  this.deleteSession({
773
959
  session,
@@ -935,6 +1121,17 @@ var Transport = class {
935
1121
  return this.status;
936
1122
  }
937
1123
  };
1124
+
1125
+ // util/stringify.ts
1126
+ function coerceErrorString(err) {
1127
+ if (err instanceof Error) {
1128
+ return err.message || "unknown reason";
1129
+ }
1130
+ return `[coerced to error] ${String(err)}`;
1131
+ }
1132
+
1133
+ // transport/server.ts
1134
+ var import_value2 = require("@sinclair/typebox/value");
938
1135
  var ServerTransport = class extends Transport {
939
1136
  /**
940
1137
  * The options for this transport.
@@ -983,7 +1180,7 @@ var ServerTransport = class extends Transport {
983
1180
  }
984
1181
  );
985
1182
  conn.telemetry?.span.setStatus({
986
- code: import_api3.SpanStatusCode.ERROR,
1183
+ code: import_api4.SpanStatusCode.ERROR,
987
1184
  message: "handshake timeout"
988
1185
  });
989
1186
  conn.close();
@@ -1034,7 +1231,7 @@ var ServerTransport = class extends Transport {
1034
1231
  });
1035
1232
  conn.addErrorListener((err) => {
1036
1233
  conn.telemetry?.span.setStatus({
1037
- code: import_api3.SpanStatusCode.ERROR,
1234
+ code: import_api4.SpanStatusCode.ERROR,
1038
1235
  message: "connection error"
1039
1236
  });
1040
1237
  if (!session)
@@ -1048,22 +1245,26 @@ var ServerTransport = class extends Transport {
1048
1245
  async validateHandshakeMetadata(conn, session, rawMetadata, from) {
1049
1246
  let parsedMetadata = {};
1050
1247
  if (this.handshakeExtensions) {
1051
- if (!import_value.Value.Check(this.handshakeExtensions.schema, rawMetadata)) {
1248
+ if (!import_value2.Value.Check(this.handshakeExtensions.schema, rawMetadata)) {
1052
1249
  conn.telemetry?.span.setStatus({
1053
- code: import_api3.SpanStatusCode.ERROR,
1250
+ code: import_api4.SpanStatusCode.ERROR,
1054
1251
  message: "malformed handshake meta"
1055
1252
  });
1056
1253
  const reason = "received malformed handshake metadata";
1057
- const responseMsg = handshakeResponseMessage(this.clientId, from, {
1058
- ok: false,
1059
- reason
1254
+ const responseMsg = handshakeResponseMessage({
1255
+ from: this.clientId,
1256
+ to: from,
1257
+ status: {
1258
+ ok: false,
1259
+ reason
1260
+ }
1060
1261
  });
1061
1262
  conn.send(this.codec.toBuffer(responseMsg));
1062
1263
  this.log?.warn(`received malformed handshake metadata from ${from}`, {
1063
1264
  ...conn.loggingMetadata,
1064
1265
  clientId: this.clientId,
1065
1266
  validationErrors: [
1066
- ...import_value.Value.Errors(this.handshakeExtensions.schema, rawMetadata)
1267
+ ...import_value2.Value.Errors(this.handshakeExtensions.schema, rawMetadata)
1067
1268
  ]
1068
1269
  });
1069
1270
  this.protocolError(ProtocolError.HandshakeFailed, reason);
@@ -1077,12 +1278,16 @@ var ServerTransport = class extends Transport {
1077
1278
  if (parsedMetadata === false) {
1078
1279
  const reason = "rejected by handshake handler";
1079
1280
  conn.telemetry?.span.setStatus({
1080
- code: import_api3.SpanStatusCode.ERROR,
1281
+ code: import_api4.SpanStatusCode.ERROR,
1081
1282
  message: reason
1082
1283
  });
1083
- const responseMsg = handshakeResponseMessage(this.clientId, from, {
1084
- ok: false,
1085
- reason
1284
+ const responseMsg = handshakeResponseMessage({
1285
+ from: this.clientId,
1286
+ to: from,
1287
+ status: {
1288
+ ok: false,
1289
+ reason
1290
+ }
1086
1291
  });
1087
1292
  conn.send(this.codec.toBuffer(responseMsg));
1088
1293
  this.log?.warn(`rejected handshake from ${from}`, {
@@ -1099,7 +1304,7 @@ var ServerTransport = class extends Transport {
1099
1304
  const parsed = this.parseMsg(data, conn);
1100
1305
  if (!parsed) {
1101
1306
  conn.telemetry?.span.setStatus({
1102
- code: import_api3.SpanStatusCode.ERROR,
1307
+ code: import_api4.SpanStatusCode.ERROR,
1103
1308
  message: "non-transport message"
1104
1309
  });
1105
1310
  this.protocolError(
@@ -1108,15 +1313,19 @@ var ServerTransport = class extends Transport {
1108
1313
  );
1109
1314
  return false;
1110
1315
  }
1111
- if (!import_value.Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
1316
+ if (!import_value2.Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
1112
1317
  conn.telemetry?.span.setStatus({
1113
- code: import_api3.SpanStatusCode.ERROR,
1318
+ code: import_api4.SpanStatusCode.ERROR,
1114
1319
  message: "invalid handshake request"
1115
1320
  });
1116
1321
  const reason = "received invalid handshake msg";
1117
- const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1118
- ok: false,
1119
- reason
1322
+ const responseMsg2 = handshakeResponseMessage({
1323
+ from: this.clientId,
1324
+ to: parsed.from,
1325
+ status: {
1326
+ ok: false,
1327
+ reason
1328
+ }
1120
1329
  });
1121
1330
  conn.send(this.codec.toBuffer(responseMsg2));
1122
1331
  this.log?.warn(reason, {
@@ -1126,7 +1335,7 @@ var ServerTransport = class extends Transport {
1126
1335
  // before passing it to user-land
1127
1336
  transportMessage: parsed,
1128
1337
  validationErrors: [
1129
- ...import_value.Value.Errors(ControlMessageHandshakeRequestSchema, parsed.payload)
1338
+ ...import_value2.Value.Errors(ControlMessageHandshakeRequestSchema, parsed.payload)
1130
1339
  ]
1131
1340
  });
1132
1341
  this.protocolError(
@@ -1138,13 +1347,17 @@ var ServerTransport = class extends Transport {
1138
1347
  const gotVersion = parsed.payload.protocolVersion;
1139
1348
  if (gotVersion !== PROTOCOL_VERSION) {
1140
1349
  conn.telemetry?.span.setStatus({
1141
- code: import_api3.SpanStatusCode.ERROR,
1350
+ code: import_api4.SpanStatusCode.ERROR,
1142
1351
  message: "incorrect protocol version"
1143
1352
  });
1144
1353
  const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
1145
- const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1146
- ok: false,
1147
- reason
1354
+ const responseMsg2 = handshakeResponseMessage({
1355
+ from: this.clientId,
1356
+ to: parsed.from,
1357
+ status: {
1358
+ ok: false,
1359
+ reason
1360
+ }
1148
1361
  });
1149
1362
  conn.send(this.codec.toBuffer(responseMsg2));
1150
1363
  this.log?.warn(
@@ -1164,20 +1377,67 @@ var ServerTransport = class extends Transport {
1164
1377
  if (parsedMetadata === false) {
1165
1378
  return false;
1166
1379
  }
1167
- const { session, isTransparentReconnect } = this.getOrCreateSession({
1168
- to: parsed.from,
1169
- conn,
1170
- sessionId: parsed.payload.sessionId,
1171
- propagationCtx: parsed.tracing
1172
- });
1380
+ let session;
1381
+ let isTransparentReconnect;
1382
+ if (!parsed.payload.expectedSessionState) {
1383
+ ({ session, isTransparentReconnect } = this.getOrCreateSession({
1384
+ to: parsed.from,
1385
+ conn,
1386
+ sessionId: parsed.payload.sessionId,
1387
+ propagationCtx: parsed.tracing
1388
+ }));
1389
+ } else if (parsed.payload.expectedSessionState.reconnect) {
1390
+ const existingSession = this.getExistingSession({
1391
+ to: parsed.from,
1392
+ sessionId: parsed.payload.sessionId,
1393
+ nextExpectedSeq: parsed.payload.expectedSessionState.nextExpectedSeq
1394
+ });
1395
+ if (existingSession === false) {
1396
+ conn.telemetry?.span.setStatus({
1397
+ code: import_api4.SpanStatusCode.ERROR,
1398
+ message: SESSION_STATE_MISMATCH
1399
+ });
1400
+ const reason = SESSION_STATE_MISMATCH;
1401
+ const responseMsg2 = handshakeResponseMessage({
1402
+ from: this.clientId,
1403
+ to: parsed.from,
1404
+ status: {
1405
+ ok: false,
1406
+ reason
1407
+ }
1408
+ });
1409
+ conn.send(this.codec.toBuffer(responseMsg2));
1410
+ this.log?.warn(
1411
+ `'received handshake msg with incompatible existing session state: ${parsed.payload.sessionId}`,
1412
+ { ...conn.loggingMetadata, clientId: this.clientId }
1413
+ );
1414
+ this.protocolError(ProtocolError.HandshakeFailed, reason);
1415
+ return false;
1416
+ }
1417
+ session = existingSession;
1418
+ isTransparentReconnect = false;
1419
+ } else {
1420
+ const createdSession = this.createNewSession({
1421
+ to: parsed.from,
1422
+ conn,
1423
+ sessionId: parsed.payload.sessionId,
1424
+ propagationCtx: parsed.tracing
1425
+ });
1426
+ session = createdSession;
1427
+ isTransparentReconnect = false;
1428
+ }
1173
1429
  this.sessionHandshakeMetadata.set(session, parsedMetadata);
1174
1430
  this.log?.debug(
1175
1431
  `handshake from ${parsed.from} ok, responding with handshake success`,
1176
1432
  conn.loggingMetadata
1177
1433
  );
1178
- const responseMsg = handshakeResponseMessage(this.clientId, parsed.from, {
1179
- ok: true,
1180
- sessionId: session.id
1434
+ const responseMsg = handshakeResponseMessage({
1435
+ from: this.clientId,
1436
+ to: parsed.from,
1437
+ status: {
1438
+ ok: true,
1439
+ sessionId: session.id
1440
+ }
1181
1441
  });
1182
1442
  conn.send(this.codec.toBuffer(responseMsg));
1183
1443
  this.onConnect(conn, session, isTransparentReconnect);
@@ -1185,104 +1445,6 @@ var ServerTransport = class extends Transport {
1185
1445
  }
1186
1446
  };
1187
1447
 
1188
- // transport/transforms/messageFraming.ts
1189
- var import_node_stream = require("stream");
1190
- var Uint32LengthPrefixFraming = class extends import_node_stream.Transform {
1191
- receivedBuffer;
1192
- maxBufferSizeBytes;
1193
- constructor({ maxBufferSizeBytes, ...options }) {
1194
- super(options);
1195
- this.maxBufferSizeBytes = maxBufferSizeBytes;
1196
- this.receivedBuffer = Buffer.alloc(0);
1197
- }
1198
- _transform(chunk, _encoding, cb) {
1199
- if (this.receivedBuffer.byteLength + chunk.byteLength > this.maxBufferSizeBytes) {
1200
- const err = new Error(
1201
- `buffer overflow: ${this.receivedBuffer.byteLength}B > ${this.maxBufferSizeBytes}B`
1202
- );
1203
- this.emit("error", err);
1204
- cb(err);
1205
- return;
1206
- }
1207
- this.receivedBuffer = Buffer.concat([this.receivedBuffer, chunk]);
1208
- while (this.receivedBuffer.length > 4) {
1209
- const claimedMessageLength = this.receivedBuffer.readUInt32BE(0) + 4;
1210
- if (this.receivedBuffer.length >= claimedMessageLength) {
1211
- const message = this.receivedBuffer.subarray(4, claimedMessageLength);
1212
- this.push(message);
1213
- this.receivedBuffer = this.receivedBuffer.subarray(claimedMessageLength);
1214
- } else {
1215
- break;
1216
- }
1217
- }
1218
- cb();
1219
- }
1220
- _flush(cb) {
1221
- if (this.receivedBuffer.length) {
1222
- this.emit("error", new Error("got incomplete message while flushing"));
1223
- }
1224
- this.receivedBuffer = Buffer.alloc(0);
1225
- cb();
1226
- }
1227
- _destroy(error, callback) {
1228
- this.receivedBuffer = Buffer.alloc(0);
1229
- super._destroy(error, callback);
1230
- }
1231
- };
1232
- function createLengthEncodedStream(options) {
1233
- return new Uint32LengthPrefixFraming({
1234
- maxBufferSizeBytes: options?.maxBufferSizeBytes ?? 16 * 1024 * 1024
1235
- // 16MB
1236
- });
1237
- }
1238
- var MessageFramer = {
1239
- createFramedStream: createLengthEncodedStream,
1240
- write: (buf) => {
1241
- const lengthPrefix = Buffer.alloc(4);
1242
- lengthPrefix.writeUInt32BE(buf.length, 0);
1243
- return Buffer.concat([lengthPrefix, buf]);
1244
- }
1245
- };
1246
-
1247
- // transport/impls/uds/connection.ts
1248
- var UdsConnection = class extends Connection {
1249
- sock;
1250
- input;
1251
- framer;
1252
- constructor(sock) {
1253
- super();
1254
- this.framer = MessageFramer.createFramedStream();
1255
- this.sock = sock;
1256
- this.input = sock.pipe(this.framer);
1257
- }
1258
- addDataListener(cb) {
1259
- this.input.on("data", cb);
1260
- }
1261
- removeDataListener(cb) {
1262
- this.input.off("data", cb);
1263
- }
1264
- addCloseListener(cb) {
1265
- this.sock.on("close", cb);
1266
- }
1267
- addErrorListener(cb) {
1268
- this.sock.on("error", (err) => {
1269
- if (err instanceof Error && "code" in err && err.code === "EPIPE") {
1270
- return;
1271
- }
1272
- cb(err);
1273
- });
1274
- }
1275
- send(payload) {
1276
- if (this.framer.destroyed || !this.sock.writable)
1277
- return false;
1278
- return this.sock.write(MessageFramer.write(payload));
1279
- }
1280
- close() {
1281
- this.sock.destroy();
1282
- this.framer.destroy();
1283
- }
1284
- };
1285
-
1286
1448
  // transport/impls/uds/server.ts
1287
1449
  var UnixDomainSocketServerTransport = class extends ServerTransport {
1288
1450
  server;