@replit/river 0.15.0 → 0.15.2

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 (35) hide show
  1. package/README.md +41 -22
  2. package/dist/{builder-ca6c4259.d.ts → builder-ebd945c0.d.ts} +1 -1
  3. package/dist/{chunk-IVNV5HBI.js → chunk-B7VTDQR7.js} +160 -51
  4. package/dist/{chunk-BSAIT634.js → chunk-UJHTHOTT.js} +1 -1
  5. package/dist/{chunk-FFT7PSUV.js → chunk-ZRB6IKPV.js} +1 -1
  6. package/dist/{connection-0c5eeb14.d.ts → connection-10a24478.d.ts} +1 -1
  7. package/dist/{connection-14675d77.d.ts → connection-f4492948.d.ts} +1 -1
  8. package/dist/{index-f922ec84.d.ts → index-bbccacef.d.ts} +90 -16
  9. package/dist/router/index.d.cts +3 -3
  10. package/dist/router/index.d.ts +3 -3
  11. package/dist/transport/impls/uds/client.cjs +206 -92
  12. package/dist/transport/impls/uds/client.d.cts +3 -3
  13. package/dist/transport/impls/uds/client.d.ts +3 -3
  14. package/dist/transport/impls/uds/client.js +2 -2
  15. package/dist/transport/impls/uds/server.cjs +75 -73
  16. package/dist/transport/impls/uds/server.d.cts +3 -3
  17. package/dist/transport/impls/uds/server.d.ts +3 -3
  18. package/dist/transport/impls/uds/server.js +2 -2
  19. package/dist/transport/impls/ws/client.cjs +206 -94
  20. package/dist/transport/impls/ws/client.d.cts +3 -3
  21. package/dist/transport/impls/ws/client.d.ts +3 -3
  22. package/dist/transport/impls/ws/client.js +2 -2
  23. package/dist/transport/impls/ws/server.cjs +75 -73
  24. package/dist/transport/impls/ws/server.d.cts +3 -3
  25. package/dist/transport/impls/ws/server.d.ts +3 -3
  26. package/dist/transport/impls/ws/server.js +2 -2
  27. package/dist/transport/index.cjs +211 -105
  28. package/dist/transport/index.d.cts +1 -1
  29. package/dist/transport/index.d.ts +1 -1
  30. package/dist/transport/index.js +3 -3
  31. package/dist/util/testHelpers.cjs +61 -64
  32. package/dist/util/testHelpers.d.cts +10 -4
  33. package/dist/util/testHelpers.d.ts +10 -4
  34. package/dist/util/testHelpers.js +13 -5
  35. package/package.json +1 -1
@@ -23,7 +23,7 @@ __export(transport_exports, {
23
23
  ClientTransport: () => ClientTransport,
24
24
  Connection: () => Connection,
25
25
  OpaqueTransportMessageSchema: () => OpaqueTransportMessageSchema,
26
- ProtocolErrorType: () => ProtocolErrorType,
26
+ ProtocolError: () => ProtocolError,
27
27
  ServerTransport: () => ServerTransport,
28
28
  Session: () => Session,
29
29
  Transport: () => Transport,
@@ -131,12 +131,11 @@ function isAck(controlFlag) {
131
131
  var log;
132
132
 
133
133
  // transport/events.ts
134
- var ProtocolErrorType = /* @__PURE__ */ ((ProtocolErrorType2) => {
135
- ProtocolErrorType2["RetriesExceeded"] = "conn_retry_exceeded";
136
- ProtocolErrorType2["HandshakeFailed"] = "handshake_failed";
137
- ProtocolErrorType2["UseAfterDestroy"] = "use_after_destroy";
138
- return ProtocolErrorType2;
139
- })(ProtocolErrorType || {});
134
+ var ProtocolError = {
135
+ RetriesExceeded: "conn_retry_exceeded",
136
+ HandshakeFailed: "handshake_failed",
137
+ UseAfterDestroy: "use_after_destroy"
138
+ };
140
139
  var EventDispatcher = class {
141
140
  eventListeners = {};
142
141
  numberOfListeners(eventType) {
@@ -166,60 +165,6 @@ var EventDispatcher = class {
166
165
 
167
166
  // transport/session.ts
168
167
  var import_nanoid2 = require("nanoid");
169
-
170
- // codec/json.ts
171
- var encoder = new TextEncoder();
172
- var decoder = new TextDecoder();
173
- function uint8ArrayToBase64(uint8Array) {
174
- let binary = "";
175
- uint8Array.forEach((byte) => {
176
- binary += String.fromCharCode(byte);
177
- });
178
- return btoa(binary);
179
- }
180
- function base64ToUint8Array(base64) {
181
- const binaryString = atob(base64);
182
- const uint8Array = new Uint8Array(binaryString.length);
183
- for (let i = 0; i < binaryString.length; i++) {
184
- uint8Array[i] = binaryString.charCodeAt(i);
185
- }
186
- return uint8Array;
187
- }
188
- var NaiveJsonCodec = {
189
- toBuffer: (obj) => {
190
- return encoder.encode(
191
- JSON.stringify(obj, function replacer(key) {
192
- const val = this[key];
193
- if (val instanceof Uint8Array) {
194
- return { $t: uint8ArrayToBase64(val) };
195
- } else {
196
- return val;
197
- }
198
- })
199
- );
200
- },
201
- fromBuffer: (buff) => {
202
- try {
203
- const parsed = JSON.parse(
204
- decoder.decode(buff),
205
- function reviver(_key, val) {
206
- if (val?.$t) {
207
- return base64ToUint8Array(val.$t);
208
- } else {
209
- return val;
210
- }
211
- }
212
- );
213
- if (typeof parsed === "object")
214
- return parsed;
215
- return null;
216
- } catch {
217
- return null;
218
- }
219
- }
220
- };
221
-
222
- // transport/session.ts
223
168
  var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
224
169
  var unsafeId = () => nanoid2();
225
170
  var Connection = class {
@@ -228,15 +173,6 @@ var Connection = class {
228
173
  this.debugId = `conn-${unsafeId()}`;
229
174
  }
230
175
  };
231
- var HEARTBEAT_INTERVAL_MS = 1e3;
232
- var HEARTBEATS_TILL_DEAD = 2;
233
- var SESSION_DISCONNECT_GRACE_MS = 5e3;
234
- var defaultSessionOptions = {
235
- heartbeatIntervalMs: HEARTBEAT_INTERVAL_MS,
236
- heartbeatsUntilDead: HEARTBEATS_TILL_DEAD,
237
- sessionDisconnectGraceMs: SESSION_DISCONNECT_GRACE_MS,
238
- codec: NaiveJsonCodec
239
- };
240
176
  var Session = class {
241
177
  codec;
242
178
  options;
@@ -431,14 +367,146 @@ function coerceErrorString(err) {
431
367
  return `[coerced to error] ${String(err)}`;
432
368
  }
433
369
 
370
+ // transport/rateLimit.ts
371
+ var LeakyBucketRateLimit = class {
372
+ budgetConsumed;
373
+ intervalHandles;
374
+ options;
375
+ constructor(options) {
376
+ this.options = options;
377
+ this.budgetConsumed = /* @__PURE__ */ new Map();
378
+ this.intervalHandles = /* @__PURE__ */ new Map();
379
+ }
380
+ getBackoffMs(user) {
381
+ if (!this.budgetConsumed.has(user))
382
+ return 0;
383
+ const exponent = Math.max(0, this.getBudgetConsumed(user) - 1);
384
+ const jitter = Math.floor(Math.random() * this.options.maxJitterMs);
385
+ const backoffMs = Math.min(
386
+ this.options.baseIntervalMs * 2 ** exponent,
387
+ this.options.maxBackoffMs
388
+ );
389
+ return backoffMs + jitter;
390
+ }
391
+ get totalBudgetRestoreTime() {
392
+ return this.options.budgetRestoreIntervalMs * this.options.attemptBudgetCapacity;
393
+ }
394
+ consumeBudget(user) {
395
+ this.stopLeak(user);
396
+ this.budgetConsumed.set(user, this.getBudgetConsumed(user) + 1);
397
+ }
398
+ getBudgetConsumed(user) {
399
+ return this.budgetConsumed.get(user) ?? 0;
400
+ }
401
+ hasBudget(user) {
402
+ return this.getBudgetConsumed(user) < this.options.attemptBudgetCapacity;
403
+ }
404
+ startRestoringBudget(user) {
405
+ if (this.intervalHandles.has(user)) {
406
+ return;
407
+ }
408
+ const restoreBudgetForUser = () => {
409
+ const currentBudget = this.budgetConsumed.get(user);
410
+ if (!currentBudget) {
411
+ this.stopLeak(user);
412
+ return;
413
+ }
414
+ const newBudget = currentBudget - 1;
415
+ if (newBudget === 0) {
416
+ this.budgetConsumed.delete(user);
417
+ return;
418
+ }
419
+ this.budgetConsumed.set(user, newBudget);
420
+ };
421
+ restoreBudgetForUser();
422
+ const intervalHandle = setInterval(
423
+ restoreBudgetForUser,
424
+ this.options.budgetRestoreIntervalMs
425
+ );
426
+ this.intervalHandles.set(user, intervalHandle);
427
+ }
428
+ stopLeak(user) {
429
+ if (!this.intervalHandles.has(user)) {
430
+ return;
431
+ }
432
+ clearInterval(this.intervalHandles.get(user));
433
+ this.intervalHandles.delete(user);
434
+ }
435
+ close() {
436
+ for (const user of this.intervalHandles.keys()) {
437
+ this.stopLeak(user);
438
+ }
439
+ }
440
+ };
441
+
442
+ // codec/json.ts
443
+ var encoder = new TextEncoder();
444
+ var decoder = new TextDecoder();
445
+ function uint8ArrayToBase64(uint8Array) {
446
+ let binary = "";
447
+ uint8Array.forEach((byte) => {
448
+ binary += String.fromCharCode(byte);
449
+ });
450
+ return btoa(binary);
451
+ }
452
+ function base64ToUint8Array(base64) {
453
+ const binaryString = atob(base64);
454
+ const uint8Array = new Uint8Array(binaryString.length);
455
+ for (let i = 0; i < binaryString.length; i++) {
456
+ uint8Array[i] = binaryString.charCodeAt(i);
457
+ }
458
+ return uint8Array;
459
+ }
460
+ var NaiveJsonCodec = {
461
+ toBuffer: (obj) => {
462
+ return encoder.encode(
463
+ JSON.stringify(obj, function replacer(key) {
464
+ const val = this[key];
465
+ if (val instanceof Uint8Array) {
466
+ return { $t: uint8ArrayToBase64(val) };
467
+ } else {
468
+ return val;
469
+ }
470
+ })
471
+ );
472
+ },
473
+ fromBuffer: (buff) => {
474
+ try {
475
+ const parsed = JSON.parse(
476
+ decoder.decode(buff),
477
+ function reviver(_key, val) {
478
+ if (val?.$t) {
479
+ return base64ToUint8Array(val.$t);
480
+ } else {
481
+ return val;
482
+ }
483
+ }
484
+ );
485
+ if (typeof parsed === "object")
486
+ return parsed;
487
+ return null;
488
+ } catch {
489
+ return null;
490
+ }
491
+ }
492
+ };
493
+
434
494
  // transport/transport.ts
435
- var RECONNECT_JITTER_MAX_MS = 500;
436
- var RECONNECT_INTERVAL_MS = 250;
437
495
  var defaultTransportOptions = {
438
- retryIntervalMs: RECONNECT_INTERVAL_MS,
439
- retryJitterMs: RECONNECT_JITTER_MAX_MS,
440
- retryAttemptsMax: 5,
441
- ...defaultSessionOptions
496
+ heartbeatIntervalMs: 1e3,
497
+ heartbeatsUntilDead: 2,
498
+ sessionDisconnectGraceMs: 5e3,
499
+ codec: NaiveJsonCodec
500
+ };
501
+ var defaultClientTransportOptions = {
502
+ connectionRetryOptions: {
503
+ baseIntervalMs: 250,
504
+ maxJitterMs: 200,
505
+ maxBackoffMs: 32e3,
506
+ attemptBudgetCapacity: 15,
507
+ budgetRestoreIntervalMs: 200
508
+ },
509
+ ...defaultTransportOptions
442
510
  };
443
511
  var Transport = class {
444
512
  /**
@@ -653,7 +721,7 @@ var Transport = class {
653
721
  if (this.state === "destroyed") {
654
722
  const err = "transport is destroyed, cant send";
655
723
  log?.error(`${this.clientId} -- ` + err + `: ${JSON.stringify(msg)}`);
656
- this.protocolError("use_after_destroy" /* UseAfterDestroy */, err);
724
+ this.protocolError(ProtocolError.UseAfterDestroy, err);
657
725
  return void 0;
658
726
  } else if (this.state === "closed") {
659
727
  log?.info(
@@ -713,14 +781,26 @@ var Transport = class {
713
781
  }
714
782
  };
715
783
  var ClientTransport = class extends Transport {
784
+ /**
785
+ * The options for this transport.
786
+ */
787
+ options;
716
788
  /**
717
789
  * The map of reconnect promises for each client ID.
718
790
  */
719
791
  inflightConnectionPromises;
792
+ retryBudget;
720
793
  tryReconnecting = true;
721
794
  constructor(clientId, providedOptions) {
722
795
  super(clientId, providedOptions);
796
+ this.options = {
797
+ ...defaultClientTransportOptions,
798
+ ...providedOptions
799
+ };
723
800
  this.inflightConnectionPromises = /* @__PURE__ */ new Map();
801
+ this.retryBudget = new LeakyBucketRateLimit(
802
+ this.options.connectionRetryOptions
803
+ );
724
804
  }
725
805
  handleConnection(conn, to) {
726
806
  if (this.state !== "open")
@@ -751,7 +831,10 @@ var ClientTransport = class extends Transport {
751
831
  log?.info(
752
832
  `${this.clientId} -- connection (id: ${conn.debugId}) to ${to} disconnected`
753
833
  );
754
- void this.connect(to);
834
+ this.inflightConnectionPromises.delete(to);
835
+ if (this.tryReconnecting) {
836
+ void this.connect(to);
837
+ }
755
838
  });
756
839
  conn.addErrorListener((err) => {
757
840
  log?.warn(
@@ -763,7 +846,7 @@ var ClientTransport = class extends Transport {
763
846
  const parsed = this.parseMsg(data);
764
847
  if (!parsed) {
765
848
  this.protocolError(
766
- "handshake_failed" /* HandshakeFailed */,
849
+ ProtocolError.HandshakeFailed,
767
850
  "received non-transport message"
768
851
  );
769
852
  return false;
@@ -775,7 +858,7 @@ var ClientTransport = class extends Transport {
775
858
  )}`
776
859
  );
777
860
  this.protocolError(
778
- "handshake_failed" /* HandshakeFailed */,
861
+ ProtocolError.HandshakeFailed,
779
862
  "invalid handshake resp"
780
863
  );
781
864
  return false;
@@ -787,7 +870,7 @@ var ClientTransport = class extends Transport {
787
870
  )}`
788
871
  );
789
872
  this.protocolError(
790
- "handshake_failed" /* HandshakeFailed */,
873
+ ProtocolError.HandshakeFailed,
791
874
  parsed.payload.status.reason
792
875
  );
793
876
  return false;
@@ -802,41 +885,64 @@ var ClientTransport = class extends Transport {
802
885
  * Manually attempts to connect to a client.
803
886
  * @param to The client ID of the node to connect to.
804
887
  */
805
- async connect(to, attempt = 0) {
806
- if (this.state !== "open" || !this.tryReconnecting) {
888
+ async connect(to) {
889
+ const canProceedWithConnection = () => this.state === "open";
890
+ if (!canProceedWithConnection()) {
807
891
  log?.info(
808
- `${this.clientId} -- transport state is no longer open, not attempting connection`
892
+ `${this.clientId} -- transport state is no longer open, cancelling attempt to connect to ${to}`
809
893
  );
810
894
  return;
811
895
  }
812
896
  let reconnectPromise = this.inflightConnectionPromises.get(to);
813
897
  if (!reconnectPromise) {
814
- reconnectPromise = this.createNewOutgoingConnection(to).then((conn) => {
898
+ log?.info(`${this.clientId} -- attempting connection to ${to}`);
899
+ const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
900
+ if (!this.retryBudget.hasBudget(to)) {
901
+ const errMsg = `not attempting to connect to ${to}, retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
902
+ log?.warn(`${this.clientId} -- ${errMsg}`);
903
+ this.protocolError(ProtocolError.RetriesExceeded, errMsg);
904
+ return;
905
+ }
906
+ let sleep = Promise.resolve();
907
+ const backoffMs = this.retryBudget.getBackoffMs(to);
908
+ if (backoffMs > 0) {
909
+ sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
910
+ }
911
+ this.retryBudget.consumeBudget(to);
912
+ reconnectPromise = sleep.then(() => {
913
+ if (!canProceedWithConnection()) {
914
+ throw new Error("transport state is no longer open");
915
+ }
916
+ }).then(() => this.createNewOutgoingConnection(to)).then((conn) => {
917
+ if (!canProceedWithConnection()) {
918
+ log?.info(
919
+ `${this.clientId} -- transport state is no longer open, closing pre-handshake connection (id: ${conn.debugId}) to ${to}`
920
+ );
921
+ conn.close();
922
+ throw new Error("transport state is no longer open");
923
+ }
924
+ this.retryBudget.startRestoringBudget(to);
815
925
  this.sendHandshake(to, conn);
816
926
  return conn;
817
927
  });
818
928
  this.inflightConnectionPromises.set(to, reconnectPromise);
929
+ } else {
930
+ log?.info(
931
+ `${this.clientId} -- attempting connection to ${to} (reusing previous attempt)`
932
+ );
819
933
  }
820
934
  try {
821
935
  await reconnectPromise;
822
936
  } catch (error) {
823
- const errStr = coerceErrorString(error);
824
937
  this.inflightConnectionPromises.delete(to);
825
- const shouldRetry = this.state === "open" && this.tryReconnecting;
826
- if (!shouldRetry)
827
- return;
828
- if (attempt >= this.options.retryAttemptsMax) {
829
- const errMsg = `connection to ${to} failed after ${attempt} attempts (${errStr}), giving up`;
830
- log?.error(`${this.clientId} -- ${errMsg}`);
831
- this.protocolError("conn_retry_exceeded" /* RetriesExceeded */, errMsg);
832
- return;
938
+ const errStr = coerceErrorString(error);
939
+ if (!this.tryReconnecting || !canProceedWithConnection()) {
940
+ log?.warn(`${this.clientId} -- connection to ${to} failed (${errStr})`);
833
941
  } else {
834
- const jitter = Math.floor(Math.random() * this.options.retryJitterMs);
835
- const backoffMs = this.options.retryIntervalMs * 2 ** attempt + jitter;
836
942
  log?.warn(
837
- `${this.clientId} -- connection to ${to} failed (${errStr}), trying again in ${backoffMs}ms`
943
+ `${this.clientId} -- connection to ${to} failed (${errStr}), retrying`
838
944
  );
839
- setTimeout(() => void this.connect(to, attempt + 1), backoffMs);
945
+ return this.connect(to);
840
946
  }
841
947
  }
842
948
  }
@@ -849,9 +955,9 @@ var ClientTransport = class extends Transport {
849
955
  log?.debug(`${this.clientId} -- sending handshake request to ${to}`);
850
956
  conn.send(this.codec.toBuffer(requestMsg));
851
957
  }
852
- onDisconnect(conn, session) {
853
- this.inflightConnectionPromises.delete(session.to);
854
- super.onDisconnect(conn, session);
958
+ close() {
959
+ this.retryBudget.close();
960
+ super.close();
855
961
  }
856
962
  };
857
963
  var ServerTransport = class extends Transport {
@@ -907,7 +1013,7 @@ var ServerTransport = class extends Transport {
907
1013
  const parsed = this.parseMsg(data);
908
1014
  if (!parsed) {
909
1015
  this.protocolError(
910
- "handshake_failed" /* HandshakeFailed */,
1016
+ ProtocolError.HandshakeFailed,
911
1017
  "received non-transport message"
912
1018
  );
913
1019
  return false;
@@ -926,7 +1032,7 @@ var ServerTransport = class extends Transport {
926
1032
  )}`
927
1033
  );
928
1034
  this.protocolError(
929
- "handshake_failed" /* HandshakeFailed */,
1035
+ ProtocolError.HandshakeFailed,
930
1036
  "invalid handshake request"
931
1037
  );
932
1038
  return false;
@@ -944,7 +1050,7 @@ var ServerTransport = class extends Transport {
944
1050
  `${this.clientId} -- received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`
945
1051
  );
946
1052
  this.protocolError(
947
- "handshake_failed" /* HandshakeFailed */,
1053
+ ProtocolError.HandshakeFailed,
948
1054
  `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`
949
1055
  );
950
1056
  return false;
@@ -968,7 +1074,7 @@ var ServerTransport = class extends Transport {
968
1074
  ClientTransport,
969
1075
  Connection,
970
1076
  OpaqueTransportMessageSchema,
971
- ProtocolErrorType,
1077
+ ProtocolError,
972
1078
  ServerTransport,
973
1079
  Session,
974
1080
  Transport,
@@ -1,3 +1,3 @@
1
- export { a as ClientTransport, C as Connection, l as EventHandler, E as EventMap, k as EventTypes, O as OpaqueTransportMessage, g as OpaqueTransportMessageSchema, m as ProtocolErrorType, S as ServerTransport, d as Session, T as Transport, b as TransportClientId, h as TransportMessage, f as TransportMessageSchema, c as TransportOptions, e as TransportStatus, j as isStreamClose, i as isStreamOpen } from '../index-f922ec84.js';
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, d as ServerTransporOptions, S as ServerTransport, e as Session, T as Transport, b as TransportClientId, i as TransportMessage, g as TransportMessageSchema, f as TransportStatus, k as isStreamClose, j as isStreamOpen } from '../index-bbccacef.js';
2
2
  import '../types-3e5768ec.js';
3
3
  import '@sinclair/typebox';
@@ -1,3 +1,3 @@
1
- export { a as ClientTransport, C as Connection, l as EventHandler, E as EventMap, k as EventTypes, O as OpaqueTransportMessage, g as OpaqueTransportMessageSchema, m as ProtocolErrorType, S as ServerTransport, d as Session, T as Transport, b as TransportClientId, h as TransportMessage, f as TransportMessageSchema, c as TransportOptions, e as TransportStatus, j as isStreamClose, i as isStreamOpen } from '../index-f922ec84.js';
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, d as ServerTransporOptions, S as ServerTransport, e as Session, T as Transport, b as TransportClientId, i as TransportMessage, g as TransportMessageSchema, f as TransportStatus, k as isStreamClose, j as isStreamOpen } from '../index-bbccacef.js';
2
2
  import '../types-3e5768ec.js';
3
3
  import '@sinclair/typebox';
@@ -2,11 +2,11 @@ import "../chunk-RPIDSIQG.js";
2
2
  import {
3
3
  ClientTransport,
4
4
  Connection,
5
- ProtocolErrorType,
5
+ ProtocolError,
6
6
  ServerTransport,
7
7
  Session,
8
8
  Transport
9
- } from "../chunk-IVNV5HBI.js";
9
+ } from "../chunk-B7VTDQR7.js";
10
10
  import {
11
11
  OpaqueTransportMessageSchema,
12
12
  TransportMessageSchema
@@ -17,7 +17,7 @@ export {
17
17
  ClientTransport,
18
18
  Connection,
19
19
  OpaqueTransportMessageSchema,
20
- ProtocolErrorType,
20
+ ProtocolError,
21
21
  ServerTransport,
22
22
  Session,
23
23
  Transport,
@@ -42,6 +42,7 @@ __export(testHelpers_exports, {
42
42
  onUdsServeReady: () => onUdsServeReady,
43
43
  onWsServerReady: () => onWsServerReady,
44
44
  payloadToTransportMessage: () => payloadToTransportMessage,
45
+ testingSessionOptions: () => testingSessionOptions,
45
46
  waitForMessage: () => waitForMessage
46
47
  });
47
48
  module.exports = __toCommonJS(testHelpers_exports);
@@ -53,71 +54,8 @@ var log;
53
54
 
54
55
  // transport/session.ts
55
56
  var import_nanoid = require("nanoid");
56
-
57
- // codec/json.ts
58
- var encoder = new TextEncoder();
59
- var decoder = new TextDecoder();
60
- function uint8ArrayToBase64(uint8Array) {
61
- let binary = "";
62
- uint8Array.forEach((byte) => {
63
- binary += String.fromCharCode(byte);
64
- });
65
- return btoa(binary);
66
- }
67
- function base64ToUint8Array(base64) {
68
- const binaryString = atob(base64);
69
- const uint8Array = new Uint8Array(binaryString.length);
70
- for (let i = 0; i < binaryString.length; i++) {
71
- uint8Array[i] = binaryString.charCodeAt(i);
72
- }
73
- return uint8Array;
74
- }
75
- var NaiveJsonCodec = {
76
- toBuffer: (obj) => {
77
- return encoder.encode(
78
- JSON.stringify(obj, function replacer(key) {
79
- const val = this[key];
80
- if (val instanceof Uint8Array) {
81
- return { $t: uint8ArrayToBase64(val) };
82
- } else {
83
- return val;
84
- }
85
- })
86
- );
87
- },
88
- fromBuffer: (buff) => {
89
- try {
90
- const parsed = JSON.parse(
91
- decoder.decode(buff),
92
- function reviver(_key, val) {
93
- if (val?.$t) {
94
- return base64ToUint8Array(val.$t);
95
- } else {
96
- return val;
97
- }
98
- }
99
- );
100
- if (typeof parsed === "object")
101
- return parsed;
102
- return null;
103
- } catch {
104
- return null;
105
- }
106
- }
107
- };
108
-
109
- // transport/session.ts
110
57
  var nanoid = (0, import_nanoid.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
111
58
  var unsafeId = () => nanoid();
112
- var HEARTBEAT_INTERVAL_MS = 1e3;
113
- var HEARTBEATS_TILL_DEAD = 2;
114
- var SESSION_DISCONNECT_GRACE_MS = 5e3;
115
- var defaultSessionOptions = {
116
- heartbeatIntervalMs: HEARTBEAT_INTERVAL_MS,
117
- heartbeatsUntilDead: HEARTBEATS_TILL_DEAD,
118
- sessionDisconnectGraceMs: SESSION_DISCONNECT_GRACE_MS,
119
- codec: NaiveJsonCodec
120
- };
121
59
  var Session = class {
122
60
  codec;
123
61
  options;
@@ -309,6 +247,58 @@ function coerceErrorString(err) {
309
247
  return `[coerced to error] ${String(err)}`;
310
248
  }
311
249
 
250
+ // codec/json.ts
251
+ var encoder = new TextEncoder();
252
+ var decoder = new TextDecoder();
253
+ function uint8ArrayToBase64(uint8Array) {
254
+ let binary = "";
255
+ uint8Array.forEach((byte) => {
256
+ binary += String.fromCharCode(byte);
257
+ });
258
+ return btoa(binary);
259
+ }
260
+ function base64ToUint8Array(base64) {
261
+ const binaryString = atob(base64);
262
+ const uint8Array = new Uint8Array(binaryString.length);
263
+ for (let i = 0; i < binaryString.length; i++) {
264
+ uint8Array[i] = binaryString.charCodeAt(i);
265
+ }
266
+ return uint8Array;
267
+ }
268
+ var NaiveJsonCodec = {
269
+ toBuffer: (obj) => {
270
+ return encoder.encode(
271
+ JSON.stringify(obj, function replacer(key) {
272
+ const val = this[key];
273
+ if (val instanceof Uint8Array) {
274
+ return { $t: uint8ArrayToBase64(val) };
275
+ } else {
276
+ return val;
277
+ }
278
+ })
279
+ );
280
+ },
281
+ fromBuffer: (buff) => {
282
+ try {
283
+ const parsed = JSON.parse(
284
+ decoder.decode(buff),
285
+ function reviver(_key, val) {
286
+ if (val?.$t) {
287
+ return base64ToUint8Array(val.$t);
288
+ } else {
289
+ return val;
290
+ }
291
+ }
292
+ );
293
+ if (typeof parsed === "object")
294
+ return parsed;
295
+ return null;
296
+ } catch {
297
+ return null;
298
+ }
299
+ }
300
+ };
301
+
312
302
  // node_modules/p-defer/index.js
313
303
  function pDefer() {
314
304
  const deferred = {};
@@ -673,12 +663,18 @@ function catchProcError(err) {
673
663
  }
674
664
  };
675
665
  }
666
+ var testingSessionOptions = {
667
+ heartbeatIntervalMs: 1e3,
668
+ heartbeatsUntilDead: 2,
669
+ sessionDisconnectGraceMs: 5e3,
670
+ codec: NaiveJsonCodec
671
+ };
676
672
  function dummyCtx(state, extendedContext) {
677
673
  const session = new Session(
678
674
  "client",
679
675
  "SERVER",
680
676
  void 0,
681
- defaultSessionOptions
677
+ testingSessionOptions
682
678
  );
683
679
  return {
684
680
  ...extendedContext,
@@ -750,5 +746,6 @@ var getUnixSocketPath = () => {
750
746
  onUdsServeReady,
751
747
  onWsServerReady,
752
748
  payloadToTransportMessage,
749
+ testingSessionOptions,
753
750
  waitForMessage
754
751
  });
@@ -1,11 +1,11 @@
1
1
  import * as it_pushable from 'it-pushable';
2
+ import { C as Codec } from '../types-3e5768ec.js';
2
3
  import WebSocket from 'isomorphic-ws';
3
4
  import http from 'node:http';
4
- import { P as PartialTransportMessage, T as Transport, C as Connection, O as OpaqueTransportMessage } from '../index-f922ec84.js';
5
- import { P as PayloadType, R as RiverError, a as Procedure, S as ServiceContext, b as Result, c as RiverUncaughtSchema } from '../builder-ca6c4259.js';
5
+ import { P as PartialTransportMessage, T as Transport, C as Connection, O as OpaqueTransportMessage } from '../index-bbccacef.js';
6
+ import { P as PayloadType, R as RiverError, a as Procedure, S as ServiceContext, b as Result, c as RiverUncaughtSchema } from '../builder-ebd945c0.js';
6
7
  import { Static } from '@sinclair/typebox';
7
8
  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,6 +48,12 @@ 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
57
  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>>>;
52
58
  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>];
53
59
  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>;
@@ -60,4 +66,4 @@ declare function asClientUpload<State extends object, I extends PayloadType, O e
60
66
  } | Result<Static<O>, Static<E>>>];
61
67
  declare const getUnixSocketPath: () => string;
62
68
 
63
- export { asClientRpc, asClientStream, asClientSubscription, asClientUpload, createDummyTransportMessage, createLocalWebSocketClient, createWebSocketServer, getUnixSocketPath, iterNext, onUdsServeReady, onWsServerReady, payloadToTransportMessage, waitForMessage };
69
+ export { asClientRpc, asClientStream, asClientSubscription, asClientUpload, createDummyTransportMessage, createLocalWebSocketClient, createWebSocketServer, getUnixSocketPath, iterNext, onUdsServeReady, onWsServerReady, payloadToTransportMessage, testingSessionOptions, waitForMessage };