← Files BranchaARCHIVED FILE

skills/brancha/app/src/ui/api.ts

1.71 KB · Oct 3, 2026 · 06:30 UTC

↓ Download file

import type { AppSettings, Locale, ThemePreference } from '../shared/types';
import type { Project, Tree } from './types';

async function req<T>(path: string, init?: RequestInit): Promise<T> {
  const res = await fetch(path, {
    headers: { 'Content-Type': 'application/json' },
    ...init,
  });
  const body = await res.json().catch(() => ({}));
  if (!res.ok) throw new Error(body.error || `HTTP ${res.status}`);
  return body as T;
}

export const api = {
  settings: () => req<AppSettings>('/api/settings'),
  updateTheme: (theme: ThemePreference) => req<AppSettings>('/api/settings/theme', {
    method: 'PUT', body: JSON.stringify({ theme }),
  }),
  updateLocale: (locale: Locale) => req<AppSettings>('/api/settings/locale', {
    method: 'PUT', body: JSON.stringify({ locale }),
  }),
  listProjects: () => req<Project[]>('/api/projects'),
  deleteProject: (id: string) => req<{ ok: true }>(`/api/projects/${id}`, { method: 'DELETE' }),
  markNodeError: (id: string, error: string) => req<{ ok: true }>(`/api/nodes/${id}/artifact/error`, { method: 'PUT', body: JSON.stringify({ error }) }),
  tree: (id: string) => req<Tree>(`/api/projects/${id}/tree`),
  nodeHtmlUrl: (nodeId: string, revision?: string) =>
    `/api/nodes/${nodeId}/html${revision ? `?revision=${encodeURIComponent(revision)}` : ''}`,
  nodeArtifactUrl: (nodeId: string) => `/api/nodes/${nodeId}/artifact`,
  eventsUrl: (projectId?: string) => (projectId ? `/api/events?project=${projectId}` : '/api/events'),
  nodeArtifactSource: async (nodeId: string) => {
    const res = await fetch(`/api/nodes/${nodeId}/artifact/source`);
    const body = await res.json();
    if (!res.ok) throw new Error(body.error || `HTTP ${res.status}`);
    return body.source as string;
  },
};

SHA-256: f86e6f5c90df2e9564cb838dea8b410f3d1792d9500e2c02f808367c97ddf03e