Pipes — Built-in, Custom, Validation
Pipe nima?
Tasavvur qiling: siz tog'dan oqib tushadigan suvni uyingizga olib kelmoqchisiz. Lekin o'sha suv toza emas — tosh, loy aralash. Shuning uchun quvurga filtr o'rnatiladi. Suv filtrdan o'tadi, toza holda kranigizga yetib keladi.
NestJS da Pipe aynan shu filtr. Foydalanuvchidan kelgan ma'lumot controller ga yetib borishidan oldin Pipe dan o'tadi. Pipe ikki ish qiladi:
Transformation — ma'lumotni o'zgartiradi. "42" stringni 42 songa aylantiradi.
Validation — ma'lumotni tekshiradi. Noto'g'ri bo'lsa — xato qaytaradi, controller ga yetkazmayin.
Built-in Pipes — tayyor Pipe lar
NestJS o'zi bir nechta tayyor Pipe beradi. Ularni import qilib ishlatish kifoya.
ParseIntPipe
URL parametrdan kelgan string ni number ga aylantiradi:
import { Controller, Get, Param, ParseIntPipe } from "@nestjs/common";
@Controller("users")
export class UsersController {
@Get(":id")
findOne(@Param("id", ParseIntPipe) id: number) {
return `${id}-foydalanuvchi`; // id bu yerda number
}
}
/users/42 — ishlaydi, id = 42.
/users/abc — ParseIntPipe xato qaytaradi:
{
"statusCode": 400,
"message": "Validation failed (numeric string is expected)",
"error": "Bad Request"
}
Controller ga umuman yetib bormaydi.
ParseUUIDPipe
Agar ID sifatida UUID ishlatayotgan bo'lsangiz:
@Get(':id')
findOne(@Param('id', ParseUUIDPipe) id: string) {
return `UUID: ${id}`;
}
/users/550e8400-e29b-41d4-a716-446655440000 — ishlaydi.
/users/123 — xato. UUID formatida emas.
ParseBoolPipe
@Get()
findAll(@Query('active', ParseBoolPipe) active: boolean) {
return `Faol: ${active}`;
}
/users?active=true → active = true (boolean).
/users?active=noto'g'ri → xato.
DefaultValuePipe
Query parametr kelmasа — standart qiymat beradi:
@Get()
findAll(
@Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number,
@Query('limit', new DefaultValuePipe(10), ParseIntPipe) limit: number,
) {
return `${page}-sahifa, ${limit} ta`;
}
/users — page = 1, limit = 10.
/users?page=3 — page = 3, limit = 10.
DefaultValuePipe avval standart qiymat beradi, keyin ParseIntPipe songa aylantiradi. Tartib muhim.
ValidationPipe
Oldingi darsda main.ts da global qo'ygan edik. Lekin uni alohida endpoint uchun ham ishlatish mumkin:
@Post()
create(@Body(new ValidationPipe()) createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
Pipe larni qayerga qo'yish mumkin
Pipe lar uch joyda ishlashi mumkin. Har birining o'z maqsadi bor.
Parametr darajasida — faqat bir parametrga:
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {}
Metod darajasida — butun metod uchun:
import { Post, Body, UsePipes, ValidationPipe } from "@nestjs/common";
@Post()
@UsePipes(new ValidationPipe())
create(@Body() dto: CreateUserDto) {}
Global darajasida — butun ilova uchun:
// main.ts
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
Real loyihalarda ValidationPipe ni global qo'yish eng qulay. ParseIntPipe kabilarni esa kerakli parametrga alohida.
Custom Pipe — o'zingizning Pipe
Ba'zan tayyor Pipe lar yetarli bo'lmaydi. Masalan, telefon raqamni tekshirish yoki o'zbekiston pochta indeksini validatsiya qilish — bular uchun o'z Pipe ingizni yozasiz.
CLI bilan yaratish:
nest g pipe common/pipes/phone --no-spec
--no-spec — test faylini yaratmaslik uchun. Fayl src/common/pipes/phone.pipe.ts manzilida yaratiladi.
// common/pipes/phone.pipe.ts
import {
PipeTransform,
Injectable,
ArgumentMetadata,
BadRequestException,
} from "@nestjs/common";
@Injectable()
export class PhonePipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
// Bo'shliqlarni olib tashlaymiz
const cleaned = value.replace(/\s/g, "");
// O'zbek telefon raqami formati: +998XXXXXXXXX
const phoneRegex = /^\+998[0-9]{9}$/;
if (!phoneRegex.test(cleaned)) {
throw new BadRequestException(
"Telefon raqam noto'g'ri. Format: +998XXXXXXXXX",
);
}
return cleaned; // tozalangan qiymatni qaytaramiz
}
}
PipeTransform — bu interfeys. Uni implement qilganda transform metodini yozish shart. Bu metod:
value— kelgan qiymatmetadata— qo'shimcha ma'lumot (parametr turi va h.k.)- return qilingan qiymat — keyingi bosqichga uzatiladi
Ishlatish:
@Post()
create(@Body('phone', PhonePipe) phone: string) {
return `Telefon: ${phone}`;
}
Custom Pipe — transformation misoli
Validation emas, transformation — ma'lumotni o'zgartirish uchun Pipe:
// common/pipes/trim.pipe.ts
import { PipeTransform, Injectable, ArgumentMetadata } from "@nestjs/common";
@Injectable()
export class TrimPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
// Faqat stringlarni tozalaymiz
if (typeof value !== "string") {
return value;
}
return value.trim(); // bosh va oxirdagi bo'shliqlarni olib tashlaymiz
}
}
Yoki butun object dagi barcha string maydonlarni trim qilish:
@Injectable()
export class TrimObjectPipe implements PipeTransform {
transform(value: any) {
if (typeof value !== "object" || value === null) {
return value;
}
return Object.keys(value).reduce((acc, key) => {
acc[key] =
typeof value[key] === "string" ? value[key].trim() : value[key];
return acc;
}, {});
}
}
Foydalanuvchi " Jasur " yuborsa — "Jasur" bo'lib keladi.
Pipe lar ketma-ketligi
Bir parametrga bir nechta Pipe qo'yish mumkin. Ular chapdan o'ngga ishlaydi:
@Get(':id')
findOne(
@Param('id', TrimPipe, ParseIntPipe) id: number
) {
return id;
}
Avval TrimPipe — bo'shliqlarni olib tashlaydi.
Keyin ParseIntPipe — stringni songa aylantiradi.
Xato xabarini sozlash
ParseIntPipe ning standart xato xabari inglizcha. O'zbek tilida bermoqchi bo'lsangiz:
@Get(':id')
findOne(
@Param('id', new ParseIntPipe({
exceptionFactory: () =>
new BadRequestException('ID butun son bo\'lishi kerak'),
}))
id: number,
) {
return id;
}
Hammasi birgalikda
Keling, real loyihadagi endpoint ko'ramiz — sahifalash bilan foydalanuvchilar ro'yxati:
import {
Controller,
Get,
Param,
Query,
ParseIntPipe,
DefaultValuePipe,
ParseUUIDPipe,
} from "@nestjs/common";
@Controller("users")
export class UsersController {
// Sahifalash bilan ro'yxat
@Get()
findAll(
@Query("page", new DefaultValuePipe(1), ParseIntPipe) page: number,
@Query("limit", new DefaultValuePipe(10), ParseIntPipe) limit: number,
) {
return {
page,
limit,
data: [],
};
}
// ID bilan bitta foydalanuvchi
@Get(":id")
findOne(@Param("id", ParseIntPipe) id: number) {
return { id };
}
}
Xulosa
Pipe — bu ma'lumotning "filtr va o'zgartiruvchi" si. Controller ga noto'g'ri yoki xom ma'lumot yetib bormasin deyishingiz uchun Pipe ishlatiladi.
Eslab qoling:
ParseIntPipe→ string → numberParseUUIDPipe→ UUID formatini tekshiradiParseBoolPipe→ string → booleanDefaultValuePipe→ standart qiymat beradiValidationPipe→ DTO validatsiyasi- Custom Pipe →
PipeTransformimplement qiling,transformmetodini yozing - Pipe lar chapdan o'ngga ketma-ket ishlaydi
Keyingi dars
7-dars: Exception Filters va Error Handling