FactuGES_ERP/apps/server/src/common/presentation/express/express-controller.ts
2025-02-03 14:12:36 +01:00

151 lines
3.6 KiB
TypeScript

import { NextFunction, Request, Response } from "express";
import httpStatus from "http-status";
import { ApiError } from "./api-error";
export abstract class ExpressController {
protected req!: Request;
protected res!: Response;
protected next!: NextFunction;
protected abstract executeImpl(): Promise<void | any>;
protected ok<T>(dto?: T) {
return dto ? this.res.status(httpStatus.OK).json(dto) : this.res.status(httpStatus.OK).send();
}
protected created<T>(dto?: T) {
return dto
? this.res.status(httpStatus.CREATED).json(dto)
: this.res.status(httpStatus.CREATED).send();
}
protected noContent() {
return this.res.status(httpStatus.NO_CONTENT).send();
}
protected errorResponse(apiError: ApiError) {
return this.res.status(apiError.status).json(apiError);
}
/**
* 🔹 Respuesta para errores de cliente (400 Bad Request)
*/
protected clientError(message: string, errors?: any[]) {
return this.errorResponse(
new ApiError({
status: 400,
title: "Bad Request",
detail: message,
errors,
})
);
}
/**
* 🔹 Respuesta para errores de autenticación (401 Unauthorized)
*/
protected unauthorizedError(message?: string) {
return this.errorResponse(
new ApiError({
status: 401,
title: "Unauthorized",
detail: message ?? "You are not authorized to access this resource.",
})
);
}
/**
* 🔹 Respuesta para errores de autorización (403 Forbidden)
*/
protected forbiddenError(message?: string) {
return this.errorResponse(
new ApiError({
status: 403,
title: "Forbidden",
detail: message ?? "You do not have permission to perform this action.",
})
);
}
/**
* 🔹 Respuesta para recursos no encontrados (404 Not Found)
*/
protected notFoundError(message: string) {
return this.errorResponse(
new ApiError({
status: 404,
title: "Not Found",
detail: message,
})
);
}
/**
* 🔹 Respuesta para conflictos (409 Conflict)
*/
protected conflictError(message: string, errors?: any[]) {
return this.errorResponse(
new ApiError({
status: 409,
title: "Conflict",
detail: message,
errors,
})
);
}
/**
* 🔹 Respuesta para errores de validación de entrada (422 Unprocessable Entity)
*/
protected invalidInputError(message: string, errors?: any[]) {
return this.errorResponse(
new ApiError({
status: 422,
title: "Invalid Input",
detail: message,
errors,
})
);
}
/**
* Respuesta para errores de servidor no disponible (503 Service Unavailable)
* @param message
* @returns
*/
protected unavailableError(message?: string) {
return this.errorResponse(
new ApiError({
status: 503,
title: "Service Unavailable",
detail: message ?? "The service is currently unavailable. Please try again later.",
})
);
}
/**
* 🔹 Respuesta para errores internos del servidor (500 Internal Server Error)
*/
protected internalServerError(message?: string) {
return this.errorResponse(
new ApiError({
status: 500,
title: "Internal Server Error",
detail: message ?? "An unexpected error occurred. Please try again later.",
})
);
}
public execute(req: Request, res: Response, next: NextFunction): void {
this.req = req;
this.res = res;
this.next = next;
try {
this.executeImpl();
} catch (error) {
this.internalServerError((error as Error).message);
}
}
}