Uvodu u Nest.js “Pipe”
Pipes u NestJS-u su specijalne komponente koje se koriste za transformaciju i validaciju podataka pre nego što stignu do kontrolera ili metoda kontrolera. Pipes su korisni kada želimo da osiguramo da podaci koje primamo u API zahtevima ispunjavaju određene uslove ili da se na specifičan način transformišu.
Nest.js dolazi sa ugrađenim pipes koji se mogu koristiti za transformaciju i validaciju podataka. Ugrađeni pipe-ovi, pružaju brza i efikasna rešenja za osnovne zadatke kao što su validacija i transformacija. Evo nekih ugrađeni pipes:
- ValidationPipe: Automatska validacija podataka koristeći dekoratore.
- ParseIntPipe: Automatska konverzija stringa u broj.
- ParseBoolPipe: Automatska konverzija stringa u boolean.
- ParseArrayPipe: Automatska konverzija stringa u niz.
- ParseUUIDPipe: Automatska validacija UUID formata.
- DefaultValuePipe: Postavljanje podrazumevane vrednosti ako vrednost nije definisana.
Međutim, ako su vaši zahtevi specifični, možete kreirati “custom pipe-ove” koristeći interfejs “PipeTransform”.

ValidationPipe
Ako se “ValidationPipe” koriste za DTO validaciju onda je potrebno da instaliramo dodatne biblioteke (kod drugih ugrađenih pipe-ove to nije potrebno). Ovo su dve neophodne biblioteke:
- class-validator: Omogućava definisanje i proveru pravila validacije.
- class-transformer: Transformiše ulazne podatke u instance klasa DTO-a.
Koristite sledeću komandu za instalaciju:
npm install class-validator class-transformer
Šta je “class-transformer”?
“class-transformer” je TypeScript biblioteka koja omogućava pretvaranje (transformaciju) plain JavaScript objekata u instance klasa i obrnuto. Obično su to jednostavni JavaScript objekti (dobijeni, na primer, iz JSON-a) u instance definisanih klasa. Takođe omogućava dodavanje logike za prilagođene transformacije i rad sa ugneždenim strukturama objekata.
Primer: JS objekt u instancu klase
import { plainToClass } from 'class-transformer';
class User {
firstName: string;
lastName: string;
}
const plainObject = { firstName: 'John', lastName: 'Doe' };
const user = plainToClass(User, plainObject);
console.log(user instanceof User); // true
Primer: klasa u plain JS objekat
import { classToPlain } from 'class-transformer';
const user = new User();
user.firstName = 'John';
user.lastName = 'Doe';
const plainObject = classToPlain(user);
console.log(plainObject); // { firstName: 'John', lastName: 'Doe' }
Šta je “class-validator”?
“class-validator” je TypeScript biblioteka koja omogućava definisanje i proveru pravila validacije za JavaScript objekte. Ova biblioteka koristi dekoratore za definisanje pravila validacije, kao što su provera tipova, dužine, minimalne i maksimalne vrednosti, obavezna polja, regularni izrazi i mnoga druga pravila.
Ovo su najčešće korišćeni:
- @IsString(): Proverava da li je vrednost string.
- @IsInt(): Proverava da li je vrednost integer.
- @IsBoolean(): Proverava da li je vrednost boolean.
- @IsEmail(): Proverava da li je vrednost validna email adresa.
- @IsNotEmpty(): Proverava da li je vrednost prazna.
- @MinLength(): Proverava minimalnu dužinu stringa.
- @MaxLength(): Proverava maksimalnu dužinu stringa.
- @Min(): Proverava minimalnu vrednost broja.
- @Max(): Proverava maksimalnu vrednost broja.
- @Matches(): Proverava da li vrednost odgovara regularnom izrazu.
Listu svih dekoratora možete pronaći na ovome linku.
Primer
import { IsString } from 'class-validator';
export class CreateUserDto {
@IsString()
name: string;
}
ValidationPipe opcije
Validation Pipe u NestJS-u ima nekoliko korisnih opcija za prilagođavanje ponašanja prilikom validacije. Ove opcije omogućavaju detaljniju kontrolu nad načinom na koji će validacija biti izvršena i pomažu pri rukovanju sa nepotrebnim ili nevalidnim podacima. U nastavku su objašnjene glavne opcije koje možete koristiti sa Validation Pipe-om.
a) Opcija whitelist
Opcija whitelist služi za automatsko uklanjanje svih svojstava koja nisu definisana u DTO (Data Transfer Object) klasi. Kada je ova opcija omogućena, svi dodatni podaci koji nisu eksplicitno definisani u DTO klasi biće ignorisani, čime se osigurava da samo željena svojstva budu obrađena.
Primer:
@UsePipes(new ValidationPipe({ whitelist: true }))
@Post()
createUser(@Body() createUserDto: CreateUserDto) {
return createUserDto;
}
b) Opcija forbidNonWhitelisted
Opcija forbidNonWhitelisted radi u kombinaciji sa whitelist. Kada je omogućena, ova opcija baca grešku svaki put kada se pojavi neko polje koje nije definisano u DTO klasi, umesto da ga samo ignoriše. Ovo je korisno ako želite striktno kontrolisati podatke i sprečiti prolazak bilo kakvih dodatnih informacija koje ne pripadaju zahtevanoj strukturi.
Primer:
@UsePipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }))
@Post()
createUser(@Body() createUserDto: CreateUserDto) {
return createUserDto;
}
c) Opcija transform
Opcija transform omogućava automatsko prebacivanje ulaznih podataka u instance DTO klasa. Kada je omogućena, ulazni podaci će se automatski transformisati u instancu DTO klase, što omogućava lakši pristup metodama i tipovima u okviru objekta.
Primer:
@UsePipes(new ValidationPipe({ transform: true }))
@Post()
createUser(@Body() createUserDto: CreateUserDto) {
return createUserDto;
}
ValidatePipe na nivou parametra
`ValidationPipe` se može primeniti na pojedinačni parametar rute za validaciju ulaznih podataka.
import { Controller, Get, Param, ValidationPipe } from '@nestjs/common';
import { IsUUID } from 'class-validator';
class FindUserDto {
@IsUUID()
id: string;
}
@Controller('users')
export class UsersController {
@Get(':id')
findOne(@Param('id', new ValidationPipe()) id: string) {
return `User with ID: ${id}`;
}
}
Ako korisnik pošalje zahtev sa nevalidnim id (npr. nije UUID), API vraća grešku:
{
"statusCode": 400,
"message": ["id must be a UUID"],
"error": "Bad Request"
}
ValidatePipe na nivou metode
Dekorator @UsePipes se koristi da primeni ValidationPipe na nivou metode kontrolera.
import { Controller, Post, Body, UsePipes, ValidationPipe } from '@nestjs/common';
import { IsString, IsInt, Min } from 'class-validator';
class CreateUserDto {
@IsString()
name: string;
@IsInt()
@Min(1)
age: number;
}
@Controller('users')
export class UsersController {
@Post()
@UsePipes(ValidationPipe)
createUser(@Body() createUserDto: CreateUserDto) {
return `User created with name: ${createUserDto.name}, age: ${createUserDto.age}`;
}
}
Validan zahtev:
{
"name": "John",
"age": 25
}
Nevalidan zahtev:
{
"name": "",
"age": -1
}
API odgovara sa greškom:
{
"statusCode": 400,
"message": [
"name should not be empty",
"age must not be less than 1"
],
"error": "Bad Request"
}
ValidatePipe na nivou klase
Dekorator @UsePipes može se primeniti na klasu kontrolera, čime se ValidationPipe primenjuje na sve metode u okviru te klase.
import { Controller, Post, Body, UsePipes, ValidationPipe } from '@nestjs/common';
import { IsString, IsInt, Min } from 'class-validator';
class CreateUserDto {
@IsString()
name: string;
@IsInt()
@Min(1)
age: number;
}
@UsePipes(ValidationPipe)
@Controller('users')
export class UsersController {
@Post()
createUser(@Body() createUserDto: CreateUserDto) {
return `User created with name: ${createUserDto.name}, age: ${createUserDto.age}`;
}
@Post('update')
updateUser(@Body() updateUserDto: CreateUserDto) {
return `User updated with name: ${updateUserDto.name}, age: ${updateUserDto.age}`;
}
}
Prednost: Svi zahtevi u okviru kontrolera automatski prolaze validaciju, što smanjuje potrebu za pojedinačnim deklarisanjem.
ValidatePipe na globalnom nivou
ValidationPipe se može registrovati kao globalni Pipe, čime se primenjuje na sve rute u aplikaciji.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Globalna registracija ValidationPipe-a
app.useGlobalPipes(new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
}));
await app.listen(3000);
}
bootstrap();
Opcije za ValidationPipe:
- whitelist: true – Automatski uklanja svojstva koja nisu definisana u DTO klasi.
- forbidNonWhitelisted: true – Baca grešku ako se pojave nepoznata svojstva.
- transform: true – Transformiše ulazne podatke u instance DTO klasa.
Prednost: Validacija se primenjuje automatski na sve zahteve, bez potrebe za deklarisanjem u svakom kontroleru.
Custom pipes
Ako su vaši zahtevi specifični, onda je nepohodno kreirati “custom pipe-ove”. Za kreiranje pipes, je potrebno:
- Kreirate novu klasu koja implementira PipeTransform interfejs.
- Implementirate metodu transform(), koja prima dva parametra:
- value: Ulazna vrednost koja dolazi iz zahteva.
- metadata: Informacije o vrednosti (opciono, sadrži podatke o tipu i dekoratorima).
Primer 1: Pipe za validaciju broja
Kreiramo Pipe koji proverava da li je ulazni string validan broj. Ako nije, baca grešku.
import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';
@Injectable()
export class ParseIntPipe implements PipeTransform {
transform(value: any): number {
const val = parseInt(value, 10);
if (isNaN(val)) {
throw new BadRequestException('Validation failed: Not a number');
}
return val;
}
}
Korišćenje u kontroleru:
import { Controller, Get, Param } from '@nestjs/common';
import { ParseIntPipe } from './parse-int.pipe';
@Controller('users')
export class UsersController {
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
return `User with ID ${id}`;
}
}
Ako klijent pošalje zahtev na /users/123, vrednost 123 se uspešno konvertuje u broj.
Ako pošalje /users/abc, API baca grešku:
{
"statusCode": 400,
"message": "Validation failed: Not a number",
"error": "Bad Request"
}
Primer 2: Pipe za dozvoljene vrednosti
Pipe proverava da li je vrednost iz liste dozvoljenih vrednosti.
import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';
@Injectable()
export class AllowedValuesPipe implements PipeTransform {
constructor(private readonly allowedValues: any[]) {}
transform(value: any): any {
if (!this.allowedValues.includes(value)) {
throw new BadRequestException(`Value '${value}' is not allowed.`);
}
return value;
}
}
Korišćenje u kontroleru:
import { Controller, Get, Query } from '@nestjs/common';
import { AllowedValuesPipe } from './allowed-values.pipe';
@Controller('products')
export class ProductsController {
@Get()
findByType(@Query('type', new AllowedValuesPipe(['electronics', 'furniture'])) type: string) {
return `Products of type: ${type}`;
}
}
Validan zahtev: /products?type=electronics
Nevalidan zahtev: /products?type=clothing
{
"statusCode": 400,
"message": "Value 'clothing' is not allowed.",
"error": "Bad Request"
}
Primer 3: Pipe za transformaciju u veliki tekst
Pipe transformiše string u uppercase.
import { PipeTransform, Injectable } from '@nestjs/common';
@Injectable()
export class UppercasePipe implements PipeTransform {
transform(value: string): string {
return value.toUpperCase();
}
}
Korišćenje u kontroleru:
import { Controller, Post, Body } from '@nestjs/common';
import { UppercasePipe } from './uppercase.pipe';
@Controller('messages')
export class MessagesController {
@Post()
createMessage(@Body('text', UppercasePipe) text: string) {
return `Message: ${text}`;
}
}
Ulaz: {“text”: “hello world”}
Izlaz: Message: HELLO WORLD