۱. قبل از شروع
یک افزونه فایربیس یک یا مجموعهای از وظایف خاص را در پاسخ به درخواستهای HTTP یا رویدادهای فعالکننده از سایر محصولات فایربیس و گوگل مانند Firebase Cloud Messaging، Cloud Firestore یا Pub/Sub انجام میدهد.
آنچه خواهید ساخت
در این آزمایشگاه کد، شما یک افزونه Firebase برای geohashing خواهید ساخت. پس از استقرار، افزونه شما مختصات X و Y را در پاسخ به رویدادهای Firestore یا از طریق فراخوانی توابع قابل فراخوانی به geohashes تبدیل میکند. این میتواند به عنوان جایگزینی برای پیادهسازی کتابخانه geofire در تمام پلتفرمهای هدف شما برای ذخیره دادهها استفاده شود و در زمان شما صرفهجویی کند.

آنچه یاد خواهید گرفت
- چگونه کد توابع ابری موجود را گرفته و آن را به یک افزونه فایربیس قابل توزیع تبدیل کنیم
- نحوه تنظیم فایل
extension.yaml - نحوه ذخیره رشتههای حساس (کلیدهای API) در یک افزونه
- چگونه به توسعهدهندگان افزونه اجازه دهیم آن را متناسب با نیازهای خود پیکربندی کنند
- نحوه آزمایش و استقرار افزونه
آنچه نیاز دارید
- رابط خط فرمان فایربیس (نصب و ورود)
- یک حساب گوگل، مانند یک حساب جیمیل
- Node.js و
npm - محیط توسعه مورد علاقه شما
۲. آماده شوید
کد را دریافت کنید
هر چیزی که برای این افزونه نیاز دارید در مخزن گیتهاب موجود است. برای شروع، کد را دریافت کرده و آن را در محیط توسعه مورد علاقه خود باز کنید.
- فایل زیپ دانلود شده را از حالت فشرده خارج کنید.
- برای نصب وابستگیهای مورد نیاز، ترمینال را در دایرکتوری
functionsباز کنید و دستورnpm installرا اجرا کنید.
فایربیس را راهاندازی کنید
این آزمایشگاه کد، استفاده از شبیهسازهای Firebase را اکیداً توصیه میکند. اگر میخواهید توسعه افزونهها را با یک پروژه واقعی Firebase امتحان کنید، به بخش ایجاد یک پروژه Firebase مراجعه کنید. این آزمایشگاه کد از توابع ابری استفاده میکند، بنابراین اگر به جای شبیهسازها از یک پروژه واقعی Firebase استفاده میکنید، باید به طرح قیمتگذاری Blaze ارتقا دهید .
میخوای از جلو رد شی؟
میتوانید نسخه کاملشدهی codelab را دانلود کنید. اگر در طول مسیر به مشکل برخوردید یا اگر میخواهید ببینید که یک افزونهی کاملشده چگونه است، به شاخهی codelab-end در مخزن گیتهاب مراجعه کنید یا فایل زیپ کاملشده را دانلود کنید.
۳. کد را بررسی کنید
- فایل
index.tsرا از فایل زیپ باز کنید. توجه داشته باشید که شامل دو اعلان توابع ابری (Cloud Functions) است.
این توابع چه کاری انجام میدهند؟
این توابع نمایشی برای 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/ collection نوشته شده است میخواند و سپس یک 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 پیکربندی شود، در اینجا گنجانده شده است.
۴. تنظیم فایل extension.yaml
حالا که میدانید کد توابع ابری در افزونه شما چه کاری انجام میدهد، آمادهاید تا آن را برای توزیع بستهبندی کنید. هر افزونه فایربیس با یک فایل extension.yaml ارائه میشود که عملکرد و نحوه رفتار افزونه را شرح میدهد.
فایل extension.yaml به برخی فرادادههای اولیه در مورد افزونه شما نیاز دارد. هر یک از مراحل زیر به شما کمک میکند تا بفهمید که همه فیلدها به چه معناست و چرا به آنها نیاز دارید.
- یک فایل
extension.yamlدر دایرکتوری ریشه پروژهای که قبلاً دانلود کردهاید، ایجاد کنید. با اضافه کردن موارد زیر شروع کنید:
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
نام افزونه به عنوان مبنای شناسه نمونه افزونه استفاده میشود (کاربران میتوانند چندین نمونه از یک افزونه را نصب کنند که هر کدام شناسه خاص خود را دارند). سپس فایربیس با استفاده از آن شناسه نمونه، نام حسابهای سرویس افزونه و منابع مختص افزونه را تولید میکند. شماره نسخه، نسخه افزونه شما را نشان میدهد. این شماره باید از نسخهبندی معنایی پیروی کند و شما باید هر زمان که تغییراتی در عملکرد افزونه ایجاد میکنید، آن را بهروزرسانی کنید. نسخه مشخصات افزونه برای تعیین اینکه کدام مشخصات افزونههای فایربیس باید دنبال شود، استفاده میشود، در این مورد، 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 برای شناسایی این افزونه را پوشش میدهد. برای جزئیات بیشتر در مورد سایر اطلاعات شناسایی که میتوانید در یک افزونه مشخص کنید، به مستندات مراجعه کنید.
۵. کد توابع ابری را به یک منبع افزونهها تبدیل کنید
منبع افزونه، آیتمی است که فایربیس در طول نصب افزونه در پروژه ایجاد میکند. سپس افزونه مالک آن منابع است و یک حساب سرویس خاص دارد که روی آنها کار میکند. در این پروژه، این منابع، توابع ابری (Cloud Functions) هستند که باید در فایل extension.yaml تعریف شوند زیرا افزونه به طور خودکار منابع را از کد موجود در پوشه functions ایجاد نمیکند. اگر توابع ابری شما به صراحت به عنوان یک منبع اعلام نشده باشند، هنگام استقرار افزونه، نمیتوانند مستقر شوند.
محل استقرار تعریف شده توسط کاربر
- به کاربر اجازه دهید مکانی را که میخواهد این افزونه را در آن مستقر کند، مشخص کند و تصمیم بگیرد که آیا بهتر است افزونه را در نزدیکی کاربران نهایی خود یا نزدیکتر به پایگاه داده خود میزبانی کند. در فایل
extension.yaml، گزینه انتخاب مکان را قرار دهید.
پسوند.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 از 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، یک منبع جدید در زیر ویژگی resources ایجاد کنید. این ویژگیها مختص یک تابع قابل فراخوانی هستند:
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
اگرچه منبع قبلی از eventTrigger استفاده میکرد، در اینجا از httpsTrigger استفاده میکنید که هم توابع قابل فراخوانی و هم توابع HTTPS را پوشش میدهد.
بررسی کد
این پیکربندی زیادی بود تا extension.yaml شما با هر کاری که توسط کد در فایل index.ts شما انجام میشود، مطابقت داشته باشد. فایل extension.yaml تکمیل شده در حال حاضر باید به این شکل باشد:
پسوند.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در پوشه functions پروژه افزونههای دانلود شده فراخوانی کنید. - یک دایرکتوری جدید روی سیستم میزبان خود ایجاد کنید و آن دایرکتوری را با استفاده از
firebase initبه پروژه Firebase خود متصل کنید.
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ایجاد میکند که حاوی اطلاعات پیکربندی برای نمونه است. - این کد، نمونه افزونه را به بخش
extensionsfirebase.jsonشما اضافه میکند. این به عنوان نگاشتی از شناسه نمونه به نسخه افزونه عمل میکند. - از آنجایی که پروژه را به صورت محلی مستقر میکنید، میتوانید مشخص کنید که میخواهید از یک فایل محلی به جای Google Cloud Secret Manager استفاده کنید.

- شبیهسازهای Firebase را با پیکربندی جدید اجرا کنید:
firebase emulators:start
- پس از اجرای
emulators:start، به تب Firestore در نمای وب شبیهسازها بروید. - یک سند به مجموعه
usersبا فیلد شمارهxvو فیلد شمارهyvاضافه کنید.

- اگر در نصب افزونه موفق باشید، افزونه یک فیلد جدید به نام
hashدر سند ایجاد میکند.

برای جلوگیری از درگیری، پاکسازی کنید
- پس از اتمام آزمایش، افزونه را حذف نصب کنید - شما قصد دارید کد افزونه را بهروزرسانی کنید و نمیخواهید بعداً با افزونه فعلی تداخل داشته باشد.
افزونهها امکان نصب چندین نسخه از یک افزونه را به طور همزمان فراهم میکنند، بنابراین با حذف نصب، مطمئن میشوید که هیچ تداخلی با افزونههای نصب شده قبلی وجود ندارد.
firebase ext:uninstall geohash-ext
راه حل فعلی کار میکند، اما همانطور که در ابتدای پروژه ذکر شد، یک کلید API کد شده برای شبیهسازی ارتباط با یک سرویس وجود دارد. چگونه میتوانید از کلید API کاربر نهایی به جای کلید اصلی ارائه شده استفاده کنید؟ برای فهمیدن این موضوع، ادامه مطلب را بخوانید.
۶. افزونه را برای کاربر قابل پیکربندی کنید
در این مرحله از کد، شما یک افزونه دارید که برای استفاده با تنظیمات دلخواه توابعی که قبلاً نوشتهاید پیکربندی شده است، اما اگر کاربر شما بخواهد از طول و عرض جغرافیایی به جای y و x برای فیلدهای نشان دهنده موقعیت مکانی در صفحه دکارتی استفاده کند، چه میشود؟ همچنین، چگونه میتوانید کاربر نهایی را وادار کنید که کلید API خود را ارائه دهد، به جای اینکه اجازه دهید کلید API ارائه شده را مصرف کند؟ شما میتوانید به سرعت سهمیه آن API را افزایش دهید. در این حالت، پارامترها را تنظیم و استفاده میکنید.
پارامترهای اساسی را در فایل extension.yaml تعریف کنید
با تبدیل مواردی که توسعهدهندگان ممکن است پیکربندی سفارشی برای آنها داشته باشند، شروع کنید. اولین مورد، پارامترهای XFIELD و YFIELD هستند.
- در فایل
extension.yaml، کد زیر را اضافه کنید که از پارامترهای فیلدXFIELDوYFIELDاستفاده میکند. این پارامترها درون ویژگی YAML مربوط بهparamsکه قبلاً تعریف شده است، قرار دارند:
پسوند.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
- param پارامتر را به گونهای نامگذاری میکند که برای شما، تولیدکننده افزونه، قابل مشاهده باشد. از این مقدار بعداً هنگام تعیین مقادیر پارامتر استفاده کنید.
- برچسب یک شناسه قابل خواندن توسط انسان برای توسعهدهنده است تا به آنها اطلاع دهد که پارامتر چه کاری انجام میدهد.
- توضیحات، شرح مفصلی از مقدار ارائه میدهد. از آنجایی که این گزینه از markdown پشتیبانی میکند، میتواند به مستندات اضافی پیوند دهد یا کلماتی را که ممکن است برای توسعهدهنده مهم باشند، برجسته کند.
- نوع، مکانیزم ورودی برای نحوه تنظیم مقدار پارامتر توسط کاربر را تعریف میکند. انواع زیادی از جمله
string،select،multiSelect،selectResourceوsecretوجود دارد. برای کسب اطلاعات بیشتر در مورد هر یک از این گزینهها، به مستندات مراجعه کنید. - validationRegex ورودی توسعهدهنده را به یک مقدار regex خاص محدود میکند (در این مثال، بر اساس دستورالعملهای ساده نام فیلد موجود در اینجا است)؛ و اگر این روش جواب نداد...
- validationErrorMessage به توسعهدهنده در مورد مقدار شکست هشدار میدهد.
- مقدار پیشفرض ، مقداری است که اگر توسعهدهنده هیچ متنی وارد نکند، خواهد بود.
- مورد نیاز به این معنی است که توسعهدهنده ملزم به وارد کردن هیچ متنی نیست.
- immutable به توسعهدهنده اجازه میدهد تا این افزونه را بهروزرسانی کند و این مقدار را تغییر دهد. در این حالت، توسعهدهنده باید بتواند نام فیلدها را با تغییر الزامات خود تغییر دهد.
- این مثال ایدهای از اینکه یک ورودی معتبر چگونه میتواند باشد، ارائه میدهد.
خیلی چیزا بود که باید میفهمیدم!
- قبل از اضافه کردن یک پارامتر خاص، سه پارامتر دیگر برای اضافه کردن به فایل
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، کد زیر را اضافه کنید:
پسوند.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، کد زیر را اضافه کنید:
پسوند.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را بررسی کنید. باید چیزی شبیه به این باشد:
پسوند.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!;
معمولاً شما میخواهید بررسیهای null را با مقادیر متغیرهای محیطی انجام دهید، اما در این مورد، شما به کپی صحیح مقادیر پارامترها اعتماد دارید. اکنون کد برای کار با پارامترهای افزونه پیکربندی شده است.
۷. ایجاد مستندات کاربر
قبل از آزمایش کد روی شبیهسازها یا در بازار افزونههای فایربیس، افزونه باید مستندسازی شود تا توسعهدهندگان بدانند هنگام استفاده از افزونه چه چیزی دریافت میکنند.
- با ایجاد فایل
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/docs/functions/faq-and-troubleshooting#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ایجاد کنید و سپس اطلاعات نصب پس از نصب زیر را در آن قرار دهید:
نصب پست.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 initبه پروژه Firebase خود متصل کنید.
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 پشتیبانی نمیشود ( به گزینه شبیهساز Extensions مراجعه کنید)، از این گردش کار آزمایشی استفاده کنید. شبیهسازها در حال حاضر از توابع فعالشده توسط درخواست HTTP و توابع فعالشده توسط رویداد پسزمینه برای Cloud Firestore، Realtime Database و Pub/Sub پشتیبانی میکنند.
- یک دایرکتوری جدید روی سیستم میزبان خود ایجاد کنید و آن دایرکتوری را با استفاده از
firebase initبه پروژه Firebase خود متصل کنید.
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 استفاده کنید، باید قبل از نصب افزونه ، API مربوط به Secret Manager را فعال کنید .
- به پروژه Firebase خود منتقل کنید.
firebase deploy
افزونه را امتحان کنید
- پس از اجرای
firebase deployیاfirebase emulators:start، به برگه Firestore در کنسول Firebase یا نمای وب شبیهسازها، بسته به مورد، بروید. - یک سند را به مجموعه مشخص شده توسط فیلد
xو فیلدyاضافه کنید. در این حالت، اسناد بهروزرسانی شده درu/{uid}با فیلدxبرابر باxvو فیلدyبرابر باyvقرار دارند.

- اگر در نصب افزونه موفق باشید، افزونه پس از ذخیره دو فیلد، فیلد جدیدی به نام
hashدر سند ایجاد میکند.

۸. تبریک میگویم!
شما با موفقیت اولین تابع ابری خود را به یک افزونه فایربیس تبدیل کردید!
شما یک فایل extension.yaml اضافه کردید و آن را پیکربندی کردید تا توسعهدهندگان بتوانند نحوهی استقرار افزونهی شما را انتخاب کنند. سپس مستندات کاربری ایجاد کردید که راهنماییهایی را در مورد کارهایی که توسعهدهندگان افزونه باید قبل از راهاندازی افزونه انجام دهند و مراحلی که ممکن است پس از نصب موفقیتآمیز افزونه لازم باشد، ارائه میدهد.
اکنون مراحل کلیدی مورد نیاز برای تبدیل یک تابع Firebase به یک افزونه Firebase قابل توزیع را میدانید.