create-kalp-boilerplate
Version:
A Kalp CLI tool to generate a React boilerplate
102 lines (87 loc) • 3.01 kB
text/typescript
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
import { API_CONFIG } from './config';
// Define types for tokens and responses
interface TokenResponse {
access_token: string;
refresh_token: string;
}
interface APIResponse<T = any> {
success: boolean;
result: T;
}
// Utility functions to manage tokens
const getAccessToken = (): string | null => localStorage.getItem('access_token');
const getRefreshToken = (): string | null => localStorage.getItem('refresh_token');
// Token refresh logic
let isRefreshing = false;
// Function to create Axios instances
const createAxiosInstance = (baseURL: string, defaultHeaders: Record<string, string> = {}): AxiosInstance => {
return axios.create({
baseURL,
timeout: API_CONFIG.TIMEOUT,
headers: defaultHeaders,
});
};
// Primary axios instance
export const axiosInstance: AxiosInstance = createAxiosInstance(API_CONFIG.BASE_URL);
// Request interceptor
axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig): AxiosRequestConfig => {
const token = getAccessToken();
if (token) {
config.headers = {
...config.headers,
Authorization: `Bearer ${token}`,
};
}
return config;
},
(error: AxiosError): Promise<AxiosError> => Promise.reject(error)
);
// Response interceptor
axiosInstance.interceptors.response.use(
(response: AxiosResponse): AxiosResponse => response,
async (error: AxiosError): Promise<AxiosResponse | void> => {
const originalRequest = error.config;
if (error.response?.status === 403) {
try {
await axios.get(`${API_CONFIG.BASE_URL}/users/logout`, {
headers: {
Authorization: `Bearer ${getAccessToken()}`,
'Content-Type': 'application/json',
},
});
} catch (logoutError) {
console.error('Logout failed:', logoutError);
}
return Promise.reject(error);
}
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
if (!isRefreshing) {
isRefreshing = true;
try {
const response = await axios.get<APIResponse<TokenResponse>>(`${API_CONFIG.BASE_URL}/users/refresh-token`, {
headers: {
refresh_token: getRefreshToken() || '',
'Content-Type': 'application/json',
},
});
const { access_token, refresh_token } = response.data.result;
localStorage.setItem('access_token', access_token);
localStorage.setItem('refresh_token', refresh_token);
isRefreshing = false;
originalRequest.headers = {
...originalRequest.headers,
Authorization: `Bearer ${access_token}`,
};
return axiosInstance(originalRequest);
} catch (refreshError) {
isRefreshing = false;
return Promise.reject(refreshError);
}
}
}
return Promise.reject(error);
}
);