68 lines
1.8 KiB
TypeScript
68 lines
1.8 KiB
TypeScript
import axios, { AxiosHeaders, type InternalAxiosRequestConfig } from "axios";
|
|
import { config } from "@config/config";
|
|
import { useAuthStore } from "@/store/authStore";
|
|
import {
|
|
applyAuthContextHeaders,
|
|
type AuthContextHeaderOptions,
|
|
} from "@/lib/requestHeaders";
|
|
|
|
export const API_URL = config.BACKEND_URL;
|
|
|
|
export const api = axios.create({
|
|
baseURL: API_URL,
|
|
});
|
|
|
|
export const resolveRequestUrl = (request: {
|
|
baseURL?: string;
|
|
url?: string;
|
|
}) => {
|
|
const requestUrl = request.url ?? "";
|
|
if (/^([a-z][a-z\d+\-.]*:)?\/\//i.test(requestUrl)) {
|
|
return requestUrl;
|
|
}
|
|
|
|
const baseURL = request.baseURL ?? "";
|
|
if (!baseURL || !requestUrl) {
|
|
return `${baseURL}${requestUrl}`;
|
|
}
|
|
|
|
return `${baseURL.replace(/\/+$/, "")}/${requestUrl.replace(/^\/+/, "")}`;
|
|
};
|
|
|
|
export interface ApiRequestConfig
|
|
extends InternalAxiosRequestConfig,
|
|
AuthContextHeaderOptions {}
|
|
|
|
api.interceptors.request.use(async (request: ApiRequestConfig) => {
|
|
const headers = new Headers(
|
|
request.headers
|
|
? AxiosHeaders.from(request.headers).toJSON() as Record<string, string>
|
|
: undefined,
|
|
);
|
|
await applyAuthContextHeaders(resolveRequestUrl(request), headers, request);
|
|
|
|
request.headers = AxiosHeaders.from(Object.fromEntries(headers.entries()));
|
|
|
|
return request;
|
|
});
|
|
|
|
api.interceptors.response.use(
|
|
(response) => {
|
|
if (
|
|
response.data &&
|
|
typeof response.data === "object" &&
|
|
Array.isArray(response.data.items) &&
|
|
typeof response.data.total === "number"
|
|
) {
|
|
response.data = response.data.items;
|
|
}
|
|
return response;
|
|
},
|
|
async (error) => {
|
|
if (error?.response?.status === 401 && typeof window !== "undefined") {
|
|
useAuthStore.getState().markSessionExpired("unauthorized");
|
|
}
|
|
return Promise.reject(error);
|
|
},
|
|
);
|