I'm working on creating api with nestjs , but when it comes to data validation it becomes so confused because of many options existing ,
for example should i validate data in rout level using schema validation (like hapi@joi)
or validate data in class level class-validator
`
use(req: Request, res: Response, next: Function) {
console.log('the method is', req.method);
const userSchema = joi.object({
name: joi
.string()
.alphanum()
.min(3)
.max(15)
.required(),
phone: joi
.number()
.min(11)
.required(),
password: joi
.string()
.min(8)
.max(100)
.required()
.regex(/((?=.*\d)|(?=.*\w+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/),
});
const { error } = userSchema.validate(req.body);
if (error) {
throw new BadRequestException(error.details);
}
next();
`
validation on class level
`
export class CreateUserDto {
@IsString()
@IsNotEmpty()
name: string;
@IsNotEmpty()
@IsString()
@Matches(/((?=.*\d)|(?=.*\w+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/)
password: string;
@IsNumber()
@Length(11, 15)
@IsNotEmpty()
phone: number;
}
`
It's a personal preference and it depends a lot on your project structure, but...
Using DTOs to validate your objects makes your code cleaner IMHO and simplifies the usage of the nest OpenAPI plugin (used for documentation). And also, since if we remove the decorators, it is nothing more than a simple class with properties, you could also use it as your type on the parameters of your functions just like -> https://docs.nestjs.com/openapi/types-and-parameters allowing typescript to infer the type of the object and allowing you to be sure it's already validated