@replit/river 0.10.13 → 0.12.0
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 +28 -8
- package/dist/{builder-1f26296b.d.ts → builder-c593de11.d.ts} +14 -13
- package/dist/{chunk-3JGVFWKQ.js → chunk-24O3BKZA.js} +205 -180
- package/dist/chunk-4HOR4NUO.js +40 -0
- package/dist/chunk-ANGOKBE5.js +708 -0
- package/dist/{chunk-R6H2BIMC.js → chunk-GZ7HCLLM.js} +31 -7
- package/dist/{chunk-T7M7OKPE.js → chunk-H4BYJELI.js} +5 -1
- package/dist/chunk-IIBVKYDB.js +62 -0
- package/dist/chunk-IUDKWAOK.js +47 -0
- package/dist/chunk-WTOIOXB7.js +125 -0
- package/dist/chunk-XOTIAXAH.js +44 -0
- package/dist/codec/index.cjs +13 -7
- package/dist/codec/index.js +2 -4
- package/dist/connection-2956a1c5.d.ts +17 -0
- package/dist/connection-aaea7c88.d.ts +15 -0
- package/dist/connection-cd963ed5.d.ts +18 -0
- package/dist/index-d91775d9.d.ts +442 -0
- package/dist/logging/index.cjs +8 -3
- package/dist/logging/index.d.cts +6 -1
- package/dist/logging/index.d.ts +6 -1
- package/dist/logging/index.js +5 -3
- package/dist/messageFraming-b200ef25.d.ts +20 -0
- package/dist/router/index.cjs +249 -211
- package/dist/router/index.d.cts +6 -7
- package/dist/router/index.d.ts +6 -7
- package/dist/router/index.js +3 -3
- package/dist/transport/impls/stdio/client.cjs +891 -0
- package/dist/transport/impls/stdio/client.d.cts +27 -0
- package/dist/transport/impls/stdio/client.d.ts +27 -0
- package/dist/transport/impls/stdio/client.js +42 -0
- package/dist/transport/impls/stdio/server.cjs +861 -0
- package/dist/transport/impls/stdio/server.d.cts +25 -0
- package/dist/transport/impls/stdio/server.d.ts +25 -0
- package/dist/transport/impls/stdio/server.js +33 -0
- package/dist/transport/impls/uds/client.cjs +893 -0
- package/dist/transport/impls/uds/client.d.cts +16 -0
- package/dist/transport/impls/uds/client.d.ts +16 -0
- package/dist/transport/impls/uds/client.js +44 -0
- package/dist/transport/impls/uds/server.cjs +863 -0
- package/dist/transport/impls/uds/server.d.cts +16 -0
- package/dist/transport/impls/uds/server.d.ts +16 -0
- package/dist/transport/impls/uds/server.js +39 -0
- package/dist/transport/impls/ws/client.cjs +587 -248
- package/dist/transport/impls/ws/client.d.cts +6 -21
- package/dist/transport/impls/ws/client.d.ts +6 -21
- package/dist/transport/impls/ws/client.js +77 -7
- package/dist/transport/impls/ws/server.cjs +541 -194
- package/dist/transport/impls/ws/server.d.cts +6 -10
- package/dist/transport/impls/ws/server.d.ts +6 -10
- package/dist/transport/impls/ws/server.js +31 -8
- package/dist/transport/index.cjs +652 -129
- package/dist/transport/index.d.cts +3 -276
- package/dist/transport/index.d.ts +3 -276
- package/dist/transport/index.js +13 -10
- package/dist/util/testHelpers.cjs +40 -602
- package/dist/util/testHelpers.d.cts +18 -37
- package/dist/util/testHelpers.d.ts +18 -37
- package/dist/util/testHelpers.js +27 -47
- package/package.json +29 -14
- package/dist/chunk-3MQETIGZ.js +0 -80
- package/dist/chunk-5IC5XMWK.js +0 -140
- package/dist/chunk-L7D75G4K.js +0 -29
- package/dist/chunk-LQXPKF3A.js +0 -282
- package/dist/chunk-PJ2EUO7O.js +0 -63
- package/dist/chunk-WVT5QXMZ.js +0 -20
- package/dist/chunk-ZE4MX7DF.js +0 -75
- package/dist/connection-2529fc14.d.ts +0 -10
- package/dist/connection-316d6e3a.d.ts +0 -10
- package/dist/connection-8e19874c.d.ts +0 -11
- package/dist/connection-f7688cc1.d.ts +0 -11
- package/dist/transport/impls/stdio/stdio.cjs +0 -508
- package/dist/transport/impls/stdio/stdio.d.cts +0 -26
- package/dist/transport/impls/stdio/stdio.d.ts +0 -26
- package/dist/transport/impls/stdio/stdio.js +0 -70
- package/dist/transport/impls/unixsocket/client.cjs +0 -506
- package/dist/transport/impls/unixsocket/client.d.cts +0 -16
- package/dist/transport/impls/unixsocket/client.d.ts +0 -16
- package/dist/transport/impls/unixsocket/client.js +0 -67
- package/dist/transport/impls/unixsocket/server.cjs +0 -510
- package/dist/transport/impls/unixsocket/server.d.cts +0 -18
- package/dist/transport/impls/unixsocket/server.d.ts +0 -18
- package/dist/transport/impls/unixsocket/server.js +0 -73
- /package/dist/{chunk-ORAG7IAU.js → chunk-5IZ2UHWV.js} +0 -0
package/dist/router/index.cjs
CHANGED
|
@@ -410,57 +410,58 @@ var TransportMessageSchema = (t) => import_typebox2.Type.Object({
|
|
|
410
410
|
id: import_typebox2.Type.String(),
|
|
411
411
|
from: import_typebox2.Type.String(),
|
|
412
412
|
to: import_typebox2.Type.String(),
|
|
413
|
+
seq: import_typebox2.Type.Integer(),
|
|
414
|
+
ack: import_typebox2.Type.Integer(),
|
|
413
415
|
serviceName: import_typebox2.Type.Optional(import_typebox2.Type.Union([import_typebox2.Type.String(), import_typebox2.Type.Null()])),
|
|
414
416
|
procedureName: import_typebox2.Type.Optional(import_typebox2.Type.Union([import_typebox2.Type.String(), import_typebox2.Type.Null()])),
|
|
415
417
|
streamId: import_typebox2.Type.String(),
|
|
416
418
|
controlFlags: import_typebox2.Type.Integer(),
|
|
417
419
|
payload: t
|
|
418
420
|
});
|
|
419
|
-
var
|
|
420
|
-
import_typebox2.Type.
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
);
|
|
424
|
-
var ControlMessagePayloadSchema = import_typebox2.Type.Object({
|
|
421
|
+
var ControlMessageAckSchema = import_typebox2.Type.Object({
|
|
422
|
+
type: import_typebox2.Type.Literal("ACK")
|
|
423
|
+
});
|
|
424
|
+
var ControlMessageCloseSchema = import_typebox2.Type.Object({
|
|
425
425
|
type: import_typebox2.Type.Literal("CLOSE")
|
|
426
426
|
});
|
|
427
|
+
var PROTOCOL_VERSION = "v1";
|
|
428
|
+
var ControlMessageHandshakeRequestSchema = import_typebox2.Type.Object({
|
|
429
|
+
type: import_typebox2.Type.Literal("HANDSHAKE_REQ"),
|
|
430
|
+
protocolVersion: import_typebox2.Type.Literal(PROTOCOL_VERSION)
|
|
431
|
+
});
|
|
432
|
+
var ControlMessageHandshakeResponseSchema = import_typebox2.Type.Object({
|
|
433
|
+
type: import_typebox2.Type.Literal("HANDSHAKE_RESP"),
|
|
434
|
+
status: import_typebox2.Type.Union([
|
|
435
|
+
import_typebox2.Type.Object({
|
|
436
|
+
ok: import_typebox2.Type.Literal(true),
|
|
437
|
+
instanceId: import_typebox2.Type.String()
|
|
438
|
+
}),
|
|
439
|
+
import_typebox2.Type.Object({
|
|
440
|
+
ok: import_typebox2.Type.Literal(false),
|
|
441
|
+
reason: import_typebox2.Type.Union([import_typebox2.Type.Literal("VERSION_MISMATCH")])
|
|
442
|
+
})
|
|
443
|
+
])
|
|
444
|
+
});
|
|
445
|
+
var ControlMessagePayloadSchema = import_typebox2.Type.Union([
|
|
446
|
+
ControlMessageCloseSchema,
|
|
447
|
+
ControlMessageAckSchema,
|
|
448
|
+
ControlMessageHandshakeRequestSchema,
|
|
449
|
+
ControlMessageHandshakeResponseSchema
|
|
450
|
+
]);
|
|
427
451
|
var OpaqueTransportMessageSchema = TransportMessageSchema(
|
|
428
452
|
import_typebox2.Type.Unknown()
|
|
429
453
|
);
|
|
430
|
-
function msg(from, to, streamId, payload, serviceName, procedureName) {
|
|
431
|
-
return {
|
|
432
|
-
id: (0, import_nanoid.nanoid)(),
|
|
433
|
-
to,
|
|
434
|
-
from,
|
|
435
|
-
serviceName,
|
|
436
|
-
procedureName,
|
|
437
|
-
streamId,
|
|
438
|
-
controlFlags: 0,
|
|
439
|
-
payload
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
function reply(msg2, response) {
|
|
443
|
-
return {
|
|
444
|
-
id: (0, import_nanoid.nanoid)(),
|
|
445
|
-
streamId: msg2.streamId,
|
|
446
|
-
controlFlags: 0,
|
|
447
|
-
to: msg2.from,
|
|
448
|
-
from: msg2.to,
|
|
449
|
-
payload: response
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
function closeStream(from, to, stream) {
|
|
453
|
-
const closeMessage = msg(from, to, stream, {
|
|
454
|
-
type: "CLOSE"
|
|
455
|
-
});
|
|
456
|
-
closeMessage.controlFlags |= 4 /* StreamClosedBit */;
|
|
457
|
-
return closeMessage;
|
|
458
|
-
}
|
|
459
454
|
function isStreamOpen(controlFlag) {
|
|
460
|
-
return (
|
|
455
|
+
return (
|
|
456
|
+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */
|
|
457
|
+
(controlFlag & 2 /* StreamOpenBit */) === 2 /* StreamOpenBit */
|
|
458
|
+
);
|
|
461
459
|
}
|
|
462
460
|
function isStreamClose(controlFlag) {
|
|
463
|
-
return (
|
|
461
|
+
return (
|
|
462
|
+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */
|
|
463
|
+
(controlFlag & 4 /* StreamClosedBit */) === 4 /* StreamClosedBit */
|
|
464
|
+
);
|
|
464
465
|
}
|
|
465
466
|
|
|
466
467
|
// router/client.ts
|
|
@@ -555,33 +556,24 @@ var createClient = (transport, serverId = "SERVER") => _createRecursiveProxy(asy
|
|
|
555
556
|
throw new Error(`invalid river call, unknown procedure type ${procType}`);
|
|
556
557
|
}
|
|
557
558
|
}, []);
|
|
558
|
-
|
|
559
|
-
function rejectAfterDisconnectGrace(from, cb) {
|
|
560
|
-
let timeout = void 0;
|
|
559
|
+
function createSessionDisconnectHandler(from, cb) {
|
|
561
560
|
return (evt) => {
|
|
562
|
-
if (evt.status === "
|
|
563
|
-
|
|
564
|
-
timeout = void 0;
|
|
565
|
-
}
|
|
566
|
-
if (evt.status === "disconnect" && evt.conn.connectedTo === from) {
|
|
567
|
-
timeout = setTimeout(cb, CONNECTION_GRACE_PERIOD_MS);
|
|
561
|
+
if (evt.status === "disconnect" && evt.session.to === from) {
|
|
562
|
+
cb();
|
|
568
563
|
}
|
|
569
564
|
};
|
|
570
565
|
}
|
|
571
|
-
function handleRpc(transport, serverId, input, serviceName,
|
|
566
|
+
function handleRpc(transport, serverId, input, serviceName, procedureName) {
|
|
572
567
|
const streamId = (0, import_nanoid2.nanoid)();
|
|
573
|
-
|
|
574
|
-
transport.clientId,
|
|
575
|
-
serverId,
|
|
568
|
+
transport.send(serverId, {
|
|
576
569
|
streamId,
|
|
577
|
-
input,
|
|
578
570
|
serviceName,
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
571
|
+
procedureName,
|
|
572
|
+
payload: input,
|
|
573
|
+
controlFlags: 2 /* StreamOpenBit */ | 4 /* StreamClosedBit */
|
|
574
|
+
});
|
|
583
575
|
const responsePromise = new Promise((resolve) => {
|
|
584
|
-
const
|
|
576
|
+
const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
|
|
585
577
|
cleanup();
|
|
586
578
|
resolve(
|
|
587
579
|
Err({
|
|
@@ -592,172 +584,181 @@ function handleRpc(transport, serverId, input, serviceName, procName) {
|
|
|
592
584
|
});
|
|
593
585
|
function cleanup() {
|
|
594
586
|
transport.removeEventListener("message", onMessage);
|
|
595
|
-
transport.removeEventListener("
|
|
587
|
+
transport.removeEventListener("sessionStatus", onSessionStatus);
|
|
596
588
|
}
|
|
597
|
-
function onMessage(
|
|
598
|
-
if (
|
|
589
|
+
function onMessage(msg) {
|
|
590
|
+
if (msg.streamId !== streamId) {
|
|
599
591
|
return;
|
|
600
592
|
}
|
|
601
|
-
if (
|
|
593
|
+
if (msg.to !== transport.clientId) {
|
|
602
594
|
return;
|
|
603
595
|
}
|
|
604
|
-
if (
|
|
596
|
+
if (msg.streamId === streamId) {
|
|
605
597
|
cleanup();
|
|
606
|
-
resolve(
|
|
598
|
+
resolve(msg.payload);
|
|
607
599
|
}
|
|
608
600
|
}
|
|
609
601
|
transport.addEventListener("message", onMessage);
|
|
610
|
-
transport.addEventListener("
|
|
602
|
+
transport.addEventListener("sessionStatus", onSessionStatus);
|
|
611
603
|
});
|
|
612
604
|
return responsePromise;
|
|
613
605
|
}
|
|
614
|
-
function handleStream(transport, serverId, init, serviceName,
|
|
606
|
+
function handleStream(transport, serverId, init, serviceName, procedureName) {
|
|
615
607
|
const streamId = (0, import_nanoid2.nanoid)();
|
|
616
608
|
const inputStream = pushable({ objectMode: true });
|
|
617
609
|
const outputStream = pushable({ objectMode: true });
|
|
618
610
|
let firstMessage = true;
|
|
611
|
+
let healthyClose = true;
|
|
619
612
|
if (init) {
|
|
620
|
-
|
|
621
|
-
transport.clientId,
|
|
622
|
-
serverId,
|
|
613
|
+
transport.send(serverId, {
|
|
623
614
|
streamId,
|
|
624
|
-
init,
|
|
625
615
|
serviceName,
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
616
|
+
procedureName,
|
|
617
|
+
payload: init,
|
|
618
|
+
controlFlags: 2 /* StreamOpenBit */
|
|
619
|
+
});
|
|
630
620
|
firstMessage = false;
|
|
631
621
|
}
|
|
632
|
-
|
|
622
|
+
const pipeInputToTransport = async () => {
|
|
633
623
|
for await (const rawIn of inputStream) {
|
|
634
|
-
const m =
|
|
624
|
+
const m = {
|
|
625
|
+
streamId,
|
|
626
|
+
payload: rawIn,
|
|
627
|
+
controlFlags: 0
|
|
628
|
+
};
|
|
635
629
|
if (firstMessage) {
|
|
636
630
|
m.serviceName = serviceName;
|
|
637
|
-
m.procedureName =
|
|
631
|
+
m.procedureName = procedureName;
|
|
638
632
|
m.controlFlags |= 2 /* StreamOpenBit */;
|
|
639
633
|
firstMessage = false;
|
|
640
634
|
}
|
|
641
|
-
transport.send(m);
|
|
635
|
+
transport.send(serverId, m);
|
|
642
636
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
637
|
+
if (!healthyClose)
|
|
638
|
+
return;
|
|
639
|
+
transport.sendCloseStream(serverId, streamId);
|
|
640
|
+
};
|
|
641
|
+
void pipeInputToTransport();
|
|
642
|
+
function onMessage(msg) {
|
|
643
|
+
if (msg.streamId !== streamId) {
|
|
647
644
|
return;
|
|
648
645
|
}
|
|
649
|
-
if (
|
|
646
|
+
if (msg.to !== transport.clientId) {
|
|
650
647
|
return;
|
|
651
648
|
}
|
|
652
|
-
if (isStreamClose(
|
|
649
|
+
if (isStreamClose(msg.controlFlags)) {
|
|
653
650
|
cleanup();
|
|
654
651
|
} else {
|
|
655
|
-
outputStream.push(
|
|
652
|
+
outputStream.push(msg.payload);
|
|
656
653
|
}
|
|
657
654
|
}
|
|
658
655
|
function cleanup() {
|
|
659
656
|
inputStream.end();
|
|
660
657
|
outputStream.end();
|
|
661
658
|
transport.removeEventListener("message", onMessage);
|
|
662
|
-
transport.removeEventListener("
|
|
659
|
+
transport.removeEventListener("sessionStatus", onSessionStatus);
|
|
663
660
|
}
|
|
664
|
-
const
|
|
665
|
-
cleanup();
|
|
666
|
-
transport.send(closeStream(transport.clientId, serverId, streamId));
|
|
667
|
-
};
|
|
668
|
-
const onConnectionStatus = rejectAfterDisconnectGrace(serverId, () => {
|
|
661
|
+
const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
|
|
669
662
|
outputStream.push(
|
|
670
663
|
Err({
|
|
671
664
|
code: UNEXPECTED_DISCONNECT,
|
|
672
665
|
message: `${serverId} unexpectedly disconnected`
|
|
673
666
|
})
|
|
674
667
|
);
|
|
668
|
+
healthyClose = false;
|
|
675
669
|
cleanup();
|
|
676
670
|
});
|
|
677
671
|
transport.addEventListener("message", onMessage);
|
|
678
|
-
transport.addEventListener("
|
|
679
|
-
return [inputStream, outputStream,
|
|
672
|
+
transport.addEventListener("sessionStatus", onSessionStatus);
|
|
673
|
+
return [inputStream, outputStream, cleanup];
|
|
680
674
|
}
|
|
681
|
-
function handleSubscribe(transport, serverId, input, serviceName,
|
|
675
|
+
function handleSubscribe(transport, serverId, input, serviceName, procedureName) {
|
|
682
676
|
const streamId = (0, import_nanoid2.nanoid)();
|
|
683
|
-
|
|
684
|
-
transport.clientId,
|
|
685
|
-
serverId,
|
|
677
|
+
transport.send(serverId, {
|
|
686
678
|
streamId,
|
|
687
|
-
input,
|
|
688
679
|
serviceName,
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
680
|
+
procedureName,
|
|
681
|
+
payload: input,
|
|
682
|
+
controlFlags: 2 /* StreamOpenBit */
|
|
683
|
+
});
|
|
684
|
+
let healthyClose = true;
|
|
693
685
|
const outputStream = pushable({ objectMode: true });
|
|
694
|
-
function onMessage(
|
|
695
|
-
if (
|
|
686
|
+
function onMessage(msg) {
|
|
687
|
+
if (msg.streamId !== streamId) {
|
|
696
688
|
return;
|
|
697
689
|
}
|
|
698
|
-
if (
|
|
690
|
+
if (msg.to !== transport.clientId) {
|
|
699
691
|
return;
|
|
700
692
|
}
|
|
701
|
-
if (isStreamClose(
|
|
693
|
+
if (isStreamClose(msg.controlFlags)) {
|
|
702
694
|
cleanup();
|
|
703
695
|
} else {
|
|
704
|
-
outputStream.push(
|
|
696
|
+
outputStream.push(msg.payload);
|
|
705
697
|
}
|
|
706
698
|
}
|
|
707
699
|
function cleanup() {
|
|
708
700
|
outputStream.end();
|
|
709
701
|
transport.removeEventListener("message", onMessage);
|
|
710
|
-
transport.removeEventListener("
|
|
702
|
+
transport.removeEventListener("sessionStatus", onSessionStatus);
|
|
711
703
|
}
|
|
712
704
|
const closeHandler = () => {
|
|
713
705
|
cleanup();
|
|
714
|
-
|
|
706
|
+
if (!healthyClose)
|
|
707
|
+
return;
|
|
708
|
+
transport.sendCloseStream(serverId, streamId);
|
|
715
709
|
};
|
|
716
|
-
const
|
|
710
|
+
const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
|
|
717
711
|
outputStream.push(
|
|
718
712
|
Err({
|
|
719
713
|
code: UNEXPECTED_DISCONNECT,
|
|
720
714
|
message: `${serverId} unexpectedly disconnected`
|
|
721
715
|
})
|
|
722
716
|
);
|
|
717
|
+
healthyClose = false;
|
|
723
718
|
cleanup();
|
|
724
719
|
});
|
|
725
720
|
transport.addEventListener("message", onMessage);
|
|
726
|
-
transport.addEventListener("
|
|
721
|
+
transport.addEventListener("sessionStatus", onSessionStatus);
|
|
727
722
|
return [outputStream, closeHandler];
|
|
728
723
|
}
|
|
729
|
-
function handleUpload(transport, serverId,
|
|
724
|
+
function handleUpload(transport, serverId, init, serviceName, procedureName) {
|
|
730
725
|
const streamId = (0, import_nanoid2.nanoid)();
|
|
731
726
|
const inputStream = pushable({ objectMode: true });
|
|
732
727
|
let firstMessage = true;
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
serverId,
|
|
728
|
+
let healthyClose = true;
|
|
729
|
+
if (init) {
|
|
730
|
+
transport.send(serverId, {
|
|
737
731
|
streamId,
|
|
738
|
-
input,
|
|
739
732
|
serviceName,
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
733
|
+
procedureName,
|
|
734
|
+
payload: init,
|
|
735
|
+
controlFlags: 2 /* StreamOpenBit */
|
|
736
|
+
});
|
|
744
737
|
firstMessage = false;
|
|
745
738
|
}
|
|
746
|
-
|
|
739
|
+
const pipeInputToTransport = async () => {
|
|
747
740
|
for await (const rawIn of inputStream) {
|
|
748
|
-
const m =
|
|
741
|
+
const m = {
|
|
742
|
+
streamId,
|
|
743
|
+
payload: rawIn,
|
|
744
|
+
controlFlags: 0
|
|
745
|
+
};
|
|
749
746
|
if (firstMessage) {
|
|
750
|
-
m.controlFlags |= 2 /* StreamOpenBit */;
|
|
751
747
|
m.serviceName = serviceName;
|
|
752
|
-
m.procedureName =
|
|
748
|
+
m.procedureName = procedureName;
|
|
749
|
+
m.controlFlags |= 2 /* StreamOpenBit */;
|
|
753
750
|
firstMessage = false;
|
|
754
751
|
}
|
|
755
|
-
transport.send(m);
|
|
752
|
+
transport.send(serverId, m);
|
|
756
753
|
}
|
|
757
|
-
|
|
758
|
-
|
|
754
|
+
if (!healthyClose)
|
|
755
|
+
return;
|
|
756
|
+
transport.sendCloseStream(serverId, streamId);
|
|
757
|
+
};
|
|
758
|
+
void pipeInputToTransport();
|
|
759
759
|
const responsePromise = new Promise((resolve) => {
|
|
760
|
-
const
|
|
760
|
+
const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
|
|
761
|
+
healthyClose = false;
|
|
761
762
|
cleanup();
|
|
762
763
|
resolve(
|
|
763
764
|
Err({
|
|
@@ -769,19 +770,19 @@ function handleUpload(transport, serverId, input, serviceName, procName) {
|
|
|
769
770
|
function cleanup() {
|
|
770
771
|
inputStream.end();
|
|
771
772
|
transport.removeEventListener("message", onMessage);
|
|
772
|
-
transport.removeEventListener("
|
|
773
|
+
transport.removeEventListener("sessionStatus", onSessionStatus);
|
|
773
774
|
}
|
|
774
|
-
function onMessage(
|
|
775
|
-
if (
|
|
775
|
+
function onMessage(msg) {
|
|
776
|
+
if (msg.to !== transport.clientId) {
|
|
776
777
|
return;
|
|
777
778
|
}
|
|
778
|
-
if (
|
|
779
|
+
if (msg.streamId === streamId) {
|
|
779
780
|
cleanup();
|
|
780
|
-
resolve(
|
|
781
|
+
resolve(msg.payload);
|
|
781
782
|
}
|
|
782
783
|
}
|
|
783
784
|
transport.addEventListener("message", onMessage);
|
|
784
|
-
transport.addEventListener("
|
|
785
|
+
transport.addEventListener("sessionStatus", onSessionStatus);
|
|
785
786
|
});
|
|
786
787
|
return [inputStream, responsePromise];
|
|
787
788
|
}
|
|
@@ -791,6 +792,16 @@ var log;
|
|
|
791
792
|
|
|
792
793
|
// router/server.ts
|
|
793
794
|
var import_value = require("@sinclair/typebox/value");
|
|
795
|
+
|
|
796
|
+
// util/stringify.ts
|
|
797
|
+
function coerceErrorString(err) {
|
|
798
|
+
if (err instanceof Error) {
|
|
799
|
+
return err.message;
|
|
800
|
+
}
|
|
801
|
+
return `[coerced to error] ${String(err)}`;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// router/server.ts
|
|
794
805
|
var RiverServer = class {
|
|
795
806
|
transport;
|
|
796
807
|
services;
|
|
@@ -799,10 +810,12 @@ var RiverServer = class {
|
|
|
799
810
|
streamMap;
|
|
800
811
|
// map of client to their open streams by streamId
|
|
801
812
|
clientStreams;
|
|
813
|
+
disconnectedSessions;
|
|
802
814
|
constructor(transport, services, extendedContext) {
|
|
803
815
|
this.transport = transport;
|
|
804
816
|
this.services = services;
|
|
805
817
|
this.contextMap = /* @__PURE__ */ new Map();
|
|
818
|
+
this.disconnectedSessions = /* @__PURE__ */ new Set();
|
|
806
819
|
for (const service of Object.values(services)) {
|
|
807
820
|
this.contextMap.set(service, {
|
|
808
821
|
...extendedContext,
|
|
@@ -811,13 +824,13 @@ var RiverServer = class {
|
|
|
811
824
|
}
|
|
812
825
|
this.streamMap = /* @__PURE__ */ new Map();
|
|
813
826
|
this.clientStreams = /* @__PURE__ */ new Map();
|
|
814
|
-
this.transport.addEventListener("message", this.
|
|
815
|
-
this.transport.addEventListener("
|
|
827
|
+
this.transport.addEventListener("message", this.onMessage);
|
|
828
|
+
this.transport.addEventListener("sessionStatus", this.onSessionStatus);
|
|
816
829
|
}
|
|
817
830
|
get streams() {
|
|
818
831
|
return this.streamMap;
|
|
819
832
|
}
|
|
820
|
-
|
|
833
|
+
onMessage = async (message) => {
|
|
821
834
|
if (message.to !== this.transport.clientId) {
|
|
822
835
|
log?.info(
|
|
823
836
|
`${this.transport.clientId} -- got msg with destination that isn't the server, ignoring`
|
|
@@ -832,12 +845,12 @@ var RiverServer = class {
|
|
|
832
845
|
}
|
|
833
846
|
await this.pushToStream(procStream, message, isInitMessage);
|
|
834
847
|
};
|
|
835
|
-
// cleanup streams on
|
|
836
|
-
|
|
848
|
+
// cleanup streams on session close
|
|
849
|
+
onSessionStatus = async (evt) => {
|
|
837
850
|
if (evt.status !== "disconnect") {
|
|
838
851
|
return;
|
|
839
852
|
}
|
|
840
|
-
const disconnectedClientId = evt.
|
|
853
|
+
const disconnectedClientId = evt.session.to;
|
|
841
854
|
log?.info(
|
|
842
855
|
`${this.transport.clientId} -- got unexpected disconnect from ${disconnectedClientId}, cleaning up streams`
|
|
843
856
|
);
|
|
@@ -845,14 +858,16 @@ var RiverServer = class {
|
|
|
845
858
|
if (!streamsFromThisClient) {
|
|
846
859
|
return;
|
|
847
860
|
}
|
|
861
|
+
this.disconnectedSessions.add(disconnectedClientId);
|
|
848
862
|
await Promise.all(
|
|
849
863
|
Array.from(streamsFromThisClient).map(this.cleanupStream)
|
|
850
864
|
);
|
|
865
|
+
this.disconnectedSessions.delete(disconnectedClientId);
|
|
851
866
|
this.clientStreams.delete(disconnectedClientId);
|
|
852
867
|
};
|
|
853
868
|
async close() {
|
|
854
|
-
this.transport.removeEventListener("message", this.
|
|
855
|
-
this.transport.removeEventListener("
|
|
869
|
+
this.transport.removeEventListener("message", this.onMessage);
|
|
870
|
+
this.transport.removeEventListener("sessionStatus", this.onSessionStatus);
|
|
856
871
|
await Promise.all([...this.streamMap.keys()].map(this.cleanupStream));
|
|
857
872
|
}
|
|
858
873
|
createNewProcStream(message) {
|
|
@@ -876,6 +891,13 @@ var RiverServer = class {
|
|
|
876
891
|
);
|
|
877
892
|
return;
|
|
878
893
|
}
|
|
894
|
+
const session = this.transport.sessions.get(message.from);
|
|
895
|
+
if (!session) {
|
|
896
|
+
log?.warn(
|
|
897
|
+
`${this.transport.clientId} -- couldn't find session for ${message.from}`
|
|
898
|
+
);
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
879
901
|
const procedure = service.procedures[message.procedureName];
|
|
880
902
|
const incoming = pushable({ objectMode: true });
|
|
881
903
|
const outgoing = pushable({ objectMode: true });
|
|
@@ -883,21 +905,20 @@ var RiverServer = class {
|
|
|
883
905
|
// sending outgoing messages back to client
|
|
884
906
|
(async () => {
|
|
885
907
|
for await (const response of outgoing) {
|
|
886
|
-
this.transport.send(
|
|
908
|
+
this.transport.send(session.to, {
|
|
909
|
+
streamId: message.streamId,
|
|
910
|
+
controlFlags: 0,
|
|
911
|
+
payload: response
|
|
912
|
+
});
|
|
887
913
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
this.transport.clientId,
|
|
892
|
-
message.from,
|
|
893
|
-
message.streamId
|
|
894
|
-
)
|
|
895
|
-
);
|
|
914
|
+
const needsClose = procedure.type === "subscription" || procedure.type === "stream";
|
|
915
|
+
if (needsClose && !this.disconnectedSessions.has(message.from)) {
|
|
916
|
+
this.transport.sendCloseStream(session.to, message.streamId);
|
|
896
917
|
}
|
|
897
918
|
})()
|
|
898
919
|
);
|
|
899
920
|
const errorHandler = (err) => {
|
|
900
|
-
const errorMsg = err
|
|
921
|
+
const errorMsg = coerceErrorString(err);
|
|
901
922
|
log?.error(
|
|
902
923
|
`${this.transport.clientId} -- procedure ${message.serviceName}.${message.procedureName}:${message.streamId} threw an error: ${errorMsg}`
|
|
903
924
|
);
|
|
@@ -910,82 +931,95 @@ var RiverServer = class {
|
|
|
910
931
|
};
|
|
911
932
|
let inputHandler;
|
|
912
933
|
const procHasInitMessage = "init" in procedure;
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
inputHandler = (async () => {
|
|
916
|
-
const initMessage = await incoming.next();
|
|
917
|
-
if (initMessage.done) {
|
|
918
|
-
return;
|
|
919
|
-
}
|
|
920
|
-
return procedure.handler(serviceContext, initMessage.value, incoming, outgoing).catch(errorHandler);
|
|
921
|
-
})();
|
|
922
|
-
} else {
|
|
923
|
-
inputHandler = procedure.handler(serviceContext, incoming, outgoing).catch(errorHandler);
|
|
924
|
-
}
|
|
925
|
-
} else if (procedure.type === "rpc") {
|
|
926
|
-
inputHandler = (async () => {
|
|
927
|
-
const inputMessage = await incoming.next();
|
|
928
|
-
if (inputMessage.done) {
|
|
929
|
-
return;
|
|
930
|
-
}
|
|
931
|
-
try {
|
|
932
|
-
const outputMessage = await procedure.handler(
|
|
933
|
-
serviceContext,
|
|
934
|
-
inputMessage.value
|
|
935
|
-
);
|
|
936
|
-
outgoing.push(outputMessage);
|
|
937
|
-
} catch (err) {
|
|
938
|
-
errorHandler(err);
|
|
939
|
-
}
|
|
940
|
-
})();
|
|
941
|
-
} else if (procedure.type === "subscription") {
|
|
942
|
-
inputHandler = (async () => {
|
|
943
|
-
const inputMessage = await incoming.next();
|
|
944
|
-
if (inputMessage.done) {
|
|
945
|
-
return;
|
|
946
|
-
}
|
|
947
|
-
try {
|
|
948
|
-
await procedure.handler(serviceContext, inputMessage.value, outgoing);
|
|
949
|
-
} catch (err) {
|
|
950
|
-
errorHandler(err);
|
|
951
|
-
}
|
|
952
|
-
})();
|
|
953
|
-
} else if (procedure.type === "upload") {
|
|
954
|
-
if (procHasInitMessage) {
|
|
934
|
+
switch (procedure.type) {
|
|
935
|
+
case "rpc":
|
|
955
936
|
inputHandler = (async () => {
|
|
956
|
-
const
|
|
957
|
-
if (
|
|
937
|
+
const inputMessage = await incoming.next();
|
|
938
|
+
if (inputMessage.done) {
|
|
958
939
|
return;
|
|
959
940
|
}
|
|
960
941
|
try {
|
|
961
942
|
const outputMessage = await procedure.handler(
|
|
962
943
|
serviceContext,
|
|
963
|
-
|
|
964
|
-
incoming
|
|
944
|
+
inputMessage.value
|
|
965
945
|
);
|
|
966
946
|
outgoing.push(outputMessage);
|
|
967
947
|
} catch (err) {
|
|
968
948
|
errorHandler(err);
|
|
969
949
|
}
|
|
970
950
|
})();
|
|
971
|
-
|
|
951
|
+
break;
|
|
952
|
+
case "stream":
|
|
953
|
+
if (procHasInitMessage) {
|
|
954
|
+
inputHandler = (async () => {
|
|
955
|
+
const initMessage = await incoming.next();
|
|
956
|
+
if (initMessage.done) {
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
return procedure.handler(serviceContext, initMessage.value, incoming, outgoing).catch(errorHandler);
|
|
960
|
+
})();
|
|
961
|
+
} else {
|
|
962
|
+
inputHandler = procedure.handler(serviceContext, incoming, outgoing).catch(errorHandler);
|
|
963
|
+
}
|
|
964
|
+
break;
|
|
965
|
+
case "subscription":
|
|
972
966
|
inputHandler = (async () => {
|
|
967
|
+
const inputMessage = await incoming.next();
|
|
968
|
+
if (inputMessage.done) {
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
973
971
|
try {
|
|
974
|
-
|
|
972
|
+
await procedure.handler(
|
|
975
973
|
serviceContext,
|
|
976
|
-
|
|
974
|
+
inputMessage.value,
|
|
975
|
+
outgoing
|
|
977
976
|
);
|
|
978
|
-
outgoing.push(outputMessage);
|
|
979
977
|
} catch (err) {
|
|
980
978
|
errorHandler(err);
|
|
981
979
|
}
|
|
982
980
|
})();
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
981
|
+
break;
|
|
982
|
+
case "upload":
|
|
983
|
+
if (procHasInitMessage) {
|
|
984
|
+
inputHandler = (async () => {
|
|
985
|
+
const initMessage = await incoming.next();
|
|
986
|
+
if (initMessage.done) {
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
try {
|
|
990
|
+
const outputMessage = await procedure.handler(
|
|
991
|
+
serviceContext,
|
|
992
|
+
initMessage.value,
|
|
993
|
+
incoming
|
|
994
|
+
);
|
|
995
|
+
if (!this.disconnectedSessions.has(message.from)) {
|
|
996
|
+
outgoing.push(outputMessage);
|
|
997
|
+
}
|
|
998
|
+
} catch (err) {
|
|
999
|
+
errorHandler(err);
|
|
1000
|
+
}
|
|
1001
|
+
})();
|
|
1002
|
+
} else {
|
|
1003
|
+
inputHandler = (async () => {
|
|
1004
|
+
try {
|
|
1005
|
+
const outputMessage = await procedure.handler(
|
|
1006
|
+
serviceContext,
|
|
1007
|
+
incoming
|
|
1008
|
+
);
|
|
1009
|
+
if (!this.disconnectedSessions.has(message.from)) {
|
|
1010
|
+
outgoing.push(outputMessage);
|
|
1011
|
+
}
|
|
1012
|
+
} catch (err) {
|
|
1013
|
+
errorHandler(err);
|
|
1014
|
+
}
|
|
1015
|
+
})();
|
|
1016
|
+
}
|
|
1017
|
+
break;
|
|
1018
|
+
default:
|
|
1019
|
+
log?.warn(
|
|
1020
|
+
`${this.transport.clientId} -- got request for invalid procedure type ${procedure.type} at ${message.serviceName}.${message.procedureName}`
|
|
1021
|
+
);
|
|
1022
|
+
return;
|
|
989
1023
|
}
|
|
990
1024
|
const procStream = {
|
|
991
1025
|
id: message.streamId,
|
|
@@ -993,7 +1027,6 @@ var RiverServer = class {
|
|
|
993
1027
|
outgoing,
|
|
994
1028
|
serviceName: message.serviceName,
|
|
995
1029
|
procedureName: message.procedureName,
|
|
996
|
-
procedure,
|
|
997
1030
|
promises: { inputHandler, outputHandler }
|
|
998
1031
|
};
|
|
999
1032
|
this.streamMap.set(message.streamId, procStream);
|
|
@@ -1003,13 +1036,18 @@ var RiverServer = class {
|
|
|
1003
1036
|
return procStream;
|
|
1004
1037
|
}
|
|
1005
1038
|
async pushToStream(procStream, message, isInit) {
|
|
1006
|
-
const
|
|
1039
|
+
const { serviceName, procedureName } = procStream;
|
|
1040
|
+
const procedure = this.services[serviceName].procedures[procedureName];
|
|
1007
1041
|
const procHasInitMessage = "init" in procedure;
|
|
1008
|
-
if (isInit && procHasInitMessage && import_value.Value.Check(procedure.init, message.payload)
|
|
1042
|
+
if (isInit && procHasInitMessage && import_value.Value.Check(procedure.init, message.payload)) {
|
|
1043
|
+
procStream.incoming.push(message.payload);
|
|
1044
|
+
} else if (import_value.Value.Check(procedure.input, message.payload)) {
|
|
1009
1045
|
procStream.incoming.push(message.payload);
|
|
1010
1046
|
} else if (!import_value.Value.Check(ControlMessagePayloadSchema, message.payload)) {
|
|
1011
1047
|
log?.error(
|
|
1012
|
-
`${this.transport.clientId} -- procedure ${
|
|
1048
|
+
`${this.transport.clientId} -- procedure ${serviceName}.${procedureName} received invalid payload: ${JSON.stringify(
|
|
1049
|
+
message.payload
|
|
1050
|
+
)}`
|
|
1013
1051
|
);
|
|
1014
1052
|
}
|
|
1015
1053
|
if (isStreamClose(message.controlFlags)) {
|