import { getAccessToken, getRefreshToken, setSession, clearSession } from './auth' const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:3100/api/v1' export class ApiError extends Error { status: number constructor(status: number, message: string) { super(message) this.name = 'ApiError' this.status = status } } type RequestOptions = { method?: string body?: unknown auth?: boolean /** Skip refresh retry (used by refresh itself). */ skipRefresh?: boolean } let refreshInFlight: Promise | null = null function parseErrorMessage(payload: unknown, fallback: string) { if (!payload || typeof payload !== 'object') return fallback const message = (payload as { message?: unknown }).message if (typeof message === 'string' && message.trim()) return message if (Array.isArray(message)) { const parts = message.filter((item) => typeof item === 'string') if (parts.length > 0) return parts.join('، ') } return fallback } async function tryRefreshSession(): Promise { if (refreshInFlight) return refreshInFlight refreshInFlight = (async () => { const refreshToken = getRefreshToken() if (!refreshToken) { clearSession() return false } try { const response = await fetch(`${API_BASE_URL}/auth/refresh`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refreshToken }), }) const payload = await response.json().catch(() => null) if (!response.ok) { clearSession() return false } setSession({ accessToken: payload.accessToken, refreshToken: payload.refreshToken, user: payload.user, }) return true } catch { clearSession() return false } finally { refreshInFlight = null } })() return refreshInFlight } export async function apiRequest( path: string, options: RequestOptions = {}, ): Promise { const { method = 'GET', body, auth = true, skipRefresh = false } = options const headers: Record = {} if (body !== undefined) { headers['Content-Type'] = 'application/json' } if (auth) { const token = getAccessToken() if (token) headers.Authorization = `Bearer ${token}` } const response = await fetch(`${API_BASE_URL}${path}`, { method, headers, body: body !== undefined ? JSON.stringify(body) : undefined, }) if (response.status === 401 && auth && !skipRefresh) { const refreshed = await tryRefreshSession() if (refreshed) { return apiRequest(path, { ...options, skipRefresh: true }) } } if (response.status === 204) { return undefined as T } const payload = await response.json().catch(() => null) if (!response.ok) { throw new ApiError( response.status, parseErrorMessage(payload, 'خطایی رخ داد'), ) } return payload as T }