diff --git a/public/js/api.js b/public/js/api.js index 4413fb4..95a1ac0 100644 --- a/public/js/api.js +++ b/public/js/api.js @@ -54,11 +54,24 @@ async function api(path, opts = {}, _retry = 0) { // timeout 15s — иначе UI висит вечно const controller = new AbortController(); const tid = setTimeout(() => controller.abort(), 15000); + const t0 = Date.now(); try { r = await fetch(API_BASE + path, { ...o, signal: controller.signal }); } catch (networkErr) { clearTimeout(tid); - console.warn('fetch network error:', networkErr); + const ms = Date.now() - t0; + console.warn('fetch network error:', networkErr, 'ms:', ms); + // детальный лог на сервер для дебага + try { + fetch(API_BASE + '/api/v1/debug/log', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + path, status: 0, ms, ua: navigator.userAgent, err: String(networkErr), isTelegram: !!(window.Telegram && window.Telegram.WebApp), + }), + keepalive: true, + }).catch(() => {}); + } catch {} if (networkErr.name === 'AbortError') { throw new Error('Сервер не отвечает (таймаут 15с)'); } @@ -69,6 +82,18 @@ async function api(path, opts = {}, _retry = 0) { throw new Error('Нет связи с сервером'); } clearTimeout(tid); + const ms = Date.now() - t0; + // логируем всё на сервер для отладки с iOS + try { + fetch(API_BASE + '/api/v1/debug/log', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + path, status: r.status, ms, ua: navigator.userAgent.substring(0, 80), isTelegram: !!(window.Telegram && window.Telegram.WebApp), + }), + keepalive: true, + }).catch(() => {}); + } catch {} if (r.status === 401 && Store.refresh && !opts._isRefresh) { try { const r2 = await fetch(API_BASE + '/api/v1/auth/refresh', {