import { useAuthStore } from '@/stores/auth' import router from '@/router' const BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000/api/v1' export function useApi() { const authStore = useAuthStore() async function refreshAccessToken(): Promise { try { const response = await fetch(`${BASE_URL}/auth/refresh`, { method: 'POST', credentials: 'include' // Include cookies for refresh token }) if (response.ok) { const data = await response.json() authStore.token = data.access_token localStorage.setItem('access_token', data.access_token) return data.access_token } } catch { // Refresh failed } return null } async function request(endpoint: string, options: RequestInit = {}, retryCount = 0): Promise { const headers: Record = { 'Content-Type': 'application/json', ...(options.headers as Record || {}) } // Only add Authorization header for non-auth endpoints // Auth endpoints (login, register, refresh) should NOT receive the old token if (authStore.token && !endpoint.includes('/auth/')) { headers['Authorization'] = `Bearer ${authStore.token}` } const response = await fetch(`${BASE_URL}${endpoint}`, { ...options, headers, body: options.body ? JSON.stringify(options.body) : undefined }) if (response.status === 401) { // Try to refresh token once if (retryCount === 0 && !endpoint.includes('/auth/')) { const newToken = await refreshAccessToken() if (newToken) { // Retry original request with new token headers['Authorization'] = `Bearer ${newToken}` const retryResponse = await fetch(`${BASE_URL}${endpoint}`, { ...options, headers, credentials: 'include', // Include cookies for auth body: options.body ? JSON.stringify(options.body) : undefined }) if (retryResponse.ok) { if (retryResponse.status === 204) { return {} as T } return retryResponse.json() } } } authStore.logout() router.push('/login') throw new Error('Unauthorized') } if (!response.ok) { const error = await response.json().catch(() => ({ detail: 'Request failed' })) throw new Error(error.detail || `HTTP ${response.status}`) } if (response.status === 204) { return {} as T } return response.json() } return { get: (endpoint: string) => request(endpoint, { method: 'GET' }), // eslint-disable-next-line @typescript-eslint/no-explicit-any post: (endpoint: string, body?: any) => request(endpoint, { method: 'POST', body }), // eslint-disable-next-line @typescript-eslint/no-explicit-any put: (endpoint: string, body?: any) => request(endpoint, { method: 'PUT', body }), delete: (endpoint: string) => request(endpoint, { method: 'DELETE' }) } }