1. قبل أن تبدأ
ينفذ ملحق Firebase مهمة محددة أو مجموعة من المهام استجابة إما لطلبات HTTP أو تشغيل الأحداث من منتجات Firebase وGoogle الأخرى مثل Firebase Cloud Messaging أو Cloud Firestore أو Pub/Sub.
ما سوف تبنيه
في هذا الدرس التطبيقي حول التعليمات البرمجية، ستقوم بإنشاء ملحق Firebase للتقطيع الجغرافي . بمجرد النشر، يقوم الامتداد الخاص بك بعد ذلك بتحويل إحداثيات X وY إلى تجزئة جغرافية استجابةً لأحداث Firestore أو من خلال استدعاءات الوظائف القابلة للاستدعاء. يمكن استخدام هذا كبديل لتنفيذ مكتبة Geofire عبر جميع الأنظمة الأساسية المستهدفة لتخزين البيانات، مما يوفر لك الوقت.
ما ستتعلمه
- كيفية أخذ رمز Cloud Functions الموجود وتحويله إلى ملحق Firebase قابل للتوزيع
- كيفية إعداد ملف
extension.yaml
- كيفية تخزين السلاسل الحساسة (مفاتيح API) في الامتداد
- كيفية السماح لمطوري الامتداد بتكوينه ليناسب احتياجاتهم
- كيفية اختبار ونشر الامتداد
ماذا ستحتاج
- Firebase CLI (التثبيت وتسجيل الدخول)
- حساب Google، مثل حساب Gmail
- Node.js و
npm
- بيئة التطوير المفضلة لديك
2. قم بالإعداد
احصل على الرمز
كل ما تحتاجه لهذا الامتداد موجود في GitHub repo. للبدء، احصل على الكود وافتحه في بيئة التطوير المفضلة لديك.
- قم بفك ضغط الملف المضغوط الذي تم تنزيله.
- لتثبيت التبعيات المطلوبة، افتح الوحدة الطرفية في دليل
functions
وقم بتشغيل أمرnpm install
.
قم بإعداد Firebase
يشجع هذا الدرس التطبيقي حول البرمجة بشدة على استخدام محاكيات Firebase. إذا كنت تريد تجربة تطوير الملحقات باستخدام مشروع Firebase حقيقي، فراجع إنشاء مشروع Firebase . يستخدم هذا الدرس التطبيقي للبرمجة وظائف السحابة، لذا إذا كنت تستخدم مشروع Firebase حقيقيًا بدلاً من المحاكيات، فستحتاج إلى الترقية إلى خطة تسعير Blaze .
هل تريد التخطي للأمام؟
يمكنك تنزيل نسخة مكتملة من Codelab. إذا واجهتك مشكلة على طول الطريق أو إذا كنت تريد رؤية الشكل الذي يبدو عليه الامتداد المكتمل، فراجع فرع codelab-end
لمستودع GitHub أو قم بتنزيل الملف المضغوط المكتمل.
3. قم بمراجعة الكود
- افتح ملف
index.ts
من الملف المضغوط. لاحظ أنه يحتوي على إعلانين للوظائف السحابية بداخله.
ماذا تفعل هذه الوظائف؟
تُستخدم هذه الوظائف التجريبية في عملية Geohashing. يأخذون زوجًا إحداثيًا ويحولونه إلى تنسيق مُحسّن للاستعلامات الجغرافية في Firestore. تحاكي الوظائف استخدام استدعاء واجهة برمجة التطبيقات (API) حتى تتمكن من معرفة المزيد حول التعامل مع أنواع البيانات الحساسة في الامتدادات. لمزيد من المعلومات، راجع الوثائق المتعلقة بتشغيل الاستعلامات الجغرافية على البيانات في Firestore .
ثوابت الدالة
يتم الإعلان عن الثوابت مبكرًا، في الجزء العلوي من ملف index.ts
. تتم الإشارة إلى بعض هذه الثوابت في مشغلات الامتداد المحددة.
Index.ts
import {firestore} from "firebase-functions";
import {initializeApp} from "firebase-admin/app";
import {GeoHashService, ResultStatusCode} from "./fake-geohash-service";
import {onCall} from "firebase-functions/v1/https";
import {fieldValueExists} from "./utils";
const documentPath = "users/{uid}";
const xField = "xv";
const yField = "yv";
const apiKey = "1234567890";
const outputField = "hash";
initializeApp();
const service = new GeoHashService(apiKey);
مشغل الحريق
تبدو الوظيفة الأولى في ملف index.ts
كما يلي:
Index.ts
export const locationUpdate = firestore.document(documentPath)
.onWrite((change) => {
// item deleted
if (change.after == null) {
return 0;
}
// double check that both values exist for computation
if (
!fieldValueExists(change.after.data(), xField) ||
!fieldValueExists(change.after.data(), yField)
) {
return 0;
}
const x: number = change.after.data()![xField];
const y: number = change.after.data()![yField];
const hash = service.convertToHash(x, y);
// This is to check whether the hash value has changed. If
// it hasn't, you don't want to write to the document again as it
// would create a recursive write loop.
if (fieldValueExists(change.after.data(), outputField)
&& change.after.data()![outputField] == hash) {
return 0;
}
return change.after.ref
.update(
{
[outputField]: hash.hash,
}
);
});
هذه الوظيفة عبارة عن مشغل Firestore . عند حدوث حدث كتابة في قاعدة البيانات، تتفاعل الوظيفة مع هذا الحدث من خلال البحث عن حقل xv
وحقل yv
، وإذا كان كلا هذين الحقلين موجودين، فإنها تحسب Geohash وتكتب الإخراج إلى موقع إخراج مستند محدد. يتم تعريف مستند الإدخال بواسطة ثابت users/{uid}
، مما يعني أن الوظيفة تقرأ كل مستند مكتوب إلى users/
المجموعة ثم تقوم بمعالجة Geohash لتلك المستندات. ثم يقوم بإخراج التجزئة إلى حقل التجزئة في نفس المستند.
وظائف قابلة للاستدعاء
تبدو الوظيفة التالية في ملف index.ts
كما يلي:
Index.ts
export const callableHash = onCall((data, context) => {
if (context.auth == undefined) {
return {error: "Only authorized users are allowed to call this endpoint"};
}
const x = data[xField];
const y = data[yField];
if (x == undefined || y == undefined) {
return {error: "Either x or y parameter was not declared"};
}
const result = service.convertToHash(x, y);
if (result.status != ResultStatusCode.ok) {
return {error: `Something went wrong ${result.message}`};
}
return {result: result.hash};
});
لاحظ وظيفة onCall
. ويشير إلى أن هذه الوظيفة هي وظيفة قابلة للاستدعاء ، والتي يمكن استدعاؤها من داخل رمز تطبيق العميل الخاص بك. تأخذ هذه الوظيفة القابلة للاستدعاء معلمات x
و y
وتقوم بإرجاع Geohash. على الرغم من أن هذه الوظيفة لن يتم استدعاؤها مباشرة في هذا الدرس التطبيقي حول التعليمات البرمجية، إلا أنها مدرجة هنا كمثال لشيء يجب تهيئته في ملحق Firebase.
4. قم بإعداد ملف Extension.yaml
الآن بعد أن عرفت ما يفعله كود وظائف السحابة في ملحقك، فأنت جاهز لتجميعه للتوزيع. يأتي كل ملحق Firebase مزودًا بملف extension.yaml
الذي يصف ما يفعله الامتداد وكيف يتصرف.
يتطلب ملف extension.yaml
بعض البيانات الوصفية الأولية حول الامتداد الخاص بك. تساعدك كل خطوة من الخطوات التالية على فهم معنى جميع الحقول وسبب حاجتك إليها.
- قم بإنشاء ملف
extension.yaml
في الدليل الجذر للمشروع الذي قمت بتنزيله مسبقًا. ابدأ بإضافة ما يلي:
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
يتم استخدام اسم الامتداد كأساس لمعرف مثيل الامتداد (يمكن للمستخدمين تثبيت مثيلات متعددة للامتداد، كل منها بمعرف خاص بها). يقوم Firebase بعد ذلك بإنشاء اسم حسابات خدمة الامتداد والموارد الخاصة بالامتداد باستخدام معرف المثيل هذا. يشير رقم الإصدار إلى إصدار الامتداد الخاص بك. يجب أن يتبع الإصدار الدلالي ، وتحتاج إلى تحديثه كلما قمت بإجراء تغييرات على وظيفة الامتداد. يتم استخدام إصدار مواصفات الامتداد لتحديد مواصفات امتدادات Firebase التي يجب اتباعها، وفي هذه الحالة، يتم استخدام v1beta
.
- أضف بعض التفاصيل سهلة الاستخدام إلى ملف YAML:
...
displayName: Latitude and longitude to GeoHash converter
description: A converter for changing your Latitude and longitude coordinates to geohashes.
يعد اسم العرض تمثيلاً مألوفًا لاسم ملحقك عندما يتفاعل المطورون مع ملحقك. يقدم الوصف نظرة عامة موجزة عما يفعله الامتداد. عندما يتم نشر الامتداد على Extensions.dev ، يبدو كما يلي:
- حدد الترخيص للكود الموجود في ملحقك.
...
license: Apache-2.0 # The license you want for the extension
- وضح من كتب الامتداد وما إذا كان يلزم الفوترة لتثبيته أم لا:
...
author:
authorName: AUTHOR_NAME
url: https://github.com/Firebase
billingRequired: true
يتم استخدام قسم author
للسماح للمستخدمين بمعرفة من يجب عليهم التواصل معه في حالة مواجهتهم مشكلات مع الامتداد أو رغبتهم في الحصول على مزيد من المعلومات حوله. تعتبر billingRequired
معلمة مطلوبة ويجب ضبطها على true
نظرًا لأن جميع الملحقات تعتمد على Cloud Functions، الأمر الذي يتطلب خطة Blaze.
يغطي هذا الحد الأدنى لعدد الحقول المطلوبة في ملف extension.yaml
لتحديد هذا الامتداد. لمزيد من التفاصيل حول معلومات التعريف الأخرى التي يمكنك تحديدها في الامتداد، راجع الوثائق .
5. قم بتحويل كود وظائف السحابة إلى مورد ملحقات
مورد الامتداد هو عنصر ينشئه Firebase في المشروع أثناء تثبيت الامتداد. يمتلك الامتداد بعد ذلك هذه الموارد ولديه حساب خدمة محدد يعمل عليها. في هذا المشروع، هذه الموارد هي وظائف السحابة، والتي يجب تعريفها في ملف extension.yaml
لأن الامتداد لن يقوم تلقائيًا بإنشاء موارد من التعليمات البرمجية في مجلد الوظائف. إذا لم يتم الإعلان عن وظائف السحابة الخاصة بك بشكل صريح كمورد، فلا يمكن نشرها عند نشر الامتداد.
موقع النشر المحدد من قبل المستخدم
- اسمح للمستخدم بتحديد الموقع الذي يريد نشر هذا الامتداد فيه وتحديد ما إذا كان من الأفضل استضافة الامتداد بالقرب من المستخدمين النهائيين أو بالقرب من قاعدة البيانات الخاصة به. في ملف
extension.yaml
، قم بتضمين خيار اختيار الموقع.
Extension.yaml
أنت الآن جاهز لكتابة التكوين لمورد الوظيفة.
- في الملف
extension.yaml
، قم بإنشاء كائن مورد لوظيفةlocationUpdate
. قم بإلحاق ما يلي بالملفextension.yaml
:
resources:
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}
يمكنك تحديد name
كاسم الوظيفة المحددة في ملف index.ts
الخاص بالمشروع. أنت تحدد type
الوظيفة التي يتم نشرها، والتي يجب أن تكون دائمًا firebaseextensions.v1beta.function
في الوقت الحالي. ثم، يمكنك تحديد properties
هذه الوظيفة. الخاصية الأولى التي تحددها هي eventTrigger
المرتبطة بهذه الوظيفة. لعكس ما يدعمه الامتداد حاليًا، يمكنك استخدام eventType
of providers/cloud.firestore/eventTypes/document.write
، الموجود في Write Cloud Functions لوثائق الامتداد الخاصة بك . يمكنك تحديد resource
كموقع للمستندات. نظرًا لأن هدفك الحالي هو عكس ما هو موجود في الكود، فإن مسار المستند يستمع إلى users/{uid}
، مع موقع قاعدة البيانات الافتراضي الذي يسبقه.
- يحتاج الامتداد إلى أذونات القراءة والكتابة لقاعدة بيانات Firestore. في نهاية ملف
extension.yaml
، حدد أدوار IAM التي يجب أن يكون للامتداد حق الوصول إليها للعمل مع قاعدة البيانات في مشروع Firebase الخاص بالمطور.
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
يأتي دور datastore.user
من قائمة أدوار IAM المدعومة للامتدادات . وبما أن الامتداد سيكون للقراءة والكتابة، فإن دور datastore.user
مناسب هنا.
- يجب إضافة الدالة القابلة للاستدعاء أيضًا. في الملف
extension.yaml
، قم بإنشاء مورد جديد ضمن خاصية الموارد. هذه الخصائص خاصة بوظيفة قابلة للاستدعاء:
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
على الرغم من أن المورد السابق استخدم eventTrigger
، إلا أنك هنا تستخدم httpsTrigger
، والذي يغطي كلاً من الوظائف القابلة للاستدعاء ووظائف HTTPS.
فحص الكود
لقد كان ذلك يتطلب الكثير من التكوين لجعل extension.yaml
الخاص بك يطابق كل ما يتم تنفيذه بواسطة الكود الموجود في ملف index.ts
الخاص بك. هذا هو الشكل الذي يجب أن يبدو عليه ملف extension.yaml
المكتمل في الوقت الحالي:
Extension.yaml
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
displayName: Latitude and Longitude to GeoHash converter
description: A converter for changing your Latitude and Longitude coordinates to geohashes.
license: Apache-2.0 # The license you want for the extension
author:
authorName: Sparky
url: https://github.com/Firebase
billingRequired: true
resources:
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
التحقق من الحالة
في هذه المرحلة، تم إعداد الأجزاء الوظيفية الأولية للامتداد، بحيث يمكنك تجربته بالفعل باستخدام محاكيات Firebase!
- إذا لم تكن قد قمت بذلك بالفعل، فاتصل بـ
npm run build
في مجلد الوظائف الخاص بمشروع الإضافات الذي تم تنزيله. - قم بإنشاء دليل جديد على نظامك المضيف وقم بتوصيل هذا الدليل بمشروع Firebase الخاص بك باستخدام
firebase init
.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
This command creates a `firebase.json` file in the directory. In the following steps, you push the configuration specified in this file to Firebase.
- من نفس الدليل، قم بتشغيل
firebase ext:install
. استبدل/path/to/extension
بالمسار المطلق للدليل الذي يحتوي على ملفextension.yaml
الخاص بك.
firebase ext:install /path/to/extension
This command does two things:
- ويطالبك بتحديد التكوين لمثيل الامتداد، ويقوم بإنشاء ملف
*.env
يحتوي على معلومات التكوين للمثيل. - يقوم بإضافة مثيل الامتداد إلى قسم
extensions
فيfirebase.json
الخاص بك. يعمل هذا كخريطة لمعرف المثيل لإصدار الملحق. - نظرًا لأنك تنشر المشروع محليًا، يمكنك تحديد رغبتك في استخدام ملف محلي بدلاً من Google Cloud Secret Manager.
- ابدأ تشغيل محاكيات Firebase بالتكوين الجديد:
firebase emulators:start
- بعد تشغيل
emulators:start
، انتقل إلى علامة التبويب Firestore في عرض الويب الخاص بالمحاكيات. - أضف مستندًا إلى مجموعة
users
باستخدام حقل رقمxv
وحقل رقمyv
.
- إذا نجحت في تثبيت الامتداد، فسيقوم الامتداد بإنشاء حقل جديد يسمى
hash
في المستند.
تنظيف لتجنب الصراعات
- بمجرد الانتهاء من الاختبار، قم بإلغاء تثبيت الامتداد — ستقوم بتحديث رمز الامتداد ولا تريد أن يتعارض مع الامتداد الحالي لاحقًا.
تسمح الإضافات بتثبيت إصدارات متعددة من نفس الإضافة مرة واحدة، لذلك من خلال إلغاء التثبيت، فإنك تضمن عدم وجود تعارضات مع الإضافة المثبتة مسبقًا.
firebase ext:uninstall geohash-ext
يعمل الحل الحالي، ولكن كما ذكرنا في بداية المشروع، يوجد مفتاح API مشفر لمحاكاة الاتصال بالخدمة. كيف يمكنك استخدام مفتاح API الخاص بالمستخدم النهائي بدلاً من المفتاح الذي تم توفيره في الأصل؟ تابع القراءة لمعرفة ذلك.
6. اجعل مستخدم الامتداد قابلاً للتكوين
في هذه المرحلة من الدرس التطبيقي حول التعليمات البرمجية، يكون لديك ملحق تم تكوينه للاستخدام مع الإعداد المختار للوظائف التي كتبتها بالفعل، ولكن ماذا لو أراد المستخدم استخدام خط الطول والعرض بدلاً من y و x للحقول التي تشير إلى موقع على متن الطائرة الديكارتية؟ وأيضًا، كيف يمكنك إقناع المستخدم النهائي بتوفير مفتاح واجهة برمجة التطبيقات (API) الخاص به، بدلاً من السماح له باستهلاك مفتاح واجهة برمجة التطبيقات (API) المقدم؟ يمكنك تجاوز الحصة النسبية لواجهة برمجة التطبيقات هذه بسرعة. في هذه الحالة، يمكنك إعداد المعلمات واستخدامها.
حدد المعلمات الأساسية في ملف extension.yaml
ابدأ بتحويل العناصر التي من المحتمل أن يكون للمطورين تكوين مخصص لها. الأول سيكون معلمات XFIELD
و YFIELD
.
- في الملف
extension.yaml
، أضف التعليمة البرمجية التالية، التي تستخدم معلمات الحقلXFIELD
وYFIELD
. تعيش هذه المعلمات داخلparams
YAML المحددة مسبقًا:
Extension.yaml
params:
- param: XFIELD
label: The X Field Name
description: >-
The X Field is also known as the **longitude** value. What does
your Firestore instance refer to as the X value or the longitude
value. If no value is specified, the extension searches for
field 'xv'.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: xv
required: false
immutable: false
example: xv
- param: YFIELD
label: The Y Field Name
description: >-
The Y Field is also known as the **latitude** value. What does
your Firestore instance refer to as the Y value or the latitude
value. If no value is specified, the extension searches for
field 'yv'.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: yv
required: false
immutable: false
example: yv
- تقوم المعلمة بتسمية المعلمة بطريقة مرئية لك، أنت منتج الامتداد. استخدم هذه القيمة لاحقًا عند تحديد قيم المعلمات.
- label هو معرف يمكن قراءته بواسطة الإنسان للمطور لإعلامه بما تفعله المعلمة.
- وصف يعطي وصفا تفصيليا للقيمة. نظرًا لأن هذا يدعم تخفيض السعر، فيمكنه الارتباط بوثائق إضافية، أو يمكنه تمييز الكلمات التي قد تكون مهمة للمطور.
- يحدد النوع آلية الإدخال لكيفية قيام المستخدم بتعيين قيمة المعلمة. هناك العديد من الأنواع الموجودة، بما في ذلك
string
وselect
وmultiSelect
وselectResource
وsecret
. لمعرفة المزيد حول كل خيار من هذه الخيارات، راجع الوثائق . - يقيد validationRegex إدخال المطور إلى قيمة regex معينة (في المثال يعتمد على إرشادات اسم الحقل البسيطة الموجودة هنا )؛ وإذا فشل ذلك...
- ينبه validationErrorMessage المطور إلى قيمة الفشل.
- الافتراضي هو القيمة التي ستكون إذا لم يقوم المطور بإدخال أي نص.
- مطلوب يعني أن المطور غير مطالب بإدخال أي نص.
- غير قابل للتغيير يسمح للمطور بتحديث هذا الامتداد وتغيير هذه القيمة. في هذه الحالة، يجب أن يكون المطور قادرًا على تغيير أسماء الحقول مع تغير متطلباته.
- يقدم المثال فكرة عما قد يبدو عليه الإدخال الصالح.
كان هذا كثيرًا لفهمه!
- لديك ثلاث معلمات أخرى لإضافتها إلى ملف
extension.yaml
قبل إضافة معلمة خاصة.
- param: INPUTPATH
label: The input document to listen to for changes
description: >-
This is the document where you write an x and y value to. Once
that document has received a value, it notifies the extension to
calculate a geohash and store that in an output document in a certain
field. This accepts function [wildcard parameters](https://firebase.google.com/docs/functions/firestore-events#wildcards-parameters)
type: string
validationRegex: ^[^/]+(/[^/]*/[^/]*)*/[^/]+$
validationErrorMessage: >-
This must point to a document path, not a collection path from the root
of the database. It must also not start or end with a '/' character.
required: true
immutable: false
example: users/{uid}
- param: OUTPUTFIELD
label: Geohash field
description: >-
This specifies the field in the output document to store the geohash in.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
required: false
default: hash
immutable: false
example: hash
تحديد المعلمات الحساسة
أنت الآن بحاجة إلى إدارة مفتاح API الذي يحدده المستخدم. هذه سلسلة حساسة لا ينبغي تخزينها في نص عادي في الوظيفة. بدلاً من ذلك، قم بتخزين هذه القيمة في Cloud Secret Manager . هذا موقع خاص في السحابة يقوم بتخزين الأسرار المشفرة، ويمنع تسربها عن طريق الخطأ. يتطلب هذا من المطور أن يدفع مقابل استخدام هذه الخدمة، ولكنه يضيف طبقة إضافية من الأمان على مفاتيح واجهة برمجة التطبيقات (API) الخاصة به ويحتمل أن يحد من النشاط الاحتيالي. تنبه وثائق المستخدم المطور إلى أنها خدمة مدفوعة، بحيث لا تكون هناك أي مفاجآت في الفواتير. بشكل عام، الاستخدام مشابه لموارد السلسلة الأخرى المذكورة أعلاه. والفرق الوحيد هو النوع الذي يسمى secret
.
- في ملف
extension.yaml
، أضف الكود التالي:
Extension.yaml
- param: APIKEY
label: GeohashService API Key
description: >-
Your geohash service API Key. Since this is a demo, and not a real
service, you can use : 1234567890.
type: secret
required: true
immutable: false
قم بتحديث سمات resource
لاستخدام المعلمات
كما ذكرنا سابقًا، يحدد المورد (وليس الوظيفة) كيفية ملاحظة المورد، لذلك يحتاج مورد locationUpdate
إلى التحديث لاستخدام المعلمة الجديدة.
- في ملف
extension.yaml
، أضف الكود التالي:
Extension.yaml
## Change from this
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}]
## To this
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/${INPUTPATH}
تحقق من الملف extension.yaml
- قم بمراجعة ملف
extension.yaml
. يجب أن يبدو مثل هذا:
Extension.yaml
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
displayName: Latitude and Longitude to GeoHash converter
description: A converter for changing your Latitude and Longitude coordinates to geohashes.
license: Apache-2.0 # The license you want to use for the extension
author:
authorName: Sparky
url: https://github.com/Firebase
billingRequired: true
params:
- param: XFIELD
label: The X Field Name
description: >-
The X Field is also known as the **longitude** value. What does
your Firestore instance refer to as the X value or the longitude
value. If you don't provide a value for this field, the extension will use 'xv' as the default value.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: xv
required: false
immutable: false
example: xv
- param: YFIELD
label: The Y Field Name
description: >-
The Y Field is also known as the **latitude** value. What does
your Firestore instance refer to as the Y value or the latitude
Value. If you don't provide a value for this field, the extension will use 'yv' as the default value.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: yv
required: false
immutable: false
example: yv
- param: INPUTPATH
label: The input document to listen to for changes
description: >-
This is the document where you write an x and y value to. Once
that document has been modified, it notifies the extension to
compute a geohash and store that in an output document in a certain
field. This accepts function [wildcard parameters](https://firebase.google.com/docs/functions/firestore-events#wildcards-parameters)
type: string
validationRegex: ^[^/]+(/[^/]*/[^/]*)*/[^/]+$
validationErrorMessage: >-
This must point to a document path, not a collection path from the root
of the database. It must also not start or end with a '/' character.
required: true
immutable: false
example: users/{uid}
- param: OUTPUTFIELD
label: Geohash field
description: >-
This specifies the field in the output document to store the geohash in.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
required: false
default: hash
immutable: false
example: hash
- param: APIKEY
label: GeohashService API Key
description: >-
Your geohash service API Key. Since this is a demo, and not a real
service, you can use : 1234567890.
type: secret
required: true
immutable: false
resources:
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/${INPUTPATH}
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
الوصول إلى المعلمات في التعليمات البرمجية
الآن بعد أن تم تكوين كافة المعلمات في ملف extension.yaml
، قم بإضافتها إلى ملف index.ts
.
- في ملف
index.ts
، استبدل القيم الافتراضية بـprocess.env.PARAMETER_NAME
، الذي يجلب قيم المعلمات المناسبة ويملأها في رمز الوظيفة المنشور في مشروع Firebase الخاص بالمطور.
Index.ts
// Replace this:
const documentPath = "users/{uid}";
const xField = "xv";
const yField = "yv";
const apiKey = "1234567890";
const outputField = "hash";
// with this:
const documentPath = process.env.INPUTPATH!; // this value is ignored since its read from the resource
const xField = process.env.XFIELD!;
const yField = process.env.YFIELD!;
const apiKey = process.env.APIKEY!;
const outputField = process.env.OUTPUTFIELD!;
عادةً، تريد إجراء عمليات فحص فارغة لقيم متغيرات البيئة، ولكن في هذه الحالة، أنت تثق في أن قيم المعلمات قد تم نسخها بشكل صحيح. تم الآن تكوين الكود للعمل مع معلمات الامتداد.
7. إنشاء وثائق المستخدم
قبل اختبار التعليمات البرمجية على المحاكيات أو في سوق ملحقات Firebase، يجب توثيق الامتداد حتى يعرف المطورون ما سيحصلون عليه عند استخدام الامتداد.
- ابدأ بإنشاء ملف
PREINSTALL.md
، والذي يُستخدم لوصف الوظيفة وأي متطلبات أساسية للتثبيت والتأثيرات المحتملة على الفواتير.
التثبيت المسبق.md
Use this extension to automatically convert documents with a latitude and
longitude to a geohash in your database. Additionally, this extension includes a callable function that allows users to make one-time calls
to convert an x,y coordinate into a geohash.
Geohashing is supported for latitudes between 90 and -90 and longitudes
between 180 and -180.
#### Third Party API Key
This extension uses a fictitious third-party API for calculating the
geohash. You need to supply your own API keys. (Since it's fictitious,
you can use 1234567890 as an API key).
#### Additional setup
Before installing this extension, make sure that you've [set up a Cloud
Firestore database](https://firebase.google.com/docs/firestore/quickstart) in your Firebase project.
After installing this extension, you'll need to:
- Update your client code to point to the callable geohash function if you
want to perform arbitrary geohashes.
Detailed information for these post-installation tasks are provided after
you install this extension.
#### 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:
- Cloud Firestore
- Cloud Functions (Node.js 16+ runtime. [See
FAQs](https://firebase.google.com/support/faq#extensions-pricing))
- [Cloud Secret Manager](https://cloud.google.com/secret-manager/pricing)
- لتوفير الوقت في كتابة
README.md
لهذا المشروع، استخدم الطريقة الملائمة:
firebase ext:info . --markdown > README.md
يجمع هذا محتويات ملف PREINSTALL.md
الخاص بك وتفاصيل إضافية حول ملحقك من ملف extension.yaml
الخاص بك.
وأخيرًا، أبلغ مطور الامتداد ببعض التفاصيل الإضافية المتعلقة بالامتداد الذي تم تثبيته للتو. قد يحصل المطور على بعض الإرشادات والمعلومات الإضافية بعد إكمال التثبيت وقد يحصل على بعض المهام التفصيلية بعد التثبيت مثل إعداد رمز العميل هنا.
- قم بإنشاء ملف
POSTINSTALL.md
، ثم قم بتضمين معلومات التثبيت اللاحقة التالية:
POSTINSTALL.md
Congratulations on installing the geohash extension!
#### Function information
* **Firestore Trigger** - ${function:locationUpdate.name} was installed
and is invoked when both an x field (${param:XFIELD}) and y field
(${param:YFIELD}) contain a value.
* **Callable Trigger** - ${function:callableHash.name} was installed and
can be invoked by writing the following client code:
```javascript
import { getFunctions, httpsCallable } from "firebase/functions";
const functions = getFunctions();
const geoHash = httpsCallable(functions, '${function:callableHash.name}');
geoHash({ ${param:XFIELD}: -122.0840, ${param:YFIELD}: 37.4221 })
.then((result) => {
// Read result of the Cloud Function.
/** @type {any} */
const data = result.data;
const error = data.error;
if (error != null) {
console.error(`callable error : ${error}`);
}
const result = data.result;
console.log(result);
});
يراقب
كأفضل الممارسات، يمكنك مراقبة نشاط الامتداد المثبت لديك، بما في ذلك التحقق من صحته واستخدامه وسجلاته.
The output rendering looks something like this when it's deployed:
<img src="img/82b54a5c6ca34b3c.png" alt="A preview of the latitude and longitude geohash converter extension in the firebase console" width="957.00" />
## Test the extension with the full configuration
Duration: 03:00
It's time to make sure that the user-configurable extension is working the way it is intended.
* Change into the functions folder and ensure that the latest compiled version of the extensions exists. In the extensions project functions directory, call:
```console
npm run build
يؤدي هذا إلى إعادة ترجمة الوظائف بحيث يكون أحدث كود المصدر جاهزًا للنشر جنبًا إلى جنب مع الامتداد عند نشره على محاكي أو إلى Firebase مباشرة.
بعد ذلك، قم بإنشاء دليل جديد لاختبار الامتداد منه. نظرًا لأنه تم تطوير الامتداد من الوظائف الموجودة، فلا تختبر من المجلد الذي تم تكوين الامتداد فيه حيث يحاول ذلك أيضًا نشر الوظائف وقواعد Firebase بجانبه.
التثبيت والاختبار باستخدام محاكيات Firebase
- قم بإنشاء دليل جديد على نظامك المضيف وقم بتوصيل هذا الدليل بمشروع Firebase الخاص بك باستخدام
firebase init
.
mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- من هذا الدليل، قم بتشغيل
firebase ext:install
لتثبيت الامتداد. استبدل/path/to/extension
بالمسار المطلق للدليل الذي يحتوي على ملفextension.yaml
الخاص بك. يؤدي هذا إلى بدء عملية تثبيت ملحقك وإنشاء ملف.env
يحتوي على التكوينات الخاصة بك قبل دفع التكوين إلى Firebase أو إلى المحاكيات.
firebase ext:install /path/to/extension
- نظرًا لأنك تقوم بنشر المشروع محليًا، حدد أنك ترغب في استخدام ملف محلي بدلاً من Google Cloud Secret Manager.
- ابدأ مجموعة المحاكي المحلية:
firebase emulators:start
التثبيت والاختبار باستخدام مشروع Firebase حقيقي
يمكنك تثبيت الامتداد الخاص بك في مشروع Firebase فعلي. يوصى باستخدام مشروع اختبار للاختبار الخاص بك. استخدم سير عمل الاختبار هذا إذا كنت تريد اختبار التدفق الشامل لامتدادك أو إذا كان مشغل الامتداد الخاص بك غير مدعوم حتى الآن بواسطة مجموعة محاكي Firebase (راجع خيار محاكي الامتدادات ). تدعم المحاكيات حاليًا وظائف تشغيل طلب HTTP ووظائف تشغيل أحداث الخلفية لـ Cloud Firestore، وRealtime Database، وPub/Sub.
- قم بإنشاء دليل جديد على نظامك المضيف وقم بتوصيل هذا الدليل بمشروع Firebase الخاص بك باستخدام
firebase init
.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- ثم، من هذا الدليل، قم بتشغيل
firebase ext:install
لتثبيت الامتداد. استبدل/path/to/extension
بالمسار المطلق للدليل الذي يحتوي على ملفextension.yaml
الخاص بك. يؤدي هذا إلى بدء عملية تثبيت ملحقك وإنشاء ملف.env
يحتوي على التكوينات الخاصة بك قبل دفع التكوين إلى Firebase أو إلى المحاكيات.
firebase ext:install /path/to/extension
- نظرًا لأنك تريد النشر إلى Firebase مباشرةً، وترغب في استخدام Google Cloud Secret Manager، فأنت بحاجة إلى تنشيط Secret Manager API قبل تثبيت الامتداد.
- نشر إلى مشروع Firebase الخاص بك.
firebase deploy
اختبر الامتداد
- بعد تشغيل
firebase deploy
أوfirebase emulators:start
، انتقل إلى علامة التبويب Firestore الخاصة بوحدة تحكم Firebase أو عرض الويب الخاص بالمحاكيات، حسب الاقتضاء. - أضف مستندًا إلى المجموعة المحددة بواسطة الحقل
x
والحقلy
. في هذه الحالة، توجد المستندات المحدثة فيu/{uid}
مع حقلx
بقيمةxv
وحقلy
بقيمةyv
.
- إذا نجحت في تثبيت الامتداد، فسيقوم الامتداد بإنشاء حقل جديد يسمى
hash
في المستند بعد حفظ الحقلين.
8. تهانينا!
لقد نجحت في تحويل وظيفة السحابة الأولى الخاصة بك إلى ملحق Firebase!
لقد قمت بإضافة ملف extension.yaml
وقمت بتكوينه حتى يتمكن المطورون من تحديد الطريقة التي يريدون نشر ملحقك بها. قمت بعد ذلك بإنشاء وثائق المستخدم التي توفر إرشادات حول ما يجب على مطوري الامتداد فعله قبل إعداد الامتداد والخطوات التي قد يتعين عليهم اتخاذها بعد تثبيت الامتداد بنجاح.
أنت تعرف الآن الخطوات الأساسية المطلوبة لتحويل وظيفة Firebase إلى ملحق Firebase قابل للتوزيع.