مقدمة
\n\nGraphQL هي لغة استعلام لواجهات API تتيح للعملاء الحصول على البيانات المطلوبة فقط. عند دمجها مع TypeScript، تصبح أداة قوية لإنشاء واجهات API آمنة من حيث الأنواع، قابلة للتوسع، وموثقة. في هذا الدليل التعليمي خطوة بخطوة، سنقوم عمليًا بإنشاء GraphQL API كامل باستخدام TypeScript مع Apollo Server و TypeGraphQL.
ستتعلم:
\n- \n
- كيفية إعداد مشروع باستخدام TypeScript و Apollo Server \n
- كيفية تعريف مخطط GraphQL باستخدام أدوات التزيين (Decorators) من TypeGraphQL \n
- كيفية كتابة المحللات (Resolvers) مع كتابة كاملة للأنواع \n
- كيفية ربط قاعدة البيانات وتنفيذ الاستعلامات \n
ستكون هذه المادة مفيدة لكل من المبتدئين والمطورين الذين هم على دراية بـ REST API ولكنهم يرغبون في إتقان النهج الحديث لبناء واجهات API.
\n\n1. إعداد المشروع وتثبيت التبعيات
\n\nلنبدأ بتهيئة المشروع. تأكد من تثبيت Node.js (الإصدار 16+) و npm/yarn.
\n\nmkdir graphql-ts-tutorial\ncd graphql-ts-tutorial\nnpm init -y\n\nقم بتثبيت الحزم اللازمة:
\n\nnpm install apollo-server graphql reflect-metadata type-graphql class-validator\nnpm install -D typescript @types/node ts-node\n\nأنشئ ملف tsconfig.json:
{\n "compilerOptions": {\n "target": "ES2020",\n "module": "commonjs",\n "lib": ["ES2020"],\n "experimentalDecorators": true,\n "emitDecoratorMetadata": true,\n "strict": true,\n "esModuleInterop": true,\n "outDir": "./dist",\n "rootDir": "./src"\n },\n "include": ["src/**/*"]\n}\n\nلاحظ العلامات experimentalDecorators و emitDecoratorMetadata — فهي ضرورية لعمل TypeGraphQL.
2. تعريف المخطط والأنواع باستخدام TypeGraphQL
\n\nلننشئ مجلد src وملف src/types/User.ts. هنا سنصف نموذج المستخدم.
import { ObjectType, Field, ID, InputType } from "type-graphql";\n\n@ObjectType()\nexport class User {\n @Field(() => ID)\n id!: number;\n\n @Field()\n name!: string;\n\n @Field()\n email!: string;\n\n @Field()\n createdAt!: Date;\n}\n\nالشرح:
\n- \n
@ObjectType()— يحدد الفئة كنوع GraphQL. \n @Field()— يحدد الحقول التي ستكون متاحة في API. \n @Field(() => ID)— للنوع القياسي ID. \n
الآن لننشئ InputType للطفرات (إنشاء مستخدم):
@InputType()\nexport class CreateUserInput {\n @Field()\n name!: string;\n\n @Field()\n email!: string;\n}\n\nسيتم استخدام هذا النوع في المحللات للتحقق من صحة البيانات المدخلة.
\n\n3. كتابة المحللات (Resolvers)
\n\nلننشئ ملف src/resolvers/UserResolver.ts. هنا سنقوم بتنفيذ منطق الاستعلامات والطفرات.
import { Resolver, Query, Mutation, Arg } from "type-graphql";\nimport { User, CreateUserInput } from "../types/User";\n\n// محاكاة قاعدة البيانات\nlet users: User[] = [\n { id: 1, name: "إيفان إيفانوف", email: "ivan@example.com", createdAt: new Date() },\n { id: 2, name: "ماريا بيتروفا", email: "maria@example.com", createdAt: new Date() }\n];\n\nlet nextId = 3;\n\n@Resolver()\nexport class UserResolver {\n @Query(() => [User])\n async users(): Promise<User[]> {\n return users;\n }\n\n @Query(() => User, { nullable: true })\n async user(@Arg("id") id: number): Promise<User | undefined> {\n return users.find(u => u.id === id);\n }\n\n @Mutation(() => User)\n async createUser(@Arg("data") data: CreateUserInput): Promise<User> {\n const newUser: User = {\n id: nextId++,\n name: data.name,\n email: data.email,\n createdAt: new Date()\n };\n users.push(ne