يمكنك منح المستخدمين الذين يثبّتون الإضافة إمكانية إدراج منطق مخصّص في عملية تنفيذها. هناك طريقتان لإجراء ذلك:
أحداث Eventarc: لمنح المستخدمين طريقة للردّ بشكل غير متزامن على الأحداث، يمكنك النشر على Eventarc. يمكن للمستخدمين نشر دوال معالجة الأحداث التي ترسل مثلاً إشعارات بعد اكتمال المهام الطويلة، أو يمكنهم تحديد دوال المعالجة اللاحقة الخاصة بهم.
الخطافات المتزامنة: لمنح المستخدمين طريقة لإضافة منطق حظر إلى الإضافة، يمكنك إضافة خطافات متزامنة في نقاط محدّدة مسبقًا في عملية تشغيل الإضافة. في هذه النقاط، يمكنك تشغيل دالة يقدّمها المستخدم ولا يمكنك المتابعة إلا بعد اكتمالها. غالبًا ما تندرج مهام المعالجة المسبقة ضمن هذه الفئة.
يمكن للإضافة استخدام إحدى الطريقتَين أو كلتيهما.
أحداث Eventarc
لنشر الأحداث من إضافة، اتّبِع الخطوات التالية:
أعلِن عن أنواع الأحداث التي ستنشرها في ملف
extension.yaml:events: - type: publisher-id.extension-name.version.event-name description: event-description - type: publisher-id.extension-name.version.another-event-name description: another-event-descriptionيتكوّن معرّف
typeمن عدة حقول مفصولة بنقاط. حقول الرقم التعريفي للناشر واسم الإضافة واسم الحدث مطلوبة. يُنصح باستخدام حقل الإصدار. اختَر اسم حدث فريدًا ووصفيًا لكل نوع حدث تنشره.على سبيل المثال، تعلن إضافة
storage-resize-imagesعن نوع حدث واحد:events: - type: firebase.extensions.storage-resize-images.v1.complete description: | Occurs when image resizing completes. The event will contain further details about specific formats and sizes.سيتمكّن المستخدمون من اختيار الأحداث التي يريدون الاشتراك فيها عند تثبيت الإضافة.
في دوال الإضافة، استورِد Eventarc API من Admin SDK وأَنشِئ قناة أحداث باستخدام إعدادات تثبيت المستخدم. يتم عرض هذه الإعدادات باستخدام متغيّرات البيئة التالية:
EVENTARC_CHANNEL: الاسم المؤهّل بالكامل لقناة Eventarc التي اختار المستخدم نشر الأحداث عليها.EXT_SELECTED_EVENTS: قائمة قيم مفصولة بفاصلة لأنواع الأحداث التي اختار المستخدم نشرها. عند إعداد قناة باستخدام هذه القيمة، يفلتر مدير SDK تلقائيًا الأحداث التي لم يختارها المستخدم.EVENTARC_CLOUD_EVENT_SOURCE: معرّف مصدر Cloud Event. يمرّر Admin SDK تلقائيًا هذه القيمة في حقلsourceللأحداث المنشورة. لا تحتاج عادةً إلى استخدام هذا المتغيّر بشكل صريح.
إذا لم يتم تفعيل الأحداث أثناء التثبيت، ستكون هذه المتغيّرات غير محدّدة. يمكنك استخدام هذه المعلومة لإنشاء قناة أحداث فقط عندما تكون الأحداث مفعّلة:
import * as admin from "firebase-admin"; import {getEventarc} from 'firebase-admin/eventarc'; admin.initializeApp(); // Set eventChannel to a newly-initialized channel, or `undefined` if events // aren't enabled. const eventChannel = process.env.EVENTARC_CHANNEL && getEventarc().channel(process.env.EVENTARC_CHANNEL, { allowedEventTypes: process.env.EXT_SELECTED_EVENTS, });انشر الأحداث على القناة في النقاط التي تريد عرضها للمستخدمين في الإضافة. على سبيل المثال:
// If events are enabled, publish a `complete` event to the configured // channel. eventChannel && eventChannel.publish({ type: 'firebase.extensions.storage-resize-images.v1.complete', subject: filename, // the name of the original file data: { // ... } });وثِّق الأحداث التي تنشرها في ملف PREINSTALL أو POSTINSTALL.
لكل حدث، وثِّق ما يلي:
- الغرض المقصود منه
- النقطة التي يتم فيها تشغيل الحدث في منطق الإضافة
- بيانات الإخراج التي يتضمّنها
- شروط تنفيذه
بالإضافة إلى ذلك، حذِّر المستخدمين من عدم تنفيذ أي إجراءات في معالجات الأحداث التي قد تؤدي إلى تشغيل الإضافة نفسها، ما يؤدي إلى حلقة لا نهائية.
عند نشر الأحداث من إضافة، يمكن للمستخدمين نشر معالجات الأحداث للردّ باستخدام منطق مخصّص.
على سبيل المثال، يحذف المثال التالي الصورة الأصلية بعد تغيير حجمها. يُرجى العِلم أنّ معالج المثال هذا يستخدم السمة subject للحدث، وهي في هذه الحالة اسم الملف الأصلي للصورة.
exports.onimageresized = onCustomEventPublished(
"firebase.extensions.storage-resize-images.v1.complete",
(event) => {
logger.info("Received image resize completed event", event);
// For example, delete the original.
return admin.storage()
.bucket("my-project.firebasestorage.app")
.file(event.subject)
.delete();
});
لمزيد من المعلومات، اطّلِع على مشغّلات الأحداث المخصّصة.
مثال
توفر إضافة Resize Images الرسمية خطافًا غير متزامن من خلال النشر على Eventarc بعد تغيير حجم الصورة.
الخطافات المتزامنة
عندما تريد تزويد المستخدمين بخطاف يجب أن يكتمل بنجاح لكي تعمل إحدى دوال الإضافة، استخدِم الخطافات المتزامنة.
يستدعي الخطاف المتزامن دالة Cloud Function قابلة للاستدعاء عبر HTTPS يحدّدها المستخدم وينتظر اكتمالها (ربما مع قيمة يتم إرجاعها) قبل المتابعة. يؤدي حدوث خطأ في الدالة التي يقدّمها المستخدم إلى حدوث خطأ في دالة الإضافة.
لعرض خطاف متزامن، اتّبِع الخطوات التالية:
أضِف مَعلمة إلى الإضافة تسمح للمستخدمين بضبط الإضافة باستخدام عنوان URL لدالة Cloud Function المخصّصة. على سبيل المثال:
- param: PREPROCESSING_FUNCTION label: Pre-processing function URL description: > An HTTPS callable function that will be called to transform the input data before it is processed by this function. type: string example: https://us-west1-my-project-id.cloudfunctions.net/preprocessData required: falseفي النقطة التي تريد عرض الخطاف فيها في الإضافة، استدعِ الدالة باستخدام عنوان URL الخاص بها. على سبيل المثال:
const functions = require('firebase-functions/v1'); const fetch = require('node-fetch'); const preprocessFunctionURL = process.env.PREPROCESSING_FUNCTION; exports.yourFunctionName = functions.firestore.document("collection/{doc_id}") .onWrite((change, context) => { // PREPROCESSING_FUNCTION hook begins here. // If a preprocessing function is defined, call it before continuing. if (preprocessFunctionURL) { try { await fetch(preprocessFunctionURL); // Could also be a POST request if you want to send data. } catch (e) { // Preprocessing failure causes the function to fail. functions.logger.error("Preprocessor error:", e); return; } } // End of PREPROCESSING_FUNCTION hook. // Main function logic follows. // ... });وثِّق أي خطافات تتيحها في ملف PREINSTALL أو POSTINSTALL.
لكل خطاف، وثِّق ما يلي:
- الغرض المقصود منه
- النقطة التي يتم فيها تشغيل الخطاف في منطق الإضافة
- المدخلات والمخرجات المتوقّعة
- شروط تنفيذه (أو خياراته)
بالإضافة إلى ذلك، حذِّر المستخدمين من عدم تنفيذ أي إجراءات في دالة الخطاف قد تؤدي إلى تشغيل الإضافة نفسها، ما يؤدي إلى حلقة لا نهائية.
مثال
توفر إضافة Algolia Search خطافًا متزامنًا لـ استدعاء دالة تحويل يقدّمها المستخدم قبل الكتابة إلى Algolia.