/** * Design System Server (DSS) - API Client * * Centralized API communication layer. * No mocks - requires backend connection. */ const API_BASE = '/api'; class ApiClient { constructor(baseUrl = API_BASE) { this.baseUrl = baseUrl; this.defaultHeaders = { 'Content-Type': 'application/json' }; this.connected = null; } setAuthToken(token) { if (token) { this.defaultHeaders['Authorization'] = `Bearer ${token}`; } else { delete this.defaultHeaders['Authorization']; } } async request(endpoint, options = {}) { const url = `${this.baseUrl}${endpoint}`; const config = { ...options, headers: { ...this.defaultHeaders, ...options.headers } }; const response = await fetch(url, config); if (!response.ok) { const error = await response.json().catch(() => ({ message: response.statusText })); throw new ApiError(error.detail || error.message || 'Request failed', response.status, error); } const text = await response.text(); return text ? JSON.parse(text) : null; } get(endpoint, options = {}) { return this.request(endpoint, { ...options, method: 'GET' }); } post(endpoint, data, options = {}) { return this.request(endpoint, { ...options, method: 'POST', body: JSON.stringify(data) }); } put(endpoint, data, options = {}) { return this.request(endpoint, { ...options, method: 'PUT', body: JSON.stringify(data) }); } delete(endpoint, options = {}) { return this.request(endpoint, { ...options, method: 'DELETE' }); } // === Domain Methods === async getHealth() { return this.get('/health'); } async getProjects() { return this.get('/projects'); } async getProject(id) { return this.get(`/projects/${id}`); } async createProject(data) { return this.post('/projects', data); } async updateProject(id, data) { return this.put(`/projects/${id}`, data); } async deleteProject(id) { return this.delete(`/projects/${id}`); } async ingestFigma(fileKey, options = {}) { return this.post('/ingest/figma', { file_key: fileKey, ...options }); } async visualDiff(baseline, current) { return this.post('/visual-diff', { baseline, current }); } async getFigmaTasks() { return this.get('/figma-bridge/tasks'); } async sendFigmaTask(task) { return this.post('/figma-bridge/tasks', task); } async getConfig() { return this.get('/config'); } async updateConfig(config) { return this.put('/config', config); } async getFigmaConfig() { return this.get('/config/figma'); } async setFigmaToken(token) { return this.put('/config', { figma_token: token }); } async testFigmaConnection() { return this.post('/config/figma/test', {}); } async getServices() { return this.get('/services'); } async configureService(serviceName, config) { return this.put(`/services/${serviceName}`, config); } async getStorybookStatus() { return this.get('/services/storybook'); } async getMode() { return this.get('/mode'); } async setMode(mode) { return this.put('/mode', { mode }); } async getStats() { return this.get('/stats'); } async getActivity(limit = 50) { return this.get(`/activity?limit=${limit}`); } async executeMCPTool(toolName, params = {}) { return this.post(`/mcp/${toolName}`, params); } async getQuickWins(path = '.') { return this.post('/mcp/get_quick_wins', { path }); } async analyzeProject(path = '.') { return this.post('/mcp/discover_project', { path }); } } class ApiError extends Error { constructor(message, status, data) { super(message); this.name = 'ApiError'; this.status = status; this.data = data; } } const api = new ApiClient(); export { api, ApiClient, ApiError }; export default api;