@strands.gg/accui 2.17.60 → 2.17.62

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.
@@ -1,5 +1,5 @@
1
- import { computed as u, getCurrentInstance as he, onUnmounted as ge, ref as h } from "vue";
2
- import { u as ve } from "./useStrandsConfig-B2UXxIbT.es.js";
1
+ import { computed as c, getCurrentInstance as ge, onUnmounted as ve, ref as h } from "vue";
2
+ import { u as me } from "./useStrandsConfig-B2UXxIbT.es.js";
3
3
  class we {
4
4
  cache = /* @__PURE__ */ new Map();
5
5
  DEFAULT_TTL = 300 * 1e3;
@@ -7,20 +7,20 @@ class we {
7
7
  /**
8
8
  * Memoized fetch - prevents duplicate requests and caches results
9
9
  */
10
- async fetch(d, m, w = this.DEFAULT_TTL) {
10
+ async fetch(d, w, m = this.DEFAULT_TTL) {
11
11
  const E = Date.now(), s = this.cache.get(d);
12
12
  if (s && E - s.timestamp < s.ttl)
13
13
  return s.promise;
14
14
  this.cleanExpired();
15
- const f = m().finally(() => {
15
+ const f = w().finally(() => {
16
16
  setTimeout(() => {
17
17
  this.cache.delete(d);
18
- }, w);
18
+ }, m);
19
19
  });
20
20
  return this.cache.set(d, {
21
21
  promise: f,
22
22
  timestamp: E,
23
- ttl: w
23
+ ttl: m
24
24
  }), f;
25
25
  }
26
26
  /**
@@ -40,8 +40,8 @@ class we {
40
40
  */
41
41
  cleanExpired() {
42
42
  const d = Date.now();
43
- for (const [m, w] of this.cache.entries())
44
- d - w.timestamp > w.ttl && this.cache.delete(m);
43
+ for (const [w, m] of this.cache.entries())
44
+ d - m.timestamp > m.ttl && this.cache.delete(w);
45
45
  }
46
46
  /**
47
47
  * Get cache statistics (for debugging)
@@ -54,7 +54,7 @@ class we {
54
54
  }
55
55
  }
56
56
  const y = new we();
57
- function me() {
57
+ function ye() {
58
58
  return {
59
59
  fetch: y.fetch.bind(y),
60
60
  clear: y.clear.bind(y),
@@ -62,34 +62,34 @@ function me() {
62
62
  getStats: y.getStats.bind(y)
63
63
  };
64
64
  }
65
- function ye(a, d) {
66
- let m = null;
67
- return (...w) => {
68
- m && clearTimeout(m), m = setTimeout(() => {
69
- a(...w);
65
+ function pe(n, d) {
66
+ let w = null;
67
+ return (...m) => {
68
+ w && clearTimeout(w), w = setTimeout(() => {
69
+ n(...m);
70
70
  }, d);
71
71
  };
72
72
  }
73
- const C = ye((a, d) => {
74
- typeof window < "u" && localStorage.setItem(a, d);
75
- }, 300), k = (a) => ({
76
- id: a.id,
77
- email: a.email,
78
- firstName: a.first_name || a.firstName || "",
79
- lastName: a.last_name || a.lastName || "",
80
- avatar: a.avatar_url || a.avatar,
81
- mfaEnabled: a.mfa_enabled ?? a.mfaEnabled ?? !1,
82
- emailVerified: a.email_verified ?? a.emailVerified ?? !1,
83
- passwordUpdatedAt: a.password_updated_at || a.passwordUpdatedAt,
84
- settings: a.settings || {},
85
- xp: a.xp || 0,
86
- level: a.level || 1,
87
- next_level_xp: a.next_level_xp || a.next_level_xp || 4,
88
- username: a.username,
89
- usernameLastChangedAt: a.username_last_changed_at || a.usernameLastChangedAt,
90
- createdAt: a.created_at || a.createdAt,
91
- updatedAt: a.updated_at || a.updatedAt || (/* @__PURE__ */ new Date()).toISOString()
92
- }), pe = () => {
73
+ const N = pe((n, d) => {
74
+ typeof window < "u" && localStorage.setItem(n, d);
75
+ }, 300), k = (n) => ({
76
+ id: n.id,
77
+ email: n.email,
78
+ firstName: n.first_name || n.firstName || "",
79
+ lastName: n.last_name || n.lastName || "",
80
+ avatar: n.avatar_url || n.avatar,
81
+ mfaEnabled: n.mfa_enabled ?? n.mfaEnabled ?? !1,
82
+ emailVerified: n.email_verified ?? n.emailVerified ?? !1,
83
+ passwordUpdatedAt: n.password_updated_at || n.passwordUpdatedAt,
84
+ settings: n.settings || {},
85
+ xp: n.xp || 0,
86
+ level: n.level || 1,
87
+ next_level_xp: n.next_level_xp || n.next_level_xp || 4,
88
+ username: n.username,
89
+ usernameLastChangedAt: n.username_last_changed_at || n.usernameLastChangedAt,
90
+ createdAt: n.created_at || n.createdAt,
91
+ updatedAt: n.updated_at || n.updatedAt || (/* @__PURE__ */ new Date()).toISOString()
92
+ }), $ = () => {
93
93
  if (typeof window > "u")
94
94
  return {
95
95
  currentUser: h(null),
@@ -110,10 +110,13 @@ const C = ye((a, d) => {
110
110
  availableMfaMethods: h([]),
111
111
  promise: null,
112
112
  refreshTimer: null,
113
- refreshPromise: null
113
+ refreshPromise: null,
114
+ refreshTokenFn: null,
115
+ startTimerFn: null,
116
+ stopTimerFn: null
114
117
  };
115
- const a = window;
116
- return a.__STRANDS_AUTH_STATE__ || (a.__STRANDS_AUTH_STATE__ = {
118
+ const n = window;
119
+ return n.__STRANDS_AUTH_STATE__ || (n.__STRANDS_AUTH_STATE__ = {
117
120
  currentUser: h(null),
118
121
  currentSession: h(null),
119
122
  loadingStates: h({
@@ -132,27 +135,30 @@ const C = ye((a, d) => {
132
135
  availableMfaMethods: h([]),
133
136
  promise: null,
134
137
  refreshTimer: null,
135
- refreshPromise: null
136
- }), a.__STRANDS_AUTH_STATE__;
137
- }, c = pe();
138
+ refreshPromise: null,
139
+ refreshTokenFn: null,
140
+ startTimerFn: null,
141
+ stopTimerFn: null
142
+ }), n.__STRANDS_AUTH_STATE__;
143
+ }, l = $();
138
144
  function _e() {
139
- const { getUrl: a, config: d } = ve(), { fetch: m, clear: w, invalidate: E } = me(), { currentUser: s, currentSession: f, loadingStates: i, isInitialized: p, mfaRequired: T, mfaSessionId: g, availableMfaMethods: S } = c, I = () => {
140
- if (s.value = null, f.value = null, T.value = !1, g.value = null, S.value = [], A(), c.refreshPromise = null, w(), typeof window < "u" && d.value?.onSignOutUrl) {
145
+ const { getUrl: n, config: d } = me(), { fetch: w, clear: m, invalidate: E } = ye(), { currentUser: s, currentSession: f, loadingStates: i, isInitialized: p, mfaRequired: T, mfaSessionId: g, availableMfaMethods: S } = l, M = () => {
146
+ if (s.value = null, f.value = null, T.value = !1, g.value = null, S.value = [], A(), l.refreshPromise = null, m(), typeof window < "u" && d.value?.onSignOutUrl) {
141
147
  const t = window.location.pathname + window.location.search, e = d.value.onSignOutUrl;
142
148
  t !== e && (window.location.href = e);
143
149
  }
144
- }, j = u(() => i.value.initializing), N = u(() => i.value.signingIn), F = u(() => i.value.signingUp), R = u(() => i.value.signingOut), z = u(() => i.value.refreshingToken), J = u(() => i.value.sendingMfaEmail), U = u(() => i.value.verifyingMfa);
145
- u(() => i.value.loadingProfile);
146
- const D = u(
150
+ }, C = c(() => i.value.initializing), j = c(() => i.value.signingIn), R = c(() => i.value.signingUp), z = c(() => i.value.signingOut), J = c(() => i.value.refreshingToken), U = c(() => i.value.sendingMfaEmail), L = c(() => i.value.verifyingMfa);
151
+ c(() => i.value.loadingProfile);
152
+ const D = c(
147
153
  () => i.value.signingIn || i.value.signingUp || i.value.signingOut || i.value.refreshingToken || i.value.sendingMfaEmail || i.value.verifyingMfa || i.value.loadingProfile
148
- ), L = u(() => i.value.initializing || D.value), q = u(() => {
154
+ ), V = c(() => i.value.initializing || D.value), q = c(() => {
149
155
  const t = i.value;
150
156
  return t.initializing ? "Checking authentication..." : t.signingIn ? "Signing you in..." : t.signingUp ? "Creating your account..." : t.signingOut ? "Signing you out..." : t.refreshingToken ? "Refreshing session..." : t.sendingMfaEmail ? "Sending verification code..." : t.verifyingMfa ? "Verifying code..." : t.loadingProfile ? "Loading profile..." : "Loading...";
151
157
  }), H = () => ({
152
158
  "Content-Type": "application/json"
153
- }), V = async () => {
159
+ }), G = async () => {
154
160
  try {
155
- const t = await fetch(a("authStatus"), {
161
+ const t = await fetch(n("authStatus"), {
156
162
  method: "GET",
157
163
  credentials: "include"
158
164
  });
@@ -161,13 +167,13 @@ function _e() {
161
167
  const e = await t.json();
162
168
  if (e.authenticated && e.user) {
163
169
  s.value = k(e.user);
164
- const n = e.expires_at ? new Date(e.expires_at * 1e3) : new Date(Date.now() + 300 * 1e3);
170
+ const a = e.expires_at ? new Date(e.expires_at * 1e3) : new Date(Date.now() + 300 * 1e3);
165
171
  return f.value = {
166
172
  accessToken: "",
167
173
  // Token is in HttpOnly cookie
168
174
  refreshToken: "",
169
175
  // Token is in HttpOnly cookie
170
- expiresAt: n,
176
+ expiresAt: a,
171
177
  userId: e.user.id
172
178
  }, !0;
173
179
  }
@@ -175,8 +181,8 @@ function _e() {
175
181
  } catch {
176
182
  return !1;
177
183
  }
178
- }, G = async (t, e, n) => {
179
- const r = await fetch(a("mfaHardwareCompleteRegistration"), {
184
+ }, B = async (t, e, a) => {
185
+ const r = await fetch(n("mfaHardwareCompleteRegistration"), {
180
186
  method: "POST",
181
187
  headers: {
182
188
  "Content-Type": "application/json"
@@ -188,19 +194,19 @@ function _e() {
188
194
  })
189
195
  });
190
196
  if (!r.ok) {
191
- const l = await r.text();
197
+ const u = await r.text();
192
198
  let o = "Failed to complete hardware key registration";
193
199
  try {
194
- const v = JSON.parse(l);
195
- o = v.message || v.error || l;
200
+ const v = JSON.parse(u);
201
+ o = v.message || v.error || u;
196
202
  } catch {
197
- o = l || "Failed to complete hardware key registration";
203
+ o = u || "Failed to complete hardware key registration";
198
204
  }
199
205
  throw new Error(o);
200
206
  }
201
207
  return r.json();
202
- }, K = async (t, e, n = "hardware") => {
203
- const r = await fetch(a("mfaHardwareStartRegistration"), {
208
+ }, K = async (t, e, a = "hardware") => {
209
+ const r = await fetch(n("mfaHardwareStartRegistration"), {
204
210
  method: "POST",
205
211
  headers: {
206
212
  "Content-Type": "application/json"
@@ -208,22 +214,22 @@ function _e() {
208
214
  credentials: "include",
209
215
  body: JSON.stringify({
210
216
  device_name: t,
211
- device_type: n
217
+ device_type: a
212
218
  })
213
219
  });
214
220
  if (!r.ok) {
215
- const l = await r.text();
221
+ const u = await r.text();
216
222
  let o = "Failed to start hardware key registration";
217
223
  try {
218
- const v = JSON.parse(l);
219
- o = v.message || v.error || l;
224
+ const v = JSON.parse(u);
225
+ o = v.message || v.error || u;
220
226
  } catch {
221
- o = l || "Failed to start hardware key registration";
227
+ o = u || "Failed to start hardware key registration";
222
228
  }
223
229
  throw new Error(o);
224
230
  }
225
231
  return r.json();
226
- }, W = u(() => s.value !== null), B = async (t) => {
232
+ }, W = c(() => s.value !== null), Y = async (t) => {
227
233
  i.value.signingIn = !0;
228
234
  try {
229
235
  T.value = !1, g.value = null, S.value = [];
@@ -231,19 +237,19 @@ function _e() {
231
237
  "Content-Type": "application/json"
232
238
  };
233
239
  typeof window < "u" && window.location && (e.Origin = window.location.origin);
234
- const n = await fetch(a("signIn"), {
240
+ const a = await fetch(n("signIn"), {
235
241
  method: "POST",
236
242
  headers: e,
237
243
  credentials: "include",
238
244
  // Include cookies for auth
239
245
  body: JSON.stringify(t)
240
246
  });
241
- if (!n.ok)
242
- throw n.status === 401 ? new Error("Invalid email or password") : n.status === 403 ? new Error("Please verify your email address before signing in") : new Error(`Sign in failed: ${n.status} ${n.statusText}`);
243
- const r = await n.json();
247
+ if (!a.ok)
248
+ throw a.status === 401 ? new Error("Invalid email or password") : a.status === 403 ? new Error("Please verify your email address before signing in") : new Error(`Sign in failed: ${a.status} ${a.statusText}`);
249
+ const r = await a.json();
244
250
  if (r.mfa_required) {
245
251
  T.value = !0, g.value = r.mfa_session_id || null;
246
- const l = (r.available_mfa_methods || []).map((o) => {
252
+ const u = (r.available_mfa_methods || []).map((o) => {
247
253
  let v = `${o.device_type.charAt(0).toUpperCase() + o.device_type.slice(1)} Authentication`;
248
254
  return o.device_type === "hardware" ? v = o.device_name || "Security Key" : o.device_type === "totp" ? v = o.device_name || "Authenticator App" : o.device_type === "email" && (v = o.device_name || "Email Verification"), {
249
255
  id: o.device_id,
@@ -257,39 +263,39 @@ function _e() {
257
263
  device_info: o.device_info
258
264
  };
259
265
  });
260
- return S.value = l, i.value.signingIn = !1, r;
266
+ return S.value = u, i.value.signingIn = !1, r;
261
267
  }
262
- return await P(r), r;
268
+ return await x(r), r;
263
269
  } catch (e) {
264
270
  throw e;
265
271
  } finally {
266
272
  i.value.signingIn = !1;
267
273
  }
268
- }, Y = async (t) => {
274
+ }, Q = async (t) => {
269
275
  i.value.signingUp = !0;
270
276
  try {
271
277
  throw new Error("Sign up not implemented - please integrate with auth SDK");
272
278
  } finally {
273
279
  i.value.signingUp = !1;
274
280
  }
275
- }, Q = async () => {
281
+ }, X = async () => {
276
282
  i.value.signingOut = !0;
277
283
  try {
278
- await fetch(a("signOut"), {
284
+ await (await fetch(n("signOut"), {
279
285
  method: "POST",
280
286
  credentials: "include"
281
287
  // Cookies will be cleared by server response
282
- }), A(), c.refreshPromise = null, w(), s.value = null, f.value = null, T.value = !1, g.value = null, S.value = [], typeof window < "u" && d.value?.onSignOutUrl && (window.location.href = d.value.onSignOutUrl);
288
+ })).text(), A(), l.refreshPromise = null, m(), s.value = null, f.value = null, T.value = !1, g.value = null, S.value = [], p.value = !1, typeof window < "u" && d.value?.onSignOutUrl && (window.location.href = d.value.onSignOutUrl);
283
289
  } finally {
284
290
  i.value.signingOut = !1;
285
291
  }
286
292
  }, O = async () => {
287
- if (c.refreshPromise)
288
- return await c.refreshPromise;
289
- c.refreshPromise = (async () => {
293
+ if (l.refreshPromise)
294
+ return await l.refreshPromise;
295
+ l.refreshPromise = (async () => {
290
296
  i.value.refreshingToken = !0;
291
297
  try {
292
- const e = await fetch(a("refresh"), {
298
+ const e = await fetch(n("refresh"), {
293
299
  method: "POST",
294
300
  headers: {
295
301
  "Content-Type": "application/json"
@@ -299,11 +305,11 @@ function _e() {
299
305
  });
300
306
  if (!e.ok) {
301
307
  if (e.status === 401)
302
- return I(), !1;
308
+ return M(), !1;
303
309
  throw new Error(`Token refresh failed: ${e.status} ${e.statusText}`);
304
310
  }
305
- const n = await e.json();
306
- n.user && (s.value = k(n.user));
311
+ const a = await e.json();
312
+ a.user && (s.value = k(a.user));
307
313
  const r = {
308
314
  accessToken: "",
309
315
  // Token is in HttpOnly cookie
@@ -311,23 +317,23 @@ function _e() {
311
317
  // Token is in HttpOnly cookie
312
318
  expiresAt: new Date(Date.now() + 300 * 1e3),
313
319
  // 5 minutes from now
314
- userId: n.user?.id || s.value?.id
320
+ userId: a.user?.id || s.value?.id
315
321
  };
316
322
  return f.value = r, _(), E(`sessions:${s.value?.id || "unknown"}`), !0;
317
323
  } catch {
318
- return I(), !1;
324
+ return M(), !1;
319
325
  } finally {
320
326
  i.value.refreshingToken = !1;
321
327
  }
322
328
  })();
323
- const t = await c.refreshPromise;
324
- return c.refreshPromise = null, t;
325
- }, X = async () => {
329
+ const t = await l.refreshPromise;
330
+ return l.refreshPromise = null, t;
331
+ }, Z = async () => {
326
332
  const t = `profile:${f.value.accessToken.slice(0, 20)}`;
327
333
  i.value.loadingProfile = !0;
328
334
  try {
329
- return await m(t, async () => {
330
- const e = await fetch(a("profile"), {
335
+ return await w(t, async () => {
336
+ const e = await fetch(n("profile"), {
331
337
  method: "GET",
332
338
  headers: {
333
339
  "Content-Type": "application/json",
@@ -336,16 +342,16 @@ function _e() {
336
342
  });
337
343
  if (!e.ok)
338
344
  throw e.status === 401 ? new Error("Authentication expired. Please sign in again.") : new Error(`Failed to fetch profile: ${e.status} ${e.statusText}`);
339
- const n = await e.json();
340
- return s.value = k(n), s.value && typeof window < "u" && localStorage.setItem("strands_auth_user", JSON.stringify(s.value)), s.value;
345
+ const a = await e.json();
346
+ return s.value = k(a), s.value && typeof window < "u" && localStorage.setItem("strands_auth_user", JSON.stringify(s.value)), s.value;
341
347
  });
342
348
  } finally {
343
349
  i.value.loadingProfile = !1;
344
350
  }
345
- }, Z = async (t) => {
351
+ }, ee = async (t) => {
346
352
  i.value.loadingProfile = !0;
347
353
  try {
348
- const e = await fetch(a("profile"), {
354
+ const e = await fetch(n("profile"), {
349
355
  method: "POST",
350
356
  headers: {
351
357
  "Content-Type": "application/json",
@@ -358,15 +364,15 @@ function _e() {
358
364
  });
359
365
  if (!e.ok)
360
366
  throw e.status === 401 ? new Error("Authentication expired. Please sign in again.") : new Error(`Profile update failed: ${e.status} ${e.statusText}`);
361
- const n = await e.json();
362
- return s.value = k(n), s.value && C("strands_auth_user", JSON.stringify(s.value)), s.value;
367
+ const a = await e.json();
368
+ return s.value = k(a), s.value && N("strands_auth_user", JSON.stringify(s.value)), s.value;
363
369
  } finally {
364
370
  i.value.loadingProfile = !1;
365
371
  }
366
- }, ee = async (t) => {
372
+ }, te = async (t) => {
367
373
  i.value.loadingProfile = !0;
368
374
  try {
369
- const e = await fetch(a("settings"), {
375
+ const e = await fetch(n("settings"), {
370
376
  method: "POST",
371
377
  headers: {
372
378
  "Content-Type": "application/json",
@@ -378,15 +384,15 @@ function _e() {
378
384
  });
379
385
  if (!e.ok)
380
386
  throw e.status === 401 ? new Error("Authentication expired. Please sign in again.") : new Error(`Settings update failed: ${e.status} ${e.statusText}`);
381
- const n = await e.json();
382
- return s.value = k(n), s.value && C("strands_auth_user", JSON.stringify(s.value)), s.value;
387
+ const a = await e.json();
388
+ return s.value = k(a), s.value && N("strands_auth_user", JSON.stringify(s.value)), s.value;
383
389
  } finally {
384
390
  i.value.loadingProfile = !1;
385
391
  }
386
- }, te = async (t, e) => {
392
+ }, ne = async (t, e) => {
387
393
  i.value.loadingProfile = !0;
388
394
  try {
389
- const n = await fetch(a("changeEmail"), {
395
+ const a = await fetch(n("changeEmail"), {
390
396
  method: "POST",
391
397
  headers: {
392
398
  "Content-Type": "application/json",
@@ -397,15 +403,15 @@ function _e() {
397
403
  password: e
398
404
  })
399
405
  });
400
- if (!n.ok) {
401
- if (n.status === 401)
406
+ if (!a.ok) {
407
+ if (a.status === 401)
402
408
  throw new Error("Authentication expired. Please sign in again.");
403
409
  {
404
- const l = await n.json().catch(() => ({}));
405
- throw new Error(l.message || `Email change failed: ${n.status} ${n.statusText}`);
410
+ const u = await a.json().catch(() => ({}));
411
+ throw new Error(u.message || `Email change failed: ${a.status} ${a.statusText}`);
406
412
  }
407
413
  }
408
- const r = await n.json();
414
+ const r = await a.json();
409
415
  return s.value && (s.value = {
410
416
  ...s.value,
411
417
  email: t,
@@ -416,39 +422,39 @@ function _e() {
416
422
  } finally {
417
423
  i.value.loadingProfile = !1;
418
424
  }
419
- }, ae = async (t, e, n = !1) => {
425
+ }, ae = async (t, e, a = !1) => {
420
426
  if (!g.value)
421
427
  throw new Error("No MFA session available");
422
428
  i.value.verifyingMfa = !0;
423
429
  try {
424
- const r = a(n ? "mfaBackupCodeVerify" : "mfaSigninVerify"), l = n ? { mfa_session_id: g.value, backup_code: e } : { mfa_session_id: g.value, device_id: t, code: e }, o = await fetch(r, {
430
+ const r = n(a ? "mfaBackupCodeVerify" : "mfaSigninVerify"), u = a ? { mfa_session_id: g.value, backup_code: e } : { mfa_session_id: g.value, device_id: t, code: e }, o = await fetch(r, {
425
431
  method: "POST",
426
432
  headers: { "Content-Type": "application/json" },
427
433
  credentials: "include",
428
- body: JSON.stringify(l)
434
+ body: JSON.stringify(u)
429
435
  });
430
436
  if (!o.ok) {
431
- const b = await o.text();
432
- let M = "MFA verification failed";
437
+ const P = await o.text();
438
+ let b = "MFA verification failed";
433
439
  try {
434
- const $ = JSON.parse(b);
435
- M = $.message || $.error || b;
440
+ const F = JSON.parse(P);
441
+ b = F.message || F.error || P;
436
442
  } catch {
437
- M = b || "MFA verification failed";
443
+ b = P || "MFA verification failed";
438
444
  }
439
- throw new Error(M);
445
+ throw new Error(b);
440
446
  }
441
447
  const v = await o.json();
442
- return T.value = !1, g.value = null, S.value = [], await P(v), v;
448
+ return T.value = !1, g.value = null, S.value = [], await x(v), v;
443
449
  } finally {
444
450
  i.value.verifyingMfa = !1;
445
451
  }
446
- }, ne = async (t) => {
452
+ }, ie = async (t) => {
447
453
  if (!g.value)
448
454
  throw new Error("No MFA session available");
449
455
  i.value.sendingMfaEmail = !0;
450
456
  try {
451
- const e = await fetch(a("mfaSigninSendEmail"), {
457
+ const e = await fetch(n("mfaSigninSendEmail"), {
452
458
  method: "POST",
453
459
  headers: { "Content-Type": "application/json" },
454
460
  credentials: "include",
@@ -459,23 +465,23 @@ function _e() {
459
465
  });
460
466
  if (!e.ok) {
461
467
  const r = await e.text();
462
- let l = "Failed to send MFA email code";
468
+ let u = "Failed to send MFA email code";
463
469
  try {
464
470
  const o = JSON.parse(r);
465
- l = o.message || o.error || r;
471
+ u = o.message || o.error || r;
466
472
  } catch {
467
- l = r || "Failed to send MFA email code";
473
+ u = r || "Failed to send MFA email code";
468
474
  }
469
- throw new Error(l);
475
+ throw new Error(u);
470
476
  }
471
477
  return await e.json();
472
478
  } finally {
473
479
  i.value.sendingMfaEmail = !1;
474
480
  }
475
- }, ie = async (t) => {
481
+ }, se = async (t) => {
476
482
  if (!g.value)
477
483
  throw new Error("No MFA session available");
478
- const e = await fetch(a("mfaWebAuthnChallenge"), {
484
+ const e = await fetch(n("mfaWebAuthnChallenge"), {
479
485
  method: "POST",
480
486
  headers: { "Content-Type": "application/json" },
481
487
  credentials: "include",
@@ -485,18 +491,18 @@ function _e() {
485
491
  })
486
492
  });
487
493
  if (!e.ok) {
488
- const n = await e.text();
494
+ const a = await e.text();
489
495
  let r = "Failed to get WebAuthn challenge";
490
496
  try {
491
- const l = JSON.parse(n);
492
- r = l.message || l.error || n;
497
+ const u = JSON.parse(a);
498
+ r = u.message || u.error || a;
493
499
  } catch {
494
- r = n || r;
500
+ r = a || r;
495
501
  }
496
502
  throw new Error(r);
497
503
  }
498
504
  return e.json();
499
- }, P = async (t) => {
505
+ }, x = async (t) => {
500
506
  try {
501
507
  t.user && (s.value = k(t.user));
502
508
  const e = {
@@ -512,44 +518,46 @@ function _e() {
512
518
  } catch {
513
519
  }
514
520
  }, _ = () => {
515
- if (c.refreshTimer && clearTimeout(c.refreshTimer), !f.value || typeof document < "u" && document.visibilityState === "hidden")
521
+ if (l.refreshTimer && clearTimeout(l.refreshTimer), !f.value || typeof document < "u" && document.visibilityState === "hidden")
516
522
  return;
517
- const t = /* @__PURE__ */ new Date(), n = f.value.expiresAt.getTime() - t.getTime() - 60 * 1e3;
518
- if (n <= 0) {
523
+ const t = /* @__PURE__ */ new Date(), a = f.value.expiresAt.getTime() - t.getTime() - 60 * 1e3;
524
+ if (a <= 0) {
519
525
  O();
520
526
  return;
521
527
  }
522
- c.refreshTimer = setTimeout(async () => {
528
+ l.refreshTimer = setTimeout(async () => {
523
529
  (typeof document > "u" || document.visibilityState === "visible") && await O() && _();
524
- }, n);
530
+ }, a);
525
531
  }, A = () => {
526
- c.refreshTimer && (clearTimeout(c.refreshTimer), c.refreshTimer = null);
527
- }, x = async () => {
532
+ l.refreshTimer && (clearTimeout(l.refreshTimer), l.refreshTimer = null);
533
+ };
534
+ l.refreshTokenFn = O, l.startTimerFn = _, l.stopTimerFn = A;
535
+ const I = async () => {
528
536
  if (p.value) {
529
537
  i.value.initializing = !1;
530
538
  return;
531
539
  }
532
- if (c.promise) {
533
- await c.promise;
540
+ if (l.promise) {
541
+ await l.promise;
534
542
  return;
535
543
  }
536
544
  i.value.initializing = !0;
537
545
  const t = async () => {
538
546
  try {
539
547
  typeof window < "u" && (await Promise.race([
540
- V(),
548
+ G(),
541
549
  new Promise((r) => setTimeout(() => r(!1), 5e3))
542
550
  ]) ? _() : (s.value = null, f.value = null)), p.value = !0, await new Promise((e) => setTimeout(e, 50));
543
551
  } catch {
544
552
  } finally {
545
- i.value.initializing = !1, c.promise = null;
553
+ i.value.initializing = !1, l.promise = null;
546
554
  }
547
555
  };
548
- return c.promise = t(), c.promise;
549
- }, se = async (t) => {
556
+ return l.promise = t(), l.promise;
557
+ }, re = async (t) => {
550
558
  i.value.loadingProfile = !0;
551
559
  try {
552
- const e = await fetch(a("changeUsername"), {
560
+ const e = await fetch(n("changeUsername"), {
553
561
  method: "POST",
554
562
  headers: {
555
563
  "Content-Type": "application/json"
@@ -563,39 +571,39 @@ function _e() {
563
571
  const r = await e.json().catch(() => ({}));
564
572
  throw e.status === 409 ? new Error("Username is already taken") : r.cooldown_end ? new Error(`You can only change your username once every 30 days. You can change it again on ${new Date(r.cooldown_end).toLocaleDateString()}`) : new Error(r.message || `Username change failed: ${e.status} ${e.statusText}`);
565
573
  }
566
- const n = await e.json();
574
+ const a = await e.json();
567
575
  return s.value && (s.value = {
568
576
  ...s.value,
569
577
  username: t,
570
578
  usernameLastChangedAt: (/* @__PURE__ */ new Date()).toISOString(),
571
579
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
572
- }), n;
580
+ }), a;
573
581
  } finally {
574
582
  i.value.loadingProfile = !1;
575
583
  }
576
- }, re = async () => {
577
- const t = await fetch(a("usernameCooldown"), {
584
+ }, oe = async () => {
585
+ const t = await fetch(n("usernameCooldown"), {
578
586
  method: "GET",
579
587
  credentials: "include"
580
588
  });
581
589
  if (!t.ok)
582
590
  throw new Error(`Failed to get username cooldown: ${t.status} ${t.statusText}`);
583
591
  return t.json();
584
- }, oe = async (t) => {
585
- const e = a("checkUsernameAvailability").replace("{username}", encodeURIComponent(t)), n = await fetch(e, {
592
+ }, le = async (t) => {
593
+ const e = n("checkUsernameAvailability").replace("{username}", encodeURIComponent(t)), a = await fetch(e, {
586
594
  method: "GET",
587
595
  headers: {
588
596
  "Content-Type": "application/json"
589
597
  }
590
598
  });
591
- if (!n.ok)
592
- throw new Error(`Failed to check username availability: ${n.status} ${n.statusText}`);
593
- return n.json();
594
- }, le = async () => {
599
+ if (!a.ok)
600
+ throw new Error(`Failed to check username availability: ${a.status} ${a.statusText}`);
601
+ return a.json();
602
+ }, ue = async () => {
595
603
  const t = `sessions:${s.value?.id || "no-user"}`;
596
604
  try {
597
- return await m(t, async () => {
598
- const e = await fetch(a("sessions"), {
605
+ return await w(t, async () => {
606
+ const e = await fetch(n("sessions"), {
599
607
  method: "GET",
600
608
  credentials: "include"
601
609
  });
@@ -606,24 +614,24 @@ function _e() {
606
614
  } catch (e) {
607
615
  throw e;
608
616
  }
609
- }, ue = async () => {
610
- const t = await fetch(a("sessionsStats"), {
617
+ }, ce = async () => {
618
+ const t = await fetch(n("sessionsStats"), {
611
619
  method: "GET",
612
620
  credentials: "include"
613
621
  });
614
622
  if (!t.ok)
615
623
  throw new Error(`Failed to get session stats: ${t.status} ${t.statusText}`);
616
624
  return t.json();
617
- }, ce = async (t) => {
618
- const e = a("sessionRevoke").replace("{session_id}", encodeURIComponent(t)), n = await fetch(e, {
625
+ }, fe = async (t) => {
626
+ const e = n("sessionRevoke").replace("{session_id}", encodeURIComponent(t)), a = await fetch(e, {
619
627
  method: "POST",
620
628
  credentials: "include"
621
629
  });
622
- if (!n.ok)
623
- throw new Error(`Failed to revoke session: ${n.status} ${n.statusText}`);
624
- return n.status === 200;
625
- }, fe = async () => {
626
- const t = await fetch(a("sessionsRevokeAll"), {
630
+ if (!a.ok)
631
+ throw new Error(`Failed to revoke session: ${a.status} ${a.statusText}`);
632
+ return a.status === 200;
633
+ }, de = async () => {
634
+ const t = await fetch(n("sessionsRevokeAll"), {
627
635
  method: "POST",
628
636
  credentials: "include"
629
637
  });
@@ -631,69 +639,76 @@ function _e() {
631
639
  throw new Error(`Failed to revoke all other sessions: ${t.status} ${t.statusText}`);
632
640
  return t.status === 200;
633
641
  };
634
- typeof document < "u" && document.addEventListener("visibilitychange", () => {
635
- document.visibilityState === "visible" && f.value ? _() : document.visibilityState === "hidden" && A();
636
- });
637
- const de = () => {
638
- A(), w();
642
+ if (typeof document < "u" && typeof window < "u") {
643
+ const t = window;
644
+ t.__STRANDS_VISIBILITY_LISTENER__ || (t.__STRANDS_VISIBILITY_LISTENER__ = !0, document.addEventListener("visibilitychange", async () => {
645
+ const e = $();
646
+ if (document.visibilityState === "visible" && e.currentSession.value) {
647
+ const a = /* @__PURE__ */ new Date();
648
+ e.currentSession.value.expiresAt.getTime() - a.getTime() <= 120 * 1e3 ? e.refreshTokenFn && await e.refreshTokenFn() : e.startTimerFn && e.startTimerFn();
649
+ } else document.visibilityState === "hidden" && e.stopTimerFn && e.stopTimerFn();
650
+ }));
651
+ }
652
+ const he = () => {
653
+ A(), m();
639
654
  };
640
655
  try {
641
- he() && ge(de);
656
+ ge() && ve(he);
642
657
  } catch {
643
658
  }
644
- return p.value || x(), {
659
+ return p.value || I(), {
645
660
  // State
646
- user: u(() => s.value),
647
- currentUser: u(() => s.value),
648
- currentSession: u(() => f.value),
661
+ user: c(() => s.value),
662
+ currentUser: c(() => s.value),
663
+ currentSession: c(() => f.value),
649
664
  isAuthenticated: W,
650
- isLoading: u(() => L.value || !p.value),
665
+ isLoading: c(() => V.value || !p.value),
651
666
  loading: D,
652
667
  loadingMessage: q,
653
668
  // Specific loading states
654
- isInitializing: j,
655
- isInitialized: u(() => p.value),
656
- isSigningIn: N,
657
- isSigningUp: F,
658
- isSigningOut: R,
659
- isRefreshingToken: z,
660
- isSendingMfaEmail: J,
661
- isVerifyingMfa: U,
669
+ isInitializing: C,
670
+ isInitialized: c(() => p.value),
671
+ isSigningIn: j,
672
+ isSigningUp: R,
673
+ isSigningOut: z,
674
+ isRefreshingToken: J,
675
+ isSendingMfaEmail: U,
676
+ isVerifyingMfa: L,
662
677
  // MFA State
663
- mfaRequired: u(() => T.value),
664
- mfaSessionId: u(() => g.value),
665
- availableMfaMethods: u(() => S.value),
678
+ mfaRequired: c(() => T.value),
679
+ mfaSessionId: c(() => g.value),
680
+ availableMfaMethods: c(() => S.value),
666
681
  // Methods
667
- signIn: B,
668
- signUp: Y,
669
- signOut: Q,
682
+ signIn: Y,
683
+ signUp: Q,
684
+ signOut: X,
670
685
  refreshToken: O,
671
- fetchProfile: X,
672
- updateProfile: Z,
673
- updateUserSettings: ee,
674
- changeEmail: te,
675
- changeUsername: se,
676
- getUsernameCooldown: re,
677
- checkUsernameAvailability: oe,
686
+ fetchProfile: Z,
687
+ updateProfile: ee,
688
+ updateUserSettings: te,
689
+ changeEmail: ne,
690
+ changeUsername: re,
691
+ getUsernameCooldown: oe,
692
+ checkUsernameAvailability: le,
678
693
  // Session management
679
- getUserSessions: le,
680
- getSessionStats: ue,
681
- revokeSession: ce,
682
- revokeAllOtherSessions: fe,
683
- initialize: x,
684
- setAuthData: P,
694
+ getUserSessions: ue,
695
+ getSessionStats: ce,
696
+ revokeSession: fe,
697
+ revokeAllOtherSessions: de,
698
+ initialize: I,
699
+ setAuthData: x,
685
700
  verifyMfa: ae,
686
- sendMfaEmailCode: ne,
687
- getMfaWebAuthnChallenge: ie,
701
+ sendMfaEmailCode: ie,
702
+ getMfaWebAuthnChallenge: se,
688
703
  registerHardwareKey: K,
689
- completeHardwareKeyRegistration: G,
704
+ completeHardwareKeyRegistration: B,
690
705
  // Token management
691
706
  startTokenRefreshTimer: _,
692
707
  stopTokenRefreshTimer: A,
693
708
  getAuthHeaders: H,
694
709
  // Force re-initialization (useful for testing or navigation)
695
710
  forceReInit: () => {
696
- p.value = !1, i.value.initializing = !0, x();
711
+ p.value = !1, i.value.initializing = !0, I();
697
712
  }
698
713
  };
699
714
  }