front-hub/src/stores/makeRequest.ts

95 lines
2.4 KiB
TypeScript
Raw Normal View History

2023-03-31 14:59:54 +00:00
import axios, { AxiosResponse } from "axios";
import { create } from "zustand";
import { persist } from "zustand/middleware";
2023-03-31 14:59:54 +00:00
2023-03-20 11:40:19 +00:00
type Token = string;
2023-03-31 14:59:54 +00:00
interface AuthStore {
2023-03-20 11:40:19 +00:00
token: Token;
2023-03-31 14:59:54 +00:00
makeRequest: <TRequest = unknown, TResponse = unknown>(props: FirstRequest<TRequest>) => Promise<TResponse>;
clearToken: () => void;
}
2023-03-31 14:59:54 +00:00
interface FirstRequest<T> {
2023-03-20 11:40:19 +00:00
method?: string;
url: string;
2023-03-31 14:59:54 +00:00
body?: T;
2023-03-20 11:40:19 +00:00
useToken?: boolean;
contentType?: boolean;
2023-03-31 14:59:54 +00:00
signal?: AbortSignal;
}
2023-03-31 14:59:54 +00:00
export const authStore = create<AuthStore>()(
2023-03-20 11:40:19 +00:00
persist(
(set, get) => ({
token: "",
2023-03-31 14:59:54 +00:00
makeRequest: <TRequest, TResponse>(props: FirstRequest<TRequest>): Promise<TResponse> => {
2023-03-20 11:40:19 +00:00
const newProps = { ...props, HC: (newToken: Token) => set({ token: newToken }), token: get().token };
2023-03-31 14:59:54 +00:00
return makeRequest<TRequest, TResponse>(newProps);
2023-03-20 11:40:19 +00:00
},
clearToken: () => set({ token: "" }),
}),
{
name: "token",
}
)
);
2023-03-31 14:59:54 +00:00
interface MakeRequest<T> extends FirstRequest<T> {
2023-03-20 11:40:19 +00:00
HC: (newToken: Token) => void;
token: Token;
}
2023-03-31 14:59:54 +00:00
async function makeRequest<TRequest, TResponse>({
method = "post",
url,
body,
useToken = true,
contentType = false,
HC,
token,
signal,
}: MakeRequest<TRequest>) {
2023-03-20 11:40:19 +00:00
//В случае 401 рефреш должен попробовать вызваться 1 раз
let headers: any = {};
if (useToken) headers["Authorization"] = token;
if (contentType) headers["Content-Type"] = "application/json";
2023-03-31 14:59:54 +00:00
try {
const response = await axios<TRequest, AxiosResponse<TResponse & { accessToken?: string; }>>(
{ url, method, headers, data: body, signal }
);
if (response.data?.accessToken) {
HC(response.data.accessToken);
}
return response.data;
} catch (error: any) {
if (error?.response?.status === 401) {
const refreshResponse = await refresh();
if (refreshResponse.data?.accessToken) HC(refreshResponse.data.accessToken);
headers["Authorization"] = refreshResponse.data.accessToken;
const response = await axios<TRequest, AxiosResponse<TResponse>>(
{ url, method, headers, data: body, signal }
);
return response.data;
}
throw error;
}
}
function refresh() {
2023-03-31 14:59:54 +00:00
return axios<never, AxiosResponse<{ accessToken: string; }>>("https://admin.pena.digital/auth/refresh", {
2023-03-20 11:40:19 +00:00
headers: {
Authorization: localStorage.getItem("AT"),
"Content-Type": "application/json",
},
});
}