import express from 'express'; import cors from 'cors'; import path from 'path'; import fs from 'fs'; import { fileURLToPath } from 'url'; import boardRoutes from './routes/boardRoutes.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export function createApp() { const app = express(); // CORS configuration app.use(cors({ origin: (origin, callback) => { callback(null, true); }, credentials: true, })); app.use(express.json()); // Health check endpoint app.get('/health', (_req, res) => { res.json({ status: 'ok', service: 'retro-kanban-server', timestamp: new Date().toISOString(), }); }); // API Routes app.use('/api/boards', boardRoutes); // Serve static frontend assets in production (when client build exists) const clientDistPaths = [ path.join(__dirname, '../public'), path.join(__dirname, '../../client/dist'), path.join(__dirname, '../client/dist'), path.join(process.cwd(), 'client/dist'), path.join(process.cwd(), 'public'), ]; let staticPath = clientDistPaths.find((p) => fs.existsSync(p)); if (staticPath) { console.log(`📁 [Static Assets] Serving frontend from: ${staticPath}`); app.use(express.static(staticPath)); // SPA fallback: any non-API route serves index.html app.get('*', (req, res, next) => { if (req.path.startsWith('/api') || req.path.startsWith('/socket.io')) { return next(); } res.sendFile(path.join(staticPath, 'index.html')); }); } // Global Error Handler app.use((err, _req, res, _next) => { console.error('Unhandled server error:', err); res.status(500).json({ error: 'Internal Server Error', message: process.env.NODE_ENV === 'development' ? err.message : undefined, }); }); return app; }