export interface ApiResponse { status: number data: T ok: boolean } export interface ApiClient { get(path: string, params?: Record): Promise> post(path: string, body?: unknown): Promise> patch(path: string, body?: unknown): Promise> del(path: string): Promise> } function buildQueryString(params?: Record): string { if (!params) return '' const sp = new URLSearchParams() for (const [k, v] of Object.entries(params)) { if (v !== undefined && v !== null && v !== '') sp.set(k, String(v)) } const qs = sp.toString() return qs ? `?${qs}` : '' } export function createClient(baseUrl: string, token?: string): ApiClient { async function request(method: string, path: string, body?: unknown): Promise> { const headers: Record = {} if (body !== undefined) headers['Content-Type'] = 'application/json' if (token) headers['Authorization'] = `Bearer ${token}` const res = await fetch(`${baseUrl}${path}`, { method, headers, body: body !== undefined ? JSON.stringify(body) : undefined, }) const data = await res.json() as T return { status: res.status, data, ok: res.ok } } return { get: (path: string, params?: Record) => request('GET', `${path}${buildQueryString(params)}`), post: (path: string, body?: unknown) => request('POST', path, body), patch: (path: string, body?: unknown) => request('PATCH', path, body), del: (path: string) => request('DELETE', path), } }