require("dotenv").config(); const express = require("express"); const http = require("http"); const morgan = require("morgan"); const bodyParser = require("body-parser"); const cookieParser = require("cookie-parser"); const fileUpload = require("express-fileupload"); const helmet = require("helmet"); const cors = require("cors"); const flightStore = require("./src/stores/flightStore"); const flighData = require("./src/modules/data.js"); const app = express(); const { init } = require("./src/modules/socket.js"); const { initFlightSockets } = require("./src/controllers/flights"); const RELEASE = require("./package.json").version; const NODE_ENV = process.env.NODE_ENV || "production"; const NODE_PORT = process.env.NODE_PORT || 3001; app.set("port", NODE_PORT); app.set("env", NODE_ENV); app.set("ver", RELEASE); function logRequests(req, res, next) { console.log(`Incoming Request: ${req.method} ${req.url}`); console.log(`Origin: ${req.headers.origin}`); next(); } app.use(logRequests); const allowedOrigins = ["https://aeroecho.onrender.com"]; if (NODE_ENV === "development" || NODE_ENV === "staging") { allowedOrigins.push("http://localhost:3000"); } //test const corsOptions = { origin: function (origin, callback) { if (!origin || allowedOrigins.indexOf(origin) !== -1) { callback(null, true); } else { callback(new Error("Not allowed by CORS")); } }, allowedHeaders: [ "Accept-Version", "Authorization", "Credentials", "Content-Type", "baggage", ], credentials: true, methods: "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS", optionsSuccessStatus: 204, }; app.use( helmet({ contentSecurityPolicy: { directives: { "default-src": ["'self'"], "connect-src": ["'self'", "ws:", "wss:", ...allowedOrigins], "script-src": ["'self'", "'unsafe-inline'"], }, }, }) ); app.disable("x-powered-by"); app.use(cors(corsOptions)); app.use(bodyParser.json({ limit: "200mb" })); app.use(bodyParser.urlencoded({ extended: true, limit: "200mb" })); app.use( fileUpload({ limits: { fileSize: 200 * 1024 * 1024 }, // 200MB }) ); app.use(cookieParser()); //Socket io const server = http.createServer(app); const io = init(server, { cors: { origin: allowedOrigins }, }); initFlightSockets(io); app.options(/.*/, cors(corsOptions)); app.set("trust proxy", true); app.use( morgan( ":remote-addr - :remote-user - [:date[clf]] ':method :url HTTP/:http-version' :status :res[content-length] ':referrer' ':user-agent'", { stream: { write: (message, encoding) => { console.log(message.substring(0, message.lastIndexOf("\n"))); }, }, } ) ); setInterval(flighData.getAllFlights, 2000); const routesBasePath = require("./src/routes"); app.use("/api/v1", routesBasePath); app.use((err, req, res, next) => { console.error(err.stack); // Log the error for debugging const statusCode = err.statusCode || 500; const message = err.message || "Something went wrong!"; res.status(statusCode).json({ status: "error", message: message, path: req.path, }); }); app.use((err, req, res, next) => { console.error("Error Details:", { message: err.message, stack: err.stack, url: req.url, method: req.method, ip: req.ip, timestamp: new Date().toISOString(), }); const statusCode = err.statusCode || err.status || 500; const message = process.env.NODE_ENV === "production" ? "Internal Server Error" : err.message; res.status(statusCode).json({ error: message, timestamp: new Date().toISOString(), ...(process.env.NODE_ENV !== "production" && { stack: err.stack, details: err, }), }); }); // Set listening port server.listen(NODE_PORT, "localhost", async () => { console.log( `Express Server with Socket.io started on Port: ${app.get( "port" )} | Environment: ${app.get("env")} | Release: ${app.get("ver")}` ); });