yusufcalisir's picture
deploy: Hugging Face space upload
73ba4f5
Raw History Blame Contribute Delete
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;
}