توضّح لك هذه الصفحة الخطوات المطلوبة لإنشاء إضافة بسيطة في Firebase يمكنك تثبيتها في مشاريعك أو مشاركتها مع الآخرين. سيرصد هذا المثال البسيط لإحدى إضافات Firebase الرسائل في قاعدة البيانات الآنية الاستجابة ويحوّلها إلى أحرف كبيرة.
1. إعداد البيئة وبدء مشروع
قبل أن تتمكّن من بدء إنشاء إضافة، عليك إعداد بيئة إنشاء تتضمّن الأدوات المطلوبة.
ثبِّت الإصدار 16 من Node.js أو إصدارًا أحدث. إحدى طرق تثبيت Node هي استخدام nvm (أو nvm-windows).
ثبِّت أحدث إصدار من Firebase CLI أو حدِّثه. لتثبيت
npm
أو تحديثه، شغِّل الأمر التالي:npm install -g firebase-tools
الآن، استخدِم واجهة سطر الأوامر في Firebase لتهيئة مشروع إضافة جديد:
أنشئ دليلاً للإضافة وانتقِل إلى
cd
:mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
نفِّذ الأمر
ext:dev:init
في واجهة سطر الأوامر (CLI) الخاصة بخدمة Firebase:firebase ext:dev:init
عندما يُطلب منك ذلك، اختَر JavaScript كلغة للدوال (مع العلم أنّه يمكنك أيضًا استخدام TypeScript عند تطوير إضافة خاصة بك)، وعندما يُطلب منك تثبيت التبعيات، أجب بـ "نعم". (اقبل الإعدادات التلقائية لأي خيارات أخرى). سيؤدي هذا الأمر إلى إعداد قاعدة رموز أساسية لإضافة جديدة، يمكنك من خلالها بدء تطوير الإضافة.
2- تجربة إضافة المثال باستخدام المحاكي
عندما أعدّت واجهة سطر الأوامر (CLI) في Firebase دليل الإضافات الجديد، أنشأت دالة مثال بسيطة ودليل integration-tests
يحتوي على الملفات اللازمة لتشغيل إضافة باستخدام "مجموعة المحاكي" في Firebase.
جرِّب تشغيل نموذج الإضافة في المحاكي:
انتقِل إلى الدليل
integration-tests
:cd functions/integration-tests
ابدأ المحاكي بمشروع تجريبي:
firebase emulators:start --project=demo-test
يحمّل المحاكي الإضافة في مشروع "وهمي" محدّد مسبقًا (
demo-test
). تتألف الإضافة حتى الآن من دالة واحدة يتم تشغيلها عبر HTTP، وهيgreetTheWorld
، وتعرض رسالة "hello world" عند الوصول إليها.مع استمرار تشغيل المحاكي، جرِّب وظيفة الإضافة
greetTheWorld
من خلال الانتقال إلى عنوان URL الذي تمت طباعته عند بدء تشغيل المحاكي.يعرض المتصفّح الرسالة "Hello World from greet-the-world".
يتوفّر الرمز المصدر لهذه الدالة في دليل
functions
الخاص بالإضافة. افتح المصدر في المحرّر أو بيئة التطوير المتكاملة (IDE) التي تختارها:functions/index.js
const functions = require("firebase-functions/v1"); exports.greetTheWorld = functions.https.onRequest((req, res) => { // Here we reference a user-provided parameter // (its value is provided by the user during installation) const consumerProvidedGreeting = process.env.GREETING; // And here we reference an auto-populated parameter // (its value is provided by Firebase after installation) const instanceId = process.env.EXT_INSTANCE_ID; const greeting = `${consumerProvidedGreeting} World from ${instanceId}`; res.send(greeting); });
أثناء تشغيل المحاكي، سيتم تلقائيًا إعادة تحميل أي تغييرات تجريها على رمز الدوال البرمجية. جرِّب إجراء تغيير بسيط على الدالة
greetTheWorld
:functions/index.js
const greeting = `${consumerProvidedGreeting} everyone, from ${instanceId}`;
احفظ التغييرات. ستعيد المحاكي تحميل الرمز، وعندما تنتقل إلى عنوان URL الخاص بالدالة، ستظهر لك رسالة الترحيب المعدَّلة.
3- إضافة معلومات أساسية إلى ملف extension.yaml
بعد إعداد بيئة التطوير وتشغيل محاكي الإضافات، يمكنك البدء في كتابة الإضافة الخاصة بك.
كخطوة أولى بسيطة، عدِّل البيانات الوصفية المحدّدة مسبقًا للإضافة لتعكس الإضافة التي تريد كتابتها بدلاً من greet-the-world
. يتم تخزين هذه البيانات الوصفية في الملف extension.yaml
.
افتح ملف
extension.yaml
في المحرّر الخاص بك، واستبدِل محتوى الملف بالكامل بما يلي:name: rtdb-uppercase-messages version: 0.0.1 specVersion: v1beta # Firebase Extensions specification version; don't change # Friendly display name for your extension (~3-5 words) displayName: Convert messages to upper case # Brief description of the task your extension performs (~1 sentence) description: >- Converts messages in RTDB to upper case author: authorName: Your Name url: https://your-site.example.com license: Apache-2.0 # Required license # Public URL for the source code of your extension sourceUrl: https://github.com/your-name/your-repo
لاحظ اصطلاح التسمية المستخدَم في الحقل
name
: يتم تسمية إضافات Firebase الرسمية ببادئة تشير إلى منتج Firebase الأساسي الذي تعمل عليه الإضافة، متبوعة بوصف لما تفعله الإضافة. عليك استخدام الاصطلاح نفسه في إضافاتك.بما أنّك غيّرت اسم الإضافة، عليك أيضًا تعديل إعدادات المحاكي باستخدام الاسم الجديد:
- في
functions/integration-tests/firebase.json
، غيِّرgreet-the-world
إلىrtdb-uppercase-messages
. - أعِد تسمية
functions/integration-tests/extensions/greet-the-world.env
إلىfunctions/integration-tests/extensions/rtdb-uppercase-messages.env
.
- في
لا تزال بعض بقايا الإضافة greet-the-world
متوفرة في رمز الإضافة، ولكن لا بأس من تركها في الوقت الحالي. ستعدّل هذه المعلومات في الأقسام القليلة التالية.
4. كتابة دالة Cloud Function وتعريفها كمورد إضافة
يمكنك الآن البدء بكتابة بعض الرموز البرمجية. في هذه الخطوة، ستكتب Cloud Function تنفّذ المهمة الأساسية للإضافة، وهي مراقبة قاعدة بيانات الوقت الفعلي بحثًا عن الرسائل وتحويلها إلى أحرف كبيرة.
افتح مصدر وظائف الإضافة (في الدليل
functions
الخاص بالإضافة) في المحرّر أو بيئة التطوير المتكاملة (IDE) التي تختارها. استبدِل محتواه بما يلي:functions/index.js
import { database, logger } from "firebase-functions/v1"; const app = initializeApp(); // Listens for new messages added to /messages/{pushId}/original and creates an // uppercase version of the message to /messages/{pushId}/uppercase // for all databases in 'us-central1' export const makeuppercase = database .ref("/messages/{pushId}/uppercase") .onCreate(async (snapshot, context) => { // Grab the current value of what was written to the Realtime Database. const original = snapshot.val(); // Convert it to upper case. logger.log("Uppercasing", context.params.pushId, original); const uppercase = original.toUpperCase(); // Setting an "uppercase" sibling in the Realtime Database. const upperRef = snapshot.ref.parent.child("upper"); await upperRef.set(uppercase); });
كانت الدالة القديمة التي استبدلتها دالة يتم تشغيلها عند تلقّي طلب HTTP، أي أنّها كانت تعمل عند الوصول إلى نقطة نهاية HTTP. يتم تشغيل الدالة الجديدة من خلال أحداث قاعدة البيانات في الوقت الفعلي: تراقب الدالة العناصر الجديدة في مسار معيّن، وعندما يتم رصد عنصر جديد، تكتب الدالة نسخة بأحرف كبيرة من القيمة مرة أخرى إلى قاعدة البيانات.
بالمناسبة، يستخدم هذا الملف الجديد بنية وحدة ECMAScript (
import
وexport
) بدلاً من CommonJS (require
). لاستخدام وحدات ES في Node، حدِّد"type": "module"
فيfunctions/package.json
:{ "name": "rtdb-uppercase-messages", "main": "index.js", "type": "module", … }
يجب تعريف كل دالة في الإضافة في ملف
extension.yaml
. في مثال الإضافة، تم تعريفgreetTheWorld
على أنّه دالة Cloud الوحيدة للإضافة، والآن بعد استبدالها بـmakeuppercase
، عليك أيضًا تعديل تعريفها.افتح
extension.yaml
وأضِف حقلresources
:resources: - name: makeuppercase type: firebaseextensions.v1beta.function properties: eventTrigger: eventType: providers/google.firebase.database/eventTypes/ref.create # DATABASE_INSTANCE (project's default instance) is an auto-populated # parameter value. You can also specify an instance. resource: projects/_/instances/${DATABASE_INSTANCE}/refs/messages/{pushId}/original runtime: "nodejs18"
بما أنّ الإضافة تستخدم الآن Realtime Database كمشغّل، عليك تعديل إعدادات المحاكي لتشغيل محاكي RTDB إلى جانب محاكي Cloud Functions:
إذا كان المحاكي لا يزال قيد التشغيل، أوقِفه بالضغط على Ctrl-C.
من دليل
functions/integration-tests
، شغِّل الأمر التالي:firebase init emulators
عندما يُطلب منك ذلك، تخطَّ إعداد مشروع تلقائي، ثم اختَر محاكيَي Functions وDatabase. اقبل المنافذ التلقائية واسمح لأداة الإعداد بتنزيل أي ملفات مطلوبة.
أعِد تشغيل المحاكي:
firebase emulators:start --project=demo-test
جرِّب الإضافة بعد تحديثها:
افتح واجهة مستخدم محاكي قاعدة البيانات باستخدام الرابط الذي طبعه المحاكي عند بدء تشغيله.
عدِّل العقدة الجذرية لقاعدة البيانات:
- الحقل:
messages
- النوع:
json
- القيمة:
{"11": {"original": "recipe"}}
إذا تم إعداد كل شيء بشكل صحيح، عند حفظ تغييرات قاعدة البيانات، من المفترض أن يتم تشغيل الدالة
makeuppercase
الخاصة بالإضافة وإضافة سجل فرعي إلى الرسالة 11 يتضمّن المحتوى"upper": "RECIPE"
. ألقِ نظرة على علامات التبويب الخاصة بالسجلات وقاعدة البيانات في واجهة مستخدم المحاكي للتأكّد من النتائج المتوقّعة.- الحقل:
حاوِل إضافة المزيد من الأطفال إلى العقدة
messages
({"original":"any text"}
). عند إضافة سجلّ جديد، يجب أن تضيف الإضافة حقلuppercase
يحتوي على محتوى الحقلoriginal
بأحرف كبيرة.
أصبح لديك الآن إضافة كاملة، وإن كانت بسيطة، تعمل على مثيل RTDB. في الأقسام التالية، ستعمل على تحسين هذه الإضافة باستخدام بعض الميزات الإضافية. بعد ذلك، ستتعرّف على كيفية إعداد الإضافة لتوزيعها على المستخدمين الآخرين، وأخيرًا، ستتعرّف على كيفية نشرها في "مركز الإضافات".
5- تحديد واجهات برمجة التطبيقات والأدوار
يمنح Firebase كل نسخة من إضافة مثبَّتة إذن وصول محدودًا إلى المشروع وبياناته باستخدام حساب خدمة لكل نسخة. يحتوي كل حساب على الحد الأدنى من الأذونات اللازمة لتشغيله. لهذا السبب، يجب أن تحدّد بوضوح أي أدوار في "إدارة الهوية وإمكانية الوصول" تتطلّبها الإضافة. وعندما يثبّت المستخدمون الإضافة، ينشئ Firebase حساب خدمة مع منح هذه الأدوار ويستخدمه لتشغيل الإضافة.
ليس عليك تحديد أدوار لتفعيل أحداث أحد المنتجات، ولكن عليك تحديد دور للتفاعل معه. بما أنّ الدالة التي أضفتها في الخطوة الأخيرة تكتب إلى Realtime Database، عليك إضافة التصريح التالي إلى extension.yaml
:
roles:
- role: firebasedatabase.admin
reason: Allows the extension to write to RTDB.
وبالمثل، عليك الإفصاح عن واجهات Google API التي تستخدمها الإضافة في الحقل apis
. عندما يثبّت المستخدمون إضافتك، سيُسألون عمّا إذا كانوا يريدون تفعيل واجهات برمجة التطبيقات هذه تلقائيًا لمشروعهم. لا يكون ذلك ضروريًا عادةً إلا لواجهات Google API غير التابعة لـ Firebase، ولا نحتاج إليه في هذا الدليل.
6. تحديد المَعلمات التي يمكن للمستخدم ضبطها
تراقب الدالة التي أنشأتها في الخطوتَين الأخيرتَين موقعًا جغرافيًا محدّدًا في قاعدة بيانات RTDB بحثًا عن الرسائل الواردة. في بعض الأحيان، قد يكون من المفيد مراقبة موقع جغرافي معيّن، مثلاً عندما تعمل الإضافة على بنية قاعدة بيانات تستخدمها حصريًا للإضافة. ومع ذلك، في معظم الأحيان، ستحتاج إلى أن تكون هذه القيم قابلة للإعداد من قِبل المستخدمين الذين يثبّتون الإضافة في مشاريعهم. بهذه الطريقة، يمكن للمستخدمين الاستفادة من إضافتك للعمل مع إعداد قاعدة البيانات الحالية.
إتاحة إمكانية ضبط المسار الذي تراقب الإضافة فيه الرسائل الجديدة من قِبل المستخدم:
في ملف
extension.yaml
، أضِف قسمparams
:- param: MESSAGE_PATH label: Message path description: >- What is the path at which the original text of a message can be found? type: string default: /messages/{pushId}/original required: true immutable: false
يحدّد هذا الخيار مَعلمة سلسلة جديدة سيُطلب من المستخدمين ضبطها عند تثبيت الإضافة.
في ملف
extension.yaml
، ارجع إلى بيانmakeuppercase
وعدِّل الحقلresource
إلى ما يلي:resource: projects/_/instances/${DATABASE_INSTANCE}/refs/${param:MESSAGE_PATH}
الرمز المميّز
${param:MESSAGE_PATH}
هو مرجع إلى المَعلمة التي حدّدتها للتو. عند تشغيل الإضافة، سيتم استبدال هذا الرمز المميز بأي قيمة ضبطها المستخدم لهذه المَعلمة، ونتيجةً لذلك، ستستمع الدالةmakeuppercase
إلى المسار الذي حدّده المستخدم. يمكنك استخدام هذه الصيغة للإشارة إلى أي مَعلمة يحدّدها المستخدم في أي مكان فيextension.yaml
(وفيPOSTINSTALL.md
أيضًا، وسنتحدّث عن ذلك لاحقًا).يمكنك أيضًا الوصول إلى المَعلمات التي يحدّدها المستخدم من رمز الدوال البرمجية.
في الدالة التي كتبتها في القسم الأخير، حدّدت المسار الذي يجب مراقبة التغييرات فيه بشكل ثابت. غيِّر تعريف المشغّل للإشارة إلى القيمة التي يحدّدها المستخدم بدلاً من ذلك:
functions/index.js
export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate
يُرجى العِلم أنّ هذا التغيير في "إضافات Firebase" يهدف فقط إلى تحسين المستندات: عند نشر إحدى دوال Cloud كجزء من إضافة، تستخدم هذه الدالة تعريف المشغّل من ملف
extension.yaml
وتتجاهل القيمة المحدّدة في تعريف الدالة. ومع ذلك، من المستحسن توثيق مصدر هذه القيمة في الرمز البرمجي.قد يكون من المحبط إجراء تغيير في الرمز البرمجي لا يؤدي إلى أي تأثير في وقت التشغيل، ولكن الدرس المهم الذي يجب استخلاصه هو أنّه يمكنك الوصول إلى أي مَعلمة يحدّدها المستخدم في رمز الدالة واستخدامها كقيمة عادية في منطق الدالة. لإثبات هذه الإمكانية، أضِف عبارة السجلّ التالية لتوضيح أنّك تصل بالفعل إلى القيمة التي حدّدها المستخدم:
functions/index.js
export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate( async (snapshot, context) => { logger.log("Found new message at ", snapshot.ref); // Grab the current value of what was written to the Realtime Database. ...
عادةً، يُطلب من المستخدمين تقديم قيم للمَعلمات عند تثبيت إضافة. عند استخدام المحاكي للاختبار والتطوير، يمكنك تخطّي عملية التثبيت، لذا عليك بدلاً من ذلك تقديم قيم للمَعلمات التي يحدّدها المستخدم باستخدام ملف
env
.افتح
functions/integration-tests/extensions/rtdb-uppercase-messages.env
واستبدِل تعريفGREETING
بما يلي:MESSAGE_PATH=/msgs/{pushId}/original
لاحظ أنّ المسار أعلاه يختلف عن المسار التلقائي والمسار الذي حدّدته سابقًا، وذلك فقط لإثبات أنّ التعريف يسري عند تجربة الإضافة المعدَّلة.
الآن، أعِد تشغيل المحاكي وانتقِل مرة أخرى إلى واجهة مستخدم محاكي قاعدة البيانات.
عدِّل العقدة الجذر لقاعدة البيانات باستخدام المسار الذي حدّدته أعلاه:
- الحقل:
msgs
- النوع:
json
- القيمة:
{"11": {"original": "recipe"}}
عند حفظ تغييرات قاعدة البيانات، من المفترض أن يتم تشغيل وظيفة
makeuppercase
الخاصة بالإضافة كما كان يحدث من قبل، ولكن من المفترض الآن أن تطبع أيضًا المَعلمة التي يحدّدها المستخدم في سجلّ وحدة التحكّم.- الحقل:
7. توفير نقاط ربط الأحداث للمنطق الذي يحدّده المستخدم
بصفتك مطوّر إضافة، سبق لك أن رأيت كيف يمكن لأحد منتجات Firebase أن يؤدي إلى تشغيل منطق توفّره الإضافة: يؤدي إنشاء سجلات جديدة في Realtime Database إلى تشغيل الدالة makeuppercase
. يمكن أن يكون لإضافتك علاقة مماثلة مع المستخدمين الذين يثبّتونها، إذ يمكن لإضافتك تشغيل منطق يحدّده المستخدم.
يمكن أن توفّر الإضافة خطافات متزامنة أو خطافات غير متزامنة أو كليهما. تتيح خطافات التزامن للمستخدمين طريقة لتنفيذ مهام تمنع إكمال إحدى وظائف الإضافة. ويمكن أن يكون ذلك مفيدًا، على سبيل المثال، لمنح المستخدمين طريقة لإجراء معالجة مسبقة مخصّصة قبل أن ينفّذ أحد الإضافات عمله.
في هذا الدليل، ستضيف خطافًا غير متزامن إلى الإضافة، ما يتيح للمستخدمين تحديد خطوات المعالجة الخاصة بهم التي سيتم تنفيذها بعد أن تكتب الإضافة الرسالة بالأحرف الكبيرة في Realtime Database. تستخدم خطافات غير متزامنة Eventarc لتشغيل الدوال المعرَّفة من قِبل المستخدم. تحدّد الإضافات أنواع الأحداث التي تصدرها، وعندما يثبّت المستخدمون الإضافة، يختارون أنواع الأحداث التي تهمّهم. إذا اختار المستخدم حدثًا واحدًا على الأقل، ستوفّر Firebase قناة Eventarc للإضافة كجزء من عملية التثبيت. يمكن للمستخدمين بعد ذلك نشر دوال Cloud الخاصة بهم التي تستمع إلى هذه القناة وتعمل عند نشر الإضافة لأحداث جديدة.
اتّبِع الخطوات التالية لإضافة خطاف غير متزامن:
في ملف
extension.yaml
، أضِف القسم التالي الذي يحدّد نوع الحدث الوحيد الذي يرسله الامتداد:events: - type: test-publisher.rtdb-uppercase-messages.v1.complete description: >- Occurs when message uppercasing completes. The event subject will contain the RTDB URL of the uppercase message.
يجب أن تكون أنواع الأحداث فريدة على مستوى العالم. ولضمان ذلك، احرص دائمًا على تسمية أحداثك باستخدام التنسيق التالي:
<publisher-id>.<extension-id>.<version>.<description>
. (ليس لديك معرّف ناشر حتى الآن، لذا استخدِمtest-publisher
في الوقت الحالي).في نهاية الدالة
makeuppercase
، أضِف بعض الرموز التي تنشر حدثًا من النوع الذي حدّدته للتو:functions/index.js
// Import the Eventarc library: import { initializeApp } from "firebase-admin/app"; import { getEventarc } from "firebase-admin/eventarc"; const app = initializeApp(); // In makeuppercase, after upperRef.set(uppercase), add: // 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: "test-publisher.rtdb-uppercase-messages.v1.complete", subject: upperRef.toString(), data: { "original": original, "uppercase": uppercase, }, });
يستفيد نموذج الرمز هذا من حقيقة أنّه لا يتم تحديد متغيّر البيئة
EVENTARC_CHANNEL
إلا عندما يفعّل المستخدم نوع حدث واحدًا على الأقل. وإذا لم يتم تحديدEVENTARC_CHANNEL
، لن يحاول الرمز نشر أي أحداث.يمكنك إرفاق معلومات إضافية بحدث Eventarc. في المثال أعلاه، يحتوي الحدث على حقل
subject
يتضمّن مرجعًا إلى القيمة التي تم إنشاؤها حديثًا، وحمولةdata
تتضمّن الرسائل الأصلية والرسائل بأحرف كبيرة. يمكن للدوال المعرَّفة من قِبل المستخدم التي يتم تشغيلها عند وقوع الحدث الاستفادة من هذه المعلومات.عادةً، يتم تحديد متغيرَي البيئة
EVENTARC_CHANNEL
وEXT_SELECTED_EVENTS
استنادًا إلى الخيارات التي يحدّدها المستخدم أثناء عملية التثبيت. للاختبار باستخدام المحاكي، حدِّد هذه المتغيرات يدويًا في ملفrtdb-uppercase-messages.env
:EVENTARC_CHANNEL=locations/us-central1/channels/firebase EXT_SELECTED_EVENTS=test-publisher.rtdb-uppercase-messages.v1.complete
في هذه المرحلة، تكون قد أكملت الخطوات اللازمة لإضافة أداة ربط حدث غير متزامن إلى الإضافة.
لتجربة هذه الميزة الجديدة التي نفّذتها للتو، اتّبِع الخطوات القليلة التالية، وافترِض أنّك مستخدم يثبّت الإضافة:
من الدليل
functions/integration-tests
، ابدأ مشروعًا جديدًا على Firebase:firebase init functions
عندما يُطلب منك ذلك، ارفض إعداد مشروع تلقائي، واختَر JavaScript كلغة Cloud Functions، وثبِّت التبعيات المطلوبة. يمثّل هذا المشروع مشروع مستخدم تم تثبيت الإضافة عليه.
عدِّل
integration-tests/functions/index.js
وألصِق الرمز التالي:import { logger } from "firebase-functions/v1"; import { onCustomEventPublished } from "firebase-functions/v2/eventarc"; import { initializeApp } from "firebase-admin/app"; import { getDatabase } from "firebase-admin/database"; const app = initializeApp(); export const extraemphasis = onCustomEventPublished( "test-publisher.rtdb-uppercase-messages.v1.complete", async (event) => { logger.info("Received makeuppercase completed event", event); const refUrl = event.subject; const ref = getDatabase().refFromURL(refUrl); const upper = (await ref.get()).val(); return ref.set(`${upper}!!!`); } );
هذا مثال على دالة ما بعد المعالجة التي قد يكتبها المستخدم. في هذه الحالة، تستمع الدالة إلى الإضافة لنشر حدث
complete
، وعندما يتم تشغيلها، تضيف ثلاث علامات تعجّب إلى الرسالة التي تم تحويلها إلى أحرف كبيرة حديثًا.أعِد تشغيل المحاكي. سيحمّل المحاكي وظائف الإضافة بالإضافة إلى وظيفة ما بعد المعالجة التي حدّدها "المستخدم".
انتقِل إلى واجهة مستخدم محاكي قاعدة البيانات وعدِّل العقدة الجذرية لقاعدة البيانات باستخدام المسار الذي حدّدته أعلاه:
- الحقل:
msgs
- النوع:
json
- القيمة:
{"11": {"original": "recipe"}}
عند حفظ تغييرات قاعدة البيانات، يجب أن يتم تشغيل الدالتَين
makeuppercase
وextraemphasis
بالتسلسل، ما يؤدي إلى حصول الحقلupper
على القيمةRECIPE!!!
.- الحقل:
8. إضافة معالِجات أحداث مراحل النشاط
تعالج الإضافة التي كتبتها حتى الآن الرسائل عند إنشائها. ولكن ماذا لو كان لدى المستخدمين قاعدة بيانات للرسائل عند تثبيت الإضافة؟ تتضمّن "إضافات Firebase" ميزة تُعرف باسم خطافات أحداث دورة الحياة يمكنك استخدامها لتفعيل إجراءات عند تثبيت الإضافة أو تحديثها أو إعادة ضبطها. في هذا القسم، ستستخدم خطافات أحداث دورة الحياة لملء قاعدة بيانات الرسائل الحالية في المشروع برسائل بأحرف كبيرة عند تثبيت المستخدم للإضافة.
تستخدم "إضافات Firebase" خدمة Cloud Tasks لتشغيل معالِجات أحداث مراحل النشاط. يمكنك تحديد معالجات الأحداث باستخدام Cloud Functions. وعندما يصل مثيل من الإضافة إلى أحد أحداث دورة الحياة المتوافقة، سيضيف المعالج إلى قائمة انتظار Cloud Tasks إذا كنت قد حدّدت معالجًا. بعد ذلك، ستنفّذ Cloud Tasks المعالج بشكل غير متزامن. أثناء تنفيذ معالج حدث دورة الحياة، ستُبلغ وحدة تحكّم Firebase المستخدم بأنّ مثيل الإضافة لديه مهمة معالجة قيد التقدّم. ويعود إلى دالة المعالجة مسؤولية إبلاغ المستخدم بحالة العملية الجارية واكتمال المهمة.
لإضافة معالج أحداث دورة الحياة الذي يعيد ملء الرسائل الحالية، اتّبِع الخطوات التالية:
حدِّد دالة Cloud جديدة يتم تشغيلها من خلال أحداث قائمة المهام:
functions/index.js
import { tasks } from "firebase-functions/v1"; import { getDatabase } from "firebase-admin/database"; import { getExtensions } from "firebase-admin/extensions"; import { getFunctions } from "firebase-admin/functions"; export const backfilldata = tasks.taskQueue().onDispatch(async () => { const batch = await getDatabase() .ref(process.env.MESSAGE_PATH) .parent.parent.orderByChild("upper") .limitToFirst(20) .get(); const promises = []; for (const key in batch.val()) { const msg = batch.child(key); if (msg.hasChild("original") && !msg.hasChild("upper")) { const upper = msg.child("original").val().toUpperCase(); promises.push(msg.child("upper").ref.set(upper)); } } await Promise.all(promises); if (promises.length > 0) { const queue = getFunctions().taskQueue( "backfilldata", process.env.EXT_INSTANCE_ID ); return queue.enqueue({}); } else { return getExtensions() .runtime() .setProcessingState("PROCESSING_COMPLETE", "Backfill complete."); } });
لاحظ أنّ الدالة تعالج بضعة سجلّات فقط قبل إعادة إضافتها إلى قائمة انتظار المهام. هذه استراتيجية شائعة الاستخدام للتعامل مع مهام المعالجة التي لا يمكن إكمالها خلال فترة المهلة المحدّدة في Cloud Function. بما أنّه لا يمكنك توقّع عدد الرسائل التي قد تكون لدى المستخدم في قاعدة البيانات عند تثبيت الإضافة، فإنّ هذه الاستراتيجية مناسبة.
في ملف
extension.yaml
، عرِّف دالة الإعلانات الاحتياطية كمورد إضافة يتضمّن السمةtaskQueueTrigger
:resources: - name: makeuppercase ... - name: backfilldata type: firebaseextensions.v1beta.function description: >- Backfill existing messages with uppercase versions properties: runtime: "nodejs18" taskQueueTrigger: {}
بعد ذلك، عرِّف الدالة على أنّها معالج حدث دورة الحياة
onInstall
:lifecycleEvents: onInstall: function: backfilldata processingMessage: Uppercasing existing messages
على الرغم من أنّ إعادة ملء الرسائل الحالية هي ميزة مفيدة، يمكن أن تعمل الإضافة بدونها. في مثل هذه الحالات، يجب أن يكون تشغيل معالجات أحداث مراحل النشاط اختياريًا.
لإجراء ذلك، أضِف مَعلمة جديدة إلى
extension.yaml
:- param: DO_BACKFILL label: Backfill existing messages description: >- Generate uppercase versions of existing messages? type: select required: true options: - label: Yes value: true - label: No value: false
بعد ذلك، في بداية دالة التعبئة، تحقَّق من قيمة المَعلمة
DO_BACKFILL
واخرج مبكرًا إذا لم يتم ضبطها:functions/index.js
if (!process.env.DO_BACKFILL) { return getExtensions() .runtime() .setProcessingState("PROCESSING_COMPLETE", "Backfill skipped."); }
بعد إجراء التغييرات المذكورة أعلاه، ستحوّل الإضافة الرسائل الحالية إلى أحرف كبيرة عند تثبيتها.
حتى هذه المرحلة، كنت تستخدم محاكي الإضافة لتطوير الإضافة واختبار التغييرات الجارية. ومع ذلك، يتخطى محاكي الإضافة عملية التثبيت، لذا لاختبار معالج الحدث onInstall
، عليك تثبيت الإضافة في مشروع حقيقي. وهذا أمر جيد، لأنّه مع إضافة ميزة التعبئة التلقائية هذه، أصبحت إضافة البرنامج التعليمي الآن مكتملة من حيث الرموز البرمجية.
9. النشر في مشروع حقيقي على Firebase
على الرغم من أنّ محاكي الإضافات هو أداة رائعة لتكرار إضافة بسرعة أثناء عملية التطوير، ستحتاج في مرحلة ما إلى تجربتها في مشروع حقيقي.
لإجراء ذلك، عليك أولاً إعداد مشروع جديد مع تفعيل بعض الخدمات:
- في وحدة تحكّم Firebase، أضِف مشروعًا جديدًا.
- رقِّي مشروعك إلى خطة Blaze بنظام الدفع حسب الاستخدام. تتطلّب Cloud Functions for Firebase أن يتضمّن مشروعك حساب فوترة، لذا يجب أن يكون لديك حساب فوترة أيضًا لتثبيت إضافة.
- في مشروعك الجديد، فعِّل Realtime Database.
- بما أنّك تريد اختبار قدرة الإضافة على إعادة ملء البيانات الحالية عند التثبيت، استورِد بعض البيانات النموذجية إلى مثيل قاعدة البيانات في الوقت الفعلي:
- نزِّل بعض بيانات RTDB الأولية.
- في صفحة Realtime Database ضمن وحدة تحكّم Firebase، انقر على (المزيد) > استيراد JSON واختَر الملف الذي نزّلته للتو.
لتفعيل وظيفة التعبئة الخلفية لاستخدام طريقة
orderByChild
، اضبط قاعدة البيانات لفهرسة الرسائل حسب قيمةupper
:{ "rules": { ".read": false, ".write": false, "messages": { ".indexOn": "upper" } } }
الآن، ثبِّت الإضافة من المصدر المحلي في المشروع الجديد:
أنشئ دليلاً جديدًا لمشروعك على Firebase:
mkdir ~/extensions-live-test && cd ~/extensions-live-test
ابدأ مشروع Firebase في دليل العمل:
firebase init database
عندما يُطلب منك ذلك، اختَر المشروع الذي أنشأته للتو.
ثبِّت الإضافة في مشروع Firebase المحلي:
firebase ext:install /path/to/rtdb-uppercase-messages
يمكنك هنا الاطّلاع على تجربة المستخدم عند تثبيت إضافة باستخدام أداة Firebase CLI. احرص على اختيار "نعم" عندما تسألك أداة الإعداد عمّا إذا كنت تريد إعادة ملء قاعدة البيانات الحالية.
بعد اختيار خيارات الإعداد، ستحفظ واجهة سطر الأوامر (CLI) الخاصة بـ Firebase إعداداتك في الدليل
extensions
وستسجّل موقع مصدر الإضافة في الملفfirebase.json
. ويُطلق على هذين السجلّين معًا اسم بيان الإضافات. يمكن للمستخدمين استخدام ملف البيان لحفظ إعدادات الإضافات ونشرها في مشاريع مختلفة.انشر إعدادات الإضافة في مشروعك المباشر باتّباع الخطوات التالية:
firebase deploy --only extensions
إذا سارت الأمور على ما يرام، من المفترض أن تحمّل واجهة سطر الأوامر (CLI) الخاصة بمنصة Firebase الإضافة إلى مشروعك وتثبّتها. بعد اكتمال عملية التثبيت، سيتم تشغيل مهمة التعبئة، وسيتم تعديل قاعدة البيانات لتتضمّن الرسائل بأحرف كبيرة في غضون بضع دقائق. أضِف بعض العُقد الجديدة إلى قاعدة بيانات الرسائل وتأكَّد من أنّ الإضافة تعمل أيضًا مع الرسائل الجديدة.
10. كتابة مستندات
قبل مشاركة الإضافة مع المستخدمين، تأكَّد من توفير قدر كافٍ من المستندات لمساعدتهم على تحقيق النجاح.
عندما بدأت مشروع الإضافة، أنشأت واجهة سطر الأوامر (CLI) من Firebase إصدارات تجريبية من الحد الأدنى المطلوب من المستندات. عدِّل هذه الملفات لتعكس بدقة الامتداد الذي أنشأته.
extension.yaml
لقد سبق لك تعديل هذا الملف أثناء تطوير هذه الإضافة، لذا ليس عليك إجراء أي تعديلات أخرى في الوقت الحالي.
ومع ذلك، لا تتجاهل أهمية المستندات الواردة في هذا الملف. بالإضافة إلى المعلومات الأساسية التي تحدّد هوية الإضافة، مثل الاسم والوصف والمؤلف وموقع المستودع الرسمي، يحتوي ملف extension.yaml
على مستندات موجّهة للمستخدمين لكل مورد ومَعلمات يمكن للمستخدم ضبطها. تظهر هذه المعلومات للمستخدمين في وحدة تحكّم Firebase و"مركز الإضافات" وFirebase CLI.
PREINSTALL.md
في هذا الملف، قدِّم المعلومات التي يحتاجها المستخدم قبل تثبيت الإضافة، مثل وصف موجز لوظيفة الإضافة، وتوضيح أي متطلبات أساسية، وتقديم معلومات للمستخدم حول الآثار المترتبة على تثبيت الإضافة من حيث الفوترة. إذا كان لديك موقع إلكتروني يتضمّن معلومات إضافية، يمكنك أيضًا إضافة رابط إليه في هذا القسم.
يتم عرض نص هذا الملف للمستخدم في "مركز الإضافات" وباستخدام الأمر
firebase ext:info
.
في ما يلي مثال على ملف PREINSTALL:
Use this extension to automatically convert strings to upper case when added to
a specified Realtime Database path.
This extension expects a database layout like the following example:
"messages": {
MESSAGE_ID: {
"original": MESSAGE_TEXT
},
MESSAGE_ID: {
"original": MESSAGE_TEXT
},
}
When you create new string records, this extension creates a new sibling record
with upper-cased text:
MESSAGE_ID: {
"original": MESSAGE_TEXT,
"upper": UPPERCASE_MESSAGE_TEXT,
}
#### Additional setup
Before installing this extension, make sure that you've
[set up Realtime Database](https://firebase.google.com/docs/database/quickstart)
in your Firebase project.
#### Billing
To install an extension, your project must be on the
[Blaze (pay as you go) plan](https://firebase.google.com/pricing).
- This extension uses other Firebase and Google Cloud Platform services, which
have associated charges if you exceed the service's no-cost tier:
- Realtime Database
- Cloud Functions (Node.js 10+ runtime)
[See FAQs](https://firebase.google.com/support/faq#extensions-pricing)
- If you enable events,
[Eventarc fees apply](https://cloud.google.com/eventarc/pricing).
POSTINSTALL.md
يحتوي هذا الملف على معلومات مفيدة للمستخدمين بعد تثبيت الإضافة بنجاح، مثل خطوات الإعداد اللاحقة ومثال على الإضافة أثناء عملها وما إلى ذلك.
يتم عرض محتوى ملف POSTINSTALL.md في وحدة تحكّم Firebase بعد إعداد إضافة وتثبيتها. يمكنك الرجوع إلى مَعلمات المستخدم في هذا الملف وسيتم استبدالها بالقيم التي تم ضبطها.
في ما يلي مثال على ملف ما بعد التثبيت الخاص بإضافة البرنامج التعليمي:
### See it in action
You can test out this extension right away!
1. Go to your
[Realtime Database dashboard](https://console.firebase.google.com/project/${param:PROJECT_ID}/database/${param:PROJECT_ID}/data) in the Firebase console.
1. Add a message string to a path that matches the pattern `${param:MESSAGE_PATH}`.
1. In a few seconds, you'll see a sibling node named `upper` that contains the
message in upper case.
### Using the extension
We recommend adding data by pushing -- for example,
`firebase.database().ref().push()` -- because pushing assigns an automatically
generated ID to the node in the database. During retrieval, these nodes are
guaranteed to be ordered by the time they were added. Learn more about reading
and writing data for your platform (iOS, Android, or Web) in the
[Realtime Database documentation](https://firebase.google.com/docs/database/).
### Monitoring
As a best practice, you can
[monitor the activity](https://firebase.google.com/docs/extensions/manage-installed-extensions#monitor)
of your installed extension, including checks on its health, usage, and logs.
CHANGELOG.md
يجب أيضًا توثيق التغييرات التي تجريها بين إصدارات إحدى الإضافات في ملف CHANGELOG.md
.
بما أنّ إضافة المثال لم يتم نشرها من قبل، يحتوي سجلّ التغيير على إدخال واحد فقط:
## Version 0.0.1
Initial release of the _Convert messages to upper case_ extension.
README.md
توفّر معظم الإضافات أيضًا ملف readme لصالح المستخدمين الذين يزورون مستودع الإضافة. يمكنك كتابة هذا الملف يدويًا أو إنشاء ملف readme باستخدام الأمر.
لأغراض هذا الدليل، تخطَّ كتابة ملف readme.
مستندات إضافية
المستندات الموضّحة أعلاه هي الحد الأدنى من المستندات التي يجب توفيرها للمستخدمين. تتطلّب العديد من الإضافات مستندات أكثر تفصيلاً ليتمكّن المستخدمون من استخدامها بنجاح. في هذه الحالة، عليك كتابة مستندات إضافية واستضافتها في مكان يمكنك توجيه المستخدمين إليه.
لأغراض هذا الدليل، تخطَّ كتابة مستندات أكثر شمولاً.
11. النشر في "مركز الإضافات"
بعد اكتمال كتابة الرمز البرمجي للإضافة وتوثيقه، يمكنك مشاركتها مع العالم على "مركز إضافات Chrome". ولكن بما أنّ هذا مجرّد درس تعليمي، لا تنفّذ هذه الخطوة. يمكنك الآن البدء في كتابة الإضافة الخاصة بك باستخدام ما تعلّمته هنا وفي بقية مستندات الناشرين الخاصة بـ "إضافات Firebase"، ومن خلال فحص مصدر الإضافات الرسمية التي كتبتها Firebase.
عندما تكون مستعدًا لنشر عملك على "مركز الإضافات"، اتّبِع الخطوات التالية:
- إذا كنت ستنشر إضافتك الأولى، عليك التسجيل كناشر إضافات. عند التسجيل كناشر إضافات، يمكنك إنشاء رقم تعريف للناشر يتيح للمستخدمين التعرّف عليك بسرعة بصفتك مؤلف إضافاتك.
استضافة رمز المصدر الخاص بالإضافة في موقع جغرافي يمكن التحقّق منه علنًا عندما يكون الرمز متاحًا من مصدر يمكن التحقّق منه، يمكن أن تنشر Firebase الإضافة مباشرةً من هذا الموقع. يساعدك ذلك في ضمان نشر الإصدار الحالي من الإضافة، كما يساعد المستخدمين من خلال السماح لهم بفحص الرمز البرمجي الذي يثبّتونه في مشاريعهم.
ويعني ذلك حاليًا إتاحة الإضافة في مستودع GitHub عام.
حمِّل الإضافة إلى "مركز الإضافات" باستخدام الأمر
firebase ext:dev:upload
.انتقِل إلى لوحة بيانات الناشر في "وحدة تحكّم Firebase"، وابحث عن الإضافة التي حمّلتها للتو، ثم انقر على "النشر في مركز الإضافات". سيؤدي ذلك إلى طلب مراجعة من فريق المراجعة، وقد يستغرق الأمر بضعة أيام. في حال الموافقة عليها، سيتم نشر الإضافة في "مركز الإضافات". في حال الرفض، ستتلقّى رسالة توضّح السبب، ويمكنك بعد ذلك معالجة المشاكل التي تم الإبلاغ عنها وإعادة إرسال التطبيق للمراجعة.