// api.ts — typed client for the moonrelay REST API. // // In Docker / production mode the SPA is served by the same Go process, // so we use a relative base URL (same origin, no CORS). // In local Vite dev mode set VITE_API_BASE to point at the backend // e.g. VITE_API_BASE=http://localhost:8080 const BASE = (import.meta.env.VITE_API_BASE as string | undefined) ?? ""; export interface AppStatus { vpn_connected: boolean; vpn_address: string; moonlight_path: string; } export interface Host { name: string; ip: string; port: number; online: boolean; seen_at: string; } async function request( method: string, path: string, body?: unknown ): Promise { const res = await fetch(`${BASE}${path}`, { method, headers: body ? { "Content-Type": "application/json" } : {}, body: body ? JSON.stringify(body) : undefined, }); if (!res.ok) { const err = await res.json().catch(() => ({ error: res.statusText })); throw new Error(err.error ?? res.statusText); } return res.json(); } export const api = { getStatus: () => request("GET", "/api/status"), getHosts: () => request("GET", "/api/hosts"), addManualHost: (name: string, ip: string, port = 47984) => request<{ ok: boolean }>("POST", "/api/hosts/manual", { name, ip, port }), connect: (ip: string, app = "Desktop") => request<{ ok: boolean }>("POST", "/api/connect", { ip, app }), pair: (ip: string) => request<{ ok: boolean }>("POST", "/api/pair", { ip }), };