/** * API Client * Centralized HTTP client for backend communication */ import CONFIG from '../config.js'; class APIClient { constructor() { this.baseURL = CONFIG.API.BASE_URL; this.timeout = CONFIG.API.TIMEOUT; this.currentProjectId = 1; // Default project } /** * Set current project ID */ setProjectId(projectId) { this.currentProjectId = projectId; } /** * Generic HTTP request with error handling * @private */ async request(url, options = {}) { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.timeout); try { const response = await fetch(this.baseURL + url, { headers: { 'Content-Type': 'application/json', ...options.headers }, signal: controller.signal, ...options }); clearTimeout(timeoutId); if (!response.ok) { const error = await response.json(); throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`); } return await response.json(); } catch (err) { clearTimeout(timeoutId); if (err.name === 'AbortError') { throw new Error('Request timeout - server is not responding'); } throw err; } } // ==================== PROJECTS ==================== async getProjects() { return this.request('/api/projects'); } async getProject(id) { return this.request(`/api/projects/${id}`); } async createProject(name, description = '') { return this.request('/api/projects', { method: 'POST', body: JSON.stringify({ name, description }) }); } async updateProject(id, name, description) { return this.request(`/api/projects/${id}`, { method: 'PUT', body: JSON.stringify({ name, description }) }); } async deleteProject(id) { return this.request(`/api/projects/${id}`, { method: 'DELETE' }); } // ==================== RACKS ==================== async getRacks(projectId = this.currentProjectId) { return this.request(`/api/racks?projectId=${projectId}`); } async getNextRackName(prefix = 'RACK', projectId = this.currentProjectId) { const data = await this.request(`/api/racks/next-name?projectId=${projectId}&prefix=${prefix}`); return data.name; } async createRack(name, x, y, projectId = this.currentProjectId) { return this.request('/api/racks', { method: 'POST', body: JSON.stringify({ projectId, name, x, y }) }); } async updateRackPosition(id, x, y) { return this.request(`/api/racks/${id}/position`, { method: 'PUT', body: JSON.stringify({ x, y }) }); } async updateRackName(id, name) { return this.request(`/api/racks/${id}/name`, { method: 'PUT', body: JSON.stringify({ name }) }); } async deleteRack(id) { return this.request(`/api/racks/${id}`, { method: 'DELETE' }); } // ==================== DEVICE TYPES ==================== async getDeviceTypes() { return this.request('/api/devices/types'); } // ==================== DEVICES ==================== async getDevices(projectId = this.currentProjectId) { return this.request(`/api/devices?projectId=${projectId}`); } async createDevice(deviceTypeId, rackId, position, name) { return this.request('/api/devices', { method: 'POST', body: JSON.stringify({ deviceTypeId, rackId, position, name }) }); } async updateDeviceRack(id, rackId, position) { return this.request(`/api/devices/${id}/rack`, { method: 'PUT', body: JSON.stringify({ rackId, position }) }); } async updateDeviceLogicalPosition(id, x, y) { return this.request(`/api/devices/${id}/logical-position`, { method: 'PUT', body: JSON.stringify({ x, y }) }); } async updateDeviceName(id, name) { return this.request(`/api/devices/${id}/name`, { method: 'PUT', body: JSON.stringify({ name }) }); } async updateDeviceRackUnits(id, rackUnits) { return this.request(`/api/devices/${id}/rack-units`, { method: 'PUT', body: JSON.stringify({ rackUnits }) }); } async getUsedPorts(deviceId) { return this.request(`/api/devices/${deviceId}/used-ports`); } async deleteDevice(id) { return this.request(`/api/devices/${id}`, { method: 'DELETE' }); } // ==================== CONNECTIONS ==================== async getConnections(projectId = this.currentProjectId) { return this.request(`/api/connections?projectId=${projectId}`); } async createConnection(sourceDeviceId, sourcePort, targetDeviceId, targetPort) { return this.request('/api/connections', { method: 'POST', body: JSON.stringify({ sourceDeviceId, sourcePort, targetDeviceId, targetPort }) }); } async updateConnection(id, sourceDeviceId, sourcePort, targetDeviceId, targetPort) { return this.request(`/api/connections/${id}`, { method: 'PUT', body: JSON.stringify({ sourceDeviceId, sourcePort, targetDeviceId, targetPort }) }); } async updateConnectionWaypoints(id, waypoints, view = null) { return this.request(`/api/connections/${id}/waypoints`, { method: 'PUT', body: JSON.stringify({ waypoints, view }) }); } async deleteConnection(id) { return this.request(`/api/connections/${id}`, { method: 'DELETE' }); } // ==================== HEALTH CHECK ==================== async healthCheck() { return this.request('/api/health'); } } // Export singleton instance export default new APIClient();