1. Hinweis
Eine Firebase-Erweiterung führt als Reaktion auf HTTP-Anfragen oder zum Auslösen von Ereignissen aus anderen Firebase- und Google-Produkten wie Firebase Cloud Messaging, Cloud Firestore oder Pub/Sub eine bestimmte Aufgabe oder eine Reihe von Aufgaben aus.
Umfang
In diesem Codelab erstellen Sie eine Firebase-Erweiterung für das Geohashing. Nach der Bereitstellung wandelt die Erweiterung die X- und Y-Koordinaten als Antwort auf Firestore-Ereignisse oder durch aufrufbare Funktionsaufrufe in Geohashes um. Diese Methode kann als Alternative zur Implementierung der Geofire-Bibliothek auf allen Zielplattformen verwendet werden, um Daten zu speichern.
Aufgaben in diesem Lab
- Vorhandenen Cloud Functions-Code in eine verteilbare Firebase-Erweiterung umwandeln
extension.yaml
-Datei einrichten- Sensible Strings (API-Schlüssel) in einer Erweiterung speichern
- Entwicklern der Erweiterung erlauben, sie an ihre Anforderungen anzupassen
- Erweiterung testen und bereitstellen
Voraussetzungen
- Firebase CLI (Installation und Anmeldung)
- Ein Google-Konto, z. B. ein Gmail-Konto
- Node.js und
npm
- Ihre bevorzugte Entwicklungsumgebung
2. Einrichten
Code abrufen
Alles, was Sie für diese Erweiterung benötigen, befindet sich in einem GitHub-Repository. Rufen Sie den Code ab und öffnen Sie ihn in Ihrer bevorzugten Entwicklungsumgebung.
- Entpacken Sie die heruntergeladene ZIP-Datei.
- Öffnen Sie das Terminal im Verzeichnis
functions
und führen Sie den Befehlnpm install
aus, um die erforderlichen Abhängigkeiten zu installieren.
Firebase einrichten
In diesem Codelab wird die Verwendung von Firebase-Emulatoren dringend empfohlen. Wenn Sie die Entwicklung von Erweiterungen mit einem echten Firebase-Projekt ausprobieren möchten, lesen Sie den Artikel Firebase-Projekt erstellen. In diesem Codelab wird Cloud Functions verwendet. Wenn Sie also ein echtes Firebase-Projekt anstelle der Emulatoren verwenden, müssen Sie ein Upgrade auf das Blaze-Preismodell ausführen.
Möchtest du überspringen?
Sie können eine fertige Version des Codelabs herunterladen. Wenn Sie nicht weiterkommen oder sehen möchten, wie eine fertige Erweiterung aussieht, sehen Sie sich den Zweig codelab-end
des GitHub-Repositorys an oder laden Sie die fertige ZIP-Datei herunter.
3. Code ansehen
- Öffnen Sie die Datei
index.ts
aus der ZIP-Datei. Wie Sie sehen, enthält er zwei Cloud Functions-Deklarationen.
Welche Funktionen haben diese Schaltflächen?
Diese Demofunktionen werden für das Geohashing verwendet. Sie wandeln ein Koordinatenpaar in ein Format um, das für Geoabfragen in Firestore optimiert ist. Die Funktionen simulieren die Verwendung eines API-Aufrufs, sodass Sie mehr über den Umgang mit sensiblen Datentypen in Erweiterungen erfahren. Weitere Informationen finden Sie in der Dokumentation zum Ausführen von Geoabfragen für Daten in Firestore.
Funktionskonstanten
Konstanten werden früh am Anfang der Datei index.ts
deklariert. Auf einige dieser Konstanten wird in den definierten Triggern der Erweiterung verwiesen.
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
Die erste Funktion in der Datei index.ts
sieht so aus:
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,
}
);
});
Diese Funktion ist ein Firestore-Trigger. Wenn in der Datenbank ein Schreibereignis auftritt, reagiert die Funktion darauf, indem sie nach einem xv
-Feld und einem yv
-Feld sucht. Wenn beide Felder vorhanden sind, berechnet sie den Geohash und schreibt die Ausgabe an einen angegebenen Speicherort für die Dokumentausgabe. Das Eingabedokument wird durch die Konstante users/{uid}
definiert. Das bedeutet, dass die Funktion jedes in die Sammlung users/
geschriebene Dokument liest und dann einen Geohash für diese Dokumente verarbeitet. Der Hashwert wird dann in ein Hash-Feld im selben Dokument ausgegeben.
Aufrufbare Funktionen
Die nächste Funktion in der Datei index.ts
sieht so aus:
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};
});
Beachten Sie die Funktion onCall
. Es gibt an, dass diese Funktion eine aufrufbare Funktion ist, die innerhalb Ihres Clientanwendungscodes aufgerufen werden kann. Diese aufrufbare Funktion verwendet die Parameter x
und y
und gibt einen Geohash zurück. Diese Funktion wird in diesem Codelab zwar nicht direkt aufgerufen, sie dient aber als Beispiel für eine Funktion, die in der Firebase-Erweiterung konfiguriert werden kann.
4. Datei „extension.yaml“ einrichten
Da Sie jetzt wissen, was der Cloud Functions-Code in Ihrer Erweiterung bewirkt, können Sie ihn für den Vertrieb verpacken. Jede Firebase-Erweiterung enthält eine extension.yaml
-Datei, in der die Funktion und das Verhalten der Erweiterung beschrieben werden.
Für eine extension.yaml
-Datei sind einige anfängliche Metadaten zu Ihrer Erweiterung erforderlich. Jeder der folgenden Schritte hilft Ihnen zu verstehen, was die Felder bedeuten und warum Sie sie benötigen.
- Erstellen Sie im Stammverzeichnis des zuvor heruntergeladenen Projekts eine
extension.yaml
-Datei. Fügen Sie zuerst Folgendes hinzu:
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
Der Name der Erweiterung wird als Basis für die Instanz-ID der Erweiterung verwendet. Nutzer können mehrere Instanzen einer Erweiterung mit jeweils einer eigenen ID installieren. Firebase generiert dann anhand dieser Instanz-ID den Namen der Dienstkonten und die erweiterungsspezifischen Ressourcen der Erweiterung. Die Versionsnummer gibt die Version Ihrer Erweiterung an. Sie muss der semantischen Versionsverwaltung entsprechen und immer dann aktualisiert werden, wenn Sie Änderungen an der Funktionalität der Erweiterung vornehmen. Anhand der Version der Erweiterungsspezifikation wird ermittelt, welcher Firebase-Erweiterungsspezifikation zu folgen ist. In diesem Fall wird v1beta
verwendet.
- Fügen Sie der YAML-Datei einige nutzerfreundliche Details hinzu:
...
displayName: Latitude and longitude to GeoHash converter
description: A converter for changing your Latitude and longitude coordinates to geohashes.
Der Anzeigename ist eine anschauliche Darstellung des Namens Ihrer Erweiterung, wenn Entwickler mit der Erweiterung interagieren. Die Beschreibung gibt einen kurzen Überblick über die Funktion der Erweiterung. Wenn die Erweiterung auf extensions.dev bereitgestellt wird, sieht sie in etwa so aus:
- Geben Sie die Lizenz für den Code in Ihrer Erweiterung an.
...
license: Apache-2.0 # The license you want for the extension
- Geben Sie an, wer die Erweiterung erstellt hat und ob für die Installation eine Abrechnung erforderlich ist:
...
author:
authorName: AUTHOR_NAME
url: https://github.com/Firebase
billingRequired: true
Im Abschnitt author
können Sie Nutzern mitteilen, an wen sie sich wenden können, wenn sie Probleme mit der Erweiterung haben oder weitere Informationen dazu benötigen. billingRequired
ist ein erforderlicher Parameter und muss auf true
gesetzt werden, da alle Erweiterungen auf Cloud Functions basieren, wofür der Tarif „Blaze“ erforderlich ist.
Dies entspricht der Mindestanzahl von Feldern, die in der extension.yaml
-Datei zur Identifizierung dieser Erweiterung erforderlich sind. Weitere Informationen zu anderen personenidentifizierbaren Informationen, die Sie in einer Erweiterung angeben können, finden Sie in der Dokumentation.
5. Cloud Functions-Code in eine Erweiterungsressource konvertieren
Eine Erweiterungsressource ist ein Element, das Firebase bei der Installation einer Erweiterung im Projekt erstellt. Die Erweiterung ist dann Inhaber dieser Ressourcen und hat ein bestimmtes Dienstkonto, das sie verwaltet. In diesem Projekt sind das Cloud Functions, die in der Datei extension.yaml
definiert werden müssen, da die Erweiterung keine Ressourcen automatisch aus dem Code im Ordner „functions“ erstellt. Wenn Ihre Cloud Functions nicht explizit als Ressource deklariert sind, können sie nicht bereitgestellt werden, wenn die Erweiterung bereitgestellt wird.
Benutzerdefinierter Bereitstellungsort
- Der Nutzer kann den Speicherort angeben, an dem er diese Erweiterung bereitstellen möchte, und entscheiden, ob es besser ist, die Erweiterung näher an den Endnutzern oder näher an der Datenbank zu hosten. Fügen Sie in der Datei
extension.yaml
die Option zur Auswahl eines Speicherorts hinzu.
extension.yaml
Sie können jetzt die Konfiguration für die Funktionsressource schreiben.
- Erstellen Sie in der Datei
extension.yaml
ein Ressourcenobjekt für die FunktionlocationUpdate
. Hängen Sie Folgendes an die Dateiextension.yaml
an:
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}
Sie definieren name
als den Funktionsnamen, der in der Datei index.ts
des Projekts definiert ist. Sie geben die type
der Funktion an, die bereitgestellt wird. Diese sollte vorerst immer firebaseextensions.v1beta.function
sein. Als Nächstes definieren Sie die properties
dieser Funktion. Das erste Attribut, das Sie definieren, ist die eventTrigger
, die mit dieser Funktion verknüpft ist. Um zu spiegeln, was die Erweiterung derzeit unterstützt, verwenden Sie den eventType
von providers/cloud.firestore/eventTypes/document.write
. Sie finden ihn in der Dokumentation Cloud Functions für Ihre Erweiterung schreiben. Sie definieren resource
als Speicherort der Dokumente. Da Ihr aktuelles Ziel darin besteht, den Code zu spiegeln, überwacht der Dokumentpfad users/{uid}
mit dem Standardspeicherort der Datenbank.
- Die Erweiterung benötigt Lese- und Schreibberechtigungen für die Firestore-Datenbank. Ganz am Ende der Datei
extension.yaml
geben Sie die IAM-Rollen an, auf die die Erweiterung Zugriff haben soll, um mit der Datenbank im Firebase-Projekt des Entwicklers zu arbeiten.
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
Die Rolle datastore.user
stammt aus der Liste der unterstützten IAM-Rollen für Erweiterungen. Da die Erweiterung lesen und schreiben wird, eignet sich die Rolle datastore.user
gut.
- Die aufrufbare Funktion muss ebenfalls hinzugefügt werden. Erstellen Sie in der Datei
extension.yaml
unter dem Attribut „resources“ eine neue Ressource. Diese Properties sind spezifisch für eine aufrufbare Funktion:
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
In der vorherigen Ressource wurde zwar ein eventTrigger
verwendet, hier verwenden Sie jedoch ein httpsTrigger
, das sowohl aufrufbare Funktionen als auch HTTPS-Funktionen abdeckt.
Codeprüfung
Das war eine Menge Konfiguration, um dafür zu sorgen, dass extension.yaml
mit allem übereinstimmt, was der Code in der Datei index.ts
vornimmt. Die fertige extension.yaml
-Datei sollte jetzt so aussehen:
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.
Statusprüfung
Sie haben jetzt die ersten funktionalen Teile der Erweiterung eingerichtet und können sie mit den Firebase-Emulatoren testen.
- Rufen Sie
npm run build
im Ordner „functions“ des heruntergeladenen Erweiterungsprojekts auf, falls noch nicht geschehen. - Erstellen Sie ein neues Verzeichnis auf Ihrem Hostsystem und verknüpfen Sie es mit
firebase init
mit Ihrem Firebase-Projekt.
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.
- Führen Sie im selben Verzeichnis
firebase ext:install
aus. Ersetzen Sie/path/to/extension
durch den absoluten Pfad zum Verzeichnis, das die Dateiextension.yaml
enthält.
firebase ext:install /path/to/extension
This command does two things:
- Sie werden aufgefordert, die Konfiguration für die Erweiterungs-Instanz anzugeben. Daraufhin wird eine
*.env
-Datei mit den Konfigurationsinformationen für die Instanz erstellt. - Dadurch wird die Erweiterungs-Instanz dem Abschnitt
extensions
Ihrerfirebase.json
hinzugefügt. Dies dient als Zuordnung der Instanz-ID zur Erweiterungsversion. - Da Sie das Projekt lokal bereitstellen, können Sie angeben, dass Sie anstelle von Google Cloud Secret Manager eine lokale Datei verwenden möchten.
- Starten Sie die Firebase-Emulatoren mit der neuen Konfiguration:
firebase emulators:start
- Nachdem Sie
emulators:start
ausgeführt haben, gehen Sie in der Webansicht der Emulatoren zum Tab „Firestore“. - Fügen Sie der Sammlung
users
ein Dokument mit dem Zahlenfeldxv
und dem Zahlenfeldyv
hinzu.
- Wenn die Erweiterung erfolgreich installiert wurde, erstellt sie im Dokument ein neues Feld mit dem Namen „
hash
“.
Bereinigung durchführen, um Konflikte zu vermeiden
- Entfernen Sie die Erweiterung, sobald Sie mit den Tests fertig sind. Sie aktualisieren den Erweiterungscode und möchten später keine Konflikte mit der aktuellen Erweiterung haben.
Erweiterungen ermöglichen die gleichzeitige Installation mehrerer Versionen derselben Erweiterung. Durch die Deinstallation stellen Sie also sicher, dass es keine Konflikte mit einer bereits installierten Erweiterung gibt.
firebase ext:uninstall geohash-ext
Die aktuelle Lösung funktioniert, aber wie bereits zu Beginn des Projekts erwähnt, gibt es einen hartcodierten API-Schlüssel, um die Kommunikation mit einem Dienst zu simulieren. Wie kannst du den API-Schlüssel des Endnutzers anstelle des ursprünglich angegebenen verwenden? Lies weiter und finde es heraus.
6. Erweiterung für Nutzer konfigurierbar machen
An dieser Stelle im Codelab haben Sie eine Erweiterung, die für die Verwendung mit der spezifischen Einrichtung der bereits geschriebenen Funktionen konfiguriert ist. Aber was ist, wenn der Nutzer für die Felder, die den Standort auf einer kartesischen Ebene angeben, Breitengrad und Längengrad anstelle von y und x verwenden möchte? Wie können Sie dafür sorgen, dass der Endnutzer seinen eigenen API-Schlüssel bereitstellt, anstatt den bereitgestellten API-Schlüssel nutzen zu lassen? Sie könnten das Kontingent für diese API schnell überschreiten. In diesem Fall richten Sie Parameter ein und verwenden sie.
Grundlegende Parameter in der extension.yaml
-Datei definieren
Konvertieren Sie zuerst die Elemente, für die Entwickler möglicherweise eine benutzerdefinierte Konfiguration haben. Die ersten sind die Parameter XFIELD
und YFIELD
.
- Fügen Sie in der Datei
extension.yaml
den folgenden Code hinzu, in dem die FeldparameterXFIELD
undYFIELD
verwendet werden. Diese Parameter befinden sich in der zuvor definierten YAML-Eigenschaftparams
:
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
- Mit param wird der Parameter so benannt, dass er für Sie als Ersteller der Erweiterung sichtbar ist. Verwenden Sie diesen Wert später bei der Angabe der Parameterwerte.
- label ist eine menschenlesbare Kennung für den Entwickler, um ihm die Funktion des Parameters mitzuteilen.
- description liefert eine detaillierte Beschreibung des Werts. Da Markdown unterstützt wird, können Links zu zusätzlicher Dokumentation hinzugefügt oder Wörter hervorgehoben werden, die für den Entwickler wichtig sein könnten.
- type definiert den Eingabemechanismus dafür, wie ein Nutzer den Parameterwert festlegen kann. Es gibt viele Typen, darunter
string
,select
,multiSelect
,selectResource
undsecret
. Weitere Informationen zu diesen Optionen finden Sie in der Dokumentation. - validationRegex schränkt den Entwicklereintrag auf einen bestimmten Regex-Wert ein. In diesem Beispiel basiert er auf den Richtlinien für einfache Feldnamen, die Sie hier finden. und falls das nicht funktioniert...
- validationErrorMessage informiert den Entwickler über den Fehlerwert.
- default ist der Wert, der verwendet würde, wenn der Entwickler keinen Text eingegeben hätte.
- required bedeutet, dass der Entwickler keinen Text eingeben muss.
- unveränderlich ermöglicht dem Entwickler, diese Erweiterung zu aktualisieren und diesen Wert zu ändern. In diesem Fall sollte der Entwickler die Feldnamen ändern können, wenn sich seine Anforderungen ändern.
- example veranschaulicht, wie eine gültige Eingabe aussehen könnte.
Das war eine Menge zu verstehen.
- Sie müssen der Datei
extension.yaml
drei weitere Parameter hinzufügen, bevor Sie einen speziellen Parameter hinzufügen.
- 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
Sensible Parameter definieren
Jetzt müssen Sie den vom Nutzer angegebenen API-Schlüssel verwalten. Dies ist ein vertraulicher String, der nicht als Klartext in der Funktion gespeichert werden sollte. Speichern Sie diesen Wert stattdessen im Cloud Secret Manager. Dies ist ein spezieller Ort in der Cloud, an dem verschlüsselte Secrets gespeichert werden und der verhindert, dass diese versehentlich gehackt werden. Dies erfordert, dass der Entwickler für die Nutzung dieses Dienstes bezahlt, bietet aber eine zusätzliche Sicherheitsebene für seine API-Schlüssel und schränkt möglicherweise betrügerische Aktivitäten ein. In der Nutzerdokumentation wird der Entwickler darauf hingewiesen, dass es sich um einen kostenpflichtigen Dienst handelt, damit es bei der Abrechnung keine Überraschungen gibt. Insgesamt ähnelt die Verwendung den anderen String-Ressourcen, die oben erwähnt wurden. Der einzige Unterschied ist der Typ secret
.
- Fügen Sie in der Datei
extension.yaml
den folgenden Code hinzu:
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
Aktualisieren Sie die resource
-Attribute, um Parameter zu verwenden.
Wie bereits erwähnt, wird in der Ressource (nicht in der Funktion) festgelegt, wie die Ressource beobachtet wird. Daher muss die locationUpdate
-Ressource aktualisiert werden, damit der neue Parameter verwendet werden kann.
- Fügen Sie in der Datei
extension.yaml
den folgenden Code hinzu:
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
-Datei prüfen
- Prüfen Sie die Datei
extension.yaml
. Die Ausgabe sollte ungefähr so aussehen:
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.
Auf Parameter im Code zugreifen
Nachdem Sie nun alle Parameter in der Datei extension.yaml
konfiguriert haben, fügen Sie sie der Datei index.ts
hinzu.
- Ersetzen Sie in der Datei
index.ts
die Standardwerte durchprocess.env.PARAMETER_NAME
. Dadurch werden die entsprechenden Parameterwerte abgerufen und in den Funktionscode eingefügt, der im Firebase-Projekt des Entwicklers bereitgestellt wird.
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!;
Normalerweise möchten Sie Null-Prüfungen mit den Werten der Umgebungsvariablen durchführen, in diesem Fall vertrauen Sie jedoch darauf, dass die Parameterwerte korrekt kopiert werden. Der Code ist jetzt für die Verwendung der Erweiterungsparameter konfiguriert.
7. Nutzerdokumentation erstellen
Bevor der Code auf Emulatoren oder im Firebase-Erweiterungen-Marktplatz getestet werden kann, muss die Erweiterung dokumentiert werden, damit Entwickler wissen, was sie bei der Verwendung der Erweiterung erhalten.
- Erstellen Sie zuerst die Datei
PREINSTALL.md
, in der die Funktion, die Voraussetzungen für die Installation und die potenziellen Auswirkungen auf die Abrechnung beschrieben werden.
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)
- Wenn Sie beim Schreiben der
README.md
für dieses Projekt Zeit sparen möchten, können Sie die folgende Methode verwenden:
firebase ext:info . --markdown > README.md
Dadurch werden der Inhalt der Datei „PREINSTALL.md
“ mit zusätzlichen Details zur Erweiterung aus der Datei „extension.yaml
“ kombiniert.
Teilen Sie dem Entwickler der Erweiterung abschließend einige zusätzliche Details zur gerade installierten Erweiterung mit. Der Entwickler erhält möglicherweise nach Abschluss der Installation einige zusätzliche Anweisungen und Informationen sowie detaillierte Aufgaben nach der Installation, z. B. die Einrichtung des Clientcodes.
- Erstellen Sie eine
POSTINSTALL.md
-Datei und geben Sie dann nach der Installation die folgenden Informationen an:
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);
});
Monitoring
Als Best Practice haben Sie die Möglichkeit, die Aktivität Ihrer installierten Erweiterung zu überwachen, einschließlich Überprüfung des Zustands, der Nutzung und der Protokolle.
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
Dadurch werden die Funktionen neu kompiliert, sodass der aktuelle Quellcode zusammen mit der Erweiterung bereitgestellt werden kann, wenn sie in einem Emulator oder direkt in Firebase bereitgestellt wird.
Erstellen Sie als Nächstes ein neues Verzeichnis, in dem Sie die Erweiterung testen möchten. Da die Erweiterung aus vorhandenen Funktionen entwickelt wurde, sollten Sie sie nicht aus dem Ordner testen, in dem sie konfiguriert wurde, da dabei auch versucht wird, die Funktionen und Firebase-Regeln zusammen mit der Erweiterung bereitzustellen.
Firebase-Emulatoren installieren und testen
- Erstellen Sie ein neues Verzeichnis auf Ihrem Hostsystem und verknüpfen Sie es mit
firebase init
mit Ihrem Firebase-Projekt.
mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Führen Sie in diesem Verzeichnis
firebase ext:install
aus, um die Erweiterung zu installieren. Ersetzen Sie/path/to/extension
durch den absoluten Pfad zu dem Verzeichnis, das die Dateiextension.yaml
enthält. Dadurch wird der Installationsprozess für Ihre Erweiterung gestartet und eine.env
-Datei mit Ihren Konfigurationen erstellt, bevor die Konfiguration an Firebase oder an die Emulatoren gesendet wird.
firebase ext:install /path/to/extension
- Da Sie das Projekt lokal bereitstellen, geben Sie an, dass Sie eine lokale Datei anstelle des Google Cloud Secret Manager verwenden möchten.
- Starten Sie die lokale Emulator-Suite:
firebase emulators:start
Mit einem echten Firebase-Projekt installieren und testen
Sie können Ihre Erweiterung in einem echten Firebase-Projekt installieren. Wir empfehlen, für die Tests ein Testprojekt zu verwenden. Verwenden Sie diesen Testablauf, wenn Sie den End-to-End-Vorgang Ihrer Erweiterung testen möchten oder der Trigger Ihrer Erweiterung noch nicht von der Firebase-Emulator-Suite unterstützt wird (siehe Emulatoroption für Erweiterungen). Die Emulatoren unterstützen derzeit HTTP-Anfrage- und Hintergrundereignis-ausgelöste Funktionen für Cloud Firestore, Realtime Database und Pub/Sub.
- Erstellen Sie ein neues Verzeichnis auf Ihrem Hostsystem und verknüpfen Sie es mit
firebase init
mit Ihrem Firebase-Projekt.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Führen Sie dann in diesem Verzeichnis
firebase ext:install
aus, um die Erweiterung zu installieren. Ersetzen Sie/path/to/extension
durch den absoluten Pfad zum Verzeichnis, das dieextension.yaml
-Datei enthält. Dadurch wird der Installationsvorgang für die Erweiterung gestartet und eine.env
-Datei mit Ihren Konfigurationen erstellt, bevor die Konfiguration an Firebase oder die Emulatoren übertragen wird.
firebase ext:install /path/to/extension
- Da Sie die Anwendung direkt in Firebase bereitstellen und den Google Cloud Secret Manager verwenden möchten, müssen Sie die Secret Manager API aktivieren, bevor Sie die Erweiterung installieren.
- In Ihrem Firebase-Projekt bereitstellen
firebase deploy
Erweiterung testen
- Nachdem Sie
firebase deploy
oderfirebase emulators:start
ausgeführt haben, rufen Sie entweder in der Firebase Console oder in der WebView der Emulatoren den Firestore-Tab auf. - Fügen Sie ein Dokument in die Sammlung ein, die mit den Feldern
x
undy
angegeben wird. In diesem Fall befinden sich die aktualisierten Dokumente unteru/{uid}
mit dem Feldx
vonxv
und dem Feldy
vonyv
.
- Wenn die Installation der Erweiterung erfolgreich war, wird nach dem Speichern der beiden Felder ein neues Feld mit dem Namen
hash
im Dokument erstellt.
8. Glückwunsch!
Sie haben Ihre erste Cloud-Funktion erfolgreich in eine Firebase-Erweiterung umgewandelt.
Sie haben eine extension.yaml
-Datei hinzugefügt und so konfiguriert, dass Entwickler auswählen können, wie Ihre Erweiterung bereitgestellt werden soll. Anschließend haben Sie eine Nutzerdokumentation erstellt, in der erklärt wird, was Entwickler der Erweiterung vor der Einrichtung der Erweiterung tun sollten und welche Schritte sie nach der Installation ausführen müssen.
Sie kennen jetzt die wichtigsten Schritte zum Umwandeln einer Firebase-Funktion in eine verteilbare Firebase-Erweiterung.