@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.
- package/README.md +41 -22
- package/dist/{builder-660d3140.d.ts → builder-4d392f6c.d.ts} +1 -1
- package/dist/{chunk-O6YQ3JAH.js → chunk-5XMMDOLH.js} +148 -37
- package/dist/{chunk-MNWOTQWX.js → chunk-MXHIHC3U.js} +1 -1
- package/dist/{chunk-5TX4BKAD.js → chunk-NSJVTNVQ.js} +1 -1
- package/dist/{connection-162c0f7b.d.ts → connection-94896f3b.d.ts} +1 -1
- package/dist/{connection-93daccc3.d.ts → connection-99346822.d.ts} +1 -1
- package/dist/{index-76b801f8.d.ts → index-2e402bb8.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 +198 -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 +67 -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 +198 -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 +67 -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 +198 -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,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
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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
|
-
|
|
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
|
|
805
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
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;
|
|
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}),
|
|
944
|
+
`${this.clientId} -- connection to ${to} failed (${errStr}), retrying`
|
|
837
945
|
);
|
|
838
|
-
|
|
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
|
-
|
|
852
|
-
this.
|
|
853
|
-
super.
|
|
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,
|
|
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,
|
|
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';
|
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-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-
|
|
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-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 };
|
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-5XMMDOLH.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