Search code examples
javascriptnode.jsnestjsdto

NestJS ValidationPipe is not working properly for @Query()


I'm trying to transform some query params from string to int using the in-build NestJS ValidationPipe, but it doesn't seem to be working correctly,

Here is my controller :

import {
..., ValidationPipe
} from '@nestjs/common';

...

@UseGuards(JwtAuthGuard)
@Get()
findAll(@Req() req, @Query(new ValidationPipe({
    transform: true,
    transformOptions: { enableImplicitConversion: true },
    forbidNonWhitelisted: true,
})) query: GetTestDto) {
    return this.testService.findAll(query, req.user.id);
}

Here is my DTO :

import { IsInt, IsOptional, IsString } from 'class-validator';
import { Transform } from 'class-transformer';

export class GetTestDto {
    @IsOptional()
    @IsString()
    public search: string;

    @IsOptional()
    @Transform(({value}) => {
        console.log(typeof value); // => string / I'm just testing here
        return value
    })
    @IsInt()
    public page: number;

    @IsOptional()
    @IsInt()
    public limit: number;
}

main.ts :

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import cookieParser from 'cookie-parser';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
    const app = await NestFactory.create(AppModule);
    app.setGlobalPrefix('api');
    app.use(cookieParser());
    app.useGlobalPipes(new ValidationPipe());
    await app.listen(3000);
}

bootstrap();

when I try to call GET http://127.0.0.1:3000/api/test?page=1&limit=10 I get this

validation error from the DTO I think:
{
    "statusCode": 400,
    "message": [
        "page must be an integer number",
        "limit must be an integer number"
    ],
    "error": "Bad Request"
} 

I've tried deleting node_modules and dist folders, but nothing changed. I don't want to use @Transform() in the DTO as a solution, I would prefer for the pipe to do the changing with the enableImplicitConversion: true

Can I please get some help?

Thank you


Solution

    1. Pass the ValidationPipe options in the main.ts file
    app.useGlobalPipes(
        new ValidationPipe({
          transform: true,
          transformOptions: {
            enableImplicitConversion: true,
          },
          whitelist: true,
        })
      );
    
    1. Get rid of the @Transform decorator in your dto class.

    2. Get rid of the ValidationPipe passed to the @Query decorator in your controller

    @UseGuards(JwtAuthGuard)
    @Get()
    findAll(@Req() req, @Query() query: GetTestDto) {
        return this.testService.findAll(query, req.user.id);
    }