Validation
While building REST APIs, validating input data becomes and important practice to validate the incoming data.
IntentJS internally uses class-validator
package to perform data validation. On top of what `class-validator` offers, IntentJS comes with some powerful and useful decorators which make data validation in your application, actually a breeze.
Validation in Intent
Creating Schema
In order to validate your input, you first need to create a schema which we will be using to compare. You can think of schemas as simple classes which has some meta information attached.
You can create a schema like below
import { IsNotEmpty, IsString } from "class-validator";export class CreateBookDto { @IsString() @IsNotEmpty() name: string; @IsString() @IsNotEmpty() author: string;}
For available validation decorators, you can refer to the `class-validator` (opens in a new tab)documentation.
Using Validator class
Now that you have the schema ready, we will need to validate it. To do so, you can make use of the Validator
class.
import { Validator } from "@intentjs/core";const validator = Validator.compareWith(CreateBookDto);
Inside the compareWith
method we are passing the schema that we created previously. We can now use the new validator
that we created to validate our inputs. Let's see an example below
await validator.validate({ name: 'Get Epic Shit Done', author: 'Ankur Warikoo'});
The validate
method internally creates the instance of the schema we passed, and then validates it. In above example, the validation will pass.
The validate
method also returns the instance of the schema if the validation has been successful. See below
const dto = await validator.validate({ name: "Get Epic Shit Done", author: "Ankur Warikoo",});console.log(dto.name);// Get Epic Shit Done
You can now use this schema the way you like, because it's just a simple class.
Validation Failure
Validator class throws ValidationFailed
exception if the validation fails. Let's see one example below
await validator.validate({ name: "Get Epic Shit Done",});
This would throw an exception because it doesn't have the author
attribute as it is expected inside the schema. To get the list of all the validation rules that failed, you can make use of the getErrors
method in the exception.
try { validator.validate({ name: "Get Epic Shit Done" });} catch (e) { if (e instanceof ValidationFailed) { console.log(e.getErrors()); }}
The getErrors
method returns the error object like below
{ "author": ["Author should not be empty"]}
Adding Meta
Using with Request and Controllers
We have also added a few helper methods built on top of the Validator
class to help you write clean and better code.
Using IntentRequest
If you want to validate the payload that you are getting inside the request, you can make use of the validate
method present inside the IntentRequest
class.
@Controller()export class BookController { @Post("") async create(@IRequest() req: IntentRequest) { const dto = await req.validate(CreateBookDto); return { msg: "Book Created Successfully!" }; }}
validate
method will automatically validate the data along with adding meta inside the schema instance.
Using @Validate Decorator
You can also make use of the Validate
decorator to automatically validate the incoming request. And if you want the instance of the validated schema, you can make use of the Dto
decorator. Let's look at an example below:
import { Validate, Dto } from "@intentjs/core";@Controller()export class BookController { @Post("") @Validate(CreateBookDto) async create(@Dto() dto: CreateBookDto) { return { msg: "Book Created Successfully!" }; }}
Available Decorators
We have added a few validation decorators which we believe will be super useful for some of your scenarios.
List of decorators available
- Exists (Database)
- IsUnique (Database)
- IsFromConfig
- IsEqualToProp
- List of
class-validator
decorators (opens in a new tab)
Exists (Database)
Rule to validate that the property should exist inside the specified database table.
@Exists({ table: 'users', col: 'email' })
IsUnique
Rule to validate that the property doesn't exist inside the specified database table.
@IsUnique({ table: 'users', col: 'email' })
IsFromConfig
Rule to check if a prop's value matches the value of the key from the config.
@IsFromConfig({ key: 'app.locale' })
IsEqualToProp
Rule to check if one prop is equal to another.
password: string;@IsEqualToProp('password')confirmPassword: string;