auto-sync: 2026-05-17 06:14:47
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user