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

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

العملاء مكتوبو الأنواع

يوفّر DaloyJS طريقتين اثنتين لاستدعاء واجهتك البرمجية بأمان أنواع كامل. استخدم ما يناسب المستهلك لديك.

1. العميل مكتوب الأنواع داخل العملية (دون توليد شيفرة)

لمستهلكي TypeScript في المستودع الأحادي نفسه (الاختبارات، والأدوات الداخلية، وإجراءات الخادم في Next.js):

ts
import { createInProcessClient } from "@daloyjs/core/client";
import { app } from "./app.js";

const client = createInProcessClient(app);

const r = await client.getBookById({ params: { id: "1" } });
//    ^? { status: 200; body: { id: string; title: string } }
//      | { status: 404; body: ProblemJson }

if (r.status === 200) {
  console.log(r.body.title); // string، مكتوب الأنواع بالكامل
}

يُفهرس العميل حسب operationId، ويعيد اتحادًا مميَّزًا من {status, body, headers}، ويستنتج كل شيء من تعريف المسار نفسه. دون خطوة بناء.

معاملات المسار

تُستبدل معاملات المسار بمقطع كامل، فلا يطابق :id أبدًا داخل :idx، وتُرمَّز كل قيمة بالنسبة المئوية في مقطعها الخاص. ومنذ 1.3.7 ترمي الدالة المولَّدة TypeError قبل إرسال أي طلب، عندما يكون المعامل مفقودًا أو فارغًا أو . أو ... فتحليل URL سيحل مقطع النقطة (حتى بصيغة %2E%2E) ويغيّر هدف الاستدعاء بصمت، فيحوّل مثلًا DELETE /orgs/:org/members/.. إلى DELETE /orgs/:org. وتقبل مسارات أحرف البدل (*path، أو * مجرد باسم wildcard) قيمة مفصولة بـ /؛ ويُرمَّز كل مقطع ويُفحص بالطريقة نفسها.

ts
// app.get("/files/*path", { operationId: "getFile", ... })
await client.getFile({ params: { path: "docs/guide.md" } }); // GET /files/docs/guide.md

await client.getBookById({ params: { id: ".." } });
// TypeError: Invalid path parameter "id" for /books/:id: empty and "."/".." segments are not allowed

2. SDK مع Hey API (عبر اللغات والمستودعات، وقت البناء)

للمستهلكين خارج المستودع الأحادي أو بلغات أخرى، ولّد SDK لـ fetch مكتوب الأنواع بالكامل باستخدام @hey-api/openapi-ts.

خط توليد الشيفرة
  1. 01المساراتapp.route(...)
  2. 02generateOpenAPI@daloyjs/core/openapi
  3. 03openapi.jsonمواصفة OpenAPI 3.1 على القرص
  4. 04openapi-tsمولّد Hey API
  5. 05SDK مكتوب الأنواعsdk.gen.ts · types.gen.ts
  6. 06المستهلكاستدعاءات fetch مكتوبة الأنواع بالكامل
يشغّل pnpm gen السلسلة كاملة: يحفظ المواصفة من مساراتك، ثم يدع Hey API يحوّلها إلى SDK لـ fetch مكتوب الأنواع. أعد تشغيله كلما تغيّر مسار فيبقى العميل متطابقًا مع العقد.
bash
pnpm add -D @hey-api/openapi-ts prettier
ts
// openapi-ts.config.ts
import { defineConfig } from "@hey-api/openapi-ts";

export default defineConfig({
  input: "./generated/openapi.json",
  output: { path: "./generated/client", postProcess: ["prettier"] },
  plugins: ["@hey-api/client-fetch", "@hey-api/typescript", "@hey-api/sdk"],
});
json
// package.json
"scripts": {
  "gen:openapi": "node scripts/dump-openapi.ts",
  "gen:client":  "openapi-ts",
  "gen":         "pnpm gen:openapi && pnpm gen:client"
}
bash
pnpm gen
# يكتب:
#   generated/openapi.json
#   generated/client/{client.gen.ts, sdk.gen.ts, types.gen.ts, index.ts}

استخدام SDK المولَّد

ts
import { client } from "./generated/client/client.gen.js";
import { getBookById } from "./generated/client/sdk.gen.js";

client.setConfig({ baseUrl: "https://api.example.com" });

const { data, error } = await getBookById({ path: { id: "1" } });
if (error) console.error(error);
else if (data) console.log(data.title);

أيهما أستخدم؟

حالة الاستخدامالاختيار
مستدعٍ بلغة TypeScript في المستودع نفسه (الاختبارات، الأدوات الداخلية)createInProcessClient
تطبيق ويب أو حزمة React Native للهاتف في مستودع منفصلSDK مع Hey API
مستهلك بغير TypeScript (Python، Swift، Kotlin)مستند OpenAPI + المولّد الذي يفضّلونه
SDK عام لأطراف ثالثةSDK مع Hey API، منشور كحزمة مستقلة

قادم من ts-rest؟

ts-rest مكتبة شائعة قائمة على العقود تمنحك أنواع TypeScript متكاملة دون توليد شيفرة عبر مشاركة عقد (initContract) بين خادم قائم على المحوّلات (Express، Fastify، NestJS، Next.js) وعميل fetch (initClient). إن كنت تحب هذا النموذج، فسيبدو DaloyJS مألوفًا، مع فرقين.

أولًا، في DaloyJS تعريف المسار هو العقد، فلا يوجد كائن عقد منفصل يجب إبقاؤه متزامنًا. ويمنح createClient داخل العملية الموضح أعلاه التجربة نفسها دون توليد شيفرة ومع أنواع مشتركة لمستدعي TypeScript في المستودع نفسه.

ثانيًا، أمان الأنواع في ts-rest خاص بـ TypeScript ويتطلب أن يستورد العميل العقد. أما DaloyJS فيُصدر مواصفة OpenAPI 3.1 من الدرجة الأولى وSDK مع Hey API من المسارات نفسها، لذا فالمستهلكون الذين لا يستطيعون استيراد أنواعك (مستودعات أخرى، لغات أخرى، حزم SDK عامة) مشمولون أيضًا. في ts-rest، يُعد OpenAPI إضافة اختيارية (@ts-rest/open-api). وDaloyJS هو أيضًا الخادم وبيئة التشغيل نفسها، قابل للنقل عبر Node وBun وDeno وCloudflare وVercel، وليس طبقة أنواع مركّبة على إطار منفصل.

ts-restDaloyJS
مصدر العقدكائن initContract منفصلتعريف المسار نفسه
عميل مكتوب الأنواع دون توليد شيفرةنعم (initClient، TypeScript فقط)نعم (createClient، TypeScript فقط)
عملاء عبر اللغات والمستودعاتإضافة OpenAPI (@ts-rest/open-api)OpenAPI 3.1 + SDK مع Hey API، من الدرجة الأولى
الخادممحوّل على Express / Fastify / NestJS / Next.jsمدمج، وقابل للنقل بين بيئات التشغيل
التحقق في وقت التشغيلStandard Schema (Zod / Valibot / ArkType)Standard Schema (Zod / Valibot / ArkType / TypeBox)
الافتراضيات الأمنيةأحضرها بنفسكالترويسات وحدود الجسم مفعّلة افتراضيًا؛ وCSRF وتحديد المعدل على بُعد سطر واحد

تحتاج إلى عقد أكبر للتحقق من مخرجات المولّد لديك؟ استخدم عرض REST الوهمي الكبير (بالإنجليزية) كحالة اختبار ضغط بدلًا من تطبيق تعليمي بسيط.

آخر تحديث: