/** * API Client for Mosaic Stack * Handles authenticated requests to the backend API */ const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:3001"; export interface ApiError { code: string; message: string; details?: unknown; } export interface ApiResponse { data: T; meta?: { total?: number; page?: number; limit?: number; }; } /** * Make an authenticated API request */ export async function apiRequest(endpoint: string, options: RequestInit = {}): Promise { const url = `${API_BASE_URL}${endpoint}`; const response = await fetch(url, { ...options, headers: { "Content-Type": "application/json", ...(options.headers ?? {}), }, credentials: "include", // Include cookies for session }); if (!response.ok) { const error: ApiError = await response.json().catch( (): ApiError => ({ code: "UNKNOWN_ERROR", message: response.statusText || "An unknown error occurred", }) ); throw new Error(error.message); } return response.json() as Promise; } /** * GET request helper */ export async function apiGet(endpoint: string): Promise { return apiRequest(endpoint, { method: "GET" }); } /** * POST request helper */ export async function apiPost(endpoint: string, data?: unknown): Promise { const options: RequestInit = { method: "POST", }; if (data !== undefined) { options.body = JSON.stringify(data); } return apiRequest(endpoint, options); } /** * PATCH request helper */ export async function apiPatch(endpoint: string, data: unknown): Promise { return apiRequest(endpoint, { method: "PATCH", body: JSON.stringify(data), }); } /** * DELETE request helper */ export async function apiDelete(endpoint: string): Promise { return apiRequest(endpoint, { method: "DELETE" }); }