veza/apps/web/src/main.tsx
senke 5f69315f15 state-utilities: update stateInvalidation to work with React Query
- Created QueryClient singleton (queryClientSingleton.ts):
  - Provides global access to QueryClient for state invalidation
  - Set in main.tsx after QueryClient creation
- Updated invalidateQueries() to use QueryClient directly:
  - Replaced custom event system with direct QueryClient.invalidateQueries()
  - Added query key mapping for all resource types
  - Event system kept as fallback if QueryClient not available
- Updated invalidateStore() for Library Store:
  - Removed clearItems() call (method doesn't exist, domain data migrated to React Query)
  - Library Store now only contains UI state (filters)
  - React Query cache invalidation handles refetching
- Query keys mapped:
  - tracks: ['tracks'], ['track'], ['library']
  - playlists: ['playlists'], ['playlist']
  - users: ['users'], ['user'], ['auth'], ['userProfile']
  - conversations: ['conversations'], ['conversation'], ['chat'], ['chatConversations']
  - roles: ['roles'], ['role']
  - library: ['library'], ['tracks'], ['favorites'], ['libraryItems']
  - auth: ['auth'], ['user']
- Action 4.6.1.5 complete
2026-01-15 19:38:47 +01:00

127 lines
5.6 KiB
TypeScript

// CRITICAL: React must be imported first before any Zustand/react imports
import React from 'react';
import ReactDOM from 'react-dom/client';
// DEBUG: Global error handler pour capturer les erreurs d'initialisation
if (typeof window !== 'undefined') {
window.addEventListener('error', (event) => {
// #region agent log
if (event.message && event.message.includes('ie') && event.message.includes('initialization')) {
fetch('http://127.0.0.1:7242/ingest/09c5ea5e-2380-4cc3-92aa-d26f3b3d26f6',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'main.tsx:globalErrorHandler',message:'Variable ie initialization error caught',data:{message:event.message,filename:event.filename,lineno:event.lineno,colno:event.colno,error:event.error?.stack,loadedScripts:Array.from(document.scripts).map(s=>s.src)},timestamp:Date.now(),sessionId:'debug-session',runId:'runtime',hypothesisId:'B'})}).catch(()=>{});
}
// #endregion
}, true);
window.addEventListener('unhandledrejection', (event) => {
// #region agent log
if (event.reason && (event.reason.message?.includes('ie') || event.reason.message?.includes('initialization'))) {
fetch('http://127.0.0.1:7242/ingest/09c5ea5e-2380-4cc3-92aa-d26f3b3d26f6',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'main.tsx:unhandledRejection',message:'Unhandled rejection with ie error',data:{reason:event.reason?.message,stack:event.reason?.stack},timestamp:Date.now(),sessionId:'debug-session',runId:'runtime',hypothesisId:'B'})}).catch(()=>{});
}
// #endregion
});
}
import { BrowserRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
// Action 4.6.1.5: Import QueryClient singleton setter
import { setQueryClient } from './utils/queryClientSingleton';
// CRITICAL FIX: Import lazy de react-hot-toast pour éviter les collisions de noms de variables après minification
import { LazyToaster } from './components/feedback/LazyToaster';
import { App } from './app/App';
import './index.css';
import './styles/design-system.css';
import './styles/global-effects.css';
import './styles/header.css';
// Initialize i18next before React renders
import './lib/i18n';
// FIX #20: Initialize Sentry for error tracking
import { initSentry } from './lib/sentry';
// FE-API-019: Initialize MSW for development if enabled
import { env } from './config/env';
// HMR Force Update: 1765126900
// FIX #20: Initialize Sentry before React renders
initSentry();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
refetchOnWindowFocus: false,
},
},
});
// Action 4.6.1.5: Set QueryClient singleton for state invalidation
setQueryClient(queryClient);
// FE-API-019: Initialize MSW worker for development
async function enableMocking() {
if (!env.USE_MSW) {
return;
}
if (import.meta.env.DEV) {
const { worker } = await import('./mocks/browser');
// Start the worker
await worker.start({
onUnhandledRequest: 'bypass', // Don't warn about unhandled requests
serviceWorker: {
url: '/mockServiceWorker.js',
},
});
// FIX #18: Utiliser logger structuré
const { logger } = await import('./utils/logger');
logger.info('[MSW] Mock Service Worker started', { component: 'MSW' });
}
}
const renderApp = () => {
// #region agent log
fetch('http://127.0.0.1:7242/ingest/09c5ea5e-2380-4cc3-92aa-d26f3b3d26f6',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'main.tsx:renderApp',message:'Rendering app',data:{loadedScripts:document.scripts.length},timestamp:Date.now(),sessionId:'debug-session',runId:'runtime',hypothesisId:'C'})}).catch(()=>{});
// #endregion
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<BrowserRouter
future={{
v7_startTransition: true,
v7_relativeSplatPath: true,
}}
>
<App />
<LazyToaster position="top-right" />
</BrowserRouter>
</QueryClientProvider>
</React.StrictMode>,
);
};
// CRITICAL FIX: Précharger react-hot-toast AVANT de rendre l'app
// pour éviter les collisions de noms de variables (ie) lors de la minification
// Le module sera chargé dans un chunk séparé, évitant les conflits
const preloadToast = import('react-hot-toast')
.then((mod) => {
// #region agent log
fetch('http://127.0.0.1:7242/ingest/09c5ea5e-2380-4cc3-92aa-d26f3b3d26f6',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'main.tsx:preloadToast',message:'react-hot-toast loaded successfully',data:{hasDefault:!!mod.default,hasToaster:!!mod.Toaster},timestamp:Date.now(),sessionId:'debug-session',runId:'runtime',hypothesisId:'D'})}).catch(()=>{});
// #endregion
return mod;
})
.catch((err) => {
// #region agent log
fetch('http://127.0.0.1:7242/ingest/09c5ea5e-2380-4cc3-92aa-d26f3b3d26f6',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'main.tsx:preloadToast',message:'react-hot-toast load error',data:{error:err.message,stack:err.stack},timestamp:Date.now(),sessionId:'debug-session',runId:'runtime',hypothesisId:'D'})}).catch(()=>{});
// #endregion
// Ignorer les erreurs de préchargement
});
// Start MSW and preload toast before rendering the app
Promise.all([enableMocking(), preloadToast])
.catch((error) => {
console.error('[Init] Failed to initialize; continuing', error);
})
.finally(() => {
renderApp();
});