import { z } from 'zod'; import { Request, Response, NextFunction } from 'express'; /** * Project status enum values */ export const ProjectStatus = { ACTIVE: 'ACTIVE', INACTIVE: 'INACTIVE', COMPLETED: 'COMPLETED', } as const; export type ProjectStatusType = (typeof ProjectStatus)[keyof typeof ProjectStatus]; /** * Schema for creating a new project * - name: required, non-empty string * - description: optional string * - area_name: optional string * - location: optional string * - status: optional, defaults to ACTIVE */ export const createProjectSchema = z.object({ name: z .string({ required_error: 'Name is required' }) .min(1, 'Name cannot be empty') .max(255, 'Name must be at most 255 characters'), description: z .string() .max(1000, 'Description must be at most 1000 characters') .optional() .nullable(), area_name: z .string() .max(255, 'Area name must be at most 255 characters') .optional() .nullable(), location: z .string() .max(500, 'Location must be at most 500 characters') .optional() .nullable(), status: z .enum([ProjectStatus.ACTIVE, ProjectStatus.INACTIVE, ProjectStatus.COMPLETED]) .default(ProjectStatus.ACTIVE) .optional(), }); /** * Schema for updating a project * All fields are optional */ export const updateProjectSchema = z.object({ name: z .string() .min(1, 'Name cannot be empty') .max(255, 'Name must be at most 255 characters') .optional(), description: z .string() .max(1000, 'Description must be at most 1000 characters') .optional() .nullable(), area_name: z .string() .max(255, 'Area name must be at most 255 characters') .optional() .nullable(), location: z .string() .max(500, 'Location must be at most 500 characters') .optional() .nullable(), status: z .enum([ProjectStatus.ACTIVE, ProjectStatus.INACTIVE, ProjectStatus.COMPLETED]) .optional(), }); /** * Type definitions derived from schemas */ export type CreateProjectInput = z.infer; export type UpdateProjectInput = z.infer; /** * Generic validation middleware factory * Creates a middleware that validates request body against a Zod schema * @param schema - Zod schema to validate against */ function validate(schema: T) { return (req: Request, res: Response, next: NextFunction): void => { const result = schema.safeParse(req.body); if (!result.success) { const errors = result.error.errors.map((err) => ({ field: err.path.join('.'), message: err.message, })); res.status(400).json({ success: false, error: 'Validation failed', details: errors, }); return; } // Replace body with validated and typed data req.body = result.data; next(); }; } /** * Pre-configured validation middlewares for projects */ export const validateCreateProject = validate(createProjectSchema); export const validateUpdateProject = validate(updateProjectSchema);