التحقق من صحة البيانات في JavaScript (Node.js): Joi و Yup
في أي تطبيق ويب، خاصة على Node.js، إحدى المهام الأساسية هي فحص البيانات الواردة. بدون التحقق من الصحة، فإنك تخاطر بالحصول على أخطاء في قاعدة البيانات، أو ثغرات أمنية (حقن SQL، XSS)، أو سلوك خادم غير صحيح. في هذه المقالة، سننظر في أشهر مكتبتين للتحقق من الصحة: Joi و Yup. ستتعلم كيفية تثبيتهما، وإنشاء المخططات، ودمجها مع Express.
لماذا نحتاج إلى التحقق من الصحة على الخادم؟
التحقق من الصحة من جانب العميل (HTML5 أو JavaScript في المتصفح) أمر مريح، لكن يمكن تجاوزه بسهولة. لذلك، فإن الفحص من جانب الخادم إلزامي. فهو يضمن أن:
- أنواع البيانات تتطابق مع المتوقع (نص، رقم، مصفوفة).
- الحقول الإلزامية ليست فارغة.
- البيانات لا تتجاوز الأحجام المسموح بها.
- التنسيقات (البريد الإلكتروني، URL، رقم الهاتف) صحيحة.
مكتبة Joi
Joi هي أداة تحقق قوية من مبتكري Hapi.js. تدعم المخططات المعقدة، والرسائل المخصصة للأخطاء، والفحوصات غير المتزامنة.
التثبيت
npm install joiمثال على مخطط لتسجيل المستخدم
const Joi = require('joi');
const userSchema = Joi.object({ username: Joi.string() .alphanum() .min(3) .max(30) .required() .messages({ 'string.min': 'يجب أن يكون اسم المستخدم 3 أحرف على الأقل', 'string.max': 'يجب ألا يتجاوز اسم المستخدم 30 حرفًا' }), email: Joi.string() .email({ tlds: { allow: false } }) .required(), password: Joi.string() .pattern(new RegExp('^[a-zA-Z0-9]{8,30}$')) .required(), birth_year: Joi.number() .integer() .min(1900) .max(2024)});
// التحققapp.post('/register', (req, res) => { const { error, value } = userSchema.validate(req.body, { abortEarly: false }); if (error) { return res.status(400).json({ status: 'error', message: error.details.map(d => d.message).join(', ') }); } res.json({ status: 'success', data: value });});الإمكانيات المتقدمة لـ Joi
- التحقق من المصفوفات:
Joi.array().items(Joi.string()) - القواعد الشرطية:
.when('role', { is: 'admin', then: Joi.required() }) - الدوال المخصصة:
.custom((value, helpers) => { ... })
مكتبة Yup
Yup هي مكتبة خفيفة وبديهية، شائعة في نظام React البيئي (Formik). لكنها تعمل بشكل ممتاز على الخادم أيضًا.
التثبيت
npm install yupمثال على مخطط لتسجيل الدخول
const yup = require('yup');
const loginSchema = yup.object().shape({ email: yup.string() .email('أدخل بريدًا إلكترونيًا صحيحًا') .required('البريد الإلكتروني مطلوب'), password: yup.string() .min(8, 'يجب أن تكون كلمة المرور 8 أحرف على الأقل') .max(50) .required('كلمة المرور مطلوبة')});
// Middleware لـ Expressasync function validateLogin(req, res, next) { try { const validatedData = await loginSchema.validate(req.body, { abortEarly: false }); req.validatedData = validatedData; next(); } catch (err) { res.status(400).json({ status: 'error', errors: err.errors // مصفوفة رسائل الأخطاء }); }}
app.post('/login', validateLogin, (req, res) => { res.json({ status: 'success', data: req.validatedData });});ميزات Yup
- التحقق غير المتزامن افتراضيًا (يُرجع Promise).
- تحويل البيانات:
.transform((value) => value.tr