Spaces:
Runtime error
Runtime error
Download frontend/src/api/client.ts from yusufcalisir/Collaborative-Fraud-Intelligence-Simulator: direct link, hf CLI and curl.
- Browser
- Download file 3.52 kB
-
https://huggingface.co/spaces/yusufcalisir/Collaborative-Fraud-Intelligence-Simulator/resolve/main/frontend/src/api/client.ts
- Command line
-
hf download hf://spaces/yusufcalisir/Collaborative-Fraud-Intelligence-Simulator/frontend/src/api/client.ts
-
curl -L -o client.ts https://huggingface.co/spaces/yusufcalisir/Collaborative-Fraud-Intelligence-Simulator/resolve/main/frontend/src/api/client.ts
3.52 kB
| import axios from 'axios'; | |
| const API_BASE = import.meta.env.VITE_API_URL ?? ''; | |
| export const apiClient = axios.create({ | |
| baseURL: API_BASE, | |
| headers: { 'Content-Type': 'application/json' }, | |
| timeout: 30000, | |
| }); | |
| apiClient.interceptors.request.use((config) => { | |
| if (typeof window !== 'undefined') { | |
| const token = localStorage.getItem('cfi_token') || sessionStorage.getItem('cfi_token'); | |
| if (token && !config.headers.Authorization) { | |
| config.headers.Authorization = `Bearer ${token}`; | |
| } | |
| const tenantId = localStorage.getItem('cfi_tenant_id') || sessionStorage.getItem('cfi_tenant_id'); | |
| if (tenantId && !config.headers['X-Tenant-ID']) { | |
| config.headers['X-Tenant-ID'] = tenantId; | |
| } | |
| } | |
| return config; | |
| }); | |
| apiClient.interceptors.response.use( | |
| (response) => response, | |
| (error) => { | |
| if (axios.isCancel(error)) { | |
| // Normal React / TanStack Query query cancellation on unmount or re-render | |
| return Promise.reject(error); | |
| } | |
| const isTest = | |
| (typeof process !== 'undefined' && process.env?.NODE_ENV === 'test') || | |
| (typeof import.meta !== 'undefined' && import.meta.env?.MODE === 'test'); | |
| if (!isTest) { | |
| if (error.code === 'ECONNABORTED' || error.message?.includes('timeout')) { | |
| console.warn('[API Warning] Request timed out, using cached/fallback state:', error.config?.url); | |
| } else { | |
| console.warn('[API Warning]', error.response?.data ?? error.message); | |
| } | |
| } | |
| return Promise.reject(error); | |
| }, | |
| ); | |
| export function getActiveTenantId(): string { | |
| if (typeof window !== 'undefined') { | |
| return localStorage.getItem('cfi_tenant_id') || sessionStorage.getItem('cfi_tenant_id') || 'default'; | |
| } | |
| return 'default'; | |
| } | |
| export function setClientTenant(tenantId: string | null): void { | |
| if (typeof window !== 'undefined') { | |
| if (tenantId) { | |
| localStorage.setItem('cfi_tenant_id', tenantId); | |
| } else { | |
| localStorage.removeItem('cfi_tenant_id'); | |
| sessionStorage.removeItem('cfi_tenant_id'); | |
| } | |
| } | |
| } | |
| export function switchActiveTenant(queryClient: { clear: () => void }, newTenantId: string): void { | |
| setClientTenant(newTenantId); | |
| queryClient.clear(); | |
| } | |
| /** | |
| * Safely extract and format an API error message into a displayable string. | |
| * Prevents React Minified Error #31 caused by rendering raw error objects or | |
| * FastAPI/Pydantic validation error detail arrays: [{ loc, msg, type }]. | |
| */ | |
| export function formatApiError(err: unknown, defaultMessage = 'An unexpected error occurred'): string { | |
| if (!err) return defaultMessage; | |
| const anyErr = err as any; | |
| const detail = anyErr?.response?.data?.detail ?? anyErr?.data?.detail; | |
| if (typeof detail === 'string') { | |
| return detail.trim() || defaultMessage; | |
| } | |
| if (Array.isArray(detail)) { | |
| const formatted = detail | |
| .map((item) => { | |
| if (typeof item === 'string') return item; | |
| if (item && typeof item === 'object') { | |
| const locStr = Array.isArray(item.loc) ? item.loc.join('.') : ''; | |
| const msg = item.msg || item.message || JSON.stringify(item); | |
| return locStr ? `${locStr}: ${msg}` : msg; | |
| } | |
| return String(item); | |
| }) | |
| .filter(Boolean) | |
| .join('; '); | |
| return formatted || defaultMessage; | |
| } | |
| if (detail && typeof detail === 'object') { | |
| return (detail as any).msg || (detail as any).message || JSON.stringify(detail); | |
| } | |
| if (typeof anyErr?.message === 'string') { | |
| return anyErr.message; | |
| } | |
| return defaultMessage; | |
| } | |