1. לפני שמתחילים
תוסף Firebase מבצע משימה ספציפית או קבוצת משימות בתגובה לבקשות HTTP או לאירועים מפעילים ממוצרי Firebase ו-Google אחרים, כמו העברת הודעות בענן ב-Firebase, Cloud Firestore או Pub/Sub.
מה תפַתחו
בשיעור הזה תלמדו איך ליצור תוסף Firebase לגיאוהאשינג. אחרי הפריסה, התוסף ממיר קואורדינטות X ו-Y לגיבובים גיאוגרפיים בתגובה לאירועים ב-Firestore או באמצעות הפעלות של פונקציות שאפשר להפעיל. אפשר להשתמש בשיטה הזו כחלופה להטמעה של ספריית geofire בכל פלטפורמות היעד לאחסון נתונים, וכך לחסוך זמן.
מה תלמדו
- איך לוקחים קוד קיים של Cloud Functions והופכים אותו לתוסף Firebase שאפשר להפיץ
- איך מגדירים קובץ
extension.yaml
- איך לאחסן מחרוזות רגישות (מפתחות API) בתוסף
- איך מאפשרים למפתחים של התוסף להגדיר אותו בהתאם לצרכים שלהם
- איך בודקים ופורסים את התוסף
מה צריך
- Firebase CLI (התקנה וכניסה)
- חשבון Google, כמו חשבון Gmail
- Node.js ו-
npm
- סביבת הפיתוח המועדפת עליך
2. שנתחיל?
קבלת הקוד
כל מה שצריך לתוסף הזה נמצא במאגר GitHub. כדי להתחיל, מעתיקים את הקוד ופותחים אותו בסביבת הפיתוח המועדפת.
- מחלצים את קובץ ה-ZIP שהורד.
- כדי להתקין את התלויות הנדרשות, פותחים את הטרמינל בספרייה
functions
ומריצים את הפקודהnpm install
.
הגדרת Firebase
מומלץ מאוד להשתמש באמולטורים של Firebase ב-codelab הזה. אם רוצים לנסות לפתח תוספים באמצעות פרויקט Firebase אמיתי, אפשר לעיין במאמר בנושא יצירת פרויקט Firebase. ב-codelab הזה נעשה שימוש ב-Cloud Functions, לכן אם אתם משתמשים בפרויקט Firebase אמיתי במקום באמולטורים, אתם צריכים לשדרג לתוכנית התמחור Blaze.
רוצים לדלג קדימה?
אפשר להוריד גרסה מלאה של ה-codelab. אם נתקעתם במהלך התהליך או שאתם רוצים לראות איך נראה תוסף שהושלם, אתם יכולים לעיין בהסתעפות codelab-end
של מאגר GitHub או להוריד את קובץ ה-ZIP שהושלם.
3. בדיקת הקוד
- פותחים את קובץ
index.ts
מקובץ ה-ZIP. שימו לב שהוא מכיל שתי הצהרות של Cloud Functions.
מה הפונקציות האלה עושות?
הפונקציות האלה של ההדגמה משמשות לגיאו-האשינג. הם מקבלים זוג קואורדינטות והופכים אותם לפורמט שעבר אופטימיזציה לשאילתות גיאוגרפיות ב-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);
Firestore Trigger
הפונקציה הראשונה בקובץ 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
. אם שני השדות האלה קיימים, הפונקציה מחשבת את הגיאוהאש וכותבת את הפלט למיקום פלט מסמך שצוין. מסמך הקלט מוגדר על ידי הקבוע users/{uid}
, כלומר הפונקציה קוראת כל מסמך שנכתב לאוסף users/
ואז מעבדת את הגיאוהאש של המסמכים האלה. לאחר מכן, הוא מוציא את הגיבוב לשדה גיבוב באותו מסמך.
פונקציות שאפשר להפעיל
הפונקציה הבאה בקובץ 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. למרות שלא תתבצע קריאה ישירה לפונקציה הזו ב-codelab הזה, היא מופיעה כאן כדוגמה למשהו שאפשר להגדיר בתוסף Firebase.
4. הגדרת קובץ extension.yaml
אחרי שהבנתם מה קוד Cloud Functions בתוסף עושה, אפשר לארוז אותו להפצה. לכל תוסף של 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. המרת הקוד של Cloud Functions למשאב Extensions
משאב של תוסף הוא פריט שנוצר בפרויקט ב-Firebase במהלך ההתקנה של התוסף. התוסף הוא הבעלים של המשאבים האלה, ויש לו חשבון שירות ספציפי שפועל עליהם. בפרויקט הזה, המשאבים האלה הם Cloud Functions, שצריך להגדיר בקובץ extension.yaml
כי התוסף לא יוצר משאבים באופן אוטומטי מקוד שבתיקיית הפונקציות. אם לא הצהרתם באופן מפורש על Cloud Functions כמשאב, לא ניתן יהיה לפרוס אותן כשפורסים את התוסף.
מיקום פריסה בהגדרת המשתמש
- המשתמש יכול לציין את המיקום שבו הוא רוצה לפרוס את התוסף, ולהחליט אם עדיף לארח את התוסף קרוב יותר למשתמשי הקצה או קרוב יותר למסד הנתונים. בקבצים מסוג
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
של providers/cloud.firestore/eventTypes/document.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
אחרי השלמת התהליך:
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. הגדרת התוסף על ידי המשתמש
בשלב הזה של ה-codelab, יש לכם תוסף שמוגדר לשימוש בהגדרה המבוססת על דעה של הפונקציות שכבר כתבתם, אבל מה קורה אם המשתמש רוצה להשתמש בקו רוחב ובקו אורך במקום ב-y וב-x בשדות שמציינים את המיקום במישור קרטזי? בנוסף, איך אפשר לגרום למשתמש הקצה לספק מפתח API משלו, במקום להשתמש במפתח ה-API שסופק? יכול להיות שתחרגו במהירות מהמכסה של ה-API הזה. במקרה כזה, צריך להגדיר פרמטרים ולהשתמש בהם.
הגדרת פרמטרים בסיסיים בextension.yaml
קובץ
מתחילים בהמרת הפריטים שעבורם יכול להיות שלמפתחים יש הגדרה מותאמת אישית. הראשון יהיה הפרמטרים XFIELD
ו-YFIELD
.
- בקובץ
extension.yaml
, מוסיפים את הקוד הבא שמשתמש בפרמטרים של השדותXFIELD
ו-YFIELD
. הפרמטרים האלה נמצאים בתוך מאפיין ה-YAMLparams
שהוגדר קודם:
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
- התג param נותן שם לפרמטר באופן שגלוי לכם, יוצרי התוסף. תצטרכו להשתמש בערך הזה בהמשך כשתציינו את ערכי הפרמטרים.
- label הוא מזהה שקריא לבני אדם, שמאפשר למפתח לדעת מה הפרמטר עושה.
- description מספק תיאור מפורט של הערך. הכלי הזה תומך ב-Markdown, ולכן אפשר לקשר אליו מסמכים נוספים או להדגיש בו מילים שעשויות להיות חשובות למפתח.
- המאפיין type מגדיר את מנגנון הקלט שבאמצעותו המשתמש יגדיר את ערך הפרמטר. יש הרבה סוגים, כולל
string
,select
,multiSelect
,selectResource
ו-secret
. מידע נוסף על כל אחת מהאפשרויות האלה זמין במאמרי העזרה. - validationRegex מגביל את הערך שהמפתח יכול להזין לערך regex מסוים (בדוגמה הוא מבוסס על ההנחיות הפשוטות לשם השדה שמופיעות כאן). אם ההגבלה הזו לא מתקיימת…
- validationErrorMessage מתריע למפתח על ערך הכשל.
- default הוא הערך שיוצג אם המפתח לא יזין טקסט.
- חובה – המפתח לא נדרש להזין טקסט כלשהו.
- 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
:
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!;
בדרך כלל, כדאי לבצע בדיקות של ערכי null באמצעות ערכי משתני הסביבה, אבל במקרה הזה, אתם בוטחים בכך שערכי הפרמטרים מועתקים בצורה נכונה. הקוד מוגדר עכשיו לפעולה עם פרמטרי התוסף.
7. יצירת מסמכי משתמש
לפני שבודקים את הקוד באמולטורים או בשוק התוספים של Firebase, צריך לתעד את התוסף כדי שהמפתחים ידעו מה הם מקבלים כשהם משתמשים בתוסף.
- מתחילים ביצירת הקובץ
PREINSTALL.md
, שמשמש לתיאור הפונקציונליות, הדרישות המוקדמות להתקנה וההשלכות הפוטנציאליות על החיוב.
PREINSTALL.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
- מכיוון שאתם פורסים את הפרויקט באופן מקומי, צריך לציין שאתם רוצים להשתמש בקובץ מקומי ולא ב-Secret Manager של Google Cloud.
- מפעילים את חבילת הכלים לאמולטור מקומי:
firebase emulators:start
התקנה ובדיקה באמצעות פרויקט Firebase אמיתי
אפשר להתקין את התוסף בפרויקט Firebase בפועל. מומלץ להשתמש בפרויקט בדיקה לצורך הבדיקות. משתמשים בתהליך העבודה הזה לבדיקה אם רוצים לבדוק את התהליך מקצה לקצה של התוסף, או אם הטריגר של התוסף עדיין לא נתמך בחבילת האמולטורים של Firebase (ראו את האפשרות Extensions emulator). האמולטורים תומכים כרגע בפונקציות שמופעלות על ידי בקשות 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 ולהשתמש ב-Secret Manager של Google Cloud, אתם צריכים להפעיל את Secret Manager API לפני שמתקינים את התוסף.
- פורסים לפרויקט Firebase.
firebase deploy
בדיקת התוסף
- אחרי שמריצים את
firebase deploy
או אתfirebase emulators:start
, עוברים לכרטיסייה Firestore במסוף Firebase או בתצוגת האינטרנט של האמולטורים, בהתאם לצורך. - הוספת מסמך לאוסף שצוין בשדה
x
ובשדהy
. במקרה הזה, המסמכים המעודכנים נמצאים ב-u/{uid}
עם שדהx
שלxv
ושדהy
שלyv
.
- אם התקנתם את התוסף בהצלחה, התוסף יוצר שדה חדש בשם
hash
במסמך אחרי ששומרים את שני השדות.
8. כל הכבוד!
המרת בהצלחה את הפונקציה הראשונה שלך ב-Cloud Functions לתוסף Firebase!
הוספתם קובץ extension.yaml
והגדרתם אותו כך שמפתחים יוכלו לבחור איך הם רוצים לפרוס את התוסף שלכם. לאחר מכן יצרתם מסמכי משתמשים שמספקים הנחיות לגבי הפעולות שמפתחי התוסף צריכים לבצע לפני הגדרת התוסף, ואילו שלבים הם צריכים לבצע אחרי שהם מתקינים את התוסף בהצלחה.
עכשיו אתם יודעים מהם השלבים העיקריים שנדרשים כדי להמיר פונקציה של Firebase לתוסף של Firebase שאפשר להפיץ.