1. Zanim zaczniesz
Rozszerzenie Firebase wykonuje określone zadanie lub zbiór zadań w odpowiedzi na żądania HTTP albo aktywuje zdarzenia z innych usług Firebase i Google, takich jak Firebase Cloud Messaging, Cloud Firestore czy Pub/Sub.
Co utworzysz
W ramach tego ćwiczenia w Codelabs utworzysz rozszerzenie Firebase do szyfrowania geograficznego. Po wdrożeniu rozszerzenie przekształca współrzędne X i Y na geohasze w odpowiedzi na zdarzenia Firestore lub za pomocą wywołań funkcji. Możesz użyć tej funkcji jako alternatywy dla implementowania biblioteki geofire na wszystkich platformach docelowych do przechowywania danych, co pozwala zaoszczędzić czas.
Czego się nauczysz
- Jak wykorzystać istniejący kod Cloud Functions i przekształcić go w dostępne do dystrybucji rozszerzenie Firebase
- Jak skonfigurować plik
extension.yaml
- Jak przechowywać poufne ciągi znaków (klucze interfejsu API) w rozszerzeniu
- jak umożliwić programistom jego skonfigurowanie zgodnie z własnymi potrzebami.
- Testowanie i wdrażanie rozszerzenia
Czego potrzebujesz
- Interfejs wiersza poleceń Firebase (instalacja i logowanie)
- Konto Google, np. konto Gmail
- Node.js i
npm
- Twoje ulubione środowisko programistyczne
2. Konfiguracja
Pobierz kod
Wszystko, czego potrzebujesz do działania tego rozszerzenia, znajduje się w repozytorium GitHub. Zacznij od pobrania kodu i otwarcia go w 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
W ramach tego ćwiczenia w Codelabs zalecamy korzystanie z emulatorów Firebase. Jeśli chcesz wypróbować programowanie rozszerzeń w prawdziwym projekcie Firebase, przeczytaj artykuł o tworzeniu projektu Firebase. To ćwiczenie w Codelabs wykorzystuje Cloud Functions, więc jeśli zamiast emulatorów używasz prawdziwego projektu Firebase, musisz przejść na abonament Blaze.
Chcesz przejść dalej?
Możesz pobrać ukończoną wersję ćwiczenia z programowania. Jeśli napotkasz jakieś problemy lub chcesz zobaczyć, jak wygląda gotowe rozszerzenie, zajrzyj do gałęzi codelab-end
w repozytorium GitHub lub pobierz gotowy plik ZIP.
3. Sprawdź kod
- Otwórz plik
index.ts
z pliku ZIP. Zwróć uwagę, że zawiera on 2 deklaracje Cloud Functions.
Do czego służą te funkcje?
Te funkcje demonstracyjne są używane do geohasła. Pobierają one parę współrzędnych i przekształcają je w format zoptymalizowany pod kątem zapytań geograficznych w Firestore. Te funkcje symulują użycie wywołań interfejsu API, dzięki czemu możesz dowiedzieć się więcej o obsłudze typów danych wrażliwych w rozszerzeniach. Więcej informacji znajdziesz w dokumentacji dotyczącej uruchamiania zapytań geograficznych dotyczących danych w Firestore.
Stałe funkcji
Stałe są deklarowane wcześnie na początku pliku index.ts
. Do niektórych z tych stałych odwołują się zdefiniowane reguły rozszerzenia.
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);
Aktywator Firestore
Pierwsza funkcja w pliku index.ts
wygląda tak:
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,
}
);
});
Ta funkcja to aktywator Firestore. Gdy w bazie danych wystąpi zdarzenie zapisu, funkcja reaguje na to zdarzenie, wyszukując pola xv
i yv
, a następnie, jeśli istnieją oba te pola, oblicza geoszyfrowanie i zapisuje dane wyjściowe w określonej lokalizacji dokumentu. Dokument wejściowy jest definiowany przez stałą users/{uid}
, co oznacza, że funkcja odczytuje każdy dokument zapisany w kolekcji users/
, a następnie przetwarza geoszyfrowanie tych dokumentów. Następnie haszuje w polu skrótu w tym samym dokumencie.
Funkcje wywoływane
Następna funkcja w pliku index.ts
wygląda tak:
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};
});
Zwróć uwagę na funkcję onCall
. Oznacza ona, że jest to funkcja wywoływana, którą można wywołać z kodu aplikacji klienckiej. Ta funkcja wywoływana przyjmuje parametry x
i y
oraz zwraca geohash. Chociaż ta funkcja nie będzie wywoływana bezpośrednio w tym ćwiczeniach z programowania, została ona uwzględniona tutaj jako przykład do skonfigurowania w rozszerzeniu Firebase.
4. Konfigurowanie pliku extensions.yaml
Wiesz już, jak działa kod Cloud Functions w rozszerzeniu, więc możesz przygotować go do dystrybucji. Każde rozszerzenie Firebase ma plik extension.yaml
, który opisuje działanie rozszerzenia i sposób jego działania.
Plik extension.yaml
wymaga wstępnych metadanych dotyczących rozszerzenia. Każdy z tych kroków pomoże Ci zrozumieć, co oznaczają wszystkie pola i dlaczego ich potrzebujesz.
- Utwórz plik
extension.yaml
w katalogu głównym pobranego wcześniej projektu. Zacznij od dodania tych elementów:
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
Nazwa rozszerzenia stanowi podstawę identyfikatora instancji rozszerzenia (użytkownicy mogą instalować wiele wystąpień rozszerzenia, każde z własnym identyfikatorem). Następnie Firebase generuje nazwy kont usługi rozszerzenia i zasoby związane z rozszerzeniem, korzystając z tego identyfikatora instancji. Numer wersji wskazuje wersję rozszerzenia. Wymagana jest semantyczna obsługa wersji, którą musisz aktualizować za każdym razem, gdy wprowadzasz zmiany w funkcjach rozszerzenia. Wersja specyfikacji rozszerzenia służy do określenia, której specyfikacji rozszerzenia Firebase należy zastosować. W tym przypadku używana jest specyfikacja rozszerzenia v1beta
.
- Dodaj proste w użyciu szczegóły do pliku YAML:
...
displayName: Latitude and longitude to GeoHash converter
description: A converter for changing your Latitude and longitude coordinates to geohashes.
Wyświetlana nazwa w przyjazny sposób odzwierciedla nazwę rozszerzenia, gdy deweloperzy z niego korzystają. Opis zawiera krótki opis funkcji rozszerzenia. Po wdrożeniu rozszerzenia na stronie extensions.dev wygląda ono mniej więcej tak:
- Określ licencję na kod w rozszerzeniu.
...
license: Apache-2.0 # The license you want for the extension
- Wskaż, kto napisał rozszerzenie i czy do jego zainstalowania wymagane są opłaty:
...
author:
authorName: AUTHOR_NAME
url: https://github.com/Firebase
billingRequired: true
W sekcji author
użytkownicy będą wiedzieć, z kim mają się skontaktować w razie problemów z rozszerzeniem lub chcą uzyskać więcej informacji. Parametr billingRequired
jest wymagany, a jego wartość należy ustawić na true
, ponieważ wszystkie rozszerzenia korzystają z Cloud Functions, który wymaga abonamentu Blaze.
Obejmuje to minimalną liczbę pól wymaganych w pliku extension.yaml
do identyfikacji tego rozszerzenia. Więcej informacji na temat innych informacji umożliwiających identyfikację, które można podać w rozszerzeniu, znajdziesz w dokumentacji.
5. Konwertowanie kodu Cloud Functions na zasób rozszerzeń
Zasób rozszerzenia to element, który Firebase tworzy w projekcie podczas instalacji rozszerzenia. Właścicielem tych zasobów jest rozszerzenie, które ma skonfigurowane konto usługi, które na nich działa. W tym projekcie te zasoby to funkcje Cloud Functions, które muszą być zdefiniowane w pliku extension.yaml
, ponieważ rozszerzenie nie będzie automatycznie tworzyć zasobów z kodu w folderze funkcji. Jeśli funkcje w Cloud Functions nie są jawnie zadeklarowane jako zasoby, nie można ich wdrożyć po wdrożeniu rozszerzenia.
Zdefiniowana przez użytkownika lokalizacja wdrożenia
- Zezwól użytkownikowi na określenie lokalizacji, w której chce wdrożyć to rozszerzenie, i zdecyduj, czy lepiej byłoby hostować je bliżej użytkowników, czy bliżej swojej bazy danych. W pliku
extension.yaml
umieść opcję wyboru lokalizacji.
extension.yaml (w języku angielskim)
Teraz możesz zapisać konfigurację zasobu funkcji.
- Utwórz w pliku
extension.yaml
obiekt zasobu dla funkcjilocationUpdate
. Dołącz do plikuextension.yaml
ten kod:
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}
Definiujesz name
jako nazwę funkcji zdefiniowaną w pliku index.ts
projektu. Określasz właściwość type
wdrażanej funkcji. Na razie powinna to być zawsze firebaseextensions.v1beta.function
. Następnie określ properties
tej funkcji. pierwszą zdefiniowaną przez Ciebie właściwość to eventTrigger
powiązana z tą funkcją. Jeśli chcesz zobaczyć, jakie funkcje są obecnie obsługiwane przez rozszerzenie, użyj funkcji eventType
z providers/cloud.firestore/eventTypes/document.write
, którą znajdziesz w dokumentacji Zapisywanie funkcji w Cloud Functions na potrzeby rozszerzenia. resource
określasz jako lokalizację dokumentów. Bieżący cel to odzwierciedlenie zawartości kodu, więc ścieżka dokumentu nasłuchuje źródła users/{uid}
, poprzedzając domyślną lokalizację bazy danych.
- Rozszerzenie wymaga uprawnień do odczytu i zapisu w bazie danych Firestore. Na końcu pliku
extension.yaml
określ role uprawnień, do których rozszerzenie powinno mieć dostęp, aby móc korzystać z bazy 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 uprawnień na potrzeby rozszerzeń. Ponieważ rozszerzenie będzie odczytywać i pisać, rola datastore.user
dobrze sprawdzi się w tym przypadku.
- Trzeba też dodać funkcję wywoływaną przez funkcję. W pliku
extension.yaml
utwórz nowy zasób dla właściwości zasobów. Te właściwości są specyficzne dla funkcji, którą można wywołać:
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
Chociaż poprzedni zasób używał eventTrigger
, tutaj używasz httpsTrigger
, który obejmuje zarówno funkcje wywoływane i HTTPS.
Sprawdzanie kodu
Wymagało to obszernej konfiguracji, aby element extension.yaml
pasował do wszystkich działań wykonanych przez kod w pliku index.ts
. Gotowy plik extension.yaml
powinien teraz wyglądać tak:
extension.yaml (w języku angielskim)
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.
Sprawdzanie stanu
Na tym etapie masz już skonfigurowane początkowe elementy rozszerzenia, które możesz wypróbować za pomocą emulatorów Firebase.
- Wywołaj polecenie
npm run build
w folderze funkcji w projekcie pobranych rozszerzeń. - Utwórz w systemie hosta nowy katalog i połącz go z projektem Firebase za pomocą usługi
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.
- W tym samym katalogu uruchom polecenie
firebase ext:install
. Zastąp/path/to/extension
ścieżką bezwzględną do katalogu zawierającego plikextension.yaml
.
firebase ext:install /path/to/extension
This command does two things:
- Zobaczysz prośbę o określenie konfiguracji instancji rozszerzenia i zostanie utworzony plik
*.env
zawierający informacje o konfiguracji instancji. - Spowoduje to dodanie wystąpienia rozszerzenia do sekcji
extensions
Twojego kontafirebase.json
. Służy do mapowania identyfikatora instancji na wersję rozszerzenia. - Wdrażasz projekt lokalnie, więc możesz wskazać, że zamiast Google Cloud Secret Manager używać pliku lokalnego.
- Uruchom emulatory Firebase z nową konfiguracją:
firebase emulators:start
- Po uruchomieniu funkcji
emulators:start
przejdź do karty Firestore w widoku internetowym emulatorów. - Dodaj do kolekcji
users
dokument z polem liczbowymxv
i polem z numeremyv
.
- Jeśli udało się zainstalować rozszerzenie, utworzy ono w dokumencie nowe pole o nazwie
hash
.
Czyszczenie danych w celu uniknięcia konfliktów
- Po zakończeniu testów odinstaluj rozszerzenie. Jeśli chcesz zaktualizować jego kod, nie musisz w przyszłości kolidować z bieżącym rozszerzeniem.
Rozszerzenia umożliwiają jednoczesne zainstalowanie wielu wersji tego samego rozszerzenia, więc odinstalowanie pozwala uniknąć konfliktów z wcześniej zainstalowanym rozszerzeniem.
firebase ext:uninstall geohash-ext
Obecne rozwiązanie działa, ale jak wspomnieliśmy na początku projektu, dostępny jest zakodowany na stałe klucz interfejsu API do symulowania komunikacji z usługą. Jak można użyć klucza interfejsu API użytkownika zamiast dostarczonego pierwotnie? Przekonaj się.
6. Umożliwianie konfigurowania rozszerzenia przez użytkownika
Na tym etapie ćwiczeń z programowania masz rozszerzenie, które jest skonfigurowane do użytku z zalecaną konfiguracją napisanych przez Ciebie funkcji. Co jednak, jeśli użytkownik chce użyć szerokości i długości geograficznej zamiast y i x w polach wskazujących lokalizację na płaszczyźnie kartezjańskiej? Poza tym co zrobić, aby użytkownik końcowy dostarczał własny klucz interfejsu API, zamiast korzystać z podanego przez niego klucza? Można szybko przekroczyć limit dla tego interfejsu API. W tym przypadku konfigurujesz parametry i korzystasz z nich.
Zdefiniuj podstawowe parametry w pliku extension.yaml
Zacznij od przekonwertowania elementów, dla których deweloperzy mogą mieć niestandardową konfigurację. Pierwszym z nich są parametry XFIELD
i YFIELD
.
- W pliku
extension.yaml
dodaj poniższy kod, który korzysta z parametrów pólXFIELD
iYFIELD
. Te parametry znajdują się w zdefiniowanej wcześniej właściwości YAMLparams
:
extension.yaml (w języku angielskim)
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 nadaje nazwę parametrowi w sposób widoczny dla Ciebie, producenta rozszerzenia. Użyj tej wartości później podczas określania wartości parametrów.
- Parametr label jest zrozumiały dla programisty i informuje go, do czego służy dany parametr.
- Parametr description zawiera szczegółowy opis wartości. Ta funkcja obsługuje Markdown, dlatego może zawierać link do dodatkowej dokumentacji lub wyróżniać słowa, które mogą być ważne dla programisty.
- Parametr type określa mechanizm, na podstawie którego użytkownik może ustawić wartość parametru. Istnieje wiele typów, np.
string
,select
,multiSelect
,selectResource
isecret
. Więcej informacji o każdej z tych opcji znajdziesz w dokumentacji. - Parametr validationRegex ogranicza wpis dewelopera do określonej wartości wyrażenia regularnego (w tym przykładzie jest ona oparta na prostych wytycznych dotyczących nazw pól dostępnych tutaj). a jeśli to nie pomoże...
- validationErrorMessage informuje dewelopera o wartości błędu.
- default (domyślna) to wartość, jaką należałoby ustawić, gdyby deweloper nie dodał żadnego tekstu.
- required oznacza, że programista nie musi wpisywać żadnego tekstu.
- niezmienna umożliwia deweloperowi aktualizowanie tego rozszerzenia i zmianę tej wartości. W takim przypadku deweloper powinien mieć możliwość zmiany nazw pól w miarę zmiany wymagań.
- Przykład pokazuje, jak mogą wyglądać prawidłowe dane wejściowe.
Trzeba było to zrozumieć.
- Musisz dodać do pliku
extension.yaml
jeszcze 3 parametry, zanim dodasz specjalny parametr.
- 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
Definiowanie parametrów poufnych
Teraz musisz zarządzać kluczem interfejsu API określonym przez użytkownika. Jest to ciąg poufny, którego nie należy przechowywać w formie zwykłego tekstu. Zamiast tego zapisz tę wartość w menedżerze obiektów tajnych Cloud. Jest to specjalna lokalizacja w chmurze, w której przechowywane są zaszyfrowane obiekty tajne, aby zapobiegać ich przypadkowemu wyciekom. Wymaga to od dewelopera płacenia za korzystanie z tej usługi, ale stanowi to dodatkową warstwę zabezpieczeń dla kluczy interfejsu API i potencjalnie ogranicza nieuczciwe działania. Dokumentacja użytkownika informuje dewelopera, że jest to usługa płatna, aby uniknąć niespodzianek w płatnościach. Ogólnie użycie jest podobne do innych zasobów z ciągami znaków wspomnianymi powyżej. Jedyną różnicą jest typ o nazwie secret
.
- W pliku
extension.yaml
dodaj ten kod:
extension.yaml (w języku angielskim)
- 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 resource
atrybuty, aby używać parametrów
Jak wspomnieliśmy wcześniej, zasób (nie funkcja) określa sposób obserwacji zasobu, więc zasób locationUpdate
musi zostać zaktualizowany, aby można było użyć nowego parametru.
- W pliku
extension.yaml
dodaj ten kod:
extension.yaml (w języku angielskim)
## 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
- Sprawdź plik
extension.yaml
. Powinna wyglądać mniej więcej tak:
extension.yaml (w języku angielskim)
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
W pliku extension.yaml
są już skonfigurowane wszystkie parametry, więc dodaj je do pliku index.ts
.
- W pliku
index.ts
zastąp wartości domyślne ciągiemprocess.env.PARAMETER_NAME
, który pobiera odpowiednie wartości parametrów i wypełnia je w kodzie funkcji wdrożonego w projekcie Firebase dewelopera.
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!;
Normalnie chcesz sprawdzić wartości null dla wartości zmiennych środowiskowych, ale w tym przypadku masz pewność, że wartości parametrów zostały prawidłowo skopiowane. Kod jest teraz skonfigurowany do działania z parametrami rozszerzenia.
7. Utwórz dokumentację użytkownika
Przed przetestowaniem kodu w emulatorach lub na platformie handlowej rozszerzeń Firebase konieczne jest udokumentowanie tego rozszerzenia, aby deweloperzy wiedzieli, co uzyskują, gdy go używają.
- Zacznij od utworzenia pliku
PREINSTALL.md
. Opisuje on funkcje, wymagania wstępne dotyczące instalacji i potencjalne konsekwencje związane z rozliczeniami.
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 podczas zapisywania właściwości
README.md
w tym projekcie, użyj metody wygodnej:
firebase ext:info . --markdown > README.md
Łączy zawartość pliku PREINSTALL.md
z dodatkowymi informacjami o rozszerzeniu z pliku extension.yaml
.
Na koniec przekaż programiście rozszerzenia o kilka dodatkowych informacji na temat właśnie zainstalowanego rozszerzenia. Po ukończeniu instalacji deweloper może uzyskać dodatkowe instrukcje i informacje, a po instalacji szczegółowe zadania, np. konfigurację kodu klienta.
- Utwórz plik
POSTINSTALL.md
, a po instalacji dołącz następujące informacje:
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
Sprawdzoną metodą jest monitorowanie aktywności zainstalowanego rozszerzenia, w tym kontrola 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 ponowne skompilowanie funkcji w taki sposób, że najnowszy kod źródłowy będzie gotowy do wdrożenia razem z rozszerzeniem, gdy zostanie ono wdrożone w emulatorze lub bezpośrednio w Firebase.
Następnie utwórz nowy katalog, z którego chcesz przetestować rozszerzenie. Rozszerzenie powstało na podstawie istniejących funkcji, dlatego nie testuj go w folderze, w którym je skonfigurowano, ponieważ powoduje to też próbę wdrożenia funkcji i reguł Firebase obok niego.
Instalowanie i testowanie za pomocą emulatorów Firebase
- Utwórz w systemie hosta nowy katalog i połącz go z projektem Firebase za pomocą usługi
firebase init
.
mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- W tym katalogu uruchom
firebase ext:install
, aby zainstalować rozszerzenie. Zastąp ciąg/path/to/extension
ścieżką bezwzględną do katalogu zawierającego Twój plikextension.yaml
. Spowoduje to rozpoczęcie procesu instalacji rozszerzenia i utworzenie pliku.env
zawierającego Twoje konfiguracje, zanim przekażesz konfigurację do Firebase lub do emulatorów.
firebase ext:install /path/to/extension
- Wdrażasz projekt lokalnie, dlatego wskaż, że zamiast usługi Google Cloud Secret Manager używać pliku lokalnego.
- Uruchom lokalny pakiet emulatorów:
firebase emulators:start
Instalowanie i testowanie z użyciem prawdziwego projektu Firebase
Możesz zainstalować swoje rozszerzenie w rzeczywistym projekcie Firebase. Do testowania zalecamy użycie projektu testowego. Skorzystaj z tego procesu testowania, jeśli chcesz przetestować cały proces rozszerzenia lub jeśli wyzwalacz rozszerzenia nie jest jeszcze obsługiwany przez pakiet emulatora Firebase (patrz opcja emulatora rozszerzeń). Emulatory obecnie obsługują funkcje wyzwalane przez żądania HTTP oraz funkcje aktywowane w tle w Cloud Firestore, Bazie danych czasu rzeczywistego i Pub/Sub.
- Utwórz w systemie hosta nowy katalog i połącz go z projektem Firebase za pomocą usługi
firebase init
.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Następnie w tym katalogu uruchom
firebase ext:install
, aby zainstalować rozszerzenie. Zastąp ciąg/path/to/extension
ścieżką bezwzględną do katalogu zawierającego Twój plikextension.yaml
. Spowoduje to rozpoczęcie procesu instalacji rozszerzenia i utworzenie pliku.env
zawierającego Twoje konfiguracje, zanim przekażesz konfigurację do Firebase lub do emulatorów.
firebase ext:install /path/to/extension
- Chcesz przeprowadzić bezpośrednie wdrożenie w Firebase i skorzystać z usługi Google Cloud Secret Manager, dlatego przed zainstalowaniem rozszerzenia musisz aktywować interfejs Secret Manager API.
- Wdróż w projekcie Firebase.
firebase deploy
Testowanie rozszerzenia
- Po uruchomieniu
firebase deploy
lubfirebase emulators:start
otwórz kartę Firestore konsoli Firebase lub widok internetowy emulatorów (w zależności od potrzeb). - Dodaj dokument do kolekcji określonej w polach
x
iy
. W tym przypadku zaktualizowane dokumenty znajdują się w folderzeu/{uid}
, gdzie polex
ma wartośćxv
, ay
ma wartośćyv
.
- Jeśli instalacja rozszerzenia się uda, po zapisaniu tych 2 pól utworzy w dokumencie nowe pole o nazwie
hash
.
8. Gratulacje!
Udało Ci się przekonwertować swoją pierwszą funkcję w Cloud Functions na rozszerzenie Firebase.
Dodałeś i skonfigurowałeś plik extension.yaml
, aby deweloperzy mogli wybrać sposób wdrażania rozszerzenia. Następnie utworzyliśmy dokumentację użytkownika z instrukcjami, co programiści powinni zrobić, zanim je skonfigurują, i co mogą oni zrobić po ich zainstalowaniu.
Znasz już najważniejsze kroki wymagane do przekształcenia funkcji Firebase w możliwe do dystrybucji rozszerzenie Firebase.