@replit/river 0.15.1 → 0.15.3

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-660d3140.d.ts → builder-4d392f6c.d.ts} +1 -1
  3. package/dist/{chunk-O6YQ3JAH.js → chunk-5XMMDOLH.js} +148 -37
  4. package/dist/{chunk-MNWOTQWX.js → chunk-MXHIHC3U.js} +1 -1
  5. package/dist/{chunk-5TX4BKAD.js → chunk-NSJVTNVQ.js} +1 -1
  6. package/dist/{connection-162c0f7b.d.ts → connection-94896f3b.d.ts} +1 -1
  7. package/dist/{connection-93daccc3.d.ts → connection-99346822.d.ts} +1 -1
  8. package/dist/{index-76b801f8.d.ts → index-2e402bb8.d.ts} +84 -11
  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 +198 -88
  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 +67 -69
  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 +198 -90
  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 +67 -69
  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 +198 -90
  28. package/dist/transport/index.d.cts +1 -1
  29. package/dist/transport/index.d.ts +1 -1
  30. package/dist/transport/index.js +1 -1
  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
@@ -165,60 +165,6 @@ var EventDispatcher = class {
165
165
 
166
166
  // transport/session.ts
167
167
  var import_nanoid2 = require("nanoid");
168
-
169
- // codec/json.ts
170
- var encoder = new TextEncoder();
171
- var decoder = new TextDecoder();
172
- function uint8ArrayToBase64(uint8Array) {
173
- let binary = "";
174
- uint8Array.forEach((byte) => {
175
- binary += String.fromCharCode(byte);
176
- });
177
- return btoa(binary);
178
- }
179
- function base64ToUint8Array(base64) {
180
- const binaryString = atob(base64);
181
- const uint8Array = new Uint8Array(binaryString.length);
182
- for (let i = 0; i < binaryString.length; i++) {
183
- uint8Array[i] = binaryString.charCodeAt(i);
184
- }
185
- return uint8Array;
186
- }
187
- var NaiveJsonCodec = {
188
- toBuffer: (obj) => {
189
- return encoder.encode(
190
- JSON.stringify(obj, function replacer(key) {
191
- const val = this[key];
192
- if (val instanceof Uint8Array) {
193
- return { $t: uint8ArrayToBase64(val) };
194
- } else {
195
- return val;
196
- }
197
- })
198
- );
199
- },
200
- fromBuffer: (buff) => {
201
- try {
202
- const parsed = JSON.parse(
203
- decoder.decode(buff),
204
- function reviver(_key, val) {
205
- if (val?.$t) {
206
- return base64ToUint8Array(val.$t);
207
- } else {
208
- return val;
209
- }
210
- }
211
- );
212
- if (typeof parsed === "object")
213
- return parsed;
214
- return null;
215
- } catch {
216
- return null;
217
- }
218
- }
219
- };
220
-
221
- // transport/session.ts
222
168
  var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
223
169
  var unsafeId = () => nanoid2();
224
170
  var Connection = class {
@@ -227,15 +173,6 @@ var Connection = class {
227
173
  this.debugId = `conn-${unsafeId()}`;
228
174
  }
229
175
  };
230
- var HEARTBEAT_INTERVAL_MS = 1e3;
231
- var HEARTBEATS_TILL_DEAD = 2;
232
- var SESSION_DISCONNECT_GRACE_MS = 5e3;
233
- var defaultSessionOptions = {
234
- heartbeatIntervalMs: HEARTBEAT_INTERVAL_MS,
235
- heartbeatsUntilDead: HEARTBEATS_TILL_DEAD,
236
- sessionDisconnectGraceMs: SESSION_DISCONNECT_GRACE_MS,
237
- codec: NaiveJsonCodec
238
- };
239
176
  var Session = class {
240
177
  codec;
241
178
  options;
@@ -430,14 +367,147 @@ function coerceErrorString(err) {
430
367
  return `[coerced to error] ${String(err)}`;
431
368
  }
432
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
+
433
494
  // transport/transport.ts
434
- var RECONNECT_JITTER_MAX_MS = 500;
435
- var RECONNECT_INTERVAL_MS = 250;
436
495
  var defaultTransportOptions = {
437
- retryIntervalMs: RECONNECT_INTERVAL_MS,
438
- retryJitterMs: RECONNECT_JITTER_MAX_MS,
439
- retryAttemptsMax: 5,
440
- ...defaultSessionOptions
496
+ heartbeatIntervalMs: 1e3,
497
+ heartbeatsUntilDead: 2,
498
+ sessionDisconnectGraceMs: 5e3,
499
+ codec: NaiveJsonCodec
500
+ };
501
+ var defaultConnectionRetryOptions = {
502
+ baseIntervalMs: 250,
503
+ maxJitterMs: 200,
504
+ maxBackoffMs: 32e3,
505
+ attemptBudgetCapacity: 15,
506
+ budgetRestoreIntervalMs: 200
507
+ };
508
+ var defaultClientTransportOptions = {
509
+ connectionRetryOptions: defaultConnectionRetryOptions,
510
+ ...defaultTransportOptions
441
511
  };
442
512
  var Transport = class {
443
513
  /**
@@ -712,14 +782,26 @@ var Transport = class {
712
782
  }
713
783
  };
714
784
  var ClientTransport = class extends Transport {
785
+ /**
786
+ * The options for this transport.
787
+ */
788
+ options;
715
789
  /**
716
790
  * The map of reconnect promises for each client ID.
717
791
  */
718
792
  inflightConnectionPromises;
793
+ retryBudget;
719
794
  tryReconnecting = true;
720
795
  constructor(clientId, providedOptions) {
721
796
  super(clientId, providedOptions);
797
+ this.options = {
798
+ ...defaultClientTransportOptions,
799
+ ...providedOptions
800
+ };
722
801
  this.inflightConnectionPromises = /* @__PURE__ */ new Map();
802
+ this.retryBudget = new LeakyBucketRateLimit(
803
+ this.options.connectionRetryOptions
804
+ );
723
805
  }
724
806
  handleConnection(conn, to) {
725
807
  if (this.state !== "open")
@@ -750,7 +832,10 @@ var ClientTransport = class extends Transport {
750
832
  log?.info(
751
833
  `${this.clientId} -- connection (id: ${conn.debugId}) to ${to} disconnected`
752
834
  );
753
- void this.connect(to);
835
+ this.inflightConnectionPromises.delete(to);
836
+ if (this.tryReconnecting) {
837
+ void this.connect(to);
838
+ }
754
839
  });
755
840
  conn.addErrorListener((err) => {
756
841
  log?.warn(
@@ -801,41 +886,64 @@ var ClientTransport = class extends Transport {
801
886
  * Manually attempts to connect to a client.
802
887
  * @param to The client ID of the node to connect to.
803
888
  */
804
- async connect(to, attempt = 0) {
805
- if (this.state !== "open" || !this.tryReconnecting) {
889
+ async connect(to) {
890
+ const canProceedWithConnection = () => this.state === "open";
891
+ if (!canProceedWithConnection()) {
806
892
  log?.info(
807
- `${this.clientId} -- transport state is no longer open, not attempting connection`
893
+ `${this.clientId} -- transport state is no longer open, cancelling attempt to connect to ${to}`
808
894
  );
809
895
  return;
810
896
  }
811
897
  let reconnectPromise = this.inflightConnectionPromises.get(to);
812
898
  if (!reconnectPromise) {
813
- reconnectPromise = this.createNewOutgoingConnection(to).then((conn) => {
899
+ log?.info(`${this.clientId} -- attempting connection to ${to}`);
900
+ const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
901
+ if (!this.retryBudget.hasBudget(to)) {
902
+ const errMsg = `not attempting to connect to ${to}, retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
903
+ log?.warn(`${this.clientId} -- ${errMsg}`);
904
+ this.protocolError(ProtocolError.RetriesExceeded, errMsg);
905
+ return;
906
+ }
907
+ let sleep = Promise.resolve();
908
+ const backoffMs = this.retryBudget.getBackoffMs(to);
909
+ if (backoffMs > 0) {
910
+ sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
911
+ }
912
+ this.retryBudget.consumeBudget(to);
913
+ reconnectPromise = sleep.then(() => {
914
+ if (!canProceedWithConnection()) {
915
+ throw new Error("transport state is no longer open");
916
+ }
917
+ }).then(() => this.createNewOutgoingConnection(to)).then((conn) => {
918
+ if (!canProceedWithConnection()) {
919
+ log?.info(
920
+ `${this.clientId} -- transport state is no longer open, closing pre-handshake connection (id: ${conn.debugId}) to ${to}`
921
+ );
922
+ conn.close();
923
+ throw new Error("transport state is no longer open");
924
+ }
925
+ this.retryBudget.startRestoringBudget(to);
814
926
  this.sendHandshake(to, conn);
815
927
  return conn;
816
928
  });
817
929
  this.inflightConnectionPromises.set(to, reconnectPromise);
930
+ } else {
931
+ log?.info(
932
+ `${this.clientId} -- attempting connection to ${to} (reusing previous attempt)`
933
+ );
818
934
  }
819
935
  try {
820
936
  await reconnectPromise;
821
937
  } catch (error) {
822
- const errStr = coerceErrorString(error);
823
938
  this.inflightConnectionPromises.delete(to);
824
- const shouldRetry = this.state === "open" && this.tryReconnecting;
825
- if (!shouldRetry)
826
- return;
827
- if (attempt >= this.options.retryAttemptsMax) {
828
- const errMsg = `connection to ${to} failed after ${attempt} attempts (${errStr}), giving up`;
829
- log?.error(`${this.clientId} -- ${errMsg}`);
830
- this.protocolError(ProtocolError.RetriesExceeded, errMsg);
831
- return;
939
+ const errStr = coerceErrorString(error);
940
+ if (!this.tryReconnecting || !canProceedWithConnection()) {
941
+ log?.warn(`${this.clientId} -- connection to ${to} failed (${errStr})`);
832
942
  } else {
833
- const jitter = Math.floor(Math.random() * this.options.retryJitterMs);
834
- const backoffMs = this.options.retryIntervalMs * 2 ** attempt + jitter;
835
943
  log?.warn(
836
- `${this.clientId} -- connection to ${to} failed (${errStr}), trying again in ${backoffMs}ms`
944
+ `${this.clientId} -- connection to ${to} failed (${errStr}), retrying`
837
945
  );
838
- setTimeout(() => void this.connect(to, attempt + 1), backoffMs);
946
+ return this.connect(to);
839
947
  }
840
948
  }
841
949
  }
@@ -848,9 +956,9 @@ var ClientTransport = class extends Transport {
848
956
  log?.debug(`${this.clientId} -- sending handshake request to ${to}`);
849
957
  conn.send(this.codec.toBuffer(requestMsg));
850
958
  }
851
- onDisconnect(conn, session) {
852
- this.inflightConnectionPromises.delete(session.to);
853
- super.onDisconnect(conn, session);
959
+ close() {
960
+ this.retryBudget.close();
961
+ super.close();
854
962
  }
855
963
  };
856
964
  var ServerTransport = class extends 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 ProtocolError, n 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-76b801f8.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, S as ServerTransport, e as Session, T as Transport, b as TransportClientId, i as TransportMessage, g as TransportMessageSchema, d as TransportOptions, f as TransportStatus, k as isStreamClose, j as isStreamOpen } from '../index-2e402bb8.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 ProtocolError, n 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-76b801f8.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, S as ServerTransport, e as Session, T as Transport, b as TransportClientId, i as TransportMessage, g as TransportMessageSchema, d as TransportOptions, f as TransportStatus, k as isStreamClose, j as isStreamOpen } from '../index-2e402bb8.js';
2
2
  import '../types-3e5768ec.js';
3
3
  import '@sinclair/typebox';
@@ -6,7 +6,7 @@ import {
6
6
  ServerTransport,
7
7
  Session,
8
8
  Transport
9
- } from "../chunk-O6YQ3JAH.js";
9
+ } from "../chunk-5XMMDOLH.js";
10
10
  import {
11
11
  OpaqueTransportMessageSchema,
12
12
  TransportMessageSchema
@@ -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-76b801f8.js';
5
- import { P as PayloadType, R as RiverError, a as Procedure, S as ServiceContext, b as Result, c as RiverUncaughtSchema } from '../builder-660d3140.js';
5
+ import { P as PartialTransportMessage, T as Transport, C as Connection, O as OpaqueTransportMessage } from '../index-2e402bb8.js';
6
+ import { P as PayloadType, R as RiverError, a as Procedure, S as ServiceContext, b as Result, c as RiverUncaughtSchema } from '../builder-4d392f6c.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 };
@@ -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-76b801f8.js';
5
- import { P as PayloadType, R as RiverError, a as Procedure, S as ServiceContext, b as Result, c as RiverUncaughtSchema } from '../builder-660d3140.js';
5
+ import { P as PartialTransportMessage, T as Transport, C as Connection, O as OpaqueTransportMessage } from '../index-2e402bb8.js';
6
+ import { P as PayloadType, R as RiverError, a as Procedure, S as ServiceContext, b as Result, c as RiverUncaughtSchema } from '../builder-4d392f6c.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 };
@@ -4,14 +4,15 @@ import {
4
4
  } from "../chunk-KWXQLQAF.js";
5
5
  import "../chunk-RPIDSIQG.js";
6
6
  import {
7
- Session,
8
- defaultSessionOptions
9
- } from "../chunk-O6YQ3JAH.js";
7
+ Session
8
+ } from "../chunk-5XMMDOLH.js";
10
9
  import {
11
10
  coerceErrorString
12
11
  } from "../chunk-GFRAOY75.js";
13
12
  import "../chunk-H4BYJELI.js";
14
- import "../chunk-GZ7HCLLM.js";
13
+ import {
14
+ NaiveJsonCodec
15
+ } from "../chunk-GZ7HCLLM.js";
15
16
 
16
17
  // util/testHelpers.ts
17
18
  import WebSocket from "isomorphic-ws";
@@ -85,12 +86,18 @@ function catchProcError(err) {
85
86
  }
86
87
  };
87
88
  }
89
+ var testingSessionOptions = {
90
+ heartbeatIntervalMs: 1e3,
91
+ heartbeatsUntilDead: 2,
92
+ sessionDisconnectGraceMs: 5e3,
93
+ codec: NaiveJsonCodec
94
+ };
88
95
  function dummyCtx(state, extendedContext) {
89
96
  const session = new Session(
90
97
  "client",
91
98
  "SERVER",
92
99
  void 0,
93
- defaultSessionOptions
100
+ testingSessionOptions
94
101
  );
95
102
  return {
96
103
  ...extendedContext,
@@ -161,5 +168,6 @@ export {
161
168
  onUdsServeReady,
162
169
  onWsServerReady,
163
170
  payloadToTransportMessage,
171
+ testingSessionOptions,
164
172
  waitForMessage
165
173
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@replit/river",
3
3
  "description": "It's like tRPC but... with JSON Schema Support, duplex streaming and support for service multiplexing. Transport agnostic!",
4
- "version": "0.15.1",
4
+ "version": "0.15.3",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": {