init ingestion
This commit is contained in:
90
ingestion/console/src/api/client.ts
Normal file
90
ingestion/console/src/api/client.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
// Thin fetch wrapper. Throws on non-2xx with a structured ApiError.
|
||||
|
||||
export class ApiError extends Error {
|
||||
status: number;
|
||||
field?: string;
|
||||
constructor(status: number, message: string, field?: string) {
|
||||
super(message);
|
||||
this.status = status;
|
||||
this.field = field;
|
||||
}
|
||||
}
|
||||
|
||||
const INGEST_BASE = import.meta.env.VITE_API_BASE_URL ?? '/api/ingest';
|
||||
const ROTOR_BASE = import.meta.env.VITE_ROTOR_BASE_URL ?? '/api/rotor';
|
||||
const BULKER_BASE = import.meta.env.VITE_BULKER_BASE_URL ?? '/api/bulker';
|
||||
|
||||
async function request<T>(base: string, path: string, init?: RequestInit): Promise<T> {
|
||||
const res = await fetch(`${base}${path}`, {
|
||||
...init,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
...(init?.headers ?? {}),
|
||||
},
|
||||
});
|
||||
const text = await res.text();
|
||||
const data = text ? safeJSON(text) : undefined;
|
||||
if (!res.ok) {
|
||||
const msg = (data as { error?: string })?.error ?? res.statusText;
|
||||
const field = (data as { field?: string })?.field;
|
||||
throw new ApiError(res.status, msg, field);
|
||||
}
|
||||
return data as T;
|
||||
}
|
||||
|
||||
function safeJSON(text: string): unknown {
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Ingest API
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const ingest = {
|
||||
health: () => request<{ status: string }>(INGEST_BASE, '/health'),
|
||||
ready: () => request<{ status: string }>(INGEST_BASE, '/ready'),
|
||||
|
||||
track: (writeKey: string, body: Record<string, unknown>) =>
|
||||
request<{ ok: boolean }>(INGEST_BASE, '/track', {
|
||||
method: 'POST',
|
||||
headers: { Authorization: `Bearer ${writeKey}` },
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Rotor API
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface RunRequest {
|
||||
code: string;
|
||||
event: Record<string, unknown>;
|
||||
}
|
||||
export interface RunResponse {
|
||||
result: unknown;
|
||||
}
|
||||
|
||||
export const rotor = {
|
||||
run: (body: RunRequest) =>
|
||||
request<RunResponse>(ROTOR_BASE, '/v1/run', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
upsert: (body: { workspace_id: string; slug: string; code: string }) =>
|
||||
request<{ ok: boolean }>(ROTOR_BASE, '/v1/functions', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Bulker API
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const bulker = {
|
||||
health: () => request<{ status: string }>(BULKER_BASE, '/health'),
|
||||
};
|
||||
Reference in New Issue
Block a user