auto-sync: 2026-05-17 06:14:47

This commit is contained in:
cfdaily
2026-05-17 06:14:47 +08:00
parent 7f1b6add2d
commit 7d6af07adb
+118
View File
@@ -0,0 +1,118 @@
// API 客户端
import type {
Task,
Project,
Observation,
Event,
DaemonStatus,
} from './types';
const API_BASE = '/api';
async function fetchJSON<T>(url: string, options?: RequestInit): Promise<T> {
const resp = await fetch(`${API_BASE}${url}`, {
headers: { 'Content-Type': 'application/json' },
...options,
});
if (!resp.ok) {
throw new Error(`API error: ${resp.status} ${resp.statusText}`);
}
return resp.json();
}
// ---- Projects ----
export async function listProjects(): Promise<Project[]> {
return fetchJSON('/projects');
}
export async function getProject(projectId: string): Promise<Project> {
return fetchJSON(`/projects/${projectId}`);
}
export async function createProject(data: Partial<Project>): Promise<Project> {
return fetchJSON('/projects', {
method: 'POST',
body: JSON.stringify(data),
});
}
// ---- Tasks ----
export async function listTasks(projectId: string): Promise<Task[]> {
return fetchJSON(`/projects/${projectId}/tasks`);
}
export async function getTask(projectId: string, taskId: string): Promise<Task> {
return fetchJSON(`/projects/${projectId}/tasks/${taskId}`);
}
export async function createTask(
projectId: string,
data: Partial<Task>
): Promise<Task> {
return fetchJSON(`/projects/${projectId}/tasks`, {
method: 'POST',
body: JSON.stringify(data),
});
}
export async function updateTask(
projectId: string,
taskId: string,
data: Partial<Task>
): Promise<Task> {
return fetchJSON(`/projects/${projectId}/tasks/${taskId}`, {
method: 'PATCH',
body: JSON.stringify(data),
});
}
// ---- Observations ----
export async function listObservations(
projectId: string,
taskId: string
): Promise<Observation[]> {
return fetchJSON(`/projects/${projectId}/tasks/${taskId}/observations`);
}
// ---- Events ----
export async function listEvents(
projectId: string,
taskId: string
): Promise<Event[]> {
return fetchJSON(`/projects/${projectId}/tasks/${taskId}/events`);
}
// ---- Daemon ----
export async function getDaemonStatus(): Promise<DaemonStatus> {
return fetchJSON('/daemon/status');
}
export async function triggerTick(): Promise<{ tick: number }> {
return fetchJSON('/daemon/tick', { method: 'POST' });
}
// ---- SSE ----
export function createEventSource(
onEvent: (data: unknown) => void,
onError?: () => void
): EventSource {
const es = new EventSource(`${API_BASE}/events`);
es.onmessage = (e) => {
try {
onEvent(JSON.parse(e.data));
} catch {
onEvent(e.data);
}
};
es.onerror = () => {
onError?.();
};
return es;
}