87 lines
3.0 KiB
TypeScript
87 lines
3.0 KiB
TypeScript
import axios from 'axios'
|
|
import { API_BASE_URL, API_ENDPOINTS } from '@/config/api-config' // api-config.ts can be moved to src/config/
|
|
import router from '@/router' // Import the router instance
|
|
import { useAuthStore } from '@/stores/auth' // Import the auth store
|
|
import type { SettlementActivityCreate, SettlementActivityPublic } from '@/types/expense' // Import the types for the payload and response
|
|
import { stringify } from 'qs';
|
|
|
|
// Create axios instance
|
|
const api = axios.create({
|
|
baseURL: API_BASE_URL, // API_BASE_URL should come from env or config
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
withCredentials: true, // Enable sending cookies and authentication headers
|
|
paramsSerializer: {
|
|
serialize: (params) => stringify(params, { arrayFormat: 'repeat' }),
|
|
},
|
|
})
|
|
|
|
// Create apiClient with helper methods
|
|
const apiClient = {
|
|
get: (endpoint: string, config = {}) => api.get(endpoint, config),
|
|
post: (endpoint: string, data = {}, config = {}) => api.post(endpoint, data, config),
|
|
put: (endpoint: string, data = {}, config = {}) => api.put(endpoint, data, config),
|
|
patch: (endpoint: string, data = {}, config = {}) => api.patch(endpoint, data, config),
|
|
delete: (endpoint: string, config = {}) => api.delete(endpoint, config),
|
|
}
|
|
|
|
// Request interceptor
|
|
api.interceptors.request.use(
|
|
(config) => {
|
|
const token = localStorage.getItem('token')
|
|
if (token) {
|
|
config.headers.Authorization = `Bearer ${token}`
|
|
}
|
|
return config
|
|
},
|
|
(error) => {
|
|
console.error('Request error:', error)
|
|
return Promise.reject(error)
|
|
},
|
|
)
|
|
|
|
// Response interceptor
|
|
api.interceptors.response.use(
|
|
(response) => response,
|
|
async (error) => {
|
|
const originalRequest = error.config
|
|
const authStore = useAuthStore()
|
|
|
|
if (error.response?.status === 401 && !originalRequest._retry) {
|
|
originalRequest._retry = true
|
|
try {
|
|
const refreshTokenValue = authStore.refreshToken
|
|
if (!refreshTokenValue) {
|
|
authStore.clearTokens()
|
|
await router.push('/auth/login')
|
|
return Promise.reject(error)
|
|
}
|
|
|
|
// Send refresh token in request body as expected by backend
|
|
const response = await api.post(API_ENDPOINTS.AUTH.REFRESH, { refresh_token: refreshTokenValue }, {
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
}
|
|
})
|
|
|
|
const { access_token: newAccessToken, refresh_token: newRefreshToken } = response.data
|
|
authStore.setTokens({ access_token: newAccessToken, refresh_token: newRefreshToken })
|
|
|
|
originalRequest.headers.Authorization = `Bearer ${newAccessToken}`
|
|
return api(originalRequest)
|
|
} catch (refreshError) {
|
|
authStore.clearTokens()
|
|
await router.push('/auth/login')
|
|
return Promise.reject(refreshError)
|
|
}
|
|
}
|
|
return Promise.reject(error)
|
|
},
|
|
)
|
|
|
|
// Export the original axios too if some parts of your app used it directly
|
|
const globalAxios = axios
|
|
|
|
export { api, globalAxios, API_ENDPOINTS, apiClient }
|