import type { FetchError, FetchOptions } from 'ofetch'; import type { ApiError } from '~/types/api/error'; import type { HttpMethod } from '~/types/http-method'; import { QueryResult } from '~/types/query-result'; export interface UseApi { get: (path: string, opts?: FetchOptions, immediate?: boolean) => UseApiResponse; del: (path: string, opts?: FetchOptions, immediate?: boolean) => UseApiResponse; post: (path: string, opts?: FetchOptions, immediate?: boolean, body?: B) => UseApiResponse; put: (path: string, opts?: FetchOptions, immediate?: boolean, body?: B) => UseApiResponse; patch: (path: string, opts?: FetchOptions, immediate?: boolean, body?: B) => UseApiResponse; } const createRequest = ( method: HttpMethod, url: string, opts?: FetchOptions, immediate: boolean = true, body?: PayloadT, ): QueryResult => { const response = new QueryResult(); const { apiBase } = useRuntimeConfig().public; const run = async (requestBody?: PayloadT): Promise => { response.loading.value = true; response.error.value = null; try { const res = await $fetch(url, { baseURL: apiBase, ...opts, method, body: requestBody ?? undefined, }); response.data.value = res; } catch (e) { const fetchError = e as FetchError; const errBody = fetchError?.response?._data as ApiError | undefined; response.error.value = errBody ?? { message: fetchError.message || 'backend.errors.unknown', success: false, }; } finally { response.loading.value = false; } }; response.run = run; if (immediate) run(body); return response; }; export const useApi = (): UseApi => { const get = (path: string, opts?: FetchOptions, immediate: boolean = true) => createRequest('GET', path, opts, immediate); const del = (path: string, opts?: FetchOptions, immediate: boolean = true) => createRequest('DELETE', path, opts, immediate); const post = (path: string, opts?: FetchOptions, immediate: boolean = true, body?: B) => createRequest('POST', path, opts, immediate, body); const put = (path: string, opts?: FetchOptions, immediate: boolean = true, body?: B) => createRequest('PUT', path, opts, immediate, body); const patch = (path: string, opts?: FetchOptions, immediate: boolean = true, body?: B) => createRequest('PATCH', path, opts, immediate, body); return { get, post, put, patch, del }; };