import type { Board, Card, CardHistoryResponse, Column, Metrics, MetricsFilter, User, } from "./types"; const BASE = "/api"; export class HTTPError extends Error { constructor(public status: number, message: string) { super(message); } } async function fetchJSON(path: string, init?: RequestInit): Promise { const res = await fetch(`${BASE}${path}`, { credentials: "include", ...init, headers: { "Content-Type": "application/json", ...(init?.headers || {}) }, }); if (!res.ok) { const err = await res.json().catch(() => ({ Message: res.statusText })); throw new HTTPError(res.status, err.Message || err.message || res.statusText); } if (res.status === 204) return undefined as T; return res.json(); } export function getBoard(): Promise { return fetchJSON("/board"); } export function createColumn(name: string): Promise { return fetchJSON("/columns", { method: "POST", body: JSON.stringify({ name }) }); } export interface UpdateColumnInput { name?: string; position?: number; location?: "board" | "sidebar"; width?: number; wip_limit?: number; is_done?: boolean; } export function updateColumn(id: string, patch: UpdateColumnInput): Promise { return fetchJSON(`/columns/${id}`, { method: "PATCH", body: JSON.stringify(patch), }); } export function deleteColumn(id: string): Promise { return fetchJSON(`/columns/${id}`, { method: "DELETE" }); } export function reorderColumns(ids: string[]): Promise { return fetchJSON("/columns/reorder", { method: "POST", body: JSON.stringify({ ids }) }); } export interface CreateCardInput { column_id: string; requester?: string; title: string; description?: string; assignee_id?: string | null; } export function createCard(input: CreateCardInput): Promise { return fetchJSON("/cards", { method: "POST", body: JSON.stringify(input) }); } export interface UpdateCardInput { requester?: string; title?: string; description?: string; color?: string; locked?: boolean; assignee_id?: string | null; } export function updateCard(id: string, patch: UpdateCardInput): Promise { return fetchJSON(`/cards/${id}`, { method: "PATCH", body: JSON.stringify(patch) }); } export function deleteCard(id: string): Promise { return fetchJSON(`/cards/${id}`, { method: "DELETE" }); } export function listTrash(): Promise { return fetchJSON("/trash"); } export function restoreCard(id: string): Promise { return fetchJSON(`/cards/${id}/restore`, { method: "POST" }); } export function purgeCard(id: string): Promise { return fetchJSON(`/cards/${id}/purge`, { method: "DELETE" }); } export function moveCard(id: string, column_id: string, ordered_ids: string[]): Promise { return fetchJSON(`/cards/${id}/move`, { method: "POST", body: JSON.stringify({ column_id, ordered_ids }), }); } export function cardHistory(id: string): Promise { return fetchJSON(`/cards/${id}/history`); } export interface ChatMessage { role: "user" | "assistant"; content: string; } export interface ChatToolCall { tool: string; ok: boolean; error?: string; } export interface ChatResponse { role: "assistant"; content: string; board_changed: boolean; tool_calls?: ChatToolCall[]; } export function sendChat(messages: ChatMessage[]): Promise { return fetchJSON("/chat", { method: "POST", body: JSON.stringify({ messages }) }); } export function login(username: string, password: string): Promise { return fetchJSON("/auth/login", { method: "POST", body: JSON.stringify({ username, password }), }); } export function register(username: string, password: string, display_name?: string): Promise { return fetchJSON("/auth/register", { method: "POST", body: JSON.stringify({ username, password, display_name }), }); } export function logout(): Promise { return fetchJSON("/auth/logout", { method: "POST" }); } export function getMe(): Promise { return fetchJSON("/me"); } export function listUsers(): Promise { return fetchJSON("/users"); } export function getMetrics(f: MetricsFilter): Promise { const qs = new URLSearchParams(); if (f.from) qs.set("from", f.from); if (f.to) qs.set("to", f.to); if (f.assignee_id) qs.set("assignee_id", f.assignee_id); if (f.requester) qs.set("requester", f.requester); const q = qs.toString(); return fetchJSON(`/metrics${q ? `?${q}` : ""}`); }