/** * Centralized API client for all backend communication. * * Every fetch call in the app should go through here so that * endpoint URLs live in one place and are easy to update * (e.g. when adding multi-node support with /api/nodes/{id}/...). */ // --------------------------------------------------------------------------- // Pages // --------------------------------------------------------------------------- export interface PageMeta { name: string; title: string | null; published: boolean; has_source: boolean; last_modified: number | null; size: number | null; } export interface PageDetail { name: string; source: string | null; } export async function fetchPages(): Promise { const res = await fetch("/api/pages"); return res.json(); } export async function fetchPage(name: string): Promise { const res = await fetch(`/api/pages/${name}`); return res.json(); } export async function savePage( name: string, source: string, publish: boolean, ): Promise { const res = await fetch(`/api/pages/${name}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ source, publish }), }); if (!res.ok) throw new Error(await res.text()); return res.json(); } export async function deletePage(name: string): Promise { await fetch(`/api/pages/${name}`, { method: "DELETE" }); } // --------------------------------------------------------------------------- // Compile // --------------------------------------------------------------------------- export interface CompileResult { ascii: string; micron: string; script: string; is_dynamic: boolean; warnings: string[]; } export async function compile( source: string, signal?: AbortSignal, ): Promise { const res = await fetch("/api/compile", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ source }), signal, }); if (!res.ok) { const err = await res.json().catch(() => ({ detail: "Compile failed" })); throw new Error(err.detail || "Compile failed"); } return res.json(); } // --------------------------------------------------------------------------- // DSL Metadata // --------------------------------------------------------------------------- export interface DslCommand { label: string; detail: string; section: string; snippet: string; } export interface DslMeta { keywords: string[]; values: string[]; commands: DslCommand[]; themes: string[]; } export async function fetchDslMeta(): Promise { const res = await fetch("/api/dsl-meta"); return res.json(); } // --------------------------------------------------------------------------- // Node Management // --------------------------------------------------------------------------- export async function restartNode(): Promise { const res = await fetch("/api/restart", { method: "POST" }); if (!res.ok) throw new Error(await res.text()); } // --------------------------------------------------------------------------- // Images // --------------------------------------------------------------------------- export interface UploadResult { filename: string; path: string; } export async function uploadImage(file: File): Promise { const form = new FormData(); form.append("file", file); const res = await fetch("/api/upload-image", { method: "POST", body: form }); if (!res.ok) throw new Error(await res.text()); return res.json(); }