@kendevelops/auth-flow-kit 1.5.0 → 1.5.5
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.cjs +49 -251
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +33 -235
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,9 +9,7 @@ import {
|
|
|
9
9
|
|
|
10
10
|
// src/http.ts
|
|
11
11
|
function makeURL(baseURL, path) {
|
|
12
|
-
|
|
13
|
-
const suffix = path.startsWith("/") ? path : `/${path}`;
|
|
14
|
-
return `${base}${suffix}`;
|
|
12
|
+
return `${baseURL.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
15
13
|
}
|
|
16
14
|
function getStoredAccessToken() {
|
|
17
15
|
try {
|
|
@@ -22,11 +20,8 @@ function getStoredAccessToken() {
|
|
|
22
20
|
}
|
|
23
21
|
function setStoredAccessToken(token) {
|
|
24
22
|
try {
|
|
25
|
-
if (token)
|
|
26
|
-
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
localStorage.removeItem("afk_access_token");
|
|
23
|
+
if (token) localStorage.setItem("afk_access_token", token);
|
|
24
|
+
else localStorage.removeItem("afk_access_token");
|
|
30
25
|
} catch {
|
|
31
26
|
}
|
|
32
27
|
}
|
|
@@ -35,27 +30,20 @@ async function httpJSON(url, opts = {}, withAuth = false) {
|
|
|
35
30
|
"Content-Type": "application/json"
|
|
36
31
|
};
|
|
37
32
|
if (withAuth) {
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
headers["Authorization"] = `Bearer ${storedToken}`;
|
|
41
|
-
}
|
|
33
|
+
const tok = getStoredAccessToken();
|
|
34
|
+
if (tok) headers["Authorization"] = `Bearer ${tok}`;
|
|
42
35
|
}
|
|
43
36
|
const res = await fetch(url, {
|
|
44
37
|
...opts,
|
|
45
|
-
headers: {
|
|
46
|
-
...headers,
|
|
47
|
-
...opts.headers || {}
|
|
48
|
-
}
|
|
38
|
+
headers: { ...headers, ...opts.headers || {} }
|
|
49
39
|
});
|
|
50
40
|
if (!res.ok) {
|
|
51
41
|
let message = `Request failed (${res.status})`;
|
|
52
42
|
const contentType = res.headers.get("content-type") || "";
|
|
53
43
|
if (contentType.includes("application/json")) {
|
|
54
44
|
try {
|
|
55
|
-
const
|
|
56
|
-
if (
|
|
57
|
-
message = body.message;
|
|
58
|
-
}
|
|
45
|
+
const data = await res.json();
|
|
46
|
+
if (data?.message) message = data.message;
|
|
59
47
|
} catch {
|
|
60
48
|
}
|
|
61
49
|
}
|
|
@@ -150,22 +138,17 @@ function AuthProvider({
|
|
|
150
138
|
}
|
|
151
139
|
|
|
152
140
|
// src/Protected.tsx
|
|
141
|
+
import { useEffect as useEffect2 } from "react";
|
|
153
142
|
import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
|
|
154
|
-
function Protected({
|
|
155
|
-
children,
|
|
156
|
-
redirectTo,
|
|
157
|
-
fallback = /* @__PURE__ */ jsx2("div", { children: "Loading..." })
|
|
158
|
-
}) {
|
|
143
|
+
function Protected({ children, redirectTo }) {
|
|
159
144
|
const { user, loading } = useAuth();
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (!user) {
|
|
164
|
-
if (redirectTo && typeof window !== "undefined") {
|
|
165
|
-
window.location.replace(redirectTo);
|
|
145
|
+
useEffect2(() => {
|
|
146
|
+
if (!loading && !user && redirectTo) {
|
|
147
|
+
window.location.href = redirectTo;
|
|
166
148
|
}
|
|
167
|
-
|
|
168
|
-
}
|
|
149
|
+
}, [loading, user, redirectTo]);
|
|
150
|
+
if (loading) return /* @__PURE__ */ jsx2("div", { children: "Loading..." });
|
|
151
|
+
if (!user) return null;
|
|
169
152
|
return /* @__PURE__ */ jsx2(Fragment, { children });
|
|
170
153
|
}
|
|
171
154
|
|
|
@@ -180,29 +163,18 @@ function PasswordResetScreen() {
|
|
|
180
163
|
const [email, setEmail] = useState2("");
|
|
181
164
|
const [sent, setSent] = useState2(false);
|
|
182
165
|
const [error, setError] = useState2(null);
|
|
183
|
-
const isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
184
166
|
const requestReset = async (e) => {
|
|
185
167
|
e.preventDefault();
|
|
186
168
|
setError(null);
|
|
187
|
-
const trimmedEmail = email.trim();
|
|
188
|
-
if (!trimmedEmail) {
|
|
189
|
-
setError("Email is required.");
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
if (!isValidEmail(trimmedEmail)) {
|
|
193
|
-
setError("Enter a valid email address.");
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
169
|
try {
|
|
197
170
|
const url = makeURL(config.baseURL, config.endpoints.forgot);
|
|
198
171
|
await httpJSON(url, {
|
|
199
172
|
method: "POST",
|
|
200
|
-
body: JSON.stringify({ email
|
|
173
|
+
body: JSON.stringify({ email })
|
|
201
174
|
});
|
|
202
175
|
setSent(true);
|
|
203
176
|
} catch (err) {
|
|
204
|
-
|
|
205
|
-
setError(message);
|
|
177
|
+
setError(err?.message || "Failed to request reset");
|
|
206
178
|
}
|
|
207
179
|
};
|
|
208
180
|
return /* @__PURE__ */ jsxs(
|
|
@@ -242,7 +214,6 @@ function PasswordResetScreen() {
|
|
|
242
214
|
/* @__PURE__ */ jsx3(
|
|
243
215
|
"label",
|
|
244
216
|
{
|
|
245
|
-
htmlFor: "afk-reset-email",
|
|
246
217
|
style: {
|
|
247
218
|
position: "absolute",
|
|
248
219
|
top: sent ? "-18px" : "-10px",
|
|
@@ -259,7 +230,6 @@ function PasswordResetScreen() {
|
|
|
259
230
|
/* @__PURE__ */ jsx3(
|
|
260
231
|
"input",
|
|
261
232
|
{
|
|
262
|
-
id: "afk-reset-email",
|
|
263
233
|
value: email,
|
|
264
234
|
onChange: (e) => setEmail(e.target.value),
|
|
265
235
|
type: "email",
|
|
@@ -322,8 +292,6 @@ function PasswordResetScreen() {
|
|
|
322
292
|
error && /* @__PURE__ */ jsx3(
|
|
323
293
|
"p",
|
|
324
294
|
{
|
|
325
|
-
role: "alert",
|
|
326
|
-
"aria-live": "polite",
|
|
327
295
|
style: {
|
|
328
296
|
marginTop: 20,
|
|
329
297
|
color: "crimson",
|
|
@@ -374,26 +342,15 @@ function LoginScreen() {
|
|
|
374
342
|
setError(null);
|
|
375
343
|
const trimmedEmail = email.trim();
|
|
376
344
|
const trimmedPassword = password.trim();
|
|
377
|
-
if (!trimmedEmail) {
|
|
378
|
-
setError("Email
|
|
379
|
-
setSubmitting(false);
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmedEmail)) {
|
|
383
|
-
setError("Enter a valid email address.");
|
|
384
|
-
setSubmitting(false);
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
if (!trimmedPassword) {
|
|
388
|
-
setError("Password is required.");
|
|
345
|
+
if (!trimmedEmail || !trimmedPassword) {
|
|
346
|
+
setError("Email and password cannot be empty.");
|
|
389
347
|
setSubmitting(false);
|
|
390
348
|
return;
|
|
391
349
|
}
|
|
392
350
|
try {
|
|
393
351
|
await login(trimmedEmail, trimmedPassword);
|
|
394
352
|
} catch (err) {
|
|
395
|
-
|
|
396
|
-
setError(message);
|
|
353
|
+
setError(err?.message || "Login failed");
|
|
397
354
|
} finally {
|
|
398
355
|
setSubmitting(false);
|
|
399
356
|
}
|
|
@@ -434,7 +391,6 @@ function LoginScreen() {
|
|
|
434
391
|
/* @__PURE__ */ jsx4(
|
|
435
392
|
"label",
|
|
436
393
|
{
|
|
437
|
-
htmlFor: "afk-login-email",
|
|
438
394
|
style: {
|
|
439
395
|
position: "absolute",
|
|
440
396
|
top: "-10px",
|
|
@@ -451,7 +407,6 @@ function LoginScreen() {
|
|
|
451
407
|
/* @__PURE__ */ jsx4(
|
|
452
408
|
"input",
|
|
453
409
|
{
|
|
454
|
-
id: "afk-login-email",
|
|
455
410
|
value: email,
|
|
456
411
|
onChange: (e) => setEmail(e.target.value),
|
|
457
412
|
type: "email",
|
|
@@ -481,7 +436,6 @@ function LoginScreen() {
|
|
|
481
436
|
/* @__PURE__ */ jsx4(
|
|
482
437
|
"label",
|
|
483
438
|
{
|
|
484
|
-
htmlFor: "afk-login-password",
|
|
485
439
|
style: {
|
|
486
440
|
position: "absolute",
|
|
487
441
|
top: "-10px",
|
|
@@ -498,7 +452,6 @@ function LoginScreen() {
|
|
|
498
452
|
/* @__PURE__ */ jsx4(
|
|
499
453
|
"input",
|
|
500
454
|
{
|
|
501
|
-
id: "afk-login-password",
|
|
502
455
|
value: password,
|
|
503
456
|
onChange: (e) => setPassword(e.target.value),
|
|
504
457
|
type: "password",
|
|
@@ -525,28 +478,17 @@ function LoginScreen() {
|
|
|
525
478
|
)
|
|
526
479
|
] }),
|
|
527
480
|
/* @__PURE__ */ jsx4(
|
|
528
|
-
"
|
|
481
|
+
"p",
|
|
529
482
|
{
|
|
483
|
+
onClick: () => setShowReset(true),
|
|
530
484
|
style: {
|
|
531
|
-
textAlign: "right"
|
|
485
|
+
textAlign: "right",
|
|
486
|
+
fontSize: 13,
|
|
487
|
+
color: "#4b4bff",
|
|
488
|
+
cursor: "pointer",
|
|
489
|
+
marginBottom: 24
|
|
532
490
|
},
|
|
533
|
-
children:
|
|
534
|
-
"button",
|
|
535
|
-
{
|
|
536
|
-
onClick: () => setShowReset(true),
|
|
537
|
-
style: {
|
|
538
|
-
textAlign: "right",
|
|
539
|
-
fontSize: 13,
|
|
540
|
-
color: "#4b4bff",
|
|
541
|
-
cursor: "pointer",
|
|
542
|
-
marginBottom: 24,
|
|
543
|
-
width: "fit-content",
|
|
544
|
-
border: "none",
|
|
545
|
-
background: "none"
|
|
546
|
-
},
|
|
547
|
-
children: "Forgot password?"
|
|
548
|
-
}
|
|
549
|
-
)
|
|
491
|
+
children: "Forgot password?"
|
|
550
492
|
}
|
|
551
493
|
),
|
|
552
494
|
/* @__PURE__ */ jsx4(
|
|
@@ -574,8 +516,6 @@ function LoginScreen() {
|
|
|
574
516
|
error && /* @__PURE__ */ jsx4(
|
|
575
517
|
"p",
|
|
576
518
|
{
|
|
577
|
-
role: "alert",
|
|
578
|
-
"aria-live": "polite",
|
|
579
519
|
style: {
|
|
580
520
|
marginTop: 18,
|
|
581
521
|
color: "crimson",
|
|
@@ -599,21 +539,8 @@ function SignupScreen() {
|
|
|
599
539
|
const [name, setName] = useState4("");
|
|
600
540
|
const [email, setEmail] = useState4("");
|
|
601
541
|
const [password, setPassword] = useState4("");
|
|
602
|
-
const [confirmPassword, setConfirmPassword] = useState4("");
|
|
603
542
|
const [submitting, setSubmitting] = useState4(false);
|
|
604
543
|
const [error, setError] = useState4(null);
|
|
605
|
-
const isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
606
|
-
const getPasswordStrength = (value) => {
|
|
607
|
-
let score = 0;
|
|
608
|
-
if (value.length >= 8) score++;
|
|
609
|
-
if (/[A-Z]/.test(value)) score++;
|
|
610
|
-
if (/[0-9]/.test(value)) score++;
|
|
611
|
-
if (/[^A-Za-z0-9]/.test(value)) score++;
|
|
612
|
-
if (!value) return { label: "", color: "" };
|
|
613
|
-
if (score <= 1) return { label: "Weak", color: "crimson" };
|
|
614
|
-
if (score === 2) return { label: "Medium", color: "#f39c12" };
|
|
615
|
-
return { label: "Strong", color: "#2ecc71" };
|
|
616
|
-
};
|
|
617
544
|
const onSubmit = async (e) => {
|
|
618
545
|
e.preventDefault();
|
|
619
546
|
setSubmitting(true);
|
|
@@ -621,47 +548,15 @@ function SignupScreen() {
|
|
|
621
548
|
const trimmedEmail = email.trim();
|
|
622
549
|
const trimmedPassword = password.trim();
|
|
623
550
|
const trimmedName = name.trim();
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
setError("Name is required.");
|
|
627
|
-
setSubmitting(false);
|
|
628
|
-
return;
|
|
629
|
-
}
|
|
630
|
-
if (!trimmedEmail) {
|
|
631
|
-
setError("Email is required.");
|
|
632
|
-
setSubmitting(false);
|
|
633
|
-
return;
|
|
634
|
-
}
|
|
635
|
-
if (!isValidEmail(trimmedEmail)) {
|
|
636
|
-
setError("Enter a valid email address.");
|
|
637
|
-
setSubmitting(false);
|
|
638
|
-
return;
|
|
639
|
-
}
|
|
640
|
-
if (!trimmedPassword) {
|
|
641
|
-
setError("Password is required.");
|
|
642
|
-
setSubmitting(false);
|
|
643
|
-
return;
|
|
644
|
-
}
|
|
645
|
-
if (trimmedPassword.length < 8) {
|
|
646
|
-
setError("Password must be at least 8 characters long.");
|
|
647
|
-
setSubmitting(false);
|
|
648
|
-
return;
|
|
649
|
-
}
|
|
650
|
-
if (!trimmedConfirm) {
|
|
651
|
-
setError("Please confirm your password.");
|
|
652
|
-
setSubmitting(false);
|
|
653
|
-
return;
|
|
654
|
-
}
|
|
655
|
-
if (trimmedPassword !== trimmedConfirm) {
|
|
656
|
-
setError("Passwords do not match.");
|
|
551
|
+
if (!trimmedEmail || !trimmedPassword || !trimmedName) {
|
|
552
|
+
setError("Email and password cannot be empty.");
|
|
657
553
|
setSubmitting(false);
|
|
658
554
|
return;
|
|
659
555
|
}
|
|
660
556
|
try {
|
|
661
|
-
await signup({ name
|
|
557
|
+
await signup({ name, email, password });
|
|
662
558
|
} catch (err) {
|
|
663
|
-
|
|
664
|
-
setError(message);
|
|
559
|
+
setError(err?.message || "Signup failed");
|
|
665
560
|
} finally {
|
|
666
561
|
setSubmitting(false);
|
|
667
562
|
}
|
|
@@ -703,7 +598,6 @@ function SignupScreen() {
|
|
|
703
598
|
/* @__PURE__ */ jsx5(
|
|
704
599
|
"label",
|
|
705
600
|
{
|
|
706
|
-
htmlFor: "afk-signup-name",
|
|
707
601
|
style: {
|
|
708
602
|
position: "absolute",
|
|
709
603
|
top: "-10px",
|
|
@@ -720,7 +614,6 @@ function SignupScreen() {
|
|
|
720
614
|
/* @__PURE__ */ jsx5(
|
|
721
615
|
"input",
|
|
722
616
|
{
|
|
723
|
-
id: "afk-signup-name",
|
|
724
617
|
value: name,
|
|
725
618
|
onChange: (e) => setName(e.target.value),
|
|
726
619
|
placeholder: "Your name",
|
|
@@ -749,7 +642,6 @@ function SignupScreen() {
|
|
|
749
642
|
/* @__PURE__ */ jsx5(
|
|
750
643
|
"label",
|
|
751
644
|
{
|
|
752
|
-
htmlFor: "afk-signup-email",
|
|
753
645
|
style: {
|
|
754
646
|
position: "absolute",
|
|
755
647
|
top: "-10px",
|
|
@@ -766,7 +658,6 @@ function SignupScreen() {
|
|
|
766
658
|
/* @__PURE__ */ jsx5(
|
|
767
659
|
"input",
|
|
768
660
|
{
|
|
769
|
-
id: "afk-signup-email",
|
|
770
661
|
value: email,
|
|
771
662
|
onChange: (e) => setEmail(e.target.value),
|
|
772
663
|
type: "email",
|
|
@@ -796,7 +687,6 @@ function SignupScreen() {
|
|
|
796
687
|
/* @__PURE__ */ jsx5(
|
|
797
688
|
"label",
|
|
798
689
|
{
|
|
799
|
-
htmlFor: "afk-signup-password",
|
|
800
690
|
style: {
|
|
801
691
|
position: "absolute",
|
|
802
692
|
top: "-10px",
|
|
@@ -813,7 +703,6 @@ function SignupScreen() {
|
|
|
813
703
|
/* @__PURE__ */ jsx5(
|
|
814
704
|
"input",
|
|
815
705
|
{
|
|
816
|
-
id: "afk-signup-password",
|
|
817
706
|
value: password,
|
|
818
707
|
onChange: (e) => setPassword(e.target.value),
|
|
819
708
|
type: "password",
|
|
@@ -839,95 +728,6 @@ function SignupScreen() {
|
|
|
839
728
|
}
|
|
840
729
|
)
|
|
841
730
|
] }),
|
|
842
|
-
/* @__PURE__ */ jsxs3("div", { style: { position: "relative", marginBottom: 18 }, children: [
|
|
843
|
-
/* @__PURE__ */ jsx5(
|
|
844
|
-
"label",
|
|
845
|
-
{
|
|
846
|
-
htmlFor: "afk-signup-confirm-password",
|
|
847
|
-
style: {
|
|
848
|
-
position: "absolute",
|
|
849
|
-
top: "-10px",
|
|
850
|
-
left: "14px",
|
|
851
|
-
background: "rgba(255,255,255,0.85)",
|
|
852
|
-
padding: "0 6px",
|
|
853
|
-
fontSize: 13,
|
|
854
|
-
color: "#444",
|
|
855
|
-
borderRadius: 6
|
|
856
|
-
},
|
|
857
|
-
children: "Confirm password"
|
|
858
|
-
}
|
|
859
|
-
),
|
|
860
|
-
/* @__PURE__ */ jsx5(
|
|
861
|
-
"input",
|
|
862
|
-
{
|
|
863
|
-
id: "afk-signup-confirm-password",
|
|
864
|
-
value: confirmPassword,
|
|
865
|
-
onChange: (e) => setConfirmPassword(e.target.value),
|
|
866
|
-
type: "password",
|
|
867
|
-
placeholder: "Repeat your password",
|
|
868
|
-
style: {
|
|
869
|
-
width: "80%",
|
|
870
|
-
padding: "14px 16px",
|
|
871
|
-
borderRadius: 12,
|
|
872
|
-
border: "1px solid #d2d2d2",
|
|
873
|
-
fontSize: 15,
|
|
874
|
-
outline: "none",
|
|
875
|
-
transition: "0.25s",
|
|
876
|
-
background: "rgba(255,255,255,0.85)"
|
|
877
|
-
},
|
|
878
|
-
onFocus: (e) => {
|
|
879
|
-
e.currentTarget.style.border = "1px solid #4b4bff";
|
|
880
|
-
e.currentTarget.style.boxShadow = "0 0 0 3px rgba(75,75,255,0.25)";
|
|
881
|
-
},
|
|
882
|
-
onBlur: (e) => {
|
|
883
|
-
e.currentTarget.style.border = "1px solid #d2d2d2";
|
|
884
|
-
e.currentTarget.style.boxShadow = "0 0 0 transparent";
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
)
|
|
888
|
-
] }),
|
|
889
|
-
/* @__PURE__ */ jsxs3(
|
|
890
|
-
"div",
|
|
891
|
-
{
|
|
892
|
-
style: {
|
|
893
|
-
marginBottom: 20,
|
|
894
|
-
fontSize: 12,
|
|
895
|
-
color: "#555"
|
|
896
|
-
},
|
|
897
|
-
children: [
|
|
898
|
-
/* @__PURE__ */ jsx5("p", { style: { marginBottom: 6 }, children: "Use at least 8 characters, including letters, numbers, and symbols." }),
|
|
899
|
-
password && /* @__PURE__ */ jsxs3(
|
|
900
|
-
"p",
|
|
901
|
-
{
|
|
902
|
-
style: {
|
|
903
|
-
fontWeight: 600,
|
|
904
|
-
color: getPasswordStrength(password).color
|
|
905
|
-
},
|
|
906
|
-
children: [
|
|
907
|
-
"Password strength: ",
|
|
908
|
-
getPasswordStrength(password).label
|
|
909
|
-
]
|
|
910
|
-
}
|
|
911
|
-
)
|
|
912
|
-
]
|
|
913
|
-
}
|
|
914
|
-
),
|
|
915
|
-
/* @__PURE__ */ jsx5(
|
|
916
|
-
"p",
|
|
917
|
-
{
|
|
918
|
-
style: {
|
|
919
|
-
textAlign: "center",
|
|
920
|
-
fontSize: 13,
|
|
921
|
-
color: "#4b4bff",
|
|
922
|
-
cursor: "pointer",
|
|
923
|
-
marginBottom: 24
|
|
924
|
-
},
|
|
925
|
-
onClick: () => {
|
|
926
|
-
window.dispatchEvent(new CustomEvent("auth-flow-kit:navigate-to-login"));
|
|
927
|
-
},
|
|
928
|
-
children: "Already have an account? Sign in"
|
|
929
|
-
}
|
|
930
|
-
),
|
|
931
731
|
/* @__PURE__ */ jsx5(
|
|
932
732
|
"button",
|
|
933
733
|
{
|
|
@@ -953,8 +753,6 @@ function SignupScreen() {
|
|
|
953
753
|
error && /* @__PURE__ */ jsx5(
|
|
954
754
|
"p",
|
|
955
755
|
{
|
|
956
|
-
role: "alert",
|
|
957
|
-
"aria-live": "polite",
|
|
958
756
|
style: {
|
|
959
757
|
marginTop: 18,
|
|
960
758
|
color: "crimson",
|