@livekit/rtc-node 0.13.33 → 0.13.35

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 (60) hide show
  1. package/README.md +0 -5
  2. package/dist/{audio_stream-CnODFAmo.d.cts → audio_stream-BNVaONuH.d.cts} +36 -11
  3. package/dist/audio_stream.d.cts +2 -2
  4. package/dist/data_streams/index.d.cts +1 -1
  5. package/dist/data_streams/stream_reader.cjs +97 -58
  6. package/dist/data_streams/stream_reader.cjs.map +1 -1
  7. package/dist/data_streams/stream_reader.d.cts +1 -1
  8. package/dist/data_streams/stream_reader.d.ts +28 -11
  9. package/dist/data_streams/stream_reader.d.ts.map +1 -1
  10. package/dist/data_streams/stream_writer.d.cts +1 -1
  11. package/dist/data_streams/types.cjs.map +1 -1
  12. package/dist/data_streams/types.d.cts +1 -1
  13. package/dist/data_streams/types.d.ts +6 -0
  14. package/dist/data_streams/types.d.ts.map +1 -1
  15. package/dist/e2ee.cjs +5 -1
  16. package/dist/e2ee.cjs.map +1 -1
  17. package/dist/e2ee.d.cts +3 -1
  18. package/dist/e2ee.d.ts +3 -1
  19. package/dist/e2ee.d.ts.map +1 -1
  20. package/dist/index.d.cts +3 -3
  21. package/dist/participant.cjs +178 -196
  22. package/dist/participant.cjs.map +1 -1
  23. package/dist/participant.d.cts +2 -2
  24. package/dist/participant.d.ts +22 -5
  25. package/dist/participant.d.ts.map +1 -1
  26. package/dist/room.cjs +166 -126
  27. package/dist/room.cjs.map +1 -1
  28. package/dist/room.d.cts +3 -3
  29. package/dist/room.d.ts +16 -8
  30. package/dist/room.d.ts.map +1 -1
  31. package/dist/tests/e2e_common.cjs +157 -0
  32. package/dist/tests/e2e_common.cjs.map +1 -0
  33. package/dist/tests/e2e_common.d.cts +56 -0
  34. package/dist/tests/e2e_common.d.ts +37 -0
  35. package/dist/tests/e2e_common.d.ts.map +1 -0
  36. package/dist/track.d.cts +2 -2
  37. package/dist/track_publication.d.cts +2 -2
  38. package/dist/{types-_PdPVish.d.cts → types-f7wTlFjs.d.cts} +34 -11
  39. package/dist/utils.cjs +27 -2
  40. package/dist/utils.cjs.map +1 -1
  41. package/dist/utils.d.cts +8 -1
  42. package/dist/utils.d.ts +6 -0
  43. package/dist/utils.d.ts.map +1 -1
  44. package/dist/version.cjs +1 -1
  45. package/dist/version.cjs.map +1 -1
  46. package/dist/version.d.cts +1 -1
  47. package/dist/version.d.ts +1 -1
  48. package/dist/video_stream.d.cts +2 -2
  49. package/package.json +2 -2
  50. package/src/audio_stream_room_lifecycle.test.ts +4 -1
  51. package/src/data_streams/stream_reader.ts +132 -82
  52. package/src/data_streams/types.ts +6 -0
  53. package/src/e2ee.ts +7 -0
  54. package/src/participant.ts +251 -228
  55. package/src/room.ts +233 -144
  56. package/src/tests/e2e.test.ts +50 -139
  57. package/src/tests/e2e_common.ts +163 -0
  58. package/src/tests/e2e_data_streams.test.ts +639 -0
  59. package/src/utils.ts +30 -0
  60. package/src/version.ts +1 -1
package/dist/room.cjs CHANGED
@@ -30,7 +30,6 @@ var room_exports = {};
30
30
  __export(room_exports, {
31
31
  ConnectError: () => ConnectError,
32
32
  Room: () => Room,
33
- RoomDataStreamOptions: () => import_rtc_ffi_bindings3.RoomDataStreamOptions,
34
33
  RoomEvent: () => RoomEvent,
35
34
  defaultRoomOptions: () => defaultRoomOptions,
36
35
  defaultRtcConfiguration: () => defaultRtcConfiguration
@@ -41,8 +40,10 @@ var import_rtc_ffi_bindings = require("@livekit/rtc-ffi-bindings");
41
40
  var import_rtc_ffi_bindings2 = require("@livekit/rtc-ffi-bindings");
42
41
  var import_rtc_ffi_bindings3 = require("@livekit/rtc-ffi-bindings");
43
42
  var import_rtc_ffi_bindings4 = require("@livekit/rtc-ffi-bindings");
43
+ var import_rtc_ffi_bindings5 = require("@livekit/rtc-ffi-bindings");
44
44
  var import_events = __toESM(require("events"), 1);
45
45
  var import_stream_reader = require("./data_streams/stream_reader.cjs");
46
+ var import_types = require("./data_streams/types.cjs");
46
47
  var import_e2ee = require("./e2ee.cjs");
47
48
  var import_ffi_client = require("./ffi_client.cjs");
48
49
  var import_log = require("./log.cjs");
@@ -51,11 +52,11 @@ var import_track = require("./track.cjs");
51
52
  var import_track_publication = require("./track_publication.cjs");
52
53
  var import_utils = require("./utils.cjs");
53
54
  const defaultRtcConfiguration = {
54
- iceTransportType: import_rtc_ffi_bindings3.IceTransportType.TRANSPORT_ALL,
55
- continualGatheringPolicy: import_rtc_ffi_bindings3.ContinualGatheringPolicy.GATHER_CONTINUALLY,
55
+ iceTransportType: import_rtc_ffi_bindings4.IceTransportType.TRANSPORT_ALL,
56
+ continualGatheringPolicy: import_rtc_ffi_bindings4.ContinualGatheringPolicy.GATHER_CONTINUALLY,
56
57
  iceServers: []
57
58
  };
58
- const defaultRoomOptions = new import_rtc_ffi_bindings3.RoomOptions({
59
+ const defaultRoomOptions = new import_rtc_ffi_bindings4.RoomOptions({
59
60
  autoSubscribe: true,
60
61
  dynacast: false,
61
62
  e2ee: void 0,
@@ -73,8 +74,9 @@ class Room extends import_events.default {
73
74
  * before processing the next events
74
75
  */
75
76
  this.ffiEventLock = new import_mutex.Mutex();
76
- this.byteStreamControllers = /* @__PURE__ */ new Map();
77
- this.textStreamControllers = /* @__PURE__ */ new Map();
77
+ // Active incoming stream readers keyed by their FFI reader handle id. Each entry
78
+ // owns the FfiClient listener feeding reader events into the ReadableStream.
79
+ this.streamReaders = /* @__PURE__ */ new Map();
78
80
  this.byteStreamHandlers = /* @__PURE__ */ new Map();
79
81
  this.textStreamHandlers = /* @__PURE__ */ new Map();
80
82
  this.preConnectEvents = [];
@@ -85,7 +87,7 @@ class Room extends import_events.default {
85
87
  // events fire exactly once, no matter which path (explicit disconnect()
86
88
  // vs. FFI 'disconnected' event) wins the race.
87
89
  this.hasCleanedUp = false;
88
- this._connectionState = import_rtc_ffi_bindings3.ConnectionState.CONN_DISCONNECTED;
90
+ this._connectionState = import_rtc_ffi_bindings4.ConnectionState.CONN_DISCONNECTED;
89
91
  this.remoteParticipants = /* @__PURE__ */ new Map();
90
92
  this.onFfiEvent = async (ffiEvent) => {
91
93
  const unlock = await this.ffiEventLock.lock();
@@ -212,9 +214,9 @@ class Room extends import_events.default {
212
214
  trackInfo.sid
213
215
  );
214
216
  publication.subscribed = true;
215
- if (trackInfo.kind == import_rtc_ffi_bindings4.TrackKind.KIND_VIDEO) {
217
+ if (trackInfo.kind == import_rtc_ffi_bindings5.TrackKind.KIND_VIDEO) {
216
218
  publication.track = new import_track.RemoteVideoTrack(ownedTrack);
217
- } else if (trackInfo.kind == import_rtc_ffi_bindings4.TrackKind.KIND_AUDIO) {
219
+ } else if (trackInfo.kind == import_rtc_ffi_bindings5.TrackKind.KIND_AUDIO) {
218
220
  publication.track = new import_track.RemoteAudioTrack(ownedTrack);
219
221
  }
220
222
  (_b = publication.track) == null ? void 0 : _b.setRoom(this);
@@ -385,12 +387,10 @@ class Room extends import_events.default {
385
387
  this.emit("reconnected" /* Reconnected */);
386
388
  } else if (ev.case == "roomSidChanged") {
387
389
  this.emit("roomSidChanged" /* RoomSidChanged */, ev.value.sid);
388
- } else if (ev.case === "streamHeaderReceived" && ev.value.header) {
389
- this.handleStreamHeader(ev.value.header, ev.value.participantIdentity);
390
- } else if (ev.case === "streamChunkReceived" && ev.value.chunk) {
391
- this.handleStreamChunk(ev.value.chunk);
392
- } else if (ev.case === "streamTrailerReceived" && ev.value.trailer) {
393
- this.handleStreamTrailer(ev.value.trailer);
390
+ } else if (ev.case === "byteStreamOpened" && ev.value.reader) {
391
+ this.handleByteStreamOpened(ev.value.reader, ev.value.participantIdentity);
392
+ } else if (ev.case === "textStreamOpened" && ev.value.reader) {
393
+ this.handleTextStreamOpened(ev.value.reader, ev.value.participantIdentity);
394
394
  } else if (ev.case === "roomUpdated") {
395
395
  this.info = ev.value;
396
396
  this.emit("roomUpdated" /* RoomUpdated */);
@@ -433,7 +433,7 @@ class Room extends import_events.default {
433
433
  return (_a = this.info) == null ? void 0 : _a.metadata;
434
434
  }
435
435
  get isConnected() {
436
- return this.ffiHandle != void 0 && this.connectionState != import_rtc_ffi_bindings3.ConnectionState.CONN_DISCONNECTED;
436
+ return this.ffiHandle != void 0 && this.connectionState != import_rtc_ffi_bindings4.ConnectionState.CONN_DISCONNECTED;
437
437
  }
438
438
  /** @internal */
439
439
  get token() {
@@ -548,17 +548,33 @@ class Room extends import_events.default {
548
548
  * @throws ConnectError - if connection fails
549
549
  */
550
550
  async connect(url, token, opts) {
551
- const options = { ...defaultRoomOptions, ...opts };
552
- options.dataStream = new import_rtc_ffi_bindings3.RoomDataStreamOptions({
553
- ...options.dataStream,
554
- useLegacyClientImplementation: true
555
- });
551
+ const { dataStream, ...restOpts } = opts ?? {};
552
+ const options = { ...defaultRoomOptions, ...restOpts };
556
553
  const e2eeEnabled = options.encryption || options.e2ee;
557
- const e2eeOptions = options.encryption ? { ...import_e2ee.defaultE2EEOptions, ...options.encryption } : { ...import_e2ee.defaultE2EEOptions, ...options.e2ee };
558
- const req = new import_rtc_ffi_bindings3.ConnectRequest({
554
+ const userE2EEOptions = options.encryption ?? options.e2ee;
555
+ const e2eeOptions = {
556
+ ...import_e2ee.defaultE2EEOptions,
557
+ ...userE2EEOptions,
558
+ keyProviderOptions: {
559
+ ...import_e2ee.defaultE2EEOptions.keyProviderOptions,
560
+ ...userE2EEOptions == null ? void 0 : userE2EEOptions.keyProviderOptions
561
+ }
562
+ };
563
+ const mergedOptions = { ...options };
564
+ if (options.encryption) {
565
+ mergedOptions.encryption = e2eeOptions;
566
+ } else if (options.e2ee) {
567
+ mergedOptions.e2ee = e2eeOptions;
568
+ }
569
+ if (dataStream) {
570
+ mergedOptions.dataStream = new import_rtc_ffi_bindings4.RoomDataStreamOptions({
571
+ maxPayloadByteLength: (0, import_utils.numberToBigInt)(dataStream.maxPayloadByteLength)
572
+ });
573
+ }
574
+ const req = new import_rtc_ffi_bindings4.ConnectRequest({
559
575
  url,
560
576
  token,
561
- options
577
+ options: mergedOptions
562
578
  });
563
579
  import_ffi_client.FfiClient.instance.on(import_ffi_client.FfiClientEvent.FfiEvent, this.onFfiEvent);
564
580
  try {
@@ -593,7 +609,7 @@ class Room extends import_events.default {
593
609
  rp.trackPublications.set(publication.sid, publication);
594
610
  }
595
611
  }
596
- this.updateConnectionState(import_rtc_ffi_bindings3.ConnectionState.CONN_CONNECTED);
612
+ this.updateConnectionState(import_rtc_ffi_bindings4.ConnectionState.CONN_CONNECTED);
597
613
  import_ffi_client.FfiClient.instance.request({
598
614
  message: {
599
615
  case: "readyForRoomEvent",
@@ -679,21 +695,16 @@ class Room extends import_events.default {
679
695
  var _a, _b;
680
696
  if (this.hasCleanedUp) return;
681
697
  this.hasCleanedUp = true;
682
- for (const [, streamController] of this.byteStreamControllers) {
698
+ for (const [, { controller, listener }] of this.streamReaders) {
699
+ import_ffi_client.FfiClient.instance.off(import_ffi_client.FfiClientEvent.FfiEvent, listener);
683
700
  try {
684
- streamController.controller.error(new Error("Disconnected while receiving"));
701
+ controller.error(new Error("Disconnected while receiving"));
685
702
  } catch {
686
703
  }
687
704
  }
688
- this.byteStreamControllers.clear();
689
- for (const [, streamController] of this.textStreamControllers) {
690
- try {
691
- streamController.controller.error(new Error("Disconnected while receiving"));
692
- } catch {
693
- }
694
- }
695
- this.textStreamControllers.clear();
705
+ this.streamReaders.clear();
696
706
  if (this.localParticipant) {
707
+ this.localParticipant.disposeOpenStreamWriters();
697
708
  for (const pub of this.localParticipant.trackPublications.values()) {
698
709
  (_a = pub.track) == null ? void 0 : _a.setRoom(null);
699
710
  }
@@ -705,7 +716,7 @@ class Room extends import_events.default {
705
716
  }
706
717
  this.sidPromise = void 0;
707
718
  this.disconnectController.abort();
708
- this.updateConnectionState(import_rtc_ffi_bindings3.ConnectionState.CONN_DISCONNECTED);
719
+ this.updateConnectionState(import_rtc_ffi_bindings4.ConnectionState.CONN_DISCONNECTED);
709
720
  this.emit("disconnected" /* Disconnected */, reason);
710
721
  }
711
722
  /**
@@ -789,100 +800,130 @@ class Room extends import_events.default {
789
800
  this.remoteParticipants.set(ownedInfo.info.identity, participant);
790
801
  return participant;
791
802
  }
792
- handleStreamHeader(streamHeader, participantIdentity) {
793
- if (streamHeader.contentHeader.case === "byteHeader") {
794
- const streamHandlerCallback = this.byteStreamHandlers.get(streamHeader.topic ?? "");
795
- if (!streamHandlerCallback) {
796
- import_log.log.debug(
797
- "ignoring incoming byte stream due to no handler for topic: %s",
798
- streamHeader.topic ?? "undefined"
799
- );
800
- return;
801
- }
802
- let streamController;
803
- const stream = new ReadableStream({
804
- start: (controller) => {
805
- streamController = controller;
806
- this.byteStreamControllers.set(streamHeader.streamId, {
807
- header: streamHeader,
808
- controller: streamController,
809
- startTime: Date.now()
810
- });
811
- }
812
- });
813
- const info = {
814
- streamId: streamHeader.streamId,
815
- name: streamHeader.contentHeader.value.name ?? "unknown",
816
- mimeType: streamHeader.mimeType,
817
- totalSize: streamHeader.totalLength ? Number(streamHeader.totalLength) : void 0,
818
- topic: streamHeader.topic,
819
- timestamp: (0, import_utils.bigIntToNumber)(streamHeader.timestamp),
820
- attributes: streamHeader.attributes
821
- };
822
- streamHandlerCallback(
823
- new import_stream_reader.ByteStreamReader(info, stream, (0, import_utils.bigIntToNumber)(streamHeader.totalLength)),
824
- { identity: participantIdentity }
825
- );
826
- } else if (streamHeader.contentHeader.case === "textHeader") {
827
- const streamHandlerCallback = this.textStreamHandlers.get(streamHeader.topic ?? "");
828
- if (!streamHandlerCallback) {
829
- import_log.log.debug(
830
- "ignoring incoming text stream due to no handler for topic: %s",
831
- streamHeader.topic ?? "undefined"
832
- );
803
+ handleByteStreamOpened(ownedReader, participantIdentity) {
804
+ const info = (0, import_utils.byteStreamInfoFromProto)(ownedReader.info);
805
+ const readerHandle = ownedReader.handle.id;
806
+ const streamHandlerCallback = this.byteStreamHandlers.get(info.topic);
807
+ if (!streamHandlerCallback) {
808
+ import_log.log.debug("ignoring incoming byte stream due to no handler for topic: %s", info.topic);
809
+ new import_ffi_client.FfiHandle(readerHandle).dispose();
810
+ return;
811
+ }
812
+ let listener = null;
813
+ const unsubscribe = () => {
814
+ if (!listener) {
833
815
  return;
834
816
  }
835
- let streamController;
836
- const stream = new ReadableStream({
837
- start: (controller) => {
838
- streamController = controller;
839
- this.textStreamControllers.set(streamHeader.streamId, {
840
- header: streamHeader,
841
- controller: streamController,
842
- startTime: Date.now()
843
- });
844
- }
845
- });
846
- const info = {
847
- streamId: streamHeader.streamId,
848
- mimeType: streamHeader.mimeType,
849
- totalSize: streamHeader.totalLength ? Number(streamHeader.totalLength) : void 0,
850
- topic: streamHeader.topic,
851
- timestamp: Number(streamHeader.timestamp),
852
- attributes: streamHeader.attributes
853
- };
854
- streamHandlerCallback(
855
- new import_stream_reader.TextStreamReader(info, stream, (0, import_utils.bigIntToNumber)(streamHeader.totalLength)),
856
- { identity: participantIdentity }
857
- );
858
- }
817
+ import_ffi_client.FfiClient.instance.off(import_ffi_client.FfiClientEvent.FfiEvent, listener);
818
+ listener = null;
819
+ this.streamReaders.delete(readerHandle);
820
+ };
821
+ const stream = new ReadableStream({
822
+ start: (controller) => {
823
+ listener = (ev) => {
824
+ if (ev.message.case !== "byteStreamReaderEvent" || ev.message.value.readerHandle !== readerHandle) {
825
+ return;
826
+ }
827
+ const detail = ev.message.value.detail;
828
+ if (detail.case === "chunkReceived") {
829
+ const content = detail.value.content;
830
+ if (content.length > 0) {
831
+ controller.enqueue(new import_rtc_ffi_bindings4.DataStream_Chunk({ content }));
832
+ }
833
+ } else if (detail.case === "eos") {
834
+ unsubscribe();
835
+ const error = detail.value.error;
836
+ if (error) {
837
+ controller.error(new Error(error.description ?? "stream terminated"));
838
+ } else {
839
+ controller.close();
840
+ }
841
+ }
842
+ };
843
+ import_ffi_client.FfiClient.instance.on(import_ffi_client.FfiClientEvent.FfiEvent, listener);
844
+ this.streamReaders.set(readerHandle, { controller, listener });
845
+ import_ffi_client.FfiClient.instance.request({
846
+ message: {
847
+ case: "byteReadIncremental",
848
+ value: new import_rtc_ffi_bindings4.ByteStreamReaderReadIncrementalRequest({ readerHandle })
849
+ }
850
+ });
851
+ },
852
+ // The consumer stopped reading before end-of-stream — ByteStreamReader
853
+ // .close(), or breaking out of a for-await. The eos event that would have
854
+ // unsubscribed is never consumed, so the listener would otherwise be run
855
+ // against every FFI event for the rest of the process. Only the
856
+ // subscription is released: the reader handle was consumed by the
857
+ // readIncremental request above, so there is nothing left to dispose.
858
+ cancel: () => unsubscribe()
859
+ });
860
+ streamHandlerCallback(
861
+ new import_stream_reader.ByteStreamReader(info, stream, (0, import_utils.bigIntToNumber)(ownedReader.info.totalLength)),
862
+ { identity: participantIdentity }
863
+ );
859
864
  }
860
- handleStreamChunk(chunk) {
861
- const fileBuffer = this.byteStreamControllers.get(chunk.streamId);
862
- if (fileBuffer) {
863
- if (chunk.content.length > 0) {
864
- fileBuffer.controller.enqueue(chunk);
865
- }
865
+ handleTextStreamOpened(ownedReader, participantIdentity) {
866
+ const info = (0, import_utils.textStreamInfoFromProto)(ownedReader.info);
867
+ const readerHandle = ownedReader.handle.id;
868
+ const streamHandlerCallback = this.textStreamHandlers.get(info.topic);
869
+ if (!streamHandlerCallback) {
870
+ import_log.log.debug("ignoring incoming text stream due to no handler for topic: %s", info.topic);
871
+ new import_ffi_client.FfiHandle(readerHandle).dispose();
872
+ return;
866
873
  }
867
- const textBuffer = this.textStreamControllers.get(chunk.streamId);
868
- if (textBuffer) {
869
- if (chunk.content.length > 0) {
870
- textBuffer.controller.enqueue(chunk);
874
+ const textEncoder = new TextEncoder();
875
+ let listener = null;
876
+ const unsubscribe = () => {
877
+ if (!listener) {
878
+ return;
871
879
  }
872
- }
873
- }
874
- handleStreamTrailer(trailer) {
875
- const streamId = trailer.streamId;
876
- const fileBuffer = this.byteStreamControllers.get(streamId);
877
- if (fileBuffer) {
878
- fileBuffer.controller.close();
879
- this.byteStreamControllers.delete(streamId);
880
- }
881
- const textBuffer = this.textStreamControllers.get(streamId);
882
- if (textBuffer) {
883
- textBuffer.controller.close();
884
- this.textStreamControllers.delete(streamId);
885
- }
880
+ import_ffi_client.FfiClient.instance.off(import_ffi_client.FfiClientEvent.FfiEvent, listener);
881
+ listener = null;
882
+ this.streamReaders.delete(readerHandle);
883
+ };
884
+ const stream = new ReadableStream({
885
+ start: (controller) => {
886
+ listener = (ev) => {
887
+ if (ev.message.case !== "textStreamReaderEvent" || ev.message.value.readerHandle !== readerHandle) {
888
+ return;
889
+ }
890
+ const detail = ev.message.value.detail;
891
+ if (detail.case === "chunkReceived") {
892
+ const content = textEncoder.encode(detail.value.content);
893
+ if (content.length > 0) {
894
+ controller.enqueue(new import_rtc_ffi_bindings4.DataStream_Chunk({ content }));
895
+ }
896
+ } else if (detail.case === "eos") {
897
+ unsubscribe();
898
+ const error = detail.value.error;
899
+ if (error) {
900
+ controller.error(new Error(error.description ?? "stream terminated"));
901
+ } else {
902
+ controller.close();
903
+ }
904
+ }
905
+ };
906
+ import_ffi_client.FfiClient.instance.on(import_ffi_client.FfiClientEvent.FfiEvent, listener);
907
+ this.streamReaders.set(readerHandle, { controller, listener });
908
+ import_ffi_client.FfiClient.instance.request({
909
+ message: {
910
+ case: "textReadIncremental",
911
+ value: new import_rtc_ffi_bindings4.TextStreamReaderReadIncrementalRequest({ readerHandle })
912
+ }
913
+ });
914
+ },
915
+ // The consumer stopped reading before end-of-stream — TextStreamReader
916
+ // .close(), or breaking out of a for-await. The eos event that would have
917
+ // unsubscribed is never consumed, so the listener would otherwise be run
918
+ // against every FFI event for the rest of the process. Only the
919
+ // subscription is released: the reader handle was consumed by the
920
+ // readIncremental request above, so there is nothing left to dispose.
921
+ cancel: () => unsubscribe()
922
+ });
923
+ streamHandlerCallback(
924
+ new import_stream_reader.TextStreamReader(info, stream, (0, import_utils.bigIntToNumber)(ownedReader.info.totalLength)),
925
+ { identity: participantIdentity }
926
+ );
886
927
  }
887
928
  }
888
929
  class ConnectError extends Error {
@@ -930,7 +971,6 @@ var RoomEvent = /* @__PURE__ */ ((RoomEvent2) => {
930
971
  0 && (module.exports = {
931
972
  ConnectError,
932
973
  Room,
933
- RoomDataStreamOptions,
934
974
  RoomEvent,
935
975
  defaultRoomOptions,
936
976
  defaultRtcConfiguration