@replit/river 0.12.6 → 0.13.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 (51) hide show
  1. package/README.md +6 -1
  2. package/dist/{builder-c593de11.d.ts → builder-eef3b061.d.ts} +16 -7
  3. package/dist/{chunk-AFLZ6INU.js → chunk-JXKTY3GQ.js} +77 -49
  4. package/dist/{chunk-IIBVKYDB.js → chunk-JXO2SCQB.js} +39 -1
  5. package/dist/{chunk-4SDJ5VN4.js → chunk-LDUFHGZU.js} +150 -116
  6. package/dist/{chunk-VLBVQX5H.js → chunk-Q7AWJYDQ.js} +1 -1
  7. package/dist/{chunk-XFFS4UOD.js → chunk-SCG5S2EC.js} +9 -9
  8. package/dist/{messageFraming-b200ef25.d.ts → connection-03e650c8.d.ts} +17 -2
  9. package/dist/{connection-ba37d174.d.ts → connection-d052d027.d.ts} +1 -1
  10. package/dist/{index-54e0f99c.d.ts → index-9aa0aabb.d.ts} +29 -39
  11. package/dist/router/index.cjs +83 -56
  12. package/dist/router/index.d.cts +5 -5
  13. package/dist/router/index.d.ts +5 -5
  14. package/dist/router/index.js +2 -2
  15. package/dist/transport/impls/uds/client.cjs +144 -122
  16. package/dist/transport/impls/uds/client.d.cts +2 -3
  17. package/dist/transport/impls/uds/client.d.ts +2 -3
  18. package/dist/transport/impls/uds/client.js +5 -6
  19. package/dist/transport/impls/uds/server.cjs +153 -129
  20. package/dist/transport/impls/uds/server.d.cts +2 -3
  21. package/dist/transport/impls/uds/server.d.ts +2 -3
  22. package/dist/transport/impls/uds/server.js +4 -5
  23. package/dist/transport/impls/ws/client.cjs +151 -134
  24. package/dist/transport/impls/ws/client.d.cts +4 -4
  25. package/dist/transport/impls/ws/client.d.ts +4 -4
  26. package/dist/transport/impls/ws/client.js +10 -17
  27. package/dist/transport/impls/ws/server.cjs +153 -129
  28. package/dist/transport/impls/ws/server.d.cts +2 -2
  29. package/dist/transport/impls/ws/server.d.ts +2 -2
  30. package/dist/transport/impls/ws/server.js +4 -4
  31. package/dist/transport/index.cjs +204 -169
  32. package/dist/transport/index.d.cts +1 -1
  33. package/dist/transport/index.d.ts +1 -1
  34. package/dist/transport/index.js +3 -3
  35. package/dist/util/testHelpers.cjs +294 -16
  36. package/dist/util/testHelpers.d.cts +2 -2
  37. package/dist/util/testHelpers.d.ts +2 -2
  38. package/dist/util/testHelpers.js +30 -8
  39. package/package.json +1 -9
  40. package/dist/chunk-PBPXYLI6.js +0 -44
  41. package/dist/chunk-Q7GL34DZ.js +0 -47
  42. package/dist/connection-1f9971d8.d.ts +0 -17
  43. package/dist/connection-24d878ac.d.ts +0 -18
  44. package/dist/transport/impls/stdio/client.cjs +0 -904
  45. package/dist/transport/impls/stdio/client.d.cts +0 -27
  46. package/dist/transport/impls/stdio/client.d.ts +0 -27
  47. package/dist/transport/impls/stdio/client.js +0 -42
  48. package/dist/transport/impls/stdio/server.cjs +0 -879
  49. package/dist/transport/impls/stdio/server.d.cts +0 -25
  50. package/dist/transport/impls/stdio/server.d.ts +0 -25
  51. package/dist/transport/impls/stdio/server.js +0 -33
@@ -39,8 +39,8 @@ var TransportMessageSchema = (t) => import_typebox.Type.Object({
39
39
  to: import_typebox.Type.String(),
40
40
  seq: import_typebox.Type.Integer(),
41
41
  ack: import_typebox.Type.Integer(),
42
- serviceName: import_typebox.Type.Optional(import_typebox.Type.Union([import_typebox.Type.String(), import_typebox.Type.Null()])),
43
- procedureName: import_typebox.Type.Optional(import_typebox.Type.Union([import_typebox.Type.String(), import_typebox.Type.Null()])),
42
+ serviceName: import_typebox.Type.Optional(import_typebox.Type.String()),
43
+ procedureName: import_typebox.Type.Optional(import_typebox.Type.String()),
44
44
  streamId: import_typebox.Type.String(),
45
45
  controlFlags: import_typebox.Type.Integer(),
46
46
  payload: t
@@ -54,7 +54,7 @@ var ControlMessageCloseSchema = import_typebox.Type.Object({
54
54
  var PROTOCOL_VERSION = "v1";
55
55
  var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
56
56
  type: import_typebox.Type.Literal("HANDSHAKE_REQ"),
57
- protocolVersion: import_typebox.Type.Literal(PROTOCOL_VERSION),
57
+ protocolVersion: import_typebox.Type.String(),
58
58
  instanceId: import_typebox.Type.String()
59
59
  });
60
60
  var ControlMessageHandshakeResponseSchema = import_typebox.Type.Object({
@@ -66,7 +66,7 @@ var ControlMessageHandshakeResponseSchema = import_typebox.Type.Object({
66
66
  }),
67
67
  import_typebox.Type.Object({
68
68
  ok: import_typebox.Type.Literal(false),
69
- reason: import_typebox.Type.Union([import_typebox.Type.Literal("VERSION_MISMATCH")])
69
+ reason: import_typebox.Type.String()
70
70
  })
71
71
  ])
72
72
  });
@@ -79,7 +79,7 @@ var ControlMessagePayloadSchema = import_typebox.Type.Union([
79
79
  var OpaqueTransportMessageSchema = TransportMessageSchema(
80
80
  import_typebox.Type.Unknown()
81
81
  );
82
- function bootResponseMessage(from, instanceId, to, ok) {
82
+ function handshakeResponseMessage(from, instanceId, to, ok, reason) {
83
83
  return {
84
84
  id: (0, import_nanoid.nanoid)(),
85
85
  from,
@@ -98,7 +98,7 @@ function bootResponseMessage(from, instanceId, to, ok) {
98
98
  type: "HANDSHAKE_RESP",
99
99
  status: {
100
100
  ok: false,
101
- reason: "VERSION_MISMATCH"
101
+ reason: reason ?? "Unknown reason"
102
102
  }
103
103
  }
104
104
  };
@@ -137,6 +137,60 @@ var EventDispatcher = class {
137
137
 
138
138
  // transport/session.ts
139
139
  var import_nanoid2 = require("nanoid");
140
+
141
+ // codec/json.ts
142
+ var encoder = new TextEncoder();
143
+ var decoder = new TextDecoder();
144
+ function uint8ArrayToBase64(uint8Array) {
145
+ let binary = "";
146
+ uint8Array.forEach((byte) => {
147
+ binary += String.fromCharCode(byte);
148
+ });
149
+ return btoa(binary);
150
+ }
151
+ function base64ToUint8Array(base64) {
152
+ const binaryString = atob(base64);
153
+ const uint8Array = new Uint8Array(binaryString.length);
154
+ for (let i = 0; i < binaryString.length; i++) {
155
+ uint8Array[i] = binaryString.charCodeAt(i);
156
+ }
157
+ return uint8Array;
158
+ }
159
+ var NaiveJsonCodec = {
160
+ toBuffer: (obj) => {
161
+ return encoder.encode(
162
+ JSON.stringify(obj, function replacer(key) {
163
+ const val = this[key];
164
+ if (val instanceof Uint8Array) {
165
+ return { $t: uint8ArrayToBase64(val) };
166
+ } else {
167
+ return val;
168
+ }
169
+ })
170
+ );
171
+ },
172
+ fromBuffer: (buff) => {
173
+ try {
174
+ const parsed = JSON.parse(
175
+ decoder.decode(buff),
176
+ function reviver(_key, val) {
177
+ if (val?.$t) {
178
+ return base64ToUint8Array(val.$t);
179
+ } else {
180
+ return val;
181
+ }
182
+ }
183
+ );
184
+ if (typeof parsed === "object")
185
+ return parsed;
186
+ return null;
187
+ } catch {
188
+ return null;
189
+ }
190
+ }
191
+ };
192
+
193
+ // transport/session.ts
140
194
  var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
141
195
  var unsafeId = () => nanoid2();
142
196
  var Connection = class {
@@ -148,8 +202,15 @@ var Connection = class {
148
202
  var HEARTBEAT_INTERVAL_MS = 1e3;
149
203
  var HEARTBEATS_TILL_DEAD = 2;
150
204
  var SESSION_DISCONNECT_GRACE_MS = 5e3;
205
+ var defaultSessionOptions = {
206
+ heartbeatIntervalMs: HEARTBEAT_INTERVAL_MS,
207
+ heartbeatsUntilDead: HEARTBEATS_TILL_DEAD,
208
+ sessionDisconnectGraceMs: SESSION_DISCONNECT_GRACE_MS,
209
+ codec: NaiveJsonCodec
210
+ };
151
211
  var Session = class {
152
212
  codec;
213
+ options;
153
214
  /**
154
215
  * The buffer of messages that have been sent but not yet acknowledged.
155
216
  */
@@ -185,16 +246,17 @@ var Session = class {
185
246
  * The interval for sending heartbeats.
186
247
  */
187
248
  heartbeat;
188
- constructor(codec, from, connectedTo, conn) {
249
+ constructor(from, connectedTo, conn, options) {
250
+ this.options = options;
189
251
  this.debugId = `sess-${unsafeId()}`;
190
252
  this.from = from;
191
253
  this.to = connectedTo;
192
254
  this.connection = conn;
193
- this.codec = codec;
255
+ this.codec = options.codec;
194
256
  this.heartbeatMisses = 0;
195
257
  this.heartbeat = setInterval(
196
258
  () => this.sendHeartbeat(),
197
- HEARTBEAT_INTERVAL_MS
259
+ options.heartbeatIntervalMs
198
260
  );
199
261
  }
200
262
  /**
@@ -230,7 +292,7 @@ var Session = class {
230
292
  return fullMsg.id;
231
293
  }
232
294
  sendHeartbeat() {
233
- if (this.heartbeatMisses >= HEARTBEATS_TILL_DEAD) {
295
+ if (this.heartbeatMisses >= this.options.heartbeatsUntilDead) {
234
296
  if (this.connection) {
235
297
  log?.info(
236
298
  `${this.from} -- closing connection (id: ${this.connection.debugId}) to ${this.to} due to inactivity`
@@ -300,7 +362,7 @@ var Session = class {
300
362
  this.disconnectionGrace = setTimeout(() => {
301
363
  this.close();
302
364
  cb();
303
- }, SESSION_DISCONNECT_GRACE_MS);
365
+ }, this.options.sessionDisconnectGraceMs);
304
366
  }
305
367
  // called on reconnect of the underlying session
306
368
  cancelGrace() {
@@ -338,58 +400,6 @@ var Session = class {
338
400
  }
339
401
  };
340
402
 
341
- // codec/json.ts
342
- var encoder = new TextEncoder();
343
- var decoder = new TextDecoder();
344
- function uint8ArrayToBase64(uint8Array) {
345
- let binary = "";
346
- uint8Array.forEach((byte) => {
347
- binary += String.fromCharCode(byte);
348
- });
349
- return btoa(binary);
350
- }
351
- function base64ToUint8Array(base64) {
352
- const binaryString = atob(base64);
353
- const uint8Array = new Uint8Array(binaryString.length);
354
- for (let i = 0; i < binaryString.length; i++) {
355
- uint8Array[i] = binaryString.charCodeAt(i);
356
- }
357
- return uint8Array;
358
- }
359
- var NaiveJsonCodec = {
360
- toBuffer: (obj) => {
361
- return encoder.encode(
362
- JSON.stringify(obj, function replacer(key) {
363
- const val = this[key];
364
- if (val instanceof Uint8Array) {
365
- return { $t: uint8ArrayToBase64(val) };
366
- } else {
367
- return val;
368
- }
369
- })
370
- );
371
- },
372
- fromBuffer: (buff) => {
373
- try {
374
- const parsed = JSON.parse(
375
- decoder.decode(buff),
376
- function reviver(_key, val) {
377
- if (val?.$t) {
378
- return base64ToUint8Array(val.$t);
379
- } else {
380
- return val;
381
- }
382
- }
383
- );
384
- if (typeof parsed === "object")
385
- return parsed;
386
- return null;
387
- } catch {
388
- return null;
389
- }
390
- }
391
- };
392
-
393
403
  // transport/transport.ts
394
404
  var import_nanoid3 = require("nanoid");
395
405
 
@@ -402,13 +412,13 @@ function coerceErrorString(err) {
402
412
  }
403
413
 
404
414
  // transport/transport.ts
405
- var DEFAULT_RECONNECT_JITTER_MAX_MS = 500;
406
- var DEFAULT_RECONNECT_INTERVAL_MS = 250;
415
+ var RECONNECT_JITTER_MAX_MS = 500;
416
+ var RECONNECT_INTERVAL_MS = 250;
407
417
  var defaultTransportOptions = {
408
- retryIntervalMs: DEFAULT_RECONNECT_INTERVAL_MS,
409
- retryJitterMs: DEFAULT_RECONNECT_JITTER_MAX_MS,
418
+ retryIntervalMs: RECONNECT_INTERVAL_MS,
419
+ retryJitterMs: RECONNECT_JITTER_MAX_MS,
410
420
  retryAttemptsMax: 5,
411
- codec: NaiveJsonCodec
421
+ ...defaultSessionOptions
412
422
  };
413
423
  var Transport = class {
414
424
  /**
@@ -479,7 +489,7 @@ var Transport = class {
479
489
  const lastInstanceId = this.connectedInstanceIds.get(connectedTo);
480
490
  if (oldSession && lastInstanceId !== void 0 && lastInstanceId !== instanceId) {
481
491
  log?.warn(
482
- `${this.clientId} -- handshake from ${connectedTo} is a different instance (got: ${instanceId}, last connected to: ${lastInstanceId}), starting a new session`
492
+ `${this.clientId} -- connection from ${connectedTo} is a different instance (got: ${instanceId}, last connected to: ${lastInstanceId}), starting a new session`
483
493
  );
484
494
  oldSession.close();
485
495
  this.deleteSession(oldSession);
@@ -502,10 +512,10 @@ var Transport = class {
502
512
  }
503
513
  createSession(connectedTo, conn) {
504
514
  const session = new Session(
505
- this.codec,
506
515
  this.clientId,
507
516
  connectedTo,
508
- conn
517
+ conn,
518
+ this.options
509
519
  );
510
520
  this.sessions.set(session.to, session);
511
521
  this.eventDispatcher.dispatchEvent("sessionStatus", {
@@ -548,7 +558,7 @@ var Transport = class {
548
558
  parseMsg(msg) {
549
559
  const parsedMsg = this.codec.fromBuffer(msg);
550
560
  if (parsedMsg === null) {
551
- const decodedBuffer = new TextDecoder().decode(msg);
561
+ const decodedBuffer = new TextDecoder().decode(Buffer.from(msg));
552
562
  log?.error(
553
563
  `${this.clientId} -- received malformed msg, killing conn: ${decodedBuffer}`
554
564
  );
@@ -562,11 +572,7 @@ var Transport = class {
562
572
  );
563
573
  return null;
564
574
  }
565
- return {
566
- ...parsedMsg,
567
- serviceName: parsedMsg.serviceName === null ? void 0 : parsedMsg.serviceName,
568
- procedureName: parsedMsg.procedureName === null ? void 0 : parsedMsg.procedureName
569
- };
575
+ return parsedMsg;
570
576
  }
571
577
  /**
572
578
  * Called when a message is received by this transport.
@@ -585,11 +591,18 @@ var Transport = class {
585
591
  session.cancelGrace();
586
592
  log?.debug(`${this.clientId} -- received msg: ${JSON.stringify(msg)}`);
587
593
  if (msg.seq !== session.nextExpectedSeq) {
588
- log?.warn(
589
- `${this.clientId} -- received out-of-order msg (got: ${msg.seq}, wanted: ${session.nextExpectedSeq}), discarding: ${JSON.stringify(
590
- msg
591
- )}`
592
- );
594
+ if (msg.seq < session.nextExpectedSeq) {
595
+ log?.debug(
596
+ `${this.clientId} -- received duplicate msg (got: ${msg.seq}, wanted: ${session.nextExpectedSeq}), discarding: ${JSON.stringify(
597
+ msg
598
+ )}`
599
+ );
600
+ } else {
601
+ log?.error(
602
+ `${this.clientId} -- received out-of-order msg (got: ${msg.seq}, wanted: ${session.nextExpectedSeq}), marking connection as dead: ${JSON.stringify(msg)}`
603
+ );
604
+ session.closeStaleConnection(session.connection);
605
+ }
593
606
  return;
594
607
  }
595
608
  if (!isAck(msg.controlFlags)) {
@@ -607,7 +620,7 @@ var Transport = class {
607
620
  }
608
621
  /**
609
622
  * Removes a listener from this transport.
610
- * @param the type of event to unlisten on
623
+ * @param the type of event to un-listen on
611
624
  * @param handler The message handler to remove.
612
625
  */
613
626
  removeEventListener(type, handler) {
@@ -688,22 +701,24 @@ var ServerTransport = class extends Transport {
688
701
  handleConnection(conn) {
689
702
  let session = void 0;
690
703
  const client = () => session?.to ?? "unknown";
691
- const bootHandler = this.receiveWithBootSequence(
692
- conn,
693
- (establishedSession) => {
694
- session = establishedSession;
695
- conn.removeDataListener(bootHandler);
696
- conn.addDataListener((data) => {
697
- const parsed = this.parseMsg(data);
698
- if (!parsed) {
699
- conn.close();
700
- return;
701
- }
702
- this.handleMsg(parsed);
703
- });
704
+ const handshakeHandler = (data) => {
705
+ const handshake = this.receiveHandshakeRequestMessage(data, conn);
706
+ if (!handshake) {
707
+ conn.close();
708
+ return;
704
709
  }
705
- );
706
- conn.addDataListener(bootHandler);
710
+ session = this.onConnect(conn, handshake.from, handshake.instanceId);
711
+ conn.removeDataListener(handshakeHandler);
712
+ conn.addDataListener((data2) => {
713
+ const parsed = this.parseMsg(data2);
714
+ if (!parsed) {
715
+ conn.close();
716
+ return;
717
+ }
718
+ this.handleMsg(parsed);
719
+ });
720
+ };
721
+ conn.addDataListener(handshakeHandler);
707
722
  conn.addCloseListener(() => {
708
723
  if (!session)
709
724
  return;
@@ -720,42 +735,51 @@ var ServerTransport = class extends Transport {
720
735
  );
721
736
  });
722
737
  }
723
- receiveWithBootSequence(conn, sessionCb) {
724
- const bootHandler = (data) => {
725
- const parsed = this.parseMsg(data);
726
- if (!parsed) {
727
- conn.close();
728
- return;
729
- }
730
- if (!import_value.Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
731
- const responseMsg2 = bootResponseMessage(
732
- this.clientId,
733
- this.instanceId,
734
- parsed.from,
735
- false
736
- );
737
- conn.send(this.codec.toBuffer(responseMsg2));
738
- log?.warn(
739
- `${this.clientId} -- received invalid handshake msg: ${JSON.stringify(
740
- parsed
741
- )}`
742
- );
743
- return;
744
- }
745
- const instanceId = parsed.payload.instanceId;
746
- log?.debug(
747
- `${this.clientId} -- handshake from ${parsed.from} ok (instance id: ${instanceId}), responding with handshake success`
738
+ receiveHandshakeRequestMessage(data, conn) {
739
+ const parsed = this.parseMsg(data);
740
+ if (!parsed)
741
+ return false;
742
+ if (!import_value.Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
743
+ const responseMsg2 = handshakeResponseMessage(
744
+ this.clientId,
745
+ this.instanceId,
746
+ parsed.from,
747
+ false
748
+ );
749
+ conn.send(this.codec.toBuffer(responseMsg2));
750
+ log?.warn(
751
+ `${this.clientId} -- received invalid handshake msg: ${JSON.stringify(
752
+ parsed
753
+ )}`
748
754
  );
749
- const responseMsg = bootResponseMessage(
755
+ return false;
756
+ }
757
+ const gotVersion = parsed.payload.protocolVersion;
758
+ if (gotVersion !== PROTOCOL_VERSION) {
759
+ const responseMsg2 = handshakeResponseMessage(
750
760
  this.clientId,
751
761
  this.instanceId,
752
762
  parsed.from,
753
- true
763
+ false
754
764
  );
755
- conn.send(this.codec.toBuffer(responseMsg));
756
- sessionCb(this.onConnect(conn, parsed.from, instanceId));
757
- };
758
- return bootHandler;
765
+ conn.send(this.codec.toBuffer(responseMsg2));
766
+ log?.warn(
767
+ `${this.clientId} -- received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`
768
+ );
769
+ return false;
770
+ }
771
+ const instanceId = parsed.payload.instanceId;
772
+ log?.debug(
773
+ `${this.clientId} -- handshake from ${parsed.from} ok (instance id: ${instanceId}), responding with handshake success`
774
+ );
775
+ const responseMsg = handshakeResponseMessage(
776
+ this.clientId,
777
+ this.instanceId,
778
+ parsed.from,
779
+ true
780
+ );
781
+ conn.send(this.codec.toBuffer(responseMsg));
782
+ return { instanceId, from: parsed.from };
759
783
  }
760
784
  };
761
785
 
@@ -1,7 +1,7 @@
1
- import { S as ServerTransport, b as TransportClientId, c as TransportOptions } from '../../../index-54e0f99c.js';
1
+ import { S as ServerTransport, b as TransportClientId, c as TransportOptions } from '../../../index-9aa0aabb.js';
2
2
  import { WebSocketServer } from 'ws';
3
3
  import { WebSocket } from 'isomorphic-ws';
4
- import { W as WebSocketConnection } from '../../../connection-ba37d174.js';
4
+ import { W as WebSocketConnection } from '../../../connection-d052d027.js';
5
5
  import '../../../types-3e5768ec.js';
6
6
  import '@sinclair/typebox';
7
7
 
@@ -1,7 +1,7 @@
1
- import { S as ServerTransport, b as TransportClientId, c as TransportOptions } from '../../../index-54e0f99c.js';
1
+ import { S as ServerTransport, b as TransportClientId, c as TransportOptions } from '../../../index-9aa0aabb.js';
2
2
  import { WebSocketServer } from 'ws';
3
3
  import { WebSocket } from 'isomorphic-ws';
4
- import { W as WebSocketConnection } from '../../../connection-ba37d174.js';
4
+ import { W as WebSocketConnection } from '../../../connection-d052d027.js';
5
5
  import '../../../types-3e5768ec.js';
6
6
  import '@sinclair/typebox';
7
7
 
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  WebSocketConnection
3
- } from "../../../chunk-VLBVQX5H.js";
3
+ } from "../../../chunk-Q7AWJYDQ.js";
4
4
  import {
5
5
  ServerTransport
6
- } from "../../../chunk-4SDJ5VN4.js";
7
- import "../../../chunk-GZ7HCLLM.js";
8
- import "../../../chunk-XFFS4UOD.js";
6
+ } from "../../../chunk-LDUFHGZU.js";
7
+ import "../../../chunk-SCG5S2EC.js";
9
8
  import {
10
9
  log
11
10
  } from "../../../chunk-H4BYJELI.js";
11
+ import "../../../chunk-GZ7HCLLM.js";
12
12
 
13
13
  // transport/impls/ws/server.ts
14
14
  var WebSocketServerTransport = class extends ServerTransport {