nestjs-crud-microservice-validation
v2.1.6
Published
Decorator used to validate @NestJSX/CRUD request params, and data that is sending between micro-services using validation DTO or preset custom DTOs
Downloads
208
Readme
Summary
The following library is used to validate @NestJSX/CRUD
request params, and data that is sending between micro-services using validation DTO
or preset custom DTO
s
Installation
npm install nestjs-crud-microservice-validation
Usage
Adding default validation to controller
In order to use the library, you need to add the @MicroserviceValidation(@validationDTO: Class)
class decorator to a controller.
The decorator takes as an argument validationDTO class, which determines all default validation rules for each request parameters, with list of method groups (create, read, update, delete) these rules are applied to.
Request group methods list:
- CrudRequestTypes.CREATE - createOne, createMany;
- CrudRequestTypes.UPDATE - updateOne, replaceOne;
- CrudRequestTypes.DELETE - deleteOne;
- CrudRequestTypes.READ - getOne, getMany
To apply validation rules to specific request type methods you should add this request type to validation decorator groups option array.
@IsBoolean({groups: [CrudRequestTypes.UPDATE, CrudRequestTypes.READ})
All other method names are considered as custom methods and require custom validation dto added.
Decorator usage:
import { MicroserviceValidation, CrudRequestTypes } from 'nestjs-crud-microservice-validation';
import { MessagePattern } from '@nestjs/microservices';
import { CrudRequest } from '@nestjsx/crud';
import { IsString } from 'class-validator';
//Validation dto
class ExampleDtoClass {
//Validation is added for both create and update request types.
@IsString({groups: [CrudRequestTypes.CREATE, CrudRequestTypes.UPDATE]})
//Field is optional only for update request types.
@IsOptional({groups: [CrudRequestTypes.UPDATE]})
stringField?: string;
}
//Adding validation to controller methods using dto created above
@MicroserviceValidation(ExampleDtoClass)
class ExapmleController {
//Because method is default @nestjsx/crud method and no custom validation is added
//"req" and "dto" properties of data argument will be validated
//based on rules in DTO added to @MicroserviceValidation decorator
@MessagePattern({exampleMicroservice: {example: 'createOne'}})
createOne(data: {req: CrudRequest; dto: ExampleDtoClass}){
//Some creating logic
}
}
_______________________________
Adding custom validation to method
In case if you want to add custom dto to specific method you have to add @RmqTrasportDtoType
to method argument.
Decorator should get custom Dto class as an argument.
import { MicroserviceValidation, RmqTransportDtoType } from 'nestjs-crud-microservice-validation';
@MicroserviceValidation(BaseDto)
class ExampleController {
@MessagePattern({exampleMicroservice: {example: 'createOne'}})
//Because custom validation is added
//"req" and "dto" properties of data argument will be validated
//based on rules in CustomDto. Validation rules from BaseDto are ignored.
createOne(@RmqTransportDtoType(CustomDto) data: { req: CrudRequest; dto: CustomDto }) {
//Some creating logic
}
}
Important:
- Custom dto class should contain
Dto
part in class name.CustonDto
,GetUserDto
,CreateUserDto
... etc. @RmqTransportDtoType
decorator is required for all custom methods added to controller.- In case of custom method validation, crud request method groups are not required.
_______________________________
Nested validation
In case if you want to manage relation between your dto classes you should add @RelatedDto
decorator to property with nested dto validation.
@RelatedDto
decorator allows managing nested relations for property (it's added to) from current dto or parent dto in case if your dto is nested one.
To specify nested relations for property you should add nested property names as strings to nestedRelations
options.
All nested levels have to be separated by dot notation.
import { ValidateNested } from 'class-validator';
import { RelatedDto, CrudRequestTypes } from 'nestjs-crud-microservice-validation';
class SecondNestedDto {
@RelatedDto()
@ValidateNested({
context: ThirdNestedDto,
groups: [CrudRequestTypes.CREATE, CrudRequestTypes.UPDATE]
})
thirdNested: ThirdNestedDto;
}
class FirstNestedDto {
//Decorator should be added for each property you want to manage nested relation for
@RelatedDto()
@ValidateNested({
context: SecondNestedDto,
groups: [CrudRequestTypes.CREATE, CrudRequestTypes.UPDATE]
})
secondNested: SecondNestedDto;
}
class MainDto {
//Allows to also include "secondNested" property of FirstNestedDto
//and "thirdNested" property of SecondNestedDto to validation process
@RelatedDto({nestedRelations: ['secondNested', 'secondNested.thirdNested']})
@ValidateNested({
context: FirstNestedDto,
groups: [CrudRequestTypes.CREATE, CrudRequestTypes.UPDATE]
})
firstNested?: FirstNestedDto;
}
Validation process checks only nestedRelations
option of main Dto and ignores values of nestedRelations
option for all nested Dto.
import { ValidateNested } from 'class-validator';
import { RelatedDto, CrudRequestTypes, MicroserviceValidation } from 'nestjs-crud-microservice-validation';
class SecondNestedDto {
@RelatedDto()
@ValidateNested({context: ThirdNestedDto})
thirdNested: ThirdNestedDto;
@RelatedDto()
@ValidateNested({context: ForthNestedDto})
forthNested: ForthNestedDto;
}
class FirstNestedDto {
@RelatedDto({nestedRelations: ['forthNested']})
@ValidateNested({context: SecondNestedDto})
secondNested: SecondNestedDto;
}
class MainDto {
@RelatedDto({nestedRelations: ['secondNested', 'secondNested.thirdNested']})
@ValidateNested({
context: FirstNestedDto,
groups: [CrudRequestTypes.CREATE, CrudRequestTypes.UPDATE]
})
firstNested?: FirstNestedDto;
}
//Validates thirdNested field of SecondDto
@MicroserviceValidation(MainDto)
class ExampleClass {
//Some methods
}
//Validates forthNested field of SecondDto
@MicroserviceValidation(FirstNestedDto)
class AnotherExampleClass {
//Some methods
}
In example above base validation for ExampleClass
will ignore {nestedRelations: ['forthNested']}
option added to
secondNested
property of FirstNestedDto
because in this case its applied for nested dto and main dto is MainDo
class,
so validation will check only it's nestedRelations
option of @RelatedDto
.
Validation for AnotherExampleClass
will validate forthNested
property of SecondNestedDto
because in this main dto is FirstNestedDto
and it's nestedRelations
options of @RelatedDto
are considered as main options for all nested relations.
_______________________________
Request validation
Request validation works with all queries from @NestJSX/CRUD
request params, but there are few cases you should know about.
"isnull" and "notnull" operators:
isnull
and notnull
operators might be applied only to fields that are allowed to have null
value.
import { IsString, IsOptional } from 'class-validator';
import { CrudRequestTypes } from 'nestjs-crud-microservice-validation';
class RequestValidationDto {
//Field is not allowed for `isnull` and `notnull` request query operators and will throw validation error
@IsString({groups: [CrudRequestTypes.READ]})
requiredField: string;
//Field is allowed for `isnull` and `notnull` request query operators
@IsString({groups: [CrudRequestTypes.READ]})
@IsOptional({groups: [CrudRequestTypes.READ]})
optionalField?: string;
}
"ValidateIf" decorator
Request validation validate each dto property separately, so it is not work correct for properties with @ValidateIf
decorator that refers to other dto properties in argument function.
import { IsString, IsOptional } from 'class-validator';
class RequestValidationDto {
//This validation is not work correct for request queries validation
//because it refers to `secondField` dto property
@ValidateIf(o => o.secondField !== 'test', {groups: [CrudRequestTypes.READ]})
@IsString({groups: [CrudRequestTypes.READ]})
firstField?: string;
//This validations works correct for request queries validation
//because it doesnt reffers to other dto properties
@ValidateIf(o => o.secondField !== 'test', {groups: [CrudRequestTypes.READ]})
@IsString({groups: [CrudRequestTypes.READ]})
secondField?: string;
}
Joins
Join query is not allowed for properties without@ValidateNested
decorator.
Working with nested fields
All nested levels have to be separated by dot notation. Example: {fields: ['user', 'user.name']}
_______________________________
Enabling validation only for nested dto properties (for CRUD methods only)
The validation decorator @ValidateIfRelatedOnly
can be used to apply the validators on a property when its parent dto
is nested, and remove validation rules in case if parent dto is base dto.
@ValidateIfRelatedOnly
is implemented by using ValidateIf
logic, so using both
@ValidateIfRelatedOnly
and @ValidateIf
decorators on the same property is not recommended.
In example bellow validation of ParentDto
for both CREATE
and READ
CRUD method groups will require
both someField
and someOtherField
properties to exists in FirstNestedDto
payload.
If you validate FirstNestedDto
directly, someField
is required only for READ
method group
and should not exist in CREATE
group methods, because @ValidateIfRelatedOnly
decorator is applied to CREATE
group.
import { IsString, IsOptional } from 'class-validator';
import { RelatedDto, ValidateIfRelatedOnly, CrudRequestTypes } from 'nestjs-crud-microservice-validation';
class FirstNestedDto {
@ValidateIfRelatedOnly({groups: [CrudRequestTypes.CREATE]})
@IsString({groups: [CrudRequestTypes.CREATE, CrudRequestTypes.READ]})
someField: string;
@IsString({groups: [CrudRequestTypes.CREATE, CrudRequestTypes.READ]})
someOtherField: string;
}
class ParentDto {
@RelatedDto()
@ValidateNested({
context: FirstNestedDto,
groups: [CrudRequestTypes.CREATE, CrudRequestTypes.READ]
})
firstNested: FirstNestedDto;
}