@replit/river 0.15.1 → 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.
- package/README.md +41 -22
- package/dist/{builder-660d3140.d.ts → builder-ebd945c0.d.ts} +1 -1
- package/dist/{chunk-O6YQ3JAH.js → chunk-B7VTDQR7.js} +147 -37
- package/dist/{chunk-MNWOTQWX.js → chunk-UJHTHOTT.js} +1 -1
- package/dist/{chunk-5TX4BKAD.js → chunk-ZRB6IKPV.js} +1 -1
- package/dist/{connection-162c0f7b.d.ts → connection-10a24478.d.ts} +1 -1
- package/dist/{connection-93daccc3.d.ts → connection-f4492948.d.ts} +1 -1
- package/dist/{index-76b801f8.d.ts → index-bbccacef.d.ts} +84 -11
- package/dist/router/index.d.cts +3 -3
- package/dist/router/index.d.ts +3 -3
- package/dist/transport/impls/uds/client.cjs +197 -88
- package/dist/transport/impls/uds/client.d.cts +3 -3
- package/dist/transport/impls/uds/client.d.ts +3 -3
- package/dist/transport/impls/uds/client.js +2 -2
- package/dist/transport/impls/uds/server.cjs +66 -69
- package/dist/transport/impls/uds/server.d.cts +3 -3
- package/dist/transport/impls/uds/server.d.ts +3 -3
- package/dist/transport/impls/uds/server.js +2 -2
- package/dist/transport/impls/ws/client.cjs +197 -90
- package/dist/transport/impls/ws/client.d.cts +3 -3
- package/dist/transport/impls/ws/client.d.ts +3 -3
- package/dist/transport/impls/ws/client.js +2 -2
- package/dist/transport/impls/ws/server.cjs +66 -69
- package/dist/transport/impls/ws/server.d.cts +3 -3
- package/dist/transport/impls/ws/server.d.ts +3 -3
- package/dist/transport/impls/ws/server.js +2 -2
- package/dist/transport/index.cjs +197 -90
- package/dist/transport/index.d.cts +1 -1
- package/dist/transport/index.d.ts +1 -1
- package/dist/transport/index.js +1 -1
- package/dist/util/testHelpers.cjs +61 -64
- package/dist/util/testHelpers.d.cts +10 -4
- package/dist/util/testHelpers.d.ts +10 -4
- package/dist/util/testHelpers.js +13 -5
- package/package.json +1 -1
package/dist/transport/index.cjs
CHANGED
|
@@ -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,146 @@ 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
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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
|
|
441
510
|
};
|
|
442
511
|
var Transport = class {
|
|
443
512
|
/**
|
|
@@ -712,14 +781,26 @@ var Transport = class {
|
|
|
712
781
|
}
|
|
713
782
|
};
|
|
714
783
|
var ClientTransport = class extends Transport {
|
|
784
|
+
/**
|
|
785
|
+
* The options for this transport.
|
|
786
|
+
*/
|
|
787
|
+
options;
|
|
715
788
|
/**
|
|
716
789
|
* The map of reconnect promises for each client ID.
|
|
717
790
|
*/
|
|
718
791
|
inflightConnectionPromises;
|
|
792
|
+
retryBudget;
|
|
719
793
|
tryReconnecting = true;
|
|
720
794
|
constructor(clientId, providedOptions) {
|
|
721
795
|
super(clientId, providedOptions);
|
|
796
|
+
this.options = {
|
|
797
|
+
...defaultClientTransportOptions,
|
|
798
|
+
...providedOptions
|
|
799
|
+
};
|
|
722
800
|
this.inflightConnectionPromises = /* @__PURE__ */ new Map();
|
|
801
|
+
this.retryBudget = new LeakyBucketRateLimit(
|
|
802
|
+
this.options.connectionRetryOptions
|
|
803
|
+
);
|
|
723
804
|
}
|
|
724
805
|
handleConnection(conn, to) {
|
|
725
806
|
if (this.state !== "open")
|
|
@@ -750,7 +831,10 @@ var ClientTransport = class extends Transport {
|
|
|
750
831
|
log?.info(
|
|
751
832
|
`${this.clientId} -- connection (id: ${conn.debugId}) to ${to} disconnected`
|
|
752
833
|
);
|
|
753
|
-
|
|
834
|
+
this.inflightConnectionPromises.delete(to);
|
|
835
|
+
if (this.tryReconnecting) {
|
|
836
|
+
void this.connect(to);
|
|
837
|
+
}
|
|
754
838
|
});
|
|
755
839
|
conn.addErrorListener((err) => {
|
|
756
840
|
log?.warn(
|
|
@@ -801,41 +885,64 @@ var ClientTransport = class extends Transport {
|
|
|
801
885
|
* Manually attempts to connect to a client.
|
|
802
886
|
* @param to The client ID of the node to connect to.
|
|
803
887
|
*/
|
|
804
|
-
async connect(to
|
|
805
|
-
|
|
888
|
+
async connect(to) {
|
|
889
|
+
const canProceedWithConnection = () => this.state === "open";
|
|
890
|
+
if (!canProceedWithConnection()) {
|
|
806
891
|
log?.info(
|
|
807
|
-
`${this.clientId} -- transport state is no longer open,
|
|
892
|
+
`${this.clientId} -- transport state is no longer open, cancelling attempt to connect to ${to}`
|
|
808
893
|
);
|
|
809
894
|
return;
|
|
810
895
|
}
|
|
811
896
|
let reconnectPromise = this.inflightConnectionPromises.get(to);
|
|
812
897
|
if (!reconnectPromise) {
|
|
813
|
-
|
|
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);
|
|
814
925
|
this.sendHandshake(to, conn);
|
|
815
926
|
return conn;
|
|
816
927
|
});
|
|
817
928
|
this.inflightConnectionPromises.set(to, reconnectPromise);
|
|
929
|
+
} else {
|
|
930
|
+
log?.info(
|
|
931
|
+
`${this.clientId} -- attempting connection to ${to} (reusing previous attempt)`
|
|
932
|
+
);
|
|
818
933
|
}
|
|
819
934
|
try {
|
|
820
935
|
await reconnectPromise;
|
|
821
936
|
} catch (error) {
|
|
822
|
-
const errStr = coerceErrorString(error);
|
|
823
937
|
this.inflightConnectionPromises.delete(to);
|
|
824
|
-
const
|
|
825
|
-
if (!
|
|
826
|
-
|
|
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;
|
|
938
|
+
const errStr = coerceErrorString(error);
|
|
939
|
+
if (!this.tryReconnecting || !canProceedWithConnection()) {
|
|
940
|
+
log?.warn(`${this.clientId} -- connection to ${to} failed (${errStr})`);
|
|
832
941
|
} else {
|
|
833
|
-
const jitter = Math.floor(Math.random() * this.options.retryJitterMs);
|
|
834
|
-
const backoffMs = this.options.retryIntervalMs * 2 ** attempt + jitter;
|
|
835
942
|
log?.warn(
|
|
836
|
-
`${this.clientId} -- connection to ${to} failed (${errStr}),
|
|
943
|
+
`${this.clientId} -- connection to ${to} failed (${errStr}), retrying`
|
|
837
944
|
);
|
|
838
|
-
|
|
945
|
+
return this.connect(to);
|
|
839
946
|
}
|
|
840
947
|
}
|
|
841
948
|
}
|
|
@@ -848,9 +955,9 @@ var ClientTransport = class extends Transport {
|
|
|
848
955
|
log?.debug(`${this.clientId} -- sending handshake request to ${to}`);
|
|
849
956
|
conn.send(this.codec.toBuffer(requestMsg));
|
|
850
957
|
}
|
|
851
|
-
|
|
852
|
-
this.
|
|
853
|
-
super.
|
|
958
|
+
close() {
|
|
959
|
+
this.retryBudget.close();
|
|
960
|
+
super.close();
|
|
854
961
|
}
|
|
855
962
|
};
|
|
856
963
|
var ServerTransport = class extends Transport {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { a as ClientTransport, C as Connection,
|
|
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,
|
|
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';
|
package/dist/transport/index.js
CHANGED
|
@@ -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
|
-
|
|
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-
|
|
5
|
-
import { P as PayloadType, R as RiverError, a as Procedure, S as ServiceContext, b as Result, c as RiverUncaughtSchema } from '../builder-
|
|
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 };
|
|
@@ -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-
|
|
5
|
-
import { P as PayloadType, R as RiverError, a as Procedure, S as ServiceContext, b as Result, c as RiverUncaughtSchema } from '../builder-
|
|
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 };
|
package/dist/util/testHelpers.js
CHANGED
|
@@ -4,14 +4,15 @@ import {
|
|
|
4
4
|
} from "../chunk-KWXQLQAF.js";
|
|
5
5
|
import "../chunk-RPIDSIQG.js";
|
|
6
6
|
import {
|
|
7
|
-
Session
|
|
8
|
-
|
|
9
|
-
} from "../chunk-O6YQ3JAH.js";
|
|
7
|
+
Session
|
|
8
|
+
} from "../chunk-B7VTDQR7.js";
|
|
10
9
|
import {
|
|
11
10
|
coerceErrorString
|
|
12
11
|
} from "../chunk-GFRAOY75.js";
|
|
13
12
|
import "../chunk-H4BYJELI.js";
|
|
14
|
-
import
|
|
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
|
-
|
|
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