بناء واجهات برمجة تطبيقات GraphQL باستخدام العقدة

نشرت: 2022-12-20

GraphQL هي الكلمة الطنانة الجديدة في تطوير API. بينما تظل RESTful APIs هي الطريقة الأكثر شيوعًا لكشف البيانات من التطبيقات ، إلا أنها تأتي مع العديد من القيود التي تهدف GraphQL إلى حلها.

GraphQL هي لغة استعلام تم إنشاؤها بواسطة Facebook ، والتي تم تحويلها إلى مشروع مفتوح المصدر في عام 2015. وهي تقدم بنية بديهية ومرنة لوصف البيانات والوصول إليها في واجهة برمجة التطبيقات.

سوف يستكشف هذا الدليل كيفية إنشاء مشروع GraphQL Node.js. سنستخدم GraphQL لإنشاء تطبيق Todo في إطار عمل الويب Express.js لـ Node.

ما هي GraphQL؟

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

GraphQL هي وقت تشغيل من جانب الخادم لتنفيذ الاستعلامات باستخدام نظام النوع الذي حددته لبياناتك. أيضًا ، لا ترتبط GraphQL بأي قاعدة بيانات محددة أو محرك تخزين. بدلاً من ذلك ، يتم دعمه بواسطة الكود الحالي ومخزن البيانات. يمكنك الحصول على مقارنة مفصلة لهذه التقنيات مع دليل GraphQL مقابل RESTful API.

لإنشاء خدمة GraphQL ، عليك أن تبدأ بتحديد أنواع المخططات وإنشاء الحقول باستخدام تلك الأنواع. بعد ذلك ، تقوم بتوفير محلل وظيفة ليتم تنفيذه في كل حقل واكتب كلما طلب جانب العميل البيانات.

مصطلحات GraphQL

يستخدم نظام نوع GraphQL لوصف البيانات التي يمكن الاستعلام عنها والبيانات التي يمكنك معالجتها. إنه جوهر GraphQL. دعونا نناقش الطرق المختلفة التي يمكننا من خلالها وصف البيانات ومعالجتها في GraphQ.

أنواع

أنواع كائنات GraphQL هي نماذج بيانات تحتوي على حقول مكتوبة بشدة. يجب أن يكون هناك تعيين 1 إلى 1 بين النماذج وأنواع GraphQL. فيما يلي مثال على نوع GraphQL:

 type User { id: ID! # The "!" means required firstname: String lastname: String email: String username: String todos: [Todo] # Todo is another GraphQL type }

استفسارات

يحدد استعلام GraphQL جميع الاستعلامات التي يمكن للعميل تشغيلها على واجهة برمجة تطبيقات GraphQL. يجب عليك تحديد RootQuery الذي سيحتوي على جميع الاستعلامات الموجودة حسب الاصطلاح.

أدناه نحدد الاستعلامات ونقوم بتعيينها إلى واجهة برمجة تطبيقات RESTful المقابلة:

 type RootQuery { user(id: ID): User # Corresponds to GET /api/users/:id users: [User] # Corresponds to GET /api/users todo(id: ID!): Todo # Corresponds to GET /api/todos/:id todos: [Todo] # Corresponds to GET /api/todos }

الطفرات

إذا كانت استعلامات GraphQL عبارة عن طلبات GET ، فإن الطفرات هي طلبات POST و PUT و PATCH و DELETE التي تتعامل مع واجهة برمجة تطبيقات GraphQL.

سنضع جميع الطفرات في RootMutation لشرح:

 type RootMutation { createUser(input: UserInput!): User # Corresponds to POST /api/users updateUser(id: ID!, input: UserInput!): User # Corresponds to PATCH /api/users removeUser(id: ID!): User # Corresponds to DELETE /api/users createTodo(input: TodoInput!): Todo updateTodo(id: ID!, input: TodoInput!): Todo removeTodo(id: ID!): Todo }

لقد لاحظت استخدام أنواع -input للطفرات مثل UserInput و TodoInput . من الأفضل دائمًا تحديد أنواع الإدخال لإنشاء مواردك وتحديثها.

يمكنك تحديد أنواع الإدخال مثل تلك الموجودة أدناه:

 input UserInput { firstname: String! lastname: String email: String! username: String! }

المحللون

تخبر المحللون GraphQL بما يجب أن تفعله عند طلب كل استعلام أو طفرة. إنها وظيفة أساسية تقوم بالعمل الشاق المتمثل في ضرب طبقة قاعدة البيانات للقيام بعمليات CRUD (إنشاء أو قراءة أو تحديث أو حذف) ، أو الوصول إلى نقطة نهاية RESTful API داخلية ، أو استدعاء خدمة مصغرة لتلبية طلب العميل.

يمكنك إنشاء ملف resolvers.js جديد وإضافة الكود التالي:

 import sequelize from '../models'; export default function resolvers () { const models = sequelize.models; return { // Resolvers for Queries RootQuery: { user (root, { id }, context) { return models.User.findById(id, context); }, users (root, args, context) { return models.User.findAll({}, context); } }, User: { todos (user) { return user.getTodos(); } }, } // Resolvers for Mutations RootMutation: { createUser (root, { input }, context) { return models.User.create(input, context); }, updateUser (root, { id, input }, context) { return models.User.update(input, { ...context, where: { id } }); }, removeUser (root, { id }, context) { return models.User.destroy(input, { ...context, where: { id } }); }, // ... Resolvers for Todos go here } }; }

مخطط

مخطط GraphQL هو ما تعرضه GraphQL للعالم. لذلك ، سيتم تضمين الأنواع والاستعلامات والطفرات داخل المخطط ليتم كشفها للعالم.

فيما يلي كيفية كشف الأنواع والاستعلامات والطفرات للعالم:

 schema { query: RootQuery mutation: RootMutation }

في البرنامج النصي أعلاه ، قمنا بتضمين RootQuery و RootMutation التي أنشأناها مسبقًا ليتم عرضها على العالم.

كيف تعمل GraphQL مع Nodejs و Expressjs

توفر GraphQL تطبيقًا لجميع لغات البرمجة الرئيسية ، ولا يتم استثناء Node.js. على موقع GraphQL الرسمي ، يوجد قسم لدعم JavaScript ، وهناك أيضًا تطبيقات أخرى لـ GraphQL لتسهيل الكتابة والتشفير في GraphQL.

يوفر GraphQL Apollo تطبيقًا لـ Node.js و Express.js ويسهل بدء استخدام GraphQL.

سوف تتعلم كيفية إنشاء وتطوير أول تطبيق GraphQL لك في إطار Nodes.js و Express.js الخلفي باستخدام GraphQL Apollo في القسم التالي.

إعداد GraphQL باستخدام Express.js

يعد إنشاء خادم واجهة برمجة تطبيقات GraphQL باستخدام Express.js أمرًا سهلاً للبدء. في هذا القسم ، سوف نستكشف كيفية بناء خادم GraphQL.

بدء المشروع باستخدام Express

أولاً ، تحتاج إلى تثبيت مشروع Express.js جديد وإعداده.

قم بإنشاء مجلد لمشروعك وقم بتثبيت Express.js باستخدام هذا الأمر:

 cd <project-name> && npm init -y npm install express

يقوم الأمر أعلاه بإنشاء ملف package.json جديد وتثبيت مكتبة Express.js في مشروعك.

بعد ذلك ، سنقوم ببناء مشروعنا كما هو موضح في الصورة أدناه. سيحتوي على وحدات مختلفة لميزات المشروع مثل المستخدمين ، todos ، إلخ.

قائمة الملفات في Graphql-todo.
ملفات لـ graphql-todo .

تهيئة GraphQL

لنبدأ بتثبيت تبعيات GraphQL Express.js. قم بتشغيل الأمر التالي للتثبيت:

 npm install apollo-server-express graphql @graphql-tools/schema --save

إنشاء المخططات والأنواع

بعد ذلك ، سننشئ ملف index.js داخل مجلد الوحدات النمطية ونضيف مقتطف الشفرة التالي:

 const { gql } = require('apollo-server-express'); const users = require('./users'); const todos = require('./todos'); const { GraphQLScalarType } = require('graphql'); const { makeExecutableSchema } = require('@graphql-tools/schema'); const typeDefs = gql` scalar Time type Query { getVersion: String! } type Mutation { version: String! } `; const timeScalar = new GraphQLScalarType({ name: 'Time', description: 'Time custom scalar type', serialize: (value) => value, }); const resolvers = { Time: timeScalar, Query: { getVersion: () => `v1`, }, }; const schema = makeExecutableSchema({ typeDefs: [typeDefs, users.typeDefs, todos.typeDefs], resolvers: [resolvers, users.resolvers, todos.resolvers], }); module.exports = schema;

تجول التعليمات البرمجية

دعنا نعمل من خلال مقتطف الشفرة ونقسمه:

الخطوة 1

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

واجهة سطر أوامر تعرض رمز "const" لاستيراد GraphQL وامتدادات أخرى.
استيراد GraphQL والإضافات.
الخطوة 2:

ثم أنشأنا نوعًا قياسيًا جديدًا للوقت ومحللنا الأول للاستعلام والطفرة التي تم إنشاؤها أعلاه. بالإضافة إلى ذلك ، أنشأنا أيضًا مخططًا باستخدام الدالة makeExecutableEchema .

يتضمن المخطط الذي تم إنشاؤه جميع المخططات الأخرى التي قمنا باستيرادها وسيشمل أيضًا المزيد عندما نقوم بإنشائها واستيرادها.

هل تعاني من مشاكل التوقف و WordPress؟ Kinsta هو حل الاستضافة المصمم لتوفير الوقت! تحقق من ميزاتنا
واجهة سطر أوامر تعرض رمز "const" لإنشاء النوع القياسي ومحللنا الأول.
إنشاء نوع قياسي للوقت بالإضافة إلى محللنا الأول.

يوضح مقتطف الشفرة أعلاه أننا قمنا باستيراد مخططات مختلفة إلى وظيفة makeExecutableEchema. يساعدنا هذا النهج في هيكلة تطبيق التعقيد. بعد ذلك ، سنقوم بإنشاء مخططات المستخدم و Todo التي قمنا باستيرادها.

إنشاء مخطط Todo

يُظهر مخطط Todo عمليات CRUD البسيطة التي يمكن لمستخدمي التطبيق تنفيذها. يوجد أدناه المخطط الذي ينفذ عملية Todo CRUD.

 const { gql } = require('apollo-server-express'); const createTodo = require('./mutations/create-todo'); const updateTodo = require('./mutations/update-todo'); const removeTodo = require('./mutations/delete-todo'); const todo = require('./queries/todo'); const todos = require('./queries/todos'); const typeDefs = gql` type Todo { id: ID! title: String description: String user: User } input CreateTodoInput { title: String! description: String isCompleted: Boolean } input UpdateTodoInput { title: String description: String isCompleted: Boolean } extend type Query { todo(id: ID): Todo! todos: [Todo!] } extend type Mutation { createTodo(input: CreateTodoInput!): Todo updateTodo(id: ID!, input: UpdateTodoInput!): Todo removeTodo(id: ID!): Todo } `; // Provide resolver functions for your schema fields const resolvers = { // Resolvers for Queries Query: { todo, todos, }, // Resolvers for Mutations Mutation: { createTodo, updateTodo, removeTodo, }, }; module.exports = { typeDefs, resolvers };

تجول التعليمات البرمجية

دعنا نعمل من خلال مقتطف الشفرة ونقسمه:

الخطوة 1:

أولاً ، أنشأنا مخططًا لـ Todo الخاص بنا باستخدام نوع GraphQL وإدخالها وتوسيعها. يتم استخدام الكلمة الأساسية الموسعة لوراثة وإضافة استعلامات وطفرات جديدة إلى استعلام الجذر الحالي والطفرة التي أنشأناها أعلاه.

واجهة سطر أوامر تعرض مخططًا لبرنامج نصي Todo الخاص بنا ، بما في ذلك المدخلات الجديدة.
إنشاء مخطط لـ Todo الخاص بنا.
الخطوة 2:

بعد ذلك ، أنشأنا وحدة الحل ، والتي تُستخدم لاسترداد البيانات الصحيحة عند استدعاء استعلام أو طفرة معينة.

واجهة سطر أوامر تعرض الكود لإنشاء محلل لـ Todo الخاص بنا.
إنشاء محلل.

مع وجود وظيفة المحلل في مكانها الصحيح ، يمكننا إنشاء طرق فردية لمنطق الأعمال ومعالجة قاعدة البيانات كما هو موضح في مثال create-todo.js .

قم بإنشاء ملف create-user.js في المجلد <code> ./mutations </code> وأضف منطق الأعمال لإنشاء Todo جديد في قاعدة البيانات الخاصة بك.

 const models = require('../../../models'); module.exports = async (root, { input }, context) => { return models.todos.push({ ...input }); };

مقتطف الشفرة أعلاه هو طريقة مبسطة لإنشاء Todo جديد في قاعدة البيانات الخاصة بنا باستخدام Sequelize ORM. يمكنك معرفة المزيد حول Sequelize وكيفية إعداده باستخدام Node.js.

يمكنك اتباع نفس الخطوة لإنشاء العديد من المخططات بناءً على التطبيق الخاص بك أو يمكنك استنساخ المشروع الكامل من GitHub.

بعد ذلك ، سنقوم بإعداد الخادم باستخدام Express.js وتشغيل تطبيق Todo الذي تم إنشاؤه حديثًا باستخدام GraphQL و Node.js

إعداد الخادم وتشغيله

أخيرًا ، سنقوم بإعداد الخادم الخاص بنا باستخدام مكتبة apollo-server-express التي قمنا بتثبيتها مسبقًا وتكوينها.

خادم apollo-server-express عبارة عن غلاف بسيط لخادم Apollo لـ Express.js ، يوصى به لأنه تم تطويره ليلائم تطوير Express.js.

باستخدام الأمثلة التي ناقشناها أعلاه ، لنقم بتهيئة خادم Express.js للعمل مع خادم apollo-server-express المثبت حديثًا.

أنشئ ملف server.js في الدليل الجذر والصقه في الكود التالي:

 const express = require('express'); const { ApolloServer } = require('apollo-server-express'); const schema = require('./modules'); const app = express(); async function startServer() { const server = new ApolloServer({ schema }); await server.start(); server.applyMiddleware({ app }); } startServer(); app.listen({ port: 3000 }, () => console.log(`Server ready at http://localhost:3000`) );

في الكود أعلاه ، نجحت في إنشاء أول خادم CRUD GraphQL لتودوس والمستخدمين. يمكنك بدء خادم التطوير الخاص بك والوصول إلى الملعب باستخدام http: // localhost: 3000 / graphql. إذا نجح كل شيء ، يجب أن تظهر لك الشاشة أدناه:

واجهة تطوير تظهر استجابة استعلام بسيط.
شاشة التحقق.

ملخص

GraphQL هي تقنية حديثة مدعومة من Facebook تعمل على تبسيط العمل الشاق الذي ينطوي عليه إنشاء واجهات برمجة تطبيقات واسعة النطاق مع أنماط معمارية RESTful.

أوضح هذا الدليل GraphQL وشرح كيفية تطوير أول واجهة برمجة تطبيقات GraphQL لديك باستخدام Express.js.

أخبرنا بما تقوم ببنائه باستخدام GraphQL.