// TypeScript API client for AI Voicebot server import { components } from './api-types'; // Re-export commonly used types from the generated schema export type LobbyModel = components['schemas']['LobbyModel']; export type LobbyListItem = components['schemas']['LobbyListItem']; export type LobbyCreateData = components['schemas']['LobbyCreateData']; export type NamePasswordRecord = components['schemas']['NamePasswordRecord']; // Type aliases for API methods export type AdminNamesResponse = components['schemas']['AdminNamesResponse']; export type AdminActionResponse = components['schemas']['AdminActionResponse']; export type AdminSetPassword = components['schemas']['AdminSetPassword']; export type AdminClearPassword = components['schemas']['AdminClearPassword']; export type HealthResponse = components['schemas']['HealthResponse']; export type LobbiesResponse = components['schemas']['LobbiesResponse']; export type SessionResponse = components['schemas']['SessionResponse']; export type LobbyCreateRequest = components['schemas']['LobbyCreateRequest']; export type LobbyCreateResponse = components['schemas']['LobbyCreateResponse']; export class ApiError extends Error { constructor( public status: number, public statusText: string, public data?: any ) { super(`HTTP ${status}: ${statusText}`); this.name = 'ApiError'; } } export class ApiClient { private baseURL: string; private defaultHeaders: Record; constructor(baseURL?: string) { this.baseURL = baseURL || process.env.REACT_APP_API_URL || 'http://localhost:8001'; this.defaultHeaders = {}; } private async request(path: string, options: { method: string; body?: any; params?: Record; }): Promise { const url = new URL(path, this.baseURL); if (options.params) { Object.entries(options.params).forEach(([key, value]) => { url.searchParams.append(key, value); }); } const requestInit: RequestInit = { method: options.method, headers: { 'Content-Type': 'application/json', ...this.defaultHeaders, }, }; if (options.body && options.method !== 'GET') { requestInit.body = JSON.stringify(options.body); } const response = await fetch(url.toString(), requestInit); if (!response.ok) { let errorData; try { errorData = await response.json(); } catch { errorData = await response.text(); } throw new ApiError(response.status, response.statusText, errorData); } const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return response.json(); } return response.text() as unknown as T; } // Admin API methods async adminListNames(): Promise { return this.request('/ai-voicebot/api/admin/names', { method: 'GET' }); } async adminSetPassword(data: AdminSetPassword): Promise { return this.request('/ai-voicebot/api/admin/set_password', { method: 'POST', body: data }); } async adminClearPassword(data: AdminClearPassword): Promise { return this.request('/ai-voicebot/api/admin/clear_password', { method: 'POST', body: data }); } // Health check async healthCheck(): Promise { return this.request('/ai-voicebot/api/health', { method: 'GET' }); } // Session methods async getSession(): Promise { return this.request('/ai-voicebot/api/session', { method: 'GET' }); } // Lobby methods async getLobbies(): Promise { return this.request('/ai-voicebot/api/lobby', { method: 'GET' }); } async createLobby(sessionId: string, data: LobbyCreateRequest): Promise { return this.request(`/ai-voicebot/api/lobby/${sessionId}`, { method: 'POST', body: data }); } } // Default client instance export const apiClient = new ApiClient(); // Convenience API namespaces export const adminApi = { listNames: () => apiClient.adminListNames(), setPassword: (data: AdminSetPassword) => apiClient.adminSetPassword(data), clearPassword: (data: AdminClearPassword) => apiClient.adminClearPassword(data), }; export const healthApi = { check: () => apiClient.healthCheck() }; export const lobbiesApi = { getAll: () => apiClient.getLobbies() }; export const sessionsApi = { getCurrent: () => apiClient.getSession(), createLobby: (sessionId: string, data: LobbyCreateRequest) => apiClient.createLobby(sessionId, data), };