Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can we override the global validation pipe in NestJs?

I have a code in which i have applied a global validation pipe in main.ts file like so:

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableCors();
  // Enable global validation pipe
  app.useGlobalPipes(new ValidationPipe({
    whitelist: true
  }));
}

Now in one of my controller i wanted to skip some properties of a DTO in a patch request like so

    @Patch(':id')
    // Override the pipes
    @UsePipes(new ValidationPipe({
        skipMissingProperties: true,
    }))
    updateProject(@Param('id') accountId: string, @Body() dataToUpdate: UpdateProjectDTO) {
        return dataToUpdate;
    }

This is my DTO:

export class UpdateProjectDTO {
    @IsNotEmpty()
    projectType: string;

    @IsNotEmpty()
    projectDescription: string;
}

I wanted to ignore projectDescription if its not submitted as part of the request. But in this case my global pipe is taking precedence which doesn't have skipMissingProperties defined as part of its property. Is there a solution to override the global pipe?

like image 314
Sandeep K Nair Avatar asked Nov 16 '22 07:11

Sandeep K Nair


1 Answers

Overriding the global validation pipe is tricky. The solution that worked for me was to override it for a specific param decorator. The example below is for the body but the principle could be applied to other decorators as well.

First, create a raw body custom decorator:

export const RawBody = createParamDecorator(
  (data: unknown, ctx: ExecutionContext): any => {
    const request = ctx.switchToHttp().getRequest();
    return request.body;
  }
);

Second, write another custom decorator that composes that with a new validation pipe:

export const AnyValidBody = () =>
  RawBody(
    new ValidationPipe({
      validateCustomDecorators: true,
      whitelist: true,
      skipMissingProperties: true
    })
  );

Now, in your controller use @AnyValidBody instead of @Body like so:

    @Patch(':id')
    updateProject(@Param('id') accountId: string, @AnyValidBody() dataToUpdate: UpdateProjectDTO) {
        return dataToUpdate;
    }

For other ways to approach this, check out: https://gist.github.com/josephdpurcell/9af97c36148673de596ecaa7e5eb6a0a. It has links to other similar stack overflow questions too.

like image 110
josephdpurcell Avatar answered Dec 20 '22 00:12

josephdpurcell