import { defineConfig, type Plugin, type ResolvedConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' import { createHash } from 'node:crypto' import { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs' import { resolve } from 'node:path' // PWA: inyecta en dist/sw.js (1) una versión de caché única por build y // (2) la lista de assets con hash a precachear. La versión es un hash del // index.html, el manifest y los nombres de los assets, así que cambia // exactamente cuando cambia el bundle (y el SW descarta las cachés viejas // en `activate`). No toca el pipeline `tsc -b && vite build`. function pwaServiceWorker(): Plugin { let outDir = 'dist' return { name: 'skeen-pwa-service-worker', apply: 'build', configResolved(config: ResolvedConfig) { outDir = config.build.outDir }, closeBundle() { const dir = resolve(process.cwd(), outDir) const swPath = resolve(dir, 'sw.js') if (!existsSync(swPath)) return const listAssets = (sub: string): string[] => { const abs = resolve(dir, sub) if (!existsSync(abs)) return [] return readdirSync(abs) .filter((f) => /\.(js|css|woff2?|png|jpe?g|svg|webp|ico|json)$/i.test(f)) .map((f) => `/${sub}/${f}`) .sort() } // Solo /assets (hash): los iconos ya van listados explícitamente en sw.js. const assets = listAssets('assets') const read = (file: string): Buffer => existsSync(resolve(dir, file)) ? readFileSync(resolve(dir, file)) : Buffer.from('') const version = createHash('sha256') .update(read('index.html')) .update(read('manifest.webmanifest')) .update(assets.join('|')) .digest('hex') .slice(0, 12) let sw = readFileSync(swPath, 'utf8') sw = sw.replace('__BUILD_VERSION__', version) // JSON dentro de un literal de una sola comilla: se quitan comillas // simples por seguridad (los nombres de Vite no las contienen). sw = sw.replace('__PRECACHE_ASSETS__', JSON.stringify(assets).replace(/'/g, '')) writeFileSync(swPath, sw) this.warn(`PWA service worker: versión de caché ${version}, ${assets.length} assets precacheados`) }, } } // https://vitejs.dev/config/ export default defineConfig({ plugins: [react(), tailwindcss(), pwaServiceWorker()], server: { port: 5173, proxy: { '/api/odoo': { target: 'http://localhost:8069', changeOrigin: true, rewrite: (path) => path.replace(/^\/api\/odoo/, ''), }, '/api/wacrm': { target: 'http://localhost:3000', changeOrigin: true, rewrite: (path) => path.replace(/^\/api\/wacrm/, '/api/v1'), }, }, }, build: { outDir: 'dist', sourcemap: false, }, })