74 lines
2.6 KiB
TypeScript
74 lines
2.6 KiB
TypeScript
import { useCallback, useEffect, useRef } from 'react';
|
|
import { useQuery } from '@msb/http';
|
|
import axios from 'axios';
|
|
import type { SentryState } from '../store/types';
|
|
import { isExcludedPath } from '../utils';
|
|
import { sentryConfig, tokenHeader } from '../utils/constants';
|
|
|
|
interface Props extends SentryState {
|
|
enabled: boolean;
|
|
}
|
|
|
|
const TOKEN_REQUEST_KEY = 'tokenRequest';
|
|
|
|
/** Хук механизма генерации токена. */
|
|
const useToken = ({ enabled, attempts, isSendingAllowed, setState }: Props) => {
|
|
const reconnectTimer = useRef<NodeJS.Timeout>();
|
|
const { enabledTokenGeneration, url, timeout, retry, retryDelay, attemptsBeforeDisable, reconnectionTime } = sentryConfig;
|
|
// Признак активности механизма генерации токена для отправляемых данных
|
|
const isTokenGenerationAvailable = Boolean(enabledTokenGeneration && url);
|
|
|
|
// GET-запрос токена для отправляемых данных
|
|
const { refetch, isLoading } = useQuery([TOKEN_REQUEST_KEY], () => axios.get(url!, { timeout }), {
|
|
enabled: enabled && isTokenGenerationAvailable && !isExcludedPath(),
|
|
retry,
|
|
retryDelay,
|
|
refetchOnWindowFocus: false,
|
|
onSuccess: response => {
|
|
const token = response?.headers?.[tokenHeader];
|
|
|
|
if (token) {
|
|
const newAttemptsCount = attempts + 1;
|
|
|
|
let newProps: Partial<SentryState> = {};
|
|
|
|
// Если количество перезапросов токена не превышает максимально допустимое,
|
|
// то включаем логирование в Sentry, иначе выключаем
|
|
newProps =
|
|
newAttemptsCount < attemptsBeforeDisable ? { isSendingAllowed: true, token: Number(token) } : { isSendingAllowed: false };
|
|
|
|
setState?.({ ...newProps, attempts: newAttemptsCount });
|
|
}
|
|
},
|
|
onError: () => {
|
|
setState?.({ isSendingAllowed: false, token: null });
|
|
},
|
|
onSettled: () => {
|
|
clearTimeout(reconnectTimer.current);
|
|
|
|
if (!isSendingAllowed) {
|
|
reconnectTimer.current = setTimeout(async () => {
|
|
setState?.({ attempts: 0 });
|
|
|
|
await refetch();
|
|
}, reconnectionTime);
|
|
}
|
|
},
|
|
});
|
|
|
|
useEffect(() => () => clearTimeout(reconnectTimer.current), []);
|
|
|
|
/** Функция перезапроса токена. */
|
|
const renewToken = useCallback(async () => {
|
|
if (isLoading) return;
|
|
|
|
setState?.({ isSendingAllowed: false });
|
|
|
|
await refetch();
|
|
}, [isLoading, setState, refetch]);
|
|
|
|
return isTokenGenerationAvailable ? renewToken : undefined;
|
|
};
|
|
|
|
export { useToken };
|