import { fileURLToPath } from 'node:url'; import vue from '@vitejs/plugin-vue'; import tailwind from '@tailwindcss/vite'; import { createServer } from 'vite'; // Isolated Inertia transport fixture; real Fortify sessions are covered by PHPUnit. const server = await createServer({ configFile: false, cacheDir: 'node_modules/.vite/auth-fixture', plugins: [vue(), tailwind()], resolve: { alias: { '@': fileURLToPath(new URL('../../resources/js', import.meta.url)), }, }, server: { host: '127.0.0.1', port: 4177, strictPort: true, hmr: false }, appType: 'custom', }); server.middlewares.use(async (request, response, next) => { const url = new URL(request.url, 'http://localhost'); const pages = { '/login': 'Login', '/two-factor-challenge': 'TwoFactorChallenge', '/email/verify': 'VerifyEmail', '/email/verification-notification': 'VerifyEmail', '/dashboard': 'Destination', '/logout': 'Login', '/forgot-password': 'Destination', '/': 'Destination', }; if (!(url.pathname in pages)) { return next(); } const mutation = request.method === 'POST'; const result = request.headers.cookie?.match(/auth_test_result=(\w+)/)?.[1] ?? 'success'; if (mutation && ['server', 'expired', 'limited'].includes(result)) { response.statusCode = { server: 503, expired: 419, limited: 429 }[ result ]; response.setHeader('Content-Type', 'text/html'); response.end('

Simulated failed response

'); return; } let body = ''; if (mutation) { for await (const chunk of request) { body += chunk; } } const submitted = body ? JSON.parse(body) : {}; let path = url.pathname; let errors = {}; let status; if (mutation && result === 'validation') { path = new URL(request.headers.referer).pathname; const field = path === '/login' ? 'email' : 'recovery_code' in submitted ? 'recovery_code' : 'code'; errors = { [field]: 'These details could not be verified.' }; } else if (mutation) { if (path === '/email/verification-notification') { path = '/email/verify'; status = 'verification-link-sent'; } else if (path === '/logout') { path = '/login'; } else { path = result === 'challenge' ? '/two-factor-challenge' : '/dashboard'; } } const page = { component: pages[path], url: path, version: null, clearHistory: false, encryptHistory: false, props: { name: 'KanbanGit', errors, status, canResetPassword: !url.searchParams.has('no-reset'), auth: { user: path === '/email/verify' ? { id: 1, name: 'Alex Morgan', email: 'alex.morgan@example.test', } : null, }, }, }; response.setHeader('Vary', 'X-Inertia'); if (request.headers['x-inertia']) { response.setHeader('X-Inertia', 'true'); response.setHeader('Content-Type', 'application/json'); response.end(JSON.stringify(page)); return; } const escaped = JSON.stringify(page) .replaceAll('&', '&') .replaceAll('"', '"') .replaceAll('<', '<'); const html = '
'; response.setHeader('Content-Type', 'text/html'); response.end(await server.transformIndexHtml(request.url, html)); }); await server.listen(); console.log('Auth fixture ready at http://127.0.0.1:4177/login');