@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.
- package/README.md +4 -4
- package/dist/{StrandsUIPlugin-B1Gl61ax.cjs.js → StrandsUIPlugin-5AOCDOcM.cjs.js} +18 -18
- package/dist/{StrandsUIPlugin-BNU_Ayly.es.js → StrandsUIPlugin-CCRrewS9.es.js} +749 -739
- package/dist/accui.css +1 -1
- package/dist/index.cjs.js +4 -4
- package/dist/index.es.js +1219 -1202
- package/dist/nuxt/module.cjs.js +1 -1
- package/dist/nuxt/module.es.js +3 -4
- package/dist/nuxt/runtime/composables/useStrandsAuth.cjs.js +1 -1
- package/dist/nuxt/runtime/composables/useStrandsAuth.es.js +1 -1
- package/dist/nuxt/runtime/middleware/auth.global.cjs.js +1 -1
- package/dist/nuxt/runtime/middleware/auth.global.es.js +14 -32
- package/dist/types/index.d.ts +2 -2
- package/dist/{useStrandsAuth-wzl2F9DE.es.js → useStrandsAuth-DSLFMDTj.es.js} +221 -206
- package/dist/useStrandsAuth-Db5ZGvxL.cjs.js +1 -0
- package/dist/vite.cjs.js +1 -1
- package/dist/vite.es.js +1 -1
- package/dist/vue/ui/UiInput/UiInput.Text.vue.d.ts +4 -0
- package/package.json +1 -1
- package/dist/useStrandsAuth-CetpoBNk.cjs.js +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { computed as
|
|
2
|
-
import { u as
|
|
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,
|
|
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 =
|
|
15
|
+
const f = w().finally(() => {
|
|
16
16
|
setTimeout(() => {
|
|
17
17
|
this.cache.delete(d);
|
|
18
|
-
},
|
|
18
|
+
}, m);
|
|
19
19
|
});
|
|
20
20
|
return this.cache.set(d, {
|
|
21
21
|
promise: f,
|
|
22
22
|
timestamp: E,
|
|
23
|
-
ttl:
|
|
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 [
|
|
44
|
-
d -
|
|
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
|
|
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
|
|
66
|
-
let
|
|
67
|
-
return (...
|
|
68
|
-
|
|
69
|
-
|
|
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
|
|
74
|
-
typeof window < "u" && localStorage.setItem(
|
|
75
|
-
}, 300), k = (
|
|
76
|
-
id:
|
|
77
|
-
email:
|
|
78
|
-
firstName:
|
|
79
|
-
lastName:
|
|
80
|
-
avatar:
|
|
81
|
-
mfaEnabled:
|
|
82
|
-
emailVerified:
|
|
83
|
-
passwordUpdatedAt:
|
|
84
|
-
settings:
|
|
85
|
-
xp:
|
|
86
|
-
level:
|
|
87
|
-
next_level_xp:
|
|
88
|
-
username:
|
|
89
|
-
usernameLastChangedAt:
|
|
90
|
-
createdAt:
|
|
91
|
-
updatedAt:
|
|
92
|
-
}),
|
|
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
|
|
116
|
-
return
|
|
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
|
-
|
|
137
|
-
|
|
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:
|
|
140
|
-
if (s.value = null, f.value = null, T.value = !1, g.value = null, S.value = [], A(),
|
|
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
|
-
},
|
|
145
|
-
|
|
146
|
-
const D =
|
|
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
|
-
),
|
|
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
|
-
}),
|
|
159
|
+
}), G = async () => {
|
|
154
160
|
try {
|
|
155
|
-
const t = await fetch(
|
|
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
|
|
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:
|
|
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
|
-
},
|
|
179
|
-
const r = await fetch(
|
|
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
|
|
197
|
+
const u = await r.text();
|
|
192
198
|
let o = "Failed to complete hardware key registration";
|
|
193
199
|
try {
|
|
194
|
-
const v = JSON.parse(
|
|
195
|
-
o = v.message || v.error ||
|
|
200
|
+
const v = JSON.parse(u);
|
|
201
|
+
o = v.message || v.error || u;
|
|
196
202
|
} catch {
|
|
197
|
-
o =
|
|
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,
|
|
203
|
-
const r = await fetch(
|
|
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:
|
|
217
|
+
device_type: a
|
|
212
218
|
})
|
|
213
219
|
});
|
|
214
220
|
if (!r.ok) {
|
|
215
|
-
const
|
|
221
|
+
const u = await r.text();
|
|
216
222
|
let o = "Failed to start hardware key registration";
|
|
217
223
|
try {
|
|
218
|
-
const v = JSON.parse(
|
|
219
|
-
o = v.message || v.error ||
|
|
224
|
+
const v = JSON.parse(u);
|
|
225
|
+
o = v.message || v.error || u;
|
|
220
226
|
} catch {
|
|
221
|
-
o =
|
|
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 =
|
|
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
|
|
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 (!
|
|
242
|
-
throw
|
|
243
|
-
const r = await
|
|
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
|
|
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 =
|
|
266
|
+
return S.value = u, i.value.signingIn = !1, r;
|
|
261
267
|
}
|
|
262
|
-
return await
|
|
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
|
-
},
|
|
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
|
-
},
|
|
281
|
+
}, X = async () => {
|
|
276
282
|
i.value.signingOut = !0;
|
|
277
283
|
try {
|
|
278
|
-
await fetch(
|
|
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(),
|
|
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 (
|
|
288
|
-
return await
|
|
289
|
-
|
|
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(
|
|
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
|
|
308
|
+
return M(), !1;
|
|
303
309
|
throw new Error(`Token refresh failed: ${e.status} ${e.statusText}`);
|
|
304
310
|
}
|
|
305
|
-
const
|
|
306
|
-
|
|
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:
|
|
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
|
|
324
|
+
return M(), !1;
|
|
319
325
|
} finally {
|
|
320
326
|
i.value.refreshingToken = !1;
|
|
321
327
|
}
|
|
322
328
|
})();
|
|
323
|
-
const t = await
|
|
324
|
-
return
|
|
325
|
-
},
|
|
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
|
|
330
|
-
const e = await fetch(
|
|
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
|
|
340
|
-
return s.value = k(
|
|
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
|
-
},
|
|
351
|
+
}, ee = async (t) => {
|
|
346
352
|
i.value.loadingProfile = !0;
|
|
347
353
|
try {
|
|
348
|
-
const e = await fetch(
|
|
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
|
|
362
|
-
return s.value = k(
|
|
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
|
-
},
|
|
372
|
+
}, te = async (t) => {
|
|
367
373
|
i.value.loadingProfile = !0;
|
|
368
374
|
try {
|
|
369
|
-
const e = await fetch(
|
|
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
|
|
382
|
-
return s.value = k(
|
|
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
|
-
},
|
|
392
|
+
}, ne = async (t, e) => {
|
|
387
393
|
i.value.loadingProfile = !0;
|
|
388
394
|
try {
|
|
389
|
-
const
|
|
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 (!
|
|
401
|
-
if (
|
|
406
|
+
if (!a.ok) {
|
|
407
|
+
if (a.status === 401)
|
|
402
408
|
throw new Error("Authentication expired. Please sign in again.");
|
|
403
409
|
{
|
|
404
|
-
const
|
|
405
|
-
throw new Error(
|
|
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
|
|
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,
|
|
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
|
|
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(
|
|
434
|
+
body: JSON.stringify(u)
|
|
429
435
|
});
|
|
430
436
|
if (!o.ok) {
|
|
431
|
-
const
|
|
432
|
-
let
|
|
437
|
+
const P = await o.text();
|
|
438
|
+
let b = "MFA verification failed";
|
|
433
439
|
try {
|
|
434
|
-
const
|
|
435
|
-
|
|
440
|
+
const F = JSON.parse(P);
|
|
441
|
+
b = F.message || F.error || P;
|
|
436
442
|
} catch {
|
|
437
|
-
|
|
443
|
+
b = P || "MFA verification failed";
|
|
438
444
|
}
|
|
439
|
-
throw new Error(
|
|
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
|
|
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
|
-
},
|
|
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(
|
|
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
|
|
468
|
+
let u = "Failed to send MFA email code";
|
|
463
469
|
try {
|
|
464
470
|
const o = JSON.parse(r);
|
|
465
|
-
|
|
471
|
+
u = o.message || o.error || r;
|
|
466
472
|
} catch {
|
|
467
|
-
|
|
473
|
+
u = r || "Failed to send MFA email code";
|
|
468
474
|
}
|
|
469
|
-
throw new Error(
|
|
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
|
-
},
|
|
481
|
+
}, se = async (t) => {
|
|
476
482
|
if (!g.value)
|
|
477
483
|
throw new Error("No MFA session available");
|
|
478
|
-
const e = await fetch(
|
|
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
|
|
494
|
+
const a = await e.text();
|
|
489
495
|
let r = "Failed to get WebAuthn challenge";
|
|
490
496
|
try {
|
|
491
|
-
const
|
|
492
|
-
r =
|
|
497
|
+
const u = JSON.parse(a);
|
|
498
|
+
r = u.message || u.error || a;
|
|
493
499
|
} catch {
|
|
494
|
-
r =
|
|
500
|
+
r = a || r;
|
|
495
501
|
}
|
|
496
502
|
throw new Error(r);
|
|
497
503
|
}
|
|
498
504
|
return e.json();
|
|
499
|
-
},
|
|
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 (
|
|
521
|
+
if (l.refreshTimer && clearTimeout(l.refreshTimer), !f.value || typeof document < "u" && document.visibilityState === "hidden")
|
|
516
522
|
return;
|
|
517
|
-
const t = /* @__PURE__ */ new Date(),
|
|
518
|
-
if (
|
|
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
|
-
|
|
528
|
+
l.refreshTimer = setTimeout(async () => {
|
|
523
529
|
(typeof document > "u" || document.visibilityState === "visible") && await O() && _();
|
|
524
|
-
},
|
|
530
|
+
}, a);
|
|
525
531
|
}, A = () => {
|
|
526
|
-
|
|
527
|
-
}
|
|
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 (
|
|
533
|
-
await
|
|
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
|
-
|
|
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,
|
|
553
|
+
i.value.initializing = !1, l.promise = null;
|
|
546
554
|
}
|
|
547
555
|
};
|
|
548
|
-
return
|
|
549
|
-
},
|
|
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(
|
|
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
|
|
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
|
-
}),
|
|
580
|
+
}), a;
|
|
573
581
|
} finally {
|
|
574
582
|
i.value.loadingProfile = !1;
|
|
575
583
|
}
|
|
576
|
-
},
|
|
577
|
-
const t = await fetch(
|
|
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
|
-
},
|
|
585
|
-
const 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 (!
|
|
592
|
-
throw new Error(`Failed to check username availability: ${
|
|
593
|
-
return
|
|
594
|
-
},
|
|
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
|
|
598
|
-
const e = await fetch(
|
|
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
|
-
},
|
|
610
|
-
const t = await fetch(
|
|
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
|
-
},
|
|
618
|
-
const 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 (!
|
|
623
|
-
throw new Error(`Failed to revoke session: ${
|
|
624
|
-
return
|
|
625
|
-
},
|
|
626
|
-
const t = await fetch(
|
|
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" &&
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
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
|
-
|
|
656
|
+
ge() && ve(he);
|
|
642
657
|
} catch {
|
|
643
658
|
}
|
|
644
|
-
return p.value ||
|
|
659
|
+
return p.value || I(), {
|
|
645
660
|
// State
|
|
646
|
-
user:
|
|
647
|
-
currentUser:
|
|
648
|
-
currentSession:
|
|
661
|
+
user: c(() => s.value),
|
|
662
|
+
currentUser: c(() => s.value),
|
|
663
|
+
currentSession: c(() => f.value),
|
|
649
664
|
isAuthenticated: W,
|
|
650
|
-
isLoading:
|
|
665
|
+
isLoading: c(() => V.value || !p.value),
|
|
651
666
|
loading: D,
|
|
652
667
|
loadingMessage: q,
|
|
653
668
|
// Specific loading states
|
|
654
|
-
isInitializing:
|
|
655
|
-
isInitialized:
|
|
656
|
-
isSigningIn:
|
|
657
|
-
isSigningUp:
|
|
658
|
-
isSigningOut:
|
|
659
|
-
isRefreshingToken:
|
|
660
|
-
isSendingMfaEmail:
|
|
661
|
-
isVerifyingMfa:
|
|
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:
|
|
664
|
-
mfaSessionId:
|
|
665
|
-
availableMfaMethods:
|
|
678
|
+
mfaRequired: c(() => T.value),
|
|
679
|
+
mfaSessionId: c(() => g.value),
|
|
680
|
+
availableMfaMethods: c(() => S.value),
|
|
666
681
|
// Methods
|
|
667
|
-
signIn:
|
|
668
|
-
signUp:
|
|
669
|
-
signOut:
|
|
682
|
+
signIn: Y,
|
|
683
|
+
signUp: Q,
|
|
684
|
+
signOut: X,
|
|
670
685
|
refreshToken: O,
|
|
671
|
-
fetchProfile:
|
|
672
|
-
updateProfile:
|
|
673
|
-
updateUserSettings:
|
|
674
|
-
changeEmail:
|
|
675
|
-
changeUsername:
|
|
676
|
-
getUsernameCooldown:
|
|
677
|
-
checkUsernameAvailability:
|
|
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:
|
|
680
|
-
getSessionStats:
|
|
681
|
-
revokeSession:
|
|
682
|
-
revokeAllOtherSessions:
|
|
683
|
-
initialize:
|
|
684
|
-
setAuthData:
|
|
694
|
+
getUserSessions: ue,
|
|
695
|
+
getSessionStats: ce,
|
|
696
|
+
revokeSession: fe,
|
|
697
|
+
revokeAllOtherSessions: de,
|
|
698
|
+
initialize: I,
|
|
699
|
+
setAuthData: x,
|
|
685
700
|
verifyMfa: ae,
|
|
686
|
-
sendMfaEmailCode:
|
|
687
|
-
getMfaWebAuthnChallenge:
|
|
701
|
+
sendMfaEmailCode: ie,
|
|
702
|
+
getMfaWebAuthnChallenge: se,
|
|
688
703
|
registerHardwareKey: K,
|
|
689
|
-
completeHardwareKeyRegistration:
|
|
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,
|
|
711
|
+
p.value = !1, i.value.initializing = !0, I();
|
|
697
712
|
}
|
|
698
713
|
};
|
|
699
714
|
}
|