@riligar/auth-react 1.16.0 → 1.18.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 CHANGED
@@ -22,14 +22,17 @@ const getEnvVar = key => {
22
22
  };
23
23
  let API_BASE = (typeof window !== 'undefined' && window?.location ? getEnvVar('VITE_API_BASE') : null) || 'http://localhost:3000';
24
24
  let API_KEY = null;
25
+ let INTERNAL_MODE = false; // Modo interno: não exige API Key (para aplicações same-domain)
25
26
 
26
- // Permite configurar a API base e key externamente (chamado pelo AuthProvider)
27
+ // Permite configurar a API base, key e modo interno externamente (chamado pelo AuthProvider)
27
28
  function configure({
28
29
  apiUrl,
29
- apiKey
30
+ apiKey,
31
+ internal = false
30
32
  }) {
31
33
  if (apiUrl) API_BASE = apiUrl.replace(/\/$/, ''); // Remove trailing slash
32
34
  if (apiKey) API_KEY = apiKey;
35
+ INTERNAL_MODE = internal;
33
36
  }
34
37
 
35
38
  // helper fetch pré-configurado
@@ -51,12 +54,14 @@ async function api(route, opts = {}) {
51
54
  headers.Authorization = `Bearer ${token}`;
52
55
  }
53
56
 
54
- // Adiciona API Key se configurada
55
- if (API_KEY) {
57
+ // Adiciona API Key se configurada e não estiver em modo interno
58
+ if (API_KEY && !INTERNAL_MODE) {
56
59
  headers['X-API-Key'] = API_KEY;
57
60
  }
58
61
  const res = await fetch(url, {
59
62
  headers,
63
+ credentials: 'include',
64
+ // Required for sending session cookies
60
65
  ...opts
61
66
  });
62
67
 
@@ -387,46 +392,33 @@ const useAuthStore = create((set, get) => ({
387
392
  try {
388
393
  // Buscar application info primeiro (não bloqueia o init)
389
394
  fetchApplicationInfo();
395
+ let user = null;
390
396
 
391
- // Verifica se um token válido
392
- if (isAuthenticated()) {
393
- // Tenta extrair usuário do token (JWT)
394
- let user = getCurrentUser();
395
-
396
- // Se o token for opaco (não-JWT), getCurrentUser retorna null.
397
- // Precisamos buscar a sessão no servidor.
398
- if (!user) {
399
- try {
400
- const sessionData = await getSession();
401
- if (sessionData?.user) {
402
- user = sessionData.user;
403
- }
404
- if (sessionData?.session) {
405
- set({
406
- currentSession: sessionData.session
407
- });
408
- }
409
- } catch (sessionError) {
410
- console.warn('[AuthStore] Failed to fetch session:', sessionError);
411
- }
397
+ // PRIMEIRO: Tenta buscar sessão do servidor (funciona com cookies)
398
+ // Isso é essencial para Better Auth que usa session cookies
399
+ try {
400
+ const sessionData = await getSession();
401
+ if (sessionData?.user) {
402
+ user = sessionData.user;
412
403
  }
413
- if (user) {
414
- set({
415
- user,
416
- loading: false
417
- });
418
- } else {
404
+ if (sessionData?.session) {
419
405
  set({
420
- user: null,
421
- loading: false
406
+ currentSession: sessionData.session
422
407
  });
423
408
  }
424
- } else {
425
- set({
426
- user: null,
427
- loading: false
428
- });
409
+ } catch (sessionError) {
410
+ // Se falhar (401), continua para verificar localStorage token
411
+ console.log('[AuthStore] Server session not found, checking local token');
429
412
  }
413
+
414
+ // SEGUNDO: Se não encontrou sessão via cookies, verifica localStorage token (JWT)
415
+ if (!user && isAuthenticated()) {
416
+ user = getCurrentUser();
417
+ }
418
+ set({
419
+ user,
420
+ loading: false
421
+ });
430
422
  } catch (error) {
431
423
  console.error('Erro na inicialização:', error);
432
424
  set({
@@ -704,19 +696,41 @@ const useAuthStore = create((set, get) => ({
704
696
  throw err;
705
697
  }
706
698
  },
707
- revokeSession: async token => {
699
+ revokeSession: async sessionId => {
708
700
  const {
709
701
  setLoading,
710
- listSessions
702
+ currentSession,
703
+ sessions,
704
+ signOut
711
705
  } = get();
712
706
  setLoading('revokeSession', true);
713
707
  set({
714
708
  error: null
715
709
  });
716
710
  try {
717
- await revokeSession(token);
718
- // Refresh sessions list after revocation
719
- await listSessions();
711
+ console.log('[AuthStore] Revoking session:', {
712
+ targetId: sessionId,
713
+ currentId: currentSession?.id,
714
+ totalSessions: sessions.length
715
+ });
716
+
717
+ // Detect if current session OR last remaining session
718
+ const isCurrent = sessionId === currentSession?.id;
719
+ const isLast = sessions.length === 1 && sessions[0].id === sessionId;
720
+
721
+ // Se for a sessão atual ou a última, faz logout normal
722
+ if (isCurrent || isLast) {
723
+ console.log('[AuthStore] Revoking current/last session -> Executing signOut');
724
+ await signOut();
725
+ // signOut já limpa loading states e erros no finally, mas
726
+ // como estamos dentro do fluxo deste método, garantimos:
727
+ setLoading('revokeSession', false);
728
+ return;
729
+ }
730
+ await revokeSession(sessionId);
731
+
732
+ // NÃO atualiza a lista automaticamente - se for a sessão atual,
733
+ // listSessions() vai falhar com 401. O componente decide se quer atualizar.
720
734
  setLoading('revokeSession', false);
721
735
  } catch (err) {
722
736
  set({
@@ -884,11 +898,14 @@ function AuthProvider({
884
898
  apiUrl,
885
899
  // URL base da API (OBRIGATÓRIA)
886
900
  apiKey,
887
- // API Key para header X-API-Key (OBRIGATÓRIA)
901
+ // API Key para header X-API-Key (obrigatória exceto em modo internal)
902
+ internal = false,
903
+ // Modo interno: não exige API Key (para aplicações same-domain como dashboard)
888
904
  onError // Callback de erro global
889
905
  }) {
890
906
  // Validação de props obrigatórias
891
- if (!apiKey) {
907
+ // apiKey só é obrigatória se não estiver em modo internal
908
+ if (!internal && !apiKey) {
892
909
  throw new Error('[@riligar/auth-react] apiKey é obrigatória no AuthProvider. ' + 'Obtenha sua API Key no dashboard em https://dashboard.myauth.click');
893
910
  }
894
911
  if (!apiUrl) {
@@ -898,15 +915,15 @@ function AuthProvider({
898
915
  const startRefresh = useAuthStore(s => s.startRefresh);
899
916
  const checkTokenValidity = useAuthStore(s => s.checkTokenValidity);
900
917
 
901
- // Configura SDK com apiUrl e apiKey
902
- // Configura SDK com apiUrl e apiKey
918
+ // Configura SDK com apiUrl, apiKey e modo interno
903
919
  // Usamos useMemo para garantir que a configuração ocorra ANTES dos efeitos dos componentes filhos
904
920
  useMemo(() => {
905
921
  configure({
906
922
  apiUrl,
907
- apiKey
923
+ apiKey,
924
+ internal
908
925
  });
909
- }, [apiUrl, apiKey]);
926
+ }, [apiUrl, apiKey, internal]);
910
927
  useEffect(() => {
911
928
  init();
912
929
  startRefresh();
@@ -935,6 +952,8 @@ function AuthProvider({
935
952
  });
936
953
  // Dispara evento de logout para sincronizar entre abas
937
954
  localStorage.setItem('auth:logout', Date.now());
955
+ // Recarrega para redirecionar - deixa o Protect/rotas decidirem para onde ir
956
+ window.location.reload();
938
957
  };
939
958
  window.addEventListener('storage', handleStorageChange);
940
959
  window.addEventListener('auth:session-revoked', handleSessionRevoked);