import { useAuthStore } from '@/stores/authStore.js'; const BASE_URL = 'http://localhost:9000/api/v2'; let isRefreshing = false; let refreshPromise = null; function createConfig(options = {}) { const authStore = useAuthStore(); const headers = { 'Content-Type': 'application/json', ...options.headers, }; if (authStore.accessToken) { headers['Authorization'] = `Bearer ${authStore.accessToken}`; } return { headers, credentials: 'include', ...options, }; } async function refreshAccessToken() { const authStore = useAuthStore(); if (isRefreshing) return refreshPromise; isRefreshing = true; refreshPromise = fetch(`${BASE_URL}/user/auth/refresh`, { method: 'POST', credentials: 'include', }) .then(async (res) => { if (!res.ok) throw new Error('Failed to refresh access token'); return res.json(); }) .then((data) => { authStore.setToken(data.accessToken); return data; }) .catch((error) => { throw error; }) .finally(() => { isRefreshing = false; refreshPromise = null; }); return refreshPromise; } async function request(url, options = {}, isRetry = false) { const config = createConfig(options); const response = await fetch(`${BASE_URL}${url}`, config); if (response.status === 401 && !isRetry) { try { const data = await refreshAccessToken(); const newOptions = { ...options, headers: { ...options.headers, 'Authorization': `Bearer ${data.accessToken}`, }, }; return await request(url, newOptions, true); } catch (e) { const authStore = useAuthStore(); authStore.forceLogout(); throw e; } } if (!response.ok) { let errorData; try { errorData = await response.json(); } catch { errorData = {}; } throw new Error(errorData.message || `HTTP Error: ${response.status}`); } const contentType = response.headers.get('content-type'); if (contentType?.includes('application/json')) { try { return await response.json(); } catch (e) { console.warn('Failed to parse JSON response', e); return null; } } return null; } export const apiClient = { get: (url) => request(url, { method: 'GET' }), post: (url, data) => request(url, { method: 'POST', body: JSON.stringify(data), }), put: (url, data) => request(url, { method: 'PUT', body: JSON.stringify(data), }), delete: (url) => request(url, { method: 'DELETE' }), };