const express = require("express"); const cors = require("cors"); const path = require("path"); require("dotenv").config(); const app = express(); const PORT = process.env.PORT || 3000; // CORS const allowedOrigins = process.env.ALLOWED_ORIGINS ? process.env.ALLOWED_ORIGINS.split(",") : null; app.use( cors({ origin: function (origin, callback) { if (!allowedOrigins || allowedOrigins.includes("*") || !origin) { return callback(null, true); } if (allowedOrigins.includes(origin)) { return callback(null, true); } return callback(null, true); }, methods: ["GET", "OPTIONS"], allowedHeaders: ["Content-Type"], }) ); // Security headers app.use((req, res, next) => { res.setHeader("access-control-allow-origin", "*"); res.setHeader("X-Content-Type-Options", "nosniff"); res.setHeader("X-Frame-Options", "DENY"); res.setHeader("X-XSS-Protection", "1; mode=block"); next(); }); // Static files app.use(express.static(path.join(__dirname, "public"))); // Health app.get("/api/health", (req, res) => { res.json({ status: "ok", version: "1.0.0", timestamp: new Date().toISOString(), uptime: process.uptime(), }); }); // Routes const apiRoutes = require("./src/routes/apiRoutes"); app.use("/api", apiRoutes); // SPA fallback app.get("*", (req, res) => { if (req.path.startsWith("/api/")) { return res.status(404).json({ success: false, message: "Endpoint not found" }); } res.sendFile(path.join(__dirname, "public", "index.html")); }); // Global error handler app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ success: false, message: "Internal server error" }); }); app.listen(PORT, () => { console.log(`MiruroAPI running on port ${PORT}`); }); module.exports = app;