File size: 2,526 Bytes
ec17af3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import { create } from "zustand";
import {
  authApi,
  clearToken,
  ensureAccessToken,
  hasValidToken,
  setToken,
} from "@/lib/api";

type AuthState = {
  userEmail: string | null;
  loading: boolean;
  bootstrapped: boolean;
  bootstrap: () => Promise<boolean>;
  login: (email: string, password: string) => Promise<void>;
  signup: (email: string, password: string) => Promise<void>;
  setup: (email: string, password: string) => Promise<void>;
  logout: () => Promise<void>;
};

export const useAuthStore = create<AuthState>((set, get) => ({
  userEmail: null,
  loading: false,
  bootstrapped: false,
  bootstrap: async () => {
    const state = get();
    if (state.bootstrapped && state.userEmail && hasValidToken()) {
      return true;
    }
    const token = await ensureAccessToken();
    if (!token) {
      set({ userEmail: null, bootstrapped: true });
      return false;
    }
    try {
      const user = await authApi.me();
      set({ userEmail: user.email, bootstrapped: true });
      return true;
    } catch {
      clearToken();
      set({ userEmail: null, bootstrapped: true });
      return false;
    }
  },
  login: async (email, password) => {
    set({ loading: true });
    try {
      const token = await authApi.login(email, password);
      setToken(token.access_token, token.expires_in, token.refresh_token);
      set({
        userEmail: token.user?.email || email,
        loading: false,
        bootstrapped: true,
      });
    } catch (error) {
      set({ loading: false });
      throw error;
    }
  },
  signup: async (email, password) => {
    set({ loading: true });
    try {
      const token = await authApi.signup(email, password);
      setToken(token.access_token, token.expires_in, token.refresh_token);
      set({
        userEmail: token.user?.email || email,
        loading: false,
        bootstrapped: true,
      });
    } catch (error) {
      set({ loading: false });
      throw error;
    }
  },
  setup: async (email, password) => {
    set({ loading: true });
    try {
      const token = await authApi.setup(email, password);
      setToken(token.access_token, token.expires_in, token.refresh_token);
      set({
        userEmail: token.user?.email || email,
        loading: false,
        bootstrapped: true,
      });
    } catch (error) {
      set({ loading: false });
      throw error;
    }
  },
  logout: async () => {
    await authApi.logout().catch(() => {});
    clearToken();
    set({ userEmail: null, bootstrapped: true });
  },
}));