import { ref, computed } from 'vue' import { lnbitsAPI, type User, type LoginCredentials, type RegisterData } from '@/lib/api/lnbits' import { useMultiAsyncOperation } from '@/core/composables/useAsyncOperation' const currentUser = ref(null) // Shared async operations for auth actions const authOperations = useMultiAsyncOperation<{ initialize: User | null login: User register: User logout: void }>() export function useAuth() { const isAuthenticated = computed(() => !!currentUser.value) // Get operation instances const initializeOp = authOperations.createOperation('initialize') const loginOp = authOperations.createOperation('login') const registerOp = authOperations.createOperation('register') const logoutOp = authOperations.createOperation('logout') /** * Initialize authentication on app start */ async function initialize(): Promise { try { await initializeOp.execute(async () => { if (lnbitsAPI.isAuthenticated()) { const user = await lnbitsAPI.getCurrentUser() currentUser.value = user return user } return null }, { errorMessage: 'Failed to initialize authentication', showToast: false // Don't show toast for initialization errors }) } catch { // Clear invalid token on error await logout() } } /** * Login with username and password */ async function login(credentials: LoginCredentials): Promise { await loginOp.execute(async () => { await lnbitsAPI.login(credentials) // Get user details const user = await lnbitsAPI.getCurrentUser() currentUser.value = user return user }, { errorMessage: 'Login failed' }) } /** * Register new user */ async function register(data: RegisterData): Promise { await registerOp.execute(async () => { await lnbitsAPI.register(data) // Get user details const user = await lnbitsAPI.getCurrentUser() currentUser.value = user return user }, { errorMessage: 'Registration failed' }) } /** * Logout and clear user data */ async function logout(): Promise { await logoutOp.execute(async () => { // Clear local state lnbitsAPI.logout() currentUser.value = null // Clear all auth operation states authOperations.clearAll() }, { showToast: false // Don't show toast for logout }) } /** * Update user password */ async function updatePassword(currentPassword: string, newPassword: string): Promise { const updatePasswordOp = authOperations.createOperation('updatePassword' as any) return await updatePasswordOp.execute(async () => { const updatedUser = await lnbitsAPI.updatePassword(currentPassword, newPassword) currentUser.value = updatedUser return updatedUser }, { errorMessage: 'Failed to update password' }) } /** * Update user profile */ async function updateProfile(data: Partial): Promise { const updateProfileOp = authOperations.createOperation('updateProfile' as any) return await updateProfileOp.execute(async () => { const updatedUser = await lnbitsAPI.updateProfile(data) currentUser.value = updatedUser return updatedUser }, { errorMessage: 'Failed to update profile' }) } /** * Check if user is authenticated */ function checkAuth(): boolean { return lnbitsAPI.isAuthenticated() } /** * Get user display info */ const userDisplay = computed(() => { if (!currentUser.value) return null return { name: currentUser.value.username || currentUser.value.email || 'Anonymous', username: currentUser.value.username, email: currentUser.value.email, id: currentUser.value.id, shortId: currentUser.value.id.slice(0, 8) + '...' + currentUser.value.id.slice(-8) } }) return { // State currentUser: computed(() => currentUser.value), isAuthenticated, isLoading: computed(() => authOperations.isAnyLoading()), error: computed(() => authOperations.hasAnyError() ? (initializeOp.error.value || loginOp.error.value || registerOp.error.value || logoutOp.error.value) : null), userDisplay, // Actions initialize, login, register, logout, updatePassword, updateProfile, checkAuth } } // Export singleton instance for global state export const auth = useAuth()