From 8a64392836ebdbb9fde8422b0452015a8b373ecd Mon Sep 17 00:00:00 2001 From: junjie-w Date: Fri, 20 Dec 2024 19:45:18 +0100 Subject: [PATCH] refactor: improve examples --- examples/package.json | 2 +- examples/src/withCustomMiddleware.js | 55 ++++++++++++++++++++-------- examples/src/withHandler.js | 11 ++++-- examples/src/withMiddleware.js | 37 ++++++++++++++++--- 4 files changed, 79 insertions(+), 26 deletions(-) diff --git a/examples/package.json b/examples/package.json index a24dd32..aafc119 100644 --- a/examples/package.json +++ b/examples/package.json @@ -5,7 +5,7 @@ "scripts": { "dev:handler": "node src/withHandler.js", "dev:middleware": "node src/withMiddleware.js", - "dev:custom": "node src/withCustomMiddleware.js" + "dev:custom-middlware": "node src/withCustomMiddleware.js" }, "dependencies": { "express": "^4.18.2", diff --git a/examples/src/withCustomMiddleware.js b/examples/src/withCustomMiddleware.js index b1301dd..1b503d2 100644 --- a/examples/src/withCustomMiddleware.js +++ b/examples/src/withCustomMiddleware.js @@ -4,6 +4,7 @@ import { UnauthorizedError, ForbiddenError, ValidationError, + NotFoundError, } from "http-error-handler"; const app = express(); @@ -21,37 +22,59 @@ const requireAuth = (req, _res, next) => { }; const validateUser = (req, _res, next) => { - const { email, password } = req.body; - if (!email || !password) { - throw new ValidationError("Missing required fields", { - email: !email ? "Email is required" : undefined, - password: !password ? "Password is required" : undefined, - }); + const { email, username } = req.body; + const errors = {}; + + if (!email?.trim()) { + errors.email = "Email is required"; + } else if (!email.includes("@")) { + errors.email = "Invalid email format"; } - if (!email.includes("@")) { - throw new ValidationError("Invalid email format", { - email: "Must be a valid email address", - }); + + if (!username?.trim()) { + errors.username = "Username is required"; + } else if (username.length < 3) { + errors.username = "Username must be at least 3 characters long"; } + + if (Object.keys(errors).length > 0) { + throw new ValidationError("Invalid user data", errors); + } + next(); }; app.get("/users/:id", requireAuth, (req, _res, next) => { try { const { id } = req.params; + if (!id.match(/^\d+$/)) { + throw new ValidationError("Invalid user ID", { + id: "User ID must be numeric", + }); + } throw new NotFoundError("User not found", { id }); } catch (error) { next(error); } }); -app.post("/users", requireAuth, validateUser, (req, res, next) => { +app.post("/users/register", requireAuth, validateUser, (req, res, next) => { try { const { role } = req.query; if (role === "admin") { - throw new ForbiddenError("Insufficient permissions"); + throw new ForbiddenError("Insufficient permissions", { + message: "Only administrators can create admin users", + currentUserRole: "user", + }); } - res.status(201).json({ message: "User created" }); + res.status(201).json({ + message: "User registered successfully", + user: { + email: req.body.email, + username: req.body.username, + role: role || "user", + }, + }); } catch (error) { next(error); } @@ -61,11 +84,11 @@ app.use( errorMiddleware({ includeStack: process.env.NODE_ENV !== "production", onError: async (error) => { - console.error(`[${new Date().toISOString()}] Error:`, error); + console.error(`[${new Date().toISOString()}] Error: ${error.message}`); }, }) ); -app.listen(3002, () => { - console.log("Server running on http://localhost:3002"); +app.listen(3003, () => { + console.log("Server running on http://localhost:3003"); }); diff --git a/examples/src/withHandler.js b/examples/src/withHandler.js index e4dc000..8a76dbe 100644 --- a/examples/src/withHandler.js +++ b/examples/src/withHandler.js @@ -38,8 +38,11 @@ app.post("/products", async (req, res) => { const { name, price } = req.body; const errors = {}; - if (!name) errors.name = "Name is required"; - if (!price) errors.price = "Price is required"; + if (!name?.trim()) errors.name = "Name is required"; + if (typeof price !== "number" || price <= 0) { + errors.price = "Price must be a positive number"; + } + if (Object.keys(errors).length > 0) { throw new ValidationError("Invalid product data", errors); } @@ -50,6 +53,6 @@ app.post("/products", async (req, res) => { } }); -app.listen(3000, () => { - console.log("Server running on http://localhost:3000"); +app.listen(3001, () => { + console.log("Server running on http://localhost:3001"); }); diff --git a/examples/src/withMiddleware.js b/examples/src/withMiddleware.js index 1d0764c..9cb0a33 100644 --- a/examples/src/withMiddleware.js +++ b/examples/src/withMiddleware.js @@ -8,7 +8,7 @@ import { const app = express(); app.use(express.json()); -app.get("/with-middleware", (req, res, next) => { +app.get("/with-middleware", (_req, _res, next) => { try { throw new NotFoundError("Resource not found"); } catch (error) { @@ -16,7 +16,7 @@ app.get("/with-middleware", (req, res, next) => { } }); -app.get("/users/:id", (req, res, next) => { +app.get("/users/:id", (req, _res, next) => { try { const { id } = req.params; if (!id.match(/^\d+$/)) { @@ -28,14 +28,41 @@ app.get("/users/:id", (req, res, next) => { } }); +app.post("/users/register", (req, _res, next) => { + try { + const { email, username } = req.body; + const errors = {}; + + if (!email?.trim()) { + errors.email = "Email is required"; + } else if (!email.includes("@")) { + errors.email = "Invalid email format"; + } + + if (!username?.trim()) { + errors.username = "Username is required"; + } else if (username.length < 3) { + errors.username = "Username must be at least 3 characters long"; + } + + if (Object.keys(errors).length > 0) { + throw new ValidationError("Invalid registration data", errors); + } + + throw new Error("Database connection failed"); + } catch (error) { + next(error); + } +}); + app.use( errorMiddleware({ onError: async (error) => { - console.error(`Error: ${error}`); + console.error(`Error: ${error.message}`); }, }) ); -app.listen(3001, () => { - console.log("Server running on http://localhost:3001"); +app.listen(3002, () => { + console.log("Server running on http://localhost:3002"); });