All checks were successful
Build Frontend / Build Frontend (push) Successful in 24s
145 lines
3.7 KiB
JavaScript
145 lines
3.7 KiB
JavaScript
import axios from "axios";
|
|
import { useAuthStore } from "@/stores/auth";
|
|
import { useToast } from "vue-toastification";
|
|
|
|
// Get the API base URL
|
|
const getApiBaseUrl = () => {
|
|
// If VITE_API_URL is set, use it
|
|
if (import.meta.env.VITE_API_URL) {
|
|
return import.meta.env.VITE_API_URL;
|
|
}
|
|
|
|
// In production, use the api subdomain
|
|
if (import.meta.env.PROD) {
|
|
const currentHost = window.location.hostname;
|
|
const protocol = window.location.protocol;
|
|
|
|
// If on turbotrades.dev, use api.turbotrades.dev
|
|
if (
|
|
currentHost === "turbotrades.dev" ||
|
|
currentHost === "www.turbotrades.dev"
|
|
) {
|
|
return `${protocol}//api.turbotrades.dev/api`;
|
|
}
|
|
|
|
// For other domains, try api subdomain
|
|
return `${protocol}//api.${currentHost}/api`;
|
|
}
|
|
|
|
// In development, use relative path (Vite proxy handles it)
|
|
return "/api";
|
|
};
|
|
|
|
// Create axios instance
|
|
const axiosInstance = axios.create({
|
|
baseURL: getApiBaseUrl(),
|
|
timeout: 15000,
|
|
withCredentials: true,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
});
|
|
|
|
// Request interceptor
|
|
axiosInstance.interceptors.request.use(
|
|
(config) => {
|
|
// You can add auth token to headers here if needed
|
|
// const token = localStorage.getItem('token')
|
|
// if (token) {
|
|
// config.headers.Authorization = `Bearer ${token}`
|
|
// }
|
|
return config;
|
|
},
|
|
(error) => {
|
|
return Promise.reject(error);
|
|
}
|
|
);
|
|
|
|
// Response interceptor
|
|
axiosInstance.interceptors.response.use(
|
|
(response) => {
|
|
return response;
|
|
},
|
|
async (error) => {
|
|
const toast = useToast();
|
|
const authStore = useAuthStore();
|
|
|
|
if (error.response) {
|
|
const { status, data } = error.response;
|
|
|
|
switch (status) {
|
|
case 401:
|
|
// Unauthorized - token expired or invalid
|
|
if (data.code === "TokenExpired") {
|
|
// Try to refresh token
|
|
try {
|
|
const refreshed = await authStore.refreshToken();
|
|
if (refreshed) {
|
|
// Retry the original request
|
|
return axiosInstance.request(error.config);
|
|
}
|
|
} catch (refreshError) {
|
|
// Refresh failed, logout user
|
|
authStore.clearUser();
|
|
window.location.href = "/";
|
|
}
|
|
} else {
|
|
authStore.clearUser();
|
|
toast.error("Please login to continue");
|
|
}
|
|
break;
|
|
|
|
case 403:
|
|
// Forbidden
|
|
toast.error(data.message || "Access denied");
|
|
break;
|
|
|
|
case 404:
|
|
// Not found
|
|
toast.error(data.message || "Resource not found");
|
|
break;
|
|
|
|
case 429:
|
|
// Too many requests
|
|
toast.error("Too many requests. Please slow down.");
|
|
break;
|
|
|
|
case 500:
|
|
// Server error
|
|
toast.error("Server error. Please try again later.");
|
|
break;
|
|
|
|
case 503:
|
|
// Service unavailable - maintenance mode
|
|
if (data.maintenance) {
|
|
// Only redirect if user is not admin
|
|
if (!authStore.isAdmin) {
|
|
window.location.href = "/maintenance";
|
|
}
|
|
// Don't show toast for maintenance, page will handle it
|
|
return Promise.reject(error);
|
|
} else {
|
|
toast.error("Service temporarily unavailable");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// Other errors
|
|
if (data.message) {
|
|
toast.error(data.message);
|
|
}
|
|
}
|
|
} else if (error.request) {
|
|
// Request made but no response
|
|
toast.error("Network error. Please check your connection.");
|
|
} else {
|
|
// Something else happened
|
|
toast.error("An unexpected error occurred");
|
|
}
|
|
|
|
return Promise.reject(error);
|
|
}
|
|
);
|
|
|
|
export default axiosInstance;
|