import 'express-async-errors'; import express from 'express'; import cors from 'cors'; import dotenv from 'dotenv'; import pinoHttp from 'pino-http'; import authRoutes from './routes/auth'; import ticketRoutes from './routes/tickets'; import ctiRoutes from './routes/cti'; import userRoutes from './routes/users'; import attachmentRoutes from './routes/attachments'; import searchRoutes from './routes/search'; import analyticsRoutes from './routes/analytics'; import exportRoutes from './routes/export'; import savedViewRoutes from './routes/savedViews'; import notificationRoutes from './routes/notifications'; import webhookRoutes from './routes/webhooks'; import { authenticate } from './middleware/auth'; import { errorHandler } from './middleware/errorHandler'; import { startAutoCloseJob } from './jobs/autoClose'; import { logger } from './lib/logger'; dotenv.config(); if (!process.env.JWT_SECRET) { logger.fatal('JWT_SECRET is not set'); process.exit(1); } const app = express(); app.use(pinoHttp({ logger })); app.use(cors({ origin: process.env.CLIENT_URL || 'http://localhost:5173' })); app.use(express.json()); app.get('/healthz', (_req, res) => { res.json({ status: 'ok' }); }); // Public app.use('/api/auth', authRoutes); // Protected app.use('/api/tickets', authenticate, ticketRoutes); app.use('/api/cti', authenticate, ctiRoutes); app.use('/api/users', authenticate, userRoutes); app.use('/api', attachmentRoutes); // self-mounts authenticate inside app.use('/api/search', authenticate, searchRoutes); app.use('/api/analytics', authenticate, analyticsRoutes); app.use('/api/export', authenticate, exportRoutes); app.use('/api/saved-views', authenticate, savedViewRoutes); app.use('/api/notifications', authenticate, notificationRoutes); app.use('/api/webhooks', authenticate, webhookRoutes); app.use(errorHandler); startAutoCloseJob(); const PORT = Number(process.env.PORT) || 3000; app.listen(PORT, () => { logger.info({ port: PORT }, 'Server started'); });