'use client'; /** Browser-side fetches: same origin `/api/v1/*` (Next rewrite → FastAPI). Never import server `api.ts` in client components. */ import type { ChangeEvent, Page, SearchPayload, Suggestion } from './types'; async function get(path: string, signal?: AbortSignal): Promise { const res = await fetch(`/api/v1${path}`, { headers: { accept: 'application/json' }, signal }); if (!res.ok) throw new Error(`API ${res.status} on ${path}`); return (await res.json()) as T; } export const clientApi = { suggest: (q: string, signal?: AbortSignal) => get<{ items: Suggestion[] }>(`/search/suggest?q=${encodeURIComponent(q)}`, signal), search: (q: string, limit = 10, signal?: AbortSignal) => get(`/search?q=${encodeURIComponent(q)}&limit=${limit}`, signal), changes: (qs: string, signal?: AbortSignal) => get>(`/changes?${qs}`, signal), /** Page-view beacon (1 req/s/IP server-side). Fire-and-forget. */ view: (path: string) => fetch('/api/v1/views', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ path }), keepalive: true }).catch(() => undefined), };