@replit/river 0.21.1 → 0.23.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.
Files changed (63) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-FDLAPYCK.js → chunk-DZOATC6M.js} +2 -2
  3. package/dist/{chunk-JMXO5L2X.js → chunk-MJUFKPBT.js} +354 -398
  4. package/dist/chunk-MJUFKPBT.js.map +1 -0
  5. package/dist/{chunk-5WFL722S.js → chunk-PCKHBAVP.js} +94 -3
  6. package/dist/chunk-PCKHBAVP.js.map +1 -0
  7. package/dist/{chunk-NCXUFDVL.js → chunk-VOJVLWVX.js} +360 -516
  8. package/dist/chunk-VOJVLWVX.js.map +1 -0
  9. package/dist/chunk-ZF2UFTNN.js +60 -0
  10. package/dist/chunk-ZF2UFTNN.js.map +1 -0
  11. package/dist/{connection-76c5ed01.d.ts → connection-5685d817.d.ts} +6 -4
  12. package/dist/{connection-975b25c9.d.ts → connection-7582fb92.d.ts} +1 -1
  13. package/dist/{index-dfad460e.d.ts → index-a6fe0edd.d.ts} +55 -59
  14. package/dist/logging/index.d.cts +2 -1
  15. package/dist/logging/index.d.ts +2 -1
  16. package/dist/router/index.cjs +405 -502
  17. package/dist/router/index.cjs.map +1 -1
  18. package/dist/router/index.d.cts +12 -6
  19. package/dist/router/index.d.ts +12 -6
  20. package/dist/router/index.js +4 -3
  21. package/dist/{services-9c496c6e.d.ts → services-be91b485.d.ts} +21 -52
  22. package/dist/{services-7b716dcf.d.ts → services-eb9326a1.d.ts} +21 -52
  23. package/dist/transport/impls/uds/client.cjs +197 -155
  24. package/dist/transport/impls/uds/client.cjs.map +1 -1
  25. package/dist/transport/impls/uds/client.d.cts +3 -2
  26. package/dist/transport/impls/uds/client.d.ts +3 -2
  27. package/dist/transport/impls/uds/client.js +3 -3
  28. package/dist/transport/impls/uds/server.cjs +280 -266
  29. package/dist/transport/impls/uds/server.cjs.map +1 -1
  30. package/dist/transport/impls/uds/server.d.cts +3 -2
  31. package/dist/transport/impls/uds/server.d.ts +3 -2
  32. package/dist/transport/impls/uds/server.js +3 -3
  33. package/dist/transport/impls/ws/client.cjs +251 -214
  34. package/dist/transport/impls/ws/client.cjs.map +1 -1
  35. package/dist/transport/impls/ws/client.d.cts +6 -6
  36. package/dist/transport/impls/ws/client.d.ts +6 -6
  37. package/dist/transport/impls/ws/client.js +33 -48
  38. package/dist/transport/impls/ws/client.js.map +1 -1
  39. package/dist/transport/impls/ws/server.cjs +302 -280
  40. package/dist/transport/impls/ws/server.cjs.map +1 -1
  41. package/dist/transport/impls/ws/server.d.cts +5 -4
  42. package/dist/transport/impls/ws/server.d.ts +5 -4
  43. package/dist/transport/impls/ws/server.js +3 -3
  44. package/dist/transport/impls/ws/server.js.map +1 -1
  45. package/dist/transport/index.cjs +400 -396
  46. package/dist/transport/index.cjs.map +1 -1
  47. package/dist/transport/index.d.cts +25 -14
  48. package/dist/transport/index.d.ts +25 -14
  49. package/dist/transport/index.js +2 -2
  50. package/dist/util/testHelpers.cjs +59 -14
  51. package/dist/util/testHelpers.cjs.map +1 -1
  52. package/dist/util/testHelpers.d.cts +14 -5
  53. package/dist/util/testHelpers.d.ts +14 -5
  54. package/dist/util/testHelpers.js +12 -5
  55. package/dist/util/testHelpers.js.map +1 -1
  56. package/dist/wslike-e0b32dd5.d.ts +40 -0
  57. package/package.json +4 -5
  58. package/dist/chunk-3Y7AB5EB.js +0 -42
  59. package/dist/chunk-3Y7AB5EB.js.map +0 -1
  60. package/dist/chunk-5WFL722S.js.map +0 -1
  61. package/dist/chunk-JMXO5L2X.js.map +0 -1
  62. package/dist/chunk-NCXUFDVL.js.map +0 -1
  63. /package/dist/{chunk-FDLAPYCK.js.map → chunk-DZOATC6M.js.map} +0 -0
@@ -1,24 +1,30 @@
1
1
  import {
2
2
  ControlMessagePayloadSchema,
3
3
  coerceErrorString,
4
+ createHandlerSpan,
5
+ createProcTelemetryInfo,
6
+ getPropagationContext,
4
7
  isStreamClose,
5
- isStreamOpen,
6
- tracing_default
7
- } from "./chunk-5WFL722S.js";
8
+ isStreamOpen
9
+ } from "./chunk-PCKHBAVP.js";
8
10
  import {
9
11
  log
10
12
  } from "./chunk-OTQNCLFH.js";
11
13
 
12
14
  // router/services.ts
13
15
  import { Type } from "@sinclair/typebox";
14
- function serializeSchema(services) {
15
- return Object.entries(services).reduce(
16
- (acc, [name, value]) => {
17
- acc[name] = value.serialize();
18
- return acc;
19
- },
20
- {}
21
- );
16
+ function serializeSchema(services, handshakeSchema) {
17
+ const serializedServiceObject = Object.entries(services).reduce((acc, [name, value]) => {
18
+ acc[name] = value.serialize();
19
+ return acc;
20
+ }, {});
21
+ const schema = {
22
+ services: serializedServiceObject
23
+ };
24
+ if (handshakeSchema) {
25
+ schema.handshakeSchema = Type.Strict(handshakeSchema);
26
+ }
27
+ return schema;
22
28
  }
23
29
  var ServiceSchema = class _ServiceSchema {
24
30
  /**
@@ -298,14 +304,6 @@ var Procedure = {
298
304
  stream
299
305
  };
300
306
 
301
- // router/client.ts
302
- import {
303
- context,
304
- propagation,
305
- SpanKind,
306
- SpanStatusCode
307
- } from "@opentelemetry/api";
308
-
309
307
  // node_modules/p-defer/index.js
310
308
  function pDefer() {
311
309
  const deferred = {};
@@ -642,7 +640,10 @@ var defaultClientOptions = {
642
640
  connectOnInvoke: true,
643
641
  eagerlyConnect: true
644
642
  };
645
- var createClient = (transport, serverId, providedClientOptions = {}) => {
643
+ function createClient(transport, serverId, providedClientOptions = {}) {
644
+ if (providedClientOptions.handshakeOptions) {
645
+ transport.extendHandshake(providedClientOptions.handshakeOptions);
646
+ }
646
647
  const options = { ...defaultClientOptions, ...providedClientOptions };
647
648
  if (options.eagerlyConnect) {
648
649
  void transport.connect(serverId);
@@ -678,7 +679,7 @@ var createClient = (transport, serverId, providedClientOptions = {}) => {
678
679
  throw new Error(`invalid river call, unknown procedure type ${procType}`);
679
680
  }
680
681
  }, []);
681
- };
682
+ }
682
683
  function createSessionDisconnectHandler(from, cb) {
683
684
  return (evt) => {
684
685
  if (evt.status === "disconnect" && evt.session.to === from) {
@@ -688,324 +689,256 @@ function createSessionDisconnectHandler(from, cb) {
688
689
  }
689
690
  function handleRpc(transport, serverId, input, serviceName, procedureName) {
690
691
  const streamId = nanoid();
691
- return tracing_default.startActiveSpan(
692
- `${serviceName}.${procedureName}`,
693
- {
694
- attributes: {
695
- component: "river",
696
- "river.method.kind": "rpc",
697
- "river.method.service": serviceName,
698
- "river.method.name": procedureName,
699
- "river.streamId": streamId,
700
- "span.kind": "client"
701
- },
702
- kind: SpanKind.CLIENT
703
- },
704
- (span) => {
705
- const tracing = { traceparent: "", tracestate: "" };
706
- propagation.inject(context.active(), tracing);
707
- transport.send(serverId, {
708
- streamId,
709
- serviceName,
710
- procedureName,
711
- tracing,
712
- payload: input,
713
- controlFlags: 2 /* StreamOpenBit */ | 4 /* StreamClosedBit */
714
- });
715
- const responsePromise = new Promise((resolve) => {
716
- const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
717
- span.setStatus({ code: SpanStatusCode.ERROR });
718
- cleanup();
719
- resolve(
720
- Err({
721
- code: UNEXPECTED_DISCONNECT,
722
- message: `${serverId} unexpectedly disconnected`
723
- })
724
- );
725
- });
726
- function cleanup() {
727
- transport.removeEventListener("message", onMessage);
728
- transport.removeEventListener("sessionStatus", onSessionStatus);
729
- span.end();
730
- }
731
- function onMessage(msg) {
732
- if (msg.streamId !== streamId)
733
- return;
734
- if (msg.to !== transport.clientId)
735
- return;
736
- if (msg.payload && typeof msg.payload === "object" && "ok" in msg.payload) {
737
- span.setStatus({
738
- code: msg.payload.ok ? SpanStatusCode.OK : SpanStatusCode.ERROR
739
- });
740
- }
741
- cleanup();
742
- resolve(msg.payload);
743
- }
744
- transport.addEventListener("message", onMessage);
745
- transport.addEventListener("sessionStatus", onSessionStatus);
746
- });
747
- return responsePromise;
748
- }
692
+ const { span, ctx } = createProcTelemetryInfo(
693
+ "rpc",
694
+ serviceName,
695
+ procedureName,
696
+ streamId
749
697
  );
698
+ transport.send(serverId, {
699
+ streamId,
700
+ serviceName,
701
+ procedureName,
702
+ payload: input,
703
+ tracing: getPropagationContext(ctx),
704
+ controlFlags: 2 /* StreamOpenBit */ | 4 /* StreamClosedBit */
705
+ });
706
+ const responsePromise = new Promise((resolve) => {
707
+ const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
708
+ cleanup();
709
+ resolve(
710
+ Err({
711
+ code: UNEXPECTED_DISCONNECT,
712
+ message: `${serverId} unexpectedly disconnected`
713
+ })
714
+ );
715
+ });
716
+ function cleanup() {
717
+ transport.removeEventListener("message", onMessage);
718
+ transport.removeEventListener("sessionStatus", onSessionStatus);
719
+ span.end();
720
+ }
721
+ function onMessage(msg) {
722
+ if (msg.streamId !== streamId)
723
+ return;
724
+ if (msg.to !== transport.clientId)
725
+ return;
726
+ cleanup();
727
+ resolve(msg.payload);
728
+ }
729
+ transport.addEventListener("message", onMessage);
730
+ transport.addEventListener("sessionStatus", onSessionStatus);
731
+ });
732
+ return responsePromise;
750
733
  }
751
734
  function handleStream(transport, serverId, init, serviceName, procedureName) {
752
735
  const streamId = nanoid();
753
- return tracing_default.startActiveSpan(
754
- `${serviceName}.${procedureName}`,
755
- {
756
- attributes: {
757
- component: "river",
758
- "river.method.kind": init ? "stream-with-init" : "stream",
759
- "river.method.service": serviceName,
760
- "river.method.name": procedureName,
761
- "river.streamId": streamId,
762
- "span.kind": "client"
763
- },
764
- kind: SpanKind.CLIENT
765
- },
766
- (span) => {
767
- const tracing = { traceparent: "", tracestate: "" };
768
- propagation.inject(context.active(), tracing);
769
- const inputStream = pushable({ objectMode: true });
770
- const outputStream = pushable({ objectMode: true });
771
- let firstMessage = true;
772
- let healthyClose = true;
773
- if (init) {
774
- transport.send(serverId, {
775
- streamId,
776
- serviceName,
777
- procedureName,
778
- tracing,
779
- payload: init,
780
- controlFlags: 2 /* StreamOpenBit */
781
- });
782
- firstMessage = false;
783
- }
784
- const pipeInputToTransport = async () => {
785
- for await (const rawIn of inputStream) {
786
- const m = {
787
- streamId,
788
- payload: rawIn,
789
- controlFlags: 0
790
- };
791
- if (firstMessage) {
792
- m.serviceName = serviceName;
793
- m.procedureName = procedureName;
794
- m.tracing = tracing;
795
- m.controlFlags |= 2 /* StreamOpenBit */;
796
- firstMessage = false;
797
- }
798
- transport.send(serverId, m);
799
- }
800
- if (!healthyClose)
801
- return;
802
- transport.sendCloseStream(serverId, streamId);
803
- span.setStatus({ code: SpanStatusCode.OK });
736
+ const { span, ctx } = createProcTelemetryInfo(
737
+ "stream",
738
+ serviceName,
739
+ procedureName,
740
+ streamId
741
+ );
742
+ const inputStream = pushable({ objectMode: true });
743
+ const outputStream = pushable({ objectMode: true });
744
+ let firstMessage = true;
745
+ let healthyClose = true;
746
+ if (init) {
747
+ transport.send(serverId, {
748
+ streamId,
749
+ serviceName,
750
+ procedureName,
751
+ payload: init,
752
+ tracing: getPropagationContext(ctx),
753
+ controlFlags: 2 /* StreamOpenBit */
754
+ });
755
+ firstMessage = false;
756
+ }
757
+ const pipeInputToTransport = async () => {
758
+ for await (const rawIn of inputStream) {
759
+ const m = {
760
+ streamId,
761
+ payload: rawIn,
762
+ controlFlags: 0
804
763
  };
805
- void pipeInputToTransport();
806
- function onMessage(msg) {
807
- if (msg.streamId !== streamId)
808
- return;
809
- if (msg.to !== transport.clientId)
810
- return;
811
- if (isStreamClose(msg.controlFlags)) {
812
- cleanup();
813
- } else {
814
- outputStream.push(msg.payload);
815
- }
816
- }
817
- function cleanup() {
818
- inputStream.end();
819
- outputStream.end();
820
- transport.removeEventListener("message", onMessage);
821
- transport.removeEventListener("sessionStatus", onSessionStatus);
822
- span.end();
764
+ if (firstMessage) {
765
+ m.serviceName = serviceName;
766
+ m.procedureName = procedureName;
767
+ m.tracing = getPropagationContext(ctx);
768
+ m.controlFlags |= 2 /* StreamOpenBit */;
769
+ firstMessage = false;
823
770
  }
824
- const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
825
- outputStream.push(
826
- Err({
827
- code: UNEXPECTED_DISCONNECT,
828
- message: `${serverId} unexpectedly disconnected`
829
- })
830
- );
831
- healthyClose = false;
832
- span.setStatus({ code: SpanStatusCode.ERROR });
833
- cleanup();
834
- });
835
- transport.addEventListener("message", onMessage);
836
- transport.addEventListener("sessionStatus", onSessionStatus);
837
- return [inputStream, outputStream, cleanup];
771
+ transport.send(serverId, m);
838
772
  }
839
- );
773
+ if (!healthyClose)
774
+ return;
775
+ transport.sendCloseStream(serverId, streamId);
776
+ };
777
+ void pipeInputToTransport();
778
+ function onMessage(msg) {
779
+ if (msg.streamId !== streamId)
780
+ return;
781
+ if (msg.to !== transport.clientId)
782
+ return;
783
+ if (isStreamClose(msg.controlFlags)) {
784
+ cleanup();
785
+ } else {
786
+ outputStream.push(msg.payload);
787
+ }
788
+ }
789
+ function cleanup() {
790
+ inputStream.end();
791
+ outputStream.end();
792
+ transport.removeEventListener("message", onMessage);
793
+ transport.removeEventListener("sessionStatus", onSessionStatus);
794
+ span.end();
795
+ }
796
+ const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
797
+ outputStream.push(
798
+ Err({
799
+ code: UNEXPECTED_DISCONNECT,
800
+ message: `${serverId} unexpectedly disconnected`
801
+ })
802
+ );
803
+ healthyClose = false;
804
+ cleanup();
805
+ });
806
+ transport.addEventListener("message", onMessage);
807
+ transport.addEventListener("sessionStatus", onSessionStatus);
808
+ return [inputStream, outputStream, cleanup];
840
809
  }
841
810
  function handleSubscribe(transport, serverId, input, serviceName, procedureName) {
842
811
  const streamId = nanoid();
843
- return tracing_default.startActiveSpan(
844
- `${serviceName}.${procedureName}`,
845
- {
846
- attributes: {
847
- component: "river",
848
- "river.method.kind": "subscribe",
849
- "river.method.service": serviceName,
850
- "river.method.name": procedureName,
851
- "river.streamId": streamId,
852
- "span.kind": "client"
853
- },
854
- kind: SpanKind.CLIENT
855
- },
856
- (span) => {
857
- const tracing = { traceparent: "", tracestate: "" };
858
- propagation.inject(context.active(), tracing);
859
- transport.send(serverId, {
860
- streamId,
861
- serviceName,
862
- procedureName,
863
- tracing,
864
- payload: input,
865
- controlFlags: 2 /* StreamOpenBit */
866
- });
867
- let healthyClose = true;
868
- const outputStream = pushable({ objectMode: true });
869
- function onMessage(msg) {
870
- if (msg.streamId !== streamId)
871
- return;
872
- if (msg.to !== transport.clientId)
873
- return;
874
- if (isStreamClose(msg.controlFlags)) {
875
- cleanup();
876
- } else {
877
- outputStream.push(msg.payload);
878
- }
879
- }
880
- function cleanup() {
881
- outputStream.end();
882
- transport.removeEventListener("message", onMessage);
883
- transport.removeEventListener("sessionStatus", onSessionStatus);
884
- span.end();
885
- }
886
- const closeHandler = () => {
887
- cleanup();
888
- if (!healthyClose)
889
- return;
890
- transport.sendCloseStream(serverId, streamId);
891
- };
892
- const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
893
- outputStream.push(
894
- Err({
895
- code: UNEXPECTED_DISCONNECT,
896
- message: `${serverId} unexpectedly disconnected`
897
- })
898
- );
899
- healthyClose = false;
900
- span.setStatus({ code: SpanStatusCode.ERROR });
901
- cleanup();
902
- });
903
- transport.addEventListener("message", onMessage);
904
- transport.addEventListener("sessionStatus", onSessionStatus);
905
- return [outputStream, closeHandler];
906
- }
812
+ const { span, ctx } = createProcTelemetryInfo(
813
+ "subscription",
814
+ serviceName,
815
+ procedureName,
816
+ streamId
907
817
  );
818
+ transport.send(serverId, {
819
+ streamId,
820
+ serviceName,
821
+ procedureName,
822
+ payload: input,
823
+ tracing: getPropagationContext(ctx),
824
+ controlFlags: 2 /* StreamOpenBit */
825
+ });
826
+ let healthyClose = true;
827
+ const outputStream = pushable({ objectMode: true });
828
+ function onMessage(msg) {
829
+ if (msg.streamId !== streamId)
830
+ return;
831
+ if (msg.to !== transport.clientId)
832
+ return;
833
+ if (isStreamClose(msg.controlFlags)) {
834
+ cleanup();
835
+ } else {
836
+ outputStream.push(msg.payload);
837
+ }
838
+ }
839
+ function cleanup() {
840
+ outputStream.end();
841
+ transport.removeEventListener("message", onMessage);
842
+ transport.removeEventListener("sessionStatus", onSessionStatus);
843
+ span.end();
844
+ }
845
+ const closeHandler = () => {
846
+ cleanup();
847
+ if (!healthyClose)
848
+ return;
849
+ transport.sendCloseStream(serverId, streamId);
850
+ };
851
+ const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
852
+ outputStream.push(
853
+ Err({
854
+ code: UNEXPECTED_DISCONNECT,
855
+ message: `${serverId} unexpectedly disconnected`
856
+ })
857
+ );
858
+ healthyClose = false;
859
+ cleanup();
860
+ });
861
+ transport.addEventListener("message", onMessage);
862
+ transport.addEventListener("sessionStatus", onSessionStatus);
863
+ return [outputStream, closeHandler];
908
864
  }
909
865
  function handleUpload(transport, serverId, init, serviceName, procedureName) {
910
866
  const streamId = nanoid();
911
- return tracing_default.startActiveSpan(
912
- `${serviceName}.${procedureName}`,
913
- {
914
- attributes: {
915
- component: "river",
916
- "river.method.kind": init ? "upload-with-init" : "upload",
917
- "river.method.service": serviceName,
918
- "river.method.name": procedureName,
919
- "river.streamId": streamId,
920
- "span.kind": "client"
921
- },
922
- kind: SpanKind.CLIENT
923
- },
924
- (span) => {
925
- const tracing = { traceparent: "", tracestate: "" };
926
- propagation.inject(context.active(), tracing);
927
- const inputStream = pushable({ objectMode: true });
928
- let firstMessage = true;
929
- let healthyClose = true;
930
- if (init) {
931
- transport.send(serverId, {
932
- streamId,
933
- serviceName,
934
- procedureName,
935
- tracing,
936
- payload: init,
937
- controlFlags: 2 /* StreamOpenBit */
938
- });
867
+ const { span, ctx } = createProcTelemetryInfo(
868
+ "upload",
869
+ serviceName,
870
+ procedureName,
871
+ streamId
872
+ );
873
+ const inputStream = pushable({ objectMode: true });
874
+ let firstMessage = true;
875
+ let healthyClose = true;
876
+ if (init) {
877
+ transport.send(serverId, {
878
+ streamId,
879
+ serviceName,
880
+ procedureName,
881
+ payload: init,
882
+ tracing: getPropagationContext(ctx),
883
+ controlFlags: 2 /* StreamOpenBit */
884
+ });
885
+ firstMessage = false;
886
+ }
887
+ const pipeInputToTransport = async () => {
888
+ for await (const rawIn of inputStream) {
889
+ const m = {
890
+ streamId,
891
+ payload: rawIn,
892
+ controlFlags: 0
893
+ };
894
+ if (firstMessage) {
895
+ m.serviceName = serviceName;
896
+ m.procedureName = procedureName;
897
+ m.tracing = getPropagationContext(ctx);
898
+ m.controlFlags |= 2 /* StreamOpenBit */;
939
899
  firstMessage = false;
940
900
  }
941
- const pipeInputToTransport = async () => {
942
- for await (const rawIn of inputStream) {
943
- const m = {
944
- streamId,
945
- payload: rawIn,
946
- controlFlags: 0
947
- };
948
- if (firstMessage) {
949
- m.serviceName = serviceName;
950
- m.procedureName = procedureName;
951
- m.tracing = tracing;
952
- m.controlFlags |= 2 /* StreamOpenBit */;
953
- firstMessage = false;
954
- }
955
- transport.send(serverId, m);
956
- }
957
- if (!healthyClose)
958
- return;
959
- transport.sendCloseStream(serverId, streamId);
960
- };
961
- void pipeInputToTransport();
962
- const responsePromise = new Promise((resolve) => {
963
- const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
964
- healthyClose = false;
965
- span.setStatus({ code: SpanStatusCode.ERROR });
966
- cleanup();
967
- resolve(
968
- Err({
969
- code: UNEXPECTED_DISCONNECT,
970
- message: `${serverId} unexpectedly disconnected`
971
- })
972
- );
973
- });
974
- function cleanup() {
975
- inputStream.end();
976
- transport.removeEventListener("message", onMessage);
977
- transport.removeEventListener("sessionStatus", onSessionStatus);
978
- span.end();
979
- }
980
- function onMessage(msg) {
981
- if (msg.streamId !== streamId)
982
- return;
983
- if (msg.to !== transport.clientId)
984
- return;
985
- if (msg.payload && typeof msg.payload === "object" && "ok" in msg.payload) {
986
- span.setStatus({
987
- code: msg.payload.ok ? SpanStatusCode.OK : SpanStatusCode.ERROR
988
- });
989
- }
990
- cleanup();
991
- resolve(msg.payload);
992
- }
993
- transport.addEventListener("message", onMessage);
994
- transport.addEventListener("sessionStatus", onSessionStatus);
995
- });
996
- return [inputStream, responsePromise];
901
+ transport.send(serverId, m);
997
902
  }
998
- );
903
+ if (!healthyClose)
904
+ return;
905
+ transport.sendCloseStream(serverId, streamId);
906
+ };
907
+ void pipeInputToTransport();
908
+ const responsePromise = new Promise((resolve) => {
909
+ const onSessionStatus = createSessionDisconnectHandler(serverId, () => {
910
+ healthyClose = false;
911
+ cleanup();
912
+ resolve(
913
+ Err({
914
+ code: UNEXPECTED_DISCONNECT,
915
+ message: `${serverId} unexpectedly disconnected`
916
+ })
917
+ );
918
+ });
919
+ function cleanup() {
920
+ inputStream.end();
921
+ transport.removeEventListener("message", onMessage);
922
+ transport.removeEventListener("sessionStatus", onSessionStatus);
923
+ span.end();
924
+ }
925
+ function onMessage(msg) {
926
+ if (msg.streamId !== streamId)
927
+ return;
928
+ if (msg.to !== transport.clientId)
929
+ return;
930
+ cleanup();
931
+ resolve(msg.payload);
932
+ }
933
+ transport.addEventListener("message", onMessage);
934
+ transport.addEventListener("sessionStatus", onSessionStatus);
935
+ });
936
+ return [inputStream, responsePromise];
999
937
  }
1000
938
 
1001
939
  // router/server.ts
1002
- import {
1003
- context as context2,
1004
- propagation as propagation2,
1005
- SpanKind as SpanKind2,
1006
- SpanStatusCode as SpanStatusCode2
1007
- } from "@opentelemetry/api";
1008
940
  import { Value } from "@sinclair/typebox/value";
941
+ import { SpanStatusCode } from "@opentelemetry/api";
1009
942
  var RiverServer = class {
1010
943
  transport;
1011
944
  services;
@@ -1015,7 +948,7 @@ var RiverServer = class {
1015
948
  // map of client to their open streams by streamId
1016
949
  clientStreams;
1017
950
  disconnectedSessions;
1018
- constructor(transport, services, extendedContext) {
951
+ constructor(transport, services, handshakeOptions, extendedContext) {
1019
952
  const instances = {};
1020
953
  this.services = instances;
1021
954
  this.contextMap = /* @__PURE__ */ new Map();
@@ -1027,6 +960,9 @@ var RiverServer = class {
1027
960
  state: instance.state
1028
961
  });
1029
962
  }
963
+ if (handshakeOptions) {
964
+ transport.extendHandshake(handshakeOptions);
965
+ }
1030
966
  this.transport = transport;
1031
967
  this.disconnectedSessions = /* @__PURE__ */ new Set();
1032
968
  this.streamMap = /* @__PURE__ */ new Map();
@@ -1076,9 +1012,9 @@ var RiverServer = class {
1076
1012
  this.transport.removeEventListener("message", this.onMessage);
1077
1013
  this.transport.removeEventListener("sessionStatus", this.onSessionStatus);
1078
1014
  await Promise.all([...this.streamMap.keys()].map(this.cleanupStream));
1079
- for (const context3 of this.contextMap.values()) {
1080
- if (Symbol.dispose in context3.state) {
1081
- const dispose = context3.state[Symbol.dispose];
1015
+ for (const context of this.contextMap.values()) {
1016
+ if (Symbol.dispose in context.state) {
1017
+ const dispose = context.state[Symbol.dispose];
1082
1018
  if (typeof dispose === "function") {
1083
1019
  dispose();
1084
1020
  }
@@ -1111,10 +1047,6 @@ var RiverServer = class {
1111
1047
  });
1112
1048
  return;
1113
1049
  }
1114
- let activeContext = context2.active();
1115
- if (message.tracing) {
1116
- activeContext = propagation2.extract(activeContext, message.tracing);
1117
- }
1118
1050
  const service = this.services[message.serviceName];
1119
1051
  const serviceContext = this.getContext(service, message.serviceName);
1120
1052
  if (!(message.procedureName in service.procedures)) {
@@ -1178,12 +1110,8 @@ var RiverServer = class {
1178
1110
  `procedure ${message.serviceName}.${message.procedureName} threw an uncaught error: ${errorMsg}`,
1179
1111
  session.loggingMetadata
1180
1112
  );
1181
- if (err instanceof Error) {
1182
- span.recordException(err);
1183
- } else {
1184
- span.recordException(errorMsg);
1185
- }
1186
- span.setStatus({ code: SpanStatusCode2.ERROR });
1113
+ span.recordException(err instanceof Error ? err : new Error(errorMsg));
1114
+ span.setStatus({ code: SpanStatusCode.ERROR });
1187
1115
  outgoing.push(
1188
1116
  Err({
1189
1117
  code: UNCAUGHT_ERROR,
@@ -1191,7 +1119,8 @@ var RiverServer = class {
1191
1119
  })
1192
1120
  );
1193
1121
  };
1194
- if (session.metadata === void 0) {
1122
+ const sessionMeta = this.transport.sessionHandshakeMetadata.get(session);
1123
+ if (!sessionMeta) {
1195
1124
  log?.error(`session doesn't have handshake metadata`, {
1196
1125
  ...session.loggingMetadata,
1197
1126
  tags: ["invariant-violation"]
@@ -1205,37 +1134,53 @@ var RiverServer = class {
1205
1134
  to: message.to,
1206
1135
  from: message.from,
1207
1136
  streamId: message.streamId,
1208
- // we've already validated that the session has handshake metadata
1209
- session
1137
+ session,
1138
+ metadata: sessionMeta
1210
1139
  };
1211
1140
  switch (procedure.type) {
1212
1141
  case "rpc":
1213
- inputHandler = (async () => {
1214
- const inputMessage = await incoming.next();
1215
- if (inputMessage.done) {
1216
- return;
1142
+ inputHandler = createHandlerSpan(
1143
+ procedure.type,
1144
+ message,
1145
+ async (span) => {
1146
+ const inputMessage = await incoming.next();
1147
+ if (inputMessage.done) {
1148
+ return;
1149
+ }
1150
+ try {
1151
+ const outputMessage = await procedure.handler(
1152
+ serviceContextWithTransportInfo,
1153
+ inputMessage.value
1154
+ );
1155
+ outgoing.push(outputMessage);
1156
+ } catch (err) {
1157
+ errorHandler(err, span);
1158
+ } finally {
1159
+ span.end();
1160
+ }
1217
1161
  }
1218
- await tracing_default.startActiveSpan(
1219
- `${message.serviceName}.${message.procedureName}`,
1220
- {
1221
- attributes: {
1222
- component: "river",
1223
- "river.method.kind": "rpc",
1224
- "river.method.service": message.serviceName,
1225
- "river.method.name": message.procedureName,
1226
- "river.streamId": message.streamId,
1227
- "span.kind": "server"
1228
- },
1229
- kind: SpanKind2.SERVER
1230
- },
1231
- activeContext,
1162
+ );
1163
+ break;
1164
+ case "stream":
1165
+ if (procHasInitMessage) {
1166
+ inputHandler = createHandlerSpan(
1167
+ procedure.type,
1168
+ message,
1232
1169
  async (span) => {
1170
+ const initMessage = await incoming.next();
1171
+ if (initMessage.done) {
1172
+ return;
1173
+ }
1233
1174
  try {
1234
- const outputMessage = await procedure.handler(
1175
+ const dispose = await procedure.handler(
1235
1176
  serviceContextWithTransportInfo,
1236
- inputMessage.value
1177
+ initMessage.value,
1178
+ incoming,
1179
+ outgoing
1237
1180
  );
1238
- outgoing.push(outputMessage);
1181
+ if (dispose) {
1182
+ disposables.push(dispose);
1183
+ }
1239
1184
  } catch (err) {
1240
1185
  errorHandler(err, span);
1241
1186
  } finally {
@@ -1243,67 +1188,10 @@ var RiverServer = class {
1243
1188
  }
1244
1189
  }
1245
1190
  );
1246
- })();
1247
- break;
1248
- case "stream":
1249
- if (procHasInitMessage) {
1250
- inputHandler = (async () => {
1251
- const initMessage = await incoming.next();
1252
- if (initMessage.done) {
1253
- return;
1254
- }
1255
- await tracing_default.startActiveSpan(
1256
- `${message.serviceName}.${message.procedureName}`,
1257
- {
1258
- attributes: {
1259
- component: "river",
1260
- "river.method.kind": "stream-with-init",
1261
- "river.method.service": message.serviceName,
1262
- "river.method.name": message.procedureName,
1263
- "river.streamId": message.streamId,
1264
- "span.kind": "server"
1265
- },
1266
- kind: SpanKind2.SERVER
1267
- },
1268
- activeContext,
1269
- async (span) => {
1270
- try {
1271
- const dispose = await procedure.handler(
1272
- serviceContextWithTransportInfo,
1273
- initMessage.value,
1274
- incoming,
1275
- outgoing
1276
- );
1277
- if (dispose) {
1278
- disposables.push(() => {
1279
- dispose();
1280
- span.end();
1281
- });
1282
- } else {
1283
- span.end();
1284
- }
1285
- } catch (err) {
1286
- errorHandler(err, span);
1287
- span.end();
1288
- }
1289
- }
1290
- );
1291
- })();
1292
1191
  } else {
1293
- inputHandler = tracing_default.startActiveSpan(
1294
- `${message.serviceName}.${message.procedureName}`,
1295
- {
1296
- attributes: {
1297
- component: "river",
1298
- "river.method.kind": "stream",
1299
- "river.method.service": message.serviceName,
1300
- "river.method.name": message.procedureName,
1301
- "river.streamId": message.streamId,
1302
- "span.kind": "server"
1303
- },
1304
- kind: SpanKind2.SERVER
1305
- },
1306
- activeContext,
1192
+ inputHandler = createHandlerSpan(
1193
+ procedure.type,
1194
+ message,
1307
1195
  async (span) => {
1308
1196
  try {
1309
1197
  const dispose = await procedure.handler(
@@ -1312,15 +1200,11 @@ var RiverServer = class {
1312
1200
  outgoing
1313
1201
  );
1314
1202
  if (dispose) {
1315
- disposables.push(() => {
1316
- dispose();
1317
- span.end();
1318
- });
1319
- } else {
1320
- span.end();
1203
+ disposables.push(dispose);
1321
1204
  }
1322
1205
  } catch (err) {
1323
1206
  errorHandler(err, span);
1207
+ } finally {
1324
1208
  span.end();
1325
1209
  }
1326
1210
  }
@@ -1328,102 +1212,61 @@ var RiverServer = class {
1328
1212
  }
1329
1213
  break;
1330
1214
  case "subscription":
1331
- inputHandler = (async () => {
1332
- const inputMessage = await incoming.next();
1333
- if (inputMessage.done) {
1334
- return;
1215
+ inputHandler = createHandlerSpan(
1216
+ procedure.type,
1217
+ message,
1218
+ async (span) => {
1219
+ const inputMessage = await incoming.next();
1220
+ if (inputMessage.done) {
1221
+ return;
1222
+ }
1223
+ try {
1224
+ const dispose = await procedure.handler(
1225
+ serviceContextWithTransportInfo,
1226
+ inputMessage.value,
1227
+ outgoing
1228
+ );
1229
+ if (dispose) {
1230
+ disposables.push(dispose);
1231
+ }
1232
+ } catch (err) {
1233
+ errorHandler(err, span);
1234
+ } finally {
1235
+ span.end();
1236
+ }
1335
1237
  }
1336
- await tracing_default.startActiveSpan(
1337
- `${message.serviceName}.${message.procedureName}`,
1338
- {
1339
- attributes: {
1340
- component: "river",
1341
- "river.method.kind": "subscription",
1342
- "river.method.service": message.serviceName,
1343
- "river.method.name": message.procedureName,
1344
- "river.streamId": message.streamId,
1345
- "span.kind": "server"
1346
- },
1347
- kind: SpanKind2.SERVER
1348
- },
1349
- activeContext,
1238
+ );
1239
+ break;
1240
+ case "upload":
1241
+ if (procHasInitMessage) {
1242
+ inputHandler = createHandlerSpan(
1243
+ procedure.type,
1244
+ message,
1350
1245
  async (span) => {
1246
+ const initMessage = await incoming.next();
1247
+ if (initMessage.done) {
1248
+ return;
1249
+ }
1351
1250
  try {
1352
- const dispose = await procedure.handler(
1251
+ const outputMessage = await procedure.handler(
1353
1252
  serviceContextWithTransportInfo,
1354
- inputMessage.value,
1355
- outgoing
1253
+ initMessage.value,
1254
+ incoming
1356
1255
  );
1357
- if (dispose) {
1358
- disposables.push(() => {
1359
- dispose();
1360
- span.end();
1361
- });
1362
- } else {
1363
- span.end();
1256
+ if (!this.disconnectedSessions.has(message.from)) {
1257
+ outgoing.push(outputMessage);
1364
1258
  }
1365
1259
  } catch (err) {
1366
1260
  errorHandler(err, span);
1261
+ } finally {
1367
1262
  span.end();
1368
1263
  }
1369
1264
  }
1370
1265
  );
1371
- })();
1372
- break;
1373
- case "upload":
1374
- if (procHasInitMessage) {
1375
- inputHandler = (async () => {
1376
- const initMessage = await incoming.next();
1377
- if (initMessage.done) {
1378
- return;
1379
- }
1380
- await tracing_default.startActiveSpan(
1381
- `${message.serviceName}.${message.procedureName}`,
1382
- {
1383
- attributes: {
1384
- component: "river",
1385
- "river.method.kind": "upload-with-init",
1386
- "river.method.service": message.serviceName,
1387
- "river.method.name": message.procedureName,
1388
- "river.streamId": message.streamId,
1389
- "span.kind": "server"
1390
- },
1391
- kind: SpanKind2.SERVER
1392
- },
1393
- activeContext,
1394
- async (span) => {
1395
- try {
1396
- const outputMessage = await procedure.handler(
1397
- serviceContextWithTransportInfo,
1398
- initMessage.value,
1399
- incoming
1400
- );
1401
- if (!this.disconnectedSessions.has(message.from)) {
1402
- outgoing.push(outputMessage);
1403
- }
1404
- } catch (err) {
1405
- errorHandler(err, span);
1406
- } finally {
1407
- span.end();
1408
- }
1409
- }
1410
- );
1411
- })();
1412
1266
  } else {
1413
- inputHandler = tracing_default.startActiveSpan(
1414
- `${message.serviceName}.${message.procedureName}`,
1415
- {
1416
- attributes: {
1417
- component: "river",
1418
- "river.method.kind": "upload",
1419
- "river.method.service": message.serviceName,
1420
- "river.method.name": message.procedureName,
1421
- "river.streamId": message.streamId,
1422
- "span.kind": "server"
1423
- },
1424
- kind: SpanKind2.SERVER
1425
- },
1426
- activeContext,
1267
+ inputHandler = createHandlerSpan(
1268
+ procedure.type,
1269
+ message,
1427
1270
  async (span) => {
1428
1271
  try {
1429
1272
  const outputMessage = await procedure.handler(
@@ -1489,8 +1332,8 @@ var RiverServer = class {
1489
1332
  }
1490
1333
  }
1491
1334
  getContext(service, serviceName) {
1492
- const context3 = this.contextMap.get(service);
1493
- if (!context3) {
1335
+ const context = this.contextMap.get(service);
1336
+ if (!context) {
1494
1337
  const err = `no context found for ${serviceName}`;
1495
1338
  log?.error(err, {
1496
1339
  clientId: this.transport.clientId,
@@ -1498,7 +1341,7 @@ var RiverServer = class {
1498
1341
  });
1499
1342
  throw new Error(err);
1500
1343
  }
1501
- return context3;
1344
+ return context;
1502
1345
  }
1503
1346
  cleanupStream = async (id) => {
1504
1347
  const stream2 = this.streamMap.get(id);
@@ -1512,13 +1355,15 @@ var RiverServer = class {
1512
1355
  this.streamMap.delete(id);
1513
1356
  };
1514
1357
  };
1515
- function createServer(transport, services, extendedContext) {
1516
- return new RiverServer(transport, services, extendedContext);
1358
+ function createServer(transport, services, providedServerOptions) {
1359
+ return new RiverServer(
1360
+ transport,
1361
+ services,
1362
+ providedServerOptions?.handshakeOptions,
1363
+ providedServerOptions?.extendedContext
1364
+ );
1517
1365
  }
1518
1366
 
1519
- // package.json
1520
- var version = "0.21.1";
1521
-
1522
1367
  export {
1523
1368
  serializeSchema,
1524
1369
  ServiceSchema,
@@ -1529,7 +1374,6 @@ export {
1529
1374
  Ok,
1530
1375
  Err,
1531
1376
  createClient,
1532
- createServer,
1533
- version
1377
+ createServer
1534
1378
  };
1535
- //# sourceMappingURL=chunk-NCXUFDVL.js.map
1379
+ //# sourceMappingURL=chunk-VOJVLWVX.js.map