vg-x07df 1.10.6 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import React, { createContext, useMemo, useEffect, useContext, useState, useRef, useReducer, useCallback } from 'react';
2
- import { io } from 'socket.io-client';
3
2
  import { create } from 'zustand';
4
3
  import { immer } from 'zustand/middleware/immer';
5
- import { z } from 'zod';
6
- import { enableMapSet } from 'immer';
7
4
  import mitt from 'mitt';
5
+ import { enableMapSet } from 'immer';
6
+ import { io } from 'socket.io-client';
7
+ import { z } from 'zod';
8
8
  import { VideoPresets, ConnectionState, Room, RoomEvent, Track } from 'livekit-client';
9
9
  import { useConnectionState as useConnectionState$1, useRoomContext, useLocalParticipant, useParticipants, useTracks } from '@livekit/components-react';
10
10
  import { BackgroundProcessor } from '@livekit/track-processors';
@@ -1290,227 +1290,6 @@ var parseTimeInput = (input) => {
1290
1290
  return Number.isFinite(timestamp) ? timestamp : null;
1291
1291
  };
1292
1292
 
1293
- // src/clients/signal/config.ts
1294
- var logger = createLogger("api-config");
1295
- var OpenApiConfigService = class _OpenApiConfigService {
1296
- constructor() {
1297
- OpenAPI.interceptors.request.use((request2) => {
1298
- const headers = request2.headers;
1299
- let authHeader = null;
1300
- if (headers instanceof Headers) {
1301
- authHeader = headers.get("Authorization") || null;
1302
- } else if (headers && typeof headers === "object") {
1303
- authHeader = headers.Authorization || null;
1304
- }
1305
- if (authHeader) {
1306
- logger.debug("API Request with Authorization header", {
1307
- hasAuth: true,
1308
- authPrefix: `${authHeader.substring(0, 20)}...`
1309
- });
1310
- } else {
1311
- logger.warn("API Request WITHOUT Authorization header", {
1312
- hasAuth: false
1313
- });
1314
- }
1315
- return request2;
1316
- });
1317
- }
1318
- static getInstance() {
1319
- if (!_OpenApiConfigService.instance) {
1320
- _OpenApiConfigService.instance = new _OpenApiConfigService();
1321
- }
1322
- return _OpenApiConfigService.instance;
1323
- }
1324
- configure(config) {
1325
- OpenAPI.BASE = config.baseUrl;
1326
- if (typeof config.token === "function") {
1327
- const tokenFn = config.token;
1328
- OpenAPI.TOKEN = async (_options) => {
1329
- const result = tokenFn();
1330
- const token = typeof result === "string" ? result : await result;
1331
- if (!token) {
1332
- logger.warn("Token provider returned empty token");
1333
- } else {
1334
- logger.debug("Token resolved successfully", {
1335
- tokenPrefix: `${token.substring(0, 10)}...`
1336
- });
1337
- }
1338
- return token;
1339
- };
1340
- } else {
1341
- OpenAPI.TOKEN = config.token;
1342
- }
1343
- OpenAPI.CREDENTIALS = config.credentials ?? "include";
1344
- OpenAPI.WITH_CREDENTIALS = config.withCredentials ?? false;
1345
- if (config.headers) {
1346
- OpenAPI.HEADERS = config.headers;
1347
- }
1348
- logger.info("Signal svc configuration completed", {
1349
- baseUrl: config.baseUrl,
1350
- hasToken: !!config.token
1351
- });
1352
- }
1353
- };
1354
- var apiConfig = OpenApiConfigService.getInstance();
1355
-
1356
- // src/core/session-storage.ts
1357
- var SessionStorage = class {
1358
- constructor(key) {
1359
- this.key = key;
1360
- }
1361
- set(data) {
1362
- const serialized = JSON.stringify(data);
1363
- sessionStorage.setItem(this.key, serialized);
1364
- }
1365
- get() {
1366
- const stored = sessionStorage.getItem(this.key);
1367
- if (!stored) {
1368
- return null;
1369
- }
1370
- try {
1371
- return JSON.parse(stored);
1372
- } catch {
1373
- return null;
1374
- }
1375
- }
1376
- clear() {
1377
- sessionStorage.removeItem(this.key);
1378
- }
1379
- exists() {
1380
- return sessionStorage.getItem(this.key) !== null;
1381
- }
1382
- };
1383
-
1384
- // src/core/auth.manager.ts
1385
- var logger2 = createLogger("auth-manager");
1386
- var DEFAULT_AUTH_RETRY_CONFIG = {
1387
- maxRetries: 10,
1388
- initialDelayMs: 200,
1389
- maxDelayMs: 5e3,
1390
- backoffMultiplier: 2
1391
- };
1392
- var AuthManager = class {
1393
- constructor(authProvider, appId, retryConfig) {
1394
- this.lastToken = null;
1395
- this.initializePromise = null;
1396
- this.authProvider = authProvider;
1397
- this.appId = appId;
1398
- this.sessionStorage = new SessionStorage(
1399
- "callpad_session_info"
1400
- );
1401
- this.retryConfig = { ...DEFAULT_AUTH_RETRY_CONFIG, ...retryConfig };
1402
- }
1403
- async acquireTokenWithRetry() {
1404
- const { maxRetries, initialDelayMs, maxDelayMs, backoffMultiplier } = this.retryConfig;
1405
- let delay = initialDelayMs;
1406
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
1407
- const token = this.authProvider();
1408
- if (token) {
1409
- if (attempt > 0) {
1410
- logger2.debug("Token acquired after retry", { attempt });
1411
- }
1412
- return token;
1413
- }
1414
- if (attempt < maxRetries) {
1415
- logger2.debug("Auth token not available, retrying", {
1416
- attempt: attempt + 1,
1417
- maxRetries,
1418
- delayMs: delay
1419
- });
1420
- await new Promise((resolve2) => setTimeout(resolve2, delay));
1421
- delay = Math.min(delay * backoffMultiplier, maxDelayMs);
1422
- }
1423
- }
1424
- throw new Error(
1425
- `No authentication token available after ${maxRetries} retries. This may indicate the auth provider is temporarily unavailable (e.g., token refresh in progress).`
1426
- );
1427
- }
1428
- async initialize(appId) {
1429
- try {
1430
- const token = await this.acquireTokenWithRetry();
1431
- const originalToken = OpenAPI.TOKEN;
1432
- OpenAPI.TOKEN = token;
1433
- try {
1434
- logger2.debug("Initializing session", { appId });
1435
- const response = await InitService.getSignalInit({ appId });
1436
- const sessionInfo = {
1437
- sessionToken: response.sessionToken,
1438
- sessionId: response.sessionId,
1439
- userId: response.userId,
1440
- deviceId: response.deviceId,
1441
- expiresAt: response.expiresAt
1442
- };
1443
- this.sessionStorage.set(sessionInfo);
1444
- logger2.info("Session initialized successfully", {
1445
- sessionId: sessionInfo.sessionId,
1446
- userId: sessionInfo.userId
1447
- });
1448
- } finally {
1449
- OpenAPI.TOKEN = originalToken;
1450
- }
1451
- } catch (error) {
1452
- logger2.error("Failed to initialize session", { appId, error });
1453
- throw new Error(`Session initialization failed: ${error}`);
1454
- }
1455
- }
1456
- async getSessionToken() {
1457
- const sessionInfo = this.sessionStorage.get();
1458
- if (sessionInfo) {
1459
- return sessionInfo.sessionToken;
1460
- }
1461
- if (!this.initializePromise) {
1462
- this.initializePromise = this.initialize(this.appId);
1463
- }
1464
- try {
1465
- await this.initializePromise;
1466
- const newSessionInfo = this.sessionStorage.get();
1467
- return newSessionInfo?.sessionToken || null;
1468
- } catch (error) {
1469
- logger2.error("Failed to get session token", { error });
1470
- return null;
1471
- }
1472
- }
1473
- getSessionInfo() {
1474
- return this.sessionStorage.get();
1475
- }
1476
- getCurrentToken() {
1477
- const token = this.authProvider();
1478
- if (token !== this.lastToken) {
1479
- this.lastToken = token;
1480
- }
1481
- return token;
1482
- }
1483
- };
1484
-
1485
- // src/core/guest-auth.manager.ts
1486
- var GuestAuthManager = class {
1487
- constructor(appId, deviceId) {
1488
- this.appId = appId;
1489
- this.deviceId = deviceId;
1490
- this.sessionStorage = new SessionStorage(
1491
- "callpad_guest_session"
1492
- );
1493
- }
1494
- getAppId() {
1495
- return this.appId;
1496
- }
1497
- getDeviceId() {
1498
- return this.deviceId;
1499
- }
1500
- setSession(session) {
1501
- this.sessionStorage.set(session);
1502
- }
1503
- async getSessionToken() {
1504
- return this.sessionStorage.get()?.sessionToken || null;
1505
- }
1506
- getSessionInfo() {
1507
- return this.sessionStorage.get();
1508
- }
1509
- clearSession() {
1510
- this.sessionStorage.clear();
1511
- }
1512
- };
1513
-
1514
1293
  // src/state/types.ts
1515
1294
  var defaultState = {
1516
1295
  initiated: false,
@@ -1539,35 +1318,6 @@ var useRtcStore = create()(
1539
1318
  }))
1540
1319
  );
1541
1320
  var rtcStore = useRtcStore;
1542
-
1543
- // src/core/socketio/handlers/base.handler.ts
1544
- var BaseSocketHandler = class {
1545
- constructor(options = {}) {
1546
- this.options = options;
1547
- }
1548
- get logger() {
1549
- if (!this._logger) {
1550
- this._logger = createLogger(`socketio:${this.eventName}`);
1551
- }
1552
- return this._logger;
1553
- }
1554
- async handleRaw(rawData) {
1555
- this.logger.info(`${this.eventName} received`, rawData);
1556
- try {
1557
- await this.handle(JSON.parse(JSON.stringify(rawData)));
1558
- this.logger.debug(`${this.eventName} handled successfully`);
1559
- } catch (error) {
1560
- this.logger.error(`${this.eventName} handler error`, error);
1561
- throw error;
1562
- }
1563
- }
1564
- updateStore(updater) {
1565
- rtcStore.getState().patch(updater);
1566
- }
1567
- get livekit() {
1568
- return this.options.livekit;
1569
- }
1570
- };
1571
1321
  var defaultChatState = {
1572
1322
  byId: {},
1573
1323
  order: [],
@@ -1863,182 +1613,63 @@ var useSpotlightStore = create()(
1863
1613
  }))
1864
1614
  }))
1865
1615
  );
1866
- var callEndedSchema = z.object({
1867
- callId: z.string(),
1868
- endedAt: z.string(),
1869
- endedByUserId: z.string().optional()
1870
- }).strict();
1871
- var callInviteSchema = z.object({
1872
- inviteId: z.string(),
1873
- callId: z.string(),
1874
- userId: z.string(),
1875
- callerId: z.string(),
1876
- mode: z.enum(["VIDEO", "AUDIO"]),
1877
- invitedAt: z.string()
1878
- }).strict();
1879
- var callInviteAcceptedSchema = z.object({
1880
- callId: z.string(),
1881
- userId: z.string(),
1882
- acceptedAt: z.string()
1883
- }).strict();
1884
- var callInviteCancelledSchema = z.object({
1885
- callId: z.string(),
1886
- cancelledByUserId: z.string(),
1887
- cancelledAt: z.string(),
1888
- reason: z.string()
1889
- }).strict();
1890
- var callInviteDeclinedSchema = z.object({
1891
- callId: z.string(),
1892
- userId: z.string(),
1893
- reason: z.string().optional(),
1894
- declinedAt: z.string()
1895
- }).strict();
1896
- var callInviteMissedSchema = z.object({
1897
- callId: z.string(),
1898
- userId: z.string(),
1899
- missedAt: z.string()
1900
- }).strict();
1901
- var callParticipantAddedSchema = z.object({
1902
- callId: z.string(),
1903
- userId: z.string(),
1904
- participantId: z.string()
1905
- }).strict();
1906
- var callParticipantKickedSchema = z.object({
1907
- callId: z.string(),
1908
- participantId: z.string(),
1909
- userId: z.string(),
1910
- reason: z.string().optional()
1911
- }).strict();
1912
- var callParticipantLeftSchema = z.object({
1913
- callId: z.string(),
1914
- userId: z.string(),
1915
- participantId: z.string(),
1916
- leftAt: z.string(),
1917
- reason: z.string().optional()
1918
- }).strict();
1919
- var callReadySchema = z.object({
1920
- callId: z.string(),
1921
- participantId: z.string().optional(),
1922
- userId: z.string(),
1923
- message: z.string()
1924
- }).strict();
1925
- var callRecordingStartedSchema = z.object({
1926
- callId: z.string(),
1927
- recordingId: z.string(),
1928
- egressId: z.string(),
1929
- initiatedBy: z.string().optional(),
1930
- startedAt: z.string()
1931
- }).strict();
1932
- var callRecordingStoppedSchema = z.object({
1933
- callId: z.string(),
1934
- recordingId: z.string(),
1935
- egressId: z.string(),
1936
- stoppedAt: z.string()
1937
- }).strict();
1938
- var callStartedSchema = z.object({
1939
- callId: z.string(),
1940
- startedAt: z.string()
1941
- }).strict();
1942
- var participantProfilesSchema = z.object({
1943
- profiles: z.array(z.object({
1944
- userId: z.string(),
1945
- username: z.string().nullable(),
1946
- firstName: z.string().nullable(),
1947
- lastName: z.string().nullable(),
1948
- profilePhoto: z.string().nullable()
1949
- }).strict())
1950
- }).strict();
1951
- var presencePingSchema = z.object({}).strict();
1616
+ var EventBus = class {
1617
+ constructor() {
1618
+ this.emitter = mitt();
1619
+ }
1620
+ on(eventType, handler) {
1621
+ const wrappedHandler = (event) => {
1622
+ handler(event);
1623
+ };
1624
+ this.emitter.on(eventType.toString(), wrappedHandler);
1625
+ return {
1626
+ unsubscribe: () => {
1627
+ this.emitter.off(eventType.toString(), wrappedHandler);
1628
+ }
1629
+ };
1630
+ }
1631
+ emit(eventType, payload) {
1632
+ const event = {
1633
+ type: eventType.toString(),
1634
+ payload,
1635
+ timestamp: Date.now()
1636
+ };
1637
+ this.emitter.emit(eventType.toString(), event);
1638
+ }
1639
+ off(eventType) {
1640
+ this.emitter.off(eventType.toString());
1641
+ }
1642
+ removeAllListeners() {
1643
+ this.emitter.all.clear();
1644
+ }
1645
+ };
1646
+ var eventBus = new EventBus();
1952
1647
 
1953
- // src/state/errors.ts
1954
- function pushError(code, message, context, logger7) {
1955
- const error = {
1956
- code,
1957
- message,
1958
- timestamp: Date.now(),
1959
- context
1960
- };
1961
- logger7?.("error", message, { code, context });
1962
- rtcStore.getState().addError(error);
1963
- }
1964
- function clearErrors(predicate) {
1965
- rtcStore.getState().patch((state) => {
1966
- if (predicate) {
1967
- state.errors = state.errors.filter((error) => !predicate(error));
1968
- } else {
1969
- state.errors = [];
1970
- }
1971
- });
1972
- }
1973
- function pushSocketValidationError(eventType, issues, payload, logger7) {
1974
- pushError(
1975
- "SOCKET_PAYLOAD",
1976
- `Invalid ${eventType} event payload`,
1977
- { eventType, issues, payload },
1978
- logger7
1979
- );
1980
- }
1981
- function pushIdentityGuardError(reason, expected, received, logger7) {
1982
- pushError(
1983
- "JOIN_FLOW",
1984
- // Use new error code
1985
- `Identity guard failed: ${reason}`,
1986
- { expected, received },
1987
- logger7
1988
- );
1989
- }
1990
- function pushLiveKitConnectError(message, error, logger7) {
1991
- pushError(
1992
- "LIVEKIT_CONNECT",
1993
- `LiveKit connection failed: ${message}`,
1994
- { originalError: error },
1995
- logger7
1996
- );
1997
- }
1998
- function pushStaleEventError(eventType, reason, context, logger7) {
1999
- pushError(
2000
- "JOIN_FLOW",
2001
- // Use new error code
2002
- `Ignored stale ${eventType} event: ${reason}`,
2003
- context,
2004
- logger7
2005
- );
2006
- }
2007
- function pushApiError(operation, error, logger7) {
2008
- const errorMessage = error instanceof Error ? error.message : String(error);
2009
- pushError(
2010
- "API_ERROR",
2011
- `API ${operation} failed: ${errorMessage}`,
2012
- { operation, originalError: error },
2013
- logger7
2014
- );
2015
- }
2016
- function pushNetworkError(operation, error, logger7) {
2017
- const errorMessage = error instanceof Error ? error.message : String(error);
2018
- pushError(
2019
- "NETWORK",
2020
- `Network error during ${operation}: ${errorMessage}`,
2021
- { operation, originalError: error },
2022
- logger7
2023
- );
2024
- }
2025
- function pushMediaPermissionError(device, error, logger7) {
2026
- pushError(
2027
- "MEDIA_PERMISSION",
2028
- `${device} permission denied`,
2029
- { device, originalError: error },
2030
- logger7
2031
- );
2032
- }
2033
- function pushDeviceError(operation, device, error, logger7) {
2034
- const errorMessage = error instanceof Error ? error.message : String(error);
2035
- pushError(
2036
- "DEVICE_SWITCH",
2037
- `Failed to ${operation} ${device}: ${errorMessage}`,
2038
- { operation, device, originalError: error },
2039
- logger7
2040
- );
2041
- }
1648
+ // src/core/events/types.ts
1649
+ var SdkEventType = /* @__PURE__ */ ((SdkEventType2) => {
1650
+ SdkEventType2["CALL_INITIATED"] = "call:initiated";
1651
+ SdkEventType2["CALL_INCOMING"] = "call:incoming";
1652
+ SdkEventType2["CALL_DECLINED"] = "call:declined";
1653
+ SdkEventType2["CALL_ENDED"] = "call:ended";
1654
+ SdkEventType2["CALL_CANCELED"] = "call:canceled";
1655
+ SdkEventType2["CALL_TIMEOUT"] = "call:timeout";
1656
+ SdkEventType2["CALL_MISSED"] = "call:missed";
1657
+ SdkEventType2["JOIN_INFO_RECEIVED"] = "join-info:received";
1658
+ SdkEventType2["CALL_STARTED"] = "call:started";
1659
+ SdkEventType2["MEETING_CREATED"] = "meeting:created";
1660
+ SdkEventType2["MEETING_STARTED"] = "meeting:started";
1661
+ SdkEventType2["MEETING_JOINED"] = "meeting:joined";
1662
+ SdkEventType2["MEETING_ENDED"] = "meeting:ended";
1663
+ SdkEventType2["PARTICIPANT_UPDATED"] = "participant:updated";
1664
+ SdkEventType2["PARTICIPANT_INVITED"] = "participant:invited";
1665
+ SdkEventType2["RECORDING_STARTED"] = "recording:started";
1666
+ SdkEventType2["RECORDING_STOPPED"] = "recording:stopped";
1667
+ SdkEventType2["GUEST_JOINED"] = "guest:joined";
1668
+ SdkEventType2["GUEST_LEFT"] = "guest:left";
1669
+ SdkEventType2["GUEST_KICKED"] = "guest:kicked";
1670
+ SdkEventType2["GUEST_SESSION_ERROR"] = "guest:session_error";
1671
+ return SdkEventType2;
1672
+ })(SdkEventType || {});
2042
1673
 
2043
1674
  // src/clients/signal/services/users.ts
2044
1675
  var SignalUsersService = class {
@@ -2152,63 +1783,473 @@ var useRecordingStore = create()(
2152
1783
  }))
2153
1784
  );
2154
1785
  var recordingStore = useRecordingStore;
2155
- var EventBus = class {
2156
- constructor() {
2157
- this.emitter = mitt();
2158
- }
2159
- on(eventType, handler) {
2160
- const wrappedHandler = (event) => {
2161
- handler(event);
2162
- };
2163
- this.emitter.on(eventType.toString(), wrappedHandler);
2164
- return {
2165
- unsubscribe: () => {
2166
- this.emitter.off(eventType.toString(), wrappedHandler);
2167
- }
1786
+
1787
+ // src/utils/session-cleanup.ts
1788
+ function cleanupSession() {
1789
+ rtcStore.getState().reset();
1790
+ profileCache.getState().clear();
1791
+ recordingStore.getState().clear();
1792
+ useChatStore.getState().clearChat();
1793
+ useSpotlightStore.getState().clear();
1794
+ useRaiseHandStore.getState().clear();
1795
+ }
1796
+
1797
+ // src/utils/error-handler.ts
1798
+ function handleServiceError(code, defaultMessage, error) {
1799
+ rtcStore.getState().addError({
1800
+ code,
1801
+ message: error.message || defaultMessage,
1802
+ timestamp: Date.now(),
1803
+ context: error
1804
+ });
1805
+ throw error;
1806
+ }
1807
+
1808
+ // src/utils/session-state.ts
1809
+ function setOptimisticSession(partial) {
1810
+ rtcStore.getState().patch((state) => {
1811
+ state.session = {
1812
+ id: "temp",
1813
+ status: "initializing",
1814
+ mode: "VIDEO",
1815
+ ...partial
2168
1816
  };
1817
+ });
1818
+ }
1819
+ function clearOptimisticSession(clearInitiated = true) {
1820
+ rtcStore.getState().patch((state) => {
1821
+ state.session = null;
1822
+ if (clearInitiated) {
1823
+ state.initiated = false;
1824
+ }
1825
+ });
1826
+ }
1827
+
1828
+ // src/clients/signal/config.ts
1829
+ var logger = createLogger("api-config");
1830
+ var OpenApiConfigService = class _OpenApiConfigService {
1831
+ constructor() {
1832
+ OpenAPI.interceptors.request.use((request2) => {
1833
+ const headers = request2.headers;
1834
+ let authHeader = null;
1835
+ if (headers instanceof Headers) {
1836
+ authHeader = headers.get("Authorization") || null;
1837
+ } else if (headers && typeof headers === "object") {
1838
+ authHeader = headers.Authorization || null;
1839
+ }
1840
+ if (authHeader) {
1841
+ logger.debug("API Request with Authorization header", {
1842
+ hasAuth: true,
1843
+ authPrefix: `${authHeader.substring(0, 20)}...`
1844
+ });
1845
+ } else {
1846
+ logger.warn("API Request WITHOUT Authorization header", {
1847
+ hasAuth: false
1848
+ });
1849
+ }
1850
+ return request2;
1851
+ });
2169
1852
  }
2170
- emit(eventType, payload) {
2171
- const event = {
2172
- type: eventType.toString(),
2173
- payload,
2174
- timestamp: Date.now()
2175
- };
2176
- this.emitter.emit(eventType.toString(), event);
2177
- }
2178
- off(eventType) {
2179
- this.emitter.off(eventType.toString());
1853
+ static getInstance() {
1854
+ if (!_OpenApiConfigService.instance) {
1855
+ _OpenApiConfigService.instance = new _OpenApiConfigService();
1856
+ }
1857
+ return _OpenApiConfigService.instance;
2180
1858
  }
2181
- removeAllListeners() {
2182
- this.emitter.all.clear();
1859
+ configure(config) {
1860
+ OpenAPI.BASE = config.baseUrl;
1861
+ if (typeof config.token === "function") {
1862
+ const tokenFn = config.token;
1863
+ OpenAPI.TOKEN = async (_options) => {
1864
+ const result = tokenFn();
1865
+ const token = typeof result === "string" ? result : await result;
1866
+ if (!token) {
1867
+ logger.warn("Token provider returned empty token");
1868
+ } else {
1869
+ logger.debug("Token resolved successfully", {
1870
+ tokenPrefix: `${token.substring(0, 10)}...`
1871
+ });
1872
+ }
1873
+ return token;
1874
+ };
1875
+ } else {
1876
+ OpenAPI.TOKEN = config.token;
1877
+ }
1878
+ OpenAPI.CREDENTIALS = config.credentials ?? "include";
1879
+ OpenAPI.WITH_CREDENTIALS = config.withCredentials ?? false;
1880
+ if (config.headers) {
1881
+ OpenAPI.HEADERS = config.headers;
1882
+ }
1883
+ logger.info("Signal svc configuration completed", {
1884
+ baseUrl: config.baseUrl,
1885
+ hasToken: !!config.token
1886
+ });
2183
1887
  }
2184
1888
  };
2185
- var eventBus = new EventBus();
1889
+ var apiConfig = OpenApiConfigService.getInstance();
1890
+
1891
+ // src/core/session-storage.ts
1892
+ var SessionStorage = class {
1893
+ constructor(key) {
1894
+ this.key = key;
1895
+ }
1896
+ set(data) {
1897
+ const serialized = JSON.stringify(data);
1898
+ sessionStorage.setItem(this.key, serialized);
1899
+ }
1900
+ get() {
1901
+ const stored = sessionStorage.getItem(this.key);
1902
+ if (!stored) {
1903
+ return null;
1904
+ }
1905
+ try {
1906
+ return JSON.parse(stored);
1907
+ } catch {
1908
+ return null;
1909
+ }
1910
+ }
1911
+ clear() {
1912
+ sessionStorage.removeItem(this.key);
1913
+ }
1914
+ exists() {
1915
+ return sessionStorage.getItem(this.key) !== null;
1916
+ }
1917
+ };
1918
+
1919
+ // src/core/auth.manager.ts
1920
+ var logger2 = createLogger("auth-manager");
1921
+ var DEFAULT_AUTH_RETRY_CONFIG = {
1922
+ maxRetries: 10,
1923
+ initialDelayMs: 200,
1924
+ maxDelayMs: 5e3,
1925
+ backoffMultiplier: 2
1926
+ };
1927
+ var AuthManager = class {
1928
+ constructor(authProvider, appId, retryConfig) {
1929
+ this.lastToken = null;
1930
+ this.initializePromise = null;
1931
+ this.authProvider = authProvider;
1932
+ this.appId = appId;
1933
+ this.sessionStorage = new SessionStorage(
1934
+ "callpad_session_info"
1935
+ );
1936
+ this.retryConfig = { ...DEFAULT_AUTH_RETRY_CONFIG, ...retryConfig };
1937
+ }
1938
+ async acquireTokenWithRetry() {
1939
+ const { maxRetries, initialDelayMs, maxDelayMs, backoffMultiplier } = this.retryConfig;
1940
+ let delay = initialDelayMs;
1941
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
1942
+ const token = this.authProvider();
1943
+ if (token) {
1944
+ if (attempt > 0) {
1945
+ logger2.debug("Token acquired after retry", { attempt });
1946
+ }
1947
+ return token;
1948
+ }
1949
+ if (attempt < maxRetries) {
1950
+ logger2.debug("Auth token not available, retrying", {
1951
+ attempt: attempt + 1,
1952
+ maxRetries,
1953
+ delayMs: delay
1954
+ });
1955
+ await new Promise((resolve2) => setTimeout(resolve2, delay));
1956
+ delay = Math.min(delay * backoffMultiplier, maxDelayMs);
1957
+ }
1958
+ }
1959
+ throw new Error(
1960
+ `No authentication token available after ${maxRetries} retries. This may indicate the auth provider is temporarily unavailable (e.g., token refresh in progress).`
1961
+ );
1962
+ }
1963
+ async initialize(appId) {
1964
+ try {
1965
+ const token = await this.acquireTokenWithRetry();
1966
+ const originalToken = OpenAPI.TOKEN;
1967
+ OpenAPI.TOKEN = token;
1968
+ try {
1969
+ logger2.debug("Initializing session", { appId });
1970
+ const response = await InitService.getSignalInit({ appId });
1971
+ const sessionInfo = {
1972
+ sessionToken: response.sessionToken,
1973
+ sessionId: response.sessionId,
1974
+ userId: response.userId,
1975
+ deviceId: response.deviceId,
1976
+ expiresAt: response.expiresAt
1977
+ };
1978
+ this.sessionStorage.set(sessionInfo);
1979
+ logger2.info("Session initialized successfully", {
1980
+ sessionId: sessionInfo.sessionId,
1981
+ userId: sessionInfo.userId
1982
+ });
1983
+ } finally {
1984
+ OpenAPI.TOKEN = originalToken;
1985
+ }
1986
+ } catch (error) {
1987
+ logger2.error("Failed to initialize session", { appId, error });
1988
+ throw new Error(`Session initialization failed: ${error}`);
1989
+ }
1990
+ }
1991
+ async getSessionToken() {
1992
+ const sessionInfo = this.sessionStorage.get();
1993
+ if (sessionInfo) {
1994
+ return sessionInfo.sessionToken;
1995
+ }
1996
+ if (!this.initializePromise) {
1997
+ this.initializePromise = this.initialize(this.appId);
1998
+ }
1999
+ try {
2000
+ await this.initializePromise;
2001
+ const newSessionInfo = this.sessionStorage.get();
2002
+ return newSessionInfo?.sessionToken || null;
2003
+ } catch (error) {
2004
+ logger2.error("Failed to get session token", { error });
2005
+ return null;
2006
+ }
2007
+ }
2008
+ getSessionInfo() {
2009
+ return this.sessionStorage.get();
2010
+ }
2011
+ getCurrentToken() {
2012
+ const token = this.authProvider();
2013
+ if (token !== this.lastToken) {
2014
+ this.lastToken = token;
2015
+ }
2016
+ return token;
2017
+ }
2018
+ };
2019
+
2020
+ // src/core/guest-auth.manager.ts
2021
+ var GuestAuthManager = class {
2022
+ constructor(appId, deviceId) {
2023
+ this.appId = appId;
2024
+ this.deviceId = deviceId;
2025
+ this.sessionStorage = new SessionStorage(
2026
+ "callpad_guest_session"
2027
+ );
2028
+ }
2029
+ getAppId() {
2030
+ return this.appId;
2031
+ }
2032
+ getDeviceId() {
2033
+ return this.deviceId;
2034
+ }
2035
+ setSession(session) {
2036
+ this.sessionStorage.set(session);
2037
+ }
2038
+ async getSessionToken() {
2039
+ return this.sessionStorage.get()?.sessionToken || null;
2040
+ }
2041
+ getSessionInfo() {
2042
+ return this.sessionStorage.get();
2043
+ }
2044
+ clearSession() {
2045
+ this.sessionStorage.clear();
2046
+ }
2047
+ };
2048
+
2049
+ // src/core/socketio/handlers/base.handler.ts
2050
+ var BaseSocketHandler = class {
2051
+ constructor(options = {}) {
2052
+ this.options = options;
2053
+ }
2054
+ get logger() {
2055
+ if (!this._logger) {
2056
+ this._logger = createLogger(`socketio:${this.eventName}`);
2057
+ }
2058
+ return this._logger;
2059
+ }
2060
+ async handleRaw(rawData) {
2061
+ this.logger.info(`${this.eventName} received`, rawData);
2062
+ try {
2063
+ await this.handle(JSON.parse(JSON.stringify(rawData)));
2064
+ this.logger.debug(`${this.eventName} handled successfully`);
2065
+ } catch (error) {
2066
+ this.logger.error(`${this.eventName} handler error`, error);
2067
+ throw error;
2068
+ }
2069
+ }
2070
+ updateStore(updater) {
2071
+ rtcStore.getState().patch(updater);
2072
+ }
2073
+ get livekit() {
2074
+ return this.options.livekit;
2075
+ }
2076
+ };
2077
+ var callEndedSchema = z.object({
2078
+ callId: z.string(),
2079
+ endedAt: z.string(),
2080
+ endedByUserId: z.string().optional()
2081
+ }).strict();
2082
+ var callInviteSchema = z.object({
2083
+ inviteId: z.string(),
2084
+ callId: z.string(),
2085
+ userId: z.string(),
2086
+ callerId: z.string(),
2087
+ mode: z.enum(["VIDEO", "AUDIO"]),
2088
+ invitedAt: z.string()
2089
+ }).strict();
2090
+ var callInviteAcceptedSchema = z.object({
2091
+ callId: z.string(),
2092
+ userId: z.string(),
2093
+ acceptedAt: z.string()
2094
+ }).strict();
2095
+ var callInviteCancelledSchema = z.object({
2096
+ callId: z.string(),
2097
+ cancelledByUserId: z.string(),
2098
+ cancelledAt: z.string(),
2099
+ reason: z.string()
2100
+ }).strict();
2101
+ var callInviteDeclinedSchema = z.object({
2102
+ callId: z.string(),
2103
+ userId: z.string(),
2104
+ reason: z.string().optional(),
2105
+ declinedAt: z.string()
2106
+ }).strict();
2107
+ var callInviteMissedSchema = z.object({
2108
+ callId: z.string(),
2109
+ userId: z.string(),
2110
+ missedAt: z.string()
2111
+ }).strict();
2112
+ var callParticipantAddedSchema = z.object({
2113
+ callId: z.string(),
2114
+ userId: z.string(),
2115
+ participantId: z.string()
2116
+ }).strict();
2117
+ var callParticipantKickedSchema = z.object({
2118
+ callId: z.string(),
2119
+ participantId: z.string(),
2120
+ userId: z.string(),
2121
+ reason: z.string().optional()
2122
+ }).strict();
2123
+ var callParticipantLeftSchema = z.object({
2124
+ callId: z.string(),
2125
+ userId: z.string(),
2126
+ participantId: z.string(),
2127
+ leftAt: z.string(),
2128
+ reason: z.string().optional()
2129
+ }).strict();
2130
+ var callReadySchema = z.object({
2131
+ callId: z.string(),
2132
+ participantId: z.string().optional(),
2133
+ userId: z.string(),
2134
+ message: z.string()
2135
+ }).strict();
2136
+ var callRecordingStartedSchema = z.object({
2137
+ callId: z.string(),
2138
+ recordingId: z.string(),
2139
+ egressId: z.string(),
2140
+ initiatedBy: z.string().optional(),
2141
+ startedAt: z.string()
2142
+ }).strict();
2143
+ var callRecordingStoppedSchema = z.object({
2144
+ callId: z.string(),
2145
+ recordingId: z.string(),
2146
+ egressId: z.string(),
2147
+ stoppedAt: z.string()
2148
+ }).strict();
2149
+ var callStartedSchema = z.object({
2150
+ callId: z.string(),
2151
+ startedAt: z.string()
2152
+ }).strict();
2153
+ var participantProfilesSchema = z.object({
2154
+ profiles: z.array(z.object({
2155
+ userId: z.string(),
2156
+ username: z.string().nullable(),
2157
+ firstName: z.string().nullable(),
2158
+ lastName: z.string().nullable(),
2159
+ profilePhoto: z.string().nullable()
2160
+ }).strict())
2161
+ }).strict();
2162
+ var presencePingSchema = z.object({}).strict();
2186
2163
 
2187
- // src/core/events/types.ts
2188
- var SdkEventType = /* @__PURE__ */ ((SdkEventType2) => {
2189
- SdkEventType2["CALL_INITIATED"] = "call:initiated";
2190
- SdkEventType2["CALL_INCOMING"] = "call:incoming";
2191
- SdkEventType2["CALL_DECLINED"] = "call:declined";
2192
- SdkEventType2["CALL_ENDED"] = "call:ended";
2193
- SdkEventType2["CALL_CANCELED"] = "call:canceled";
2194
- SdkEventType2["CALL_TIMEOUT"] = "call:timeout";
2195
- SdkEventType2["CALL_MISSED"] = "call:missed";
2196
- SdkEventType2["JOIN_INFO_RECEIVED"] = "join-info:received";
2197
- SdkEventType2["CALL_STARTED"] = "call:started";
2198
- SdkEventType2["MEETING_CREATED"] = "meeting:created";
2199
- SdkEventType2["MEETING_STARTED"] = "meeting:started";
2200
- SdkEventType2["MEETING_JOINED"] = "meeting:joined";
2201
- SdkEventType2["MEETING_ENDED"] = "meeting:ended";
2202
- SdkEventType2["PARTICIPANT_UPDATED"] = "participant:updated";
2203
- SdkEventType2["PARTICIPANT_INVITED"] = "participant:invited";
2204
- SdkEventType2["RECORDING_STARTED"] = "recording:started";
2205
- SdkEventType2["RECORDING_STOPPED"] = "recording:stopped";
2206
- SdkEventType2["GUEST_JOINED"] = "guest:joined";
2207
- SdkEventType2["GUEST_LEFT"] = "guest:left";
2208
- SdkEventType2["GUEST_KICKED"] = "guest:kicked";
2209
- SdkEventType2["GUEST_SESSION_ERROR"] = "guest:session_error";
2210
- return SdkEventType2;
2211
- })(SdkEventType || {});
2164
+ // src/state/errors.ts
2165
+ function pushError(code, message, context, logger7) {
2166
+ const error = {
2167
+ code,
2168
+ message,
2169
+ timestamp: Date.now(),
2170
+ context
2171
+ };
2172
+ logger7?.("error", message, { code, context });
2173
+ rtcStore.getState().addError(error);
2174
+ }
2175
+ function clearErrors(predicate) {
2176
+ rtcStore.getState().patch((state) => {
2177
+ if (predicate) {
2178
+ state.errors = state.errors.filter((error) => !predicate(error));
2179
+ } else {
2180
+ state.errors = [];
2181
+ }
2182
+ });
2183
+ }
2184
+ function pushSocketValidationError(eventType, issues, payload, logger7) {
2185
+ pushError(
2186
+ "SOCKET_PAYLOAD",
2187
+ `Invalid ${eventType} event payload`,
2188
+ { eventType, issues, payload },
2189
+ logger7
2190
+ );
2191
+ }
2192
+ function pushIdentityGuardError(reason, expected, received, logger7) {
2193
+ pushError(
2194
+ "JOIN_FLOW",
2195
+ // Use new error code
2196
+ `Identity guard failed: ${reason}`,
2197
+ { expected, received },
2198
+ logger7
2199
+ );
2200
+ }
2201
+ function pushLiveKitConnectError(message, error, logger7) {
2202
+ pushError(
2203
+ "LIVEKIT_CONNECT",
2204
+ `LiveKit connection failed: ${message}`,
2205
+ { originalError: error },
2206
+ logger7
2207
+ );
2208
+ }
2209
+ function pushStaleEventError(eventType, reason, context, logger7) {
2210
+ pushError(
2211
+ "JOIN_FLOW",
2212
+ // Use new error code
2213
+ `Ignored stale ${eventType} event: ${reason}`,
2214
+ context,
2215
+ logger7
2216
+ );
2217
+ }
2218
+ function pushApiError(operation, error, logger7) {
2219
+ const errorMessage = error instanceof Error ? error.message : String(error);
2220
+ pushError(
2221
+ "API_ERROR",
2222
+ `API ${operation} failed: ${errorMessage}`,
2223
+ { operation, originalError: error },
2224
+ logger7
2225
+ );
2226
+ }
2227
+ function pushNetworkError(operation, error, logger7) {
2228
+ const errorMessage = error instanceof Error ? error.message : String(error);
2229
+ pushError(
2230
+ "NETWORK",
2231
+ `Network error during ${operation}: ${errorMessage}`,
2232
+ { operation, originalError: error },
2233
+ logger7
2234
+ );
2235
+ }
2236
+ function pushMediaPermissionError(device, error, logger7) {
2237
+ pushError(
2238
+ "MEDIA_PERMISSION",
2239
+ `${device} permission denied`,
2240
+ { device, originalError: error },
2241
+ logger7
2242
+ );
2243
+ }
2244
+ function pushDeviceError(operation, device, error, logger7) {
2245
+ const errorMessage = error instanceof Error ? error.message : String(error);
2246
+ pushError(
2247
+ "DEVICE_SWITCH",
2248
+ `Failed to ${operation} ${device}: ${errorMessage}`,
2249
+ { operation, device, originalError: error },
2250
+ logger7
2251
+ );
2252
+ }
2212
2253
 
2213
2254
  // src/core/socketio/handlers/call-ended.handler.ts
2214
2255
  var SessionEndedHandler = class extends BaseSocketHandler {
@@ -3141,13 +3182,11 @@ function createCallsService(config, deps) {
3141
3182
  try {
3142
3183
  console.log(params, "params");
3143
3184
  if (!params.callId) {
3185
+ setOptimisticSession({
3186
+ mode: params.mode || "AUDIO",
3187
+ role: "HOST"
3188
+ });
3144
3189
  rtcStore.getState().patch((state) => {
3145
- state.session = {
3146
- id: "temp",
3147
- status: "initializing",
3148
- mode: params.mode || "AUDIO",
3149
- role: "HOST"
3150
- };
3151
3190
  state.initiated = true;
3152
3191
  });
3153
3192
  console.log("state: ", rtcStore.getState());
@@ -3249,17 +3288,8 @@ function createCallsService(config, deps) {
3249
3288
  });
3250
3289
  return response;
3251
3290
  } catch (error) {
3252
- rtcStore.getState().patch((state) => {
3253
- state.session = null;
3254
- state.initiated = false;
3255
- });
3256
- rtcStore.getState().addError({
3257
- code: "INITIATE_FAILED",
3258
- message: error.message || "Failed to initiate call",
3259
- timestamp: Date.now(),
3260
- context: error
3261
- });
3262
- throw error;
3291
+ clearOptimisticSession();
3292
+ handleServiceError("INITIATE_FAILED", "Failed to initiate call", error);
3263
3293
  }
3264
3294
  }
3265
3295
  async function accept() {
@@ -3268,13 +3298,12 @@ function createCallsService(config, deps) {
3268
3298
  throw new Error("No incoming invite to accept");
3269
3299
  }
3270
3300
  const { callId, inviteId, mode } = currentState.incomingInvite;
3301
+ setOptimisticSession({
3302
+ id: callId,
3303
+ mode,
3304
+ role: "PARTICIPANT"
3305
+ });
3271
3306
  rtcStore.getState().patch((state) => {
3272
- state.session = {
3273
- id: callId,
3274
- status: "initializing",
3275
- mode,
3276
- role: "PARTICIPANT"
3277
- };
3278
3307
  state.incomingInvite = null;
3279
3308
  });
3280
3309
  try {
@@ -3310,13 +3339,7 @@ function createCallsService(config, deps) {
3310
3339
  state.session = null;
3311
3340
  state.incomingInvite = currentState.incomingInvite;
3312
3341
  });
3313
- rtcStore.getState().addError({
3314
- code: "ACCEPT_FAILED",
3315
- message: error.message || "Failed to accept call",
3316
- timestamp: Date.now(),
3317
- context: error
3318
- });
3319
- throw error;
3342
+ handleServiceError("ACCEPT_FAILED", "Failed to accept call", error);
3320
3343
  }
3321
3344
  }
3322
3345
  async function decline(reason) {
@@ -3342,13 +3365,7 @@ function createCallsService(config, deps) {
3342
3365
  });
3343
3366
  return response;
3344
3367
  } catch (error) {
3345
- rtcStore.getState().addError({
3346
- code: "DECLINE_FAILED",
3347
- message: error.message || "Failed to decline call",
3348
- timestamp: Date.now(),
3349
- context: error
3350
- });
3351
- throw error;
3368
+ handleServiceError("DECLINE_FAILED", "Failed to decline call", error);
3352
3369
  }
3353
3370
  }
3354
3371
  async function cancel(callId) {
@@ -3358,13 +3375,7 @@ function createCallsService(config, deps) {
3358
3375
  callId
3359
3376
  });
3360
3377
  } catch (error) {
3361
- rtcStore.getState().addError({
3362
- code: "CANCEL_FAILED",
3363
- message: error.message || "Failed to cancel call",
3364
- timestamp: Date.now(),
3365
- context: error
3366
- });
3367
- throw error;
3378
+ handleServiceError("CANCEL_FAILED", "Failed to cancel call", error);
3368
3379
  }
3369
3380
  }
3370
3381
  async function leave() {
@@ -3372,21 +3383,10 @@ function createCallsService(config, deps) {
3372
3383
  if (deps?.livekitManager) {
3373
3384
  await deps.livekitManager.disconnect();
3374
3385
  } else {
3375
- rtcStore.getState().reset();
3376
- profileCache.getState().clear();
3377
- recordingStore.getState().clear();
3378
- useChatStore.getState().clearChat();
3379
- useSpotlightStore.getState().clear();
3380
- useRaiseHandStore.getState().clear();
3386
+ cleanupSession();
3381
3387
  }
3382
3388
  } catch (error) {
3383
- rtcStore.getState().addError({
3384
- code: "LEAVE_FAILED",
3385
- message: error.message || "Failed to leave call",
3386
- timestamp: Date.now(),
3387
- context: error
3388
- });
3389
- throw error;
3389
+ handleServiceError("LEAVE_FAILED", "Failed to leave call", error);
3390
3390
  }
3391
3391
  }
3392
3392
  async function transfer(callId, targetParticipantId, reason) {
@@ -3402,13 +3402,7 @@ function createCallsService(config, deps) {
3402
3402
  requestBody
3403
3403
  });
3404
3404
  } catch (error) {
3405
- rtcStore.getState().addError({
3406
- code: "TRANSFER_FAILED",
3407
- message: error.message || "Failed to transfer call",
3408
- timestamp: Date.now(),
3409
- context: error
3410
- });
3411
- throw error;
3405
+ handleServiceError("TRANSFER_FAILED", "Failed to transfer call", error);
3412
3406
  }
3413
3407
  }
3414
3408
  async function kick(callId, participantId, reason) {
@@ -3424,13 +3418,7 @@ function createCallsService(config, deps) {
3424
3418
  requestBody
3425
3419
  });
3426
3420
  } catch (error) {
3427
- rtcStore.getState().addError({
3428
- code: "KICK_FAILED",
3429
- message: error.message || "Failed to kick participant",
3430
- timestamp: Date.now(),
3431
- context: error
3432
- });
3433
- throw error;
3421
+ handleServiceError("KICK_FAILED", "Failed to kick participant", error);
3434
3422
  }
3435
3423
  }
3436
3424
  async function mute(callId, participantId) {
@@ -3442,13 +3430,7 @@ function createCallsService(config, deps) {
3442
3430
  }
3443
3431
  });
3444
3432
  } catch (error) {
3445
- rtcStore.getState().addError({
3446
- code: "MUTE_FAILED",
3447
- message: error.message || "Failed to mute participant",
3448
- timestamp: Date.now(),
3449
- context: error
3450
- });
3451
- throw error;
3433
+ handleServiceError("MUTE_FAILED", "Failed to mute participant", error);
3452
3434
  }
3453
3435
  }
3454
3436
  async function end(callId) {
@@ -3456,21 +3438,10 @@ function createCallsService(config, deps) {
3456
3438
  const response = await signalCalls.end({
3457
3439
  callId
3458
3440
  });
3459
- rtcStore.getState().reset();
3460
- profileCache.getState().clear();
3461
- recordingStore.getState().clear();
3462
- useChatStore.getState().clearChat();
3463
- useSpotlightStore.getState().clear();
3464
- useRaiseHandStore.getState().clear();
3441
+ cleanupSession();
3465
3442
  return response;
3466
3443
  } catch (error) {
3467
- rtcStore.getState().addError({
3468
- code: "END_CALL_FAILED",
3469
- message: error.message || "Failed to end call",
3470
- timestamp: Date.now(),
3471
- context: error
3472
- });
3473
- throw error;
3444
+ handleServiceError("END_CALL_FAILED", "Failed to end call", error);
3474
3445
  }
3475
3446
  }
3476
3447
  async function invite(callId, invitees) {
@@ -3519,13 +3490,7 @@ function createCallsService(config, deps) {
3519
3490
  });
3520
3491
  return response;
3521
3492
  } catch (error) {
3522
- rtcStore.getState().addError({
3523
- code: "INVITE_FAILED",
3524
- message: error.message || "Failed to send invites",
3525
- timestamp: Date.now(),
3526
- context: error
3527
- });
3528
- throw error;
3493
+ handleServiceError("INVITE_FAILED", "Failed to send invites", error);
3529
3494
  }
3530
3495
  }
3531
3496
  async function startRecording(callId) {
@@ -3566,13 +3531,7 @@ function createCallsService(config, deps) {
3566
3531
  });
3567
3532
  return response;
3568
3533
  } catch (error) {
3569
- rtcStore.getState().addError({
3570
- code: "START_RECORDING_FAILED",
3571
- message: error.message || "Failed to start recording",
3572
- timestamp: Date.now(),
3573
- context: error
3574
- });
3575
- throw error;
3534
+ handleServiceError("START_RECORDING_FAILED", "Failed to start recording", error);
3576
3535
  }
3577
3536
  }
3578
3537
  async function stopRecording(callId, recordingId) {
@@ -3589,13 +3548,7 @@ function createCallsService(config, deps) {
3589
3548
  recordingStore.getState().clear();
3590
3549
  return response;
3591
3550
  } catch (error) {
3592
- rtcStore.getState().addError({
3593
- code: "STOP_RECORDING_FAILED",
3594
- message: error.message || "Failed to stop recording",
3595
- timestamp: Date.now(),
3596
- context: error
3597
- });
3598
- throw error;
3551
+ handleServiceError("STOP_RECORDING_FAILED", "Failed to stop recording", error);
3599
3552
  }
3600
3553
  }
3601
3554
  return {
@@ -3693,14 +3646,12 @@ function createMeetingsService(config, deps) {
3693
3646
  const signalMeetings = new SignalMeetingsService(appId);
3694
3647
  async function createAdHoc(params = {}) {
3695
3648
  try {
3649
+ setOptimisticSession({
3650
+ mode: params.mode || "VIDEO",
3651
+ role: "HOST",
3652
+ sessionType: "MEETING"
3653
+ });
3696
3654
  rtcStore.getState().patch((state) => {
3697
- state.session = {
3698
- id: "temp",
3699
- status: "initializing",
3700
- mode: params.mode || "VIDEO",
3701
- role: "HOST",
3702
- sessionType: "MEETING"
3703
- };
3704
3655
  state.initiated = true;
3705
3656
  });
3706
3657
  const requestBody = {};
@@ -3734,29 +3685,18 @@ function createMeetingsService(config, deps) {
3734
3685
  });
3735
3686
  return response;
3736
3687
  } catch (error) {
3737
- rtcStore.getState().patch((state) => {
3738
- state.session = null;
3739
- state.initiated = false;
3740
- });
3741
- rtcStore.getState().addError({
3742
- code: "CREATE_MEETING_FAILED",
3743
- message: error.message || "Failed to create meeting",
3744
- timestamp: Date.now(),
3745
- context: error
3746
- });
3747
- throw error;
3688
+ clearOptimisticSession();
3689
+ handleServiceError("CREATE_MEETING_FAILED", "Failed to create meeting", error);
3748
3690
  }
3749
3691
  }
3750
3692
  async function start(meetingId) {
3751
3693
  try {
3694
+ setOptimisticSession({
3695
+ mode: "VIDEO",
3696
+ role: "HOST",
3697
+ sessionType: "MEETING"
3698
+ });
3752
3699
  rtcStore.getState().patch((state) => {
3753
- state.session = {
3754
- id: "temp",
3755
- status: "initializing",
3756
- mode: "VIDEO",
3757
- role: "HOST",
3758
- sessionType: "MEETING"
3759
- };
3760
3700
  state.initiated = true;
3761
3701
  });
3762
3702
  const response = await signalMeetings.start({
@@ -3783,17 +3723,8 @@ function createMeetingsService(config, deps) {
3783
3723
  });
3784
3724
  return response;
3785
3725
  } catch (error) {
3786
- rtcStore.getState().patch((state) => {
3787
- state.session = null;
3788
- state.initiated = false;
3789
- });
3790
- rtcStore.getState().addError({
3791
- code: "START_MEETING_FAILED",
3792
- message: error.message || "Failed to start meeting",
3793
- timestamp: Date.now(),
3794
- context: error
3795
- });
3796
- throw error;
3726
+ clearOptimisticSession();
3727
+ handleServiceError("START_MEETING_FAILED", "Failed to start meeting", error);
3797
3728
  }
3798
3729
  }
3799
3730
  async function join(params) {
@@ -3801,14 +3732,12 @@ function createMeetingsService(config, deps) {
3801
3732
  throw new Error("Either meetingCode or meetingId is required");
3802
3733
  }
3803
3734
  try {
3735
+ setOptimisticSession({
3736
+ mode: "VIDEO",
3737
+ role: "PARTICIPANT",
3738
+ sessionType: "MEETING"
3739
+ });
3804
3740
  rtcStore.getState().patch((state) => {
3805
- state.session = {
3806
- id: "temp",
3807
- status: "initializing",
3808
- mode: "VIDEO",
3809
- role: "PARTICIPANT",
3810
- sessionType: "MEETING"
3811
- };
3812
3741
  state.initiated = false;
3813
3742
  });
3814
3743
  const requestBody = {};
@@ -3841,16 +3770,8 @@ function createMeetingsService(config, deps) {
3841
3770
  });
3842
3771
  return response;
3843
3772
  } catch (error) {
3844
- rtcStore.getState().patch((state) => {
3845
- state.session = null;
3846
- });
3847
- rtcStore.getState().addError({
3848
- code: "JOIN_MEETING_FAILED",
3849
- message: error.message || "Failed to join meeting",
3850
- timestamp: Date.now(),
3851
- context: error
3852
- });
3853
- throw error;
3773
+ clearOptimisticSession(false);
3774
+ handleServiceError("JOIN_MEETING_FAILED", "Failed to join meeting", error);
3854
3775
  }
3855
3776
  }
3856
3777
  async function end(meetingId) {
@@ -3858,34 +3779,21 @@ function createMeetingsService(config, deps) {
3858
3779
  const response = await signalMeetings.end({
3859
3780
  meetingId
3860
3781
  });
3861
- rtcStore.getState().reset();
3862
- profileCache.getState().clear();
3863
- recordingStore.getState().clear();
3864
- useChatStore.getState().clearChat();
3865
- useSpotlightStore.getState().clear();
3866
- useRaiseHandStore.getState().clear();
3782
+ cleanupSession();
3867
3783
  return response;
3868
3784
  } catch (error) {
3869
- rtcStore.getState().addError({
3870
- code: "END_MEETING_FAILED",
3871
- message: error.message || "Failed to end meeting",
3872
- timestamp: Date.now(),
3873
- context: error
3874
- });
3875
- throw error;
3785
+ handleServiceError("END_MEETING_FAILED", "Failed to end meeting", error);
3876
3786
  }
3877
3787
  }
3878
3788
  async function guestJoin(params, context) {
3879
3789
  const { meetingCode, displayName, passcode } = params;
3790
+ setOptimisticSession({
3791
+ mode: "VIDEO",
3792
+ role: "GUEST",
3793
+ sessionType: "MEETING"
3794
+ });
3880
3795
  rtcStore.getState().patch((state) => {
3881
3796
  state.isGuestMode = true;
3882
- state.session = {
3883
- id: "temp",
3884
- status: "initializing",
3885
- mode: "VIDEO",
3886
- role: "GUEST",
3887
- sessionType: "MEETING"
3888
- };
3889
3797
  });
3890
3798
  try {
3891
3799
  const guestJoinParams = {
@@ -3936,13 +3844,7 @@ function createMeetingsService(config, deps) {
3936
3844
  state.guestIdentity = null;
3937
3845
  state.isGuestMode = false;
3938
3846
  });
3939
- rtcStore.getState().addError({
3940
- code: "GUEST_JOIN_FAILED",
3941
- message: error.message || "Failed to join meeting as guest",
3942
- timestamp: Date.now(),
3943
- context: error
3944
- });
3945
- throw error;
3847
+ handleServiceError("GUEST_JOIN_FAILED", "Failed to join meeting as guest", error);
3946
3848
  }
3947
3849
  }
3948
3850
  async function leave() {
@@ -3952,31 +3854,19 @@ function createMeetingsService(config, deps) {
3952
3854
  if (deps?.livekitManager) {
3953
3855
  await deps.livekitManager.disconnect();
3954
3856
  }
3955
- rtcStore.getState().patch((state2) => {
3956
- state2.session = null;
3957
- state2.initiated = false;
3958
- if (isGuest) {
3857
+ if (isGuest) {
3858
+ rtcStore.getState().patch((state2) => {
3959
3859
  state2.guestIdentity = null;
3960
3860
  state2.isGuestMode = false;
3961
- }
3962
- });
3963
- profileCache.getState().clear();
3964
- recordingStore.getState().clear();
3965
- useChatStore.getState().clearChat();
3966
- useSpotlightStore.getState().clear();
3967
- useRaiseHandStore.getState().clear();
3861
+ });
3862
+ }
3863
+ cleanupSession();
3968
3864
  eventBus.emit(
3969
3865
  isGuest ? "guest:left" /* GUEST_LEFT */ : "meeting:ended" /* MEETING_ENDED */,
3970
3866
  {}
3971
3867
  );
3972
3868
  } catch (error) {
3973
- rtcStore.getState().addError({
3974
- code: "LEAVE_MEETING_FAILED",
3975
- message: error.message || "Failed to leave meeting",
3976
- timestamp: Date.now(),
3977
- context: error
3978
- });
3979
- throw error;
3869
+ handleServiceError("LEAVE_MEETING_FAILED", "Failed to leave meeting", error);
3980
3870
  }
3981
3871
  }
3982
3872
  return {