DEV Community

Cover image for NestJS Pipes
Sanjai Sakthivel
Sanjai Sakthivel

Posted on

NestJS Pipes

Title: Mastering NestJS Pipes: Types, Implementation, and Useful Packages

NestJS, a robust Node.js framework, empowers developers with a multitude of features to streamline backend development. Among these, pipes stand out as a fundamental tool for transforming and validating data within your application. In this comprehensive guide, we'll dive deep into the realm of NestJS pipes, exploring their various types, implementation strategies, and even shine a spotlight on a selection of packages that can elevate your pipe-handling experience.

Understanding NestJS Pipes

Pipes in NestJS are the Swiss Army knife of data processing. They facilitate seamless transformation, sanitization, and validation of incoming data as it traverses various parts of your application. This ensures that the data conforms to specific requirements before it's used in controllers or sent back as responses.

Types of Pipes

  1. Built-in Pipes: NestJS comes equipped with an arsenal of built-in pipes tailored for common use cases. These pipes significantly expedite your development process. Some noteworthy built-in pipes include:
  • ParseIntPipe: Converts a string to an integer.
  • ParseFloatPipe: Converts a string to a floating-point number.
  • ValidationPipe: Performs automatic data validation based on decorators such as @Body(), @Query(), and more.
  • DefaultValuePipe: Provides default values when a value is missing.
  1. Custom Pipes: For specialized requirements, crafting custom pipes is the way to go. By implementing the PipeTransform interface, you gain the ability to handle intricate transformations and validations tailored precisely to your application's needs.

Applying Pipes

NestJS empowers you to apply pipes at different levels within your application:

  1. Parameter Level:

Apply a pipe to a specific parameter within a route handler. For instance:

   @Get(':id')
   getOne(@Param('id', ParseIntPipe) id: number) {
     // Controller logic
   }
Enter fullscreen mode Exit fullscreen mode
  1. Route Level:

Apply a pipe to an entire route handler within a controller:

   @UsePipes(MyCustomPipe)
   @Controller('items')
   export class ItemsController {
     // Controller methods
   }
Enter fullscreen mode Exit fullscreen mode
  1. Global Level:

Apply a pipe globally to the entire application:

   // main.ts
   async function bootstrap() {
     const app = await NestFactory.create(AppModule);
     app.useGlobalPipes(new MyCustomPipe());
     // ...
   }
   bootstrap();
Enter fullscreen mode Exit fullscreen mode

Useful Packages for NestJS Pipes

  1. class-validator: This package complements NestJS's built-in ValidationPipe. It utilizes decorators to effortlessly add validation rules to your DTOs (Data Transfer Objects) and executes automatic validation based on these rules.

  2. class-transformer: In conjunction with class-validator, this package is a game-changer for transforming and normalizing incoming data to the desired format. It shines when handling intricate data transformations.

  3. @nestjs/mapped-types: This package introduces utility functions for generating mapped types. It's invaluable for crafting new DTOs derived from existing ones, complete with additional validation rules or transformed properties.

  4. nestjs-query/packages/query-graphql: If you're in the realm of GraphQL and aspire to seamlessly handle query validation and filtering, the nestjs-query library furnishes potent tools for defining and validating queries.

Examples of Types of Pipes

1. Built-in Pipes

ParseIntPipe and ParseFloatPipe

Imagine an API endpoint that anticipates an ID as a parameter in the URL. The ID requires conversion into a numeric format for processing.

@Get(':id')
getOne(@Param('id', ParseIntPipe) id: number) {
  // Now 'id' is a number
  // Controller logic
}
Enter fullscreen mode Exit fullscreen mode

ValidationPipe

Consider a scenario where user input validation is imperative for creating a new item. Employ the ValidationPipe to automatically validate incoming data based on a DTO class furnished with validation decorators.

@Post()
createItem(@Body(ValidationPipe) createItemDto: CreateItemDto) {
  // 'createItemDto' is validated as per DTO rules
  // Controller logic
}
Enter fullscreen mode Exit fullscreen mode

DefaultValuePipe

In situations where a query parameter is optional and absent from the request, DefaultValuePipe steps in to assign a default value.

@Get()
getItems(@Query('page', DefaultValuePipe) page: number = 1) {
  // If 'page' query parameter is omitted, 'page' defaults to 1
  // Controller logic
}
Enter fullscreen mode Exit fullscreen mode

2. Custom Pipe

Custom Validation Pipe

Suppose you're tasked with validating whether an email adheres to a valid format. Crafting a custom pipe is the optimal route for executing this validation.

import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';

@Injectable()
export class EmailValidationPipe implements PipeTransform {
  transform(value: any) {
    const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    if (!emailRegex.test(value)) {
      throw new BadRequestException('Invalid email format');
    }
    return value;
  }
}
Enter fullscreen mode Exit fullscreen mode

Subsequently, apply this custom pipe to your route:

@Post('register')
registerUser(@Body('email', EmailValidationPipe) email: string) {
  // Email is validated by the custom pipe
  // Controller logic
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Navigating NestJS pipes, whether they're baked into the framework or custom-crafted, ushers in an era of data processing prowess. By immersing yourself in the world of these pipes and leveraging packages like class-validator and class-transformer, you unlock the potential to ensure data consistency, amplify validation processes, and keep your codebase modular and primed for growth. Be discerning in your choice of pipe type for every situation, and explore the remarkable utilities bestowed upon you by NestJS and its associated packages, all in the pursuit of refining your backend development journey.

Top comments (4)

Collapse
 
larbi_benyakhou_1cfec2bf2 profile image
larbi benyakhou

Thank You

Collapse
 
muzammal_hussain_df77c292 profile image
Muzammal Hussain

Great explanation. Thanks bro

Collapse
 
fclmman profile image
Bulat.V

Hi, cannot make pipe work for controller, what can I do wrong?

Collapse
 
thepouria profile image
thepouria

can u provide more info, so i could help