Ta strona przeprowadzi Cię przez kroki wymagane do zbudowania prostego rozszerzenia Firebase, które możesz zainstalować w swoich projektach lub udostępnić innym. Ten prosty przykład rozszerzenia Firebase będzie przeglądał bazę danych czasu rzeczywistego pod kątem wiadomości i konwertował je na wielkie litery.
1. Skonfiguruj środowisko i zainicjuj projekt
Zanim zaczniesz tworzyć rozszerzenie, musisz skonfigurować środowisko kompilacji z wymaganymi narzędziami.
Zainstaluj Node.js 16 lub nowszy. Jednym ze sposobów zainstalowania Node jest użycie nvm (lub nvm-windows ).
Zainstaluj lub zaktualizuj do najnowszej wersji Firebase CLI . Aby zainstalować lub zaktualizować za pomocą
npm
, uruchom to polecenie:npm install -g firebase-tools
Teraz użyj interfejsu CLI Firebase, aby zainicjować nowy projekt rozszerzenia:
Utwórz katalog dla swojego rozszerzenia i włóż do niego
cd
:mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
Uruchom polecenie
ext:dev:init
interfejsu Firebase CLI:firebase ext:dev:init
Gdy pojawi się monit, wybierz JavaScript jako język funkcji (ale pamiętaj, że możesz także używać TypeScriptu, gdy tworzysz własne rozszerzenie), a gdy zostaniesz poproszony o zainstalowanie zależności, odpowiedz „tak”. (Zaakceptuj wartości domyślne pozostałych opcji.) To polecenie skonfiguruje szkieletową bazę kodu dla nowego rozszerzenia, od której będziesz mógł rozpocząć tworzenie swojego rozszerzenia.
Użyj firebase ext:dev:init
aby zainicjować nowy katalog rozszerzenia.
2. Wypróbuj przykładowe rozszerzenie za pomocą emulatora
Kiedy interfejs CLI Firebase zainicjował nowy katalog rozszerzeń, utworzył prostą przykładową funkcję i katalog integration-tests
, który zawiera pliki niezbędne do uruchomienia rozszerzenia przy użyciu zestawu emulatorów Firebase.
Spróbuj uruchomić przykładowe rozszerzenie w emulatorze:
Przejdź do katalogu
integration-tests
:cd functions/integration-tests
Uruchom emulator z projektem demonstracyjnym:
firebase emulators:start --project=demo-test
Emulator ładuje rozszerzenie do predefiniowanego „fikcyjnego” projektu (
demo-test
). Dotychczasowe rozszerzenie składa się z pojedynczej funkcji uruchamianej przez HTTP,greetTheWorld
, która po uzyskaniu dostępu zwraca komunikat „witaj świecie”.Gdy emulator jest nadal uruchomiony, wypróbuj funkcję
greetTheWorld
rozszerzenia, odwiedzając adres URL wyświetlony podczas jego uruchamiania.Twoja przeglądarka wyświetla komunikat „Hello World, witaj na świecie”.
Kod źródłowy tej funkcji znajduje się w katalogu
functions
rozszerzenia. Otwórz źródło w wybranym edytorze lub IDE:funkcje/indeks.js
const functions = require("firebase-functions"); exports.greetTheWorld = functions.https.onRequest((req, res) => { // Here we reference a user-provided parameter // (its value is provided by the user during installation) const consumerProvidedGreeting = process.env.GREETING; // And here we reference an auto-populated parameter // (its value is provided by Firebase after installation) const instanceId = process.env.EXT_INSTANCE_ID; const greeting = `${consumerProvidedGreeting} World from ${instanceId}`; res.send(greeting); });
Gdy emulator jest uruchomiony, automatycznie przeładuje wszelkie zmiany wprowadzone w kodzie funkcji. Spróbuj wprowadzić małą zmianę w funkcji
greetTheWorld
:funkcje/indeks.js
const greeting = `${consumerProvidedGreeting} everyone, from ${instanceId}`;
Zapisz zmiany. Emulator przeładuje Twój kod i teraz, gdy odwiedzisz adres URL funkcji, zobaczysz zaktualizowane powitanie.
Korzystanie z emulatora rozszerzeń może przyspieszyć programowanie, umożliwiając szybkie testowanie i iterację kodu.
Więcej informacji
Dowiedz się więcej o korzystaniu z emulatora rozszerzeń .
3. Dodaj podstawowe informacje do pliku Extension.yaml
Teraz, gdy masz już skonfigurowane środowisko programistyczne i uruchomiłeś emulator rozszerzeń, możesz zacząć pisać własne rozszerzenie.
Jako skromny pierwszy krok zmodyfikuj wstępnie zdefiniowane metadane rozszerzenia, aby odzwierciedlały rozszerzenie, które chcesz napisać, a nie greet-the-world
. Te metadane są przechowywane w pliku extension.yaml
.
Otwórz
extension.yaml
w swoim edytorze i zamień całą zawartość pliku na następującą:name: rtdb-uppercase-messages version: 0.0.1 specVersion: v1beta # Firebase Extensions specification version; don't change # Friendly display name for your extension (~3-5 words) displayName: Convert messages to upper case # Brief description of the task your extension performs (~1 sentence) description: >- Converts messages in RTDB to upper case author: authorName: Your Name url: https://your-site.example.com license: Apache-2.0 # Required license # Public URL for the source code of your extension sourceUrl: https://github.com/your-name/your-repo
Zwróć uwagę na konwencję nazewnictwa zastosowaną w polu
name
: oficjalne rozszerzenia Firebase mają przedrostek wskazujący podstawowy produkt Firebase, na którym działa rozszerzenie, po którym następuje opis działania rozszerzenia. Powinieneś używać tej samej konwencji we własnych rozszerzeniach.Ponieważ zmieniłeś nazwę swojego rozszerzenia, powinieneś także zaktualizować konfigurację emulatora o nową nazwę:
-
functions/integration-tests/firebase.json
zmieńgreet-the-world
nartdb-uppercase-messages
. - Zmień nazwę
functions/integration-tests/extensions/greet-the-world.env
nafunctions/integration-tests/extensions/rtdb-uppercase-messages.env
.
-
W kodzie rozszerzenia nadal znajdują się pozostałości rozszerzenia greet-the-world
, ale zostaw je na razie. Zaktualizujesz je w kilku następnych sekcjach.
Plik
extension.yaml
zawiera metadane dotyczące Twojego rozszerzenia. Najbardziej podstawowymi z tych metadanych jest nazwa rozszerzenia i opis jego działania.Nazwij swoje rozszerzenia w następującym formacie:
<firebase-product>-<description-of-tasks-performed>
.
Więcej informacji
Odwołanie do extension.yaml
zawiera pełną specyfikację pliku; jednak w tej dokumentacji omówiono konkretne zastosowania tego pliku, ponieważ trzeba z nich korzystać.
4. Napisz funkcję chmury i zadeklaruj ją jako zasób rozszerzenia
Teraz możesz zacząć pisać kod. Na tym etapie napiszesz funkcję chmury, która wykona podstawowe zadanie Twojego rozszerzenia, czyli przeglądanie bazy danych w czasie rzeczywistym pod kątem wiadomości i konwertowanie ich na wielkie litery.
Otwórz źródło funkcji rozszerzenia (w katalogu
functions
rozszerzenia) w wybranym edytorze lub środowisku IDE. Zastąp jego zawartość następującą treścią:funkcje/indeks.js
import { database, logger } from "firebase-functions/v1"; const app = initializeApp(); // Listens for new messages added to /messages/{pushId}/original and creates an // uppercase version of the message to /messages/{pushId}/uppercase // for all databases in 'us-central1' export const makeuppercase = database .ref("/messages/{pushId}/uppercase") .onCreate(async (snapshot, context) => { // Grab the current value of what was written to the Realtime Database. const original = snapshot.val(); // Convert it to upper case. logger.log("Uppercasing", context.params.pushId, original); const uppercase = original.toUpperCase(); // Setting an "uppercase" sibling in the Realtime Database. const upperRef = snapshot.ref.parent.child("upper"); await upperRef.set(uppercase); });
Stara funkcja, którą zastąpiłeś, była funkcją wyzwalaną przez protokół HTTP i działała po uzyskaniu dostępu do punktu końcowego HTTP. Nowa funkcja jest uruchamiana na podstawie zdarzeń w bazie danych w czasie rzeczywistym: wyszukuje nowe elementy na określonej ścieżce i w przypadku ich wykrycia zapisuje wartość z powrotem do bazy danych.
Nawiasem mówiąc, ten nowy plik używa składni modułu ECMAScript (
import
iexport
) zamiast CommonJS (require
). Aby używać modułów ES w węźle, określ"type": "module"
functions/package.json
:{ "name": "rtdb-uppercase-messages", "main": "index.js", "type": "module", … }
Każda funkcja w Twoim rozszerzeniu musi być zadeklarowana w pliku
extension.yaml
. Przykładowe rozszerzenie zadeklarowałogreetTheWorld
jako jedyną funkcję w chmurze rozszerzenia; teraz, gdy zastąpiłeś gomakeuppercase
, musisz także zaktualizować jego deklarację.Otwórz
extension.yaml
i dodaj poleresources
:resources: - name: makeuppercase type: firebaseextensions.v1beta.function properties: eventTrigger: eventType: providers/google.firebase.database/eventTypes/ref.create # DATABASE_INSTANCE (project's default instance) is an auto-populated # parameter value. You can also specify an instance. resource: projects/_/instances/${DATABASE_INSTANCE}/refs/messages/{pushId}/original runtime: "nodejs18"
Ponieważ Twoje rozszerzenie używa teraz bazy danych czasu rzeczywistego jako wyzwalacza, musisz zaktualizować konfigurację emulatora, aby uruchomić emulator RTDB razem z emulatorem Cloud Functions:
Jeśli emulator nadal działa, zatrzymaj go, naciskając Ctrl-C.
Z katalogufunctions
functions/integration-tests
uruchom następującą komendę:firebase init emulators
Gdy zostaniesz o to poproszony, pomiń konfigurowanie projektu domyślnego, a następnie wybierz emulatory funkcji i bazy danych. Zaakceptuj domyślne porty i pozwól narzędziu instalacyjnemu pobrać wymagane pliki.
Uruchom ponownie emulator:
firebase emulators:start --project=demo-test
Wypróbuj zaktualizowane rozszerzenie:
Otwórz interfejs emulatora bazy danych, korzystając z łącza wydrukowanego podczas uruchamiania emulatora.
Edytuj węzeł główny bazy danych:
- Pole:
messages
- Typ:
json
- Wartość:
{"11": {"original": "recipe"}}
Jeśli wszystko jest skonfigurowane poprawnie, po zapisaniu zmian w bazie danych funkcja
makeuppercase
rozszerzenia powinna uruchomić się i dodać rekord podrzędny do wiadomości 11 o treści"upper": "RECIPE"
. Przyjrzyj się dziennikom i zakładkom bazy danych interfejsu użytkownika emulatora, aby potwierdzić oczekiwane wyniki.- Pole:
Spróbuj dodać więcej elementów podrzędnych do węzła
messages
({"original":"any text"}
). Za każdym razem, gdy dodajesz nowy rekord, rozszerzenie powinno dodać pole zawierająceuppercase
zawierające wielką zawartośćoriginal
pola.
Masz teraz kompletne, choć proste rozszerzenie, które działa na instancji RTDB. W kolejnych sekcjach udoskonalisz to rozszerzenie, dodając kilka dodatkowych funkcji. Następnie przygotujesz rozszerzenie do dystrybucji wśród innych, a na koniec dowiesz się, jak opublikować swoje rozszerzenie w Centrum rozszerzeń.
- Funkcje tworzące logikę rozszerzenia muszą być zdefiniowane jako kod Cloud Functions i zadeklarowane jako zasób rozszerzenia w pliku
extension.yaml
. - Możesz napisać funkcje, które będą uruchamiane po uzyskaniu dostępu do punktów końcowych HTTP lub w odpowiedzi na zdarzenia emitowane przez produkty Firebase, produkty Google Cloud i inne rozszerzenia.
Więcej informacji
- Dowiedz się więcej o pisaniu funkcji Cloud Functions dla rozszerzeń , w tym o obsługiwanych wyzwalaczach zdarzeń.
- Odwołanie do
extension.yaml
zawiera pełną specyfikację pliku; jednak w tej dokumentacji omówiono konkretne zastosowania tego pliku, ponieważ trzeba z nich korzystać. - Dokumentacja Cloud Functions dla Firebase zawiera ogólne informacje na temat korzystania z Cloud Functions, a nie specyficzne dla rozszerzeń Firebase.
5. Zadeklaruj interfejsy API i role
Firebase przyznaje każdej instancji zainstalowanego rozszerzenia ograniczony dostęp do projektu i jego danych za pomocą konta usługi dla poszczególnych instancji. Każde konto posiada minimalny zestaw uprawnień potrzebnych do działania. Z tego powodu musisz wyraźnie zadeklarować wszelkie role IAM wymagane przez Twoje rozszerzenie; gdy użytkownicy instalują Twoje rozszerzenie, Firebase tworzy konto usługi z przyznanymi tymi rolami i używa go do uruchamiania rozszerzenia.
Nie musisz deklarować ról, aby wywołać zdarzenia związane z produktem, ale musisz zadeklarować rolę, aby w inny sposób z nią wchodzić w interakcję. Ponieważ funkcja dodana w ostatnim kroku zapisuje dane do bazy danych Realtime Database, musisz dodać następującą deklarację do extension.yaml
:
roles:
- role: firebasedatabase.admin
reason: Allows the extension to write to RTDB.
Podobnie deklarujesz interfejsy API Google, których używa rozszerzenie, w polu apis
. Gdy użytkownicy zainstalują Twoje rozszerzenie, zostaną zapytani, czy chcą automatycznie włączyć te interfejsy API w swoim projekcie. Jest to zazwyczaj konieczne tylko w przypadku interfejsów API Google innych niż Firebase i nie jest potrzebne w tym przewodniku.
- Zadeklaruj dowolną rolę IAM, której potrzebuje Twoje rozszerzenie, w polu
roles
w plikuextensions.yaml
. Po zainstalowaniu rozszerzenia automatycznie otrzymują te role. - Zadeklaruj wszystkie interfejsy API Google, których potrzebuje Twoje rozszerzenie, w polu
apis
plikuextensions.yaml
. Gdy użytkownicy instalują Twoje rozszerzenie, mogą automatycznie włączyć te interfejsy API w swoim projekcie. - Na potrzeby dokumentacji zadeklaruj wszelkie interfejsy API spoza Google, których potrzebuje Twoje rozszerzenie, w polu
externalServices
w plikuextensions.yaml
.
Więcej informacji
- Dowiedz się więcej o konfigurowaniu odpowiedniego dostępu dla rozszerzenia .
- Odwołanie do
extension.yaml
zawiera pełną specyfikację pliku; jednak w tej dokumentacji omówiono konkretne zastosowania tego pliku, ponieważ trzeba z nich korzystać.
6. Zdefiniuj parametry konfigurowane przez użytkownika
Funkcja utworzona w dwóch ostatnich krokach obserwowała określoną lokalizację RTDB pod kątem przychodzących wiadomości. Czasami naprawdę chcesz oglądać konkretną lokalizację, na przykład gdy Twoje rozszerzenie działa w oparciu o strukturę bazy danych, której używasz wyłącznie dla swojego rozszerzenia. Jednak w większości przypadków będziesz chciał, aby te wartości mogły być konfigurowane przez użytkowników, którzy instalują Twoje rozszerzenie w swoich projektach. W ten sposób użytkownicy będą mogli wykorzystać Twoje rozszerzenie do pracy z istniejącą konfiguracją bazy danych.
Ustaw ścieżkę, którą rozszerzenie obserwuje pod kątem nowych wiadomości, aby użytkownik mógł ją konfigurować:
W pliku
extension.yaml
dodaj sekcjęparams
:- param: MESSAGE_PATH label: Message path description: >- What is the path at which the original text of a message can be found? type: string default: /messages/{pushId}/original required: true immutable: false
Definiuje to nowy parametr w postaci ciągu znaków, o ustawienie którego użytkownicy będą proszeni podczas instalowania rozszerzenia.
Będąc nadal w pliku
extension.yaml
, wróć do deklaracjimakeuppercase
i zmień poleresource
na następujące:resource: projects/_/instances/${DATABASE_INSTANCE}/refs/${param:MESSAGE_PATH}
Token
${param:MESSAGE_PATH}
jest odniesieniem do właśnie zdefiniowanego parametru. Po uruchomieniu rozszerzenia ten token zostanie zastąpiony dowolną wartością skonfigurowaną przez użytkownika dla tego parametru, w wyniku czego funkcjamakeuppercase
będzie nasłuchiwać ścieżki określonej przez użytkownika. Możesz użyć tej składni, aby odwołać się do dowolnego parametru zdefiniowanego przez użytkownika w dowolnym miejscuextension.yaml
(orazPOSTINSTALL.md
— więcej o tym później).Dostęp do parametrów zdefiniowanych przez użytkownika można także uzyskać z poziomu kodu funkcji.
W funkcji, którą napisałeś w ostatniej sekcji, zakodowałeś na stałe ścieżkę, aby obserwować zmiany. Zmień definicję wyzwalacza, aby zamiast tego odwoływała się do wartości zdefiniowanej przez użytkownika:
funkcje/indeks.js
export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate
Należy pamiętać, że w rozszerzeniach Firebase ta zmiana ma wyłącznie charakter dokumentacyjny: gdy funkcja chmury jest wdrażana jako część rozszerzenia, korzysta ona z definicji wyzwalacza z pliku
extension.yaml
i ignoruje wartość określoną w definicji funkcji. Niemniej jednak dobrym pomysłem jest udokumentowanie w kodzie, skąd pochodzi ta wartość.Zmiana kodu, która nie ma wpływu na środowisko wykonawcze, może wydawać się rozczarowująca, ale ważną lekcją, jaką należy wyciągnąć, jest to, że możesz uzyskać dostęp do dowolnego parametru zdefiniowanego przez użytkownika w kodzie funkcji i użyć go jako zwykłej wartości w logice funkcji. Jako ukłon w stronę tej możliwości dodaj następującą instrukcję dziennika, aby wykazać, że rzeczywiście uzyskujesz dostęp do wartości zdefiniowanej przez użytkownika:
funkcje/indeks.js
export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate( async (snapshot, context) => { logger.log("Found new message at ", snapshot.ref); // Grab the current value of what was written to the Realtime Database. ...
Zwykle podczas instalowania rozszerzenia użytkownicy są proszeni o podanie wartości parametrów. Kiedy jednak używasz emulatora do testowania i programowania, pomijasz proces instalacji, więc zamiast tego podajesz wartości parametrów zdefiniowanych przez użytkownika za pomocą pliku
env
.Otwórz
functions/integration-tests/extensions/rtdb-uppercase-messages.env
i zamień definicjęGREETING
na następującą:MESSAGE_PATH=/msgs/{pushId}/original
Zauważ, że powyższa ścieżka różni się od ścieżki domyślnej i ścieżki, którą wcześniej zdefiniowałeś; ma to na celu tylko udowodnienie sobie, gdy wypróbujesz zaktualizowane rozszerzenie, że Twoja definicja zaczyna obowiązywać.
Teraz uruchom ponownie emulator i jeszcze raz odwiedź interfejs emulatora bazy danych.
Edytuj węzeł główny bazy danych, korzystając ze ścieżki zdefiniowanej powyżej:
- Pole:
msgs
- Typ:
json
- Wartość:
{"11": {"original": "recipe"}}
Po zapisaniu zmian w bazie danych funkcja
makeuppercase
rozszerzenia powinna zostać uruchomiona tak jak wcześniej, ale teraz powinna również wydrukować parametr zdefiniowany przez użytkownika w dzienniku konsoli.- Pole:
- Możesz dać użytkownikom możliwość dostosowania rozszerzenia do swoich potrzeb poprzez zadeklarowanie parametrów zdefiniowanych przez użytkownika w pliku
extension.yaml
. Użytkownicy są proszeni o zdefiniowanie tych wartości podczas instalowania rozszerzenia. - Do wartości parametrów zdefiniowanych przez użytkownika można odwoływać się w plikach
extension.yaml
i w plikuPOSTINSTALL.md
, korzystając z następującej składni:${param:PARAMETER_NAME}
- Dostęp do wartości parametrów zdefiniowanych przez użytkownika możesz uzyskać w kodzie Cloud Functions jako zmienne środowiskowe:
process.env.PARAMETER_NAME
- Podczas testowania przy użyciu emulatora zdefiniuj parametry użytkownika w pliku
<extension-name>.env
.
Więcej informacji
Dowiedz się więcej o konfigurowaniu i używaniu parametrów w rozszerzeniu .
7. Zapewnij zaczepy zdarzeń dla logiki zdefiniowanej przez użytkownika
Jako autor rozszerzenia widziałeś już, jak produkt Firebase może uruchomić logikę dostarczoną przez rozszerzenie: utworzenie nowych rekordów w bazie danych Realtime uruchamia funkcję makeuppercase
. Twoje rozszerzenie może mieć analogiczną relację z użytkownikami, którzy je instalują: Twoje rozszerzenie może uruchamiać logikę zdefiniowaną przez użytkownika .
Rozszerzenie może udostępniać haki synchroniczne , asynchroniczne lub oba. Synchroniczne zaczepy umożliwiają użytkownikom wykonywanie zadań blokujących wykonanie jednej z funkcji rozszerzenia. Może to być przydatne, na przykład, aby dać użytkownikom możliwość przeprowadzenia niestandardowego przetwarzania wstępnego, zanim rozszerzenie zacznie działać.
W tym przewodniku dodasz do rozszerzenia asynchroniczny element przechwytujący, który umożliwi użytkownikom zdefiniowanie własnych kroków przetwarzania, które będą uruchamiane po zapisaniu przez rozszerzenie komunikatu zawierającego wielkie litery w bazie danych czasu rzeczywistego. Asynchroniczne zaczepy wykorzystują Eventarc do wyzwalania funkcji zdefiniowanych przez użytkownika. Rozszerzenia deklarują typy emitowanych przez siebie zdarzeń, a gdy użytkownicy instalują rozszerzenie, wybierają typy zdarzeń, które ich interesują. Jeśli wybiorą co najmniej jedno zdarzenie, Firebase udostępni kanał Eventarc dla rozszerzenia w ramach procesu instalacji . Użytkownicy mogą następnie wdrożyć własne funkcje w chmurze, które nasłuchują na tym kanale i uruchamiają się, gdy rozszerzenie opublikuje nowe zdarzenia.
Wykonaj poniższe kroki, aby dodać asynchroniczny hak:
W pliku
extension.yaml
dodaj następującą sekcję, która deklaruje jeden typ zdarzenia emitowanego przez rozszerzenie:events: - type: test-publisher.rtdb-uppercase-messages.v1.complete description: >- Occurs when message uppercasing completes. The event subject will contain the RTDB URL of the uppercase message.
Typy zdarzeń muszą być uniwersalnie unikalne; aby zapewnić niepowtarzalność, zawsze nazywaj swoje wydarzenia w następującym formacie:
<publisher-id>.<extension-id>.<version>.<description>
. (Nie masz jeszcze identyfikatora wydawcy, więc na razie użyjtest-publisher
.)Na koniec funkcji
makeuppercase
dodaj kod, który opublikuje zdarzenie zadeklarowanego typu:funkcje/indeks.js
// Import the Eventarc library: import { initializeApp } from "firebase-admin/app"; import { getEventarc } from "firebase-admin/eventarc"; const app = initializeApp(); // In makeuppercase, after upperRef.set(uppercase), add: // Set eventChannel to a newly-initialized channel, or `undefined` if events // aren't enabled. const eventChannel = process.env.EVENTARC_CHANNEL && getEventarc().channel(process.env.EVENTARC_CHANNEL, { allowedEventTypes: process.env.EXT_SELECTED_EVENTS, }); // If events are enabled, publish a `complete` event to the configured // channel. eventChannel && eventChannel.publish({ type: "test-publisher.rtdb-uppercase-messages.v1.complete", subject: upperRef.toString(), data: { "original": original, "uppercase": uppercase, }, });
W tym przykładowym kodzie wykorzystano fakt, że zmienna środowiskowa
EVENTARC_CHANNEL
jest zdefiniowana tylko wtedy, gdy użytkownik włączył co najmniej jeden typ zdarzenia. jeśliEVENTARC_CHANNEL
nie jest zdefiniowany, kod nie próbuje publikować żadnych zdarzeń.Możesz dołączyć dodatkowe informacje do wydarzenia Eventarc. W powyższym przykładzie zdarzenie ma pole
subject
zawierające odniesienie do nowo utworzonej wartości oraz ładunekdata
zawierający komunikat oryginalny i pisany wielkimi literami. Zdefiniowane przez użytkownika funkcje wyzwalające zdarzenie mogą wykorzystywać te informacje.Zwykle zmienne środowiskowe
EVENTARC_CHANNEL
iEXT_SELECTED_EVENTS
są definiowane na podstawie opcji wybranych przez użytkownika podczas instalacji. Aby przetestować emulator, zdefiniuj ręcznie te zmienne w plikurtdb-uppercase-messages.env
:EVENTARC_CHANNEL=locations/us-central1/channels/firebase EXT_SELECTED_EVENTS=test-publisher.rtdb-uppercase-messages.v1.complete
W tym momencie ukończyłeś kroki niezbędne do dodania asynchronicznego haka zdarzenia do swojego rozszerzenia.
Aby wypróbować tę nową, właśnie zaimplementowaną funkcję, w kilku kolejnych krokach wciel się w rolę użytkownika instalującego rozszerzenie:
Z katalogufunctions
functions/integration-tests
zainicjuj nowy projekt Firebase:firebase init functions
Po wyświetleniu monitu odmów skonfigurowania projektu domyślnego, wybierz JavaScript jako język Cloud Functions i zainstaluj wymagane zależności. Ten projekt reprezentuje projekt użytkownika , w którym zainstalowane jest Twoje rozszerzenie.
Edytuj
integration-tests/functions/index.js
i wklej następujący kod:import { logger } from "firebase-functions/v1"; import { onCustomEventPublished } from "firebase-functions/v2/eventarc"; import { initializeApp } from "firebase-admin/app"; import { getDatabase } from "firebase-admin/database"; const app = initializeApp(); export const extraemphasis = onCustomEventPublished( "test-publisher.rtdb-uppercase-messages.v1.complete", async (event) => { logger.info("Received makeuppercase completed event", event); const refUrl = event.subject; const ref = getDatabase().refFromURL(refUrl); const upper = (await ref.get()).val(); return ref.set(`${upper}!!!`); } );
To jest przykład funkcji przetwarzania końcowego, którą może napisać użytkownik. W tym przypadku funkcja nasłuchuje, czy rozszerzenie opublikuje
complete
zdarzenie, a po uruchomieniu dodaje trzy wykrzykniki do wiadomości pisanej wielkimi literami.Uruchom ponownie emulator. Emulator załaduje funkcje rozszerzenia, a także funkcję przetwarzania końcowego zdefiniowaną przez „użytkownika”.
Odwiedź interfejs emulatora bazy danych i edytuj węzeł główny bazy danych, korzystając ze ścieżki zdefiniowanej powyżej:
- Pole:
msgs
- Typ:
json
- Wartość:
{"11": {"original": "recipe"}}
Kiedy zapiszesz zmiany w bazie danych, funkcja
makeuppercase
i funkcjaextraemphasis
użytkownika powinny wywołać się po kolei, w wyniku czego wupper
polu zostanie wyświetlona wartośćRECIPE!!!
.- Pole:
- Twoje rozszerzenia mogą zawierać elementy umożliwiające użytkownikom wstawienie własnej logiki do podstawowych operacji rozszerzenia.
- Haki użytkownika mogą być synchroniczne, co blokuje wykonanie rozszerzenia do czasu jego zakończenia. Rozszerzenia często używają synchronicznych haków do wykonywania zdefiniowanych przez użytkownika zadań przetwarzania wstępnego.
- Haki użytkownika mogą być również asynchroniczne, jak w powyższym przykładzie. Asynchronicznych haków można używać do uruchamiania logiki zdefiniowanej przez użytkownika, która nie jest krytyczna dla prawidłowego działania rozszerzenia.
Więcej informacji
Dowiedz się więcej o dodawaniu haków do logiki zdefiniowanej przez użytkownika , w tym zarówno asynchronicznych, jak i synchronicznych.
8. Dodaj procedury obsługi zdarzeń cyklu życia
Rozszerzenie, które do tej pory napisałeś, przetwarza wiadomości w momencie ich tworzenia. Ale co, jeśli Twoi użytkownicy mają już bazę danych wiadomości, gdy instalują rozszerzenie? Rozszerzenia Firebase mają funkcję zwaną hakami zdarzeń cyklu życia , których możesz użyć do wyzwalania działań po zainstalowaniu, aktualizacji lub ponownej konfiguracji rozszerzenia. W tej sekcji użyjesz haków zdarzeń cyklu życia, aby wypełnić istniejącą bazę danych komunikatów projektu komunikatami pisanymi wielkimi literami, gdy użytkownik zainstaluje Twoje rozszerzenie.
Rozszerzenia Firebase korzystają z zadań w chmurze do uruchamiania programów obsługi zdarzeń cyklu życia. Definiujesz procedury obsługi zdarzeń za pomocą Cloud Functions; za każdym razem, gdy instancja Twojego rozszerzenia osiągnie jedno z obsługiwanych zdarzeń cyklu życia, jeśli zdefiniowałeś procedurę obsługi, zostanie ona dodana do kolejki Cloud Tasks. Cloud Tasks następnie asynchronicznie wykona procedurę obsługi. Gdy działa procedura obsługi zdarzeń cyklu życia, konsola Firebase zgłosi użytkownikowi, że w instancji rozszerzenia trwa zadanie przetwarzania. Do funkcji obsługi należy raportowanie użytkownikowi bieżącego stanu i zakończenia zadania.
Aby dodać procedurę obsługi zdarzeń cyklu życia, która uzupełnia istniejące komunikaty, wykonaj następujące czynności:
Zdefiniuj nową funkcję Cloud, która będzie wyzwalana przez zdarzenia w kolejce zadań:
funkcje/indeks.js
import { tasks } from "firebase-functions/v1"; import { getDatabase } from "firebase-admin/database"; import { getExtensions } from "firebase-admin/extensions"; import { getFunctions } from "firebase-admin/functions"; export const backfilldata = tasks.taskQueue().onDispatch(async () => { const batch = await getDatabase() .ref(process.env.MESSAGE_PATH) .parent.parent.orderByChild("upper") .limitToFirst(20) .get(); const promises = []; for (const key in batch.val()) { const msg = batch.child(key); if (msg.hasChild("original") && !msg.hasChild("upper")) { const upper = msg.child("original").val().toUpperCase(); promises.push(msg.child("upper").ref.set(upper)); } } await Promise.all(promises); if (promises.length > 0) { const queue = getFunctions().taskQueue( "backfilldata", process.env.EXT_INSTANCE_ID ); return queue.enqueue({}); } else { return getExtensions() .runtime() .setProcessingState("PROCESSING_COMPLETE", "Backfill complete."); } });
Zwróć uwagę, że funkcja przetwarza tylko kilka rekordów, zanim ponownie doda się do kolejki zadań. Jest to powszechnie stosowana strategia radzenia sobie z zadaniami przetwarzania, których nie można ukończyć w oknie limitu czasu Funkcji Cloud. Ponieważ nie możesz przewidzieć, ile wiadomości użytkownik może już mieć w swojej bazie danych po zainstalowaniu Twojego rozszerzenia, ta strategia jest dobrym rozwiązaniem.
W pliku
extension.yaml
zadeklaruj funkcję wypełniania jako zasób rozszerzenia posiadający właściwośćtaskQueueTrigger
:resources: - name: makeuppercase ... - name: backfilldata type: firebaseextensions.v1beta.function description: >- Backfill existing messages with uppercase versions properties: runtime: "nodejs18" taskQueueTrigger: {}
Następnie zadeklaruj funkcję jako procedurę obsługi zdarzenia cyklu życia
onInstall
:lifecycleEvents: onInstall: function: backfilldata processingMessage: Uppercasing existing messages
Chociaż uzupełnianie istniejących wiadomości jest fajne, rozszerzenie może nadal działać bez niego. W takich sytuacjach należy uczynić uruchamianie procedur obsługi zdarzeń cyklu życia opcjonalnym.
Aby to zrobić, dodaj nowy parametr do
extension.yaml
:- param: DO_BACKFILL label: Backfill existing messages description: >- Generate uppercase versions of existing messages? type: select required: true options: - label: Yes value: true - label: No value: false
Następnie na początku funkcji wypełniania sprawdź wartość parametru
DO_BACKFILL
i wyjdź wcześniej, jeśli nie jest ustawiony:funkcje/indeks.js
if (!process.env.DO_BACKFILL) { return getExtensions() .runtime() .setProcessingState("PROCESSING_COMPLETE", "Backfill skipped."); }
Dzięki powyższym zmianom rozszerzenie po zainstalowaniu będzie teraz konwertować istniejące wiadomości na wielkie litery.
Do tego momentu używałeś emulatora rozszerzenia do rozwijania rozszerzenia i testowania bieżących zmian. Jednak emulator rozszerzenia pomija proces instalacji, więc aby przetestować procedurę obsługi zdarzeń onInstall
, musisz zainstalować rozszerzenie w prawdziwym projekcie. To jednak dobrze, ponieważ dzięki dodaniu tej funkcji automatycznego uzupełniania rozszerzenie samouczka jest teraz kompletne i zawiera cały kod!
Zdarzenia cyklu życia są wyzwalane, gdy użytkownicy wykonują określone zadania związane z zarządzaniem rozszerzeniami:
- Instalowanie wystąpienia rozszerzenia
- Aktualizacja instancji rozszerzenia do nowej wersji
- Ponowna konfiguracja instancji rozszerzenia
Możesz zdefiniować funkcje, które będą uruchamiane w przypadku zdarzeń cyklu życia Twojego rozszerzenia.
Użyj interfejsu API środowiska wykonawczego rozszerzenia pakietu Admin SDK, aby zgłosić użytkownikowi stan procedury obsługi zdarzeń cyklu życia. Użytkownicy zobaczą bieżący stan przetwarzania rozszerzenia w konsoli Firebase.
Funkcje działające na całej bazie danych (takie jak operacje uzupełniania) często nie mogą zostać ukończone przed upływem limitu czasu dla Funkcji Cloud. Można uniknąć tego problemu, dzieląc zadanie na kilka wywołań funkcji.
Jeśli rozszerzenie zawiera procedury obsługi zdarzeń cyklu życia, które nie są krytyczne dla działania rozszerzenia, należy umożliwić użytkownikowi konfigurowanie wykonywania procedury obsługi.
Więcej informacji
Dowiedz się więcej o obsłudze zdarzeń cyklu życia rozszerzenia .
9. Wdróż w prawdziwym projekcie Firebase
Chociaż emulator rozszerzeń jest doskonałym narzędziem do szybkiej iteracji rozszerzenia podczas programowania, w pewnym momencie będziesz chciał wypróbować go w prawdziwym projekcie.
Aby to zrobić, skonfiguruj najpierw nowy projekt z włączonymi niektórymi usługami:
- W konsoli Firebase dodaj nowy projekt.
- Uaktualnij swój projekt do planu Blaze z płatnością zgodnie z rzeczywistym użyciem. Cloud Functions dla Firebase wymaga, aby Twój projekt miał konto rozliczeniowe, dlatego też potrzebujesz konta rozliczeniowego, aby zainstalować rozszerzenie.
- W swoim nowym projekcie włącz bazę danych czasu rzeczywistego .
- Ponieważ chcesz przetestować zdolność rozszerzenia do uzupełniania istniejących danych podczas instalacji, zaimportuj kilka przykładowych danych do instancji bazy danych czasu rzeczywistego:
- Pobierz niektóre dane początkowe RTDB .
- Na stronie Baza danych czasu rzeczywistego w konsoli Firebase kliknij (więcej) > Importuj JSON i wybierz właśnie pobrany plik.
Aby umożliwić funkcji uzupełniania korzystanie z metody
orderByChild
, skonfiguruj bazę danych tak, aby indeksowała wiadomości na podstawie wartościupper
:{ "rules": { ".read": false, ".write": false, "messages": { ".indexOn": "upper" } } }
Teraz zainstaluj rozszerzenie z lokalnego źródła w nowym projekcie:
Utwórz nowy katalog dla swojego projektu Firebase:
mkdir ~/extensions-live-test && cd ~/extensions-live-test
Zainicjuj projekt Firebase w katalogu roboczym:
firebase init database
Po wyświetleniu monitu wybierz właśnie utworzony projekt.
Zainstaluj rozszerzenie w lokalnym projekcie Firebase:
firebase ext:install /path/to/rtdb-uppercase-messages
Tutaj możesz zobaczyć, jak wygląda doświadczenie użytkownika podczas instalowania rozszerzenia za pomocą narzędzia Firebase CLI. Pamiętaj, aby wybrać „tak”, gdy narzędzie konfiguracyjne zapyta, czy chcesz uzupełnić istniejącą bazę danych.
Po wybraniu opcji konfiguracji interfejs CLI Firebase zapisze Twoją konfigurację w katalogu
extensions
i zarejestruje lokalizację źródła rozszerzenia w plikufirebase.json
. Łącznie te dwa rekordy nazywane są manifestem rozszerzeń . Użytkownicy mogą używać manifestu do zapisywania konfiguracji rozszerzeń i wdrażania jej w różnych projektach.Wdróż konfigurację rozszerzenia w aktywnym projekcie:
firebase deploy --only extensions
Jeśli wszystko pójdzie dobrze, interfejs Firebase CLI powinien przesłać rozszerzenie do projektu i zainstalować je. Po zakończeniu instalacji zostanie uruchomione zadanie uzupełniania i za kilka minut Twoja baza danych zostanie zaktualizowana o wiadomości pisane wielkimi literami. Dodaj kilka nowych węzłów do bazy danych wiadomości i upewnij się, że rozszerzenie działa również w przypadku nowych wiadomości.
- Użytkownicy mogą utworzyć manifest rozszerzenia za pomocą polecenia
firebase ext:install
. Możesz także użyć tego polecenia, aby zainstalować rozszerzenie ze źródła lokalnego. - Wdróż konfigurację rozszerzenia z manifestu do działającego projektu za pomocą
firebase deploy
. - Chociaż nie zostało to tutaj pokazane, użytkownicy mogą również instalować rozszerzenia w swoich projektach z poziomu Extensions Hub.
Więcej informacji
Zobacz dokumentację użytkownika dotyczącą zarządzania konfiguracjami projektu za pomocą manifestu rozszerzeń .
10. Napisz dokumentację
Zanim udostępnisz rozszerzenie użytkownikom, upewnij się, że udostępniasz wystarczającą dokumentację, aby mogli odnieść sukces.
Po zainicjowaniu projektu rozszerzenia interfejs CLI Firebase utworzył wersje pośrednie minimalnej wymaganej dokumentacji. Zaktualizuj te pliki, aby dokładnie odzwierciedlały utworzone rozszerzenie.
rozszerzenie.yaml
Aktualizowałeś już ten plik w miarę tworzenia tego rozszerzenia, więc nie musisz teraz wprowadzać żadnych dalszych aktualizacji.
Nie należy jednak zapominać o znaczeniu dokumentacji zawartej w tym pliku. Oprócz kluczowych informacji identyfikujących rozszerzenie — nazwy, opisu, autora i oficjalnej lokalizacji repozytorium — plik extension.yaml
zawiera dostępną dla użytkownika dokumentację dotyczącą każdego zasobu i konfigurowalnego przez użytkownika parametru. Informacje te są wyświetlane użytkownikom w konsoli Firebase, Centrum rozszerzeń i interfejsie wiersza poleceń Firebase.
PREINSTALL.md
W tym pliku podaj informacje, których potrzebuje użytkownik przed zainstalowaniem rozszerzenia: krótko opisz, co robi rozszerzenie, wyjaśnij wszelkie wymagania wstępne i przekaż użytkownikowi informacje na temat konsekwencji rozliczeniowych instalacji rozszerzenia. Jeśli masz witrynę internetową zawierającą dodatkowe informacje, jest to również dobre miejsce na umieszczenie linku do niej.
Tekst tego pliku jest wyświetlany użytkownikowi w Extensions Hub i po wydaniu polecenia firebase ext:info
.
Oto przykład pliku PREINSTALL:
Use this extension to automatically convert strings to upper case when added to
a specified Realtime Database path.
This extension expects a database layout like the following example:
"messages": {
MESSAGE_ID: {
"original": MESSAGE_TEXT
},
MESSAGE_ID: {
"original": MESSAGE_TEXT
},
}
When you create new string records, this extension creates a new sibling record
with upper-cased text:
MESSAGE_ID: {
"original": MESSAGE_TEXT,
"upper": UPPERCASE_MESSAGE_TEXT,
}
#### Additional setup
Before installing this extension, make sure that you've
[set up Realtime Database](https://firebase.google.com/docs/database/quickstart)
in your Firebase project.
#### 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:
- Realtime Database
- Cloud Functions (Node.js 10+ runtime)
[See FAQs](https://firebase.google.com/support/faq#extensions-pricing)
- If you enable events,
[Eventarc fees apply](https://cloud.google.com/eventarc/pricing).
POSTINSTALL.md
Ten plik zawiera informacje przydatne dla użytkowników po pomyślnym zainstalowaniu rozszerzenia: na przykład dalsze kroki konfiguracji, przykład działania rozszerzenia i tak dalej.
Zawartość POSTINSTALL.md jest wyświetlana w konsoli Firebase po skonfigurowaniu i zainstalowaniu rozszerzenia. W tym pliku możesz odwoływać się do parametrów użytkownika, które zostaną zastąpione skonfigurowanymi wartościami.
Oto przykładowy plik poinstalacyjny rozszerzenia samouczka:
### See it in action
You can test out this extension right away!
1. Go to your
[Realtime Database dashboard](https://console.firebase.google.com/project/${param:PROJECT_ID}/database/${param:PROJECT_ID}/data) in the Firebase console.
1. Add a message string to a path that matches the pattern `${param:MESSAGE_PATH}`.
1. In a few seconds, you'll see a sibling node named `upper` that contains the
message in upper case.
### Using the extension
We recommend adding data by pushing -- for example,
`firebase.database().ref().push()` -- because pushing assigns an automatically
generated ID to the node in the database. During retrieval, these nodes are
guaranteed to be ordered by the time they were added. Learn more about reading
and writing data for your platform (iOS, Android, or Web) in the
[Realtime Database documentation](https://firebase.google.com/docs/database/).
### Monitoring
As a best practice, you can
[monitor the activity](https://firebase.google.com/docs/extensions/manage-installed-extensions#monitor)
of your installed extension, including checks on its health, usage, and logs.
CHANGELOG.md
Powinieneś także udokumentować zmiany wprowadzane pomiędzy wydaniami rozszerzenia w pliku CHANGELOG.md
.
Ponieważ przykładowe rozszerzenie nie było nigdy wcześniej publikowane, dziennik zmian zawiera tylko jeden wpis:
## Version 0.0.1
Initial release of the _Convert messages to upper case_ extension.
README.md
Większość rozszerzeń udostępnia także plik Readme, z którego mogą korzystać użytkownicy odwiedzający repozytorium rozszerzenia. możesz zapisać ten plik ręcznie lub wygenerować plik Read Me za pomocą polecenia.
Na potrzeby tego przewodnika pomiń pisanie pliku Readme.
Dodatkowa dokumentacja
Dokumentacja omówiona powyżej to minimalny zestaw dokumentacji, jaki należy dostarczyć użytkownikom. Wiele rozszerzeń wymaga bardziej szczegółowej dokumentacji, aby użytkownicy mogli z nich pomyślnie korzystać. W takim przypadku należy napisać dodatkową dokumentację i umieścić ją w miejscu, do którego można wskazać użytkownikom.
Na potrzeby tego przewodnika pomiń pisanie bardziej rozbudowanej dokumentacji.
- Każde rozszerzenie powinno udostępniać dokumentację użytkownika co najmniej w następujących plikach:
extension.yaml
,PREINSTALL.md
,POSTINSTALL.md
iCHANGELOG.md
. - W razie potrzeby należy także udostępnić użytkownikom bardziej szczegółową dokumentację.
Więcej informacji
Zobacz dokumentację dotyczącą pisania dokumentacji .
11. Opublikuj w Centrum rozszerzeń
Teraz, gdy kod Twojego rozszerzenia jest już kompletny i udokumentowany, możesz udostępnić je światu w Centrum rozszerzeń. Ale ponieważ jest to tylko tutorial, nie rób tego. Idź i zacznij pisać własne rozszerzenie, korzystając z tego, czego nauczyłeś się tutaj i z pozostałej dokumentacji wydawcy rozszerzeń Firebase, a także sprawdzając źródło oficjalnych rozszerzeń napisanych przez Firebase.
Gdy będziesz gotowy opublikować swoją pracę w Extensions Hub, możesz to zrobić w następujący sposób:
- Jeśli publikujesz swoje pierwsze rozszerzenie, zarejestruj się jako wydawca rozszerzenia . Rejestrując się jako wydawca rozszerzeń, tworzysz identyfikator wydawcy, który pozwala użytkownikom szybko zidentyfikować Cię jako autora rozszerzeń.
Hostuj kod źródłowy rozszerzenia w publicznie weryfikowalnej lokalizacji. Jeśli Twój kod jest dostępny z weryfikowalnego źródła, Firebase może opublikować Twoje rozszerzenie bezpośrednio z tej lokalizacji. Dzięki temu będziesz mieć pewność, że opublikujesz aktualnie wydaną wersję rozszerzenia, a także pomożesz użytkownikom sprawdzić kod, który instalują w swoich projektach.
Obecnie oznacza to udostępnienie rozszerzenia w publicznym repozytorium GitHub.
Prześlij swoje rozszerzenie do Extensions Hub za pomocą polecenia
firebase ext:dev:upload
.Przejdź do panelu wydawcy w konsoli Firebase, znajdź właśnie przesłane rozszerzenie i kliknij „Opublikuj w Centrum rozszerzeń”. Wymaga to sprawdzenia przez nasz zespół recenzentów, co może zająć kilka dni. Po zatwierdzeniu rozszerzenie zostanie opublikowane w Centrum rozszerzeń. W przypadku odrzucenia otrzymasz wiadomość wyjaśniającą przyczynę; możesz następnie rozwiązać zgłoszone problemy i przesłać je ponownie do sprawdzenia.
- Aby udostępniać rozszerzenia w Extensions Hub, musisz być zarejestrowany jako wydawca.
- Wymagana jest publikacja z weryfikowalnego źródła, która daje użytkownikom pewność, że instalowany przez nich kod jest tym samym kodem, który mogą sprawdzić w GitHub.
- Użyj polecenia
firebase ext:dev:upload
aby przesłać rozszerzenie do Centrum rozszerzeń. - Prześlij swoje rozszerzenia do sprawdzenia w panelu wydawcy.
Więcej informacji
Dowiedz się więcej o rejestrowaniu się jako wydawca i publikowaniu rozszerzenia .