import { create } from 'zustand'; import { persist } from 'zustand/middleware'; export interface User { accountId: string; displayName: string; emailAddress?: string; avatarUrl?: string; } interface AuthConfig { oauthEnabled: boolean; serviceAccountEnabled: boolean; jiraHost: string; } interface AuthState { // State user: User | null; isAuthenticated: boolean; authMethod: 'oauth' | 'service-account' | null; isLoading: boolean; error: string | null; config: AuthConfig | null; // Actions setUser: (user: User | null, method: 'oauth' | 'service-account' | null) => void; setLoading: (loading: boolean) => void; setError: (error: string | null) => void; setConfig: (config: AuthConfig) => void; logout: () => Promise; checkAuth: () => Promise; fetchConfig: () => Promise; } const API_BASE = import.meta.env.VITE_API_URL || 'http://localhost:3001'; export const useAuthStore = create()( persist( (set, get) => ({ // Initial state user: null, isAuthenticated: false, authMethod: null, isLoading: true, error: null, config: null, // Actions setUser: (user, method) => set({ user, isAuthenticated: !!user, authMethod: method, error: null, }), setLoading: (loading) => set({ isLoading: loading }), setError: (error) => set({ error, isLoading: false }), setConfig: (config) => set({ config }), logout: async () => { try { await fetch(`${API_BASE}/api/auth/logout`, { method: 'POST', credentials: 'include', }); } catch (error) { console.error('Logout error:', error); } set({ user: null, isAuthenticated: false, authMethod: null, error: null, }); }, checkAuth: async () => { set({ isLoading: true }); try { const response = await fetch(`${API_BASE}/api/auth/me`, { credentials: 'include', }); if (!response.ok) { throw new Error('Auth check failed'); } const data = await response.json(); if (data.authenticated) { set({ user: data.user, isAuthenticated: true, authMethod: data.authMethod, isLoading: false, error: null, }); } else { set({ user: null, isAuthenticated: false, authMethod: null, isLoading: false, }); } } catch (error) { console.error('Auth check error:', error); set({ user: null, isAuthenticated: false, authMethod: null, isLoading: false, error: error instanceof Error ? error.message : 'Authentication check failed', }); } }, fetchConfig: async () => { try { const response = await fetch(`${API_BASE}/api/auth/config`, { credentials: 'include', }); if (response.ok) { const config = await response.json(); set({ config }); } } catch (error) { console.error('Failed to fetch auth config:', error); } }, }), { name: 'auth-storage', partialize: (state) => ({ // Only persist non-sensitive data authMethod: state.authMethod, }), } ) ); // Helper to get login URL export function getLoginUrl(): string { return `${API_BASE}/api/auth/login`; }