112 lines
3.6 KiB
TypeScript
112 lines
3.6 KiB
TypeScript
import type { ExtractionBatch, RowsResponse, SchemaResponse, Task } from "../../shared/types";
|
|
|
|
export class ApiClient {
|
|
constructor(private readonly baseUrl: string) {}
|
|
|
|
private url(path: string): string {
|
|
return `${this.baseUrl.replace(/\/+$/, "")}${path}`;
|
|
}
|
|
|
|
async getJson<T>(path: string): Promise<T> {
|
|
const response = await fetch(this.url(path));
|
|
return this.handle<T>(response);
|
|
}
|
|
|
|
async postJson<T>(path: string, body: unknown): Promise<T> {
|
|
const response = await fetch(this.url(path), {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(body),
|
|
});
|
|
return this.handle<T>(response);
|
|
}
|
|
|
|
async postForm<T>(path: string, form: FormData): Promise<T> {
|
|
const response = await fetch(this.url(path), {
|
|
method: "POST",
|
|
body: form,
|
|
});
|
|
return this.handle<T>(response);
|
|
}
|
|
|
|
async health(): Promise<unknown> {
|
|
return this.getJson("/health");
|
|
}
|
|
|
|
async config(): Promise<unknown> {
|
|
return this.getJson("/config");
|
|
}
|
|
|
|
async models(): Promise<unknown> {
|
|
return this.getJson("/models");
|
|
}
|
|
|
|
async discoverSchema(payload: Record<string, unknown>): Promise<SchemaResponse> {
|
|
return this.postJson<SchemaResponse>("/extraction/schemas", payload);
|
|
}
|
|
|
|
async discoverSchemaUpload(form: FormData): Promise<SchemaResponse> {
|
|
return this.postForm<SchemaResponse>("/extraction/schemas/upload", form);
|
|
}
|
|
|
|
async estimate(payload: Record<string, unknown>): Promise<unknown> {
|
|
return this.postJson("/extraction/estimate", payload);
|
|
}
|
|
|
|
async estimateUpload(form: FormData): Promise<unknown> {
|
|
return this.postForm("/extraction/estimate/upload", form);
|
|
}
|
|
|
|
async createBatch(payload: Record<string, unknown>): Promise<ExtractionBatch> {
|
|
return this.postJson<ExtractionBatch>("/extraction/batches", payload);
|
|
}
|
|
|
|
async createExtractionTask(payload: Record<string, unknown>): Promise<Task> {
|
|
return this.postJson<Task>("/tasks/extraction", payload);
|
|
}
|
|
|
|
async ingestTaskDocument(taskId: string, form: FormData): Promise<Record<string, unknown>> {
|
|
return this.postForm<Record<string, unknown>>(`/tasks/${encodeURIComponent(taskId)}/ingest`, form);
|
|
}
|
|
|
|
async ingestTaskDocumentsBulk(taskId: string, form: FormData): Promise<Record<string, unknown>> {
|
|
return this.postForm<Record<string, unknown>>(`/tasks/${encodeURIComponent(taskId)}/ingest-many`, form);
|
|
}
|
|
|
|
async tasks(type = "extraction"): Promise<Task[]> {
|
|
return this.getJson<Task[]>(`/tasks?type=${encodeURIComponent(type)}`);
|
|
}
|
|
|
|
async task(taskId: string): Promise<Task> {
|
|
return this.getJson<Task>(`/tasks/${encodeURIComponent(taskId)}`);
|
|
}
|
|
|
|
async taskRows(taskId: string, limit = 500, offset = 0): Promise<RowsResponse> {
|
|
return this.getJson<RowsResponse>(`/tasks/${encodeURIComponent(taskId)}/rows?limit=${limit}&offset=${offset}`);
|
|
}
|
|
|
|
async rows(batchId: string, limit = 500, offset = 0): Promise<RowsResponse> {
|
|
return this.getJson<RowsResponse>(`/extraction/batches/${encodeURIComponent(batchId)}/rows?limit=${limit}&offset=${offset}`);
|
|
}
|
|
|
|
private async handle<T>(response: Response): Promise<T> {
|
|
const text = await response.text();
|
|
let data: unknown = null;
|
|
if (text) {
|
|
try {
|
|
data = JSON.parse(text);
|
|
} catch {
|
|
data = null;
|
|
}
|
|
}
|
|
if (!response.ok) {
|
|
const detail =
|
|
typeof (data as { detail?: unknown } | null)?.detail === "string"
|
|
? (data as { detail: string }).detail
|
|
: text || response.statusText;
|
|
throw new Error(detail || `HTTP ${response.status}`);
|
|
}
|
|
return data as T;
|
|
}
|
|
}
|