import express from 'express'; import cors from 'cors'; import { env } from './config/env'; import { connectDatabase, disconnectDatabase } from './db/prisma'; import { logger } from './utils/logger'; import { requestLogger } from './middlewares/request-logger'; import { notFoundHandler } from './middlewares/not-found'; import { errorHandler } from './middlewares/error-handler'; import { apiRouter } from './routes'; const app = express(); // En développement, on accepte toute origine locale (le front Flutter tourne sur // un port variable) ; en production, seule l'origine du frontend est autorisée. app.use(cors({ origin: env.nodeEnv === 'development' ? true : env.frontendUrl })); app.use(express.json()); app.use(requestLogger); app.get('/health', (_req, res) => { res.json({ status: 'ok', app: 'EME API' }); }); app.use('/api', apiRouter); /* notFoundHandler et errorHandler doivent rester après toutes les routes : le premier capture les URL non gérées, le second clôt la chaîne Express. */ app.use(notFoundHandler); app.use(errorHandler); async function bootstrap(): Promise { await connectDatabase(); const server = app.listen(env.port, () => { logger.info(`Serveur demarre sur http://localhost:${env.port}`); }); const shutdown = async (signal: string): Promise => { logger.info(`Arret en cours (${signal})`); await disconnectDatabase(); server.close(() => process.exit(0)); }; // SIGTERM est le signal envoyé par Docker à l'arrêt du container. process.on('SIGINT', () => void shutdown('SIGINT')); process.on('SIGTERM', () => void shutdown('SIGTERM')); } bootstrap().catch((error: unknown) => { logger.error('Echec du demarrage', error); process.exit(1); });