UNPKG

@vizzly-testing/cli

Version:

Visual review platform for UI developers and designers

119 lines (112 loc) 3.6 kB
/** * Dashboard Router * Serves the React SPA for all dashboard routes */ import { existsSync, readFileSync } from 'node:fs'; import { join } from 'node:path'; import * as output from '../../utils/output.js'; import { sendHtml, sendSuccess } from '../middleware/response.js'; // SPA routes that should serve the dashboard HTML const SPA_ROUTES = ['/', '/stats', '/settings', '/projects', '/builds']; /** * Create dashboard router * @param {Object} context - Router context * @param {string} context.workingDir - Working directory for report data * @returns {Function} Route handler */ export function createDashboardRouter(context) { const { workingDir = process.cwd() } = context || {}; /** * Read baseline metadata from baselines/metadata.json */ const readBaselineMetadata = () => { const metadataPath = join(workingDir, '.vizzly', 'baselines', 'metadata.json'); if (!existsSync(metadataPath)) { return null; } try { return JSON.parse(readFileSync(metadataPath, 'utf8')); } catch { return null; } }; return async function handleDashboardRoute(req, res, pathname) { if (req.method !== 'GET') { return false; } // API endpoint for fetching report data if (pathname === '/api/report-data') { const reportDataPath = join(workingDir, '.vizzly', 'report-data.json'); if (existsSync(reportDataPath)) { try { const data = JSON.parse(readFileSync(reportDataPath, 'utf8')); // Include baseline metadata for stats view data.baseline = readBaselineMetadata(); res.setHeader('Content-Type', 'application/json'); res.statusCode = 200; res.end(JSON.stringify(data)); return true; } catch (error) { output.debug('Error reading report data:', { error: error.message }); res.statusCode = 500; res.end(JSON.stringify({ error: 'Failed to read report data' })); return true; } } else { sendSuccess(res, null); return true; } } // Serve React SPA for dashboard routes if (SPA_ROUTES.includes(pathname) || pathname.startsWith('/comparison/')) { const reportDataPath = join(workingDir, '.vizzly', 'report-data.json'); let reportData = null; if (existsSync(reportDataPath)) { try { const data = readFileSync(reportDataPath, 'utf8'); reportData = JSON.parse(data); // Include baseline metadata for stats view reportData.baseline = readBaselineMetadata(); } catch (error) { output.debug('Could not read report data:', { error: error.message }); } } const dashboardHtml = ` <!DOCTYPE html> <html> <head> <title>Vizzly Dev Dashboard</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/reporter-bundle.css"> </head> <body> <div id="vizzly-reporter-root"> <div class="reporter-loading"> <div> <div class="spinner"></div> <p>Loading Vizzly Dev Dashboard...</p> </div> </div> </div> <script> // Inject report data if available ${reportData ? `window.VIZZLY_REPORTER_DATA = ${JSON.stringify(reportData)};` : ''} </script> <script src="/reporter-bundle.js"></script> </body> </html>`; sendHtml(res, 200, dashboardHtml); return true; } return false; }; }