1. Zanim zaczniesz
Rozszerzenie Firebase wykonuje określone zadanie lub zestaw zadań w odpowiedzi na żądania HTTP lub zdarzenia wyzwalające z innych produktów Firebase i Google, takich jak Firebase Cloud Messaging, Cloud Firestore lub Pub/Sub.
Co zbudujesz
Podczas tych zajęć z programowania utworzysz rozszerzenie Firebase do geohashingu . Po wdrożeniu rozszerzenie konwertuje współrzędne X i Y na geohasze w odpowiedzi na zdarzenia Firestore lub poprzez wywołania funkcji, które można wywołać. Można to wykorzystać jako alternatywę dla wdrożenia biblioteki geofire na wszystkich platformach docelowych do przechowywania danych, oszczędzając czas.
Czego się dowiesz
- Jak wziąć istniejący kod Cloud Functions i przekształcić go w dystrybuowalne rozszerzenie Firebase
- Jak skonfigurować plik
extension.yaml
- Jak przechowywać wrażliwe ciągi znaków (klucze API) w rozszerzeniu
- Jak umożliwić twórcom rozszerzenia skonfigurowanie go pod własne potrzeby
- Jak przetestować i wdrożyć rozszerzenie
Co będziesz potrzebował
- Firebase CLI (instalacja i logowanie)
- Konto Google, takie jak konto Gmail
- Node.js i
npm
- Twoje ulubione środowisko programistyczne
2. Przygotuj się
Zdobądź kod
Wszystko, czego potrzebujesz do tego rozszerzenia, znajduje się w repozytorium GitHub. Aby rozpocząć, pobierz kod i otwórz go w swoim ulubionym środowisku programistycznym.
- Rozpakuj pobrany plik zip.
- Aby zainstalować wymagane zależności, otwórz terminal w katalogu
functions
i uruchom polecenienpm install
.
Skonfiguruj Firebase
To ćwiczenie z programowania bardzo zachęca do korzystania z emulatorów Firebase. Jeśli chcesz wypróbować tworzenie rozszerzeń w prawdziwym projekcie Firebase, zobacz tworzenie projektu Firebase . To ćwiczenie z programowania korzysta z Cloud Functions, więc jeśli zamiast emulatorów używasz prawdziwego projektu Firebase, musisz przejść na plan cenowy Blaze .
Chcesz przejść dalej?
Możesz pobrać ukończoną wersję ćwiczeń z programowania. Jeśli utkniesz po drodze lub chcesz zobaczyć, jak wygląda ukończone rozszerzenie, sprawdź gałąź codelab-end
w repozytorium GitHub lub pobierz ukończony plik ZIP.
3. Przejrzyj kod
- Otwórz plik
index.ts
z pliku ZIP. Zauważ, że zawiera dwie deklaracje Cloud Functions.
Co robią te funkcje?
Te funkcje demonstracyjne służą do geohashingu. Biorą parę współrzędnych i przekształcają je w format zoptymalizowany pod kątem zapytań geograficznych w Firestore. Funkcje symulują użycie wywołania API, dzięki czemu możesz dowiedzieć się więcej o obsłudze wrażliwych typów danych w rozszerzeniach. Aby uzyskać więcej informacji, zapoznaj się z dokumentacją dotyczącą uruchamiania zapytań Geo na danych w Firestore .
Stałe funkcji
Stałe deklarowane są na początku, na górze pliku index.ts
. Do niektórych z tych stałych odwołują się zdefiniowane wyzwalacze rozszerzenia.
indeks.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);
Wyzwalacz Firestore
Pierwsza funkcja w pliku index.ts
wygląda następująco:
indeks.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,
}
);
});
Ta funkcja jest wyzwalaczem Firestore . Gdy w bazie danych wystąpi zdarzenie zapisu, funkcja reaguje na to zdarzenie, wyszukując pola xv
i pole yv
, a jeśli oba te pola istnieją, oblicza geohash i zapisuje wynik w określonej lokalizacji wyjściowej dokumentu. Dokument wejściowy jest definiowany przez stałą users/{uid}
, co oznacza, że funkcja czyta każdy dokument zapisany w kolekcji users/
, a następnie przetwarza geohash dla tych dokumentów. Następnie wyprowadza skrót do pola skrótu w tym samym dokumencie.
Funkcje wywoływalne
Następna funkcja w pliku index.ts
wygląda następująco:
indeks.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};
});
Zwróć uwagę na funkcję onCall
. Wskazuje, że ta funkcja jest funkcją wywoływalną , którą można wywołać z poziomu kodu aplikacji klienckiej. Ta wywoływalna funkcja pobiera parametry x
i y
i zwraca geohash. Chociaż ta funkcja nie będzie wywoływana bezpośrednio w tym ćwiczeniu z programowania, została ona tutaj uwzględniona jako przykład czegoś do skonfigurowania w rozszerzeniu Firebase.
4. Skonfiguruj plik rozszerzenie.yaml
Teraz, gdy wiesz, co robi kod Cloud Functions w Twoim rozszerzeniu, możesz spakować go do dystrybucji. Każde rozszerzenie Firebase zawiera plik extension.yaml
, który opisuje, co robi rozszerzenie i jak się zachowuje.
Plik extension.yaml
wymaga początkowych metadanych na temat rozszerzenia. Każdy z poniższych kroków pomoże Ci zrozumieć, co oznaczają wszystkie pola i dlaczego są potrzebne.
- Utwórz plik
extension.yaml
w katalogu głównym pobranego wcześniej projektu. Zacznij od dodania następujących elementów:
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
Nazwa rozszerzenia jest używana jako podstawa identyfikatora instancji rozszerzenia (użytkownicy mogą zainstalować wiele wystąpień rozszerzenia, każde z własnym identyfikatorem). Firebase następnie generuje nazwy kont usług rozszerzenia i zasobów specyficznych dla rozszerzenia, korzystając z tego identyfikatora instancji. Numer wersji wskazuje wersję Twojego rozszerzenia. Musi być zgodne z wersjonowaniem semantycznym i należy je aktualizować za każdym razem, gdy wprowadzasz zmiany w funkcjonalności rozszerzenia. Wersja specyfikacji rozszerzenia służy do określenia, której specyfikacji rozszerzeń Firebase należy przestrzegać, w tym przypadku używana jest v1beta
.
- Dodaj kilka przyjaznych dla użytkownika szczegółów do pliku YAML:
...
displayName: Latitude and longitude to GeoHash converter
description: A converter for changing your Latitude and longitude coordinates to geohashes.
Nazwa wyświetlana jest przyjazną reprezentacją nazwy Twojego rozszerzenia, gdy programiści wchodzą w interakcję z Twoim rozszerzeniem. Opis zawiera krótki przegląd funkcji rozszerzenia. Po wdrożeniu rozszerzenia na stronie rozszerzenia.dev wygląda to mniej więcej tak:
- Określ licencję na kod w swoim rozszerzeniu.
...
license: Apache-2.0 # The license you want for the extension
- Wskaż, kto jest autorem rozszerzenia i czy jego instalacja wymaga płatności:
...
author:
authorName: AUTHOR_NAME
url: https://github.com/Firebase
billingRequired: true
Sekcja author
służy do informowania użytkowników, do kogo mogą się zwrócić w przypadku problemów z rozszerzeniem lub chęci uzyskania dodatkowych informacji na jego temat. billingRequired
jest wymaganym parametrem i musi mieć wartość true
, ponieważ wszystkie rozszerzenia korzystają z Cloud Functions, co wymaga planu Blaze.
Obejmuje to minimalną liczbę pól wymaganych w pliku extension.yaml
w celu zidentyfikowania tego rozszerzenia. Więcej informacji na temat innych informacji identyfikacyjnych, które można określić w rozszerzeniu, można znaleźć w dokumentacji .
5. Przekonwertuj kod Cloud Functions na zasób rozszerzeń
Zasób rozszerzenia to element, który Firebase tworzy w projekcie podczas instalacji rozszerzenia. Rozszerzenie jest wówczas właścicielem tych zasobów i ma określone konto usługi, które na nich operuje. W tym projekcie tymi zasobami są Cloud Functions, które należy zdefiniować w pliku extension.yaml
, ponieważ rozszerzenie nie utworzy automatycznie zasobów z kodu w folderze funkcji. Jeśli Twoje funkcje Cloud Functions nie zostały jawnie zadeklarowane jako zasób, nie można ich wdrożyć podczas wdrażania rozszerzenia.
Zdefiniowana przez użytkownika lokalizacja wdrożenia
- Pozwól użytkownikowi określić lokalizację, w której chce wdrożyć to rozszerzenie, i zdecydować, czy lepiej będzie hostować rozszerzenie bliżej użytkowników końcowych, czy bliżej ich bazy danych. W pliku
extension.yaml
dołącz opcję wyboru lokalizacji.
rozszerzenie.yaml
Można teraz zapisać konfigurację zasobu funkcji.
- W pliku
extension.yaml
utwórz obiekt zasobu dla funkcjilocationUpdate
. Dołącz następujący tekst do plikuextension.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
definiujesz jako nazwę funkcji zdefiniowaną w pliku index.ts
projektu. Określasz type
wdrażanej funkcji, czyli na razie zawsze powinna to być firebaseextensions.v1beta.function
. Następnie definiujesz properties
tej funkcji. pierwszą zdefiniowaną właściwością jest eventTrigger
powiązany z tą funkcją. Aby odzwierciedlić to, co rozszerzenie jest obecnie obsługiwane, użyj eventType
providers/cloud.firestore/eventTypes/document.write
, który można znaleźć w dokumentacji rozszerzenia Write Cloud Functions . resource
definiujesz jako lokalizację dokumentów. Ponieważ Twoim obecnym celem jest odzwierciedlenie tego, co istnieje w kodzie, ścieżka dokumentu nasłuchuje users/{uid}
, z poprzedzającą domyślną lokalizacją bazy danych.
- Rozszerzenie wymaga uprawnień do odczytu i zapisu w bazie danych Firestore. Na samym końcu pliku
extension.yaml
określ role IAM, do których rozszerzenie powinno mieć dostęp, aby móc pracować z bazą danych w projekcie Firebase dewelopera.
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
Rola datastore.user
pochodzi z listy obsługiwanych ról IAM dla rozszerzeń . Ponieważ rozszerzenie będzie czytać i zapisywać, rola datastore.user
dobrze tu pasuje.
- Należy również dodać funkcję wywoływalną. W pliku
extension.yaml
utwórz nowy zasób we właściwości Resources. Te właściwości są specyficzne dla funkcji wywoływalnej:
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
Chociaż poprzedni zasób korzystał z eventTrigger
, tutaj używasz httpsTrigger
, który obejmuje zarówno funkcje wywoływalne, jak i funkcje HTTPS.
Kontrola kodu
Wymagało to dużo konfiguracji, aby plik extension.yaml
pasował do wszystkiego, co zrobił kod w pliku index.ts
. Tak powinien w tej chwili wyglądać gotowy plik extension.yaml
:
rozszerzenie.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.
Kontrola stanu
W tym momencie masz skonfigurowane początkowe elementy funkcjonalne rozszerzenia, więc możesz go wypróbować za pomocą emulatorów Firebase!
- Jeśli jeszcze tego nie zrobiłeś, wywołaj
npm run build
w folderze funkcji pobranego projektu rozszerzeń. - Utwórz nowy katalog w systemie hosta i połącz ten katalog z projektem Firebase za pomocą
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.
- Z tego samego katalogu uruchom
firebase ext:install
. Zamień/path/to/extension
na bezwzględną ścieżkę do katalogu zawierającego plikextension.yaml
.
firebase ext:install /path/to/extension
This command does two things:
- Monituje o określenie konfiguracji instancji rozszerzenia i tworzy plik
*.env
zawierający informacje o konfiguracji instancji. - Dodaje instancję rozszerzenia do sekcji
extensions
plikufirebase.json
. Działa to jak mapa identyfikatora instancji na wersję rozszerzenia. - Ponieważ wdrażasz projekt lokalnie, możesz określić, że chcesz używać pliku lokalnego, a nie Menedżera Google Cloud Secret.
- Uruchom emulatory Firebase z nową konfiguracją:
firebase emulators:start
- Po uruchomieniu
emulators:start
przejdź do karty Firestore w widoku internetowym emulatorów. - Dodaj dokument do kolekcji
users
z polemxv
iyv
.
- Jeśli pomyślnie zainstalowałeś rozszerzenie, utworzy ono w dokumencie nowe pole o nazwie
hash
.
Posprzątaj, aby uniknąć konfliktów
- Po zakończeniu testowania odinstaluj rozszerzenie — zamierzasz zaktualizować kod rozszerzenia i nie chcesz później powodować konfliktu z bieżącym rozszerzeniem.
Rozszerzenia umożliwiają jednoczesne zainstalowanie wielu wersji tego samego rozszerzenia, więc odinstalowując, masz pewność, że nie będzie konfliktów z wcześniej zainstalowanym rozszerzeniem.
firebase ext:uninstall geohash-ext
Obecne rozwiązanie działa, ale jak wspomniano na początku projektu, istnieje zakodowany na stałe klucz API do symulacji komunikacji z usługą. Jak można wykorzystać klucz API użytkownika końcowego zamiast oryginalnie dostarczonego? Czytaj dalej, aby się dowiedzieć.
6. Ustaw rozszerzenie jako konfigurowalne przez użytkownika
Na tym etapie ćwiczeń z kodowania masz rozszerzenie skonfigurowane do użytku z uproszczoną konfiguracją funkcji, które już napisałeś, ale co się stanie, jeśli użytkownik będzie chciał użyć szerokości i długości geograficznej zamiast y i x w polach wskazujących położenie na płaszczyźnie kartezjańskiej? Ponadto, w jaki sposób można nakłonić użytkownika końcowego do dostarczenia własnego klucza API, zamiast pozwalać mu korzystać z dostarczonego klucza API? Możesz szybko przekroczyć limit dla tego interfejsu API. W tym przypadku konfigurujesz i używasz parametrów.
Zdefiniuj podstawowe parametry w pliku extension.yaml
Zacznij od konwersji elementów, dla których programiści mogą potencjalnie mieć niestandardową konfigurację. Pierwszym z nich będą parametry XFIELD
i YFIELD
.
- W pliku
extension.yaml
dodaj następujący kod, który wykorzystuje parametry pólXFIELD
iYFIELD
. Parametry te znajdują się wewnątrz wcześniej zdefiniowanej właściwościparams
YAML:
rozszerzenie.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 nazywa parametr w sposób widoczny dla Ciebie, producenta rozszerzenia. Użyj tej wartości później podczas określania wartości parametrów.
- etykieta jest czytelnym dla człowieka identyfikatorem dla programisty, informującym go o działaniu parametru.
- opis zawiera szczegółowy opis wartości. Ponieważ obsługuje to przecenę, może zawierać łącza do dodatkowej dokumentacji lub wyróżniać słowa, które mogą być ważne dla programisty.
- type definiuje mechanizm wejściowy, w jaki sposób użytkownik ustawi wartość parametru. Istnieje wiele typów, w tym
string
,select
,multiSelect
,selectResource
isecret
. Aby dowiedzieć się więcej o każdej z tych opcji, zapoznaj się z dokumentacją . - validationRegex ogranicza wpis programisty do określonej wartości wyrażenia regularnego (w tym przykładzie jest to oparte na prostych wytycznych dotyczących nazw pól , które można znaleźć tutaj ); a jeśli to się nie uda...
- validationErrorMessage ostrzega programistę o wartości błędu.
- domyślna to wartość, jaka byłaby, gdyby programista nie wprowadził żadnego tekstu.
- wymagane oznacza, że programista nie musi wprowadzać żadnego tekstu.
- immutable pozwala programiście zaktualizować to rozszerzenie i zmienić tę wartość. W takim przypadku programista powinien mieć możliwość zmiany nazw pól w miarę zmiany wymagań.
- przykład daje wyobrażenie o tym, jak mogą wyglądać prawidłowe dane wejściowe.
To było wiele do zrozumienia!
- Przed dodaniem parametru specjalnego musisz dodać jeszcze trzy parametry do pliku
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
Zdefiniuj wrażliwe parametry
Teraz musisz zarządzać kluczem API określonym przez użytkownika. Jest to wrażliwy ciąg znaków, który nie powinien być przechowywany w funkcji jako zwykły tekst. Zamiast tego zapisz tę wartość w menedżerze tajnych obiektów w chmurze . To specjalne miejsce w chmurze, w którym przechowywane są zaszyfrowane sekrety i zapobiegają ich przypadkowemu wyciekowi. Wymaga to od programisty płacenia za korzystanie z tej usługi, ale dodaje dodatkową warstwę bezpieczeństwa w stosunku do kluczy API i potencjalnie ogranicza nieuczciwą działalność. Dokumentacja użytkownika ostrzega programistę, że jest to usługa płatna, dzięki czemu nie ma żadnych niespodzianek w rozliczeniach. Ogólnie rzecz biorąc, zastosowanie jest podobne do innych zasobów ciągów wymienionych powyżej. Jedyną różnicą jest typ, który nazywa się secret
.
- W pliku
extension.yaml
dodaj następujący kod:
rozszerzenie.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
Zaktualizuj atrybuty resource
, aby używać parametrów
Jak wspomniano wcześniej, zasób (nie funkcja) definiuje sposób obserwowania zasobu, dlatego zasób locationUpdate
musi zostać zaktualizowany, aby móc korzystać z nowego parametru.
- W pliku
extension.yaml
dodaj następujący kod:
rozszerzenie.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}
Sprawdź plik extension.yaml
- Przejrzyj plik
extension.yaml
. Powinno to wyglądać mniej więcej tak:
rozszerzenie.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.
Parametry dostępu w kodzie
Teraz, gdy wszystkie parametry są skonfigurowane w pliku extension.yaml
, dodaj je do pliku index.ts
.
- W pliku
index.ts
zamień wartości domyślne naprocess.env.PARAMETER_NAME
, który pobiera odpowiednie wartości parametrów i umieszcza je w kodzie funkcji wdrożonym w projekcie Firebase dewelopera.
indeks.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!;
Zwykle chcesz sprawdzić wartość null wartości zmiennych środowiskowych, ale w tym przypadku masz pewność, że wartości parametrów zostaną poprawnie skopiowane. Kod jest teraz skonfigurowany do pracy z parametrami rozszerzenia.
7. Utwórz dokumentację użytkownika
Przed przetestowaniem kodu na emulatorach lub na rynku rozszerzeń Firebase rozszerzenie należy udokumentować, aby programiści wiedzieli, co otrzymają, korzystając z rozszerzenia.
- Zacznij od utworzenia pliku
PREINSTALL.md
, który jest używany do opisu funkcjonalności, wszelkich wymagań wstępnych instalacji i potencjalnych konsekwencji rozliczeniowych.
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)
- Aby zaoszczędzić czas na pisaniu pliku
README.md
dla tego projektu, użyj wygodnej metody:
firebase ext:info . --markdown > README.md
Łączy to zawartość pliku PREINSTALL.md
i dodatkowe szczegóły dotyczące rozszerzenia z pliku extension.yaml
.
Na koniec poinformuj twórcę rozszerzenia o dodatkowych szczegółach dotyczących właśnie zainstalowanego rozszerzenia. Programista może otrzymać dodatkowe instrukcje i informacje po zakończeniu instalacji, a także może otrzymać szczegółowe zadania poinstalacyjne, takie jak konfiguracja kodu klienta tutaj.
- Utwórz plik
POSTINSTALL.md
, a następnie dołącz następujące informacje po instalacji:
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);
});
Monitorowanie
Najlepszą praktyką jest monitorowanie aktywności zainstalowanego rozszerzenia, w tym sprawdzanie jego stanu, użycia i dzienników.
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
Spowoduje to ponowną kompilację funkcji, dzięki czemu najnowszy kod źródłowy będzie gotowy do wdrożenia wraz z rozszerzeniem po wdrożeniu w emulatorze lub bezpośrednio w Firebase.
Następnie utwórz nowy katalog, z którego chcesz przetestować rozszerzenie. Ponieważ rozszerzenie zostało opracowane na podstawie istniejących funkcji, nie przeprowadzaj testu z folderu, w którym rozszerzenie zostało skonfigurowane, ponieważ powoduje to również próbę wdrożenia wraz z nim funkcji i reguł Firebase.
Zainstaluj i przetestuj za pomocą emulatorów Firebase
- Utwórz nowy katalog w systemie hosta i połącz ten katalog z projektem Firebase za pomocą
firebase init
.
mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Z tego katalogu uruchom
firebase ext:install
, aby zainstalować rozszerzenie. Zamień/path/to/extension
na bezwzględną ścieżkę do katalogu zawierającego plikextension.yaml
. Spowoduje to rozpoczęcie procesu instalacji rozszerzenia i utworzenie pliku.env
zawierającego konfiguracje przed wypchnięciem konfiguracji do Firebase lub emulatorów.
firebase ext:install /path/to/extension
- Ponieważ wdrażasz projekt lokalnie, określ, że chcesz używać pliku lokalnego, a nie Menedżera Google Cloud Secret.
- Uruchom lokalny pakiet emulatorów:
firebase emulators:start
Zainstaluj i przetestuj z prawdziwym projektem Firebase
Możesz zainstalować rozszerzenie w rzeczywistym projekcie Firebase. Do testów zaleca się użycie projektu testowego. Użyj tego przepływu pracy testowej, jeśli chcesz przetestować kompleksowy przepływ rozszerzenia lub jeśli wyzwalacz Twojego rozszerzenia nie jest jeszcze obsługiwany przez zestaw emulatorów Firebase (zobacz opcję Emulator rozszerzeń ). Emulatory obsługują obecnie funkcje wyzwalane żądaniami HTTP i funkcje wyzwalane zdarzeniami w tle dla Cloud Firestore, Realtime Database i Pub/Sub.
- Utwórz nowy katalog w systemie hosta i połącz ten katalog z projektem Firebase za pomocą
firebase init
.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Następnie z tego katalogu uruchom
firebase ext:install
, aby zainstalować rozszerzenie. Zamień/path/to/extension
na bezwzględną ścieżkę do katalogu zawierającego plikextension.yaml
. Spowoduje to rozpoczęcie procesu instalacji rozszerzenia i utworzenie pliku.env
zawierającego konfiguracje przed wypchnięciem konfiguracji do Firebase lub emulatorów.
firebase ext:install /path/to/extension
- Ponieważ chcesz wdrożyć bezpośrednio w Firebase i chcesz korzystać z Google Cloud Secret Manager, przed zainstalowaniem rozszerzenia musisz aktywować API Secret Manager .
- Wdróż w swoim projekcie Firebase.
firebase deploy
Przetestuj rozszerzenie
- Po uruchomieniu
firebase deploy
lubfirebase emulators:start
przejdź do karty Firestore w konsoli Firebase lub w widoku internetowym emulatorów, odpowiednio. - Dodaj dokument do kolekcji określonej przez pole
x
i poley
. W tym przypadku zaktualizowane dokumenty znajdują się pod adresemu/{uid}
z polemx
oxv
i polemy
o wartościyv
.
- Jeśli instalacja rozszerzenia przebiegła pomyślnie, po zapisaniu obu pól rozszerzenie utworzy w dokumencie nowe pole o nazwie
hash
.
8. Gratulacje!
Pomyślnie przekonwertowałeś swoją pierwszą funkcję chmury na rozszerzenie Firebase!
Dodałeś plik extension.yaml
i skonfigurowałeś go tak, aby programiści mogli wybrać sposób wdrożenia rozszerzenia. Następnie utworzono dokumentację dla użytkownika zawierającą wskazówki dotyczące tego, co twórcy rozszerzenia powinni zrobić przed skonfigurowaniem rozszerzenia i jakie kroki mogą być konieczne do wykonania po pomyślnym zainstalowaniu rozszerzenia.
Znasz już kluczowe kroki wymagane do przekształcenia funkcji Firebase w dystrybuowalne rozszerzenie Firebase.