feat: librairies client API REST + WebSocket
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
// client/src/lib/api.ts
|
||||||
|
import type { MachineView, UpdateSnapshot, ActionType } from "@shared/types.js";
|
||||||
|
|
||||||
|
async function req<T>(path: string, init?: RequestInit): Promise<T> {
|
||||||
|
const res = await fetch(`/api${path}`, {
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
...init,
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error((await res.json().catch(() => ({}))).error ?? res.statusText);
|
||||||
|
return res.json() as Promise<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const api = {
|
||||||
|
listMachines: () => req<MachineView[]>("/machines"),
|
||||||
|
createMachine: (body: unknown) => req<MachineView>("/machines", { method: "POST", body: JSON.stringify(body) }),
|
||||||
|
refresh: (id: string) => req<UpdateSnapshot>(`/machines/${id}/refresh`, { method: "POST" }),
|
||||||
|
snapshot: (id: string) => req<UpdateSnapshot>(`/machines/${id}/snapshot`),
|
||||||
|
runAction: (id: string, action: ActionType) =>
|
||||||
|
req<{ ok: boolean }>(`/machines/${id}/actions`, { method: "POST", body: JSON.stringify({ action }) }),
|
||||||
|
deleteMachine: (id: string) => req<{ ok: boolean }>(`/machines/${id}`, { method: "DELETE" }),
|
||||||
|
};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// client/src/lib/ws.ts
|
||||||
|
export function connectOutput(machineId: string, onChunk: (s: string) => void): () => void {
|
||||||
|
const proto = location.protocol === "https:" ? "wss" : "ws";
|
||||||
|
const ws = new WebSocket(`${proto}://${location.host}/api/ws/machines/${machineId}/output`);
|
||||||
|
ws.onmessage = (ev) => onChunk(typeof ev.data === "string" ? ev.data : "");
|
||||||
|
return () => ws.close();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user