Files
tabdeal-job-queue/frontend/src/api.ts

43 lines
1.6 KiB
TypeScript

import type { Health, Job, JobEvent, JobStats } from "./types";
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? "http://localhost:8000/api";
async function request<T>(path: string, init?: RequestInit): Promise<T> {
const response = await fetch(`${API_BASE_URL}${path}`, {
headers: { "Content-Type": "application/json", ...(init?.headers ?? {}) },
...init
});
if (!response.ok) {
const body = await response.text();
throw new Error(body || response.statusText);
}
return response.json() as Promise<T>;
}
export type CreateJobBody = {
type: string;
payload?: Record<string, unknown>;
priority?: number;
available_at?: string | null;
max_attempts?: number;
idempotency_key?: string | null;
};
export const api = {
health: () => request<Health>("/health/"),
listJobs: () => request<Job[]>("/jobs/"),
getJob: (jobId: string) => request<Job>(`/jobs/${jobId}/`),
createJob: (body: CreateJobBody) => request<Job>("/jobs/", { method: "POST", body: JSON.stringify(body) }),
retryJob: (jobId: string) => request<Job>(`/jobs/${jobId}/retry/`, { method: "POST" }),
getStats: () => request<JobStats>("/jobs/stats/"),
listJobEvents: (jobId: string) => request<JobEvent[]>(`/jobs/${jobId}/events/`),
listEvents: (filters: { after_id?: number; limit?: number; job_id?: string; type?: string } = {}) => {
const params = new URLSearchParams();
Object.entries(filters).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== "") params.set(key, String(value));
});
const query = params.toString();
return request<JobEvent[]>(`/job-events/${query ? `?${query}` : ""}`);
}
};