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