import { NextFunction, Request, Response } from "express"; type StandardResponse = { code: number | string; msg: string; data: unknown; }; function isStandardResponse(value: unknown): value is StandardResponse { if (value === null || typeof value !== "object") return false; return "code" in value && "msg" in value && "data" in value; } function extractSuccessData(body: unknown): unknown { if (body === null || typeof body !== "object") return body; const record = body as Record; const keys = Object.keys(record); if (keys.length === 1 && keys[0] === "data") return record.data; return body; } function buildErrorResponse(statusCode: number, body: unknown): StandardResponse { let code: number | string = statusCode; let msg = "Request failed"; let data: unknown = null; if (body && typeof body === "object") { const record = body as Record; const error = record.error && typeof record.error === "object" ? (record.error as Record) : null; const rawCode = record.code ?? error?.code; if (typeof rawCode === "string" || typeof rawCode === "number") code = rawCode; const rawMsg = record.msg ?? record.message ?? error?.message; if (typeof rawMsg === "string" && rawMsg.trim().length > 0) msg = rawMsg; if ("data" in record) data = record.data; else if ("details" in record) data = record.details; else if (error && "details" in error) data = error.details; } return { code, msg, data }; } export function responseMiddleware(_req: Request, res: Response, next: NextFunction): void { const originalJson = res.json.bind(res); const originalSend = res.send.bind(res); res.json = ((body: unknown) => { if (isStandardResponse(body)) return originalJson(body); if (res.statusCode >= 400) { return originalJson(buildErrorResponse(res.statusCode, body)); } const wrapped: StandardResponse = { code: 0, msg: "success", data: extractSuccessData(body) }; return originalJson(wrapped); }) as Response["json"]; res.send = ((body?: unknown) => { if (body && typeof body === "object") return res.json(body); return originalSend(body as never); }) as Response["send"]; next(); }