import { authStore } from '$lib/stores/auth.js'; import { get } from 'svelte/store'; /** * @typedef {import('./types.js').APIResponse} APIResponse * @typedef {import('./types.js').AuthTokens} AuthTokens */ export const API_BASE = import.meta.env.VITE_API_URL || 'http://localhost:8080'; /** * Make authenticated API request * @template T * @param {string} endpoint * @param {RequestInit} [options] * @returns {Promise} */ export async function apiRequest(endpoint, options = {}) { const auth = get(authStore); const headers = { 'Content-Type': 'application/json', ...options.headers }; if (auth.accessToken) { headers['Authorization'] = `Bearer ${auth.accessToken}`; } try { const response = await fetch(`${API_BASE}${endpoint}`, { ...options, headers }); if (response.status === 401 && auth.refreshToken) { const refreshed = await refreshAccessToken(auth.refreshToken); if (refreshed) { headers['Authorization'] = `Bearer ${refreshed.access_token}`; return apiRequest(endpoint, { ...options, headers }); } } if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const result = await response.json(); if (!result.success) { throw new Error(result.error || 'Unknown error'); } return result.data; } catch (error) { console.error(`API Error [${endpoint}]:`, error); throw error; } } /** * Refresh access token * @param {string} refreshToken * @returns {Promise} */ async function refreshAccessToken(refreshToken) { try { const response = await fetch(`${API_BASE}/auth/refresh`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refresh_token: refreshToken }) }); if (!response.ok) return null; const result = await response.json(); if (result.success) { authStore.setTokens(result.data); return result.data; } return null; } catch { return null; } }