انتقل إلى المحتوى
التوثيق بالعربية

هذه ترجمة للصفحة الأصلية بالإنجليزية. عند وجود أي اختلاف، تُعتمد النسخة الإنجليزية.

التحقق

يتحقق DaloyJS من المدخلات عبر Standard Schema، وهي واجهة صغيرة تعرضها أدوات تحقق مثل Zod وValibot وArkType، وكذلك TypeBox عبر محوّل Standard Schema. اختر أداة التحقق التي تناسب مشروعك؛ فعقد DaloyJS واحد في كل الحالات.

واجهة واحدة وأربع أدوات تحقق
عقد الإطارStandard Schemaالخاصية ~standard
الافتراضيZodz.object({ ... })
قابل لإزالة الشيفرة غير المستخدمةValibotv.object({ ... })
ArkTypetype({ ... })
TypeBoxعبر محوّل
تعرض كل أداة تحقق الخاصية ~standard نفسها، لذا يستنتج DaloyJS أنواع المعالج، ويولّد OpenAPI، ويعيد أخطاء problem+json عبر مسار واحد في الإطار.

ما الذي يُتحقق منه

يمكنك لكل مسار التصريح بمخططات لما يلي:

  • request.params: معاملات المسار المفكوكة الترميز. تبدأ كنصوص؛ حوّلها في مخططك إن أردت أرقامًا أو UUID أو قيمًا تعدادية.
  • request.query: قيم سلسلة الاستعلام. تصبح المفاتيح المكررة مصفوفات قبل التحقق.
  • request.headers: ترويسات الطلب بأسماء بأحرف صغيرة.
  • request.body: أجسام الطلبات المحللة. لا يُقرأ الجسم إلا عندما يصرّح المسار بمخطط للجسم.
  • responses[status].body: أجسام استجابة مكتوبة الأنواع ومتحقق منها.

تُسقط سلاسل الاستعلام وحقول النماذج وحقول multipart مفاتيح تلويث النماذج الأولية مثل __proto__ وconstructor وprototype قبل التحقق.

قيّد الحقول الرقمية (المال والكميات والمعرّفات)

يقبل z.number() المجرد القيمة 1e308، و-Infinity بعد أخطاء التحويل، وقيمًا أخرى سليمة لأعداد IEEE العشرية لكنها كارثية للمال أو المخزون أو ترقيم الصفحات. ضع دائمًا حدودًا خاصة بالمجال على حقول الطلب الرقمية:

ts
import { z } from "zod";

// المال: قيمة منتهية وموجبة ومحدودة بسقف تجاري.
const Money = z.number().finite().positive().max(1_000_000);

// الكميات: أعداد صحيحة في نطاق معقول.
const Qty = z.number().int().positive().max(10_000);

// استخدم coerce فقط عندما تصل القيمة نصًا (استعلام أو نموذج).
const Page = z.coerce.number().int().min(1).max(1000);

// الأجسام الصارمة ترفض الحقول الإضافية في الإسناد الجماعي.
const CreatePayment = z
  .object({ amount: Money, currency: z.enum(["USD", "EUR", "NOK"]) })
  .strict();

يرفض Zod 4 بالفعل NaN والأرقام غير المنتهية في z.number() في حالات كثيرة، لكن السقف (.max()) وقيد الإشارة (.positive() / .nonnegative()) يظلان خط دفاعك الأخير ضد احتيال المبالغ المستردة والفيض العددي. اقرن ذلك بمخططات الاستجابة حتى لا تتسرب الحقول الحساسة إلى الخارج أبدًا.

مثال متكامل

ts
import { App } from "@daloyjs/core";
import { z } from "zod";

const CreateLineItem = z.object({
  sku: z.string().min(1),
  qty: z.coerce.number().int().positive().max(10_000),
});

const LineItem = z.object({
  id: z.string(),
  tenantId: z.string(),
  sku: z.string(),
  qty: z.number().int().positive(),
  dryRun: z.boolean(),
});

export const app = new App().post(
  "/orders/:orderId/items",
  {
    operationId: "createOrderItem",
    request: {
      params: z.object({ orderId: z.uuid() }),
      query: z
        .object({
          dryRun: z
            .enum(["true", "false"])
            .transform((value) => value === "true")
            .optional(),
        })
        .optional(),
      headers: z.object({ "x-tenant": z.string().min(1) }),
      body: CreateLineItem,
    },
    responses: {
      201: { description: "Created", body: LineItem },
      422: { description: "Validation error" },
    },
  },
  async ({ params, query, headers, body }) => {
    const tenantId = headers["x-tenant"];
    const dryRun = query?.dryRun ?? false;

    return {
      status: 201,
      body: {
        id: `${params.orderId}:li_1`,
        tenantId,
        ...body,
        dryRun,
      },
    };
  },
);

اختر أداة التحقق

  • Zod (بالإنجليزية): الخيار الافتراضي لمعظم الفرق. واجهة قابلة للتسلسل، ومنظومة كبيرة، وسهلة التعلم.
  • Valibot (بالإنجليزية): معيارية وقابلة لإزالة الشيفرة غير المستخدمة. ممتازة لبيئات الحافة (edge) وللعقود التي تُشحن إلى المتصفح.

تعمل أيضًا المخططات المتوافقة مع ArkType وTypeBox عندما تعرض الخاصية ~standard نفسها، لكن DaloyJS لا يوفّر توثيقًا وقوالب رسمية إلا لـ Zod وValibot.

مقارنة جنبًا إلى جنب

ts
// Zod
import { z } from "zod";
const Body = z.object({
  sku: z.string(),
  qty: z.number().int().positive(),
});

// Valibot
import * as v from "valibot";
const Body = v.object({
  sku: v.string(),
  qty: v.pipe(v.number(), v.integer(), v.minValue(1)),
});

// ArkType
import { type } from "arktype";
const Body = type({ sku: "string", qty: "1<=number.integer" });

// TypeBox
import { Type } from "@sinclair/typebox";
const Body = Type.Object({ sku: Type.String(), qty: Type.Integer({ minimum: 1 }) });
// غلّفه بمحوّل Standard Schema الخاص بمشروعك قبل تمريره إلى DaloyJS.

بمجرد أن يعرض المخطط ~standard، يستنتج DaloyJS أنواع المعالج، ويولّد OpenAPI، ويعيد أخطاء problem+json بالطريقة نفسها أيًا كانت أداة التحقق التي أنتجته.

الأخطاء

حلّل، ثم تفرّع حسب النتيجة
  1. غير موثوقالطلب الخامparams · query · headers · body
  2. standard schemaتحليل المخططvalidate(schema, input)
  3. عند الفشل422 problem+jsonerrors: [{ path, message }]
  4. عند النجاحمعالج مكتوب الأنواعctx.body / params / query / headers
يعمل كل مخطط مصرّح به قبل معالجك. المدخلات غير الصالحة لا تصل أبدًا إلى شيفرة المعالج، بل تنتهي مبكرًا باستجابة 422 وفق RFC 9457. أما المدخلات الصالحة فتصل مكتوبة الأنواع بالكامل.

عند المدخلات غير الصالحة، يعيد DaloyJS 422 Unprocessable Entity بصيغة problem+json وفق RFC 9457، مع مصفوفة errors تحتوي على سجلات path وmessage لكل مشكلة. لا تكتب معالج أخطاء لهذا، فهو مدمج. راجع الأخطاء وproblem+json.

التحقق من الاستجابات

عند التصريح بمخطط استجابة، يتحقق DaloyJS من القيمة التي يعيدها المعالج قبل تسلسلها. والقيمة المتحقق منها هي ما يُرسل عبر الشبكة، لذا فإن مخططات الكائنات التي تحذف المفاتيح غير المعروفة تمنع أيضًا تسرب الحقول غير المصرّح بها إلى العملاء. إذا فشل التحقق، يتلقى العميل في الإنتاج استجابة مشكلة 500 منقّحة.

حدود الجسم وأنواع المحتوى

يحدّ خيار التطبيق bodyLimitBytes (الافتراضي 1 MiB) من قيمة Content-Length المعلنة ومن الحجم المتدفق لكل جسم طلب -> 413. ومنذ 1.5.4 ينطبق هذا على كل مسار، بما في ذلك الأجسام التي يقرؤها المعالج بنفسه من ctx.request؛ ويُفحص الحد بشكل كسول، عند قراءة الجسم.

عندما يصرّح المسار بـ request.body، يفرض DaloyJS أيضًا ما يلي:

  • مطابقة Content-Type لقائمة accepts الخاصة بالمسار، أو لـ allowedContentTypes العامة إن ضُبطت -> 415.
  • أنواع الأجسام المقبولة افتراضيًا: application/json وapplication/x-www-form-urlencoded وmultipart/form-data.
  • تحليل آمن من تلويث النماذج الأولية لـ JSON وسلاسل الاستعلام ونماذج urlencoded ونماذج multipart.

تُحلَّل أجسام JSON إلى كائنات، وأجسام urlencoded عبر URLSearchParams، وأجسام multipart عبر واجهة المنصة Request.formData(). وإذا فعّلت لمسار ما نوع وسائط نصيًا مخصصًا، يمرر DaloyJS النص المفكوك إلى مخطط الجسم لديك.

ts
app.post(
  "/legacy-form",
  {
    operationId: "legacyForm",
    accepts: ["application/x-www-form-urlencoded"],
    request: {
      body: z.object({
        email: z.email(),
        qty: z.coerce.number().int().positive(),
      }),
    },
    responses: {
      200: { description: "ok", body: z.object({ ok: z.boolean() }) },
    },
  },
  async ({ body }) => ({ status: 200, body: { ok: body.qty > 0 } }),
);

المزج بين أدوات التحقق

يمكنك المزج بينها لكل مسار. مخطط Zod في ملف ومخطط Valibot في ملف آخر كلاهما صالح، وهذا مفيد عند ترحيل قاعدة شيفرة قائمة أو عند استهلاك مخططات من حزمة مشتركة.

آخر تحديث: