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