package.json type=module, tsconfig module/moduleResolution=NodeNext, target es2022, explicit .js on all relative imports. Center: jsonwebtoken & bcryptjs switched to default imports (ESM/CJS interop). Verified: builds, boots, full auth + plugin round-trip work under ESM. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
37 lines
1.1 KiB
TypeScript
37 lines
1.1 KiB
TypeScript
import { randomUUID } from 'crypto';
|
|
import { NextFunction, Request, Response } from 'express';
|
|
import { MetricsService } from './metrics.service.js';
|
|
|
|
type ReqWithId = Request & { requestId?: string };
|
|
|
|
export function createRequestContextMiddleware(service: 'center' | 'guild', metrics: MetricsService) {
|
|
return (req: ReqWithId, res: Response, next: NextFunction): void => {
|
|
const headerId = req.headers['x-request-id'];
|
|
const requestId =
|
|
(Array.isArray(headerId) ? headerId[0] : headerId) || randomUUID();
|
|
|
|
req.requestId = requestId;
|
|
res.setHeader('x-request-id', requestId);
|
|
|
|
const startedAt = Date.now();
|
|
res.on('finish', () => {
|
|
const durationMs = Date.now() - startedAt;
|
|
metrics.record(res.statusCode, durationMs);
|
|
|
|
const log = {
|
|
level: 'info',
|
|
service,
|
|
requestId,
|
|
method: req.method,
|
|
path: req.originalUrl,
|
|
statusCode: res.statusCode,
|
|
durationMs,
|
|
timestamp: new Date().toISOString(),
|
|
};
|
|
console.log(JSON.stringify(log));
|
|
});
|
|
|
|
next();
|
|
};
|
|
}
|