/** * Compila el sitio para los tests end-to-end. * * Existe por un motivo concreto: en Windows, el empaquetador nativo de Vite 8 * (rolldown) revienta con SIGSEGV *al terminar el proceso*, de forma * intermitente —unas dos de cada tres veces en la máquina donde se escribió * esto—. El build en sí se completa: los artefactos quedan escritos y son * correctos; lo que falla es el cierre del proceso. * * `vite build` a secas devuelve entonces un código de error que tumba el * arranque del servidor de Playwright, y con él toda la suite, por algo que no * tiene que ver con el código del proyecto. * * Este envoltorio comprueba lo único que importa —que los artefactos existan y * se hayan escrito en esta ejecución— y avisa por consola cuando ha tenido que * pasar por alto ese cierre sucio. Un build que falla de verdad no deja * artefactos nuevos, así que sigue fallando aquí. * * `npm run build` NO usa esto: el despliegue ejecuta `vite build` tal cual, que * es lo que esperan las plataformas y lo que hay que arreglar si el fallo se * reproduce en otro sitio. */ import { spawnSync } from 'node:child_process'; import { readdirSync, statSync } from 'node:fs'; import { resolve } from 'node:path'; /** * Archivos que adapter-node deja siempre en un build correcto. * * No está `build/server/index.js`: el adaptador no genera ese archivo. El * servidor sale troceado en `build/server/chunks/`, y quien lo arranca es * `build/index.js`. Comprobarlo costó un rato de creer que el build fallaba * cuando lo que fallaba era esta lista. */ const ARTEFACTOS = ['build/index.js', 'build/handler.js']; /** Directorios que tienen que haber quedado con algo dentro. */ const DIRECTORIOS = ['build/client', 'build/server/chunks', '.svelte-kit/output/client/_app']; const inicio = Date.now(); const resultado = spawnSync('npx', ['vite', 'build'], { stdio: 'inherit', shell: process.platform === 'win32' }); if (resultado.status === 0) process.exit(0); const faltan = []; for (const directorio of DIRECTORIOS) { try { if (readdirSync(resolve(directorio)).length === 0) { faltan.push(`${directorio} (vacío)`); } } catch { faltan.push(`${directorio} (no existe)`); } } for (const artefacto of ARTEFACTOS) { try { const info = statSync(resolve(artefacto)); // Un artefacto viejo es de un build anterior: no cuenta. if (info.mtimeMs < inicio) faltan.push(`${artefacto} (no se ha regenerado)`); } catch { faltan.push(`${artefacto} (no existe)`); } } if (faltan.length > 0) { console.error('\nEl build ha fallado de verdad. Falta:'); for (const f of faltan) console.error(` - ${f}`); process.exit(resultado.status ?? 1); } console.warn( `\n[construir] El empaquetador ha salido con código ${resultado.status} (${resultado.signal ?? 'sin señal'}),` + '\n[construir] pero los artefactos están completos y recién escritos. Es el cierre' + '\n[construir] sucio conocido de rolldown en Windows; se continúa.\n' ); process.exit(0);