NestJS / الأساسي: الوحدات وعقود الطلب / الدرس 5
التحقق من DTO وعمليات pipe والقيم الفعلية
ابن عقد إدخال وقت التشغيل بدلاً من افتراض أن تعليقات TypeScript تتحقق من الوارد.
في هذه الصفحة
أهداف الدرس
- افصل التحليل والتحويل والتحقق وتفويض المجال.
- اشرح القائمة المسموحة والرفض الصريح للحقل المجهول.
تمحى الأنواع وتبقى قيم الطلب
تصف فئة DTO الإدخال، ولا يتحقق تعليق الخاصية وحده من JSON أو يحول الاستعلام لعدد. تعمل pipe عند حد وسيط الطلب لتحول أو ترفض. يثبت التحليل والبنية وحدود المجال والتفويض حقائق مختلفة. اختر نهج التحقق واربطه بالتطبيق. يوثق Nest 12 بدائل بمخططات، ولا يفرض إرفاق بيانات المخطط شيئاً دون pipe المناسبة. يختار الدرس نهج الفئة والمزخرف مثالاً صريحاً. لا تجعل النوع المولد أو نجاح الترجمة دليلاً على أن قيمة وردت من الشبكة تلبي شرط الطول أو المفردات المسموحة.
راجع خيارات التحقق كسلوك عام
يفترض الجزء مزخرفات class-validator وValidationPipe مضبوطة. تزيل whitelist خصائص بلا بيانات تحقق مناسبة وقد ترفضها forbidNonWhitelisted بدلاً من إسقاطها. تسمح transform بالتحويل وفق الإعداد ولا تبرر إكراهاً ضمنياً دون اختبار. تهم الفئة الفعلية وبيانات الانعكاس؛ فلا تعوضهما واجهة أو استيراد نوع فقط. لم يترجم المثال أو تثبت الحزمة. اختبر المجهول والمفقود وnull والنوع المخالف في موائم معزول. اختيار الإسقاط بدلاً من الرفض قرار واجهة يغير ما يراه العميل ويجب ألا ينتج عرضياً من افتراض غير موثق.
export class CreateCourseDto {
@IsString()
@Length(1,60)
title!: string;
}
// Application configuration fragment:
app.useGlobalPipes(new ValidationPipe({
whitelist:true,forbidNonWhitelisted:true,transform:true
}));
يفترض الاستيراد والبيانات والتطبيق. تحتاج الخيارات تسجيل pipe فعلياً ولا تنفذ هنا.
وضح وجود حقول التحديث والإسقاط
قد يعني حذف حقل تحديث الإبقاء، وnull المسح، والفارغ قيمة مقدمة صحيحة أو مخالفة وفق العقد. تجنب فحص الصدق الذي يدمجها. ليست القائمة تفويضاً؛ فقد يمنع حقل حالة مسموح لهذه الهوية أو المرحلة. ابن إدخالاً ضيقاً بعد التحقق ولا تنسخ الخصائص للكيان. حدد إزالة الفراغات وعد Unicode، ووافق توقع العميل مع القيمة المعتمدة المعادة. لا يصح أن يفهم العميل غياب العضو حفظاً ثم يحوله موائم إلى null فيمسح بيانات لم يقصد مسحها.
اختبر قاعدة فعلية ضيقة مستقلة
يطلب المحقق كائناً بعنوان سلسلة ويرفض المجهول، ثم يزيل الفراغات ويعد من نقطة Unicode إلى ستين. يختلف العد عن المحرف المرئي وبايت التخزين فهو اتفاق عينة. لا يحاكي ValidationPipe أو class-validator. يوضح التطبيع والرفض قبل أي كتابة. يسهل فصل القاعدة اختبار حدود متعددة اللغات، ويبقى على موائم Nest إثبات القيم التي يمررها وربط فشله بأمان. لا تنقل نجاح التأكيد المحلي إلى ادعاء أن global pipe سجلت أو أن الاستثناء العام يخفي تفاصيل المصدر.
function courseInput(value) {
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("INVALID_INPUT");
if (Object.keys(value).some(k => k !== "title")) throw new Error("UNKNOWN_FIELD");
if (typeof value.title !== "string") throw new Error("INVALID_TITLE");
const title=value.title.trim();
if ([...title].length < 1 || [...title].length > 60) throw new Error("INVALID_TITLE");
return {title};
}
console.assert(courseInput({title:" Modules "}).title === "Modules");
let denied=false; try {courseInput({title:"X",owner:"other"});} catch {denied=true;}
console.assert(denied);
يزيل فراغات العنوان ويرفض owner المجهول دون تشغيل pipe أو مزخرف تحقق أو دورة طلب Nest.
تحقق من الموائم والمجال منفصلين
استخدم pipe معامل حيث توضح القصد وطبق العام بقصد ولا تفترض وراثة كل سياق له. قد لا تعيد وحدة اختبار إعداد الإقلاع الإنتاجي. تحقق من السلاسل والتكرار والجسم المفقود والعدد المخالف عبر الموائم المختار. أكد حقول الخطأ وعدم كتابة الرفض. يشغل المقرر المحقق فقط ولا يترجم DTO أو يختبر التحويل أو البديل بالمخطط أو HTTP. يحفظ التقرير هذا القيد حتى لا يعد نجاح اختبار مجال إثبات حماية حد النقل الذي قد يظل غير مربوط أصلاً.
الأخطاء الشائعة وإصلاحها
يقبل تعليق DTO إدخالاً مخالفاً
- لماذا يحدث؟
- اعتبرت الأنواع الثابتة سياسة تحقق مربوطة فعلياً وقت التشغيل.
- كيف تصلحه؟
- سجل pipe المختارة وفئة DTO الفعلية أو المخطط المختار بصورة صحيحة.
- كيف تتجنب تكراره؟
- مرر إدخالاً فعلياً عبر موائم الطلب المركب في الاختبار.
يصل owner مجهول للتخزين
- لماذا يحدث؟
- نسخ الإدخال كله إلى الكيان دون عقد ضيق متحقق منه.
- كيف تصلحه؟
- ارفض الحقول أو أسقطها وفق السياسة، ثم اختر حقول إدخال المجال.
- كيف تتجنب تكراره؟
- أكد أن الحقول الحساسة المجهولة لا تستطيع التسبب في كتابة.
تمسح null حقلاً أريد إبقاؤه
- لماذا يحدث؟
- دمج غياب عضو التحديث مع وجوده بقيمة null صريحة.
- كيف تصلحه؟
- احفظ وجود العضو ووثق الفرق بين الإبقاء على القيمة ومسحها.
- كيف تتجنب تكراره؟
- اختبر العضو المحذوف وnull والقيمة الملموسة كل حالة مستقلة.
اختبر فهمك
1. هل تفرض whitelist ما إذا كان المستخدم يحق له نشر مقرر؟
اعرض الحل المشروح
لا. تضبط whitelist بنية الإدخال المقبولة وفق بيانات التحقق. وقد يمثل حقل معروف فعلاً محظوراً على هذا المستدعي أو غير مسموح به في مرحلة سير العمل الحالية. طبق تفويض المجال المشترك بعد التحقق من الإدخال وقبل الأثر. اختبر إدخالاً معيباً وانتقال حالة صحيح البنية لكنه غير مفوض، لأنهما يختبران حدين مختلفين.
2. لماذا لا تصلح واجهة TypeScript وحدها DTO للتحقق وقت التشغيل؟
اعرض الحل المشروح
تمحى الواجهة وقت التشغيل، فلا تقدم بيانات الفئة التي يحتاجها مسار التحقق المختار القائم على المزخرفات. استخدم الفئة الفعلية والاستيرادات الصحيحة، أو اختر وسجل بديلاً قائماً على مخطط بقصد واضح. تحقق من إعداد pipe كاملاً بدلاً من افتراض أن تطابق الشكل في الأنواع الثابتة ينفذ التحقق من القيم الواردة.
أهم ما تعلمته
- التحقق الفعلي وصلاحية العمل قراران منفصلان.
- التحويل والمجهول ووجود الحقل جزء من العقد العام.