@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.
Files changed (82) hide show
  1. package/README.md +28 -8
  2. package/dist/{builder-1f26296b.d.ts → builder-c593de11.d.ts} +14 -13
  3. package/dist/{chunk-3JGVFWKQ.js → chunk-55XUAPC6.js} +205 -180
  4. package/dist/{chunk-R6H2BIMC.js → chunk-GZ7HCLLM.js} +31 -7
  5. package/dist/{chunk-T7M7OKPE.js → chunk-H4BYJELI.js} +5 -1
  6. package/dist/{chunk-GKPT5YQE.js → chunk-IIBVKYDB.js} +6 -34
  7. package/dist/chunk-M6LY25P2.js +47 -0
  8. package/dist/chunk-QEYN2Z6O.js +726 -0
  9. package/dist/chunk-RDTTKCGV.js +40 -0
  10. package/dist/chunk-TKINU53F.js +44 -0
  11. package/dist/chunk-XFFS4UOD.js +127 -0
  12. package/dist/codec/index.cjs +13 -7
  13. package/dist/codec/index.js +2 -4
  14. package/dist/connection-bf7811aa.d.ts +17 -0
  15. package/dist/connection-d880aa4a.d.ts +18 -0
  16. package/dist/connection-eb10d250.d.ts +15 -0
  17. package/dist/index-0c0a69f6.d.ts +440 -0
  18. package/dist/logging/index.cjs +8 -3
  19. package/dist/logging/index.d.cts +6 -1
  20. package/dist/logging/index.d.ts +6 -1
  21. package/dist/logging/index.js +5 -3
  22. package/dist/messageFraming-b200ef25.d.ts +20 -0
  23. package/dist/router/index.cjs +250 -211
  24. package/dist/router/index.d.cts +6 -7
  25. package/dist/router/index.d.ts +6 -7
  26. package/dist/router/index.js +3 -3
  27. package/dist/transport/impls/stdio/client.cjs +909 -0
  28. package/dist/transport/impls/stdio/client.d.cts +27 -0
  29. package/dist/transport/impls/stdio/client.d.ts +27 -0
  30. package/dist/transport/impls/stdio/client.js +42 -0
  31. package/dist/transport/impls/stdio/server.cjs +883 -0
  32. package/dist/transport/impls/stdio/server.d.cts +25 -0
  33. package/dist/transport/impls/stdio/server.d.ts +25 -0
  34. package/dist/transport/impls/stdio/server.js +33 -0
  35. package/dist/transport/impls/uds/client.cjs +911 -0
  36. package/dist/transport/impls/uds/client.d.cts +16 -0
  37. package/dist/transport/impls/uds/client.d.ts +16 -0
  38. package/dist/transport/impls/uds/client.js +44 -0
  39. package/dist/transport/impls/uds/server.cjs +885 -0
  40. package/dist/transport/impls/uds/server.d.cts +16 -0
  41. package/dist/transport/impls/uds/server.d.ts +16 -0
  42. package/dist/transport/impls/uds/server.js +39 -0
  43. package/dist/transport/impls/ws/client.cjs +612 -249
  44. package/dist/transport/impls/ws/client.d.cts +6 -21
  45. package/dist/transport/impls/ws/client.d.ts +6 -21
  46. package/dist/transport/impls/ws/client.js +83 -7
  47. package/dist/transport/impls/ws/server.cjs +565 -196
  48. package/dist/transport/impls/ws/server.d.cts +6 -10
  49. package/dist/transport/impls/ws/server.d.ts +6 -10
  50. package/dist/transport/impls/ws/server.js +31 -8
  51. package/dist/transport/index.cjs +673 -130
  52. package/dist/transport/index.d.cts +3 -276
  53. package/dist/transport/index.d.ts +3 -276
  54. package/dist/transport/index.js +13 -10
  55. package/dist/util/testHelpers.cjs +40 -602
  56. package/dist/util/testHelpers.d.cts +18 -37
  57. package/dist/util/testHelpers.d.ts +18 -37
  58. package/dist/util/testHelpers.js +27 -47
  59. package/package.json +29 -14
  60. package/dist/chunk-5IC5XMWK.js +0 -140
  61. package/dist/chunk-L7D75G4K.js +0 -29
  62. package/dist/chunk-LQXPKF3A.js +0 -282
  63. package/dist/chunk-PJ2EUO7O.js +0 -63
  64. package/dist/chunk-WVT5QXMZ.js +0 -20
  65. package/dist/chunk-ZE4MX7DF.js +0 -75
  66. package/dist/connection-2529fc14.d.ts +0 -10
  67. package/dist/connection-316d6e3a.d.ts +0 -10
  68. package/dist/connection-8e19874c.d.ts +0 -11
  69. package/dist/connection-f7688cc1.d.ts +0 -11
  70. package/dist/transport/impls/stdio/stdio.cjs +0 -518
  71. package/dist/transport/impls/stdio/stdio.d.cts +0 -26
  72. package/dist/transport/impls/stdio/stdio.d.ts +0 -26
  73. package/dist/transport/impls/stdio/stdio.js +0 -70
  74. package/dist/transport/impls/unixsocket/client.cjs +0 -516
  75. package/dist/transport/impls/unixsocket/client.d.cts +0 -16
  76. package/dist/transport/impls/unixsocket/client.d.ts +0 -16
  77. package/dist/transport/impls/unixsocket/client.js +0 -67
  78. package/dist/transport/impls/unixsocket/server.cjs +0 -520
  79. package/dist/transport/impls/unixsocket/server.d.cts +0 -18
  80. package/dist/transport/impls/unixsocket/server.d.ts +0 -18
  81. package/dist/transport/impls/unixsocket/server.js +0 -73
  82. /package/dist/{chunk-ORAG7IAU.js → chunk-5IZ2UHWV.js} +0 -0
@@ -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 TransportAckSchema = TransportMessageSchema(
420
- import_typebox2.Type.Object({
421
- ack: import_typebox2.Type.String()
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 (controlFlag & 2 /* StreamOpenBit */) === 2 /* StreamOpenBit */;
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 (controlFlag & 4 /* StreamClosedBit */) === 4 /* StreamClosedBit */;
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
- var CONNECTION_GRACE_PERIOD_MS = 5e3;
559
- function rejectAfterDisconnectGrace(from, cb) {
560
- let timeout = void 0;
560
+ function createSessionDisconnectHandler(from, cb) {
561
561
  return (evt) => {
562
- if (evt.status === "connect" && evt.conn.connectedTo === from) {
563
- clearTimeout(timeout);
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, procName) {
567
+ function handleRpc(transport, serverId, input, serviceName, procedureName) {
572
568
  const streamId = (0, import_nanoid2.nanoid)();
573
- const m = msg(
574
- transport.clientId,
575
- serverId,
569
+ transport.send(serverId, {
576
570
  streamId,
577
- input,
578
571
  serviceName,
579
- procName
580
- );
581
- m.controlFlags |= 2 /* StreamOpenBit */ | 4 /* StreamClosedBit */;
582
- transport.send(m);
572
+ procedureName,
573
+ payload: input,
574
+ controlFlags: 2 /* StreamOpenBit */ | 4 /* StreamClosedBit */
575
+ });
583
576
  const responsePromise = new Promise((resolve) => {
584
- const onConnectionStatus = rejectAfterDisconnectGrace(serverId, () => {
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("connectionStatus", onConnectionStatus);
588
+ transport.removeEventListener("sessionStatus", onSessionStatus);
596
589
  }
597
- function onMessage(msg2) {
598
- if (msg2.streamId !== streamId) {
590
+ function onMessage(msg) {
591
+ if (msg.streamId !== streamId) {
599
592
  return;
600
593
  }
601
- if (msg2.to !== transport.clientId) {
594
+ if (msg.to !== transport.clientId) {
602
595
  return;
603
596
  }
604
- if (msg2.streamId === streamId) {
597
+ if (msg.streamId === streamId) {
605
598
  cleanup();
606
- resolve(msg2.payload);
599
+ resolve(msg.payload);
607
600
  }
608
601
  }
609
602
  transport.addEventListener("message", onMessage);
610
- transport.addEventListener("connectionStatus", onConnectionStatus);
603
+ transport.addEventListener("sessionStatus", onSessionStatus);
611
604
  });
612
605
  return responsePromise;
613
606
  }
614
- function handleStream(transport, serverId, init, serviceName, procName) {
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
- const m = msg(
621
- transport.clientId,
622
- serverId,
614
+ transport.send(serverId, {
623
615
  streamId,
624
- init,
625
616
  serviceName,
626
- procName
627
- );
628
- m.controlFlags = 2 /* StreamOpenBit */;
629
- transport.send(m);
617
+ procedureName,
618
+ payload: init,
619
+ controlFlags: 2 /* StreamOpenBit */
620
+ });
630
621
  firstMessage = false;
631
622
  }
632
- (async () => {
623
+ const pipeInputToTransport = async () => {
633
624
  for await (const rawIn of inputStream) {
634
- const m = msg(transport.clientId, serverId, streamId, rawIn);
625
+ const m = {
626
+ streamId,
627
+ payload: rawIn,
628
+ controlFlags: 0
629
+ };
635
630
  if (firstMessage) {
636
631
  m.serviceName = serviceName;
637
- m.procedureName = procName;
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
- transport.send(closeStream(transport.clientId, serverId, streamId));
644
- })();
645
- function onMessage(msg2) {
646
- if (msg2.streamId !== streamId) {
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 (msg2.to !== transport.clientId) {
647
+ if (msg.to !== transport.clientId) {
650
648
  return;
651
649
  }
652
- if (isStreamClose(msg2.controlFlags)) {
650
+ if (isStreamClose(msg.controlFlags)) {
653
651
  cleanup();
654
652
  } else {
655
- outputStream.push(msg2.payload);
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("connectionStatus", onConnectionStatus);
660
+ transport.removeEventListener("sessionStatus", onSessionStatus);
663
661
  }
664
- const closeHandler = () => {
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("connectionStatus", onConnectionStatus);
679
- return [inputStream, outputStream, closeHandler];
673
+ transport.addEventListener("sessionStatus", onSessionStatus);
674
+ return [inputStream, outputStream, cleanup];
680
675
  }
681
- function handleSubscribe(transport, serverId, input, serviceName, procName) {
676
+ function handleSubscribe(transport, serverId, input, serviceName, procedureName) {
682
677
  const streamId = (0, import_nanoid2.nanoid)();
683
- const m = msg(
684
- transport.clientId,
685
- serverId,
678
+ transport.send(serverId, {
686
679
  streamId,
687
- input,
688
680
  serviceName,
689
- procName
690
- );
691
- m.controlFlags |= 2 /* StreamOpenBit */;
692
- transport.send(m);
681
+ procedureName,
682
+ payload: input,
683
+ controlFlags: 2 /* StreamOpenBit */
684
+ });
685
+ let healthyClose = true;
693
686
  const outputStream = pushable({ objectMode: true });
694
- function onMessage(msg2) {
695
- if (msg2.streamId !== streamId) {
687
+ function onMessage(msg) {
688
+ if (msg.streamId !== streamId) {
696
689
  return;
697
690
  }
698
- if (msg2.to !== transport.clientId) {
691
+ if (msg.to !== transport.clientId) {
699
692
  return;
700
693
  }
701
- if (isStreamClose(msg2.controlFlags)) {
694
+ if (isStreamClose(msg.controlFlags)) {
702
695
  cleanup();
703
696
  } else {
704
- outputStream.push(msg2.payload);
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("connectionStatus", onConnectionStatus);
703
+ transport.removeEventListener("sessionStatus", onSessionStatus);
711
704
  }
712
705
  const closeHandler = () => {
713
706
  cleanup();
714
- transport.send(closeStream(transport.clientId, serverId, streamId));
707
+ if (!healthyClose)
708
+ return;
709
+ transport.sendCloseStream(serverId, streamId);
715
710
  };
716
- const onConnectionStatus = rejectAfterDisconnectGrace(serverId, () => {
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("connectionStatus", onConnectionStatus);
722
+ transport.addEventListener("sessionStatus", onSessionStatus);
727
723
  return [outputStream, closeHandler];
728
724
  }
729
- function handleUpload(transport, serverId, input, serviceName, procName) {
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
- if (input) {
734
- const m = msg(
735
- transport.clientId,
736
- serverId,
729
+ let healthyClose = true;
730
+ if (init) {
731
+ transport.send(serverId, {
737
732
  streamId,
738
- input,
739
733
  serviceName,
740
- procName
741
- );
742
- m.controlFlags = 2 /* StreamOpenBit */;
743
- transport.send(m);
734
+ procedureName,
735
+ payload: init,
736
+ controlFlags: 2 /* StreamOpenBit */
737
+ });
744
738
  firstMessage = false;
745
739
  }
746
- (async () => {
740
+ const pipeInputToTransport = async () => {
747
741
  for await (const rawIn of inputStream) {
748
- const m = msg(transport.clientId, serverId, streamId, rawIn);
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 = procName;
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
- transport.send(closeStream(transport.clientId, serverId, streamId));
758
- })();
755
+ if (!healthyClose)
756
+ return;
757
+ transport.sendCloseStream(serverId, streamId);
758
+ };
759
+ void pipeInputToTransport();
759
760
  const responsePromise = new Promise((resolve) => {
760
- const onConnectionStatus = rejectAfterDisconnectGrace(serverId, () => {
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("connectionStatus", onConnectionStatus);
774
+ transport.removeEventListener("sessionStatus", onSessionStatus);
773
775
  }
774
- function onMessage(msg2) {
775
- if (msg2.to !== transport.clientId) {
776
+ function onMessage(msg) {
777
+ if (msg.to !== transport.clientId) {
776
778
  return;
777
779
  }
778
- if (msg2.streamId === streamId) {
780
+ if (msg.streamId === streamId) {
779
781
  cleanup();
780
- resolve(msg2.payload);
782
+ resolve(msg.payload);
781
783
  }
782
784
  }
783
785
  transport.addEventListener("message", onMessage);
784
- transport.addEventListener("connectionStatus", onConnectionStatus);
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.handler);
815
- this.transport.addEventListener("connectionStatus", this.onDisconnect);
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
- handler = async (message) => {
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 unexpected disconnections
836
- onDisconnect = async (evt) => {
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.conn.connectedTo;
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.handler);
855
- this.transport.removeEventListener("connectionStatus", this.onDisconnect);
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(reply(message, response));
909
+ this.transport.send(session.to, {
910
+ streamId: message.streamId,
911
+ controlFlags: 0,
912
+ payload: response
913
+ });
887
914
  }
888
- if (procedure.type === "subscription" || procedure.type === "stream") {
889
- this.transport.send(
890
- closeStream(
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 instanceof Error ? err.message : `[coerced to error] ${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
- if (procedure.type === "stream") {
914
- if (procHasInitMessage) {
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 initMessage = await incoming.next();
957
- if (initMessage.done) {
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
- initMessage.value,
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
- } else {
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
- const outputMessage = await procedure.handler(
973
+ await procedure.handler(
975
974
  serviceContext,
976
- incoming
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
- } else {
985
- log?.warn(
986
- `${this.transport.clientId} -- got request for invalid procedure type ${procedure.type} at ${message.serviceName}.${message.procedureName}`
987
- );
988
- return;
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 procedure = procStream.procedure;
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) || import_value.Value.Check(procedure.input, 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 ${procStream.serviceName}.${procStream.procedureName} received invalid payload: ${JSON.stringify(message.payload)}`
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)) {