import axios, { InternalAxiosRequestConfig } from 'axios'; import { getApiBaseUrl } from '../config'; import { triggerSessionExpired, isUserSyncEndpoint, isTenantEndpoint } from './sessionExpiration'; import { isUserSyncedInBrowser, isActivationPending, syncUserAccount } from './userSyncService'; export const apiClient = axios.create({ baseURL: getApiBaseUrl(), headers: { 'Content-Type': 'application/json; version=1', Accept: 'application/json; version=1', }, timeout: 20000, }); apiClient.interceptors.request.use( async (config: InternalAxiosRequestConfig) => { config.baseURL = getApiBaseUrl(); const token = typeof window !== 'undefined' ? localStorage.getItem('pfm_access_token') : null; if (token && config.headers) { config.headers.Authorization = `Bearer ${token}`; } const isLifecycleRequest = isUserSyncEndpoint(config.url) || isTenantEndpoint(config.url); if (token && !isLifecycleRequest) { if (isActivationPending()) { return Promise.reject(new Error('User account is pending administrator activation')); } const storedSub = typeof window !== 'undefined' ? (localStorage.getItem('pfm_user_sub') || '') : ''; if (!isUserSyncedInBrowser(storedSub, token)) { const syncRes = await syncUserAccount(storedSub, token); if (!syncRes.success) { return Promise.reject(new Error(syncRes.errorMessage || 'User account sync pending activation')); } } } return config; }, (error) => Promise.reject(error) ); apiClient.interceptors.response.use( (response) => response, (error) => { if (error?.response?.status === 401) { const requestUrl = error.config?.url; const isLifecycleEndpoint = isUserSyncEndpoint(requestUrl) || isTenantEndpoint(requestUrl); if (!isLifecycleEndpoint) { const detailMsg = error?.response?.data?.detail || error?.response?.data?.message || 'Session expired (HTTP 401).'; triggerSessionExpired(detailMsg, requestUrl); } } return Promise.reject(error); } );