Refactor authentication and async operation handling in useAuth composable

- Introduce useMultiAsyncOperation to manage multiple async operations in useAuth, enhancing error handling and loading state management.
- Replace manual loading and error state management with standardized async operation patterns for initialize, login, register, and logout functions.
- Update related components to utilize the new async operation structure, improving code clarity and maintainability.
- Add useAsyncOperation to other composables (useChat, useTicketPurchase, useMarket) for consistent async handling across the application.
This commit is contained in:
padreug 2025-09-05 06:08:08 +02:00
parent e0443742c5
commit 7c439361b7
5 changed files with 298 additions and 133 deletions

View file

@ -1,31 +1,45 @@
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<User | null>(null)
const isLoading = ref(false)
const error = ref<string | null>(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<void> {
try {
isLoading.value = true
error.value = null
if (lnbitsAPI.isAuthenticated()) {
const user = await lnbitsAPI.getCurrentUser()
currentUser.value = user
}
} catch (err) {
error.value = err instanceof Error ? err.message : 'Failed to initialize authentication'
// Clear invalid token
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()
} finally {
isLoading.value = false
}
}
@ -33,88 +47,77 @@ export function useAuth() {
* Login with username and password
*/
async function login(credentials: LoginCredentials): Promise<void> {
try {
isLoading.value = true
error.value = null
await loginOp.execute(async () => {
await lnbitsAPI.login(credentials)
// Get user details
const user = await lnbitsAPI.getCurrentUser()
currentUser.value = user
} catch (err) {
error.value = err instanceof Error ? err.message : 'Login failed'
throw err
} finally {
isLoading.value = false
}
return user
}, {
errorMessage: 'Login failed'
})
}
/**
* Register new user
*/
async function register(data: RegisterData): Promise<void> {
try {
isLoading.value = true
error.value = null
await registerOp.execute(async () => {
await lnbitsAPI.register(data)
// Get user details
const user = await lnbitsAPI.getCurrentUser()
currentUser.value = user
} catch (err) {
error.value = err instanceof Error ? err.message : 'Registration failed'
throw err
} finally {
isLoading.value = false
}
return user
}, {
errorMessage: 'Registration failed'
})
}
/**
* Logout and clear user data
*/
async function logout(): Promise<void> {
// Clear local state
lnbitsAPI.logout()
currentUser.value = null
error.value = null
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<void> {
try {
isLoading.value = true
error.value = null
const updatePasswordOp = authOperations.createOperation('updatePassword' as any)
return await updatePasswordOp.execute(async () => {
const updatedUser = await lnbitsAPI.updatePassword(currentPassword, newPassword)
currentUser.value = updatedUser
} catch (err) {
error.value = err instanceof Error ? err.message : 'Failed to update password'
throw err
} finally {
isLoading.value = false
}
return updatedUser
}, {
errorMessage: 'Failed to update password'
})
}
/**
* Update user profile
*/
async function updateProfile(data: Partial<User>): Promise<void> {
try {
isLoading.value = true
error.value = null
const updateProfileOp = authOperations.createOperation('updateProfile' as any)
return await updateProfileOp.execute(async () => {
const updatedUser = await lnbitsAPI.updateProfile(data)
currentUser.value = updatedUser
} catch (err) {
error.value = err instanceof Error ? err.message : 'Failed to update profile'
throw err
} finally {
isLoading.value = false
}
return updatedUser
}, {
errorMessage: 'Failed to update profile'
})
}
/**
@ -145,8 +148,9 @@ export function useAuth() {
// State
currentUser: computed(() => currentUser.value),
isAuthenticated,
isLoading,
error,
isLoading: computed(() => authOperations.isAnyLoading()),
error: computed(() => authOperations.hasAnyError() ?
(initializeOp.error.value || loginOp.error.value || registerOp.error.value || logoutOp.error.value) : null),
userDisplay,
// Actions