@riligar/auth-react 1.4.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.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) throw Object.assign(new Error(data?.error ?? res.statusText), {
65
- res,
66
- data
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
 
@@ -759,7 +767,9 @@ function AuthProvider({
759
767
  const checkTokenValidity = useAuthStore(s => s.checkTokenValidity);
760
768
 
761
769
  // Configura SDK com apiUrl e apiKey
762
- React$1.useEffect(() => {
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(() => {
763
773
  configure({
764
774
  apiUrl,
765
775
  apiKey
@@ -1277,6 +1287,7 @@ function MagicLinkVerify({
1277
1287
  const [status, setStatus] = React$1.useState('verifying'); // verifying, success, error
1278
1288
  const [errorMessage, setErrorMessage] = React$1.useState('');
1279
1289
  const verifyMagicLink = useAuthStore(s => s.verifyMagicLink);
1290
+ const verifyingTokenRef = React$1.useRef(null);
1280
1291
  React$1.useEffect(() => {
1281
1292
  const verify = async () => {
1282
1293
  // Pega token da prop ou da URL
@@ -1291,6 +1302,10 @@ function MagicLinkVerify({
1291
1302
  onError?.(new Error('No token'));
1292
1303
  return;
1293
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;
1294
1309
  try {
1295
1310
  const result = await verifyMagicLink(token);
1296
1311
  setStatus('success');
@@ -1307,7 +1322,8 @@ function MagicLinkVerify({
1307
1322
  }
1308
1323
  };
1309
1324
  verify();
1310
- }, [propToken, verifyMagicLink, onSuccess, onError, redirectTo, redirectDelay, labels]);
1325
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1326
+ }, [propToken, redirectTo, redirectDelay]);
1311
1327
  return /*#__PURE__*/React.createElement(AuthCard, _extends({
1312
1328
  logo: logo
1313
1329
  }, cardProps), status === 'verifying' && /*#__PURE__*/React.createElement(core.Stack, {
@@ -1562,9 +1578,13 @@ function VerifyEmailCard({
1562
1578
  }) {
1563
1579
  const [status, setStatus] = React$1.useState('verifying'); // verifying, success, error
1564
1580
  const [errorMessage, setErrorMessage] = React$1.useState('');
1581
+ const [tokenEmail, setTokenEmail] = React$1.useState(null); // Novo estado para email do token
1582
+
1565
1583
  const verifyEmail = useAuthStore(s => s.verifyEmail);
1566
1584
  const resendVerification = useAuthStore(s => s.resendVerification);
1567
1585
  const loadingResend = useAuthStore(s => s.loadingStates.resendVerification);
1586
+ const user = useAuthStore(s => s.user);
1587
+ const verifyingTokenRef = React$1.useRef(null);
1568
1588
  React$1.useEffect(() => {
1569
1589
  const verify = async () => {
1570
1590
  // Pega token da prop ou da URL
@@ -1574,11 +1594,25 @@ function VerifyEmailCard({
1574
1594
  token = urlParams.get('token');
1575
1595
  }
1576
1596
  if (!token) {
1577
- setStatus('error');
1578
- setErrorMessage(labels.noToken || 'Token não encontrado na URL');
1579
- onError?.(new Error('No token'));
1597
+ // Se já mostramos o erro de token faltando, não precisa fazer nada
1598
+ if (status === 'missing_token') return;
1599
+ setStatus('missing_token');
1580
1600
  return;
1581
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;
1582
1616
  try {
1583
1617
  const result = await verifyEmail(token);
1584
1618
  setStatus('success');
@@ -1589,18 +1623,22 @@ function VerifyEmailCard({
1589
1623
  }, redirectDelay);
1590
1624
  }
1591
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
1592
1628
  setStatus('error');
1593
1629
  setErrorMessage(error.message || labels.verificationFailed || 'Verificação falhou');
1594
1630
  onError?.(error);
1595
1631
  }
1596
1632
  };
1597
1633
  verify();
1598
- }, [propToken, verifyEmail, onSuccess, onError, redirectTo, redirectDelay, labels]);
1634
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1635
+ }, [propToken, redirectTo, redirectDelay]);
1599
1636
  const handleResend = async () => {
1600
- if (!email) return;
1637
+ const targetEmail = email || user?.email || tokenEmail;
1638
+ if (!targetEmail) return;
1601
1639
  try {
1602
- await resendVerification(email);
1603
- onResent?.(email);
1640
+ await resendVerification(targetEmail);
1641
+ onResent?.(targetEmail);
1604
1642
  } catch (error) {
1605
1643
  onError?.(error);
1606
1644
  }
@@ -1618,7 +1656,19 @@ function VerifyEmailCard({
1618
1656
  size: "sm",
1619
1657
  c: "dimmed",
1620
1658
  ta: "center"
1621
- }, labels.pleaseWait || 'Aguarde enquanto verificamos seu email...')), status === 'success' && /*#__PURE__*/React.createElement(core.Stack, {
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, {
1622
1672
  align: "center",
1623
1673
  gap: "sm"
1624
1674
  }, /*#__PURE__*/React.createElement(iconsReact.IconCheck, {
@@ -1642,7 +1692,7 @@ function VerifyEmailCard({
1642
1692
  size: "sm",
1643
1693
  c: "dimmed",
1644
1694
  ta: "center"
1645
- }, 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, {
1646
1696
  variant: "light",
1647
1697
  leftSection: /*#__PURE__*/React.createElement(iconsReact.IconRefresh, {
1648
1698
  size: 16
@@ -1650,7 +1700,7 @@ function VerifyEmailCard({
1650
1700
  onClick: handleResend,
1651
1701
  loading: loadingResend,
1652
1702
  fullWidth: true
1653
- }, labels.resend || 'Reenviar Email de Verificação')));
1703
+ }, labels.resend || 'Solicitar novo link')));
1654
1704
  }
1655
1705
 
1656
1706
  exports.AuthCard = AuthCard;
@@ -1664,6 +1714,7 @@ exports.SignInForm = SignInForm;
1664
1714
  exports.SignUpForm = SignUpForm;
1665
1715
  exports.VerifyEmailCard = VerifyEmailCard;
1666
1716
  exports.configure = configure;
1717
+ exports.decodeJWT = decodeJWT;
1667
1718
  exports.forgotPassword = forgotPassword;
1668
1719
  exports.getCurrentUser = getCurrentUser;
1669
1720
  exports.getSession = getSession;