Spaces:
Running
Running
| const API_BASE = '/api'; | |
| class ApiClient { | |
| private token: string | null = null; | |
| setToken(token: string | null) { | |
| this.token = token; | |
| } | |
| async request<T>( | |
| method: string, | |
| path: string, | |
| body?: any | |
| ): Promise<T> { | |
| const headers: Record<string, string> = { | |
| '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(); | |