Commencer à créer une extension

Cette page vous explique les étapes à suivre pour créer un projet Firebase simple que vous pouvez installer dans vos projets ou partager avec d'autres utilisateurs. Ce exemple simple d'extension Firebase surveillera votre base de données Realtime Database pour messages et de les convertir en majuscules.

1. Configurer votre environnement et initialiser un projet

Avant de pouvoir commencer à créer une extension, vous devez configurer un environnement de compilation avec les outils requis.

  1. Installez Node.js 16 ou une version ultérieure. Pour installer Node.js, vous pouvez utiliser NVM (ou nvm-windows).

  2. Installez la dernière version de la CLI Firebase ou appliquez la mise à jour correspondante. À installer ou mettre à jour à l'aide de npm, exécutez la commande suivante:

    npm install -g firebase-tools

Utilisez maintenant la CLI Firebase pour initialiser un nouveau projet d'extension:

  1. Créez un répertoire pour votre extension et cd dans celui-ci:

    mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
  2. Exécutez la commande ext:dev:init de la CLI Firebase:

    firebase ext:dev:init

    Lorsque vous y êtes invité, sélectionnez JavaScript comme langage pour les fonctions (notez toutefois que vous pouvez également utiliser TypeScript lorsque vous développez votre propre extension). Lorsque vous êtes invité à installer des dépendances, répondez "oui". (Acceptez les valeurs par défaut pour toute autre option.) Cette commande configure un squelette de codebase pour nouvelle extension, à partir de laquelle vous pourrez commencer à développer votre extension.

2. Essayez l'exemple d'extension avec l'émulateur

Lorsque la CLI Firebase a initialisé le nouveau répertoire des extensions, elle a créé un exemple de fonction simple et un répertoire integration-tests contenant le les fichiers nécessaires à l'exécution d'une extension à l'aide de la suite d'émulateurs Firebase.

Essayez d'exécuter l'exemple d'extension dans l'émulateur :

  1. Accédez au répertoire integration-tests :

    cd functions/integration-tests
  2. Démarrez l'émulateur avec un projet de démonstration:

    firebase emulators:start --project=demo-test

    L'émulateur charge l'extension dans un modèle "factice" prédéfini projet (demo-test). Jusqu'à présent, l'extension se composait d'un seul modèle, greetTheWorld, qui renvoie un message "hello world" message quand y accéder.

  3. Pendant que l'émulateur est toujours en cours d'exécution, essayez la méthode greetTheWorld de l'extension en accédant à l'URL qui s'affiche au démarrage.

    Votre navigateur affiche le message "Hello World from greet-the-world" (Bonjour le monde depuis greet-the-world).

  4. Le code source de cette fonction se trouve dans le fichier functions de l'extension . Ouvrez la source dans l'éditeur ou l'IDE de votre choix:

    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. Lorsque l'émulateur est en cours d'exécution, il recharge automatiquement toutes les modifications que vous apportez à votre code Functions. Essayez d'apporter une légère modification Fonction greetTheWorld:

    functions/index.js

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

    Enregistrez les modifications. L'émulateur actualise votre code. Désormais, lorsque vous exécutez accédez à l'URL de la fonction, vous verrez le message d'accueil mis à jour.

3. Ajouter des informations de base au fichier extension.yaml

Maintenant que votre environnement de développement est configuré et que vous exécutez le vous pouvez commencer à écrire votre propre extension.

Dans un premier temps, modifiez les métadonnées prédéfinies de l'extension afin de refléter que vous souhaitez écrire à la place de greet-the-world. Ces métadonnées sont stockées dans le fichier extension.yaml.

  1. Ouvrez extension.yaml dans votre éditeur et remplacez l'intégralité du contenu de par le code suivant:

    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
    

    Notez la convention d'attribution de noms utilisée dans le champ name: Firebase officiel Les extensions sont nommées avec un préfixe indiquant le produit Firebase principal. l'opération sur laquelle l'extension fonctionne, suivi d'une description de ce sur quoi elle doit . Vous devez utiliser la même convention dans vos propres extensions.

  2. Puisque vous avez modifié le nom de votre extension, vous devez également mettre à jour votre la configuration de l'émulateur s'appelle désormais la commande suivante:

    1. Dans functions/integration-tests/firebase.json, modifiez greet-the-world. à rtdb-uppercase-messages.
    2. Renommer functions/integration-tests/extensions/greet-the-world.env en functions/integration-tests/extensions/rtdb-uppercase-messages.env

Il reste encore des restes de l'extension greet-the-world dans le code de votre extension, mais laissez-les pour l'instant. Vous les mettrez à jour dans les prochaines .

4. Écrire une fonction Cloud et la déclarer en tant que ressource d'extension

Vous pouvez maintenant commencer à écrire du code. Dans cette étape, vous allez écrire Fonction qui effectue la tâche principale de votre extension, à savoir pour surveiller les messages dans votre base de données Realtime Database et les convertir en majuscules.

  1. Ouvrez le code source des fonctions de l'extension (dans le fichier functions) dans l'éditeur ou l'IDE de votre choix. Remplacez son par le code suivant:

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

    L'ancienne fonction, que vous avez remplacée, était déclenchée par HTTP, exécuté lors de l'accès à un point de terminaison HTTP. La nouvelle fonction est déclenchée Événements de base de données en temps réel: elle surveille les nouveaux éléments sur un chemin particulier Lorsque l'une d'elles est détectée, il réécrit la valeur en majuscules. à la base de données.

    À ce propos, ce nouveau fichier utilise la syntaxe du module ECMAScript (import et export) au lieu de CommonJS (require). Pour utiliser les modules ES dans Node, procédez comme suit : spécifiez "type": "module" dans functions/package.json:

    {
      "name": "rtdb-uppercase-messages",
      "main": "index.js",
      "type": "module",
      
    }
    
  2. Chaque fonction de votre extension doit être déclarée dans le fichier extension.yaml. L'exemple d'extension a déclaré greetTheWorld comme seule de l'extension Cloud Functions maintenant que vous l'avez remplacé par makeuppercase, modifier sa déclaration.

    Ouvrez extension.yaml et ajoutez un champ resources:

    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. Étant donné que votre extension utilise désormais Realtime Database comme déclencheur, vous devez pour mettre à jour la configuration de l'émulateur afin d'exécuter l'émulateur RTDB en même temps que Émulateur Cloud Functions:

    1. Si l'émulateur est toujours en cours d'exécution, arrêtez-le en appuyant sur Ctrl-C.

    2. Depuis le répertoire functions/integration-tests, exécutez la commande suivante :

      firebase init emulators

      Lorsque vous y êtes invité, ignorez la configuration d'un projet par défaut, puis sélectionnez l'option "Functions" (Fonctions). et les émulateurs de base de données. Acceptez les ports par défaut et autorisez l'outil de configuration à télécharger les fichiers requis.

    3. Redémarrez l'émulateur:

      firebase emulators:start --project=demo-test
  4. Essayez votre extension mise à jour :

    1. Ouvrez l'interface utilisateur de l'émulateur de base de données à l'aide du lien affiché par l'émulateur. lorsque vous l'avez lancée.

    2. Modifiez le nœud racine de la base de données:

      • Champ:messages
      • Type : json
      • Valeur : {"11": {"original": "recipe"}}

      Si tout est correctement configuré, lorsque vous enregistrez les modifications de votre base de données, la fonction makeuppercase de l'extension doit se déclencher et ajouter un élément enfant enregistrez le message 11 avec le contenu "upper": "RECIPE". Consultez les journaux et les onglets de base de données de l'UI de l'émulateur pour confirmer les résultats attendus.

    3. Essayez d'ajouter d'autres enfants au nœud messages ({"original":"any text"}). Chaque fois que vous ajoutez un enregistrement, la l'extension doit ajouter un champ uppercase contenant les majuscules le contenu du champ original.

Vous disposez désormais d'une extension complète, mais simple, qui fonctionne sur une instance RTDB. Dans les sections suivantes, vous allez affiner cette extension avec quelques fonctionnalités supplémentaires. Ensuite, vous préparerez l'extension à distribuer sur et comment publier votre extension sur le Hub des extensions.

5. Déclarer des API et des rôles

Firebase accorde à chaque instance d'une extension installée un accès limité à et ses données à l'aide d'un compte de service par instance. Chaque compte dispose du un ensemble minimal d'autorisations nécessaires pour fonctionner. Vous devez donc déclarer explicitement les rôles IAM requis par votre extension ; lorsque les utilisateurs installent votre extension, Firebase crée un compte de service auquel ces rôles sont attribués l'utilise pour exécuter l'extension.

Il n'est pas nécessaire de déclarer des rôles pour déclencher les événements d'un produit, mais devez déclarer un rôle pour interagir avec lui. Parce que la fonction que vous ajoutées à la dernière étape pour les écritures dans Realtime Database, vous devez ajouter la déclaration suivante à extension.yaml:

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

De même, vous déclarez les API Google qu'une extension utilise dans apis. . Lorsque les utilisateurs installent votre extension, ils sont invités à activer automatiquement ces API pour leur projet. En général, il s'agit uniquement est nécessaire pour les API Google en dehors de Firebase et n'est pas nécessaire dans le cadre de ce guide.

6. Définir des paramètres configurables par l'utilisateur

La fonction que vous avez créée au cours des deux dernières étapes a surveillé un emplacement RTDB spécifique pour les messages entrants. Parfois, regarder un lieu spécifique est vraiment ce qui comme lorsque votre extension fonctionne sur une structure de base de données utiliser exclusivement pour votre extension. Cependant, la plupart du temps, vous devrez rendre ces valeurs configurables par les utilisateurs qui installent votre extension dans leur projets. Les utilisateurs peuvent ainsi utiliser votre extension pour travailler avec leur configuration de base de données existante.

Faites en sorte que le chemin d'accès que l'extension surveille pour les nouveaux messages soit configurable par l'utilisateur :

  1. Dans le fichier extension.yaml, ajoutez une section 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
    

    Cela définit un nouveau paramètre de chaîne que les utilisateurs seront invités à définir lorsqu'ils installeront votre extension.

  2. Toujours dans le fichier extension.yaml, revenez à votre déclaration makeuppercase et remplacez le champ resource par le code suivant :

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

    Le jeton ${param:MESSAGE_PATH} est une référence au paramètre que vous venez de définir. définis. Lorsque votre extension s'exécute, ce jeton est remplacé par le nom valeur configurée par l'utilisateur pour ce paramètre. Le résultat est La fonction makeuppercase écoute le chemin spécifié par l'utilisateur. Vous pouvez utilisez cette syntaxe pour référencer n'importe quel paramètre défini par l'utilisateur dans extension.yaml (et dans POSTINSTALL.md, nous y reviendrons plus tard).

  3. Vous pouvez également accéder aux paramètres définis par l'utilisateur à partir du code de vos fonctions.

    Dans la fonction que vous avez écrite dans la section précédente, vous avez codé en dur le chemin d'accès surveillez les changements. Modifiez la définition du déclencheur pour référencer le définie par l'utilisateur:

    functions/index.js

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

    Notez que dans les extensions Firebase, ce changement est purement à des fins de documentation : lorsqu'une fonction Cloud est déployée dans le cadre d'une extension, elle utilise la définition du déclencheur du fichier extension.yaml et ignore la valeur spécifiée dans la définition de la fonction. Néanmoins, il est judicieux pour indiquer dans votre code d'où vient cette valeur.

  4. Vous pouvez être déçu de modifier le code sans effet d'exécution, mais la leçon importante à retenir est que vous pouvez accéder à n'importe quel paramètre défini par l'utilisateur dans le code de votre fonction et l'utiliser comme une valeur ordinaire dans la logique de la fonction. En guise de clin d'œil à cette fonctionnalité, ajoutez le journal suivant : pour démontrer que vous accédez bien à la valeur Définie par l'utilisateur:

    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. Normalement, les utilisateurs sont invités à fournir des valeurs pour les paramètres lorsqu'ils installent une extension. Lorsque vous utilisez l'émulateur pour les tests et le développement, Cependant, vous ignorez le processus d'installation et fournissez plutôt des valeurs pour les paramètres définis par l'utilisateur à l'aide d'un fichier env.

    Ouvrez functions/integration-tests/extensions/rtdb-uppercase-messages.env et remplacez la définition de GREETING par ce qui suit :

    MESSAGE_PATH=/msgs/{pushId}/original
    

    Notez que le chemin d'accès ci-dessus est différent du chemin par défaut et de la section que vous avez défini précédemment, c'est juste pour vous prouver à vous-même quand vous essayez votre extension mise à jour pour que votre définition soit prise en compte.

  6. Redémarrez maintenant l'émulateur et consultez à nouveau l'interface utilisateur de l'émulateur de base de données.

    Modifiez le nœud racine de la base de données à l'aide du chemin d'accès que vous avez défini ci-dessus:

    • Champ : msgs
    • Type : json
    • Valeur : {"11": {"original": "recipe"}}

    Lorsque vous enregistrez les modifications apportées à la base de données, le paramètre makeuppercase de l'extension doit se déclencher comme précédemment, mais afficher aussi la valeur défini par l'utilisateur au journal de la console.

7. Fournir des hooks d'événement pour la logique définie par l'utilisateur

En tant qu'auteur d'extensions, vous avez déjà vu comment un produit Firebase peut déclencher votre logique fournie par l'extension: la création d'enregistrements dans Realtime Database déclenche votre fonction makeuppercase. Votre extension peut avoir une version votre relation avec les utilisateurs qui installent votre extension: votre extension peut de déclenchement définie par l'utilisateur.

Une extension peut fournir des hooks synchrones, des hooks asynchrones ou les deux. Les hooks synchrones permettent aux utilisateurs d'effectuer des tâches qui bloquent l'une des fonctions de l'extension. Cela peut être utile, par exemple, pour fournir aux utilisateurs une manière d'effectuer un prétraitement personnalisé avant qu'une extension ne fasse son travail.

Dans ce guide, vous allez ajouter un hook asynchrone à votre extension, qui permettent aux utilisateurs de définir leurs propres étapes de traitement à exécuter après l'extension. écrit le message en majuscules dans Realtime Database. Les hooks asynchrones utilisent Eventarc pour déclencher des fonctions définies par l'utilisateur. Les extensions déclarent les types d'événements qu'elles émettent. Lorsque les utilisateurs installent l'extension, ils choisissent les types d'événements qui les intéressent. S'il choisit au moins un événement, Firebase provisionnera un canal Eventarc pour l'extension lors du processus d'installation. Utilisateurs peuvent ensuite déployer leurs propres fonctions Cloud qui écoutent ce canal lorsque l'extension publie de nouveaux événements.

Pour ajouter un hook asynchrone, procédez comme suit :

  1. Dans le fichier extension.yaml, ajoutez la section suivante, qui déclare le Type d'événement émis par l'extension:

    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.
    

    Les types d'événements doivent être uniques pour garantir l'unicité, toujours vos événements en utilisant le format suivant: <publisher-id>.<extension-id>.<version>.<description> (Vous ne disposez référence éditeur, utilisez simplement test-publisher pour le moment.)

  2. À la fin de la fonction makeuppercase, ajoutez du code qui publie une du type que vous venez de déclarer:

    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,
        },
      });
    

    Cet exemple de code tire parti du fait que EVENTARC_CHANNEL est définie uniquement lorsque l'utilisateur a activé au moins type d'événement. Si EVENTARC_CHANNEL n'est pas défini, le code ne tente pas de publier des événements.

    Vous pouvez joindre des informations supplémentaires à un événement Eventarc. Dans l'exemple ci-dessus, l'événement comporte un champ subject contenant une référence à la valeur nouvellement créée et une charge utile data contenant les valeurs d'origine et en majuscules. Les fonctions définies par l'utilisateur qui déclenchent l'événement utiliser ces informations.

  3. Normalement, les environnements EVENTARC_CHANNEL et EXT_SELECTED_EVENTS sont définies en fonction des options sélectionnées par l'utilisateur l'installation. Pour effectuer des tests avec l'émulateur, définissez manuellement ces variables dans le fichier rtdb-uppercase-messages.env:

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

À ce stade, vous avez terminé les étapes nécessaires pour ajouter un événement asynchrone. accrochez votre extension.

Pour essayer cette nouvelle fonctionnalité que vous venez d'implémenter, dans les prochaines par défaut, supposons que vous ayez le rôle d'un utilisateur qui installe l'extension:

  1. À partir du répertoire functions/integration-tests, initialisez une nouvelle instance projet:

    firebase init functions

    Lorsque vous y êtes invité, refusez de configurer un projet par défaut, puis sélectionnez JavaScript en tant que le langage Cloud Functions et installez les dépendances requises. Ce "project" représente le projet d'un utilisateur sur lequel votre extension est installée.

  2. Modifiez integration-tests/functions/index.js et collez le code suivant:

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

    Voici un exemple de fonction de post-traitement qu'un utilisateur peut écrire. Dans ce la fonction écoute si l'extension publie un événement complete, Lorsqu'elle est déclenchée, trois points d'exclamation sont ajoutés .

  3. Redémarrez l'émulateur. L'émulateur charge les fonctions de l'extension en tant que ainsi que la fonction de post-traitement, définis.

  4. Accédez à l'interface utilisateur de l'émulateur de base de données et modifiez le nœud racine de la base de données à l'aide de le chemin d'accès que vous avez défini ci-dessus:

    • Champ : msgs
    • Type : json
    • Valeur : {"11": {"original": "recipe"}}

    Lorsque vous enregistrez les modifications apportées à la base de données, le paramètre makeuppercase de l'extension et la fonction extraemphasis de l'utilisateur doivent se déclencher dans l'ordre. ce qui fait que le champ upper obtient la valeur RECIPE!!!.

8. Ajouter des gestionnaires d'événements de cycle de vie

L'extension que vous avez écrite traite les messages à mesure qu'ils sont créés. Mais que se passe-t-il si vos utilisateurs disposent déjà d'une base de données de messages lorsqu'ils installent l'extension ? Les extensions Firebase disposent d'une fonctionnalité appelée hooks d'événement de cycle de vie que vous pouvez utiliser pour déclencher des actions lorsque votre extension est installée, mise à jour ou reconfigurée. Dans cette section, vous allez utiliser des hooks d'événement de cycle de vie pour remplir une la base de données de messages existante du projet avec des messages en majuscules lorsqu'un utilisateur installe votre extension.

Les extensions Firebase utilisent Cloud Tasks pour exécuter vos gestionnaires d'événements de cycle de vie. Toi définir des gestionnaires d'événements à l'aide de Cloud Functions ; chaque fois qu'une instance atteint l'un des événements de cycle de vie acceptés, si vous avez défini il ajoute le gestionnaire à une file d'attente Cloud Tasks. Cloud Tasks exécute ensuite le gestionnaire de manière asynchrone. Lorsqu'un gestionnaire d'événements de cycle de vie est en cours d'exécution, la console Firebase indique à l'utilisateur que l'instance de l'extension tâche de traitement en cours. C'est à votre fonction de gestionnaire de signaler l'état et l'achèvement de la tâche à l'utilisateur.

Pour ajouter un gestionnaire d'événements de cycle de vie qui remplit les messages existants, exécutez la suivantes:

  1. Définissez une nouvelle fonction Cloud déclenchée par des événements de file d'attente de tâches :

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

    Notez que la fonction ne traite que quelques enregistrements avant de s'ajouter elle-même. à la file d'attente de tâches. Il s'agit d'une stratégie couramment utilisée des tâches qui ne peuvent pas s'achever dans le délai imparti Fonction. Comme vous ne pouvez pas prévoir le nombre de messages qu'un utilisateur dans sa base de données lorsqu'il installe votre extension, cette stratégie est adapté.

  2. Dans le fichier extension.yaml, déclarez votre fonction de remplissage en tant qu'extension ressource ayant la propriété taskQueueTrigger:

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

    Déclarez ensuite la fonction en tant que gestionnaire pour le cycle de vie de onInstall. événement:

    lifecycleEvents:
      onInstall:
        function: backfilldata
        processingMessage: Uppercasing existing messages
    
  3. Bien qu'il soit utile de remplir des messages existants, l'extension peut sans quoi elles fonctionnent. Dans de telles situations, vous devez faire en sorte que les gestionnaires d'événements de cycle de vie sont facultatifs.

    Pour ce faire, ajoutez un paramètre à 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
    

    Ensuite, au début de la fonction de remplissage, vérifiez la valeur du paramètre DO_BACKFILL et quitter plus tôt s'il n'est pas défini:

    functions/index.js

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

Avec les modifications ci-dessus, l'extension convertit les messages existants en en majuscules lorsqu'il est installé.

Jusqu'ici, vous avez utilisé l'émulateur d'extension pour développer votre extension et tester les modifications en cours. Toutefois, l'émulateur d'extension ignore l'installation Par conséquent, pour tester votre gestionnaire d'événements onInstall, vous devez installer d’extension dans un projet réel. C'est tout aussi bien, puisqu'avec l'ajout de cette fonctionnalité de remplissage automatique, l'extension du tutoriel est maintenant complète.

9. Déployer dans un projet Firebase réel

Bien que l'émulateur d'extensions soit un excellent outil pour effectuer rapidement des itérations sur une pendant le développement, vous aurez envie de l'essayer projet.

Pour ce faire, commencez par configurer un nouveau projet avec certains services activés :

  1. Dans la console Firebase, ajoutez un projet.
  2. Mettre à niveau votre projet au forfait Blaze avec paiement à l'usage. Cloud Functions for Firebase nécessite que votre projet dispose d'un compte de facturation. Vous avez donc également besoin d'un compte de facturation pour installer une extension.
  3. Dans votre nouveau projet, activez Real-time Database.
  4. Puisque vous souhaitez tester la capacité de votre extension à remplir les données existantes l'installation, importez des exemples de données dans votre instance de base de données en temps réel:
    1. Téléchargez des données RTDB source.
    2. Sur la page "Realtime Database" (Base de données en temps réel) de la console Firebase, cliquez sur (Plus) > Importer un fichier JSON, puis sélectionnez le fichier que vous venez de télécharger.
  5. Pour permettre à la fonction de remplissage d'utiliser la méthode orderByChild, configurez la base de données pour indexer les messages sur la valeur de upper:

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

Installez maintenant votre extension à partir d'une source locale dans le nouveau projet:

  1. Créez un répertoire pour votre projet Firebase :

    mkdir ~/extensions-live-test && cd ~/extensions-live-test
    
  2. Initialisez un projet Firebase dans le répertoire de travail:

    firebase init database

    Lorsque vous y êtes invité, sélectionnez le projet que vous venez de créer.

  3. Installez l'extension dans votre projet Firebase local:

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

    Vous pouvez voir ici à quoi ressemble l'expérience utilisateur lors de l'installation d'un à l'aide de la CLI Firebase. Veillez à sélectionner "Oui" lorsque de configuration Terraform vous demande si vous souhaitez remplir votre base de données existante.

    Une fois les options de configuration sélectionnées, la CLI Firebase enregistre votre dans le répertoire extensions et enregistrer la source de l'extension dans le fichier firebase.json. Collectivement, ces deux enregistrements appelé fichier manifeste des extensions. Les utilisateurs peuvent utiliser le fichier manifeste pour enregistrer la configuration des extensions et la déployer dans différents projets.

  4. Déployez la configuration de votre extension dans votre projet en ligne :

    firebase deploy --only extensions

Si tout se passe comme prévu, la CLI Firebase devrait importer votre extension dans votre projet et l'installer. Une fois l'installation terminée, la tâche de remplissage s'exécute et, dans après quelques minutes, votre base de données sera mise à jour avec des messages en majuscules. Ajouter de nouveaux nœuds à la base de données des messages et s'assurer que l'extension fonctionne également pour les nouveaux messages.

10. Rédiger de la documentation

Avant de partager votre extension avec des utilisateurs, assurez-vous d'en fournir suffisamment la documentation pour qu'ils réussissent.

Lorsque vous avez initialisé le projet d'extension, la CLI Firebase a créé un bouchon de la documentation minimale requise. Mettez à jour ces fichiers pour reflètent l'extension que vous avez créée.

extension.yaml

Vous avez déjà mis à jour ce fichier lorsque vous avez développé cette extension. Vous n'avez donc pas besoin d'apporter d'autres modifications pour le moment.

Cependant, ne négligez pas l'importance de la documentation contenue dans ce . En plus des informations d'identification cruciales de l'extension : nom, description, auteur, emplacement du dépôt officiel (extension.yaml) contient de la documentation destinée à l'utilisateur pour chaque ressource et qu'il peut configurer . Ces informations sont visibles par les utilisateurs dans la console Firebase, Extensions Hub et CLI Firebase.

PREINSTALL.md

Dans ce fichier, fournissez les informations dont l'utilisateur a besoin pour installer votre l'extension: décrire brièvement ce que fait l'extension, expliquer les conditions préalables, et de fournir à l'utilisateur des informations sur les implications de facturation de l'installation . Si vous disposez d'un site Web contenant des informations supplémentaires, il s'agit également au bon endroit pour le relier.

Le texte de ce fichier est visible par l'utilisateur dans le Hub des extensions et par firebase ext:info.

Voici un exemple de fichier 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

Ce fichier contient des informations utiles pour les utilisateurs après l'installation de votre extension : par exemple, les étapes de configuration ultérieures, un exemple de l'extension en action, etc.

Le contenu de POSTINSTALL.md s'affiche dans la console Firebase une fois une extension configurée et installée. Vous pouvez référencer des paramètres utilisateur et elles seront remplacées par les valeurs configurées.

Voici un exemple de fichier post-installation pour l'extension du tutoriel :

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

Vous devez également documenter les modifications que vous apportez entre les versions d'une extension. dans le fichier CHANGELOG.md.

Étant donné que l'exemple d'extension n'a jamais été publié, l'historique des modifications une seule entrée:

## Version 0.0.1

Initial release of the _Convert messages to upper case_ extension.

README.md

La plupart des extensions fournissent également un fichier README à l’intention des utilisateurs dans le dépôt de l'extension. vous pouvez écrire ce fichier à la main ou générer un fichier de lecture à l'aide de la commande.

Pour les besoins de ce guide, ignorez l’écriture d’un fichier README.

Documentation supplémentaire

La documentation discutée ci-dessus est l'ensemble minimal de documents que vous devez fournir aux utilisateurs. De nombreuses extensions nécessitent une documentation plus détaillée pour que les utilisateurs les utiliser avec succès. Dans ce cas, vous devez écrire de la documentation et de l'héberger à un endroit vers lequel vous pouvez diriger les utilisateurs.

Pour les besoins de ce guide, ne rédigez pas de documentation plus approfondie.

11. Publier sur Extensions Hub

Maintenant que le code de votre extension est terminé et documenté, vous pouvez la partager avec le monde entier sur le Hub des extensions. Mais comme il ne s'agit que d'un tutoriel, le faire réellement. Commencez à créer votre propre extension en utilisant que nous avons vu ici et dans le reste de la documentation sur les extensions Firebase pour les éditeurs, et en examinant la source des extensions officielles, écrites dans Firebase.

Lorsque vous êtes prêt à publier votre travail sur le Hub des extensions, voici la marche à suivre comme suit:

  1. Si vous publiez votre première extension, S'enregistrer en tant qu'éditeur d'extensions Quand ? vous vous inscrivez en tant qu'éditeur d'extensions, vous créez une référence éditeur les utilisateurs vous identifient rapidement en tant qu'auteur de vos extensions.
  2. Hébergez le code source de votre extension dans un emplacement vérifiable publiquement. Quand ? si votre code est disponible à partir d'une source vérifiable, Firebase peut publier votre l'extension directement depuis cet emplacement. Cela vous permet de vous assurer que en publiant la version actuellement publiée de votre extension en leur permettant d'examiner le code qu'ils installent dans leurs projets.

    Actuellement, cela signifie rendre votre extension disponible dans un un dépôt de clés.

  3. Importez votre extension sur le Hub des extensions à l'aide de l'firebase ext:dev:upload. .

  4. Accédez au tableau de bord de l'éditeur dans la console Firebase, recherchez l'extension que vous venez d'importer, puis cliquez sur "Publier sur le Hub des extensions". Cela demande un ce qui peut prendre quelques jours. En cas d'approbation, le sera publiée sur le Hub des extensions. En cas de refus, vous recevrez un un message expliquant la raison ; vous pouvez ensuite résoudre les problèmes signalés et à renvoyer pour examen.