const API_URL = import.meta.env.VITE_API_URL || '/api' async function fetchAPI(endpoint, options = {}) { const response = await fetch(`${API_URL}${endpoint}`, { ...options, headers: { 'Content-Type': 'application/json', ...options.headers, }, }) // Auto-logout on auth errors (invalid/expired token) if (response.status === 401 || response.status === 403) { localStorage.removeItem('gsm_token') window.location.href = '/' throw new Error('Session expired') } if (!response.ok) { const error = await response.json().catch(() => ({ message: 'Request failed' })) throw new Error(error.message || `HTTP ${response.status}`) } return response.json() } // Auth export async function login(username, password) { return fetchAPI('/auth/login', { method: 'POST', body: JSON.stringify({ username, password }), }) } export async function getMe(token) { return fetchAPI('/auth/me', { headers: { Authorization: `Bearer ${token}` }, }) } export async function changePassword(currentPassword, newPassword) { const token = localStorage.getItem('gsm_token') return fetchAPI('/auth/change-password', { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ currentPassword, newPassword }), }) } // Servers export async function getServers(token) { return fetchAPI('/servers', { headers: { Authorization: `Bearer ${token}` }, }) } export async function serverAction(token, serverId, action, body = null) { return fetchAPI(`/servers/${serverId}/${action}`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, ...(body && { body: JSON.stringify(body) }), }) } export async function getWhitelist(token, serverId) { const headers = token ? { Authorization: `Bearer ${token}` } : {} return fetchAPI(`/servers/${serverId}/whitelist`, { headers }) } export async function sendRcon(token, serverId, command) { return fetchAPI(`/servers/${serverId}/rcon`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ command }), }) } export async function getServerLogs(token, serverId, lines = 50) { return fetchAPI(`/servers/${serverId}/logs?lines=${lines}`, { headers: { Authorization: `Bearer ${token}` }, }) } // Metrics export async function getMetricsHistory(token, serverId, range = '1h') { return fetchAPI(`/servers/${serverId}/metrics/history?range=${range}`, { headers: { Authorization: `Bearer ${token}` }, }) } // Users (admin only) export async function getUsers(token) { return fetchAPI('/auth/users', { headers: { Authorization: `Bearer ${token}` }, }) } export async function createUser(token, userData) { return fetchAPI('/auth/users', { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify(userData), }) } export async function updateUserRole(token, userId, role) { return fetchAPI(`/auth/users/${userId}/role`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ role }), }) } export async function updateUserPassword(token, userId, password) { return fetchAPI(`/auth/users/${userId}/password`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ password }), }) } export async function deleteUser(token, userId) { return fetchAPI(`/auth/users/${userId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) } // Factorio World Management export async function getFactorioSaves(token) { return fetchAPI('/servers/factorio/saves', { headers: { Authorization: `Bearer ${token}` }, }) } export async function getFactorioPresets(token) { return fetchAPI('/servers/factorio/presets', { headers: { Authorization: `Bearer ${token}` }, }) } export async function getFactorioPreset(token, name) { return fetchAPI(`/servers/factorio/presets/${name}`, { headers: { Authorization: `Bearer ${token}` }, }) } export async function getFactorioTemplates(token) { return fetchAPI('/servers/factorio/templates', { headers: { Authorization: `Bearer ${token}` }, }) } export async function createFactorioTemplate(token, name, settings) { return fetchAPI('/servers/factorio/templates', { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ name, settings }), }) } export async function deleteFactorioTemplate(token, id) { return fetchAPI(`/servers/factorio/templates/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) } export async function createFactorioWorld(token, saveName, settings) { return fetchAPI('/servers/factorio/create-world', { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ saveName, settings }), }) } export async function deleteFactorioSave(token, saveName) { return fetchAPI(`/servers/factorio/saves/${encodeURIComponent(saveName)}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) } export async function getFactorioCurrentSave(token) { return fetchAPI('/servers/factorio/current-save', { headers: { Authorization: `Bearer ${token}` }, }) } export async function getFactorioWorldSettings(token, saveName) { return fetchAPI(`/servers/factorio/saves/${encodeURIComponent(saveName)}/settings`, { headers: { Authorization: `Bearer ${token}` }, }) } // Auto-Shutdown Settings export async function getAutoShutdownSettings(token, serverId) { return fetchAPI(`/servers/${serverId}/autoshutdown`, { headers: { Authorization: `Bearer ${token}` }, }) } export async function setAutoShutdownSettings(token, serverId, enabled, timeoutMinutes) { return fetchAPI(`/servers/${serverId}/autoshutdown`, { method: 'PUT', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ enabled, timeoutMinutes }), }) } // Zomboid Config Management export async function getZomboidConfigs(token) { return fetchAPI('/servers/zomboid/config', { headers: { Authorization: `Bearer ${token}` }, }) } export async function getZomboidConfig(token, filename) { return fetchAPI(`/servers/zomboid/config/${encodeURIComponent(filename)}`, { headers: { Authorization: `Bearer ${token}` }, }) } export async function saveZomboidConfig(token, filename, content) { return fetchAPI(`/servers/zomboid/config/${encodeURIComponent(filename)}`, { method: 'PUT', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ content }), }) } // Palworld Config Management export async function getPalworldConfigs(token) { return fetchAPI('/servers/palworld/config', { headers: { Authorization: `Bearer ${token}` }, }) } export async function getPalworldConfig(token, filename) { return fetchAPI(`/servers/palworld/config/${encodeURIComponent(filename)}`, { headers: { Authorization: `Bearer ${token}` }, }) } export async function savePalworldConfig(token, filename, content) { return fetchAPI(`/servers/palworld/config/${encodeURIComponent(filename)}`, { method: 'PUT', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ content }), }) } // Terraria Config Management export async function getTerrariaConfig(token) { return fetchAPI('/servers/terraria/config', { headers: { Authorization: `Bearer ${token}` }, }) } export async function saveTerrariaConfig(token, content) { return fetchAPI('/servers/terraria/config', { method: 'PUT', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ content }), }) } // OpenTTD Config Management export async function getOpenTTDConfig(token) { return fetchAPI('/servers/openttd/config', { headers: { Authorization: `Bearer ${token}` }, }) } export async function saveOpenTTDConfig(token, content) { return fetchAPI('/servers/openttd/config', { method: 'PUT', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ content }), }) } // Activity Log export async function getActivityLog(token, limit = 100) { return fetchAPI(`/servers/activity-log?limit=${limit}`, { headers: { Authorization: `Bearer ${token}` }, }) } // Display Settings export async function getAllDisplaySettings(token) { return fetchAPI('/servers/display-settings', { headers: token ? { Authorization: `Bearer ${token}` } : {}, }) } export async function getDisplaySettings(token, serverId) { return fetchAPI(`/servers/${serverId}/display-settings`, { headers: { Authorization: `Bearer ${token}` }, }) } export async function saveDisplaySettings(token, serverId, address, hint) { return fetchAPI(`/servers/${serverId}/display-settings`, { method: 'PUT', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ address, hint }), }) } // Alias for backwards compatibility export const setDisplaySettings = saveDisplaySettings