Skip to content

Commit

Permalink
add database error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
willpinha committed May 14, 2024
1 parent a2dd63d commit 00eb6b1
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/controllers/hello.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const controller: RequestHandler = async (req, res) => {
req.body,
z.object({
customPrefix: z.enum(["Hey", "Hi"]).optional(),
name: z.string(),
name: z.string().min(1),
})
);

Expand Down
21 changes: 21 additions & 0 deletions src/errors/database.handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ErrorRequestHandler } from "express";
import { DrizzleError } from "drizzle-orm";
import { JSendException } from "@/utils/exception";

/**
* Handles all Drizzle errors and converts them to JSend exceptions
*/
const handler: ErrorRequestHandler = (err, req, res, next) => {
if (err instanceof DrizzleError) {
return next(
new JSendException(500, {
status: "error",
message: err.message,
})
);
}

next(err);
};

export default handler;
32 changes: 32 additions & 0 deletions src/errors/global.handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { JSendException } from "@/utils/exception";
import { JSend } from "@/utils/jsend";
import type { ErrorRequestHandler } from "express";

/**
* Global error handler for the application. This function should be the last middleware in the chain
* to catch any errors that were not handled by the other middlewares
*
* You can use JSendException to throw errors from your controllers and services
*/
const globalErrorHandler: ErrorRequestHandler = (err, req, res, next) => {
if (err instanceof JSendException) {
return res.status(err.status).json(err.response);
}

console.error(err);

/**
* Any errors that were not manually throw with JSendException will return a 500 status code
*
* Ideally, the API should not reach this point. Instead, all errors should be handled by
* throwing JSendException with the appropriate status code and response
*
* A good pattern for that is creating a chain of error handlers to handle different types of
* errors that are not manually throwed (database errors, ...) and convert them to
* JSendException before reaching the global error handler. This is done, for example, in the
* `src/errors/database.handler.ts` file
*/
res.status(500).json(JSend.error("Internal Server Error"));
};

export default globalErrorHandler;
15 changes: 0 additions & 15 deletions src/lib/error-handler.ts

This file was deleted.

9 changes: 6 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import cors from "cors";
import bodyParser from "body-parser";
import routes from "@/routes";
import dotenv from "@/lib/dotenv";
import errorHandler from "@/lib/error-handler";
import databaseErrorHandler from "@/errors/database.handler";
import globalErrorHandler from "@/errors/global.handler";

const app = express();

Expand All @@ -25,14 +26,16 @@ app.use(
*
* {@link https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#custom-headers-and-cors}
*/
origin: [new RegExp("http://localhost:\\d*"), "https://example.com"],
origin: [new RegExp("http://localhost:\\d+"), "https://example.com"],
credentials: true,
})
);

app.use("/api", routes);

app.use(errorHandler);
// Error handlers. The global error handler must be the last middleware in the chain
app.use(databaseErrorHandler);
app.use(globalErrorHandler);

app.listen(dotenv.SERVER_PORT, () => {
console.log(`🚀 Server is running on port ${dotenv.SERVER_PORT}`);
Expand Down
2 changes: 2 additions & 0 deletions src/services/hello.service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// This is only an example file. You can safely delete it

export function getHelloMessage(name: string, prefix: string = "Hello") {
return `${prefix}, ${name}!`;
}
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"exclude": ["node_modules"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
Expand Down

0 comments on commit 00eb6b1

Please sign in to comment.