Reputation: 2063
I am trying to use a ValidationPipe
but no matter how I write my code I get the following warning when sending a request: No metadata found. There is more than once class-validator version installed probably. You need to flatten your dependencies
.
My route looks something like this:
@Get()
@UsePipes(new ValidationPipe({ transform: true }))
async findAll(@Query() queryDto: QueryDto) {
return await this.myService.findAll(queryDto);
}
And my DTO looks something like this:
export class queryDto
{
@ApiModelProperty({
description: 'Maximum number of results',
type: Number,
example: 50,
default: 50,
required: false
})
readonly limit: number = 50;
}
I tried using the ValidationPipe
several ways, following the doc, but nothing works for me. I know it does not work because although the request gets a response, the default value that I wrote in my DTO for the property limit
, which is 50
, is not used when the query is empty. Therefore, when no limit
is provided in the query, limit
's value is undefined, whereas it should be 50
(which means the ValidationPipe
is not used).
My package.json
seems correct:
npm ls class-validator
[email protected] /home/pierre_t/Bureau/dev/ApiSport
└── [email protected]
Full package.json
:
{
"name": "api-sport",
"version": "0.0.1",
"description": "",
"author": "",
"license": "MIT",
"scripts": {
"build": "tsc -p tsconfig.build.json",
"format": "prettier --write \"src/**/*.ts\"",
"start": "ts-node -r tsconfig-paths/register src/main.ts",
"start:dev": "nodemon",
"start:debug": "nodemon --config nodemon-debug.json",
"start:prod": "pm2 start ./src/main.js --no-daemon",
"lint": "tslint -p tsconfig.json -c tslint.json",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^6.0.5",
"@nestjs/core": "^6.0.5",
"@nestjs/platform-express": "^6.0.5",
"@nestjs/swagger": "^3.0.1",
"@nestjs/typeorm": "^6.0.0",
"@types/lodash": "^4.14.123",
"class-transformer": "^0.2.0",
"class-validator": "^0.9.1",
"dotenv": "^7.0.0",
"hbs": "^4.0.3",
"mysql": "^2.16.0",
"pm2": "^3.4.1",
"reflect-metadata": "^0.1.12",
"rimraf": "^2.6.2",
"rxjs": "^6.3.3",
"swagger-ui-express": "^4.0.2",
"typeorm": "^0.2.16"
},
"devDependencies": {
"@nestjs/testing": "^6.0.5",
"@types/express": "^4.16.0",
"@types/jest": "^23.3.13",
"@types/node": "^10.14.4",
"@types/supertest": "^2.0.7",
"jest": "^23.6.0",
"nodemon": "^1.18.9",
"prettier": "^1.15.3",
"supertest": "^3.4.1",
"ts-jest": "^23.10.5",
"ts-node": "^7.0.1",
"tsconfig-paths": "^3.7.0",
"tslint": "5.12.1",
"typescript": "^3.4.1"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
Why do I get this message and how can I use ValidationPipe
?
Upvotes: 12
Views: 12528
Reputation: 392
I will share here a solution for another situation which provokes the same error. (Error comes from class-validator
package as mentioned above, 0.14.1
version in my case)
If you import only the typescript type of DTO class and use it with a nest param decorator (@Body
, @Query
etc.), you will get the same error:
/** this fails */
import {Body} from '@nestjs/common';
import type {CreatePageDto} from './pages/dto/create-page.dto';
createPage(@Body() pageDto: CreatePageDto) { ... }
class-validator
use reflection to access class constructor, so you need to remove 'type' in the CreatePageDto
import:
/** this works */
import {Body} from '@nestjs/common';
import {CreatePageDto} from './pages/dto/create-page.dto';
createPage(@Body() pageDto: CreatePageDto) { ... }
It is not obvious from the text of this error message, so I hope it helps someone.
Upvotes: 0
Reputation: 625
This is my bootstrap, it works with class-validator:
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
bootstrap();
Upvotes: 0
Reputation: 1697
The question has already been answered, but for future reference of people with the same problem...
The class-validator allows you to bypass the validation of certain property (whitelisting) special flags to validate any property.
As the docs:
This will strip all properties that don't have any decorators. If no other decorator is suitable for your property, you can use @Allow decorator
e.g:
import {validate, Allow, Min} from "class-validator";
export class Post {
@Allow()
title: string;
@Min(0)
views: number;
nonWhitelistedProperty: number;
}
Upvotes: 1
Reputation: 60357
This is because you are using class-validator
but without any validations, see this issue:
Basically, it warns that you don't have any metadatas in the storage, which means you haven't used any decorator from class-validator. That means you don't perform any validation, so you should just pass
validate: false
option tobuildSchema
to disable automatic validation.
I'm not sure if you can turn of validation for nest's ValidationPipe
, but alternatively you can just add an assertion to your dto (if it makes sense), e.g.:
import { Min } from 'class-validator';
export class QueryDto {
@Min(1)
readonly limit: number = 50;
}
By the way: Since your @Query
will only have string properties, you'll probably want to transform your limit
from string
to number
. Have a look at this answer.
Upvotes: 16