@defcomm/meetingsdk 0.1.5 → 0.1.6

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/dist/index.mjs CHANGED
@@ -392,7 +392,7 @@ var SFUClient = class {
392
392
  this.subscriberStatsTimer = null;
393
393
  this.apiBase = options.apiBase || "https://api.example.com/api";
394
394
  this.wsBase = options.wsBase || "wss://api.example.com/ws";
395
- this.userId = options.userId || this.createId();
395
+ this.participantId = options.participantId || this.createId();
396
396
  this.onStateChange = options.onStateChange || (() => {
397
397
  });
398
398
  this.onParticipantJoined = options.onParticipantJoined || (() => {
@@ -513,12 +513,17 @@ var SFUClient = class {
513
513
  });
514
514
  }
515
515
  async getRoom(roomCode) {
516
- return this.request(`${this.apiBase}/rooms/${encodeURIComponent(roomCode)}`);
516
+ return this.request(
517
+ `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}`
518
+ );
517
519
  }
518
520
  async deleteRoom(roomCode) {
519
- return this.request(`${this.apiBase}/rooms/${encodeURIComponent(roomCode)}`, {
520
- method: "DELETE"
521
- });
521
+ return this.request(
522
+ `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}`,
523
+ {
524
+ method: "DELETE"
525
+ }
526
+ );
522
527
  }
523
528
  async getToken(roomCode, options = {}) {
524
529
  const nextRoom = roomCode.trim();
@@ -530,7 +535,7 @@ var SFUClient = class {
530
535
  displayName: options.displayName,
531
536
  avatarUrl: options.avatarUrl
532
537
  };
533
- if (options.userId) this.userId = options.userId;
538
+ if (options.participantId) this.participantId = options.participantId;
534
539
  if (!this.resumeToken) {
535
540
  this.resumeToken = this.loadResumeToken(this.room);
536
541
  }
@@ -538,7 +543,7 @@ var SFUClient = class {
538
543
  method: "POST",
539
544
  body: JSON.stringify({
540
545
  room_code: this.room,
541
- user_id: this.userId,
546
+ user_id: this.participantId,
542
547
  display_name: options.displayName,
543
548
  avatar_url: options.avatarUrl
544
549
  })
@@ -553,7 +558,7 @@ var SFUClient = class {
553
558
  method: "POST",
554
559
  body: JSON.stringify({
555
560
  room_code: this.room,
556
- user_id: this.userId,
561
+ user_id: this.participantId,
557
562
  display_name: this.joinOptions.displayName,
558
563
  avatar_url: this.joinOptions.avatarUrl
559
564
  })
@@ -756,7 +761,8 @@ var SFUClient = class {
756
761
  case "participant_joined": {
757
762
  const participant = payload.participant || payload;
758
763
  const participantId = participant?.participant_id || payload.participant_id;
759
- if (!participantId || participantId === this.currentParticipantId) break;
764
+ if (!participantId || participantId === this.currentParticipantId)
765
+ break;
760
766
  if (participant) this.participants.set(participantId, participant);
761
767
  this.onParticipantJoined(participant);
762
768
  break;
@@ -786,14 +792,21 @@ var SFUClient = class {
786
792
  if (track.source === "audio") {
787
793
  this.localTrackIds.set("audio", track.track_id);
788
794
  const muted = !(this.localStream?.getAudioTracks()[0]?.enabled ?? true);
789
- this.send({ type: "track_state", payload: { track_id: track.track_id, muted } });
795
+ this.send({
796
+ type: "track_state",
797
+ payload: { track_id: track.track_id, muted }
798
+ });
790
799
  }
791
800
  if (track.source === "camera") {
792
801
  this.localTrackIds.set("camera", track.track_id);
793
802
  const muted = !(this.localStream?.getVideoTracks()[0]?.enabled ?? true);
794
- this.send({ type: "track_state", payload: { track_id: track.track_id, muted } });
803
+ this.send({
804
+ type: "track_state",
805
+ payload: { track_id: track.track_id, muted }
806
+ });
795
807
  }
796
- if (track.source === "screen") this.localTrackIds.set("screen", track.track_id);
808
+ if (track.source === "screen")
809
+ this.localTrackIds.set("screen", track.track_id);
797
810
  break;
798
811
  }
799
812
  this.onTrackPublished(track);
@@ -1024,10 +1037,7 @@ var SFUClient = class {
1024
1037
  }
1025
1038
  if (screenStream?.getTracks().length === 0) {
1026
1039
  this.remoteScreenStreams.delete(participantId);
1027
- this.onScreenShareStopped(
1028
- participantId,
1029
- metadata.track_id
1030
- );
1040
+ this.onScreenShareStopped(participantId, metadata.track_id);
1031
1041
  }
1032
1042
  };
1033
1043
  this.onScreenShareStarted(participantId, metadata);
@@ -1114,7 +1124,9 @@ var SFUClient = class {
1114
1124
  try {
1115
1125
  await pc.addIceCandidate(candidate);
1116
1126
  } catch (error) {
1117
- this.onError(new Error(`Failed to add ${peer} ICE candidate: ${String(error)}`));
1127
+ this.onError(
1128
+ new Error(`Failed to add ${peer} ICE candidate: ${String(error)}`)
1129
+ );
1118
1130
  }
1119
1131
  }
1120
1132
  async flushPendingIce(peer) {
@@ -1126,7 +1138,11 @@ var SFUClient = class {
1126
1138
  try {
1127
1139
  await pc.addIceCandidate(candidate);
1128
1140
  } catch (error) {
1129
- this.onError(new Error(`Failed to add queued ${peer} ICE candidate: ${String(error)}`));
1141
+ this.onError(
1142
+ new Error(
1143
+ `Failed to add queued ${peer} ICE candidate: ${String(error)}`
1144
+ )
1145
+ );
1130
1146
  }
1131
1147
  }
1132
1148
  }
@@ -1156,7 +1172,9 @@ var SFUClient = class {
1156
1172
  } catch (error) {
1157
1173
  const waiters = this.subscriptionWaiters.splice(0);
1158
1174
  waiters.forEach((w) => w.reject(error));
1159
- this.onError(new Error(`Failed to process subscriber offer: ${String(error)}`));
1175
+ this.onError(
1176
+ new Error(`Failed to process subscriber offer: ${String(error)}`)
1177
+ );
1160
1178
  } finally {
1161
1179
  this.subscriberNegotiating = false;
1162
1180
  }
@@ -1204,9 +1222,13 @@ var SFUClient = class {
1204
1222
  }
1205
1223
  }
1206
1224
  async publish({ audio = true, video = true } = {}) {
1207
- if (!this.publisher) throw new Error("Publisher PeerConnection is not initialized");
1225
+ if (!this.publisher)
1226
+ throw new Error("Publisher PeerConnection is not initialized");
1208
1227
  if (!this.localStream) {
1209
- this.localStream = await navigator.mediaDevices.getUserMedia({ audio, video });
1228
+ this.localStream = await navigator.mediaDevices.getUserMedia({
1229
+ audio,
1230
+ video
1231
+ });
1210
1232
  }
1211
1233
  await this.publishExistingTracks(audio, video);
1212
1234
  return this.localStream;
@@ -1219,9 +1241,13 @@ var SFUClient = class {
1219
1241
  const audioTrack = this.localStream.getAudioTracks().find((track) => track.readyState === "live");
1220
1242
  const cameraTrack = this.localStream.getVideoTracks().find((track) => track.readyState === "live");
1221
1243
  const screenTrack = this.screenStream?.getVideoTracks().find((track) => track.readyState === "live");
1222
- await this.audioSender?.replaceTrack(audio && audioTrack ? audioTrack : null);
1244
+ await this.audioSender?.replaceTrack(
1245
+ audio && audioTrack ? audioTrack : null
1246
+ );
1223
1247
  this.audioTransceiver.direction = audio && audioTrack ? "sendonly" : "inactive";
1224
- await this.videoSender?.replaceTrack(video && cameraTrack ? cameraTrack : null);
1248
+ await this.videoSender?.replaceTrack(
1249
+ video && cameraTrack ? cameraTrack : null
1250
+ );
1225
1251
  this.cameraTransceiver.direction = video && cameraTrack ? "sendonly" : "inactive";
1226
1252
  await this.screenSender?.replaceTrack(screenTrack || null);
1227
1253
  this.screenTransceiver.direction = screenTrack ? "sendonly" : "inactive";
@@ -1394,7 +1420,10 @@ var SFUClient = class {
1394
1420
  }
1395
1421
  async rejectJoinRequest(requestId, reason) {
1396
1422
  if (!requestId) throw new Error("requestId is required");
1397
- if (!this.send({ type: "reject_join", payload: { request_id: requestId, reason } })) {
1423
+ if (!this.send({
1424
+ type: "reject_join",
1425
+ payload: { request_id: requestId, reason }
1426
+ })) {
1398
1427
  throw new Error("SFU signaling is not connected");
1399
1428
  }
1400
1429
  }
@@ -1463,10 +1492,14 @@ var SFUClient = class {
1463
1492
  }
1464
1493
  setTimeout(check, 25);
1465
1494
  };
1466
- ws.addEventListener("close", () => {
1467
- clearTimeout(timeout);
1468
- finish();
1469
- }, { once: true });
1495
+ ws.addEventListener(
1496
+ "close",
1497
+ () => {
1498
+ clearTimeout(timeout);
1499
+ finish();
1500
+ },
1501
+ { once: true }
1502
+ );
1470
1503
  this.send({ type: "leave" });
1471
1504
  check();
1472
1505
  });
@@ -1545,7 +1578,8 @@ var SFUClient = class {
1545
1578
  }
1546
1579
  }
1547
1580
  async logSubscriberVideoStats() {
1548
- if (!this.subscriber || this.subscriber.connectionState === "closed") return;
1581
+ if (!this.subscriber || this.subscriber.connectionState === "closed")
1582
+ return;
1549
1583
  try {
1550
1584
  const stats = await this.subscriber.getStats();
1551
1585
  stats.forEach((report) => {
@@ -1566,7 +1600,7 @@ var SFUClient = class {
1566
1600
 
1567
1601
  // src/core/VideoCore.ts
1568
1602
  var VideoSDKCore = class {
1569
- constructor(events = {}, apiBase = SDK_CONFIG.apiBase, wsBase = SDK_CONFIG.wsBase) {
1603
+ constructor(options, events = {}, apiBase = SDK_CONFIG.apiBase, wsBase = SDK_CONFIG.wsBase) {
1570
1604
  this.events = events;
1571
1605
  this.apiBase = apiBase;
1572
1606
  this.wsBase = wsBase;
@@ -1592,18 +1626,7 @@ var VideoSDKCore = class {
1592
1626
  this.events.onActiveSpeakersChanged?.(participantIds);
1593
1627
  }
1594
1628
  });
1595
- let storedId = null;
1596
- try {
1597
- storedId = typeof localStorage !== "undefined" ? localStorage.getItem("defcomm:participant_id") : null;
1598
- } catch {
1599
- }
1600
- this.myId = storedId || (typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `user_${Date.now()}`);
1601
- try {
1602
- if (typeof localStorage !== "undefined") {
1603
- localStorage.setItem("defcomm:participant_id", this.myId);
1604
- }
1605
- } catch {
1606
- }
1629
+ this.myId = options.participantId;
1607
1630
  }
1608
1631
  emitError(code, message, raw, recoverable = true) {
1609
1632
  const err = {
@@ -1611,7 +1634,7 @@ var VideoSDKCore = class {
1611
1634
  message,
1612
1635
  raw,
1613
1636
  roomId: this.room.id,
1614
- userId: this.myId,
1637
+ participantId: this.myId,
1615
1638
  recoverable
1616
1639
  };
1617
1640
  this.events.onError?.(err);
@@ -1671,7 +1694,7 @@ var VideoSDKCore = class {
1671
1694
  const client = this.sfuClient ?? new SFUClient({
1672
1695
  apiBase: this.apiBase,
1673
1696
  wsBase: this.wsBase,
1674
- userId: this.myId
1697
+ participantId: this.myId
1675
1698
  });
1676
1699
  return client.createRoom(input);
1677
1700
  }
@@ -1679,7 +1702,7 @@ var VideoSDKCore = class {
1679
1702
  const client = this.sfuClient ?? new SFUClient({
1680
1703
  apiBase: this.apiBase,
1681
1704
  wsBase: this.wsBase,
1682
- userId: this.myId
1705
+ participantId: this.myId
1683
1706
  });
1684
1707
  return client.getRoom(roomCode);
1685
1708
  }
@@ -1687,29 +1710,23 @@ var VideoSDKCore = class {
1687
1710
  const client = this.sfuClient ?? new SFUClient({
1688
1711
  apiBase: this.apiBase,
1689
1712
  wsBase: this.wsBase,
1690
- userId: this.myId
1713
+ participantId: this.myId
1691
1714
  });
1692
1715
  return client.deleteRoom(roomCode);
1693
1716
  }
1694
1717
  // JOIN
1695
1718
  async joinMeeting(config) {
1696
- const {
1697
- roomId,
1698
- name,
1699
- audioMuted = false,
1700
- videoMuted = false,
1701
- userId
1702
- } = config;
1719
+ const { roomId, name, audioMuted = false, videoMuted = false } = config;
1703
1720
  if (!roomId || !name) {
1704
1721
  throw new Error("roomId and name are required to join meeting");
1705
1722
  }
1706
- if (userId) {
1707
- this.myId = userId;
1723
+ if (!this.myId) {
1724
+ throw new Error("participantId is required");
1708
1725
  }
1709
1726
  if (this.sfuClient && this.room.id === roomId && this.sfuClient.getConnectionState() === "connected") {
1710
1727
  console.info("[SDK] Already connected; duplicate join ignored", {
1711
1728
  roomId,
1712
- userId: this.myId
1729
+ participantId: this.myId
1713
1730
  });
1714
1731
  return;
1715
1732
  }
@@ -1718,7 +1735,7 @@ var VideoSDKCore = class {
1718
1735
  "[SDK] Join already in progress; waiting for existing join",
1719
1736
  {
1720
1737
  roomId,
1721
- userId: this.myId
1738
+ participantId: this.myId
1722
1739
  }
1723
1740
  );
1724
1741
  return this.joinPromise;
@@ -1780,7 +1797,7 @@ var VideoSDKCore = class {
1780
1797
  const client = new SFUClient({
1781
1798
  apiBase: this.apiBase,
1782
1799
  wsBase: this.wsBase,
1783
- userId: this.myId,
1800
+ participantId: this.myId,
1784
1801
  autoSubscribe: true,
1785
1802
  // CONNECTION STATE
1786
1803
  onStateChange: (state) => {
@@ -1804,7 +1821,7 @@ var VideoSDKCore = class {
1804
1821
  console.log("[SFU] Join request pending", info);
1805
1822
  this.events.onEntryRequested?.({
1806
1823
  requestId: info.request_id,
1807
- userId: this.myId,
1824
+ participantId: this.myId,
1808
1825
  name: this.participantName
1809
1826
  });
1810
1827
  },
@@ -1841,14 +1858,14 @@ var VideoSDKCore = class {
1841
1858
  },
1842
1859
  onJoinRequested: (request) => {
1843
1860
  const requestId = request?.request_id || request?.requestId;
1844
- const userId = request?.user_id || request?.userId;
1861
+ const participantId = request?.user_id || request?.participantId;
1845
1862
  const nameValue = request?.user_metadata?.name || request?.display_name || request?.name || "Participant";
1846
- if (!requestId || !userId) {
1863
+ if (!requestId || !participantId) {
1847
1864
  return;
1848
1865
  }
1849
1866
  this.events.onEntryRequested?.({
1850
1867
  requestId,
1851
- userId,
1868
+ participantId,
1852
1869
  name: nameValue
1853
1870
  });
1854
1871
  },
@@ -2022,6 +2039,10 @@ var VideoSDKCore = class {
2022
2039
  // ERROR
2023
2040
  onError: (error) => {
2024
2041
  console.error("[SFU] Error:", error);
2042
+ if (error?.code === "request_failed" || error?.code === "authorization") {
2043
+ this.emitError("PERMISSION_DENIED", error.message, error, false);
2044
+ return;
2045
+ }
2025
2046
  this.emitError(
2026
2047
  "SFU_ERROR",
2027
2048
  error?.message || String(error),
@@ -2034,7 +2055,7 @@ var VideoSDKCore = class {
2034
2055
  client.setLocalStream(this.localStream);
2035
2056
  await client.getToken(roomId, {
2036
2057
  displayName: name,
2037
- userId: this.myId
2058
+ participantId: this.myId
2038
2059
  });
2039
2060
  }
2040
2061
  // SFU STATE
@@ -2356,6 +2377,7 @@ var MeetingProvider = ({
2356
2377
  );
2357
2378
  if (!sdkRef.current) {
2358
2379
  sdkRef.current = new VideoSDKCore({
2380
+ participantId: config.participantId,
2359
2381
  onError: (err) => errorListeners.current.forEach((fn) => fn(err)),
2360
2382
  onEntryRequested: (req) => entryRequestListeners.current.forEach((fn) => fn(req)),
2361
2383
  onEntryResponded: (p, d) => entryResponseListeners.current.forEach((fn) => fn(p, d)),
@@ -2392,13 +2414,6 @@ var MeetingProvider = ({
2392
2414
  (s) => s.getChatMessages()
2393
2415
  );
2394
2416
  const value = useMemo(() => {
2395
- if (!sdkRef.current) {
2396
- sdkRef.current = new VideoSDKCore({
2397
- onError: (err) => {
2398
- errorListeners.current.forEach((fn) => fn(err));
2399
- }
2400
- });
2401
- }
2402
2417
  return {
2403
2418
  sdk,
2404
2419
  join: (joinConfig) => sdk.joinMeeting({
@@ -2630,7 +2645,7 @@ var useRemoteMedia = (participantId) => {
2630
2645
 
2631
2646
  // src/react/useMeetingPreview.ts
2632
2647
  import { useEffect as useEffect6, useState as useState5 } from "react";
2633
- function useMeetingPreview(roomId, userId) {
2648
+ function useMeetingPreview(roomId, participantId) {
2634
2649
  const [room, setRoom] = useState5(null);
2635
2650
  const [error, setError] = useState5(null);
2636
2651
  const [isConnected, setIsConnected] = useState5(false);
@@ -2689,7 +2704,7 @@ function useMeetingPreview(roomId, userId) {
2689
2704
  stopped = true;
2690
2705
  if (timer) clearTimeout(timer);
2691
2706
  };
2692
- }, [roomId, userId]);
2707
+ }, [roomId, participantId]);
2693
2708
  return {
2694
2709
  room,
2695
2710
  isConnected,