Files
GSM/gsm-frontend/src/api.js
Alexander Zielonka 1010fe7d11 Add OpenTTD and Terraria support, improve config editors
- Add OpenTTD server integration (config editor, server card, API)
- Add Terraria server integration (config editor, API)
- Add legends to all config editors for syntax highlighting
- Simplify UserManagement: remove edit/delete buttons, add Discord avatars
- Add auto-logout on 401/403 API errors
- Update save button styling with visible borders

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 12:32:38 +01:00

313 lines
8.8 KiB
JavaScript

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