import { json } from '@sveltejs/kit'; import { getServer, listServers } from '$lib/server/fleet/servers.js'; import { getBaselineForScope, getScript, getVersion, listPromotedOverlaysForScope, type ScriptRow } from '$lib/server/fleet/scripts.js'; import { inspectConfig, type ConfigLayer } from '$lib/server/fleet/config-inspect.js'; import type { ConfigInspection } from '$lib/config-workbench.js'; function inspect(serverName: string, draft?: { artifactId: number; text: string }): ConfigInspection { const server = getServer(serverName); if (!server || server.destroyed_at) throw new Error('Server not found.'); const artifact = draft ? getScript(draft.artifactId) : undefined; if (draft && (!artifact || !['baseline', 'config'].includes(artifact.kind))) throw new Error('Config not found.'); if (artifact && (artifact.scope_type === null || artifact.scope_value !== server[artifact.scope_type])) { throw new Error('This config does not apply to the selected server.'); } if (artifact?.kind === 'baseline' && artifact.scope_type !== 'game') throw new Error('Server composition requires a game baseline.'); const baseline = artifact?.kind === 'baseline' ? artifact : server.game ? getBaselineForScope('game', server.game) : undefined; function layer(row: ScriptRow): ConfigLayer | null { const isDraft = row.id === draft?.artifactId; const version = row.current_version_id ? getVersion(row.current_version_id) : undefined; if (!isDraft && !version) return null; return { source: { id: row.id, name: row.name, version: isDraft ? null : version!.version, kind: row.kind as 'baseline' | 'config', draft: isDraft }, text: isDraft ? draft!.text : version!.content.toString('utf8') }; } const base = baseline ? layer(baseline) : null; if (!base) return { text: '', sources: [], settings: [], warnings: [], reason: 'No promoted baseline for this game. Promote a baseline through a beta to inspect the managed configuration.' }; const overlays = [ ...(server.game ? listPromotedOverlaysForScope('game', server.game) : []), ...(server.map ? listPromotedOverlaysForScope('map', server.map) : []) ].filter(row => row.id !== artifact?.id); if (artifact?.kind === 'config') overlays.push(artifact); return inspectConfig(base, overlays.map(layer).filter((l): l is ConfigLayer => l !== null), server.game, server.map, server.map_slug); } export async function GET({ url }: { url: URL }) { const servers = listServers().filter(s => !s.destroyed_at).map(({ name, game, map }) => ({ name, game, map })); try { const server = url.searchParams.get('server'); return json({ servers, inspection: server ? inspect(server) : null }, { headers: { 'Cache-Control': 'no-store' } }); } catch (err) { return json({ error: (err as Error).message }, { status: 400 }); } } export async function POST({ request }: { request: Request }) { let body; try { body = await request.json(); } catch { return json({ error: 'Invalid preview request.' }, { status: 400 }); } if (!body || typeof body.server !== 'string' || !Number.isSafeInteger(body.artifactId) || typeof body.text !== 'string') { return json({ error: 'Server, config ID and text are required.' }, { status: 400 }); } try { return json({ inspection: inspect(body.server, body), promoted: inspect(body.server) }, { headers: { 'Cache-Control': 'no-store' } }); } catch (err) { return json({ error: (err as Error).message }, { status: 400 }); } }