| import { AuthUser, getTokenFromStorage } from '@/stores/authStore';
|
|
|
|
|
| export const API_BASE_URL = '';
|
|
|
| type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };
|
|
|
| type ErrorResponseBody = {
|
| message?: string;
|
| error?: string | { message?: string };
|
| };
|
|
|
| const isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null;
|
|
|
| const isErrorResponseBody = (value: unknown): value is ErrorResponseBody => {
|
| if (!isRecord(value)) {
|
| return false;
|
| }
|
|
|
| const message = value.message;
|
| const error = value.error;
|
|
|
| const hasValidMessage = message === undefined || typeof message === 'string';
|
|
|
| const hasValidError =
|
| error === undefined ||
|
| typeof error === 'string' ||
|
| (isRecord(error) && (error.message === undefined || typeof error.message === 'string'));
|
|
|
| return hasValidMessage && hasValidError;
|
| };
|
|
|
| interface ApiRequestOptions {
|
| method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
| headers?: Record<string, string>;
|
| body?: JsonValue;
|
| requireAuth?: boolean;
|
| }
|
|
|
| class ApiError extends Error {
|
| constructor(
|
| message: string,
|
| public status: number,
|
| public response?: unknown
|
| ) {
|
| super(message);
|
| this.name = 'ApiError';
|
| }
|
| }
|
|
|
| export async function apiRequest<T>(endpoint: string, options: ApiRequestOptions = {}): Promise<T> {
|
| const { method = 'GET', headers = {}, body, requireAuth = false } = options;
|
|
|
| const url = `${API_BASE_URL}${endpoint}`;
|
|
|
| const requestHeaders: Record<string, string> = {
|
| 'Content-Type': 'application/json',
|
| ...headers,
|
| };
|
|
|
|
|
| if (requireAuth) {
|
| const token = getTokenFromStorage();
|
| if (token) {
|
| requestHeaders['Authorization'] = `Bearer ${token}`;
|
| }
|
| }
|
|
|
| const requestOptions: RequestInit = {
|
| method,
|
| headers: requestHeaders,
|
| };
|
|
|
| if (body && method !== 'GET') {
|
| requestOptions.body = JSON.stringify(body);
|
| }
|
|
|
| try {
|
| const response = await fetch(url, requestOptions);
|
|
|
| if (!response.ok) {
|
| let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
| let errorData: unknown = null;
|
|
|
| try {
|
| errorData = await response.json();
|
| if (isErrorResponseBody(errorData)) {
|
| if (errorData.message) {
|
| errorMessage = errorData.message;
|
| } else if (errorData.error) {
|
| errorMessage = typeof errorData.error === 'string' ? errorData.error : errorData.error?.message || errorMessage;
|
| }
|
| }
|
| } catch {
|
|
|
| }
|
|
|
| throw new ApiError(errorMessage, response.status, errorData);
|
| }
|
|
|
|
|
| const contentType = response.headers.get('content-type');
|
| if (contentType && contentType.includes('application/json')) {
|
| return (await response.json()) as T;
|
| }
|
|
|
| return {} as T;
|
| } catch (error) {
|
| if (error instanceof ApiError) {
|
| throw error;
|
| }
|
|
|
| const message = error instanceof Error ? error.message : 'Network error occurred';
|
| throw new ApiError(message, 0);
|
| }
|
| }
|
|
|
|
|
| export const systemApi = {
|
| getStatus: (): Promise<{ isInitialized: boolean }> => apiRequest('/admin/system/status'),
|
|
|
| initialize: (data: {
|
| ownerEmail: string;
|
| ownerPassword: string;
|
| ownerFirstName: string;
|
| ownerLastName: string;
|
| brandName: string;
|
| }): Promise<{ success: boolean; message: string }> =>
|
| apiRequest('/admin/system/initialize', {
|
| method: 'POST',
|
| body: data,
|
| }),
|
| };
|
|
|
|
|
| export const authApi = {
|
| signIn: (data: {
|
| email: string;
|
| password: string;
|
| }): Promise<{
|
| user: AuthUser;
|
| token: string;
|
| }> =>
|
| apiRequest('/admin/auth/signin', {
|
| method: 'POST',
|
| body: data,
|
| }),
|
| };
|
|
|
|
|
| export const rerankApi = {
|
| rerank: (data: {
|
| model: string;
|
| query: string;
|
| documents: string[];
|
| top_n?: number;
|
| }): Promise<{
|
| results: Array<{
|
| index: number;
|
| relevance_score: number;
|
| document?: string;
|
| }>;
|
| usage?: {
|
| prompt_tokens: number;
|
| completion_tokens: number;
|
| total_tokens: number;
|
| };
|
| }> =>
|
| apiRequest('/v1/rerank', {
|
| method: 'POST',
|
| body: data,
|
| requireAuth: true,
|
| }),
|
| };
|
|
|