Merge branch 'dev' of gitea.pena:PenaSide/UIKit into dev
Some checks failed
CreateVersion / BumpVersion (push) Has been cancelled

This commit is contained in:
Nastya 2025-07-22 21:49:14 +03:00
commit 784bd57410
4 changed files with 34 additions and 75 deletions

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

@ -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

@ -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",