Erste Schritte beim Erstellen einer Erweiterung

Auf dieser Seite werden die Schritte zum Erstellen einer einfachen Firebase-Erweiterung beschrieben, die Sie in Ihren Projekten installieren oder für andere freigeben können. Dieses Beispiel für eine Firebase-Erweiterung, die Ihre Realtime Database auf und wandeln sie in Großbuchstaben um.

1. Umgebung einrichten und Projekt initialisieren

Bevor Sie mit der Erstellung einer Erweiterung beginnen können, müssen Sie einen Build einrichten. mit den erforderlichen Tools.

  1. Installieren Sie Node.js 16 oder höher. Eine Möglichkeit, Node zu installieren, ist die nvm (oder nvm-windows).

  2. Installieren Sie die Firebase CLI oder aktualisieren Sie sie auf die neueste Version. Bis Führen Sie den folgenden Befehl aus, um die App mit npm zu installieren oder zu aktualisieren:

    npm install -g firebase-tools

Verwenden Sie jetzt die Firebase CLI, um ein neues Erweiterungsprojekt zu initialisieren:

  1. Erstellen Sie ein Verzeichnis für die Erweiterung und fügen Sie cd hinzu:

    mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
  2. Führen Sie den Befehl ext:dev:init der Firebase CLI aus:

    firebase ext:dev:init

    Wählen Sie bei entsprechender Aufforderung JavaScript als Sprache für die Funktionen aus (Hinweis: Sie können auch TypeScript verwenden, wenn Sie Ihre eigene Erweiterung entwickeln. Antworten Sie mit „Ja“, wenn Sie aufgefordert werden, Abhängigkeiten zu installieren. (Übernehmen Sie die Standardwerte für alle anderen Optionen.) Mit diesem Befehl wird die Basis für eine neue Erweiterung, über die Sie mit der Entwicklung Ihrer Erweiterung beginnen können.

2. Beispielerweiterung mit dem Emulator testen

Als die Firebase CLI das neue Erweiterungsverzeichnis initialisiert hat, wurde ein einfache Beispielfunktion und ein integration-tests-Verzeichnis, das die Dateien, die zum Ausführen einer Erweiterung mit der Firebase-Emulator-Suite erforderlich sind.

Führen Sie die Beispielerweiterung im Emulator aus:

  1. Wechseln Sie in das Verzeichnis integration-tests:

    cd functions/integration-tests
  2. Starten Sie den Emulator mit einem Demoprojekt:

    firebase emulators:start --project=demo-test

    Der Emulator lädt die Erweiterung in eine vordefinierte Dummy-Datei. Projekt (demo-test). Die Erweiterung besteht bisher aus einem einzelnen, durch HTTP ausgelösten greetTheWorld, die "Hello World" zurückgibt Nachricht senden, wenn Zugriff haben.

  3. Wenn der Emulator noch ausgeführt wird, versuche es mit dem greetTheWorld der Erweiterung über die URL, die beim Start ausgegeben wurde.

    In Ihrem Browser wird die Nachricht „Hello World from greet-the-world“ angezeigt.

  4. Der Quellcode für diese Funktion befindet sich im functions der Erweiterung -Verzeichnis. Öffnen Sie die Quelle im Editor oder in der IDE Ihrer Wahl:

    functions/index.js

    const functions = require("firebase-functions/v1");
    
    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);
    });
    
  5. Während der Emulator ausgeführt wird, werden alle Änderungen, die Sie im Functions-Code vornehmen. Nehmen Sie eine kleine Änderung am greetTheWorld-Funktion:

    functions/index.js

    const greeting = `${consumerProvidedGreeting} everyone, from ${instanceId}`;
    

    Speichern Sie die Änderungen. Der Emulator lädt Ihren Code neu. Wenn Sie die Funktions-URL aufrufen, sehen Sie die aktualisierte Begrüßung.

3. Grundlegende Informationen zu „extension.yaml“ hinzufügen

Nachdem Sie eine Entwicklungsumgebung eingerichtet und den Erweiterungsemulator gestartet haben, können Sie mit dem Erstellen Ihrer eigenen Erweiterung beginnen.

Als ersten Schritt kannst du die vordefinierten Metadaten der Erweiterung entsprechend bearbeiten. die Sie anstelle von greet-the-world schreiben möchten. Diese Metadaten sind die in der Datei extension.yaml gespeichert sind.

  1. Öffnen Sie extension.yaml in Ihrem Editor und ersetzen Sie den gesamten Inhalt der Datei durch Folgendes:

    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
    

    Beachten Sie die im Feld name verwendete Namenskonvention: offizielle Firebase Erweiterungen werden mit einem Präfix benannt, das das primäre Firebase-Produkt angibt. auf der die Erweiterung ausgeführt wird, gefolgt von einer Beschreibung macht. Sie sollten dieselbe Konvention in Ihren eigenen Erweiterungen verwenden.

  2. Da Sie den Namen Ihrer Erweiterung geändert haben, sollten Sie auch die Emulator-Konfiguration mit dem neuen Namen:

    1. Ändern Sie in functions/integration-tests/firebase.json den Wert greet-the-world in rtdb-uppercase-messages.
    2. functions/integration-tests/extensions/greet-the-world.env umbenennen in functions/integration-tests/extensions/rtdb-uppercase-messages.env.

Im Erweiterungscode sind noch einige Überreste der greet-the-world-Erweiterung vorhanden. Lassen Sie sie vorerst. Sie aktualisieren diese in den nächsten Abschnitten.

4. Cloud Functions-Funktion schreiben und als Erweiterungsressource deklarieren

Jetzt können Sie anfangen, Code zu schreiben. In diesem Schritt schreiben Sie eine Cloud Funktion, die die Hauptaufgabe Ihrer Erweiterung ausführt: um Ihre Realtime Database auf Nachrichten zu prüfen und sie in Großbuchstaben umzuwandeln.

  1. Öffnen Sie die Quelle für die Funktionen der Erweiterung (in der functions) im Editor oder in der IDE Ihrer Wahl. Ersetzen Sie den Inhalt durch Folgendes:

    functions/index.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);
    });
    

    Die alte Funktion, die Sie ersetzt haben, war eine durch HTTP ausgelöste Funktion, ausgeführt, als auf einen HTTP-Endpunkt zugegriffen wurde. Die neue Funktion wird durch Echtzeit-Datenbankereignisse ausgelöst: Sie prüft, ob neue Elemente an einem bestimmten Pfad vorhanden sind, und schreibt bei einem positiven Ergebnis die Großbuchstabenversion des Werts zurück in die Datenbank.

    Diese neue Datei verwendet übrigens die ECMAScript-Modulsyntax (import und export) anstelle von CommonJS (require). Um ES-Module in Node zu verwenden, "type": "module" in functions/package.json angeben:

    {
      "name": "rtdb-uppercase-messages",
      "main": "index.js",
      "type": "module",
      
    }
    
  2. Jede Funktion in Ihrer Erweiterung muss in der Datei extension.yaml deklariert werden. In der Beispielerweiterung wurde greetTheWorld als einzige Cloud-Funktion der Erweiterung deklariert. Da Sie sie jetzt durch makeuppercase ersetzt haben, müssen Sie auch die Deklaration aktualisieren.

    Öffnen Sie extension.yaml und fügen Sie ein resources-Feld hinzu:

    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"
    
  3. Da Ihre Erweiterung jetzt Realtime Database als Trigger verwendet, benötigen Sie um die Konfiguration des Emulators zu aktualisieren, sodass der RTDB-Emulator parallel zum Cloud Functions-Emulator:

    1. Wenn der Emulator noch ausgeführt wird, beenden Sie ihn durch Drücken von Strg+C.

    2. Führen Sie im Verzeichnis functions/integration-tests folgenden Befehl aus: Befehl:

      firebase init emulators

      Überspringen Sie bei Aufforderung die Einrichtung eines Standardprojekts und wählen Sie die Funktionen und Datenbankemulatoren. Akzeptieren Sie die Standardports und erlauben Sie dem Einrichtungstool, alle erforderlichen Dateien herunterzuladen.

    3. Starten Sie den Emulator neu:

      firebase emulators:start --project=demo-test
  4. Testen Sie die aktualisierte Erweiterung:

    1. Öffnen Sie die Benutzeroberfläche des Datenbankemulators über den vom Emulator ausgegebenen Link als Sie ihn begonnen haben.

    2. Bearbeiten Sie den Stammknoten der Datenbank:

      • Feld: messages
      • Typ: json
      • Wert: {"11": {"original": "recipe"}}

      Wenn alles korrekt eingerichtet ist, Die Funktion makeuppercase der Erweiterung sollte auslösen und ein untergeordnetes Element hinzufügen Datensatz in Nachricht 11 mit dem Inhalt "upper": "RECIPE" aufnehmen. Sehen Sie sich die Protokolle und die Datenbank-Tabs der Emulator-Benutzeroberfläche an, um die erwarteten Ergebnisse zu bestätigen.

    3. Fügen Sie dem Knoten messages weitere untergeordnete Elemente hinzu ({"original":"any text"}). Jedes Mal, wenn Sie einen neuen Eintrag hinzufügen, muss das Feld uppercase mit dem Großbuchstaben des Felds original enthält.

Sie haben jetzt eine vollständige, aber einfache Erweiterung, die auf einem RTDB basiert. Instanz. In den folgenden Abschnitten verfeinern Sie diese Erweiterung, zusätzliche Funktionen. Anschließend bereiten Sie die Erweiterung vor, und erfahren, wie Sie Ihre Erweiterung im Erweiterungs-Hub veröffentlichen.

5. APIs und Rollen deklarieren

Firebase gewährt jeder Instanz einer installierten Erweiterung eingeschränkten Zugriff auf die Projekt und seine Daten mit einem instanzspezifischen Dienstkonto. Jedes Konto hat die Berechtigungen, die für den Betrieb erforderlich sind. Aus diesem Grund müssen Sie Sie müssen explizit alle IAM-Rollen deklarieren, die Ihre Erweiterung erfordert. wenn Nutzer*innen die App installieren Erweiterung hinzufügen, erstellt Firebase ein Dienstkonto mit diesen Rollen, um die Erweiterung auszuführen.

Sie müssen keine Rollen zum Auslösen von Produktereignissen deklarieren, eine Rolle erklären müssen, um anderweitig mit ihr interagieren zu können. Da die Funktion, die Sie die im letzten Schritt in Realtime Database geschrieben werden, müssen Sie die Methode folgende Erklärung an extension.yaml:

roles:
  - role: firebasedatabase.admin
    reason: Allows the extension to write to RTDB.

Ebenso deklarieren Sie die Google APIs, die von einer Erweiterung verwendet werden, im Feld apis. Wenn Nutzer Ihre Erweiterung installieren, werden sie gefragt, ob sie um diese APIs automatisch für ihr Projekt zu aktivieren. Dies ist normalerweise nur erforderlich für Nicht-Firebase-Google-APIs und wird für diesen Leitfaden nicht benötigt.

6. Benutzerdefinierte Parameter definieren

Die Funktion, die Sie in den letzten beiden Schritten erstellt haben, hat an einem bestimmten RTDB-Speicherort nach eingehenden Nachrichten gesucht. Manchmal ist es wichtig, einen bestimmten Ort zu beobachten, z. B. wenn Ihre Erweiterung auf einer Datenbankstruktur läuft, die Sie ausschließlich für Ihre Erweiterung verwenden. Meistens werden Sie jedoch können Sie diese Werte für Nutzer konfigurieren, die Ihre Erweiterung in ihrem Projekten. So können Nutzer die Erweiterung für ihre vorhandenen Datenbank-Setup haben.

Der Pfad, den die Erweiterung auf neue Nachrichten überwacht, sollte vom Nutzer konfiguriert werden:

  1. Fügen Sie in der Datei extension.yaml einen Abschnitt params hinzu:

    - 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
    

    Definiert einen neuen String-Parameter, den Nutzer festlegen müssen, wenn sie installieren Ihre Erweiterung.

  2. Gehen Sie in der Datei extension.yaml zurück zur makeuppercase-Erklärung und ändern Sie das Feld resource in Folgendes:

    resource: projects/_/instances/${DATABASE_INSTANCE}/refs/${param:MESSAGE_PATH}
    

    Das ${param:MESSAGE_PATH}-Token ist ein Verweis auf den gerade definierten Parameter. Wenn Ihre Erweiterung ausgeführt wird, wird dieses Token durch ein beliebiges Wert, den der Nutzer für diesen Parameter konfiguriert hat, mit dem Ergebnis, dass der Die Funktion makeuppercase überwacht den vom Nutzer angegebenen Pfad. Sie können können Sie diese Syntax verwenden, um auf beliebige benutzerdefinierte Parameter an beliebiger Stelle in extension.yaml (und in POSTINSTALL.md – dazu später mehr).

  3. Sie können auch über den Funktionscode auf benutzerdefinierte Parameter zugreifen.

    In der Funktion, die Sie im letzten Abschnitt geschrieben haben, haben Sie den Pfad zu und achten Sie auf Veränderungen. Ändern Sie die Triggerdefinition so, dass sie auf die benutzerdefinierten Wert:

    functions/index.js

    export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate
    

    In Firebase Extensions ist diese Änderung einzig Dokumentation: Wenn eine Cloud Functions-Funktion als Teil einer Erweiterung bereitgestellt wird, verwendet die Triggerdefinition aus der Datei extension.yaml und ignoriert den Parameter Wert, der in der Funktionsdefinition angegeben wurde. Dennoch ist es eine gute Idee, um in Ihrem Code zu dokumentieren, woher dieser Wert stammt.

  4. Es kann enttäuschend sein, eine Codeänderung ohne Laufzeit vorzunehmen. aber die wichtigste Lektion ist, dass Sie auf alle benutzerdefinierten Parameter in Ihrem Funktionscode und verwenden Sie ihn als gewöhnlichen Wert in der Logik der Funktion. Fügen Sie zur Veranschaulichung das folgende Log hinzu: um zu zeigen, dass Sie tatsächlich auf den Wert zugreifen, Benutzerdefiniert:

    functions/index.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.
        ...
    
  5. Normalerweise werden Nutzer aufgefordert, Werte für Parameter anzugeben, wenn sie eine Erweiterung installieren. Wenn Sie den Emulator zu Test- und Entwicklungszwecken verwenden, Sie überspringen jedoch den Installationsprozess und geben stattdessen Werte an. für benutzerdefinierte Parameter mithilfe einer env-Datei.

    functions/integration-tests/extensions/rtdb-uppercase-messages.env öffnen und ersetzen Sie die GREETING-Definition durch Folgendes:

    MESSAGE_PATH=/msgs/{pushId}/original
    

    Beachten Sie, dass sich der obige Pfad vom Standardpfad und vom Pfad, den Sie zuvor definiert haben; dass Sie sich selbst beweisen, wenn Sie dass Ihre Definition wirksam wird.

  6. Starten Sie nun den Emulator neu und rufen Sie noch einmal die Benutzeroberfläche des Datenbankemulators auf.

    Bearbeiten Sie den Stammknoten der Datenbank unter Verwendung des oben definierten Pfads:

    • Feld: msgs
    • Typ: json
    • Wert: {"11": {"original": "recipe"}}

    Wenn du die Datenbankänderungen speicherst, wird der makeuppercase der Erweiterung sollte wie zuvor ausgelöst werden, jetzt sollte sie aber auch benutzerdefinierten Parameter an das Konsolenprotokoll übergeben.

7. Ereignis-Hooks für benutzerdefinierte Logik bereitstellen

Sie haben als Autor von Erweiterungen bereits gesehen, wie ein Firebase-Produkt Von der Erweiterung bereitgestellte Logik: Erstellung neuer Datensätze in Realtime Database Löst die Funktion makeuppercase aus. Ihre Erweiterung kann ein analoges zu den Nutzern, die die Erweiterung installiert haben: Ihre Erweiterung kann Triggerlogik, die der user definiert.

Eine Erweiterung kann synchrone Hooks, asynchrone Hooks oder beides bereitstellen. Mit synchronen Hooks können Nutzende Aufgaben ausführen, die den Abschluss einer der Funktionen der Erweiterung. Dies kann beispielsweise nützlich sein, um Nutzenden eine Möglichkeit, eine benutzerdefinierte Vorverarbeitung durchzuführen, bevor eine Erweiterung ihre Arbeit übernimmt.

In diesem Leitfaden fügen Sie Ihrer Erweiterung einen asynchronen Hook hinzu, der Nutzer können eigene Verarbeitungsschritte definieren, die nach der Erweiterung ausgeführt werden sollen schreibt die Nachricht in Großbuchstaben in Realtime Database. Bei asynchronen Hooks werden benutzerdefinierte Funktionen über Eventarc ausgelöst. Erweiterungen deklarieren die Arten von Ereignissen, die sie ausgeben, und Wenn Nutzer die Erweiterung installieren, wählen sie die Ereignistypen aus, an denen Sie interessiert sind. Wenn er mindestens ein Ereignis auswählt, wird von Firebase ein Eventarc-Kanal für die Erweiterung im Rahmen der Installation. Nutzer können dann eigene Cloud-Funktionen bereitstellen, die auf diesem Kanal lauschen und ausgelöst werden, wenn die Erweiterung neue Ereignisse veröffentlicht.

Führen Sie die folgenden Schritte aus, um einen asynchronen Hook hinzuzufügen:

  1. Fügen Sie der Datei extension.yaml den folgenden Abschnitt hinzu, in dem die einen Ereignistyp, den die Erweiterung ausgibt:

    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.
    

    Ereignistypen müssen universell eindeutig sein. um die Eindeutigkeit zu gewährleisten, im folgenden Format erstellen: <publisher-id>.<extension-id>.<version>.<description> Da du noch keine Publisher-ID hast, verwende vorerst test-publisher.

  2. Fügen Sie am Ende der Funktion makeuppercase Code hinzu, der einen -Ereignis des soeben deklarierten Typs ein:

    functions/index.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,
        },
      });
    

    Bei diesem Beispielcode wird die Tatsache ausgenutzt, dass das EVENTARC_CHANNEL Umgebungsvariable wird nur definiert, wenn der Nutzer mindestens eine Variable aktiviert hat Ereignistyp. Ist EVENTARC_CHANNEL nicht definiert, versucht der Code nicht, um Ereignisse zu veröffentlichen.

    Sie können einem Eventarc-Ereignis zusätzliche Informationen anhängen. Im obigen Beispiel Das Ereignis hat ein subject-Feld mit einem Verweis auf den neu erstellten Wert und eine data-Nutzlast, die das ursprüngliche und Nachrichten in Großbuchstaben. Benutzerdefinierte Funktionen, die das Ereignis auslösen, können diese Informationen zu nutzen.

  3. Normalerweise werden die Umgebungsvariablen EVENTARC_CHANNEL und EXT_SELECTED_EVENTS anhand der Optionen definiert, die der Nutzer bei der Installation ausgewählt hat. Definieren Sie diese Variablen für Tests mit dem Emulator manuell in der Datei rtdb-uppercase-messages.env:

    EVENTARC_CHANNEL=locations/us-central1/channels/firebase
    EXT_SELECTED_EVENTS=test-publisher.rtdb-uppercase-messages.v1.complete
    

Sie haben jetzt alle Schritte ausgeführt, die zum Hinzufügen eines asynchronen Ereignis-Hooks zu Ihrer Erweiterung erforderlich sind.

Um diese neue Funktion auszuprobieren, die Sie gerade implementiert haben, übernehmen Sie in den nächsten Schritten die Rolle eines Nutzers, der die Erweiterung installiert:

  1. Initialisieren Sie im Verzeichnis functions/integration-tests ein neues Firebase Projekt:

    firebase init functions

    Lehnen Sie die Einrichtung eines Standardprojekts ab, wählen Sie JavaScript als Cloud Functions-Sprache aus und installieren Sie die erforderlichen Abhängigkeiten. Dieses Projekt stellt das Projekt eines Nutzers dar, in dem Ihre Erweiterung installiert ist.

  2. Bearbeiten Sie integration-tests/functions/index.js und fügen Sie den folgenden Code ein:

    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}!!!`);
      }
    );
    

    Dies ist ein Beispiel für eine Funktion zur Nachbearbeitung, die ein Nutzer schreiben könnte. In dieser wartet die Funktion auf die Erweiterung, um ein complete-Ereignis zu veröffentlichen. Beim Auslösen werden dem neuen Großbuchstaben drei Ausrufezeichen hinzugefügt. .

  3. Starte den Emulator neu. Der Emulator lädt die Funktionen der Erweiterung als sowie die Nachbearbeitungsfunktion „Nutzer“ definiert.

  4. Rufen Sie die Benutzeroberfläche des Datenbankemulators auf und bearbeiten Sie den Stammknoten der Datenbank mit Pfad, den Sie oben definiert haben:

    • Feld:msgs
    • Typ: json
    • Wert: {"11": {"original": "recipe"}}

    Wenn du die Datenbankänderungen speicherst, wird der makeuppercase der Erweiterung und die Funktion extraemphasis des Nutzers der Reihe nach ausgelöst werden, Dadurch wird im Feld upper der Wert RECIPE!!! abgerufen.

8. Lifecycle-Event-Handler hinzufügen

Die von Ihnen erstellte Erweiterung verarbeitet Nachrichten, während sie erstellt werden. Was ist aber, wenn Ihre Nutzer bereits eine Datenbank mit Nachrichten haben, wenn sie die Erweiterung installieren? Firebase Extensions hat eine Funktion namens Lebenszyklus-Ereignis-Hooks, die Aktionen auslösen, wenn Ihre Erweiterung installiert, aktualisiert oder neu konfiguriert. In diesem Abschnitt verwenden Sie Lebenszyklus-Ereignis-Hooks, um einen Backfill für einen Nachrichtendatenbank des Projekts mit Nachrichten in Großbuchstaben, wenn ein Nutzer installiert Ihre Erweiterung.

Firebase Extensions verwendet Cloud Tasks, um Ihre Lebenszyklus-Event-Handler auszuführen. Ich Event-Handler mithilfe von Cloud Functions definieren wenn eine Instanz Ihres Erweiterung eines der unterstützten Lebenszyklus-Ereignisse erreicht, wenn Sie ein -Handler erstellt haben, wird der Handler einer Cloud Tasks-Warteschlange hinzugefügt. wird Cloud Tasks dann den Handler asynchron auszuführen. Während ein Lebenszyklus-Event-Handler ausgeführt wird, meldet die Firebase Console dem Nutzer, dass die Erweiterungsinstanz in Bearbeitung ist. Es liegt an der Handler-Funktion, fortlaufende Status und Abschluss der Aufgabe an die Nutzenden senden.

So fügen Sie einen Lebenszyklus-Event-Handler hinzu, der vorhandene Nachrichten auffüllt: Folgendes:

  1. Definieren Sie eine neue Cloud Functions-Funktion, die durch Ereignisse in der Aufgabenwarteschlange ausgelöst wird:

    functions/index.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.");
      }
    });
    

    Beachten Sie, dass die Funktion nur einige Datensätze verarbeitet, bevor sie sich selbst hinzufügt zurück in die Aufgabenwarteschlange. Dies ist eine gängige Strategie, um mit Verarbeitungsaufgaben umzugehen, die nicht innerhalb des Zeitlimits einer Cloud-Funktion abgeschlossen werden können. Da Sie nicht vorhersagen können, wie viele Nachrichten ein Nutzer in der Datenbank gespeichert sind, wenn sie Ihre Erweiterung installieren, die gut passen.

  2. Deklarieren Sie in der Datei extension.yaml die Backfill-Funktion als Erweiterung Ressource mit dem Attribut taskQueueTrigger:

    resources:
      - name: makeuppercase
        ...
      - name: backfilldata
        type: firebaseextensions.v1beta.function
        description: >-
          Backfill existing messages with uppercase versions
        properties:
          runtime: "nodejs18"
          taskQueueTrigger: {}
    

    Deklarieren Sie dann die Funktion als Handler für den onInstall-Lebenszyklus Ereignis:

    lifecycleEvents:
      onInstall:
        function: backfilldata
        processingMessage: Uppercasing existing messages
    
  3. Das Backfilling vorhandener Nachrichten ist zwar praktisch, die Erweiterung funktioniert aber auch ohne. In solchen Fällen sollten Sie sind die Lifecycle-Event-Handler optional.

    Fügen Sie dazu einen neuen Parameter zu extension.yaml hinzu:

    - 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
    

    Überprüfen Sie dann am Anfang der Backfill-Funktion den Wert des DO_BACKFILL-Parameter und vorzeitig beenden, wenn er nicht festgelegt ist:

    functions/index.js

    if (!process.env.DO_BACKFILL) {
      return getExtensions()
        .runtime()
        .setProcessingState("PROCESSING_COMPLETE", "Backfill skipped.");
    }
    

Durch die oben genannten Änderungen werden vorhandene Nachrichten nach der Installation der Erweiterung in Großbuchstaben umgewandelt.

Bisher haben Sie den Erweiterungsemulator verwendet, um Ihre Erweiterung zu entwickeln und laufende Änderungen testen. Der Erweiterungsemulator überspringt die Installation jedoch. Zum Testen des onInstall-Event-Handlers musst du den in einem echten Projekt nutzen. Das ist aber genauso gut, da die Erweiterung dieser automatischen Auffüllfunktion ist die Erweiterung der Anleitung jetzt vollständig mit dem Code ausgestattet.

9. In echtem Firebase-Projekt bereitstellen

Der Erweiterungsemulator ist ein hervorragendes Tool, um während der Entwicklung schnell Änderungen an einer Erweiterung vorzunehmen. Irgendwann sollten Sie sie jedoch in einem echten Projekt ausprobieren.

Richten Sie dazu zuerst ein neues Projekt mit einigen aktivierten Diensten ein:

  1. Fügen Sie in der Firebase Console eine neue Projekt arbeiten.
  2. Upgrade für Projekt durchführen zum „Pay as you go“-Tarif. Cloud Functions for Firebase benötigt Ihr Projekt benötigen Sie ein Rechnungskonto. eine Erweiterung installieren.
  3. Aktivieren Sie in Ihrem neuen Projekt die Realtime Database.
  4. Da Sie testen möchten, ob Ihre Erweiterung Installieren Sie einige Beispieldaten in Ihre Echtzeit-Datenbankinstanz:
    1. Laden Sie einige Seed-RTDB-Daten herunter.
    2. Klicken Sie auf der Seite „Echtzeitdatenbank“ der Firebase Console auf (mehr) > JSON importieren und wählen Sie die Datei aus, die Sie gerade heruntergeladen haben.
  5. Damit die Backfill-Funktion die Methode orderByChild verwenden kann, müssen Sie die Datenbank, um Nachrichten für den Wert von upper zu indexieren:

    {
      "rules": {
        ".read": false,
        ".write": false,
        "messages": {
          ".indexOn": "upper"
        }
      }
    }
    

Installieren Sie jetzt die Erweiterung aus der lokalen Quelle im neuen Projekt:

  1. Erstellen Sie ein neues Verzeichnis für Ihr Firebase-Projekt:

    mkdir ~/extensions-live-test && cd ~/extensions-live-test
    
  2. Initialisieren Sie im Arbeitsverzeichnis ein Firebase-Projekt:

    firebase init database

    Wählen Sie das gerade erstellte Projekt aus, wenn Sie dazu aufgefordert werden.

  3. Installieren Sie die Erweiterung in Ihrem lokalen Firebase-Projekt:

    firebase ext:install /path/to/rtdb-uppercase-messages

    Hier sehen Sie, wie die Installation eines mit dem Firebase CLI-Tool. Achten Sie darauf, „Ja“ auszuwählen. wenn das Ereignis Konfigurationstool fragt, ob Sie ein Backfill für Ihre vorhandene Datenbank ausführen möchten.

    Nachdem Sie die Konfigurationsoptionen ausgewählt haben, speichert die Firebase CLI Ihre Konfiguration im Verzeichnis extensions und notieren Sie sich die Erweiterungsquelle Speicherort in der Datei firebase.json. Zusammen sind diese beiden Datensätze das Erweiterungsmanifest. Nutzer können das Manifest verwenden, um ihre Konfiguration von Erweiterungen und stellen sie in verschiedenen Projekten bereit.

  4. Stellen Sie die Erweiterungskonfiguration für Ihr Live-Projekt bereit:

    firebase deploy --only extensions

Wenn alles richtig funktioniert, sollte die Firebase CLI Ihre Erweiterung in Ihr Projekt hochladen und installieren. Nach Abschluss der Installation wird die Backfill-Aufgabe ausgeführt. wird Ihre Datenbank mit Nachrichten in Großbuchstaben aktualisiert. Füge welche hinzu neue Knoten zur Nachrichtendatenbank hinzu und stellen Sie sicher, dass die Erweiterung für neue Nachrichten.

10. Dokumentation schreiben

Stellen Sie vor der Freigabe Ihrer Erweiterung sicher, dass Sie damit sie erfolgreich sind.

Bei der Initialisierung des Erweiterungsprojekts hat die Firebase CLI einen Stub erstellt Versionen der erforderlichen Mindestdokumentation. Aktualisieren Sie diese Dateien, damit sie die von Ihnen erstellte Erweiterung korrekt widerspiegeln.

Erweiterung.yaml

Sie haben diese Datei mit dieser Erweiterung bereits aktualisiert. Sie müssen momentan keine weiteren Aktualisierungen vornehmen.

Sie dürfen jedoch nicht übersehen, wie wichtig die in diesem Dokument -Datei. Neben den wichtigen Identifizierungsinformationen einer Erweiterung, wie Name, Beschreibung, Autor, offizieller Repository-Speicherort (extension.yaml) Datei enthält eine an den Nutzer gerichtete Dokumentation für jede Ressource und kann vom Nutzer konfiguriert werden. . Diese Informationen werden Nutzern in der Firebase Console angezeigt, Extensions Hub und Firebase CLI.

PREINSTALL.md:

Geben Sie in dieser Datei Informationen an, die der Nutzer benötigt, bevor er Ihre App installiert. Erweiterung: Beschreiben Sie kurz die Funktion der Erweiterung, erklären Sie alle Voraussetzungen, und Nutzer darüber zu informieren, welche Auswirkungen die Installation der . Wenn du eine Website mit zusätzlichen Informationen hast, ist dies auch ein um es zu verknüpfen.

Der Text dieser Datei wird dem Nutzer im Extensions Hub und über den Befehl firebase ext:info angezeigt.

Hier ist ein Beispiel für eine PREINSTALL-Datei:

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

Diese Datei enthält Informationen, die für Nutzer nützlich sind, nachdem sie Ihre Erweiterung installiert haben. Dazu gehören beispielsweise weitere Einrichtungsschritte und ein Beispiel für die Verwendung der Erweiterung.

Der Inhalt von POSTINSTALL.md wird in der Firebase Console angezeigt, nachdem eine Erweiterung konfiguriert und installiert wurde. Sie können in diesem und werden durch die konfigurierten Werte ersetzt.

Hier ist eine Beispieldatei für die Erweiterung nach der Installation:

### 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

Sie sollten auch die Änderungen dokumentieren, die Sie zwischen den Releases einer Erweiterung vornehmen. in der Datei CHANGELOG.md.

Da die Beispielerweiterung noch nie veröffentlicht wurde, wurde das Änderungsprotokoll nur einen Eintrag:

## Version 0.0.1

Initial release of the _Convert messages to upper case_ extension.

README.md

Die meisten Erweiterungen bieten auch eine Readme-Datei zum Vorteil der Besucher der Website des Repositorys der Erweiterung. können Sie diese Datei von Hand schreiben mit dem -Befehl.

Für die Zwecke dieses Leitfadens überspringen Sie das Schreiben einer Readme-Datei.

Zusätzliche Dokumentation

Die oben erläuterte Dokumentation ist die Mindestmenge an Dokumentation, die Sie den Nutzenden bieten. Viele Erweiterungen erfordern eine detailliertere Dokumentation, erfolgreich einsetzen können. In diesem Fall sollten Sie zusätzliche und an einem Ort hosten, an den Sie die Nutzenden verweisen können.

Für die Zwecke dieses Leitfadens überspringen Sie das Schreiben einer ausführlicheren Dokumentation.

11. Im Erweiterungs-Hub veröffentlichen

Der Code Ihrer Erweiterung ist vollständig und dokumentiert. Jetzt können Sie sie teilen. im Erweiterungs-Hub mit der Welt teilen. Da es sich aber nur um eine Demo handelt, sollten Sie das nicht tun. Beginnen Sie damit, Ihre eigene Erweiterung mit dem, was Sie und der anderen Publisher-Dokumentation zu Firebase Extensions. und die Quelle der offiziellen, von Firebase geschriebenen Erweiterungen.

Wenn Sie bereit sind, Ihre Arbeit im Erweiterungs-Hub zu veröffentlichen, gehen Sie so vor: es:

  1. Wenn Sie Ihre erste Erweiterung veröffentlichen, als Erweiterungs-Publisher registrieren. Wenn Sie sich als Publisher von Erweiterungen registrieren, erstellen Sie eine Publisher-ID, anhand derer Nutzer Sie schnell als Autor Ihrer Erweiterungen identifizieren können.
  2. Hosten Sie den Quellcode Ihrer Erweiterung an einem öffentlich überprüfbaren Ort. Wann? aus einer überprüfbaren Quelle stammt, kann Firebase Ihre Erweiterung direkt von diesem Standort aus. So können Sie sicherstellen, Wenn Sie die aktuell veröffentlichte Version Ihrer Erweiterung veröffentlichen, helfen Sie Nutzern, indem sie den Code untersuchen können, den sie in ihren Projekten installieren.

    Derzeit bedeutet das, dass Sie Ihre Erweiterung in einem öffentlichen GitHub-Repository verfügbar machen müssen.

  3. Lade deine Erweiterung über die firebase ext:dev:upload in den Erweiterungs-Hub hoch .

  4. Rufen Sie in der Firebase Console Ihr Publisher-Dashboard auf, suchen Sie die gerade hochgeladene Erweiterung und klicken Sie auf „Im Erweiterungs-Hub veröffentlichen“. Hier wird ein Überprüfung durch unsere Mitarbeiter. Dies kann einige Tage dauern. Wenn die Erweiterung genehmigt wird, wird sie im Erweiterungs-Hub veröffentlicht. Wenn der Antrag abgelehnt wird, erhalten Sie eine Nachricht mit einer Begründung. Sie können dann die gemeldeten Probleme beheben und den Antrag noch einmal zur Überprüfung einreichen.