77 lines
2.2 KiB
TypeScript
77 lines
2.2 KiB
TypeScript
import axios, { AxiosResponse, Method, ResponseType } from "axios";
|
|
import { getAuthToken, setAuthToken } from "../stores/auth";
|
|
|
|
|
|
export async function makeRequest<TRequest = unknown, TResponse = unknown>({
|
|
method = "post",
|
|
url,
|
|
body,
|
|
useToken = true,
|
|
contentType = false,
|
|
responseType = "json",
|
|
signal,
|
|
withCredentials,
|
|
}: {
|
|
method?: Method;
|
|
url: string;
|
|
body?: TRequest;
|
|
/** Send access token */
|
|
useToken?: boolean;
|
|
contentType?: boolean;
|
|
responseType?: ResponseType;
|
|
signal?: AbortSignal;
|
|
/** Send refresh token */
|
|
withCredentials?: boolean;
|
|
}): Promise<TResponse> {
|
|
const headers: Record<string, string> = {};
|
|
if (useToken) headers["Authorization"] = getAuthToken() ? `Bearer ${getAuthToken()}` : "";
|
|
if (contentType) headers["Content-Type"] = "application/json";
|
|
|
|
try {
|
|
const response = await axios<TRequest, AxiosResponse<TResponse & { accessToken?: string; }>>({
|
|
url,
|
|
method,
|
|
headers,
|
|
data: body,
|
|
signal,
|
|
responseType,
|
|
withCredentials,
|
|
});
|
|
|
|
if (response.data?.accessToken) {
|
|
setAuthToken(response.data.accessToken);
|
|
}
|
|
|
|
return response.data;
|
|
} catch (error) {
|
|
if (axios.isAxiosError(error) && error.response?.status === 401 && !withCredentials) {
|
|
const refreshResponse = await refresh(getAuthToken());
|
|
if (refreshResponse.data?.accessToken) setAuthToken(refreshResponse.data.accessToken);
|
|
|
|
headers["Authorization"] = refreshResponse.data.accessToken;
|
|
const response = await axios.request<TRequest, AxiosResponse<TResponse>>({
|
|
url,
|
|
method,
|
|
headers,
|
|
data: body,
|
|
signal,
|
|
});
|
|
|
|
return response.data;
|
|
}
|
|
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
function refresh(token: string) {
|
|
|
|
|
|
return axios<never, AxiosResponse<{ accessToken: string; }>>(import.meta.env.VITE__APP_DOMAIN + "/auth/refresh", { headers: {
|
|
"Authorization": `Bearer ${token}`,
|
|
"Content-Type": "application/json",
|
|
},
|
|
method: "post"
|
|
});
|
|
}
|