Skip to main content

Overview

PyqDeck implements a robust validation layer using Zod. Validation happens at two levels:
  1. Schema Level: Defining the shape and constraints of data within our models.
  2. Middleware Level: Intercepting requests and validating req.body, req.query, or req.params before they reach the controller.

Zod Schemas in Models

Every Mongoose model has a corresponding Zod schema exported from the same file (e.g., backend/src/models/University.js).
export const universityZodSchema = z.object({
  name: z.string().min(1, "Name is required").max(200),
  shortName: z.string().min(1, "Short name is required").max(20),
  slug: z.string().min(1, "Slug is required").max(100),
  // ... other fields
});
Using Zod in models provides:
  • Type Safety: Clearer documentation of what fields are required and their types.
  • Reusability: The same schema can be used for both POST (creation) and PATCH (updates, via .partial()).

Validation Middleware

The validationMiddleware.js is a higher-order function that generates Express middleware for a given Zod schema.

Usage in Routes

import { validate } from "../middlewares/validationMiddleware.js";
import { universityZodSchema } from "../models/University.js";

router.post("/", validate(universityZodSchema), universityController.create);

How it Works

  1. Validation: It runs schema.safeParse() against req.body.
  2. Success: If valid, it replaces req.body with the parsed (and potentially transformed/sanitized) data and calls next().
  3. Failure: If invalid, it formats the Zod error into a human-readable message and throws a ValidationError (400), which is then handled by the global error handler.

Validation Strategies

  • Strict Mode: We generally allow extra fields in the request body but ignore them (Zod’s default behavior).
  • Partial Updates: For PATCH requests, we use schema.partial() to make all fields optional while still enforcing types and constraints for the fields that are provided.
  • Query Validation: We also use Zod to validate pagination parameters (page, limit, sort) in the paginationMiddleware.