import express from "express"; import cors from "cors"; import bodyParser from "body-parser"; import morgan from "morgan"; import mainRouter from "@app/routes/main"; import userRouter from "@app/routes/users"; import authRouter from "@app/routes/auth"; import moodRouter from "@app/routes/moods"; import triggerRouter from "@app/routes/triggers"; import sleepRecordRouter from "@app/routes/sleepRecords"; import insightRouter from "@app/routes/insights"; import { errorHandler } from "@app/middleware/errorHandler"; import { PrismaClient } from "@prisma/client"; import { bootWorkers, closeAllWorkers, closeAllQueues, scheduleInsights, } from "@app/lib/queue"; import pino from "pino"; import pinoHttp from "pino-http"; import path from "path"; export function createApp() { const app = express(); bootWorkers(); scheduleInsights(); // Configure CORS app.use(cors({ origin: process.env.FRONTEND_URL || '*', credentials: true })); app.use(bodyParser.json()); const isDev = process.env.NODE_ENV !== 'production'; const logger = pino({ level: process.env.LOG_LEVEL || 'info', ...(isDev && { transport: { target: 'pino-pretty', options: { colorize: true, singleLine: false, messageFormat: '{if levelLabel}{levelLabel} - {end}{msg}', }, }, }), }); // Use pino-http for HTTP logging (better than Morgan for structured logs) app.use(pinoHttp({ logger })); app.use("/users", userRouter); app.use("/auth", authRouter); app.use("/moods", moodRouter); app.use("/sleep_records", sleepRecordRouter); app.use("/triggers", triggerRouter); app.use(errorHandler); // always last // TODO: flesh the actual page here app.use(express.static(path.join(__dirname, './static'))); app.get(/.*/, (req, res) => { res.sendFile(path.join(__dirname, './static/index.html')); }); process.on('SIGTERM', shutdown); process.on('SIGINT', shutdown); return app; } const shutdown = async () => { await Promise.all([closeAllWorkers(), closeAllQueues()]); process.exit(0); };