import type { FetchOptions } from 'ofetch' import { $fetch, FetchError } from 'ofetch' export type AnyObject = Record export type ApiClient = { get(url: string, query?: AnyObject, options?: FetchOptions<'json'>): Promise post(url: string, body?: AnyObject, options?: FetchOptions<'json'>): Promise put(url: string, body?: AnyObject, options?: FetchOptions<'json'>): Promise patch(url: string, body?: AnyObject, options?: FetchOptions<'json'>): Promise delete(url: string, query?: AnyObject, options?: FetchOptions<'json'>): Promise } export const useApi = (): ApiClient => { const config = useRuntimeConfig() const baseURL = config.public.apiBase ?? '/api' const client = $fetch.create({ baseURL, retry: 0 }) const request = ( method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', url: string, options: FetchOptions<'json'> = {} ) => { const needsJsonBody = method === 'POST' || method === 'PUT' const needsMergePatch = method === 'PATCH' const headers = new Headers(options.headers as HeadersInit | undefined) if (needsMergePatch && !headers.has('Content-Type')) { headers.set('Content-Type', 'application/merge-patch+json') } else if (needsJsonBody && !headers.has('Content-Type')) { headers.set('Content-Type', 'application/json') } return client(url, { ...options, method, headers }) } return { get(url: string, query: AnyObject = {}, options: FetchOptions<'json'> = {}) { return request('GET', url, { ...options, query }) }, post(url: string, body: AnyObject = {}, options: FetchOptions<'json'> = {}) { return request('POST', url, { ...options, body }) }, put(url: string, body: AnyObject = {}, options: FetchOptions<'json'> = {}) { return request('PUT', url, { ...options, body }) }, patch(url: string, body: AnyObject = {}, options: FetchOptions<'json'> = {}) { return request('PATCH', url, { ...options, body }) }, delete(url: string, query: AnyObject = {}, options: FetchOptions<'json'> = {}) { return request('DELETE', url, { ...options, query }) } } }