@droppii-org/chat-sdk
Version:
Droppii React Chat SDK
66 lines (65 loc) • 2.79 kB
JavaScript
import axios from "axios";
import useAuthStore from "../store/auth";
const TIMEOUT = 90000;
export const apiInstance = axios.create({
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
timeout: TIMEOUT,
});
// Module-level refresh promise cache to prevent concurrent refresh calls
let sdkRefreshPromise = null;
apiInstance.interceptors.request.use((config) => {
return Object.assign(Object.assign({}, config), { baseURL: useAuthStore.getState().apiAddress, headers: Object.assign(Object.assign({}, config.headers), { Authorization: `Bearer ${useAuthStore.getState().accessToken}`, token: useAuthStore.getState().chatToken }) });
}, (error) => {
// Handle errors globally
return Promise.reject(error);
});
// Response interceptor for 401 handling - delegates to consumer app
apiInstance.interceptors.response.use((response) => response, async (error) => {
var _a;
const originalRequest = error.config;
// Prevent infinite loops with _retry flag
if (originalRequest._retry) {
return Promise.reject(error);
}
// Handle 401 responses
if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 401) {
const { onTokenRefresh, onAuthError } = useAuthStore.getState();
// No callback provided, reject immediately
if (!onTokenRefresh) {
const authError = new Error("Token expired, no refresh callback provided");
onAuthError === null || onAuthError === void 0 ? void 0 : onAuthError(authError);
return Promise.reject(error);
}
originalRequest._retry = true;
try {
// Cache refresh promise to ensure single refresh call for concurrent requests
if (!sdkRefreshPromise) {
sdkRefreshPromise = onTokenRefresh()
.then((newToken) => {
// Update SDK's access token
useAuthStore.getState().setAccessToken(newToken);
return newToken;
})
.catch((err) => {
// Notify consumer app of auth error
onAuthError === null || onAuthError === void 0 ? void 0 : onAuthError(err);
throw err;
})
.finally(() => {
sdkRefreshPromise = null;
});
}
const newToken = await sdkRefreshPromise;
// Retry original request with new token
originalRequest.headers.Authorization = `Bearer ${newToken}`;
return apiInstance(originalRequest);
}
catch (refreshError) {
return Promise.reject(error);
}
}
return Promise.reject(error);
});