const API_BASE = '/api'; class ApiClient { private token: string | null = null; setToken(token: string | null) { this.token = token; } async request( method: string, path: string, body?: any ): Promise { const headers: Record = { 'Content-Type': 'application/json', }; if (this.token) { headers['Authorization'] = `Bearer ${this.token}`; } const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 30000); try { const response = await fetch(`${API_BASE}${path}`, { method, headers, body: body ? JSON.stringify(body) : undefined, signal: controller.signal, }); const data = await response.json(); if (!response.ok) { throw new ApiError(data.error || 'Request failed', response.status, data.details); } return data; } catch (err: any) { if (err instanceof ApiError) throw err; if (err.name === 'AbortError') throw new ApiError('Request timed out', 0); throw new ApiError(err.message || 'Network error', 0); } finally { clearTimeout(timeout); } } // Auth async register(email: string, username: string, password: string) { return this.request<{ token: string; user: any }>('POST', '/auth/register', { email, username, password }); } async login(email: string, password: string) { return this.request<{ token: string; user: any }>('POST', '/auth/login', { email, password }); } async logout() { return this.request<{ message: string }>('POST', '/auth/logout'); } async forgotPassword(email: string) { return this.request<{ message: string }>('POST', '/auth/forgot-password', { email }); } async resetPassword(token: string, password: string) { return this.request<{ message: string }>('POST', '/auth/reset-password', { token, password }); } async verifyEmail(token: string) { return this.request<{ message: string }>('POST', '/auth/verify-email', { token }); } async getMe() { return this.request<{ user: any }>('GET', '/auth/me'); } // Projects moved to WebSocket - see wsStore and projectStore } export class ApiError extends Error { constructor( message: string, public status: number, public details?: any ) { super(message); this.name = 'ApiError'; } } export const api = new ApiClient();