Files
kongruity/backend/app.ts
2026-08-02 06:13:01 -04:00

36 lines
1.4 KiB
TypeScript

import express, { type NextFunction, type Request, type Response } from 'express';
import cors from 'cors';
import notesRouter from './routes/notes.routes.js';
import ingestRouter from './routes/ingest.routes.js';
import webhooksRouter from './routes/webhooks.routes.js';
import slackRouter from './routes/slack.routes.js';
const app = express();
app.use(cors());
// Order matters: the raw parser must claim webhook bodies before express.json
// consumes them, because signature verification needs the exact bytes sent.
// Moving this below express.json silently breaks every signature check.
app.use('/v1/webhooks', express.raw({ type: '*/*', limit: '2mb' }), webhooksRouter);
// Slash commands are form-encoded and signed over the same raw bytes, so this
// router sits above express.json for the reason described above.
app.use('/v1/slack', express.raw({ type: '*/*', limit: '2mb' }), slackRouter);
app.use(express.json({ limit: '2mb' }));
app.use('/v1/notes', ingestRouter);
app.use('/v1/notes', notesRouter);
app.use((req: Request, res: Response) => {
res.status(404).json({ error: `Requested path is invalid or does not exist: ${req.method} ${req.originalUrl}` });
});
app.use((err: Error, _req: Request, res: Response, _next: NextFunction) => {
console.error(`Unhandled error: ${err.stack ?? err.message}`);
if (res.headersSent) return;
res.status(500).json({ error: 'Internal server error' });
});
export default app;