- 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.
168 lines
No EOL
4.5 KiB
TypeScript
168 lines
No EOL
4.5 KiB
TypeScript
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)
|
|
|
|
// 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 {
|
|
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<void> {
|
|
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<void> {
|
|
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<void> {
|
|
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> {
|
|
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<User>): Promise<void> {
|
|
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()
|