Repository navigation
Expand file tree
/
Copy pathapp.ts
More file actions
133 lines (117 loc) · 5.35 KB
/
Copy pathapp.ts
File metadata and controls
133 lines (117 loc) · 5.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// src/app.ts
import express, { Express, Response, RequestHandler } from 'express';
import { TspecDocsMiddleware } from 'tspec';
import { errorHandler, notFoundHandler } from './middlewares/error.middleware'; // Add notFoundHandler import
import router from './modules/index';
import stakingRouter from './modules/staking/staking.routes';
import statusRouter from './modules/status/status.routes';
import tradesRouter from './modules/trades/trades.routes';
import tradersRouter from './modules/traders/traders.routes';
import nonceRouter from './modules/nonce/nonce.routes';
import swapsRouter from './modules/swaps/swaps.routes';
import keysRouter from './modules/keys/keys.routes';
import internalRouter from './modules/admin/sequencer.routes';
import eventsRouter from './modules/events/events.routes';
import { corsMiddleware } from './middlewares/cors.middleware';
import helmet from 'helmet';
import morgan from 'morgan';
import tspecOptions from './tspec.config';
import { SendMail } from './utils/mail.utils';
import { appRateLimit } from './middlewares/rate.middleware';
import { requestIdMiddleware } from './middlewares/request-id.middleware';
import { responseTimingMiddleware } from './middlewares/response-timing.middleware';
import { apiVersionMiddleware } from './middlewares/api-version.middleware';
import { schemaVersionMiddleware } from './middlewares/schema-version.middleware';
import { requestLoggerMiddleware } from './middlewares/request-logger.middleware';
import { requestContextMiddleware } from './middlewares/request-context.middleware';
import { requestEntryLoggerMiddleware } from './middlewares/request-entry-logger.middleware';
import { requestCompletionLoggerMiddleware } from './middlewares/request-completion-logger.middleware';
import { sessionActivityMiddleware } from './middlewares/session-activity.middleware';
import { bodyParseErrorMiddleware } from './middlewares/body-parse-error.middleware';
import { routeBodySizeLimit } from './middlewares/body-size-limit.middleware';
import { envConfig } from './config';
import { logger } from './utils/logger.utils';
const app: Express = express();
// Middleware setup
app.set('trust proxy', 1);
app.use(responseTimingMiddleware);
// requestIdMiddleware must run before requestContextMiddleware: it assigns
// req.traceId/req.requestId, which requestContextMiddleware then captures
// into AsyncLocalStorage for the rest of the request's call stack.
app.use(requestIdMiddleware);
app.use(requestContextMiddleware);
app.use(apiVersionMiddleware);
app.use(schemaVersionMiddleware);
app.use(requestEntryLoggerMiddleware);
app.use(requestCompletionLoggerMiddleware);
// Session activity logging (#1035): registers a res.on('finish') listener
// so it can read req.user after route-level auth guards have run. Mount
// position only needs to be before the routers.
app.use(sessionActivityMiddleware);
app.use(corsMiddleware());
app.use(helmet());
// Request body parsing is applied per route group (see modules/index.ts)
// via routeBodySizeLimit, so each group can have its own configured size
// limit instead of one global express.json() call. bodyParseErrorMiddleware
// is mounted after the router (below) since that's where those parsers
// actually live now — Express only walks forward to later error handlers,
// so it has to come after the point where the parse error can occur.
if (!envConfig.ENABLE_REQUEST_LOGGING) {
app.use(morgan('combined'));
}
app.use(requestLoggerMiddleware);
app.use(express.urlencoded({ extended: true }));
app.use(appRateLimit);
// Health check endpoints are now in /api/v1/health
async function setupTspecDocs() {
try {
const tspecMiddlewares = await TspecDocsMiddleware(tspecOptions);
app.use(
'/api-docs',
...(tspecMiddlewares as unknown as RequestHandler[])
);
} catch (error) {
logger.error({ error }, 'Failed to setup API docs');
}
}
setupTspecDocs();
// Quick test endpoint
app.get('/test-email', async (_, res: Response) => {
try {
const result = await SendMail({
to: 'aniokesebastian@gmail.com',
subject: 'Test Email',
html: '<h1>Test</h1><p>If you get this, it works!</p>',
});
res.json({
success: result,
message: result ? 'Check your email' : 'Email failed',
});
} catch (error) {
res.json({ error: error });
}
});
// Redirect root
app.get('/', (_, res: Response) => {
res.redirect('/api-docs');
});
// Routes
app.use('/status', routeBodySizeLimit('default'), statusRouter);
app.use('/nonce', routeBodySizeLimit('default'), nonceRouter);
app.use('/internal', routeBodySizeLimit('default'), internalRouter);
app.use('/api/v1', router);
app.use('/staking', routeBodySizeLimit('default'), stakingRouter);
app.use('/trades', routeBodySizeLimit('default'), tradesRouter);
app.use('/traders', routeBodySizeLimit('default'), tradersRouter);
app.use('/keys', routeBodySizeLimit('default'), keysRouter);
app.use('/swaps', routeBodySizeLimit('default'), swapsRouter);
app.use('/events', routeBodySizeLimit('default'), eventsRouter);
// Catches body-parse errors (including entity.too.large from the per-group
// JSON parsers mounted inside router) — must come after the router since
// that's where those parsers run.
app.use(bodyParseErrorMiddleware);
// 404 handler - MUST come after all routes
app.use(notFoundHandler);
// Error handler - MUST be last
app.use(errorHandler);
export default app;