// API service configuration and base client import { useAuth } from '@clerk/clerk-react'; const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3005/api'; // Export function to get the base URL without /api suffix for static assets export const getApiBaseUrl = () => { return (import.meta.env.VITE_API_BASE_URL || 'http://localhost:3005/api').replace('/api', ''); }; export interface ApiError { code: string; message: string; details?: any; timestamp: string; } export class ApiClient { private baseUrl: string; private getToken?: () => Promise; constructor(baseUrl: string = API_BASE_URL) { this.baseUrl = baseUrl; } setTokenGetter(getToken: () => Promise) { this.getToken = getToken; } private async request( endpoint: string, options: RequestInit = {} ): Promise { const url = `${this.baseUrl}${endpoint}`; // Get auth token if available const token = this.getToken ? await this.getToken() : null; const response = await fetch(url, { ...options, headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}), ...options.headers, }, }); if (!response.ok) { let error: ApiError; try { error = await response.json(); } catch { // If response is not JSON, create a generic error throw new Error(`HTTP ${response.status}: ${response.statusText}`); } throw new Error(error.message || 'An error occurred'); } // Handle empty responses (like DELETE) const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return response.json(); } // For non-JSON responses, return empty object return {} as T; } async get(endpoint: string, options?: RequestInit): Promise { return this.request(endpoint, { ...options, method: 'GET' }); } async post(endpoint: string, data?: any, options?: RequestInit): Promise { return this.request(endpoint, { ...options, method: 'POST', body: JSON.stringify(data), }); } async patch(endpoint: string, data?: any, options?: RequestInit): Promise { return this.request(endpoint, { ...options, method: 'PATCH', body: JSON.stringify(data), }); } async delete(endpoint: string, options?: RequestInit): Promise { return this.request(endpoint, { ...options, method: 'DELETE' }); } } export const apiClient = new ApiClient();