const express = require("express"); const cors = require("cors"); require("dotenv").config(); const { log } = require("./lib/log"); const { friendlyErrorMessage } = require("./lib/errors"); const { reportError, reportUnhandled } = require("./lib/report-error"); const { ensureScheduleStopProgressTable } = require("./lib/schema"); const app = express(); app.use(express.json()); app.use(cors()); process.on("uncaughtException", (err) => reportUnhandled("uncaughtException", err)); process.on("unhandledRejection", (reason) => reportUnhandled("unhandledRejection", reason)); app.use((req, res, next) => { const originalJson = res.json.bind(res); res.json = (body) => { if (res.statusCode >= 400 && body && typeof body === "object") { const rawError = [body.error, body.message, body.details] .filter((v) => v !== undefined && v !== null && v !== "") .join(" - ") || `HTTP ${res.statusCode}`; log("warn", `HTTP ${res.statusCode}`, { path: req.originalUrl, method: req.method, error: rawError }); void reportError({ partofservice: `${req.method} ${req.originalUrl}`, error: rawError, }); return originalJson({ error: friendlyErrorMessage(res.statusCode) }); } return originalJson(body); }; next(); }); // Canonical router for all bus endpoints. Mounted twice: under /bus (canonical) // and under / (deprecated legacy alias for old clients such as the Windows XP // driver UI). /health stays on `app` and is never registered on this router. const busRouter = express.Router(); busRouter.use(require("./routes/stops")); busRouter.use(require("./routes/lines")); busRouter.use(require("./routes/fleet")); busRouter.use(require("./routes/drivers")); busRouter.use(require("./routes/navigation")); busRouter.use(require("./routes/gps")); busRouter.use(require("./routes/routes")); busRouter.use(require("./routes/daily")); busRouter.use(require("./routes/weekly")); busRouter.use(require("./routes/adminSchedules")); busRouter.use(require("./routes/schedules")); app.use("/health", require("./routes/health")); // Canonical bus routes. app.use("/bus", busRouter); // Legacy aliases for old clients (Windows XP driver). Deprecated: remove only // after the driver is retired. app.use( "/", (req, res, next) => { res.set("Deprecation", 'true; date="2030-01-01"'); next(); }, busRouter, ); const PORT = process.env.PORT || 5001; // Initialize database tables on startup (async () => { try { await ensureScheduleStopProgressTable(); console.log("✓ Database tables initialized"); } catch (err) { console.error("⚠ Error initializing tables:", err.message); reportError({ partofservice: "startup: table init", error: err.stack || err.message }); } app.listen(PORT, () => console.log(`Transit API listening on ${PORT}`)); })(); module.exports = app;