import { logger } from './logger'; /** * toast - Wrapper lazy pour react-hot-toast * * CRITICAL FIX: Charge react-hot-toast de manière lazy pour éviter * les collisions de noms de variables (ie) lors de la minification. * * Le problème: react-hot-toast utilise une variable 'ie' qui entre * en conflit avec d'autres variables minifiées dans le même chunk. * Solution: Chargement dynamique pour isoler le module. * * Le module est préchargé dans main.tsx AVANT le rendu de l'app, * donc il sera toujours disponible quand ce wrapper est utilisé. * * Usage: * import toast from '@/utils/toast'; * toast.success('Message'); * toast.error('Error'); */ // Import dynamique - cela force Vite à créer un chunk séparé // Le module est préchargé dans main.tsx, donc il sera déjà chargé // quand ce fichier est évalué const toastModulePromise = import('react-hot-toast'); // Cache pour le module une fois chargé let toastModule: typeof import('react-hot-toast') | null = null; let isResolved = false; // Charger le module et le mettre en cache immédiatement toastModulePromise.then((mod) => { toastModule = mod; isResolved = true; }).catch(() => { isResolved = true; // Ignorer les erreurs de chargement }); /** * Récupère le module toast de manière synchrone * Le module devrait être déjà chargé grâce au préchargement dans main.tsx */ function getToastModuleSync() { // Attendre que le module soit chargé (bloquant mais très rapide) // En pratique, le module sera déjà chargé car il est préchargé dans main.tsx if (!toastModule && isResolved) { // Le module a échoué à charger, retourner un stub logger.error('Toast module failed to load'); return { success: () => { }, error: () => { }, loading: () => { }, custom: () => { }, dismiss: () => { }, remove: () => { }, promise: () => Promise.resolve(), } as any; } if (toastModule) { return toastModule.default; } // Si le module n'est pas encore chargé, retourner un stub temporaire // qui sera remplacé une fois le module chargé return { success: (...args: any[]) => { toastModulePromise.then((mod) => (mod.default.success as any)(...args)); }, error: (...args: any[]) => { toastModulePromise.then((mod) => (mod.default.error as any)(...args)); }, loading: (...args: any[]) => { toastModulePromise.then((mod) => (mod.default.loading as any)(...args)); }, custom: (...args: any[]) => { toastModulePromise.then((mod) => (mod.default.custom as any)(...args)); }, dismiss: (...args: any[]) => { toastModulePromise.then((mod) => (mod.default.dismiss as any)(...args)); }, remove: (...args: any[]) => { toastModulePromise.then((mod) => (mod.default.remove as any)(...args)); }, promise: (...args: any[]) => { return toastModulePromise.then((mod) => (mod.default.promise as any)(...args)); }, } as any; } // Créer un proxy qui délègue toutes les méthodes à react-hot-toast const toast = new Proxy({} as typeof import('react-hot-toast').default, { get(_target, prop) { const toastFn = getToastModuleSync() as any; if (prop in toastFn) { const method = toastFn[prop]; if (typeof method === 'function') { return method.bind(toastFn); } return method; } return undefined; }, apply(_target, _thisArg, args) { const toastFn = getToastModuleSync(); if (typeof toastFn === 'function') { return toastFn(...args); } // Si ce n'est pas une fonction, essayer d'appeler via le module return toastModulePromise.then((mod) => (mod.default as any)(...args)); }, }) as typeof import('react-hot-toast').default; export default toast;