/** * API Client — تنها راه ارتباط frontend با backend. * توکن SSO از sessionStorage به هدر Authorization اضافه می‌شود. */ import { getStoredToken } from "./auth"; const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000"; export class ApiError extends Error { constructor( public status: number, public code: string, message: string ) { super(message); this.name = "ApiError"; } } interface RequestOptions extends RequestInit { tenantId?: string; tenantSlug?: string; } async function request(path: string, options: RequestOptions = {}): Promise { const { tenantId, tenantSlug, headers: customHeaders, ...init } = options; const headers = new Headers(customHeaders); headers.set("Content-Type", "application/json"); const token = getStoredToken(); if (token) headers.set("Authorization", `Bearer ${token}`); if (tenantId) headers.set("X-Tenant-ID", tenantId); if (tenantSlug) headers.set("X-Tenant-Slug", tenantSlug); const res = await fetch(`${API_BASE}${path}`, { ...init, headers }); if (!res.ok) { const body = await res.json().catch(() => ({})); throw new ApiError( res.status, body?.error?.code || "unknown_error", body?.error?.message || res.statusText ); } return res.json() as Promise; } export const api = { health: () => request<{ status: string; service: string }>("/health"), tenants: { list: (page = 1, pageSize = 20) => request(`/api/v1/tenants?page=${page}&page_size=${pageSize}`), get: (id: string) => request(`/api/v1/tenants/${id}`), create: (data: { name: string; slug: string }) => request("/api/v1/tenants", { method: "POST", body: JSON.stringify(data) }), }, };