Files
micronomicon/frontend/src/api/client.ts
2026-04-03 15:24:06 +02:00

132 lines
3.5 KiB
TypeScript

/**
* 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<PageMeta[]> {
const res = await fetch("/api/pages");
return res.json();
}
export async function fetchPage(name: string): Promise<PageDetail> {
const res = await fetch(`/api/pages/${name}`);
return res.json();
}
export async function savePage(
name: string,
source: string,
publish: boolean,
): Promise<PageMeta> {
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<void> {
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<CompileResult> {
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<DslMeta> {
const res = await fetch("/api/dsl-meta");
return res.json();
}
// ---------------------------------------------------------------------------
// Node Management
// ---------------------------------------------------------------------------
export async function restartNode(): Promise<void> {
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<UploadResult> {
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();
}