61 lines
1.4 KiB
TypeScript
61 lines
1.4 KiB
TypeScript
/**
|
|
* API 호출 유틸리티 composable
|
|
*/
|
|
|
|
interface ApiOptions {
|
|
method?: 'GET' | 'POST' | 'PUT' | 'DELETE'
|
|
body?: any
|
|
query?: Record<string, any>
|
|
}
|
|
|
|
export function useApi() {
|
|
const isLoading = ref(false)
|
|
const error = ref<string | null>(null)
|
|
|
|
/**
|
|
* API 호출 래퍼
|
|
*/
|
|
async function call<T>(url: string, options: ApiOptions = {}): Promise<T> {
|
|
isLoading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
const response = await $fetch<T>(url, {
|
|
method: options.method || 'GET',
|
|
body: options.body,
|
|
query: options.query
|
|
})
|
|
return response
|
|
} catch (err: any) {
|
|
const message = err.data?.message || err.message || '요청 처리 중 오류가 발생했습니다.'
|
|
error.value = message
|
|
throw new Error(message)
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
// 편의 메서드들
|
|
const get = <T>(url: string, query?: Record<string, any>) =>
|
|
call<T>(url, { method: 'GET', query })
|
|
|
|
const post = <T>(url: string, body?: any) =>
|
|
call<T>(url, { method: 'POST', body })
|
|
|
|
const put = <T>(url: string, body?: any) =>
|
|
call<T>(url, { method: 'PUT', body })
|
|
|
|
const del = <T>(url: string) =>
|
|
call<T>(url, { method: 'DELETE' })
|
|
|
|
return {
|
|
isLoading: readonly(isLoading),
|
|
error: readonly(error),
|
|
call,
|
|
get,
|
|
post,
|
|
put,
|
|
del
|
|
}
|
|
}
|