const express = require('express'); const cors = require('cors'); const helmet = require('helmet'); const path = require('path'); const fs = require('fs'); const { initDatabase } = require('./db/init'); const app = express(); const PORT = process.env.PORT || 3000; // Ensure required directories exist const UPLOAD_PATH = process.env.UPLOAD_PATH || path.join(__dirname, '../uploads'); const STATIC_PATH = process.env.STATIC_PATH || path.join(__dirname, '../static'); const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, '../data'); [DATA_DIR, UPLOAD_PATH, STATIC_PATH].forEach(dir => { if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); }); // Init DB (path is managed internally by db/init.js) console.log('Initializing database...'); initDatabase(); console.log('✓ Database ready!\n'); // ── Middleware ────────────────────────────────────────────────────────── app.use(helmet({ contentSecurityPolicy: false })); app.use(cors()); app.use(express.json()); app.use(express.urlencoded({ extended: true })); // ── Static file serving ───────────────────────────────────────────── app.use('/uploads', express.static(UPLOAD_PATH)); app.use('/static', express.static(STATIC_PATH)); app.use('/uploads', (_req, res) => res.status(404).json({ error: 'Upload not found' })); app.use('/static', (_req, res) => res.status(404).json({ error: 'Static asset not found' })); // ── API Routes ──────────────────────────────────────────────────────── app.use('/api/dogs', require('./routes/dogs')); app.use('/api/litters', require('./routes/litters')); app.use('/api/health', require('./routes/health')); app.use('/api/genetics', require('./routes/genetics')); app.use('/api/pedigree', require('./routes/pedigree')); app.use('/api/breeding', require('./routes/breeding')); app.use('/api/settings', require('./routes/settings')); // ── Production SPA fallback ─────────────────────────────────────────── if (process.env.NODE_ENV === 'production') { const clientBuild = path.join(__dirname, '../client/dist'); app.use(express.static(clientBuild)); app.get(/^(?!\/(?:api|static|uploads)\/).+$/, (_req, res) => { res.sendFile(path.join(clientBuild, 'index.html')); }); } // ── Global error handler ────────────────────────────────────────────── app.use((err, _req, res, _next) => { console.error('Error:', err); res.status(err.status || 500).json({ error: err.message || 'Internal server error', ...(process.env.NODE_ENV === 'development' && { stack: err.stack }) }); }); app.listen(PORT, '0.0.0.0', () => { console.log(`\n🐕 BREEDR Server Running`); console.log(`=============================================`); console.log(`Environment : ${process.env.NODE_ENV || 'development'}`); console.log(`Port : ${PORT}`); console.log(`Data dir : ${DATA_DIR}`); console.log(`Uploads : ${UPLOAD_PATH}`); console.log(`Static : ${STATIC_PATH}`); console.log(`Access : http://localhost:${PORT}`); console.log(`=============================================\n`); }); module.exports = app;