بناء واجهات برمجة تطبيقات خلفية سحابية آمنة الأنواع مع Encore.ts: من الصفر إلى الإنتاج

إطار العمل الخلفي الخاص بك يجب أن يدير البنية التحتية، وليس العكس. Encore.ts هو إطار عمل TypeScript الخلفي الذي يمنحك واجهات برمجة تطبيقات آمنة الأنواع وتوفير تلقائي للبنية التحتية ومراقبة مدمجة — كل ذلك دون كتابة سطر واحد من Terraform أو تكوين Docker. في هذا الدرس، ستبني واجهة برمجة تطبيقات كاملة لإدارة المهام من الصفر.
ما ستتعلمه
في نهاية هذا الدرس، ستكون قادراً على:
- إعداد مشروع Encore.ts مع TypeScript
- تعريف نقاط نهاية API آمنة الأنواع مع التحقق التلقائي من الطلبات/الاستجابات
- إنشاء وإدارة قواعد بيانات SQL مع عمليات الترحيل
- تنفيذ نظام الرسائل pub/sub بين الخدمات
- جدولة مهام cron للعمليات المتكررة
- استخدام المراقبة المدمجة في Encore (التتبع والسجلات والمقاييس)
- النشر في السحابة مع التوفير التلقائي للبنية التحتية
المتطلبات المسبقة
قبل البدء، تأكد من أن لديك:
- Node.js 18+ مثبت (
node --version) - خبرة في TypeScript (الأنواع، الأنماط العامة، async/await)
- مفاهيم أساسية عن واجهات REST API (طرق HTTP، رموز الحالة، JSON)
- محرر أكواد — يُنصح بـ VS Code أو Cursor
- حساب Encore (الطبقة المجانية متاحة على encore.dev)
لماذا Encore.ts؟
يحتوي نظام TypeScript الخلفي على العديد من الخيارات — Express وFastify وHono وNestJS — فلماذا نختار Encore؟ إليك ما يميزه:
| الميزة | Encore.ts | Fastify | NestJS | Hono |
|---|---|---|---|---|
| أمان الأنواع | شامل، وقت التجميع | يدوي مع المخططات | مبني على المُزخرفات | يدوي |
| البنية التحتية | توفير تلقائي | يدوي | يدوي | يدوي |
| قاعدة البيانات | ترحيل مدمج | ORM خارجي | ORM خارجي | خارجي |
| Pub/Sub | بدائي مدمج | مكتبة خارجية | وحدة خارجية | غير مضمن |
| مهام Cron | بدائي مدمج | مُجدول خارجي | مُجدول خارجي | غير مضمن |
| المراقبة | تتبع تلقائي | إعداد يدوي | إعداد يدوي | يدوي |
| التطوير المحلي | محاكاة سحابية كاملة | Docker يدوي | Docker يدوي | يدوي |
يتبنى Encore نهجاً مختلفاً جذرياً: أنت تُعلن عن البنية التحتية التي تحتاجها في كود TypeScript الخاص بك، ويقوم Encore بتوفيرها تلقائياً — سواء محلياً للتطوير أو في السحابة للإنتاج. لا Terraform، لا ملفات Docker Compose، لا بيانات Kubernetes.
الخطوة 1: تثبيت CLI Encore وإنشاء مشروع
أولاً، قم بتثبيت CLI Encore:
# macOS
brew install encoredev/tap/encore
# Linux
curl -L https://encore.dev/install.sh | bash
# Windows (WSL2)
curl -L https://encore.dev/install.sh | bashتحقق من التثبيت:
encore versionالآن أنشئ مشروعاً جديداً:
encore app create task-api --example=ts/empty
cd task-apiهذا ينشئ مشروع Encore.ts بسيط. لنلقِ نظرة على الهيكل:
task-api/
├── encore.app # تكوين تطبيق Encore
├── package.json
├── tsconfig.json
└── ... (ملفات بداية بسيطة)
يحتوي ملف encore.app على معرّف التطبيق والتكوين. على عكس الأطر التقليدية، لا يوجد ملف index.ts أو تهيئة خادم — يكتشف Encore خدماتك تلقائياً.
الخطوة 2: إنشاء أول خدمة ونقطة نهاية API
في Encore، الخدمة هي ببساطة مجلد يحتوي على ملف encore.service.ts. لننشئ خدمة إدارة المهام:
mkdir taskأنشئ تعريف الخدمة:
// task/encore.service.ts
import { Service } from "encore.dev/service";
export default new Service("task");الآن أنشئ نقاط نهاية API:
// task/task.ts
import { api } from "encore.dev/api";
// تعريف واجهة المهمة
interface Task {
id: number;
title: string;
description: string;
completed: boolean;
createdAt: string;
}
// تخزين في الذاكرة (سنضيف قاعدة بيانات لاحقاً)
let tasks: Task[] = [];
let nextId = 1;
// إنشاء مهمة جديدة
export const create = api(
{ expose: true, method: "POST", path: "/tasks" },
async (req: { title: string; description: string }): Promise<Task> => {
const task: Task = {
id: nextId++,
title: req.title,
description: req.description,
completed: false,
createdAt: new Date().toISOString(),
};
tasks.push(task);
return task;
}
);
// عرض جميع المهام
export const list = api(
{ expose: true, method: "GET", path: "/tasks" },
async (): Promise<{ tasks: Task[] }> => {
return { tasks };
}
);
// الحصول على مهمة بالمعرّف
export const get = api(
{ expose: true, method: "GET", path: "/tasks/:id" },
async (req: { id: number }): Promise<Task> => {
const task = tasks.find((t) => t.id === req.id);
if (!task) {
throw new Error(`المهمة ${req.id} غير موجودة`);
}
return task;
}
);لاحظ شيئاً مهماً: لا يوجد إعداد خادم، لا تكوين middleware، لا تسجيل مسارات. أنت تُعرّف الدوال فقط ويتولى Encore الباقي. توفر دالة api():
- التحقق التلقائي من الطلبات — إذا كان حقل مطلوب مفقوداً، يُرجع Encore خطأ 400
- معاملات المسار الآمنة — يتم تحليل
:idتلقائياً كرقم - التسلسل التلقائي — يتم تحويل نوع الإرجاع إلى JSON
شغّل خادم التطوير:
encore runيبدأ Encore بيئة تطوير محلية مع لوحة تحكم مدمجة على http://localhost:9400. يمكنك اختبار API الخاص بك:
curl -X POST http://localhost:4000/tasks \
-H "Content-Type: application/json" \
-d '{"title": "تعلم Encore", "description": "بناء واجهة برمجة تطبيقات للمهام"}'الخطوة 3: إضافة قاعدة بيانات PostgreSQL
التخزين في الذاكرة كافٍ للنماذج الأولية، لكن لنضف قاعدة بيانات حقيقية. مع Encore، لا تحتاج لتثبيت PostgreSQL أو كتابة ملفات Docker Compose — فقط أعلن عن قاعدة البيانات في الكود:
// task/db.ts
import { SQLDatabase } from "encore.dev/storage/sqldb";
// الإعلان عن قاعدة البيانات — يوفرها Encore تلقائياً
const db = new SQLDatabase("taskdb", {
migrations: "./migrations",
});
export default db;أنشئ مجلد عمليات الترحيل وأول ترحيل:
mkdir -p task/migrations-- task/migrations/001_create_tasks.up.sql
CREATE TABLE tasks (
id BIGSERIAL PRIMARY KEY,
title TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
completed BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_tasks_completed ON tasks(completed);حدّث API لاستخدام قاعدة البيانات:
// task/task.ts
import { api } from "encore.dev/api";
import db from "./db";
interface Task {
id: number;
title: string;
description: string;
completed: boolean;
createdAt: string;
}
interface CreateParams {
title: string;
description: string;
}
interface ListResponse {
tasks: Task[];
}
// إنشاء مهمة جديدة
export const create = api(
{ expose: true, method: "POST", path: "/tasks" },
async (req: CreateParams): Promise<Task> => {
const row = await db.queryRow`
INSERT INTO tasks (title, description)
VALUES (${req.title}, ${req.description})
RETURNING id, title, description, completed, created_at
`;
return rowToTask(row!);
}
);
// عرض جميع المهام
export const list = api(
{ expose: true, method: "GET", path: "/tasks" },
async (): Promise<ListResponse> => {
const rows = await db.query`
SELECT id, title, description, completed, created_at
FROM tasks
ORDER BY created_at DESC
`;
const tasks: Task[] = [];
for await (const row of rows) {
tasks.push(rowToTask(row));
}
return { tasks };
}
);
// الحصول على مهمة بالمعرّف
export const get = api(
{ expose: true, method: "GET", path: "/tasks/:id" },
async (req: { id: number }): Promise<Task> => {
const row = await db.queryRow`
SELECT id, title, description, completed, created_at
FROM tasks WHERE id = ${req.id}
`;
if (!row) throw new Error(`المهمة ${req.id} غير موجودة`);
return rowToTask(row);
}
);
// تحديث مهمة
export const update = api(
{ expose: true, method: "PUT", path: "/tasks/:id" },
async (req: {
id: number;
title?: string;
description?: string;
completed?: boolean;
}): Promise<Task> => {
const row = await db.queryRow`
UPDATE tasks SET
title = COALESCE(${req.title ?? null}, title),
description = COALESCE(${req.description ?? null}, description),
completed = COALESCE(${req.completed ?? null}, completed)
WHERE id = ${req.id}
RETURNING id, title, description, completed, created_at
`;
if (!row) throw new Error(`المهمة ${req.id} غير موجودة`);
return rowToTask(row);
}
);
// حذف مهمة
export const remove = api(
{ expose: true, method: "DELETE", path: "/tasks/:id" },
async (req: { id: number }): Promise<void> => {
await db.exec`DELETE FROM tasks WHERE id = ${req.id}`;
}
);
// دالة مساعدة لتحويل صف قاعدة البيانات إلى مهمة
function rowToTask(row: any): Task {
return {
id: row.id,
title: row.title,
description: row.description,
completed: row.completed,
createdAt: row.created_at.toISOString(),
};
}عند تشغيل encore run مجدداً، يقوم Encore تلقائياً بتوفير قاعدة بيانات PostgreSQL محلية وتشغيل عمليات الترحيل وربط الخدمة. بدون Docker، بدون سلاسل اتصال، بدون متغيرات بيئية.
الخطوة 4: إضافة خدمة إشعارات مع Pub/Sub
لنضف خدمة ثانية ترسل إشعارات عند اكتمال المهام. أولاً، لنُعرّف موضوع pub/sub:
// task/events.ts
import { Topic } from "encore.dev/pubsub";
// تعريف نوع الحدث
export interface TaskCompletedEvent {
taskId: number;
title: string;
completedAt: string;
}
// إنشاء الموضوع
export const taskCompleted = new Topic<TaskCompletedEvent>("task-completed", {
deliveryGuarantee: "at-least-once",
});حدّث نقطة نهاية update لنشر حدث عند اكتمال مهمة:
// في task/task.ts — أضف هذا الاستيراد في الأعلى
import { taskCompleted } from "./events";
// حدّث دالة update لنشر الأحداث
export const update = api(
{ expose: true, method: "PUT", path: "/tasks/:id" },
async (req: {
id: number;
title?: string;
description?: string;
completed?: boolean;
}): Promise<Task> => {
const row = await db.queryRow`
UPDATE tasks SET
title = COALESCE(${req.title ?? null}, title),
description = COALESCE(${req.description ?? null}, description),
completed = COALESCE(${req.completed ?? null}, completed)
WHERE id = ${req.id}
RETURNING id, title, description, completed, created_at
`;
if (!row) throw new Error(`المهمة ${req.id} غير موجودة`);
const task = rowToTask(row);
// نشر حدث إذا تم تعليم المهمة كمكتملة
if (req.completed === true) {
await taskCompleted.publish({
taskId: task.id,
title: task.title,
completedAt: new Date().toISOString(),
});
}
return task;
}
);الآن أنشئ خدمة الإشعارات:
mkdir notification// notification/encore.service.ts
import { Service } from "encore.dev/service";
export default new Service("notification");// notification/notification.ts
import { Subscription } from "encore.dev/pubsub";
import { taskCompleted, TaskCompletedEvent } from "../task/events";
// الاشتراك في أحداث اكتمال المهام
const _ = new Subscription(taskCompleted, "notify-on-complete", {
handler: async (event: TaskCompletedEvent) => {
console.log(
`مهمة مكتملة: "${event.title}" (المعرّف: ${event.taskId}) في ${event.completedAt}`
);
// في الإنتاج، سترسل بريداً إلكترونياً أو رسالة Slack، إلخ.
},
});هذا كل شيء. يتولى Encore:
- تسلسل الرسائل مع أمان الأنواع
- ضمانات التسليم (مرة واحدة على الأقل)
- المحاكاة المحلية باستخدام وسيط رسائل في الذاكرة
- التوفير السحابي للبنية التحتية الفعلية لـ pub/sub (مثل GCP Pub/Sub أو AWS SNS/SQS)
الخطوة 5: إضافة مهام Cron للعمليات المتكررة
لنضف مهمة cron ترسل ملخصاً يومياً للمهام غير المكتملة:
// task/cron.ts
import { CronJob } from "encore.dev/cron";
import db from "./db";
// التنفيذ كل يوم الساعة 9:00 صباحاً بتوقيت UTC
const dailySummary = new CronJob("daily-task-summary", {
title: "ملخص المهام اليومي",
schedule: "0 9 * * *",
endpoint: sendDailySummary,
});
async function sendDailySummary() {
const row = await db.queryRow`
SELECT
COUNT(*) FILTER (WHERE completed = false) as pending,
COUNT(*) FILTER (WHERE completed = true) as done,
COUNT(*) as total
FROM tasks
`;
console.log(
`الملخص اليومي — قيد الانتظار: ${row!.pending}، مكتملة: ${row!.done}، الإجمالي: ${row!.total}`
);
}مهام cron في Encore:
- مُعلنة في الكود — لا حاجة لمُجدول خارجي أو crontab
- مُسجلة تلقائياً — يكتشفها Encore أثناء التجميع
- مرئية في لوحة التحكم — يمكنك رؤية سجل التنفيذ والسجلات
الخطوة 6: المصادقة والتفويض
يوفر Encore نمطاً مدمجاً لإدارة المصادقة. لنضف مصادقة بمفتاح API:
// auth/encore.service.ts
import { Service } from "encore.dev/service";
export default new Service("auth");// auth/auth.ts
import { authHandler } from "encore.dev/auth";
import { Header } from "encore.dev/api";
interface AuthParams {
authorization: Header<"Authorization">;
}
interface AuthData {
userId: string;
role: string;
}
// تعريف معالج المصادقة
export const auth = authHandler(
async (params: AuthParams): Promise<AuthData> => {
const token = params.authorization?.replace("Bearer ", "");
if (!token) {
throw new Error("رمز التفويض مفقود");
}
// في الإنتاج، تحقق من JWT أو ابحث عن مفتاح API
// لهذا الدرس، نستخدم تحققاً بسيطاً
if (token === "admin-secret-key") {
return { userId: "admin", role: "admin" };
}
throw new Error("رمز غير صالح");
}
);الآن احمِ نقاط النهاية بإضافة auth: true:
// في task/task.ts — حدّث نقطة نهاية create
export const create = api(
{ expose: true, auth: true, method: "POST", path: "/tasks" },
async (req: CreateParams): Promise<Task> => {
// req يتضمن الآن بيانات المصادقة
// ... نفس التنفيذ
}
);الطلبات إلى نقاط النهاية المحمية تتطلب الآن رأس Authorization صالح.
الخطوة 7: اختبار API الخاص بك
يمتلك Encore دعماً مدمجاً للاختبارات. أنشئ ملف اختبار:
// task/task.test.ts
import { describe, it, expect } from "vitest";
import { create, list, get, update, remove } from "./task";
describe("واجهة برمجة تطبيقات المهام", () => {
it("يجب أن ينشئ مهمة", async () => {
const task = await create({
title: "مهمة اختبار",
description: "مهمة للاختبار",
});
expect(task.title).toBe("مهمة اختبار");
expect(task.description).toBe("مهمة للاختبار");
expect(task.completed).toBe(false);
expect(task.id).toBeGreaterThan(0);
});
it("يجب أن يعرض المهام", async () => {
const result = await list();
expect(result.tasks.length).toBeGreaterThan(0);
});
it("يجب أن يحدّث مهمة", async () => {
const task = await create({
title: "للإكمال",
description: "ستُكمل",
});
const updated = await update({
id: task.id,
completed: true,
});
expect(updated.completed).toBe(true);
});
it("يجب أن يحذف مهمة", async () => {
const task = await create({
title: "للحذف",
description: "ستُحذف",
});
await remove({ id: task.id });
await expect(get({ id: task.id })).rejects.toThrow();
});
});شغّل الاختبارات:
encore test ./task/...يوفر Encore تلقائياً قاعدة بيانات اختبار منفصلة لكل تشغيل اختبار، ويُنفذ عمليات الترحيل ويحذفها بعد ذلك. لا حاجة لبيانات اختبار أو كود تنظيف.
الخطوة 8: استكشاف لوحة تحكم التطوير المحلي
واحدة من أبرز ميزات Encore هي لوحة تحكم التطوير المحلي. عندما يعمل تطبيقك (encore run)، افتح http://localhost:9400 للوصول إلى:
- كتالوج الخدمات — جميع خدماتك ونقاط النهاية وأنواعها
- مستكشف API — اختبر نقاط النهاية مباشرة من المتصفح
- مخططات التدفق — تصور كيف تتواصل الخدمات
- مستكشف التتبع — فحص تتبعات الطلبات مع تفاصيل التوقيت
- مستكشف قاعدة البيانات — تصفح جداولك
- مراقب Pub/Sub — عرض الرسائل المنشورة والاشتراكات
يتم إنشاء لوحة التحكم هذه تلقائياً من الكود — لا تكوين Swagger، لا ملفات مواصفات OpenAPI، لا توثيق يدوي.
الخطوة 9: توليد SDK عميل
يمكن لـ Encore توليد SDKs عميل آمنة الأنواع لواجهة برمجة التطبيقات الخاصة بك:
encore gen client task-api --output=./client --lang=typescriptهذا يولّد عميل TypeScript يمكنك استخدامه في الواجهة الأمامية:
import Client from "./client";
const client = new Client({ baseURL: "http://localhost:4000" });
// مكتمل الأنواع — الإكمال التلقائي في المحرر يعمل بشكل مثالي
const task = await client.task.create({
title: "من الواجهة الأمامية",
description: "تم إنشاؤه عبر العميل المُولّد",
});
const allTasks = await client.task.list();يتضمن العميل المُولّد:
- جميع أنواع الطلب/الاستجابة المطابقة للخلفية
- التسلسل التلقائي للتواريخ والتعدادات، إلخ.
- معالجة الأخطاء مع استجابات خطأ مُنمّطة
- دعم المصادقة المدمج
الخطوة 10: النشر في السحابة
نشر تطبيق Encore بسيط بشكل ملحوظ:
git add -A
git commit -m "feat: واجهة برمجة تطبيقات إدارة المهام مع قاعدة بيانات وpub/sub وcron"
git push encore mainيتولى Encore كل شيء:
- يبني تطبيقك
- يوفر البنية التحتية — قاعدة البيانات وموضوعات pub/sub ومُجدولات cron
- يُكوّن الشبكة — service mesh وتوزيع الحمل وTLS
- ينشر بدون وقت توقف
- يُعد المراقبة — التتبع الموزع والسجلات والمقاييس
يمكنك النشر على Encore Cloud (مُدار) أو على حسابك الخاص في AWS أو GCP. في كلتا الحالتين، يوفر Encore خدمات البنية التحتية المناسبة تلقائياً.
راقب نشرك من لوحة تحكم Encore Cloud:
encore app openنظرة عامة على هندسة المشروع
إليك ما بنيناه:
task-api/
├── encore.app
├── task/
│ ├── encore.service.ts # تعريف الخدمة
│ ├── task.ts # نقاط نهاية CRUD API
│ ├── db.ts # إعلان قاعدة البيانات
│ ├── events.ts # تعريف موضوع pub/sub
│ ├── cron.ts # تعريفات مهام cron
│ ├── task.test.ts # اختبارات التكامل
│ └── migrations/
│ └── 001_create_tasks.up.sql
├── notification/
│ ├── encore.service.ts # تعريف الخدمة
│ └── notification.ts # مشترك في الأحداث
└── auth/
├── encore.service.ts # تعريف الخدمة
└── auth.ts # معالج المصادقة
ثلاث خدمات، قاعدة بيانات، نظام رسائل pub/sub، مهام cron، مصادقة، ونشر سحابي — كل ذلك في حوالي 200 سطر من TypeScript. بدون Terraform، بدون Docker، بدون Kubernetes، بدون متغيرات بيئية.
استكشاف الأخطاء وإصلاحها
المشاكل الشائعة
"فشل ترحيل قاعدة البيانات"
تأكد من أن ملف SQL الخاص بك ينتهي بـ .up.sql ومُرقم تسلسلياً (001، 002، إلخ). تحقق من أخطاء الصياغة في SQL.
"لم يتم اكتشاف الخدمة"
تأكد من وجود ملف encore.service.ts في مجلد الخدمة مع استدعاء new Service() صالح.
"معالج المصادقة غير موجود"
يجب تصدير معالج المصادقة من ملف في مجلد خدمة. تأكد من استيراد authHandler من encore.dev/auth.
"المنفذ مستخدم بالفعل" يستخدم Encore المنفذ 4000 افتراضياً. إذا كان مشغولاً، سيختار Encore المنفذ التالي المتاح. تحقق من مخرجات الطرفية للرابط الفعلي.
الخطوات التالية
الآن بعد أن أصبح لديك تطبيق Encore.ts يعمل، إليك بعض الأفكار لتوسيعه:
- إضافة واجهة أمامية باستخدام SDK العميل المُولّد مع Next.js أو React
- إضافة المزيد من الخدمات — إدارة المستخدمين والتحليلات ورفع الملفات
- تنفيذ webhooks باستخدام pub/sub من Encore للتكاملات الخارجية
- إعداد البيئات — التجريب والإنتاج بتكوينات مختلفة
- إضافة إدارة الأسرار باستخدام
encore secret set - استكشاف مقاييس Encore للمقاييس التجارية المخصصة
دروس ذات صلة
- بناء واجهات REST API مع Hono وBun — مقارنة مع نهج خفيف الوزن
- واجهة REST API مع NestJS TypeORM PostgreSQL — خلفية Node.js تقليدية
- واجهة REST API مع Fastify TypeScript — بديل مبني على Fastify
الخلاصة
يمثل Encore.ts تحولاً جذرياً في تطوير الخلفيات. بدلاً من تجميع عشرات الحزم وكتابة البنية التحتية ككود وتكوين خطوط CI/CD، أنت تركز على منطق العمل وتترك لـ Encore التعامل مع الباقي.
في هذا الدرس، بنيت واجهة برمجة تطبيقات كاملة لإدارة المهام مع:
- نقاط نهاية آمنة الأنواع مع تحقق تلقائي
- قاعدة بيانات PostgreSQL مع عمليات ترحيل
- نظام رسائل pub/sub بين الخدمات
- مهام cron للعمليات المجدولة
- المصادقة مع معالج مصادقة
- اختبارات مع توفير تلقائي لقاعدة البيانات
- نشر سحابي بدون تكوين بنية تحتية
النقطة الأساسية هي أن Encore لا يوفر عليك فقط الكود النمطي — بل يُلغي فئات كاملة من العمل (توفير البنية التحتية وإعداد المراقبة وتوليد SDK العميل) التي تستهلك تقليدياً وقتاً هندسياً كبيراً. سواء كنت تبني نموذجاً أولياً لشركة ناشئة أو تتوسع لملايين المستخدمين، يمنحك Encore.ts أساساً صلباً وآمن الأنواع ينمو مع احتياجاتك.
ناقش مشروعك معنا
نحن هنا للمساعدة في احتياجات تطوير الويب الخاصة بك. حدد موعدًا لمناقشة مشروعك وكيف يمكننا مساعدتك.
دعنا نجد أفضل الحلول لاحتياجاتك.
مقالات ذات صلة

بناء ونشر واجهة برمجية بدون خوادم باستخدام Cloudflare Workers و Hono و D1
تعلّم كيف تبني واجهة برمجية REST جاهزة للإنتاج باستخدام Cloudflare Workers وإطار Hono وقاعدة بيانات D1 — من إعداد المشروع حتى النشر العالمي.

بناء واجهات برمجة تطبيقات جاهزة للإنتاج باستخدام Fastify و TypeScript
تعلّم كيفية بناء واجهات برمجة تطبيقات REST سريعة وآمنة الأنواع باستخدام Fastify و TypeScript. يغطي هذا الدليل الشامل إعداد المشروع، التحقق من المخطط، المصادقة، تكامل قاعدة البيانات، معالجة الأخطاء، الاختبار، وأفضل ممارسات النشر.

بناء واجهة GraphQL آمنة الأنواع مع Next.js App Router و Yoga و Pothos
تعلم كيفية بناء واجهة GraphQL API آمنة الأنواع بالكامل باستخدام Next.js 15 App Router و GraphQL Yoga و Pothos schema builder. يغطي هذا الدليل العملي تصميم المخططات والاستعلامات والتحولات والمصادقة وعميل React باستخدام urql.