Files
mcb-platform-monorepo/packages/sentry/model/hooks/use-token.ts
T
2025-11-25 09:43:22 +03:00

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 };