import type { Board, BoardListData, TaskSummary, TaskDetail, TaskListData, CreateTaskPayload, CommentPayload, ApiResponse, HealthData, } from '@kanban/contracts' import { getInitData } from '../telegram' const BRIDGE_URL = import.meta.env.VITE_BRIDGE_URL || '/bridge' const AUTH_TOKEN: string = import.meta.env.VITE_AUTH_TOKEN || '' async function request(path: string, init: RequestInit = {}): Promise { const headers = new Headers(init.headers) headers.set('Content-Type', 'application/json') // Auth: prefer X-Bridge-Token, fall back to Telegram initData if (AUTH_TOKEN) { headers.set('X-Bridge-Token', AUTH_TOKEN) } else { const initData = getInitData() if (initData) { headers.set('X-Bridge-Token', initData) } } const url = `${BRIDGE_URL}${path}` const response = await fetch(url, { ...init, headers }) const data = await response.json().catch(() => null) if (!response.ok || !data) { const message = (data as { error?: { message?: string } })?.error?.message || response.statusText || `HTTP ${response.status}` throw new Error(message) } const envelope = data as ApiResponse if (!envelope.ok) { throw new Error(envelope.error?.message || 'API error') } return envelope.data } // ─── API methods ──────────────────────────────────────────── export async function fetchHealth(): Promise { return request('/v1/health') } export async function fetchBoards(): Promise { return request('/v1/boards') } export async function fetchTasks(board: string): Promise { return request(`/v1/boards/${encodeURIComponent(board)}/tasks`) } export async function fetchTask(board: string, taskId: string): Promise { return request( `/v1/boards/${encodeURIComponent(board)}/tasks/${encodeURIComponent(taskId)}` ) } export async function createTask( board: string, payload: CreateTaskPayload ): Promise { return request( `/v1/boards/${encodeURIComponent(board)}/tasks`, { method: 'POST', body: JSON.stringify(payload), } ) } export async function addComment( board: string, taskId: string, payload: CommentPayload ): Promise { await request( `/v1/boards/${encodeURIComponent(board)}/tasks/${encodeURIComponent(taskId)}/comments`, { method: 'POST', body: JSON.stringify(payload), } ) }