NestJS — Node.js للمؤسسات

كائنات نقل البيانات والتحقّق

16 دقيقة الدرس 10 من 48

كائنات نقل البيانات والتحقّق

لا تثق أبدًا بالبيانات الواردة. يُعرّف DTO (كائن نقل البيانات) الشكل الدقيق لحمولة الطلب، ويتولّى NestJS — بمساعدة class-validator وclass-transformer — التحقّق منها وتحويلها تلقائيًا قبل أن تصل إلى متحكّمك أصلًا. وهذه من أعلى ميزات الإطار قيمةً.

ما هو DTO؟

الـ DTO صنف بسيط يصف البيانات التي يقبلها المسار. استخدام صنف (لا واجهة) مقصود: الأصناف موجودة وقت التشغيل، فيستطيع NestJS قراءة مُزخرِفات التحقّق فيها.

// create-user.dto.ts import { IsString, IsEmail, MinLength, IsInt, Min } from 'class-validator'; export class CreateUserDto { @IsString() @MinLength(2) name: string; @IsEmail() email: string; @IsInt() @Min(18) age: number; }

ربط التحقّق

ثبّت المكتبتين، ثم فعّل ValidationPipe العام مرّة واحدة في main.ts:

// الطرفية npm install class-validator class-transformer // main.ts import { ValidationPipe } from '@nestjs/common'; app.useGlobalPipes(new ValidationPipe());

الآن استخدم الـ DTO كنوع لـ @Body(). أي طلب يخالف قاعدة يُرفض بـ 400 Bad Request برسالة واضحة — قبل تشغيل معالجك:

@Post() create(@Body() dto: CreateUserDto) { // dto مضمون الصحّة هنا return this.usersService.create(dto); }

مُزخرِفات التحقّق الشائعة

  • @IsString() و@IsInt() و@IsBoolean() و@IsEmail() و@IsUrl()
  • @MinLength() و@MaxLength() و@Min() و@Max()
  • @IsOptional() — تخطّي التحقّق حين يغيب الحقل
  • @IsEnum() و@IsArray() و@IsDateString()

تقوية ValidationPipe

ثلاثة خيارات تجعل التحقّق أكثر أمانًا بكثير:

app.useGlobalPipes(new ValidationPipe({ whitelist: true, // إزالة الخصائص التي بلا مُزخرِف تحقّق forbidNonWhitelisted: true, // رمي خطأ عند إرسال خصائص غير معروفة transform: true, // تحويل الحمولة تلقائيًا إلى نسخة DTO بأنواع صحيحة }));
whitelist + transform هما المزيج القوي. تُزيل whitelist بصمت الحقول غير المتوقّعة (كمهاجم يحاول ضبط isAdmin)، وتُحوّل transform الـ JSON الخام إلى نسخة DTO حقيقية بقيم مكتوبة الأنواع صحيحةً.

الكائنات المتداخلة

للتحقّق من DTOs متداخلة، علّم الخاصيّة بـ @ValidateNested() و@Type() ليعرف المُحوِّل الصنف الذي يبنيه:

import { ValidateNested } from 'class-validator'; import { Type } from 'class-transformer'; export class CreateOrderDto { @ValidateNested() @Type(() => AddressDto) address: AddressDto; }
يعمل التحقّق على الأصناف فقط، لا الواجهات. تُمحى واجهات TypeScript وقت التجميع، فلا توجد مُزخرِفاتها وقت التشغيل. استخدم دائمًا صنفًا للـ DTO.

الخلاصة

الـ DTOs أصناف تصف بيانات الطلب وتتحقّق منها بمُزخرِفات class-validator. فعّل ValidationPipe العام مع whitelist وforbidNonWhitelisted وtransform لتحقّق وتحويل أنواع آمنين وتلقائيين. تُرفض الطلبات غير الصالحة بـ 400 قبل تشغيل كودك. تاليًا ننظر في الأنابيب — الآليّة التي تشغّل هذا.