2026-06-16 01:17:58 -05:00
|
|
|
import 'dotenv/config'
|
|
|
|
|
import express from 'express'
|
|
|
|
|
import helmet from 'helmet'
|
|
|
|
|
import morgan from 'morgan'
|
|
|
|
|
import { initFirebase } from './config/firebase'
|
|
|
|
|
import { startAnswerListener } from './listeners/answerListener'
|
2026-06-16 21:37:57 -05:00
|
|
|
import { validateEnv } from './config/env'
|
2026-06-16 21:56:32 -05:00
|
|
|
import { webhookLimiter, healthLimiter } from './middleware/rateLimiter'
|
2026-06-16 01:17:58 -05:00
|
|
|
import healthRouter from './routes/health'
|
|
|
|
|
import webhooksRouter from './routes/webhooks'
|
|
|
|
|
|
2026-06-16 21:37:57 -05:00
|
|
|
// Validate required env vars before starting
|
|
|
|
|
try {
|
|
|
|
|
validateEnv()
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error('[startup] Env validation failed:')
|
|
|
|
|
console.error(err)
|
|
|
|
|
process.exit(1)
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-16 01:17:58 -05:00
|
|
|
initFirebase()
|
|
|
|
|
|
|
|
|
|
const app = express()
|
|
|
|
|
const PORT = parseInt(process.env.PORT ?? '8080', 10)
|
|
|
|
|
|
2026-06-16 21:53:53 -05:00
|
|
|
// Capture raw body BEFORE express.json() for webhook signature verification
|
|
|
|
|
app.use(express.json({
|
|
|
|
|
verify: (req: express.Request, res: express.Response, body: Buffer) => {
|
|
|
|
|
(req as any).rawBody = body
|
|
|
|
|
},
|
|
|
|
|
}))
|
|
|
|
|
|
2026-06-16 01:17:58 -05:00
|
|
|
app.use(helmet())
|
|
|
|
|
app.use(morgan('combined'))
|
|
|
|
|
|
2026-06-16 21:56:32 -05:00
|
|
|
// Rate limiting middleware (applied before routes)
|
|
|
|
|
app.use('/webhooks', webhookLimiter)
|
|
|
|
|
app.use('/health', healthLimiter)
|
|
|
|
|
|
2026-06-16 01:17:58 -05:00
|
|
|
app.use('/health', healthRouter)
|
|
|
|
|
app.use('/webhooks', webhooksRouter)
|
|
|
|
|
|
|
|
|
|
const server = app.listen(PORT, () => {
|
|
|
|
|
console.log(`[server] listening on port ${PORT}`)
|
|
|
|
|
startAnswerListener()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Graceful shutdown
|
|
|
|
|
process.on('SIGTERM', () => {
|
|
|
|
|
console.log('[server] SIGTERM received, shutting down')
|
|
|
|
|
server.close(() => process.exit(0))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
process.on('SIGINT', () => {
|
|
|
|
|
console.log('[server] SIGINT received, shutting down')
|
|
|
|
|
server.close(() => process.exit(0))
|
|
|
|
|
})
|