Spaces:
Running
Running
| // Buzón opt-in de errores/feedback. Apagado por defecto — la promesa de | |
| // «nada sale de tu máquina» sigue siendo cierta salvo que el usuario decida | |
| // lo contrario en Ajustes. Cuando está activo: | |
| // - errores no capturados (window.onerror / unhandledrejection) y los | |
| // puntos concretos del código que llaman a reportError() se mandan a | |
| // /proxy/report (mismo origen, vía el proxy compartido de Elffuss) | |
| // - sendFeedback() manda texto libre que el usuario escriba a propósito | |
| // Nunca se manda código ni contenido del proyecto — solo el mensaje técnico, | |
| // la pila, la URL y el user-agent. Sin cola ni reintentos: si el envío | |
| // falla, se descarta sin más (evita que un fallo de red se convierta en | |
| // almacenamiento sin límite). | |
| let appName = 'elffuss'; | |
| let enabled = false; | |
| let hooked = false; | |
| const storageKey = () => 'elffuss.telemetry.' + appName; | |
| export function isEnabled() { return enabled; } | |
| export function setEnabled(v) { | |
| enabled = !!v; | |
| try { localStorage.setItem(storageKey(), enabled ? '1' : '0'); } catch { /* localStorage lleno/bloqueado */ } | |
| if (enabled) hookGlobalErrors(); | |
| } | |
| async function post(kind, message, opts = {}) { | |
| if (!enabled) return; | |
| try { | |
| await fetch('/proxy/report', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| app: appName, kind, message: String(message ?? '').slice(0, 2000), | |
| stack: String(opts.stack || '').slice(0, 4000), | |
| url: location.href, userAgent: navigator.userAgent, | |
| extra: String(opts.extra || '').slice(0, 2000), | |
| }), | |
| }); | |
| } catch { /* sin conexión o proxy caído: se descarta, no hay reintento */ } | |
| } | |
| export function reportError(message, opts = {}) { return post('error', message, opts); } | |
| export function sendFeedback(text) { return post('feedback', text); } | |
| function hookGlobalErrors() { | |
| if (hooked) return; | |
| hooked = true; | |
| window.addEventListener('error', e => { | |
| reportError(e.message || String(e.error) || 'error', { stack: e.error?.stack || '' }); | |
| }); | |
| window.addEventListener('unhandledrejection', e => { | |
| const r = e.reason; | |
| reportError('unhandledrejection: ' + (r?.message || r), { stack: r?.stack || '' }); | |
| }); | |
| } | |
| // Llamar UNA vez al arrancar, con el nombre de la app (para distinguir | |
| // elffuss-code de elffuss-claw en los informes) — lee la preferencia guardada. | |
| export function init(name) { | |
| appName = name || appName; | |
| try { enabled = localStorage.getItem(storageKey()) === '1'; } catch { enabled = false; } | |
| if (enabled) hookGlobalErrors(); | |
| } | |