Juniper: إنشاء واجهات GraphQL API فعالة باستخدام Rust

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

Juniper — مكتبة GraphQL للغة Rust



Juniper هي مكتبة قوية وعالية الأداء لإنشاء واجهات GraphQL API بلغة Rust. توفر للمطورين وحدات ماكرو وأنواع مناسبة لبناء المخططات (schemas) والمحللات (resolvers) ومعالجة الاستعلامات بسرعة. Juniper مثالية للمشاريع التي تكون فيها سرعة الأداء، أمان الأنواع، وانخفاض استهلاك الذاكرة أمورًا حاسمة — وهي نقاط القوة في Rust.



تدعم المكتبة كلاً من المحللات المتزامنة وغير المتزامنة (عبر async-trait)، والتكامل مع أطر الويب الشهيرة (Actix-web، Rocket، Warp، Axum)، بالإضافة إلى إمكانيات متقدمة: الاشتراكات (Subscriptions)، الأجزاء (fragments)، التوجيهات (directives)، والأنواع العددية المخصصة (custom scalars).



الميزات الرئيسية لـ Juniper



  • وحدات ماكرو للتطوير السريع: #[derive(GraphQLObject)]، #[derive(GraphQLInputObject)]، #[graphql_interface] تقوم تلقائيًا بتوليد أنواع GraphQL من هياكل Rust.
  • أمان الأنواع على مستوى التجميع: جميع أخطاء عدم تطابق المخطط وأنواع البيانات يتم اكتشافها في مرحلة البناء، وليس أثناء التشغيل.
  • دعم العمليات غير المتزامنة: تكامل مدمج مع async/await عبر juniper::graphql_object و async-graphql.
  • محللات مرنة: إمكانية استخدام السياق (context)، قواعد البيانات، واجهات API الخارجية، والمنطق التجاري المعقد.
  • الاشتراكات (WebSockets): تنفيذ الإشعارات في الوقت الفعلي باستخدام futures.
  • دعم GraphQL Playground و GraphiQL: أدوات مدمجة لاختبار الاستعلامات.


التثبيت والإعداد



أضف Juniper إلى مشروعك عبر Cargo.toml:



[dependencies]juniper = "0.16"# لدعم العمليات غير المتزامنة:juniper = { version = "0.16", features = ["async-trait"] }# للتكامل مع Actix-web:actix-web = "4"juniper-actix = "2"


يتكون الهيكل الأساسي للمخطط من ثلاثة عناصر: Query (الاستعلامات)، Mutation (التعديلات)، و Subscription (الاشتراكات). فيما يلي مثال على واجهة API بسيطة لإدارة قائمة الكتب.



مثال على الكود: إنشاء واجهة GraphQL API بسيطة



use juniper::{graphql_object, FieldResult, GraphQLObject, RootNode};

// نموذج البيانات#[derive(GraphQLObject)]struct Book { id: String, title: String, author: String, year: i32,}

// السياق (مثل الوصول إلى قاعدة البيانات)struct Context { pub books: Vec<Book>,}impl juniper::Context for Context {}

// المحللات لـ Querystruct Query;#[graphql_object]#[graphql(context = Context)]impl Query { fn books(context: &Context) -> &Vec<Book> { &context.books }

fn book_by_id(context: &Context, id: String) -> FieldResult<&Book> { context.books.iter() .find(|b| b.id == id) .ok_or_else(|| juniper::FieldError::new("Book not found", graphql_value!({"code": "NOT_FOUND"}))) }}

// المحللات لـ Mutationstruct Mutation;#[graphql_object]#[graphql(context = Context)]impl Mutation { fn add_book(context: &mut Context, title: String, author: String, year: i32) -> FieldResult<Book> { let new_book = Book { id: uuid::Uuid::new_v4().to_string(), title, author, year, }; context.books.push(new_book); Ok(new_book) }}

// إنشاء العقدة الجذريةpub type Schema = RootNode<'static, Query, Mutation>;

// نقطة الدخول لمعالجة الاستعلامpub fn create_schema() -> Schema { Schema::new(Query, Mutation)}


لتشغيل الخادم على Actix-web، استخدم الموصل الجاهز:



<                    

توصيات