import type { Request, Response } from "express"; interface PRASResponse extends Response { pras: { ok: (message: string, data: any, code: string, extra: any) => void; created: (message: string, data: any, code: string, extra: any) => void; badRequest: (message: string, data: any, code: string, extra: any) => void; unauthorized: ( message: string, data: any, code: string, extra: any ) => void; forbidden: (message: string, data: any, code: string, extra: any) => void; notFound: (message: string, data: any, code: string, extra: any) => void; serverError: (message: string, data: any, code: string, extra: any) => void; customMessage: ( statusCode: number, message: string, data: any, code: string, extra: any ) => void; }; } export class PRAS { private getPRASResultObject( statusCode = 200, status = "OK", message = "", data: any = null, code = "UNKNOWN_CODE", extra: any = null ): any { return { statusCode, status, message, data, code, extra, }; } public responseMiddleware() { // eslint-disable-next-line @typescript-eslint/ban-types return (req: Request, res: PRASResponse, next: Function): void => { res.pras = { ok: (message, data, code, extra) => { res.json( this.getPRASResultObject(200, "OK", message, data, code, extra) ); }, created: (message, data, code, extra) => { res.json( this.getPRASResultObject(201, "OK", message, data, code, extra) ); }, badRequest: (message, data, code, extra) => { res.json( this.getPRASResultObject(400, "FAIL", message, data, code, extra) ); }, unauthorized: (message, data, code, extra) => { res.json( this.getPRASResultObject(401, "FAIL", message, data, code, extra) ); }, forbidden: (message, data, code, extra) => { res.json( this.getPRASResultObject(403, "FAIL", message, data, code, extra) ); }, notFound: (message, data, code, extra) => { res.json( this.getPRASResultObject(404, "FAIL", message, data, code, extra) ); }, serverError: (message, data, code, extra) => { res.json( this.getPRASResultObject(500, "ERROR", message, data, code, extra) ); }, customMessage: (statusCode, message, data, code, extra) => { let status; if (statusCode >= 500) { status = "ERROR"; } else if (statusCode >= 400) { status = "FAIL"; } else { status = "OK"; } res.json( this.getPRASResultObject( statusCode, status, message, data, code, extra ) ); }, }; if ( req.rawHeaders.hasOwnProperty("Accept") && /application\/json/.test(req.rawHeaders["Accept"]) ) { const send = res.send; res.send = (body) => { try { if (typeof body === "string") { body = JSON.parse(body); } if (typeof body === "string") { body = { data: body }; } else if (!body.hasOwnProperty("data")) { body = { data: body }; } const prasBody = this.getPRASResultObject( body.statusCode, body.status, body.message, body.data, body.code, body.extra ); res.status(prasBody.statusCode || 200); delete prasBody.statusCode; return send.call(res, JSON.stringify(prasBody)); } catch (err) { return send.call(res, body); } }; } next(); }; } } export default new PRAS();