كيفية إنشاء واجهة برمجة تطبيقات GraphQL باستخدام Nest.js؟
في هذه المقالة، ستتعلم كيفية إنشاء واجهة برمجة تطبيقات GraphQL باستخدام NestJS مستفيدًا من بنيتها النظيفة وأمان النوع.
NestJS هو إطار عمل NodeJS يساعد المستخدمين على إنشاء تطبيقات خلفية قابلة للتطوير على مستوى المؤسسات من خلال توفير أمان النوع ونمط معماري صارم.
GraphQL هي لغة استعلام لواجهات برمجة التطبيقات (APIs) تُستخدم على نطاق واسع كبديل لـ REST نظرًا لسرعتها وثباتها، وهو ما تحققه من خلال الاستجابة للاستعلامات بالبيانات التي تطلبها بدقة. تعمل ميزة GraphQL هذه على حل مشكلة الجلب الزائد والجلب الناقص التي تطرحها REST.
Contents
إعداد بيئة التطوير الخاصة بك
إذا لم تكن واجهة Nest.js CLI مثبتة عالميًا على نظامك، فقم بتشغيل الأمر أدناه لتثبيته:
npm i -g @nestjs/cli
تحتوي واجهة Nest.js CLI على العديد من الأوامر التي تساعدك على إنشاء شيفرة برمجية لتسهيل عملية التطوير.
بعد ذلك، قم بإنشاء المشروع وإنشاء ملفات البدء اللازمة عن طريق تشغيل الأمر أدناه:
nest new graphql-api
ثم، قم بتشغيل الأمر أدناه للقرص المضغوط إلى دليل المشروع الخاص بك:
cd graphql-api
بعد ذلك، قم بتثبيت التبعيات المطلوبة عن طريق تشغيل الأمر أدناه:
npm i @nestjs/graphql @nestjs/apollo graphql apollo-server-express
تتضمن التبعيات المثبتة أعلاه ما يلي:
nest/graphql
nestjs/apollo
graphql
apollo-server-express
بعد ذلك، قم بتثبيت حزمة TypeORM وبرنامج تشغيل قاعدة بيانات sqlite عن طريق تشغيل الأمر أدناه:
npm install @nestjs/typeorm typeorm sqlite3
ستحتاج إلى الحزم المثبتة أعلاه للاتصال بقاعدة البيانات وقراءتها وكتابتها.
تكوين GraphQL في Nest.js
يقدّم Nest.js طريقتين لإنشاء واجهة برمجة GraphQL API: نهج التعليمات البرمجية أولًا ونهج المخطط أولًا.
يتميز نهج التعليمات البرمجية أولًا باستخدام مزخرفات وفئات TypeScript لإنشاء مخطط GraphQL المقابل.
يتميز نهج المخطط أولًا باستخدام ملفات لغة تعريف مخطط GraphQL (SDL)، بينما يقوم Nest.js بإنشاء تعريفات TypeScript باستخدام فئات أو واجهات تستند إلى مخطط GraphQL.
سيعرض هذا البرنامج التعليمي استخدام نهج التعليمات البرمجية أولاً لتجنب التبديل بين اللغات المختلفة.
لاستخدام نهج الشيفرة أولًا، انتقل إلى ملف إدخال التطبيق الخاص بك، app.module.ts،
واستورد GraphQLModule
من @nestjs/graphql
. هكذا
import { GraphQLModule } from '@nestjs/graphql';
ثم، في مصفوفة الواردات
الخاصة بك، قم باستدعاء طريقة GraphQLModule
‘s forRoot
. يأخذ هذا الأسلوب كائن تكوين كوسيطة. يتم تمرير خيارات التكوين من خلال برنامج تشغيل GraphQL الأساسي (يتميز هذا البرنامج التعليمي باستخدام برنامج تشغيل Apollo). عيّن خاصية autoSchemaFile
في كائن التكوين إلى schema.gql.
هكذا
//app.module.ts
GraphQLModule.forRoot({ autoSchemaFile: 'schema.gql' }),
خاصية autoSchemaFile
هي مسار الملف حيث سيتم تخزين المخطط الذي تم إنشاؤه تلقائيًا.
الاتصال بقاعدة بيانات
لتوصيل تطبيقك بقاعدة بيانات، انتقل إلى ملف app.module.ts
الخاص بك واستورد TypeOrmModule
من @nestjs/typeorm
.
هكذا
import { TypeOrmModule } from '@nestjs/typeorm';
بعد ذلك، أضف الكتلة البرمجية أدناه إلى مصفوفة الواردات
:
TypeOrmModule.forRoot({
type: 'sqlite',
database: ':memory:',
entities: ['dist/**/*.entity{.ts,.js}'],
synchronize: true,
}),
تنشئ كتلة التعليمات البرمجية أعلاه اتصال قاعدة بيانات بين تطبيقك وقاعدة بيانات Sqlite وتشارك الاتصال في جميع الوحدات النمطية في تطبيقك.
توليد الموارد
بعد ذلك، أنشئ وحدة نمطية لتنظيم شفرتك عن طريق تشغيل الأمر أدناه:
nest g module blog
يُنشئ الأمر أعلاه وحدة نمطية للمدونة لتطبيقك.
بعد ذلك، قم بتشغيل الأمر أدناه لإنشاء خدمة:
nest g service blog
تقوم كتلة الشيفرة أعلاه بإنشاء وتسجيل خدمة في تطبيقك. ستحتوي هذه الخدمة على كل منطق العمل الخاص بتطبيقك وتتعامل معه.
بعد ذلك، قم بتشغيل الأمر أدناه لإنشاء محلل:
nest g resolver
تقوم الكتلة البرمجية أعلاه بإنشاء وتسجيل محلل في تطبيقك. يحدد المُحلِّل تعليمات لتحويل استعلامات GraphQL والطفرات إلى بيانات وإرجاع شكل البيانات المحددة في المخطط بشكل متزامن أو غير متزامن.
إنشاء كيان
الكيان هو مجموعة من الحقول التي تحدد كيفية تخزين البيانات في قاعدة البيانات.
لإنشاء كيان، في مجلد الوحدة النمطية (المدونة)، قم بإنشاء ملف كيان باتباع اصطلاح .entity.ts،
على سبيل المثال، blog.entity.ts
.
في ملف الكيان الخاص بك، قم باستيراد العمود
والكيان
والعمود الأساسي المُنشأ
من typeorm
. هكذا
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
يضيف مُزيِّن العمود
الحقول التي يشرحها كأعمدة في قاعدة البيانات. يقوم مزين الكيان
بتمييز الفئة التي يشرحها ككيان. يقوم مُزيِّن العمود الأساسي PrimaryGeneratedColumn
بتمييز الخاصية التي يشرحها كمعرِّف فريد لجدولك ويقوم بإنشائها تلقائيًا.
بعد ذلك، قم بإنشاء وتصدير صنف، مدونة
. بعد ذلك، قم بتعليق الصنف بمُزيِّن الكيان
لتمييزه ككيان. هكذا:
@Entity()
export class Blog {}
بما أن هذا البرنامج التعليمي يحتوي على واجهة برمجة تطبيقات للمدونة، أضف خاصية المعرف، والعنوان، والنص، والمؤلف، والتاريخ إلى صفك. ثم، قم بتعليق كل خاصية من الخصائص بمُزيِّن العمود
باستثناء خاصية المعرف
. قم بتعليق خاصية المُعرِّف
باستخدام مُزيِّن العمود الأساسي PrimaryGeneratedColumn
.
هكذا
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Blog {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
body: string;
@Column()
author: string;
@Column()
date: string;
}
إنشاء نوع الكائن
نوع الكائن هو تعريف مخطط GraphQL يمثل الكائن الذي يحتاج العميل إلى التفاعل معه. على سبيل المثال، إذا كنت تنشئ واجهة برمجة تطبيقات مدونة، فستحتاج إلى تعريف مخطط/كائن المدونة بفئة TypeScript وتعليق كل حقل بالمزخرفات المناسبة.
بعد ذلك، في ملف الكيان الخاص بك، قم باستيراد نوع Int
ومزخرفات الحقل
و ObjectType
من @nestjs/graphqql
. هكذا:
import { Field, Int, ObjectType } from '@nestjs/graphql';
يحدد مُزين الحقل
خاصية فئة معينة كحقل GraphQL. سيتم تعريف الخصائص المشروحة بهذا المزيِّن فقط في المخطط. يقبل دالة نوع إرجاع اختيارية وكائن تكوين كوسيطات.
نوع Int
مطلوب لإزالة الغموض المحتمل بين نظامي TypeScript و GraphQL. وهو مطلوب فقط للخصائص ذات القيم العددية حيث يمكن أن تكون إما أعدادًا صحيحة أو عائمة.
يقوم مزين ObjectType
بتمييز الصنف كنوع GraphQL.
بعد ذلك، قم بتعليق صنف مدونتك بمُزيِّن ObjectType
لتمييزه كنوع GraphQL. هكذا:
@ObjectType()
export class Blog {}
أخيرًا، حدِّد الخصائص المطلوبة لنوعك داخل الصنف، وقم بتوضيح كل منها باستخدام مُزيِّن الحقل
. على سبيل المثال:
//blog.entity.ts
import { Field, Int, ObjectType } from '@nestjs/graphql';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
@ObjectType()
export class Blog {
@PrimaryGeneratedColumn()
@Field((type) => Int)
id: number;
@Column()
@Field()
title: string;
@Column()
@Field()
body: string;
@Column()
@Field()
author: string;
@Column()
@Field()
date: string;
}
يجب أن يبدو نوع الكائن النهائي الخاص بك مثل الكتلة البرمجية أعلاه.
لاحظ أن المعرف
بنوع رقم
في الكتلة البرمجية أعلاه تم تحديده صراحةً كعدد صحيح لتجنب الغموض بين نظامي TypeScript و GraphQL.
أخيراً، احقن كيانك في تطبيقك لإنشاء طبقة وصول بين تطبيقك وقاعدة بياناتك.
لتحقيق ذلك، انتقل إلى ملف blog.module.ts
الخاص بك، واستورد TypeOrmModule
من @nestjs/typeorm،
واستورد كيان المدونة الخاص بك.
بعد ذلك، أضف الكتلة البرمجية أدناه إلى مُزيِّن الوحدة النمطية لديك:
imports: [TypeOrmModule.forFeature([Blog])],
تقوم كتلة الشيفرة أعلاه بإنشاء مستودع يعمل كطبقة وصول بين تطبيقك وقاعدة البيانات.
إنشاء خدمة
انتقل إلى ملف الخدمة الذي تم إنشاؤه مسبقًا، blog.service.ts،
واستورد InjectRepository
من @nestjs/typeorm
ونوع الكائن الخاص بك.
هكذا
import { InjectRepository } from '@nestjs/typeorm';
import { Blog } from './blog.entity';
بعد ذلك، أضف الكتلة البرمجية أدناه إلى فئة BlogService
الخاصة بك لحقن المستودع الخاص بك:
constructor(
@InjectRepository(Blog)
private blogRepository: Repository<Blog>,
) {}
بعد ذلك، أضف الكتلة البرمجية أدناه إلى صف الخدمة الخاص بك لتنفيذ منطق استرداد جميع المدونات في قاعدة البيانات:
async getAll(): Promise<Blog[]> {
return await this.blogRepository.find();
}
بعد ذلك، ستحتاج إلى تنفيذ منطق إضافة مدونة جديدة إلى قاعدة البيانات الخاصة بك، ولكن أولاً، ستحتاج إلى إنشاء نوع إدخال.
إنشاء نوع الإدخال
لإنشاء نوع إدخال لطفراتك التي تأخذ كائنات معقدة، أنشئ مجلد dtos
في مجلد مدونتك
. ثم، في مجلد dtos
الخاص بك، قم بإنشاء ملف جديد، create-blog.input.ts.
في ملف create-blog.input.ts
الخاص بك، استورد مُزيِّنات الحقل
و InputType
. هكذا:
import { Field, InputType } from '@nestjs/graphql';
يقوم مُزيِّن نوع الإدخال
بتمييز الصنف كنوع إدخال GraphQL.
بعد ذلك، قم بإنشاء وتصدير صنف، BlogInput
. بعد ذلك، قم بتعليق الصنف بمُزيِّن InputType
. هكذا:
@InputType()
export class BlogInput {}
أخيرًا، أضف جميع خصائص المدونة المطلوبة وعلق عليها بمزخرف الحقل
.
هكذا
//create-blog.input.ts
import { Field, InputType } from '@nestjs/graphql';
@InputType()
export class BlogInput {
@Field()
id: number;
@Field()
title: string;
@Field()
body: string;
@Field()
author: string;
@Field()
date: string;
}
يجب أن يبدو نوع الإدخال النهائي الخاص بك مثل كتلة التعليمات البرمجية أعلاه.
بعد ذلك، استورد نوع الإدخال الخاص بك إلى ملف الخدمة الخاص بك وأضف الكتلة البرمجية أدناه إلى صنف الخدمة الخاص بك لتنفيذ منطق إضافة مدونة إلى قاعدة البيانات:
async createBlog(blogInput: BlogInput): Promise<Blog> {
const newBlog = this.blogRepository.create(blogInput);
return this.blogRepository.save(newBlog);
}
يُطبَّق نوع الإدخال بنفس الطريقة التي يُطبَّق بها كائن نقل بيانات Nest.js العادي، كآلية للتحقق من صحة البيانات الواردة. مثل dtos، يمكنك أيضًا إجراء تحقق إضافي من صحة البيانات باستخدام حزمة أداة التحقق من صحة الفئة
.
إنشاء محلل
انتقل إلى ملف Resolver .resolver.ts
الذي تم إنشاؤه مسبقًا، blog.resolver.ts،
واستورد الكيان ونوع الإدخال والخدمة. هكذا
import { Blog } from './blog.entity';
import { BlogService } from './blog.service';
import { BlogInput } from './dto/create-blog.input';
بعد ذلك، أضف الكتلة البرمجية أدناه إلى صنف المُحلِّل الخاص بك لحقن خدمتك في المُحلِّل:
constructor(private blogService: BlogService) {}
بعد ذلك، استورد مُزخرفات Args،
والطفرة،
والاستعلام
من @nestjs/graphql
.
هكذا
import { Args, Mutation, Query } from '@nestjs/graphql';
يستخرج مُزيِّن Args
كائن الوسيطات من المنصة الأساسية ويملأ المعلمة المزينة بقيمة جميع الوسيطات أو وسيطة واحدة محددة.
يحدد مصمم الطفرات
مسارًا كطفرة.
يحدد مصمم الاستعلام
مسارًا كاستعلام.
بعد ذلك، مرر الدالة أدناه إلى مُزيِّن المُحلِّل
لتحديد نوع الكائن:
(of) => Blog
بعد ذلك، أضف الكتلة البرمجية أدناه إلى صنف المُحلِّل لحل طريقة getAll
.
@Query((type) => [Blog])
async getAllBlogs() {
return this.blogService.getAll();
}
أخيرًا، أضف الكتلة البرمجية أدناه إلى صنف Resolver لحل طريقة إنشاء مدونة
.
@Mutation((returns) => Blog)
createBlog(@Args('blogInput') blogInput: BlogInput): Promise<Blog> {
return this.blogService.createBlog(blogInput);
}
ملاحظة: تأكد من تحديد دالة نوع الإرجاع لكل مُزيِّن.
يجب أن يبدو صنف المحلول النهائي الخاص بك مثل الكتلة البرمجية أدناه:
@Resolver((of) => Blog)
export class BlogResolver {
constructor(private blogService: BlogService) {}
@Query((type) => [Blog])
async getAllBlogs() {
return this.blogService.getAll();
}
@Mutation((returns) => Blog)
createBlog(@Args('blogInput') blogInput: BlogInput): Promise<Blog> {
return this.blogService.createBlog(blogInput);
}
}
اختبار واجهة برمجة التطبيقات الخاصة بك باستخدام GraphQL Playground
لاختبار تطبيقك باستخدام ملعب GraphQL، المتاح افتراضيًا، قم بتشغيل الأمر أدناه وانتقل إلى http://localhost:3000/graphql.
npm start
بعد ذلك، يجب أن ترى ملعبًا حيث يمكنك اختبار استفساراتك وطفراتك، كما هو موضح في الصورة أدناه.
لاسترداد جميع المدونات من قاعدة البيانات، قم بتشغيل الاستعلام أدناه:
query getAll{
getAllBlogs {
id,
title,
body,
author,
date
}
}
يظهر مثال على ذلك في الصورة أدناه:
لإضافة مدونة إلى قاعدة بياناتك، قم بتشغيل الطفرة أدناه:
mutation createBlog {
createBlog (blogInput: {
id: 1,
title: "GraphQL is great",
body: "GraphQL APIs are faster than REST APIs",
author: "David Ekete",
date: "01-02-03"
}) {
id,
title,
body,
author,
date,
}
}
يظهر مثال على ذلك في الصورة أدناه:
Back4app و GraphQL
نظرًا للمزايا العديدة التي يتمتع بها GraphQL على REST، مثل التحكم في جلب البيانات، توفر منصة Back4app واجهة برمجة تطبيقات GraphQL مدمجة في تطبيقات التحليل التي تعمل على المنصة.
يتيح لك هذا التكامل التحقق من صحة الواجهة الخلفية لخادمك، وإجراء عمليات إنشاء وقراءة وتحديث وحذف (CRUD) على قاعدة بياناتك، وغير ذلك الكثير من خلال كتابة استعلامات وطفرات GraphQL بسيطة.
على سبيل المثال، للتحقق من حالة خادمك الخلفي باستخدام واجهة برمجة تطبيقات GraphQL، قم بتشغيل الاستعلام أدناه:
query Health {
health
}
سيعود الاستعلام أعلاه:
{
"data": {
"health": true
}
}
لبدء استخدام ميزة GraphQL، انتقل إلى لوحة معلومات Parse الخاصة بك وحدد تطبيقك وانقر فوق تطبيقك. في واجهة المستخدم الخاصة بتطبيقك، حدد وانقر على Core، ثم حدد وانقر على وحدة تحكم API واختر وحدة تحكم GraphQL.
سيؤدي اتباع الإرشادات أعلاه إلى فتح وحدة تحكم GraphQL حيث يمكنك تشغيل استفساراتك وطفراتك المشابهة لملعب GraphQL الذي استخدمته في التطوير. يمكنك معرفة المزيد حول ميزة GraphQL في Back4app في وثائق Back4app.
الخاتمة
تناولت هذه المقالة كيف يمكنك إنشاء واجهة برمجة تطبيقات GraphQL في Nest.js واختبار واجهة برمجة التطبيقات باستخدام ملعب GraphQL. تتمتع واجهات برمجة تطبيقات GraphQL بالعديد من المزايا مقارنةً بواجهات برمجة تطبيقات REST.
ومع ذلك، فهي ليست مثالية لكل تطبيق. تأكد من النظر في إيجابيات وسلبيات GraphQL و REST قبل اختيار أيهما مناسب لتطبيقك.
بغض النظر عن اختيارك، GraphQL أو REST، ستظل بحاجة إلى نشر تطبيقك. Back4app هي خدمة BaaS منخفضة الكود تعتمد على تقنيات مفتوحة المصدر تعمل على تبسيط عملية بناء الواجهة الخلفية من خلال التخلص من المهام المتكررة باستخدام قوالب قابلة لإعادة الاستخدام وإدارة معظم البنية التحتية للواجهة الخلفية.
تتضمن بعض ميزات تطبيق Back4app قاعدة بيانات في الوقت الفعلي، ووظائف السحابة، وواجهات برمجة التطبيقات الأصلية وحزم تطوير البرمجيات SDK، ونظام إدارة مستخدم كامل، وغير ذلك الكثير.
تتميز هذه المنصة أيضاً بفئة مجانية تتيح لك استكشاف المنصة دون دفع رسوم.
بناء سعيد!
الأسئلة الشائعة
ما هو GraphQL؟
GraphQL هي لغة استعلام ومعالجة بيانات مفتوحة المصدر لواجهات برمجة التطبيقات، تم إنشاؤها بواسطة Facebook في عام 2012.
ما هو Nest.JS؟
Nest.JS هو إطار عمل Node.js مفتوح المصدر لبناء تطبيقات فعالة وقابلة للتطوير على جانب الخادم.
كيفية إنشاء واجهة برمجة تطبيقات GraphQL باستخدام Nest.JS؟
– تكوين GraphQL في Nest.js
– الاتصال بقاعدة بيانات
– توليد موارد
– إنشاء كيان
– إنشاء نوع كائن
– إنشاء خدمة