const BASE_URL = import.meta.env.VITE_API_URL ?? ''; export type ServiceStatus = 'running' | 'stopped' | 'unhealthy' | 'unknown'; export interface InfraService { name: string; container: string; status: ServiceStatus; ports: string[]; uptime?: string; } export interface InfraStatusResponse { services: InfraService[]; checkedAt: string; } export async function getInfraStatus(): Promise { const res = await fetch(`${BASE_URL}/api/infra/status`); if (!res.ok) throw new Error('Failed to fetch infra status'); return res.json(); } export async function infraServiceAction( service: string, action: 'start' | 'stop' | 'restart' ): Promise { const res = await fetch(`${BASE_URL}/api/infra/${service}/${action}`, { method: 'POST' }); if (!res.ok) throw new Error(`Failed to ${action} ${service}`); } export function streamComposeUp(onLine: (line: string) => void, onDone: () => void): EventSource { const src = new EventSource(`${BASE_URL}/api/infra/compose/up/stream`); src.onmessage = (e) => onLine(e.data); src.onerror = () => { onDone(); src.close(); }; return src; } /** Force-recreates all containers and removes orphans — fixes name-conflict errors. */ export function streamComposeForceUp(onLine: (line: string) => void, onDone: () => void): EventSource { const src = new EventSource(`${BASE_URL}/api/infra/compose/up-force/stream`); src.onmessage = (e) => onLine(e.data); src.onerror = () => { onDone(); src.close(); }; return src; } /** * Nuke & Recreate — force-removes every known platform container by name first * (kills orphans that --remove-orphans won't touch), then runs compose up fresh. * Use this when Force Recreate still fails with "container name already in use". */ export function streamComposeNuke(onLine: (line: string) => void, onDone: () => void): EventSource { const src = new EventSource(`${BASE_URL}/api/infra/compose/nuke/stream`); src.onmessage = (e) => onLine(e.data); src.onerror = () => { onDone(); src.close(); }; return src; } export function streamComposeDown(onLine: (line: string) => void, onDone: () => void): EventSource { const src = new EventSource(`${BASE_URL}/api/infra/compose/down/stream`); src.onmessage = (e) => onLine(e.data); src.onerror = () => { onDone(); src.close(); }; return src; }