@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
@@ -1,6 +1,6 @@
1
- import { A as AnyService, P as PayloadType, b as Result, R as RiverError, S as ServiceContext, d as ProcType, e as ProcInput, f as ProcOutput, g as ProcErrors, h as ProcHasInit, i as ProcInit } from '../builder-ca6c4259.js';
2
- export { E as Err, O as Ok, m as ProcHandler, k as ProcListing, a as Procedure, p as RiverErrorSchema, c as RiverUncaughtSchema, l as Service, j as ServiceBuilder, n as ServiceContextWithState, o as ServiceContextWithTransportInfo, U as UNCAUGHT_ERROR, V as ValidProcType, s as serializeService } from '../builder-ca6c4259.js';
3
- import { S as ServerTransport, C as Connection, a as ClientTransport, b as TransportClientId } from '../index-f922ec84.js';
1
+ import { A as AnyService, P as PayloadType, b as Result, R as RiverError, S as ServiceContext, d as ProcType, e as ProcInput, f as ProcOutput, g as ProcErrors, h as ProcHasInit, i as ProcInit } from '../builder-ebd945c0.js';
2
+ export { E as Err, O as Ok, m as ProcHandler, k as ProcListing, a as Procedure, p as RiverErrorSchema, c as RiverUncaughtSchema, l as Service, j as ServiceBuilder, n as ServiceContextWithState, o as ServiceContextWithTransportInfo, U as UNCAUGHT_ERROR, V as ValidProcType, s as serializeService } from '../builder-ebd945c0.js';
3
+ import { S as ServerTransport, C as Connection, a as ClientTransport, b as TransportClientId } from '../index-bbccacef.js';
4
4
  import { Pushable } from 'it-pushable';
5
5
  import { Static } from '@sinclair/typebox';
6
6
  import '../types-3e5768ec.js';
@@ -1,6 +1,6 @@
1
- import { A as AnyService, P as PayloadType, b as Result, R as RiverError, S as ServiceContext, d as ProcType, e as ProcInput, f as ProcOutput, g as ProcErrors, h as ProcHasInit, i as ProcInit } from '../builder-ca6c4259.js';
2
- export { E as Err, O as Ok, m as ProcHandler, k as ProcListing, a as Procedure, p as RiverErrorSchema, c as RiverUncaughtSchema, l as Service, j as ServiceBuilder, n as ServiceContextWithState, o as ServiceContextWithTransportInfo, U as UNCAUGHT_ERROR, V as ValidProcType, s as serializeService } from '../builder-ca6c4259.js';
3
- import { S as ServerTransport, C as Connection, a as ClientTransport, b as TransportClientId } from '../index-f922ec84.js';
1
+ import { A as AnyService, P as PayloadType, b as Result, R as RiverError, S as ServiceContext, d as ProcType, e as ProcInput, f as ProcOutput, g as ProcErrors, h as ProcHasInit, i as ProcInit } from '../builder-ebd945c0.js';
2
+ export { E as Err, O as Ok, m as ProcHandler, k as ProcListing, a as Procedure, p as RiverErrorSchema, c as RiverUncaughtSchema, l as Service, j as ServiceBuilder, n as ServiceContextWithState, o as ServiceContextWithTransportInfo, U as UNCAUGHT_ERROR, V as ValidProcType, s as serializeService } from '../builder-ebd945c0.js';
3
+ import { S as ServerTransport, C as Connection, a as ClientTransport, b as TransportClientId } from '../index-bbccacef.js';
4
4
  import { Pushable } from 'it-pushable';
5
5
  import { Static } from '@sinclair/typebox';
6
6
  import '../types-3e5768ec.js';
@@ -100,58 +100,6 @@ function isAck(controlFlag) {
100
100
  return (controlFlag & 1 /* AckBit */) === 1 /* AckBit */;
101
101
  }
102
102
 
103
- // codec/json.ts
104
- var encoder = new TextEncoder();
105
- var decoder = new TextDecoder();
106
- function uint8ArrayToBase64(uint8Array) {
107
- let binary = "";
108
- uint8Array.forEach((byte) => {
109
- binary += String.fromCharCode(byte);
110
- });
111
- return btoa(binary);
112
- }
113
- function base64ToUint8Array(base64) {
114
- const binaryString = atob(base64);
115
- const uint8Array = new Uint8Array(binaryString.length);
116
- for (let i = 0; i < binaryString.length; i++) {
117
- uint8Array[i] = binaryString.charCodeAt(i);
118
- }
119
- return uint8Array;
120
- }
121
- var NaiveJsonCodec = {
122
- toBuffer: (obj) => {
123
- return encoder.encode(
124
- JSON.stringify(obj, function replacer(key) {
125
- const val = this[key];
126
- if (val instanceof Uint8Array) {
127
- return { $t: uint8ArrayToBase64(val) };
128
- } else {
129
- return val;
130
- }
131
- })
132
- );
133
- },
134
- fromBuffer: (buff) => {
135
- try {
136
- const parsed = JSON.parse(
137
- decoder.decode(buff),
138
- function reviver(_key, val) {
139
- if (val?.$t) {
140
- return base64ToUint8Array(val.$t);
141
- } else {
142
- return val;
143
- }
144
- }
145
- );
146
- if (typeof parsed === "object")
147
- return parsed;
148
- return null;
149
- } catch {
150
- return null;
151
- }
152
- }
153
- };
154
-
155
103
  // transport/session.ts
156
104
  var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
157
105
  var unsafeId = () => nanoid2();
@@ -161,15 +109,6 @@ var Connection = class {
161
109
  this.debugId = `conn-${unsafeId()}`;
162
110
  }
163
111
  };
164
- var HEARTBEAT_INTERVAL_MS = 1e3;
165
- var HEARTBEATS_TILL_DEAD = 2;
166
- var SESSION_DISCONNECT_GRACE_MS = 5e3;
167
- var defaultSessionOptions = {
168
- heartbeatIntervalMs: HEARTBEAT_INTERVAL_MS,
169
- heartbeatsUntilDead: HEARTBEATS_TILL_DEAD,
170
- sessionDisconnectGraceMs: SESSION_DISCONNECT_GRACE_MS,
171
- codec: NaiveJsonCodec
172
- };
173
112
  var Session = class {
174
113
  codec;
175
114
  options;
@@ -450,6 +389,11 @@ var UdsConnection = class extends Connection {
450
389
  var import_value = require("@sinclair/typebox/value");
451
390
 
452
391
  // transport/events.ts
392
+ var ProtocolError = {
393
+ RetriesExceeded: "conn_retry_exceeded",
394
+ HandshakeFailed: "handshake_failed",
395
+ UseAfterDestroy: "use_after_destroy"
396
+ };
453
397
  var EventDispatcher = class {
454
398
  eventListeners = {};
455
399
  numberOfListeners(eventType) {
@@ -488,14 +432,146 @@ function coerceErrorString(err) {
488
432
  return `[coerced to error] ${String(err)}`;
489
433
  }
490
434
 
435
+ // transport/rateLimit.ts
436
+ var LeakyBucketRateLimit = class {
437
+ budgetConsumed;
438
+ intervalHandles;
439
+ options;
440
+ constructor(options) {
441
+ this.options = options;
442
+ this.budgetConsumed = /* @__PURE__ */ new Map();
443
+ this.intervalHandles = /* @__PURE__ */ new Map();
444
+ }
445
+ getBackoffMs(user) {
446
+ if (!this.budgetConsumed.has(user))
447
+ return 0;
448
+ const exponent = Math.max(0, this.getBudgetConsumed(user) - 1);
449
+ const jitter = Math.floor(Math.random() * this.options.maxJitterMs);
450
+ const backoffMs = Math.min(
451
+ this.options.baseIntervalMs * 2 ** exponent,
452
+ this.options.maxBackoffMs
453
+ );
454
+ return backoffMs + jitter;
455
+ }
456
+ get totalBudgetRestoreTime() {
457
+ return this.options.budgetRestoreIntervalMs * this.options.attemptBudgetCapacity;
458
+ }
459
+ consumeBudget(user) {
460
+ this.stopLeak(user);
461
+ this.budgetConsumed.set(user, this.getBudgetConsumed(user) + 1);
462
+ }
463
+ getBudgetConsumed(user) {
464
+ return this.budgetConsumed.get(user) ?? 0;
465
+ }
466
+ hasBudget(user) {
467
+ return this.getBudgetConsumed(user) < this.options.attemptBudgetCapacity;
468
+ }
469
+ startRestoringBudget(user) {
470
+ if (this.intervalHandles.has(user)) {
471
+ return;
472
+ }
473
+ const restoreBudgetForUser = () => {
474
+ const currentBudget = this.budgetConsumed.get(user);
475
+ if (!currentBudget) {
476
+ this.stopLeak(user);
477
+ return;
478
+ }
479
+ const newBudget = currentBudget - 1;
480
+ if (newBudget === 0) {
481
+ this.budgetConsumed.delete(user);
482
+ return;
483
+ }
484
+ this.budgetConsumed.set(user, newBudget);
485
+ };
486
+ restoreBudgetForUser();
487
+ const intervalHandle = setInterval(
488
+ restoreBudgetForUser,
489
+ this.options.budgetRestoreIntervalMs
490
+ );
491
+ this.intervalHandles.set(user, intervalHandle);
492
+ }
493
+ stopLeak(user) {
494
+ if (!this.intervalHandles.has(user)) {
495
+ return;
496
+ }
497
+ clearInterval(this.intervalHandles.get(user));
498
+ this.intervalHandles.delete(user);
499
+ }
500
+ close() {
501
+ for (const user of this.intervalHandles.keys()) {
502
+ this.stopLeak(user);
503
+ }
504
+ }
505
+ };
506
+
507
+ // codec/json.ts
508
+ var encoder = new TextEncoder();
509
+ var decoder = new TextDecoder();
510
+ function uint8ArrayToBase64(uint8Array) {
511
+ let binary = "";
512
+ uint8Array.forEach((byte) => {
513
+ binary += String.fromCharCode(byte);
514
+ });
515
+ return btoa(binary);
516
+ }
517
+ function base64ToUint8Array(base64) {
518
+ const binaryString = atob(base64);
519
+ const uint8Array = new Uint8Array(binaryString.length);
520
+ for (let i = 0; i < binaryString.length; i++) {
521
+ uint8Array[i] = binaryString.charCodeAt(i);
522
+ }
523
+ return uint8Array;
524
+ }
525
+ var NaiveJsonCodec = {
526
+ toBuffer: (obj) => {
527
+ return encoder.encode(
528
+ JSON.stringify(obj, function replacer(key) {
529
+ const val = this[key];
530
+ if (val instanceof Uint8Array) {
531
+ return { $t: uint8ArrayToBase64(val) };
532
+ } else {
533
+ return val;
534
+ }
535
+ })
536
+ );
537
+ },
538
+ fromBuffer: (buff) => {
539
+ try {
540
+ const parsed = JSON.parse(
541
+ decoder.decode(buff),
542
+ function reviver(_key, val) {
543
+ if (val?.$t) {
544
+ return base64ToUint8Array(val.$t);
545
+ } else {
546
+ return val;
547
+ }
548
+ }
549
+ );
550
+ if (typeof parsed === "object")
551
+ return parsed;
552
+ return null;
553
+ } catch {
554
+ return null;
555
+ }
556
+ }
557
+ };
558
+
491
559
  // transport/transport.ts
492
- var RECONNECT_JITTER_MAX_MS = 500;
493
- var RECONNECT_INTERVAL_MS = 250;
494
560
  var defaultTransportOptions = {
495
- retryIntervalMs: RECONNECT_INTERVAL_MS,
496
- retryJitterMs: RECONNECT_JITTER_MAX_MS,
497
- retryAttemptsMax: 5,
498
- ...defaultSessionOptions
561
+ heartbeatIntervalMs: 1e3,
562
+ heartbeatsUntilDead: 2,
563
+ sessionDisconnectGraceMs: 5e3,
564
+ codec: NaiveJsonCodec
565
+ };
566
+ var defaultClientTransportOptions = {
567
+ connectionRetryOptions: {
568
+ baseIntervalMs: 250,
569
+ maxJitterMs: 200,
570
+ maxBackoffMs: 32e3,
571
+ attemptBudgetCapacity: 15,
572
+ budgetRestoreIntervalMs: 200
573
+ },
574
+ ...defaultTransportOptions
499
575
  };
500
576
  var Transport = class {
501
577
  /**
@@ -710,7 +786,7 @@ var Transport = class {
710
786
  if (this.state === "destroyed") {
711
787
  const err = "transport is destroyed, cant send";
712
788
  log?.error(`${this.clientId} -- ` + err + `: ${JSON.stringify(msg)}`);
713
- this.protocolError("use_after_destroy" /* UseAfterDestroy */, err);
789
+ this.protocolError(ProtocolError.UseAfterDestroy, err);
714
790
  return void 0;
715
791
  } else if (this.state === "closed") {
716
792
  log?.info(
@@ -770,14 +846,26 @@ var Transport = class {
770
846
  }
771
847
  };
772
848
  var ClientTransport = class extends Transport {
849
+ /**
850
+ * The options for this transport.
851
+ */
852
+ options;
773
853
  /**
774
854
  * The map of reconnect promises for each client ID.
775
855
  */
776
856
  inflightConnectionPromises;
857
+ retryBudget;
777
858
  tryReconnecting = true;
778
859
  constructor(clientId, providedOptions) {
779
860
  super(clientId, providedOptions);
861
+ this.options = {
862
+ ...defaultClientTransportOptions,
863
+ ...providedOptions
864
+ };
780
865
  this.inflightConnectionPromises = /* @__PURE__ */ new Map();
866
+ this.retryBudget = new LeakyBucketRateLimit(
867
+ this.options.connectionRetryOptions
868
+ );
781
869
  }
782
870
  handleConnection(conn, to) {
783
871
  if (this.state !== "open")
@@ -808,7 +896,10 @@ var ClientTransport = class extends Transport {
808
896
  log?.info(
809
897
  `${this.clientId} -- connection (id: ${conn.debugId}) to ${to} disconnected`
810
898
  );
811
- void this.connect(to);
899
+ this.inflightConnectionPromises.delete(to);
900
+ if (this.tryReconnecting) {
901
+ void this.connect(to);
902
+ }
812
903
  });
813
904
  conn.addErrorListener((err) => {
814
905
  log?.warn(
@@ -820,7 +911,7 @@ var ClientTransport = class extends Transport {
820
911
  const parsed = this.parseMsg(data);
821
912
  if (!parsed) {
822
913
  this.protocolError(
823
- "handshake_failed" /* HandshakeFailed */,
914
+ ProtocolError.HandshakeFailed,
824
915
  "received non-transport message"
825
916
  );
826
917
  return false;
@@ -832,7 +923,7 @@ var ClientTransport = class extends Transport {
832
923
  )}`
833
924
  );
834
925
  this.protocolError(
835
- "handshake_failed" /* HandshakeFailed */,
926
+ ProtocolError.HandshakeFailed,
836
927
  "invalid handshake resp"
837
928
  );
838
929
  return false;
@@ -844,7 +935,7 @@ var ClientTransport = class extends Transport {
844
935
  )}`
845
936
  );
846
937
  this.protocolError(
847
- "handshake_failed" /* HandshakeFailed */,
938
+ ProtocolError.HandshakeFailed,
848
939
  parsed.payload.status.reason
849
940
  );
850
941
  return false;
@@ -859,41 +950,64 @@ var ClientTransport = class extends Transport {
859
950
  * Manually attempts to connect to a client.
860
951
  * @param to The client ID of the node to connect to.
861
952
  */
862
- async connect(to, attempt = 0) {
863
- if (this.state !== "open" || !this.tryReconnecting) {
953
+ async connect(to) {
954
+ const canProceedWithConnection = () => this.state === "open";
955
+ if (!canProceedWithConnection()) {
864
956
  log?.info(
865
- `${this.clientId} -- transport state is no longer open, not attempting connection`
957
+ `${this.clientId} -- transport state is no longer open, cancelling attempt to connect to ${to}`
866
958
  );
867
959
  return;
868
960
  }
869
961
  let reconnectPromise = this.inflightConnectionPromises.get(to);
870
962
  if (!reconnectPromise) {
871
- reconnectPromise = this.createNewOutgoingConnection(to).then((conn) => {
963
+ log?.info(`${this.clientId} -- attempting connection to ${to}`);
964
+ const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
965
+ if (!this.retryBudget.hasBudget(to)) {
966
+ const errMsg = `not attempting to connect to ${to}, retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
967
+ log?.warn(`${this.clientId} -- ${errMsg}`);
968
+ this.protocolError(ProtocolError.RetriesExceeded, errMsg);
969
+ return;
970
+ }
971
+ let sleep = Promise.resolve();
972
+ const backoffMs = this.retryBudget.getBackoffMs(to);
973
+ if (backoffMs > 0) {
974
+ sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
975
+ }
976
+ this.retryBudget.consumeBudget(to);
977
+ reconnectPromise = sleep.then(() => {
978
+ if (!canProceedWithConnection()) {
979
+ throw new Error("transport state is no longer open");
980
+ }
981
+ }).then(() => this.createNewOutgoingConnection(to)).then((conn) => {
982
+ if (!canProceedWithConnection()) {
983
+ log?.info(
984
+ `${this.clientId} -- transport state is no longer open, closing pre-handshake connection (id: ${conn.debugId}) to ${to}`
985
+ );
986
+ conn.close();
987
+ throw new Error("transport state is no longer open");
988
+ }
989
+ this.retryBudget.startRestoringBudget(to);
872
990
  this.sendHandshake(to, conn);
873
991
  return conn;
874
992
  });
875
993
  this.inflightConnectionPromises.set(to, reconnectPromise);
994
+ } else {
995
+ log?.info(
996
+ `${this.clientId} -- attempting connection to ${to} (reusing previous attempt)`
997
+ );
876
998
  }
877
999
  try {
878
1000
  await reconnectPromise;
879
1001
  } catch (error) {
880
- const errStr = coerceErrorString(error);
881
1002
  this.inflightConnectionPromises.delete(to);
882
- const shouldRetry = this.state === "open" && this.tryReconnecting;
883
- if (!shouldRetry)
884
- return;
885
- if (attempt >= this.options.retryAttemptsMax) {
886
- const errMsg = `connection to ${to} failed after ${attempt} attempts (${errStr}), giving up`;
887
- log?.error(`${this.clientId} -- ${errMsg}`);
888
- this.protocolError("conn_retry_exceeded" /* RetriesExceeded */, errMsg);
889
- return;
1003
+ const errStr = coerceErrorString(error);
1004
+ if (!this.tryReconnecting || !canProceedWithConnection()) {
1005
+ log?.warn(`${this.clientId} -- connection to ${to} failed (${errStr})`);
890
1006
  } else {
891
- const jitter = Math.floor(Math.random() * this.options.retryJitterMs);
892
- const backoffMs = this.options.retryIntervalMs * 2 ** attempt + jitter;
893
1007
  log?.warn(
894
- `${this.clientId} -- connection to ${to} failed (${errStr}), trying again in ${backoffMs}ms`
1008
+ `${this.clientId} -- connection to ${to} failed (${errStr}), retrying`
895
1009
  );
896
- setTimeout(() => void this.connect(to, attempt + 1), backoffMs);
1010
+ return this.connect(to);
897
1011
  }
898
1012
  }
899
1013
  }
@@ -906,9 +1020,9 @@ var ClientTransport = class extends Transport {
906
1020
  log?.debug(`${this.clientId} -- sending handshake request to ${to}`);
907
1021
  conn.send(this.codec.toBuffer(requestMsg));
908
1022
  }
909
- onDisconnect(conn, session) {
910
- this.inflightConnectionPromises.delete(session.to);
911
- super.onDisconnect(conn, session);
1023
+ close() {
1024
+ this.retryBudget.close();
1025
+ super.close();
912
1026
  }
913
1027
  };
914
1028
 
@@ -1,5 +1,5 @@
1
- import { a as ClientTransport, c as TransportOptions, b as TransportClientId } from '../../../index-f922ec84.js';
2
- import { U as UdsConnection } from '../../../connection-0c5eeb14.js';
1
+ import { a as ClientTransport, c as ProvidedClientTransportOptions, b as TransportClientId } from '../../../index-bbccacef.js';
2
+ import { U as UdsConnection } from '../../../connection-10a24478.js';
3
3
  import '../../../types-3e5768ec.js';
4
4
  import '@sinclair/typebox';
5
5
  import 'node:net';
@@ -7,7 +7,7 @@ import 'node:stream';
7
7
 
8
8
  declare class UnixDomainSocketClientTransport extends ClientTransport<UdsConnection> {
9
9
  path: string;
10
- constructor(socketPath: string, clientId: string, providedOptions?: Partial<TransportOptions>);
10
+ constructor(socketPath: string, clientId: string, providedOptions?: ProvidedClientTransportOptions);
11
11
  createNewOutgoingConnection(to: TransportClientId): Promise<UdsConnection>;
12
12
  }
13
13
 
@@ -1,5 +1,5 @@
1
- import { a as ClientTransport, c as TransportOptions, b as TransportClientId } from '../../../index-f922ec84.js';
2
- import { U as UdsConnection } from '../../../connection-0c5eeb14.js';
1
+ import { a as ClientTransport, c as ProvidedClientTransportOptions, b as TransportClientId } from '../../../index-bbccacef.js';
2
+ import { U as UdsConnection } from '../../../connection-10a24478.js';
3
3
  import '../../../types-3e5768ec.js';
4
4
  import '@sinclair/typebox';
5
5
  import 'node:net';
@@ -7,7 +7,7 @@ import 'node:stream';
7
7
 
8
8
  declare class UnixDomainSocketClientTransport extends ClientTransport<UdsConnection> {
9
9
  path: string;
10
- constructor(socketPath: string, clientId: string, providedOptions?: Partial<TransportOptions>);
10
+ constructor(socketPath: string, clientId: string, providedOptions?: ProvidedClientTransportOptions);
11
11
  createNewOutgoingConnection(to: TransportClientId): Promise<UdsConnection>;
12
12
  }
13
13
 
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  UdsConnection
3
- } from "../../../chunk-BSAIT634.js";
3
+ } from "../../../chunk-UJHTHOTT.js";
4
4
  import {
5
5
  ClientTransport
6
- } from "../../../chunk-IVNV5HBI.js";
6
+ } from "../../../chunk-B7VTDQR7.js";
7
7
  import "../../../chunk-GFRAOY75.js";
8
8
  import {
9
9
  log
@@ -108,6 +108,11 @@ function isAck(controlFlag) {
108
108
  }
109
109
 
110
110
  // transport/events.ts
111
+ var ProtocolError = {
112
+ RetriesExceeded: "conn_retry_exceeded",
113
+ HandshakeFailed: "handshake_failed",
114
+ UseAfterDestroy: "use_after_destroy"
115
+ };
111
116
  var EventDispatcher = class {
112
117
  eventListeners = {};
113
118
  numberOfListeners(eventType) {
@@ -137,60 +142,6 @@ var EventDispatcher = class {
137
142
 
138
143
  // transport/session.ts
139
144
  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
194
145
  var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
195
146
  var unsafeId = () => nanoid2();
196
147
  var Connection = class {
@@ -199,15 +150,6 @@ var Connection = class {
199
150
  this.debugId = `conn-${unsafeId()}`;
200
151
  }
201
152
  };
202
- var HEARTBEAT_INTERVAL_MS = 1e3;
203
- var HEARTBEATS_TILL_DEAD = 2;
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
- };
211
153
  var Session = class {
212
154
  codec;
213
155
  options;
@@ -402,14 +344,74 @@ function coerceErrorString(err) {
402
344
  return `[coerced to error] ${String(err)}`;
403
345
  }
404
346
 
347
+ // codec/json.ts
348
+ var encoder = new TextEncoder();
349
+ var decoder = new TextDecoder();
350
+ function uint8ArrayToBase64(uint8Array) {
351
+ let binary = "";
352
+ uint8Array.forEach((byte) => {
353
+ binary += String.fromCharCode(byte);
354
+ });
355
+ return btoa(binary);
356
+ }
357
+ function base64ToUint8Array(base64) {
358
+ const binaryString = atob(base64);
359
+ const uint8Array = new Uint8Array(binaryString.length);
360
+ for (let i = 0; i < binaryString.length; i++) {
361
+ uint8Array[i] = binaryString.charCodeAt(i);
362
+ }
363
+ return uint8Array;
364
+ }
365
+ var NaiveJsonCodec = {
366
+ toBuffer: (obj) => {
367
+ return encoder.encode(
368
+ JSON.stringify(obj, function replacer(key) {
369
+ const val = this[key];
370
+ if (val instanceof Uint8Array) {
371
+ return { $t: uint8ArrayToBase64(val) };
372
+ } else {
373
+ return val;
374
+ }
375
+ })
376
+ );
377
+ },
378
+ fromBuffer: (buff) => {
379
+ try {
380
+ const parsed = JSON.parse(
381
+ decoder.decode(buff),
382
+ function reviver(_key, val) {
383
+ if (val?.$t) {
384
+ return base64ToUint8Array(val.$t);
385
+ } else {
386
+ return val;
387
+ }
388
+ }
389
+ );
390
+ if (typeof parsed === "object")
391
+ return parsed;
392
+ return null;
393
+ } catch {
394
+ return null;
395
+ }
396
+ }
397
+ };
398
+
405
399
  // transport/transport.ts
406
- var RECONNECT_JITTER_MAX_MS = 500;
407
- var RECONNECT_INTERVAL_MS = 250;
408
400
  var defaultTransportOptions = {
409
- retryIntervalMs: RECONNECT_INTERVAL_MS,
410
- retryJitterMs: RECONNECT_JITTER_MAX_MS,
411
- retryAttemptsMax: 5,
412
- ...defaultSessionOptions
401
+ heartbeatIntervalMs: 1e3,
402
+ heartbeatsUntilDead: 2,
403
+ sessionDisconnectGraceMs: 5e3,
404
+ codec: NaiveJsonCodec
405
+ };
406
+ var defaultClientTransportOptions = {
407
+ connectionRetryOptions: {
408
+ baseIntervalMs: 250,
409
+ maxJitterMs: 200,
410
+ maxBackoffMs: 32e3,
411
+ attemptBudgetCapacity: 15,
412
+ budgetRestoreIntervalMs: 200
413
+ },
414
+ ...defaultTransportOptions
413
415
  };
414
416
  var Transport = class {
415
417
  /**
@@ -624,7 +626,7 @@ var Transport = class {
624
626
  if (this.state === "destroyed") {
625
627
  const err = "transport is destroyed, cant send";
626
628
  log?.error(`${this.clientId} -- ` + err + `: ${JSON.stringify(msg)}`);
627
- this.protocolError("use_after_destroy" /* UseAfterDestroy */, err);
629
+ this.protocolError(ProtocolError.UseAfterDestroy, err);
628
630
  return void 0;
629
631
  } else if (this.state === "closed") {
630
632
  log?.info(
@@ -736,7 +738,7 @@ var ServerTransport = class extends Transport {
736
738
  const parsed = this.parseMsg(data);
737
739
  if (!parsed) {
738
740
  this.protocolError(
739
- "handshake_failed" /* HandshakeFailed */,
741
+ ProtocolError.HandshakeFailed,
740
742
  "received non-transport message"
741
743
  );
742
744
  return false;
@@ -755,7 +757,7 @@ var ServerTransport = class extends Transport {
755
757
  )}`
756
758
  );
757
759
  this.protocolError(
758
- "handshake_failed" /* HandshakeFailed */,
760
+ ProtocolError.HandshakeFailed,
759
761
  "invalid handshake request"
760
762
  );
761
763
  return false;
@@ -773,7 +775,7 @@ var ServerTransport = class extends Transport {
773
775
  `${this.clientId} -- received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`
774
776
  );
775
777
  this.protocolError(
776
- "handshake_failed" /* HandshakeFailed */,
778
+ ProtocolError.HandshakeFailed,
777
779
  `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`
778
780
  );
779
781
  return false;