@riligar/auth-react 1.3.0 → 1.5.0
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.esm.js +157 -70
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +156 -68
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -61,10 +61,18 @@ async function api(route, opts = {}) {
|
|
|
61
61
|
|
|
62
62
|
// Converte JSON automaticamente e lança erro legível
|
|
63
63
|
const data = res.status !== 204 ? await res.json().catch(() => ({})) : null;
|
|
64
|
-
if (!res.ok)
|
|
65
|
-
res
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
if (!res.ok) {
|
|
65
|
+
let errorMessage = data?.message || data?.error || data?.detail || res.statusText;
|
|
66
|
+
|
|
67
|
+
// Se a mensagem for um objeto, tenta extrair string ou stringify
|
|
68
|
+
if (typeof errorMessage === 'object') {
|
|
69
|
+
errorMessage = errorMessage.message || JSON.stringify(errorMessage);
|
|
70
|
+
}
|
|
71
|
+
throw Object.assign(new Error(errorMessage), {
|
|
72
|
+
res,
|
|
73
|
+
data
|
|
74
|
+
});
|
|
75
|
+
}
|
|
68
76
|
return data;
|
|
69
77
|
}
|
|
70
78
|
|
|
@@ -675,6 +683,68 @@ const useAuthStore = create((set, get) => ({
|
|
|
675
683
|
})
|
|
676
684
|
}));
|
|
677
685
|
|
|
686
|
+
const isIterable = (obj) => Symbol.iterator in obj;
|
|
687
|
+
const hasIterableEntries = (value) => (
|
|
688
|
+
// HACK: avoid checking entries type
|
|
689
|
+
"entries" in value
|
|
690
|
+
);
|
|
691
|
+
const compareEntries = (valueA, valueB) => {
|
|
692
|
+
const mapA = valueA instanceof Map ? valueA : new Map(valueA.entries());
|
|
693
|
+
const mapB = valueB instanceof Map ? valueB : new Map(valueB.entries());
|
|
694
|
+
if (mapA.size !== mapB.size) {
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
for (const [key, value] of mapA) {
|
|
698
|
+
if (!mapB.has(key) || !Object.is(value, mapB.get(key))) {
|
|
699
|
+
return false;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
return true;
|
|
703
|
+
};
|
|
704
|
+
const compareIterables = (valueA, valueB) => {
|
|
705
|
+
const iteratorA = valueA[Symbol.iterator]();
|
|
706
|
+
const iteratorB = valueB[Symbol.iterator]();
|
|
707
|
+
let nextA = iteratorA.next();
|
|
708
|
+
let nextB = iteratorB.next();
|
|
709
|
+
while (!nextA.done && !nextB.done) {
|
|
710
|
+
if (!Object.is(nextA.value, nextB.value)) {
|
|
711
|
+
return false;
|
|
712
|
+
}
|
|
713
|
+
nextA = iteratorA.next();
|
|
714
|
+
nextB = iteratorB.next();
|
|
715
|
+
}
|
|
716
|
+
return !!nextA.done && !!nextB.done;
|
|
717
|
+
};
|
|
718
|
+
function shallow(valueA, valueB) {
|
|
719
|
+
if (Object.is(valueA, valueB)) {
|
|
720
|
+
return true;
|
|
721
|
+
}
|
|
722
|
+
if (typeof valueA !== "object" || valueA === null || typeof valueB !== "object" || valueB === null) {
|
|
723
|
+
return false;
|
|
724
|
+
}
|
|
725
|
+
if (Object.getPrototypeOf(valueA) !== Object.getPrototypeOf(valueB)) {
|
|
726
|
+
return false;
|
|
727
|
+
}
|
|
728
|
+
if (isIterable(valueA) && isIterable(valueB)) {
|
|
729
|
+
if (hasIterableEntries(valueA) && hasIterableEntries(valueB)) {
|
|
730
|
+
return compareEntries(valueA, valueB);
|
|
731
|
+
}
|
|
732
|
+
return compareIterables(valueA, valueB);
|
|
733
|
+
}
|
|
734
|
+
return compareEntries(
|
|
735
|
+
{ entries: () => Object.entries(valueA) },
|
|
736
|
+
{ entries: () => Object.entries(valueB) }
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
function useShallow(selector) {
|
|
741
|
+
const prev = React$1.useRef(void 0);
|
|
742
|
+
return (state) => {
|
|
743
|
+
const next = selector(state);
|
|
744
|
+
return shallow(prev.current, next) ? prev.current : prev.current = next;
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
|
|
678
748
|
const AuthContext = /*#__PURE__*/React$1.createContext(); // só para ter o Provider em JSX
|
|
679
749
|
|
|
680
750
|
function AuthProvider({
|
|
@@ -697,7 +767,9 @@ function AuthProvider({
|
|
|
697
767
|
const checkTokenValidity = useAuthStore(s => s.checkTokenValidity);
|
|
698
768
|
|
|
699
769
|
// Configura SDK com apiUrl e apiKey
|
|
700
|
-
|
|
770
|
+
// Configura SDK com apiUrl e apiKey
|
|
771
|
+
// Usamos useMemo para garantir que a configuração ocorra ANTES dos efeitos dos componentes filhos
|
|
772
|
+
React$1.useMemo(() => {
|
|
701
773
|
configure({
|
|
702
774
|
apiUrl,
|
|
703
775
|
apiKey
|
|
@@ -744,12 +816,12 @@ function AuthProvider({
|
|
|
744
816
|
}
|
|
745
817
|
|
|
746
818
|
/* Hooks "facade" que a app vai usar */
|
|
747
|
-
const useAuth = () => useAuthStore(s => ({
|
|
819
|
+
const useAuth = () => useAuthStore(useShallow(s => ({
|
|
748
820
|
user: s.user,
|
|
749
821
|
loading: s.loading,
|
|
750
822
|
error: s.error,
|
|
751
823
|
isAuthenticated: s.user !== null
|
|
752
|
-
}));
|
|
824
|
+
})));
|
|
753
825
|
|
|
754
826
|
// Auth Actions
|
|
755
827
|
const useSignIn = () => useAuthStore(s => s.signIn);
|
|
@@ -758,62 +830,37 @@ const useSignOut = () => useAuthStore(s => s.signOut);
|
|
|
758
830
|
const useCheckToken = () => useAuthStore(s => s.checkTokenValidity);
|
|
759
831
|
|
|
760
832
|
// Magic Link Hook
|
|
761
|
-
const useMagicLink = () => {
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
sendMagicLink,
|
|
769
|
-
verifyMagicLink,
|
|
770
|
-
loading,
|
|
771
|
-
verifying,
|
|
772
|
-
error
|
|
773
|
-
};
|
|
774
|
-
};
|
|
833
|
+
const useMagicLink = () => useAuthStore(useShallow(s => ({
|
|
834
|
+
sendMagicLink: s.sendMagicLink,
|
|
835
|
+
verifyMagicLink: s.verifyMagicLink,
|
|
836
|
+
loading: s.loadingStates.magicLink,
|
|
837
|
+
verifying: s.loadingStates.verifyMagicLink,
|
|
838
|
+
error: s.error
|
|
839
|
+
})));
|
|
775
840
|
|
|
776
841
|
// Password Reset Hook
|
|
777
|
-
const usePasswordReset = () => {
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
forgotPassword,
|
|
784
|
-
resetPassword,
|
|
785
|
-
loading,
|
|
786
|
-
error
|
|
787
|
-
};
|
|
788
|
-
};
|
|
842
|
+
const usePasswordReset = () => useAuthStore(useShallow(s => ({
|
|
843
|
+
forgotPassword: s.forgotPassword,
|
|
844
|
+
resetPassword: s.resetPassword,
|
|
845
|
+
loading: s.loadingStates.resetPassword,
|
|
846
|
+
error: s.error
|
|
847
|
+
})));
|
|
789
848
|
|
|
790
849
|
// Email Verification Hook
|
|
791
|
-
const useEmailVerification = () => {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
verifyEmail,
|
|
799
|
-
resendVerification,
|
|
800
|
-
loading,
|
|
801
|
-
resending,
|
|
802
|
-
error
|
|
803
|
-
};
|
|
804
|
-
};
|
|
850
|
+
const useEmailVerification = () => useAuthStore(useShallow(s => ({
|
|
851
|
+
verifyEmail: s.verifyEmail,
|
|
852
|
+
resendVerification: s.resendVerification,
|
|
853
|
+
loading: s.loadingStates.verifyEmail,
|
|
854
|
+
resending: s.loadingStates.resendVerification,
|
|
855
|
+
error: s.error
|
|
856
|
+
})));
|
|
805
857
|
|
|
806
858
|
// Session Hook
|
|
807
|
-
const useSession = () => {
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
getSession,
|
|
813
|
-
user,
|
|
814
|
-
setUser
|
|
815
|
-
};
|
|
816
|
-
};
|
|
859
|
+
const useSession = () => useAuthStore(useShallow(s => ({
|
|
860
|
+
getSession: s.getSession,
|
|
861
|
+
user: s.user,
|
|
862
|
+
setUser: s.setUser
|
|
863
|
+
})));
|
|
817
864
|
|
|
818
865
|
// Loading States Hook
|
|
819
866
|
const useAuthLoading = () => useAuthStore(s => s.loadingStates);
|
|
@@ -1240,6 +1287,7 @@ function MagicLinkVerify({
|
|
|
1240
1287
|
const [status, setStatus] = React$1.useState('verifying'); // verifying, success, error
|
|
1241
1288
|
const [errorMessage, setErrorMessage] = React$1.useState('');
|
|
1242
1289
|
const verifyMagicLink = useAuthStore(s => s.verifyMagicLink);
|
|
1290
|
+
const verifyingTokenRef = React$1.useRef(null);
|
|
1243
1291
|
React$1.useEffect(() => {
|
|
1244
1292
|
const verify = async () => {
|
|
1245
1293
|
// Pega token da prop ou da URL
|
|
@@ -1254,6 +1302,10 @@ function MagicLinkVerify({
|
|
|
1254
1302
|
onError?.(new Error('No token'));
|
|
1255
1303
|
return;
|
|
1256
1304
|
}
|
|
1305
|
+
|
|
1306
|
+
// Evita verificar o mesmo token duas vezes (React Strict Mode ou re-renders)
|
|
1307
|
+
if (verifyingTokenRef.current === token) return;
|
|
1308
|
+
verifyingTokenRef.current = token;
|
|
1257
1309
|
try {
|
|
1258
1310
|
const result = await verifyMagicLink(token);
|
|
1259
1311
|
setStatus('success');
|
|
@@ -1270,7 +1322,8 @@ function MagicLinkVerify({
|
|
|
1270
1322
|
}
|
|
1271
1323
|
};
|
|
1272
1324
|
verify();
|
|
1273
|
-
|
|
1325
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1326
|
+
}, [propToken, redirectTo, redirectDelay]);
|
|
1274
1327
|
return /*#__PURE__*/React.createElement(AuthCard, _extends({
|
|
1275
1328
|
logo: logo
|
|
1276
1329
|
}, cardProps), status === 'verifying' && /*#__PURE__*/React.createElement(core.Stack, {
|
|
@@ -1525,9 +1578,13 @@ function VerifyEmailCard({
|
|
|
1525
1578
|
}) {
|
|
1526
1579
|
const [status, setStatus] = React$1.useState('verifying'); // verifying, success, error
|
|
1527
1580
|
const [errorMessage, setErrorMessage] = React$1.useState('');
|
|
1581
|
+
const [tokenEmail, setTokenEmail] = React$1.useState(null); // Novo estado para email do token
|
|
1582
|
+
|
|
1528
1583
|
const verifyEmail = useAuthStore(s => s.verifyEmail);
|
|
1529
1584
|
const resendVerification = useAuthStore(s => s.resendVerification);
|
|
1530
1585
|
const loadingResend = useAuthStore(s => s.loadingStates.resendVerification);
|
|
1586
|
+
const user = useAuthStore(s => s.user);
|
|
1587
|
+
const verifyingTokenRef = React$1.useRef(null);
|
|
1531
1588
|
React$1.useEffect(() => {
|
|
1532
1589
|
const verify = async () => {
|
|
1533
1590
|
// Pega token da prop ou da URL
|
|
@@ -1537,11 +1594,25 @@ function VerifyEmailCard({
|
|
|
1537
1594
|
token = urlParams.get('token');
|
|
1538
1595
|
}
|
|
1539
1596
|
if (!token) {
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1597
|
+
// Se já mostramos o erro de token faltando, não precisa fazer nada
|
|
1598
|
+
if (status === 'missing_token') return;
|
|
1599
|
+
setStatus('missing_token');
|
|
1543
1600
|
return;
|
|
1544
1601
|
}
|
|
1602
|
+
|
|
1603
|
+
// Tenta extrair email do token (mesmo expirado) para permitir reenvio
|
|
1604
|
+
try {
|
|
1605
|
+
const payload = decodeJWT(token);
|
|
1606
|
+
if (payload?.email) {
|
|
1607
|
+
setTokenEmail(payload.email);
|
|
1608
|
+
}
|
|
1609
|
+
} catch (e) {
|
|
1610
|
+
// ignore jwt error
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
// Evita verificar o mesmo token duas vezes (React Strict Mode ou re-renders)
|
|
1614
|
+
if (verifyingTokenRef.current === token) return;
|
|
1615
|
+
verifyingTokenRef.current = token;
|
|
1545
1616
|
try {
|
|
1546
1617
|
const result = await verifyEmail(token);
|
|
1547
1618
|
setStatus('success');
|
|
@@ -1552,18 +1623,22 @@ function VerifyEmailCard({
|
|
|
1552
1623
|
}, redirectDelay);
|
|
1553
1624
|
}
|
|
1554
1625
|
} catch (error) {
|
|
1626
|
+
// Se der erro, permitimos tentar novamente apenas se o usuário recarregar
|
|
1627
|
+
// ou se implementarmos um botão de retry que limpe o ref
|
|
1555
1628
|
setStatus('error');
|
|
1556
1629
|
setErrorMessage(error.message || labels.verificationFailed || 'Verificação falhou');
|
|
1557
1630
|
onError?.(error);
|
|
1558
1631
|
}
|
|
1559
1632
|
};
|
|
1560
1633
|
verify();
|
|
1561
|
-
|
|
1634
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1635
|
+
}, [propToken, redirectTo, redirectDelay]);
|
|
1562
1636
|
const handleResend = async () => {
|
|
1563
|
-
|
|
1637
|
+
const targetEmail = email || user?.email || tokenEmail;
|
|
1638
|
+
if (!targetEmail) return;
|
|
1564
1639
|
try {
|
|
1565
|
-
await resendVerification(
|
|
1566
|
-
onResent?.(
|
|
1640
|
+
await resendVerification(targetEmail);
|
|
1641
|
+
onResent?.(targetEmail);
|
|
1567
1642
|
} catch (error) {
|
|
1568
1643
|
onError?.(error);
|
|
1569
1644
|
}
|
|
@@ -1581,7 +1656,19 @@ function VerifyEmailCard({
|
|
|
1581
1656
|
size: "sm",
|
|
1582
1657
|
c: "dimmed",
|
|
1583
1658
|
ta: "center"
|
|
1584
|
-
}, labels.pleaseWait || 'Aguarde enquanto verificamos seu email...')), status === '
|
|
1659
|
+
}, labels.pleaseWait || 'Aguarde enquanto verificamos seu email...')), status === 'missing_token' && /*#__PURE__*/React.createElement(core.Stack, {
|
|
1660
|
+
align: "center",
|
|
1661
|
+
gap: "sm"
|
|
1662
|
+
}, /*#__PURE__*/React.createElement(iconsReact.IconMail, {
|
|
1663
|
+
size: 48,
|
|
1664
|
+
color: "var(--mantine-color-blue-6)"
|
|
1665
|
+
}), /*#__PURE__*/React.createElement(core.Title, {
|
|
1666
|
+
order: 4
|
|
1667
|
+
}, labels.verification || 'Verificação de Email'), /*#__PURE__*/React.createElement(core.Text, {
|
|
1668
|
+
size: "sm",
|
|
1669
|
+
c: "dimmed",
|
|
1670
|
+
ta: "center"
|
|
1671
|
+
}, labels.missingToken || 'Para verificar seu conta, clique no link enviado para seu email.')), status === 'success' && /*#__PURE__*/React.createElement(core.Stack, {
|
|
1585
1672
|
align: "center",
|
|
1586
1673
|
gap: "sm"
|
|
1587
1674
|
}, /*#__PURE__*/React.createElement(iconsReact.IconCheck, {
|
|
@@ -1605,7 +1692,7 @@ function VerifyEmailCard({
|
|
|
1605
1692
|
size: "sm",
|
|
1606
1693
|
c: "dimmed",
|
|
1607
1694
|
ta: "center"
|
|
1608
|
-
}, errorMessage || labels.invalidToken || 'O link é inválido ou expirou.'), email && /*#__PURE__*/React.createElement(core.Button, {
|
|
1695
|
+
}, errorMessage || labels.invalidToken || 'O link é inválido ou expirou.'), (email || user?.email || tokenEmail) && errorMessage?.toLowerCase().includes('expired') && /*#__PURE__*/React.createElement(core.Button, {
|
|
1609
1696
|
variant: "light",
|
|
1610
1697
|
leftSection: /*#__PURE__*/React.createElement(iconsReact.IconRefresh, {
|
|
1611
1698
|
size: 16
|
|
@@ -1613,7 +1700,7 @@ function VerifyEmailCard({
|
|
|
1613
1700
|
onClick: handleResend,
|
|
1614
1701
|
loading: loadingResend,
|
|
1615
1702
|
fullWidth: true
|
|
1616
|
-
}, labels.resend || '
|
|
1703
|
+
}, labels.resend || 'Solicitar novo link')));
|
|
1617
1704
|
}
|
|
1618
1705
|
|
|
1619
1706
|
exports.AuthCard = AuthCard;
|
|
@@ -1627,6 +1714,7 @@ exports.SignInForm = SignInForm;
|
|
|
1627
1714
|
exports.SignUpForm = SignUpForm;
|
|
1628
1715
|
exports.VerifyEmailCard = VerifyEmailCard;
|
|
1629
1716
|
exports.configure = configure;
|
|
1717
|
+
exports.decodeJWT = decodeJWT;
|
|
1630
1718
|
exports.forgotPassword = forgotPassword;
|
|
1631
1719
|
exports.getCurrentUser = getCurrentUser;
|
|
1632
1720
|
exports.getSession = getSession;
|