v1.0.110 makerequest теперь сообщает о ошибках статуса сразу в обработчик + добавлен обработчик ошибок, анализирующий куда ему там слаться
Some checks failed
CreateVersion / BumpVersion (push) Has been cancelled
Some checks failed
CreateVersion / BumpVersion (push) Has been cancelled
This commit is contained in:
commit
7eb8988fc6
@ -1,49 +1,27 @@
|
||||
import axios, { AxiosResponse, Method, ResponseType } from "axios";
|
||||
import { getAuthToken, setAuthToken } from "../stores/auth";
|
||||
|
||||
export interface MakeRequestConfig {
|
||||
getAuthToken: () => string | undefined;
|
||||
setAuthToken: (token: string) => void;
|
||||
refreshUrl: string;
|
||||
logoutFn: () => void;
|
||||
handleComponentError?: (error: Error, info?: any) => void;
|
||||
clearAuthDataFn?: () => void;
|
||||
clearErrorHandlingConfig?: () => void;
|
||||
allowedDomains?: string[];
|
||||
debugSecretKey?: string;
|
||||
logErrorFn?: (message: string, error?: any) => void;
|
||||
}
|
||||
import { Ticket, clearErrorHandlingConfig } from "..";
|
||||
|
||||
let makeRequestConfig: MakeRequestConfig | null = null;
|
||||
|
||||
export interface MakeRequestConfig {
|
||||
logoutFn: () => void;
|
||||
handleComponentError?: (error: Error, info: any, getTickets: () => Ticket[]) => void;
|
||||
getTickets?: () => Ticket[];
|
||||
}
|
||||
|
||||
export function createMakeRequestConfig(
|
||||
getAuthToken: () => string | undefined,
|
||||
setAuthToken: (token: string) => void,
|
||||
refreshUrl: string,
|
||||
logoutFn?: () => void,
|
||||
handleComponentError?: (error: Error, info?: any) => void,
|
||||
clearAuthDataFn?: () => void,
|
||||
clearErrorHandlingConfig?: () => void,
|
||||
allowedDomains?: string[],
|
||||
debugSecretKey?: string,
|
||||
logErrorFn?: (message: string, error?: any) => void,
|
||||
handleComponentError?: (error: Error, info: any, getTickets: () => Ticket[]) => void,
|
||||
getTickets?: () => Ticket[]
|
||||
) {
|
||||
makeRequestConfig = {
|
||||
getAuthToken,
|
||||
setAuthToken,
|
||||
refreshUrl,
|
||||
logoutFn: () => {
|
||||
clearMakeRequestConfig();
|
||||
if (typeof clearErrorHandlingConfig === 'function') clearErrorHandlingConfig();
|
||||
clearErrorHandlingConfig();
|
||||
if (logoutFn) logoutFn();
|
||||
},
|
||||
handleComponentError,
|
||||
clearAuthDataFn,
|
||||
clearErrorHandlingConfig,
|
||||
allowedDomains,
|
||||
debugSecretKey,
|
||||
logErrorFn,
|
||||
getTickets,
|
||||
};
|
||||
}
|
||||
|
||||
@ -51,10 +29,6 @@ export function getMakeRequestConfig(): MakeRequestConfig | null {
|
||||
return makeRequestConfig;
|
||||
}
|
||||
|
||||
export function clearMakeRequestConfig() {
|
||||
makeRequestConfig = null;
|
||||
}
|
||||
|
||||
export async function makeRequest<TRequest = unknown, TResponse = unknown>({
|
||||
method = "post",
|
||||
url,
|
||||
@ -129,15 +103,16 @@ export async function makeRequest<TRequest = unknown, TResponse = unknown>({
|
||||
const errorMessage = `HTTP ${error.response.status}: ${error.response?.data?.message || error.message}`;
|
||||
const httpError = new Error(errorMessage);
|
||||
httpError.stack = error.stack;
|
||||
config.handleComponentError(httpError, { componentStack: null });
|
||||
// Передаем getTickets как callback
|
||||
config.handleComponentError(httpError, { componentStack: null }, config.getTickets || (() => []));
|
||||
}
|
||||
// refreshToken is empty
|
||||
if (
|
||||
error.response?.status === 400 &&
|
||||
error.response?.data?.message === "refreshToken is empty" &&
|
||||
config?.clearAuthDataFn
|
||||
config?.logoutFn
|
||||
) {
|
||||
config.clearAuthDataFn();
|
||||
config.logoutFn();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
@ -152,4 +127,4 @@ export async function refresh(token?: string): Promise<AxiosResponse<{ accessTok
|
||||
},
|
||||
method: "post"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
|
||||
import { ErrorInfo } from "react";
|
||||
import { Ticket, createTicket, getAuthToken, sendTicketMessage } from "..";
|
||||
|
||||
let errorsQueue: ComponentError[] = [];
|
||||
let timeoutId: ReturnType<typeof setTimeout>;
|
||||
|
||||
|
||||
interface ComponentError {
|
||||
timestamp: number;
|
||||
message: string;
|
||||
@ -13,29 +11,24 @@ interface ComponentError {
|
||||
componentStack: string | null | undefined;
|
||||
}
|
||||
|
||||
|
||||
function isErrorReportingAllowed(error?: Error): boolean {
|
||||
// Если ошибка помечена как debug-override — всегда отправлять
|
||||
if (error && (error as any).__forceSend) return true;
|
||||
|
||||
// Проверяем домен
|
||||
const currentDomain = window.location.hostname;
|
||||
|
||||
return currentDomain !== 'localhost';
|
||||
}
|
||||
|
||||
export function handleComponentError(error: Error, info: ErrorInfo, tickets: Ticket[]) {
|
||||
// Новый API: getTickets — callback, возвращающий актуальные тикеты
|
||||
export function handleComponentError(error: Error, info: ErrorInfo, getTickets: () => Ticket[]) {
|
||||
//репортим только о авторизонышах
|
||||
if (!getAuthToken()) return;
|
||||
|
||||
// Проверяем разрешение на отправку ошибок (по домену)
|
||||
if (!isErrorReportingAllowed(error)) {
|
||||
console.log('❌ Отправка ошибки заблокирована:', error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`✅ Обработка ошибки: ${error.message}`);
|
||||
|
||||
// Копируем __forceSend если есть
|
||||
const componentError: ComponentError & { __forceSend?: boolean } = {
|
||||
timestamp: Math.floor(Date.now() / 1000),
|
||||
@ -44,30 +37,21 @@ export function handleComponentError(error: Error, info: ErrorInfo, tickets: Tic
|
||||
componentStack: info.componentStack,
|
||||
...(error && (error as any).__forceSend ? { __forceSend: true } : {})
|
||||
};
|
||||
|
||||
queueErrorRequest(componentError, tickets);
|
||||
queueErrorRequest(componentError, getTickets);
|
||||
}
|
||||
|
||||
//Ставит ошибку в очередь для отправки
|
||||
//Через 1 секунду вызывает sendErrorsToServer
|
||||
export function queueErrorRequest(error: ComponentError, tickets: Ticket[]) {
|
||||
// Ставит ошибку в очередь для отправки, через 1 секунду вызывает sendErrorsToServer
|
||||
export function queueErrorRequest(error: ComponentError, getTickets: () => Ticket[]) {
|
||||
errorsQueue.push(error);
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => {
|
||||
sendErrorsToServer(tickets);
|
||||
sendErrorsToServer(getTickets);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
||||
//Отправляет накопленные ошибки в тикеты
|
||||
//Ищет существующий тикет с system: true или создает новый
|
||||
|
||||
export async function sendErrorsToServer(
|
||||
tickets: Ticket[]
|
||||
) {
|
||||
// Отправляет накопленные ошибки в тикеты, ищет существующий тикет с system: true или создает новый
|
||||
export async function sendErrorsToServer(getTickets: () => Ticket[]) {
|
||||
if (errorsQueue.length === 0) return;
|
||||
|
||||
// Проверяем разрешение на отправку ошибок (по домену и debug-override)
|
||||
// Если хотя бы одна ошибка в очереди с __forceSend, отправляем всё
|
||||
const forceSend = errorsQueue.some(e => (e as any).__forceSend);
|
||||
@ -76,16 +60,14 @@ export async function sendErrorsToServer(
|
||||
errorsQueue = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const tickets = getTickets();
|
||||
try {
|
||||
// Формируем сообщение об ошибке
|
||||
const errorMessage = errorsQueue.map(error => {
|
||||
return `[${new Date(error.timestamp * 1000).toISOString()}] ${error.message}\n\nCall Stack:\n${error.callStack || 'N/A'}\n\nComponent Stack:\n${error.componentStack || 'N/A'}`;
|
||||
}).join('\n\n---\n\n');
|
||||
|
||||
// ВСЕГДА ищем тикет через API
|
||||
const existingSystemTicket = await findSystemTicket(tickets);
|
||||
|
||||
if (existingSystemTicket) {
|
||||
sendTicketMessage({
|
||||
ticketId: existingSystemTicket,
|
||||
@ -109,9 +91,7 @@ export async function sendErrorsToServer(
|
||||
}
|
||||
|
||||
// Ищет существующий тикет с system: true
|
||||
export async function findSystemTicket(
|
||||
tickets: Ticket[]
|
||||
) {
|
||||
export async function findSystemTicket(tickets: Ticket[]) {
|
||||
for (const ticket of tickets) {
|
||||
console.log("[findSystemTicket] Проверяем тикет:", ticket);
|
||||
if (!('messages' in ticket)) {
|
||||
@ -119,7 +99,11 @@ export async function findSystemTicket(
|
||||
console.log("[findSystemTicket] Найден тикет по top_message.system:true:", ticket.id);
|
||||
return ticket.id;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function clearErrorHandlingConfig () {
|
||||
clearTimeout(timeoutId);
|
||||
errorsQueue = [];
|
||||
}
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@frontend/kitui",
|
||||
"version": "1.0.108",
|
||||
"version": "1.0.109",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@frontend/kitui",
|
||||
"version": "1.0.108",
|
||||
"version": "1.0.109",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"immer": "^10.0.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@frontend/kitui",
|
||||
"version": "1.0.109",
|
||||
"version": "1.0.110",
|
||||
"description": "test",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
|
Loading…
Reference in New Issue
Block a user