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 type UseApiResponse = QueryResult; 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; } export interface CreateRequestOptions { host?: string; path: string; immediate?: boolean; method: HttpMethod; body?: PayloadT; opts?: FetchOptions; } const createRequest = ( options: CreateRequestOptions, ): 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(options.path, { ...options.opts, baseURL: options.host ?? apiBase, method: options.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 (options.immediate) run(options.body); return response; }; export const useApi = (host?: string): UseApi => { const get = (path: string, opts?: FetchOptions, immediate: boolean = true) => createRequest({ method: 'GET', path, opts, immediate, host }); const del = (path: string, opts?: FetchOptions, immediate: boolean = true) => createRequest({ method: 'DELETE', path, opts, immediate, host }); const post = (path: string, opts?: FetchOptions, immediate: boolean = true, body?: B) => createRequest({ method: 'POST', path, opts, immediate, body, host }); const put = (path: string, opts?: FetchOptions, immediate: boolean = true, body?: B) => createRequest({ method: 'PUT', path, opts, immediate, body, host }); const patch = (path: string, opts?: FetchOptions, immediate: boolean = true, body?: B) => createRequest({ method: 'PATCH', path, opts, immediate, body, host }); return { get, post, put, patch, del }; };