sabha-meetings-react 0.1.5 → 0.1.7

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.d.mts CHANGED
@@ -2,10 +2,11 @@ import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
 
4
4
  type SabhaTokens = {
5
- /** Optional bearer token (Postman-style). Live API primarily uses `vm_session` cookie. */
5
+ /** Bearer access token from login `token` (Postman `accessToken`). */
6
6
  accessToken?: string;
7
+ /** Refresh token from login `refreshToken` (Postman). */
7
8
  refreshToken?: string;
8
- /** Session cookie value when running outside the browser (Node / RN). */
9
+ /** Optional legacy `vm_session` cookie / x-sabha-session bridge. */
9
10
  sessionCookie?: string;
10
11
  };
11
12
  type SabhaConfig = {
@@ -19,11 +20,11 @@ type SabhaConfig = {
19
20
  /** Optional bearer access token */
20
21
  accessToken?: string;
21
22
  refreshToken?: string;
22
- /** Persist/reuse `vm_session` (also sent as x-sabha-session for proxies). */
23
+ /** Optional legacy `vm_session` (also sent as x-sabha-session for proxies). */
23
24
  sessionCookie?: string;
24
25
  /**
25
- * Persist `vm_session` in localStorage after login and restore on configure.
26
- * Default true in browsers.
26
+ * Persist access/refresh tokens (and optional vm_session) after login and restore on configure.
27
+ * Matches Postman collection variables. Default true.
27
28
  */
28
29
  persistSession?: boolean;
29
30
  /** Send cookies (`credentials: "include"`). Default true. */
@@ -347,6 +348,7 @@ declare class SabhaClient {
347
348
  getConnection(): MeetingConnection | null;
348
349
  leaveMeeting(): Promise<void>;
349
350
  private applySession;
351
+ private persistTokens;
350
352
  private persistSessionCookie;
351
353
  private tryRefresh;
352
354
  private getOrigin;
@@ -435,9 +437,14 @@ declare function normalizeMeeting(raw: unknown): Meeting;
435
437
 
436
438
  /** Readable session bridge header (browsers cannot set the Cookie request header). */
437
439
  declare const SABHA_SESSION_HEADER = "x-sabha-session";
440
+ /** @deprecated Prefer SABHA_TOKENS_STORAGE_KEY — kept for one-time migration. */
438
441
  declare const SABHA_SESSION_STORAGE_KEY = "sabha_vm_session";
442
+ /** Persists Postman-style `accessToken` / `refreshToken` (+ optional vm_session). */
443
+ declare const SABHA_TOKENS_STORAGE_KEY = "sabha_auth_tokens";
444
+ declare function readStoredTokens(): SabhaTokens | null;
445
+ declare function writeStoredTokens(tokens: SabhaTokens | null): void;
439
446
  declare function readStoredSessionCookie(): string | null;
440
447
  declare function writeStoredSessionCookie(value: string | null): void;
441
448
 
442
- export { ContentProtection, DEFAULT_BASE_URL, DEFAULT_MEDIA_POLICY, MediaController, MeetingConnection, SABHA_SESSION_HEADER, SABHA_SESSION_STORAGE_KEY, SabhaClient, SabhaError, SabhaProvider, createSabhaClient, normalizeMeeting, readStoredSessionCookie, toSabhaError, useSabha, useSabhaMeetings, writeStoredSessionCookie };
449
+ export { ContentProtection, DEFAULT_BASE_URL, DEFAULT_MEDIA_POLICY, MediaController, MeetingConnection, SABHA_SESSION_HEADER, SABHA_SESSION_STORAGE_KEY, SABHA_TOKENS_STORAGE_KEY, SabhaClient, SabhaError, SabhaProvider, createSabhaClient, normalizeMeeting, readStoredSessionCookie, readStoredTokens, toSabhaError, useSabha, useSabhaMeetings, writeStoredSessionCookie, writeStoredTokens };
443
450
  export type { AuthSession, AuthUser, CaptureAttemptType, CreateMeetingInput, LocalMediaState, LoginInput, MediaPolicy, MediaTrackKind, Meeting, MeetingConnectionOptions, MeetingConnectionState, MeetingInvitee, MeetingOrganizer, MeetingParticipant, MeetingRoomEventMap, RegisterInput, SabhaClientStatus, SabhaConfig, SabhaContextValue, SabhaOrg, SabhaProviderProps, SabhaSocketEvents, SabhaTokens, UpdateMeetingInput, VerifyEmailInput };
package/dist/index.d.ts CHANGED
@@ -2,10 +2,11 @@ import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
 
4
4
  type SabhaTokens = {
5
- /** Optional bearer token (Postman-style). Live API primarily uses `vm_session` cookie. */
5
+ /** Bearer access token from login `token` (Postman `accessToken`). */
6
6
  accessToken?: string;
7
+ /** Refresh token from login `refreshToken` (Postman). */
7
8
  refreshToken?: string;
8
- /** Session cookie value when running outside the browser (Node / RN). */
9
+ /** Optional legacy `vm_session` cookie / x-sabha-session bridge. */
9
10
  sessionCookie?: string;
10
11
  };
11
12
  type SabhaConfig = {
@@ -19,11 +20,11 @@ type SabhaConfig = {
19
20
  /** Optional bearer access token */
20
21
  accessToken?: string;
21
22
  refreshToken?: string;
22
- /** Persist/reuse `vm_session` (also sent as x-sabha-session for proxies). */
23
+ /** Optional legacy `vm_session` (also sent as x-sabha-session for proxies). */
23
24
  sessionCookie?: string;
24
25
  /**
25
- * Persist `vm_session` in localStorage after login and restore on configure.
26
- * Default true in browsers.
26
+ * Persist access/refresh tokens (and optional vm_session) after login and restore on configure.
27
+ * Matches Postman collection variables. Default true.
27
28
  */
28
29
  persistSession?: boolean;
29
30
  /** Send cookies (`credentials: "include"`). Default true. */
@@ -347,6 +348,7 @@ declare class SabhaClient {
347
348
  getConnection(): MeetingConnection | null;
348
349
  leaveMeeting(): Promise<void>;
349
350
  private applySession;
351
+ private persistTokens;
350
352
  private persistSessionCookie;
351
353
  private tryRefresh;
352
354
  private getOrigin;
@@ -435,9 +437,14 @@ declare function normalizeMeeting(raw: unknown): Meeting;
435
437
 
436
438
  /** Readable session bridge header (browsers cannot set the Cookie request header). */
437
439
  declare const SABHA_SESSION_HEADER = "x-sabha-session";
440
+ /** @deprecated Prefer SABHA_TOKENS_STORAGE_KEY — kept for one-time migration. */
438
441
  declare const SABHA_SESSION_STORAGE_KEY = "sabha_vm_session";
442
+ /** Persists Postman-style `accessToken` / `refreshToken` (+ optional vm_session). */
443
+ declare const SABHA_TOKENS_STORAGE_KEY = "sabha_auth_tokens";
444
+ declare function readStoredTokens(): SabhaTokens | null;
445
+ declare function writeStoredTokens(tokens: SabhaTokens | null): void;
439
446
  declare function readStoredSessionCookie(): string | null;
440
447
  declare function writeStoredSessionCookie(value: string | null): void;
441
448
 
442
- export { ContentProtection, DEFAULT_BASE_URL, DEFAULT_MEDIA_POLICY, MediaController, MeetingConnection, SABHA_SESSION_HEADER, SABHA_SESSION_STORAGE_KEY, SabhaClient, SabhaError, SabhaProvider, createSabhaClient, normalizeMeeting, readStoredSessionCookie, toSabhaError, useSabha, useSabhaMeetings, writeStoredSessionCookie };
449
+ export { ContentProtection, DEFAULT_BASE_URL, DEFAULT_MEDIA_POLICY, MediaController, MeetingConnection, SABHA_SESSION_HEADER, SABHA_SESSION_STORAGE_KEY, SABHA_TOKENS_STORAGE_KEY, SabhaClient, SabhaError, SabhaProvider, createSabhaClient, normalizeMeeting, readStoredSessionCookie, readStoredTokens, toSabhaError, useSabha, useSabhaMeetings, writeStoredSessionCookie, writeStoredTokens };
443
450
  export type { AuthSession, AuthUser, CaptureAttemptType, CreateMeetingInput, LocalMediaState, LoginInput, MediaPolicy, MediaTrackKind, Meeting, MeetingConnectionOptions, MeetingConnectionState, MeetingInvitee, MeetingOrganizer, MeetingParticipant, MeetingRoomEventMap, RegisterInput, SabhaClientStatus, SabhaConfig, SabhaContextValue, SabhaOrg, SabhaProviderProps, SabhaSocketEvents, SabhaTokens, UpdateMeetingInput, VerifyEmailInput };
package/dist/index.js CHANGED
@@ -166,6 +166,59 @@ function toSabhaError(error, fallback = "Sabha request failed") {
166
166
  // src/session.ts
167
167
  var SABHA_SESSION_HEADER = "x-sabha-session";
168
168
  var SABHA_SESSION_STORAGE_KEY = "sabha_vm_session";
169
+ var SABHA_TOKENS_STORAGE_KEY = "sabha_auth_tokens";
170
+ function readJson(key) {
171
+ try {
172
+ if (typeof localStorage === "undefined") return null;
173
+ const raw = localStorage.getItem(key);
174
+ if (!raw) return null;
175
+ return JSON.parse(raw);
176
+ } catch {
177
+ return null;
178
+ }
179
+ }
180
+ function writeJson(key, value) {
181
+ try {
182
+ if (typeof localStorage === "undefined") return;
183
+ if (value == null) localStorage.removeItem(key);
184
+ else localStorage.setItem(key, JSON.stringify(value));
185
+ } catch {
186
+ }
187
+ }
188
+ function readStoredTokens() {
189
+ const parsed = readJson(SABHA_TOKENS_STORAGE_KEY);
190
+ if (parsed && typeof parsed === "object") {
191
+ const record = parsed;
192
+ const tokens = {
193
+ accessToken: typeof record.accessToken === "string" ? record.accessToken : void 0,
194
+ refreshToken: typeof record.refreshToken === "string" ? record.refreshToken : void 0,
195
+ sessionCookie: typeof record.sessionCookie === "string" ? record.sessionCookie : void 0
196
+ };
197
+ if (tokens.accessToken || tokens.refreshToken || tokens.sessionCookie) {
198
+ return tokens;
199
+ }
200
+ }
201
+ const legacy = readStoredSessionCookie();
202
+ if (legacy) {
203
+ const migrated = { sessionCookie: legacy };
204
+ writeStoredTokens(migrated);
205
+ return migrated;
206
+ }
207
+ return null;
208
+ }
209
+ function writeStoredTokens(tokens) {
210
+ if (!tokens || !tokens.accessToken && !tokens.refreshToken && !tokens.sessionCookie) {
211
+ writeJson(SABHA_TOKENS_STORAGE_KEY, null);
212
+ writeStoredSessionCookie(null);
213
+ return;
214
+ }
215
+ writeJson(SABHA_TOKENS_STORAGE_KEY, {
216
+ accessToken: tokens.accessToken,
217
+ refreshToken: tokens.refreshToken,
218
+ sessionCookie: tokens.sessionCookie
219
+ });
220
+ writeStoredSessionCookie(tokens.sessionCookie ?? null);
221
+ }
169
222
  function readStoredSessionCookie() {
170
223
  try {
171
224
  if (typeof localStorage === "undefined") return null;
@@ -872,16 +925,19 @@ var SabhaClient = class {
872
925
  ...DEFAULT_MEDIA_POLICY,
873
926
  ...this.config.mediaPolicy
874
927
  };
875
- const stored = this.config.persistSession !== false ? readStoredSessionCookie() : null;
928
+ const stored = this.config.persistSession !== false ? readStoredTokens() : null;
876
929
  this.tokens = {
877
- accessToken: config.accessToken ?? this.tokens?.accessToken,
878
- refreshToken: config.refreshToken ?? this.tokens?.refreshToken,
879
- sessionCookie: config.sessionCookie ?? this.tokens?.sessionCookie ?? stored ?? void 0
930
+ accessToken: config.accessToken ?? this.tokens?.accessToken ?? stored?.accessToken,
931
+ refreshToken: config.refreshToken ?? this.tokens?.refreshToken ?? stored?.refreshToken,
932
+ sessionCookie: config.sessionCookie ?? this.tokens?.sessionCookie ?? stored?.sessionCookie ?? void 0
880
933
  };
881
934
  const hasAnyToken = Boolean(
882
935
  this.tokens.accessToken || this.tokens.sessionCookie || this.tokens.refreshToken
883
936
  );
884
937
  if (!hasAnyToken) this.tokens = null;
938
+ else if (this.config.persistSession !== false) {
939
+ this.persistTokens(this.tokens);
940
+ }
885
941
  this.http = new HttpClient({
886
942
  baseUrl,
887
943
  withCredentials: this.config.withCredentials !== false,
@@ -889,6 +945,9 @@ var SabhaClient = class {
889
945
  getTokens: () => this.tokens,
890
946
  setTokens: (tokens) => {
891
947
  this.tokens = tokens;
948
+ if (this.config.persistSession !== false) {
949
+ this.persistTokens(tokens);
950
+ }
892
951
  },
893
952
  onSessionCookie: (cookie) => {
894
953
  this.persistSessionCookie(cookie);
@@ -928,27 +987,24 @@ var SabhaClient = class {
928
987
  }
929
988
  setTokens(tokens) {
930
989
  this.ensureConfigured();
931
- this.tokens = tokens;
990
+ this.persistTokens(tokens);
932
991
  }
933
992
  clearSession() {
934
993
  this.tokens = null;
935
994
  this.user = null;
936
- this.persistSessionCookie(null);
995
+ this.persistTokens(null);
937
996
  this.activeConnection?.disconnect();
938
997
  this.activeConnection = null;
939
998
  }
940
999
  async login(input) {
941
1000
  const session = await this.auth().login(input);
942
1001
  this.applySession(session);
943
- if (session.accessToken) {
944
- this.persistSessionCookie(this.tokens?.sessionCookie ?? null);
945
- } else if (session.sessionCookie || this.tokens?.sessionCookie) {
946
- this.persistSessionCookie(session.sessionCookie ?? this.tokens?.sessionCookie ?? null);
947
- }
948
1002
  try {
949
1003
  const me = await this.auth().me();
950
1004
  this.user = me;
951
1005
  session.user = me;
1006
+ session.accessToken = this.tokens?.accessToken;
1007
+ session.refreshToken = this.tokens?.refreshToken;
952
1008
  session.sessionCookie = this.tokens?.sessionCookie;
953
1009
  return session;
954
1010
  } catch (error) {
@@ -958,7 +1014,7 @@ var SabhaClient = class {
958
1014
  if (!hasCredential) {
959
1015
  this.clearSession();
960
1016
  throw new SabhaError(
961
- "Login returned a user profile but no auth credential. Need JWT `token` from /api/auth/login (Postman) or Set-Cookie vm_session (exposed to the app as x-sabha-session via /sabha proxy). Without that, POST /api/meetings returns 401 Sign in first.",
1017
+ "Login returned a user profile but no auth credential. Need JWT `token` (+ optional `refreshToken`) from /api/auth/login as in Sabha-API Postman (Auth \u2192 Login). Without that, POST /api/meetings returns 401 Sign in first.",
962
1018
  {
963
1019
  code: "SESSION_NOT_ESTABLISHED",
964
1020
  status: 401,
@@ -975,7 +1031,7 @@ var SabhaClient = class {
975
1031
  return await this.me();
976
1032
  } catch (error) {
977
1033
  throw new SabhaError(
978
- "Not signed in to Sabha. Call login() first, and ensure the `vm_session` cookie is sent (credentials: 'include', CORS allow-credentials, allow-listed Origin).",
1034
+ "Not signed in to Sabha. Call login() first so Authorization: Bearer <accessToken> is sent (Postman Auth \u2192 Login stores json.token).",
979
1035
  {
980
1036
  code: "UNAUTHENTICATED",
981
1037
  status: 401,
@@ -1097,30 +1153,36 @@ var SabhaClient = class {
1097
1153
  refreshToken: session.refreshToken ?? this.tokens?.refreshToken,
1098
1154
  sessionCookie: session.sessionCookie ?? this.tokens?.sessionCookie
1099
1155
  };
1100
- if (this.tokens.sessionCookie) {
1101
- this.persistSessionCookie(this.tokens.sessionCookie);
1156
+ this.persistTokens(this.tokens);
1157
+ }
1158
+ persistTokens(tokens) {
1159
+ this.tokens = tokens;
1160
+ if (this.config.persistSession !== false) {
1161
+ writeStoredTokens(tokens);
1102
1162
  }
1103
1163
  }
1104
1164
  persistSessionCookie(cookie) {
1105
1165
  if (cookie) {
1106
- this.tokens = {
1166
+ this.persistTokens({
1107
1167
  ...this.tokens ?? {},
1108
1168
  sessionCookie: cookie
1109
- };
1110
- } else if (this.tokens) {
1111
- const { sessionCookie: _removed, ...rest } = this.tokens;
1112
- this.tokens = Object.keys(rest).length ? rest : null;
1169
+ });
1170
+ return;
1113
1171
  }
1114
- if (this.config.persistSession !== false) {
1115
- writeStoredSessionCookie(cookie ?? null);
1172
+ if (!this.tokens) {
1173
+ this.persistTokens(null);
1174
+ return;
1116
1175
  }
1176
+ const { sessionCookie: _removed, ...rest } = this.tokens;
1177
+ this.persistTokens(Object.keys(rest).length ? rest : null);
1117
1178
  }
1118
1179
  async tryRefresh() {
1119
1180
  if (!this.tokens?.refreshToken) return false;
1120
1181
  if (this.refreshPromise) return this.refreshPromise;
1121
1182
  this.refreshPromise = (async () => {
1122
1183
  try {
1123
- await this.refreshSession();
1184
+ const tokens = await this.refreshSession();
1185
+ this.persistTokens({ ...this.tokens ?? {}, ...tokens });
1124
1186
  return true;
1125
1187
  } catch {
1126
1188
  return false;
@@ -1201,8 +1263,10 @@ function SabhaProvider({
1201
1263
  const [error, setError] = react.useState(null);
1202
1264
  react.useEffect(() => {
1203
1265
  client.configure(resolvedConfig);
1204
- setAuthenticated(client.getStatus().authenticated);
1205
- setUser(client.getUser());
1266
+ setAuthenticated(false);
1267
+ setUser(null);
1268
+ setError(null);
1269
+ setMeetings([]);
1206
1270
  setReady(true);
1207
1271
  }, [
1208
1272
  client,
@@ -1245,12 +1309,26 @@ function SabhaProvider({
1245
1309
  }, [client]);
1246
1310
  react.useEffect(() => {
1247
1311
  if (!ready || !autoLoadMeetings) return;
1248
- void client.me().then((me) => {
1312
+ let cancelled = false;
1313
+ void client.me().then(async (me) => {
1314
+ if (cancelled) return;
1249
1315
  setUser(me);
1250
1316
  setAuthenticated(true);
1251
- return refreshMeetings();
1317
+ try {
1318
+ await refreshMeetings();
1319
+ } catch {
1320
+ }
1252
1321
  }).catch(() => {
1322
+ if (cancelled) return;
1323
+ client.clearSession();
1324
+ setAuthenticated(false);
1325
+ setUser(null);
1326
+ setMeetings([]);
1327
+ setError(null);
1253
1328
  });
1329
+ return () => {
1330
+ cancelled = true;
1331
+ };
1254
1332
  }, [ready, autoLoadMeetings, client, refreshMeetings]);
1255
1333
  const createMeeting = react.useCallback(
1256
1334
  async (input) => {
@@ -1516,15 +1594,18 @@ exports.MediaController = MediaController;
1516
1594
  exports.MeetingConnection = MeetingConnection;
1517
1595
  exports.SABHA_SESSION_HEADER = SABHA_SESSION_HEADER;
1518
1596
  exports.SABHA_SESSION_STORAGE_KEY = SABHA_SESSION_STORAGE_KEY;
1597
+ exports.SABHA_TOKENS_STORAGE_KEY = SABHA_TOKENS_STORAGE_KEY;
1519
1598
  exports.SabhaClient = SabhaClient;
1520
1599
  exports.SabhaError = SabhaError;
1521
1600
  exports.SabhaProvider = SabhaProvider;
1522
1601
  exports.createSabhaClient = createSabhaClient;
1523
1602
  exports.normalizeMeeting = normalizeMeeting;
1524
1603
  exports.readStoredSessionCookie = readStoredSessionCookie;
1604
+ exports.readStoredTokens = readStoredTokens;
1525
1605
  exports.toSabhaError = toSabhaError;
1526
1606
  exports.useSabha = useSabha;
1527
1607
  exports.useSabhaMeetings = useSabhaMeetings;
1528
1608
  exports.writeStoredSessionCookie = writeStoredSessionCookie;
1609
+ exports.writeStoredTokens = writeStoredTokens;
1529
1610
  //# sourceMappingURL=index.js.map
1530
1611
  //# sourceMappingURL=index.js.map