phase 16: React dashboard with full platform control and analytics
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Shared API client targeting Query API, Symbol Registry, and Risk Engine.
|
||||
* Base URLs are configurable via env vars (VITE_*).
|
||||
*/
|
||||
|
||||
const QUERY_API_BASE = import.meta.env.VITE_QUERY_API_URL ?? '';
|
||||
const SYMBOL_REGISTRY_BASE = import.meta.env.VITE_SYMBOL_REGISTRY_URL ?? '';
|
||||
const RISK_ENGINE_BASE = import.meta.env.VITE_RISK_ENGINE_URL ?? '';
|
||||
|
||||
export type ApiBase = 'query' | 'registry' | 'risk';
|
||||
|
||||
function baseUrl(api: ApiBase): string {
|
||||
switch (api) {
|
||||
case 'query':
|
||||
return QUERY_API_BASE;
|
||||
case 'registry':
|
||||
return SYMBOL_REGISTRY_BASE;
|
||||
case 'risk':
|
||||
return RISK_ENGINE_BASE;
|
||||
}
|
||||
}
|
||||
|
||||
export class ApiError extends Error {
|
||||
status: number;
|
||||
body: unknown;
|
||||
|
||||
constructor(status: number, body: unknown) {
|
||||
super(`API error ${status}`);
|
||||
this.name = 'ApiError';
|
||||
this.status = status;
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
|
||||
export async function apiFetch<T>(
|
||||
api: ApiBase,
|
||||
path: string,
|
||||
init?: RequestInit,
|
||||
): Promise<T> {
|
||||
const url = `${baseUrl(api)}${path}`;
|
||||
const res = await fetch(url, {
|
||||
...init,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...init?.headers,
|
||||
},
|
||||
});
|
||||
if (!res.ok) {
|
||||
const body = await res.json().catch(() => null);
|
||||
throw new ApiError(res.status, body);
|
||||
}
|
||||
return res.json() as Promise<T>;
|
||||
}
|
||||
|
||||
/** Convenience GET */
|
||||
export function apiGet<T>(api: ApiBase, path: string): Promise<T> {
|
||||
return apiFetch<T>(api, path);
|
||||
}
|
||||
|
||||
/** Convenience POST */
|
||||
export function apiPost<T>(api: ApiBase, path: string, body: unknown): Promise<T> {
|
||||
return apiFetch<T>(api, path, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
}
|
||||
|
||||
/** Convenience PUT */
|
||||
export function apiPut<T>(api: ApiBase, path: string, body: unknown): Promise<T> {
|
||||
return apiFetch<T>(api, path, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
}
|
||||
|
||||
/** Convenience DELETE */
|
||||
export function apiDelete<T>(api: ApiBase, path: string): Promise<T> {
|
||||
return apiFetch<T>(api, path, { method: 'DELETE' });
|
||||
}
|
||||
Reference in New Issue
Block a user