import {createRoot} from 'react-dom/client'; import App from './App'; import './index.css'; import { ErrorBoundary } from './lib/sentry'; // WebSocket Suppressor (Benign Vite noise) window.addEventListener('error', (e) => { if (e.message && (e.message.includes('WebSocket') || e.message.includes('vite'))) { e.preventDefault(); } }); const rootElement = document.getElementById('root'); if (!rootElement) throw new Error('No se encontró el elemento root'); try { createRoot(rootElement).render( ); } catch (error) { console.error('❌ Fatal error rendering app:', error); const div = document.createElement('div'); div.style.cssText = 'padding:20px; color:red; font-family:monospace;'; div.textContent = `Error: ${String(error)}`; rootElement.appendChild(div); } // Service Worker: DESACTIVADO — desregistrar + limpiar cachés viejas. if ("serviceWorker" in navigator) { navigator.serviceWorker.getRegistrations() .then((regs) => regs.forEach((r) => r.unregister())) .catch(() => {}); if (typeof caches !== "undefined") { caches.keys().then((keys) => keys.forEach((k) => caches.delete(k))).catch(() => {}); } } // Chunk viejo tras un deploy: Vite emite 'vite:preloadError' cuando un import() // dinámico falla (el JS con hash ya no existe). Recargar UNA vez trae el // index.html nuevo. Guard en sessionStorage para no entrar en bucle. window.addEventListener("vite:preloadError", (e) => { if (!sessionStorage.getItem("agrovida_chunk_reload")) { sessionStorage.setItem("agrovida_chunk_reload", "1"); e.preventDefault(); window.location.reload(); } }); // Verificador de versión — fuerza recarga cuando hay un nuevo deploy. // /version.json tiene ?ts=Date.now() para evitar caché HTTP de ese archivo. // Corre al inicio Y cada vez que la app vuelve a primer plano (el caso típico: // el teléfono la tenía abierta en segundo plano durante un deploy). const KEY_BUILD = "agrovida_build"; const KEY_LAST_RELOAD = "agrovida_last_reload"; function checkVersion() { fetch("/version.json?ts=" + Date.now(), { cache: "no-store" }) .then(r => r.json()) .then(({ build }: { build: string }) => { const stored = localStorage.getItem(KEY_BUILD); if (!stored) { localStorage.setItem(KEY_BUILD, build); return; } // Solo recargar si el build es MÁS NUEVO (timestamp numérico). Durante la // propagación de un deploy, los nodos CDN pueden alternar viejo/nuevo: // comparar por desigualdad simple causaba un bucle infinito de recargas. if (Number(build) <= Number(stored)) return; // Máximo una recarga automática por minuto (corta cualquier bucle). const last = Number(sessionStorage.getItem(KEY_LAST_RELOAD) || 0); if (Date.now() - last < 60_000) { localStorage.setItem(KEY_BUILD, build); return; } sessionStorage.setItem(KEY_LAST_RELOAD, String(Date.now())); localStorage.setItem(KEY_BUILD, build); window.location.reload(); }) .catch(() => {}); } checkVersion(); document.addEventListener("visibilitychange", () => { if (document.visibilityState === "visible") checkVersion(); }); setInterval(checkVersion, 5 * 60 * 1000);