diff --git a/src/constants/index.ts b/src/constants/index.ts index 3c06f4cf..cd7dfd1d 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -2,11 +2,13 @@ export type HttpErrorCodes = { OK: number; FORBIDDEN: number; BAD_REQUEST: number; + NOT_FOUND: number; UNAUTHORIZED: number; TOO_MANY_REQS: number; SOMETHING_WRONG: number; MOVED_PERMANENTLY: number; SUPPORT_DOC: number; + SERVER_ERROR: number; }; export type ConstantType = { AXIOS_TIMEOUT: number; @@ -36,11 +38,13 @@ export const constants: ConstantType = { OK: 200, FORBIDDEN: 403, BAD_REQUEST: 400, + NOT_FOUND: 404, UNAUTHORIZED: 401, TOO_MANY_REQS: 429, SOMETHING_WRONG: 501, MOVED_PERMANENTLY: 301, SUPPORT_DOC: 294, + SERVER_ERROR: 500, }, HTTP_TEXTS: { INTERNAL_ERROR: "Internal server error, please try again later.", diff --git a/src/controllers/auth.controller.ts b/src/controllers/auth.controller.ts index 8ffebf91..e473514a 100644 --- a/src/controllers/auth.controller.ts +++ b/src/controllers/auth.controller.ts @@ -1,24 +1,25 @@ -import { Request, Response } from "express"; +import { NextFunction, Request, Response } from "express"; import { userService } from "../services/auth.service"; -import { constants } from "../constants"; -const login = async (req: Request, res: Response) => { +const login = async (req: Request, res: Response, next: NextFunction) => { try { const resp = await userService.login(req); res.status(resp?.status).json(resp?.data); } catch (error) { console.error(error); - res - .status(constants.HTTP_CODES.SOMETHING_WRONG) - .json({ message: constants.HTTP_TEXTS.INTERNAL_ERROR }); + next(error); } }; -const getUserProfile = async (req: Request, res: Response) => { +const getUserProfile = async ( + req: Request, + res: Response, + next: NextFunction +) => { try { const user = await userService.getUserProfile(req); res.status(200).json(user); } catch (error) { console.error(error); - res.status(500).json({ message: "Internal Server Error" }); + next(error); } }; diff --git a/src/middlewares/error.middleware.ts b/src/middlewares/error.middleware.ts new file mode 100644 index 00000000..8ce5fffe --- /dev/null +++ b/src/middlewares/error.middleware.ts @@ -0,0 +1,20 @@ +import { NextFunction, Request, Response } from "express"; +import { AppError } from "../utils/custom-errors.utils"; + +export const errorMiddleware = ( + err: Error, + req: Request, + res: Response, + next: NextFunction +) => { + if (err instanceof AppError) { + res + .status(err.statusCode) + .json({ error: { code: err.statusCode, message: err.message } }); + } else { + console.error(err.stack); + res + .status(500) + .json({ error: { code: 500, message: "Internal Server Error" } }); + } +}; diff --git a/src/server.ts b/src/server.ts index fd1f74f5..915fcb46 100644 --- a/src/server.ts +++ b/src/server.ts @@ -5,6 +5,7 @@ import cors from "cors"; import helmet from "helmet"; import authRoutes from "./routes/auth.routes"; import projectRoutes from "./routes/projects.routes"; +import { errorMiddleware } from "./middlewares/error.middleware"; import loggerMiddleware from "./middlewares/logger.middleware"; try { @@ -24,6 +25,9 @@ try { app.use("/v2/auth", authRoutes); app.use("/v2/org", projectRoutes); + // Middleware + app.use(errorMiddleware); + app.use((req: Request, res: Response, next: NextFunction) => { res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader( diff --git a/src/utils/custom-errors.utils.ts b/src/utils/custom-errors.utils.ts new file mode 100644 index 00000000..2694b77c --- /dev/null +++ b/src/utils/custom-errors.utils.ts @@ -0,0 +1,34 @@ +import { constants } from "../constants"; + +export class AppError extends Error { + constructor(public statusCode: number, message: string) { + super(message); + Object.setPrototypeOf(this, AppError.prototype); + } +} + +export class NotFoundError extends AppError { + constructor(message: string = "Not Found") { + super(constants.HTTP_CODES.NOT_FOUND, message); + } +} + +export class BadRequestError extends AppError { + constructor(message: string = "Bad Request") { + super(constants.HTTP_CODES.BAD_REQUEST, message); + } +} + +export class DatabaseError extends AppError { + constructor(message: string = "DB error") { + super(constants.HTTP_CODES.SERVER_ERROR, message); + } +} + +export class ValidationError extends AppError { + constructor(message: string = "User validation error") { + super(constants.HTTP_CODES.FORBIDDEN, message); + } +} + +// Add more custom error classes as needed