Iniziare a creare un'estensione

Questa pagina illustra i passaggi necessari per creare una semplice campagna Firebase Estensione, che puoi installare nei tuoi progetti o condividere con altri. Questo un semplice esempio di estensione Firebase osserva che il tuo Realtime Database e convertirli in lettere maiuscole.

1. Configura il tuo ambiente e inizializza un progetto

Per poter iniziare a creare un'estensione, devi prima configurare una build dell'ambiente con gli strumenti richiesti.

  1. Installa Node.js 16 o versioni successive. Un modo per installare Node è utilizzare nvm (o nvm-windows).

  2. Installa o esegui l'aggiornamento alla versione più recente dell'interfaccia a riga di comando di Firebase. A installa o aggiorna utilizzando npm, esegui questo comando:

    npm install -g firebase-tools

Ora utilizza l'interfaccia a riga di comando di Firebase per inizializzare un nuovo progetto di estensioni:

  1. Crea una directory per l'estensione e al suo interno cd:

    mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
  2. Esegui il comando ext:dev:init dell'interfaccia a riga di comando di Firebase:

    firebase ext:dev:init

    Quando richiesto, scegli JavaScript come linguaggio per le funzioni (ma tieni presente che puoi anche usare TypeScript quando sviluppi la tua estensione). quando ti viene chiesto di installare le dipendenze, rispondi "yes". (Accetta i valori predefiniti per qualsiasi altra opzione.) Questo comando configura una base di codice di base per una nuova estensione, da cui puoi iniziare a svilupparla.

2. Prova l'estensione di esempio usando l'emulatore

Quando l'interfaccia a riga di comando di Firebase ha inizializzato la nuova directory delle estensioni, ha creato un di semplice funzione di esempio e una directory integration-tests che contiene necessari per eseguire un'estensione utilizzando la suite di emulatori Firebase.

Prova a eseguire l'estensione di esempio nell'emulatore:

  1. Passa alla directory integration-tests:

    cd functions/integration-tests
  2. Avvia l'emulatore con un progetto demo:

    firebase emulators:start --project=demo-test

    L'emulatore carica l'estensione in un file "fittizio" predefinito progetto (demo-test). Finora, l'estensione è composta da un singolo trigger HTTP funzione, greetTheWorld, che restituisce "hello world" messaggio quando o rifiutano le richieste in base all'organizzazione a cui si accede.

  3. Con l'emulatore ancora in esecuzione, prova il greetTheWorld dell'estensione visitando l'URL stampato all'avvio.

    Il browser visualizza il messaggio "Hello World da greet-the-world".

  4. Il codice sorgente di questa funzione si trova nel file functions dell'estensione . Apri il codice sorgente nell'editor o nell'IDE di tua scelta:

    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. Mentre è in esecuzione, l'emulatore ricarica automaticamente le modifiche al codice Functions. Prova ad apportare una piccola modifica Funzione greetTheWorld:

    functions/index.js

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

    Salva le modifiche. L'emulatore ricarica il codice e ora, visita l'URL della funzione, vedrai il messaggio di benvenuto aggiornato.

3. Aggiungi informazioni di base a extensions.yaml

Ora che hai configurato un ambiente di sviluppo e stai eseguendo un emulatore di estensioni, puoi iniziare a scrivere la tua estensione.

Come primo passaggio, modifica i metadati dell'estensione predefiniti in modo che riflettano che vuoi scrivere al posto di greet-the-world. Questi metadati sono archiviati nel file extension.yaml.

  1. Apri extension.yaml nell'editor e sostituisci l'intero contenuto del con il seguente codice:

    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
    

    Tieni presente la convenzione di denominazione utilizzata nel campo name: Firebase ufficiale le estensioni sono denominate con un prefisso che indica il prodotto Firebase principale su cui opera l'estensione, seguita da una descrizione di ciò che l'estensione encoder-decoder. Devi utilizzare la stessa convenzione nelle tue estensioni.

  2. Poiché hai cambiato il nome dell'estensione, dovresti anche aggiornare i dell'emulatore con il nuovo nome:

    1. In functions/integration-tests/firebase.json, cambia greet-the-world a rtdb-uppercase-messages.
    2. Rinomina functions/integration-tests/extensions/greet-the-world.env in functions/integration-tests/extensions/rtdb-uppercase-messages.env.

Nel codice dell'estensione sono ancora presenti alcuni resti dell'estensione greet-the-world, ma per il momento non farne caso. Li aggiornerai nei prossimi sezioni.

4. Scrivi una funzione Cloud Functions e dichiarala come risorsa di estensione

Ora puoi iniziare a scrivere del codice. In questo passaggio scriverai un codice Cloud Funzione che esegue l'attività principale dell'estensione, ovvero per osservare i messaggi nel Realtime Database e convertirli in lettere maiuscole.

  1. Apri il codice sorgente delle funzioni dell'estensione (nella directory functions dell'estensione) nell'editor o nell'IDE che preferisci. Sostituisci la relativa con i seguenti contenuti:

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

    La vecchia funzione, che hai sostituito, era una funzione attivata da HTTP, che eseguito quando è stato eseguito l'accesso a un endpoint HTTP. La nuova funzione viene attivata gli eventi del database in tempo reale: rileva i nuovi elementi in un determinato percorso e, quando ne viene rilevata una, ne riscrive la versione maiuscola al database.

    A proposito, questo nuovo file utilizza la sintassi del modulo ECMAScript (import e export) anziché CommonJS (require). Per utilizzare i moduli ES in Node, specifica "type": "module" in functions/package.json:

    {
      "name": "rtdb-uppercase-messages",
      "main": "index.js",
      "type": "module",
      
    }
    
  2. Ogni funzione nell'estensione deve essere dichiarata nel extension.yaml . L'estensione di esempio ha dichiarato greetTheWorld come l'unica estensione funzione Cloud Functions; dopo averlo sostituito con makeuppercase, puoi anche deve aggiornare la relativa dichiarazione.

    Apri extension.yaml e aggiungi un campo 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. Poiché l'estensione ora utilizza Realtime Database come trigger, devi per aggiornare la configurazione dell'emulatore in modo da eseguirlo insieme Emulatore Cloud Functions:

    1. Se l'emulatore è ancora in esecuzione, interrompilo premendo Ctrl-C.

    2. Dalla directory functions/integration-tests, esegui questo comando :

      firebase init emulators

      Quando richiesto, salta la configurazione di un progetto predefinito, quindi seleziona le funzioni e emulatori di database. Accetta le porte predefinite e consenti allo strumento di configurazione di scaricare i file richiesti.

    3. Riavvia l'emulatore:

      firebase emulators:start --project=demo-test
  4. Prova l'estensione aggiornata:

    1. Apri l'interfaccia utente dell'emulatore di database utilizzando il link stampato dall'emulatore da quando l'hai avviata.

    2. Modifica il nodo principale del database:

      • Campo: messages
      • Tipo: json
      • Valore: {"11": {"original": "recipe"}}

      Se tutto è configurato correttamente, quando salvi le modifiche al database, la funzione makeuppercase dell'estensione deve attivarsi e aggiungere un asset secondario record nel messaggio 11 con il contenuto "upper": "RECIPE". Dai un'occhiata nei log e nelle schede di database dell'interfaccia utente dell'emulatore per confermare i risultati attesi.

    3. Prova ad aggiungere altri elementi secondari al nodo messages ({"original":"any text"}). Ogni volta che aggiungi un nuovo record, l'estensione deve aggiungere un campo uppercase contenente i contenuti in maiuscolo del campo original.

Ora hai un'estensione completa, ma semplice, che opera su un database RTDB in esecuzione in un'istanza Compute Engine. Nelle sezioni che seguono, perfezionerai questa estensione con alcuni funzionalità aggiuntive. Quindi, puoi preparare l'estensione per la distribuzione su e infine scoprire come pubblicare le tue estensioni nell'hub delle estensioni.

5. Dichiara le API e i ruoli

Firebase concede a ciascuna istanza di un'estensione installata un accesso limitato al utilizzando un account di servizio per istanza. Ogni account dispone dell'insieme minimo di autorizzazioni necessarie per il funzionamento. Per questo motivo, devi dichiarare esplicitamente i ruoli IAM richiesti dalla tua estensione. Quando gli utenti installano la tua estensione, Firebase crea un account di servizio a cui sono stati concessi questi ruoli e lo utilizza per eseguire l'estensione.

Non è necessario dichiarare i ruoli per attivare gli eventi di un prodotto, devi dichiarare un ruolo per interagire in altro modo. Poiché la funzione che hai aggiunto nell'ultimo passaggio scrive nel database in tempo reale, devi aggiungere la seguente dichiarazione a extension.yaml:

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

Allo stesso modo, dichiari le API di Google utilizzate da un'estensione nel campo apis . Quando gli utenti installano la tua estensione, verrà chiesto se vogliono per abilitare automaticamente queste API per il progetto. Di solito sono disponibili solo per le API di Google non Firebase e non sono necessarie per questa guida.

6. Definire i parametri configurabili dall'utente

La funzione creata negli ultimi due passaggi ha monitorato una posizione RTDB specifica per i messaggi in arrivo. A volte, monitorare una località specifica è proprio ciò che vuoi, ad esempio quando la tua estensione opera su una struttura di database che utilizzi esclusivamente per la tua estensione. Tuttavia, nella maggior parte dei casi è consigliabile configura questi valori dagli utenti che installano la tua estensione nei loro in modo programmatico a gestire i progetti. In questo modo, gli utenti possono utilizzare la tua estensione per lavorare con la configurazione del database esistente.

Rendi il percorso che l'estensione controlla per i nuovi messaggi configurabili dall'utente:

  1. Nel file extension.yaml, aggiungi una sezione 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
    

    Definisce un nuovo parametro di stringa che agli utenti verrà chiesto di impostare quando per installare l'estensione.

  2. Sempre nel file extension.yaml, torna al tuo makeuppercase e modifica il campo resource nel seguente modo:

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

    Il token ${param:MESSAGE_PATH} è un riferimento al parametro che hai appena definito. Quando l'estensione viene eseguita, questo token verrà sostituito dal valore che l'utente ha configurato per quel parametro, con il risultato che la funzione makeuppercase ascolterà il percorso specificato dall'utente. Puoi utilizzare questa sintassi per fare riferimento a qualsiasi parametro definito dall'utente ovunque in extension.yaml (e in POSTINSTALL.md; di seguito sono riportate ulteriori informazioni).

  3. Puoi anche accedere ai parametri definiti dall'utente dal codice della funzione.

    Nella funzione che hai scritto nella sezione precedente, hai impostato come hardcoded il percorso cerca le modifiche. Modifica la definizione dell'attivatore in modo che faccia riferimento definito dall'utente:

    functions/index.js

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

    Tieni presente che nelle estensioni di Firebase questa modifica è esclusivamente per il gusto di documentazione: quando viene eseguito il deployment di una funzione Cloud Functions come parte di un'estensione, utilizza la definizione dell'attivatore del file extension.yaml e ignora il specificato nella definizione della funzione. Tuttavia, è una buona idea per documentare nel codice la provenienza di questo valore.

  4. Potrebbe essere deludente apportare una modifica al codice senza runtime ma la lezione importante da imparare è che si può accedere a qualsiasi parametro definito dall'utente nel codice della funzione e utilizzarlo come valore ordinario nella logica della funzione. Come cenno a questa funzionalità, aggiungi il seguente log per dimostrare che si sta accedendo al valore fornito definito dall'utente:

    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. Di solito, agli utenti viene richiesto di fornire i valori dei parametri quando installare un'estensione. Quando usi l'emulatore per i test e lo sviluppo, ma si salta il processo di installazione e vengono forniti valori per i parametri definiti dall'utente utilizzando un file env.

    Apri functions/integration-tests/extensions/rtdb-uppercase-messages.env e sostituisci la definizione di GREETING con la seguente:

    MESSAGE_PATH=/msgs/{pushId}/original
    

    Nota che il percorso riportato sopra è diverso dal percorso predefinito e definito in precedenza; è solo per dimostrare a te stesso quando provi l'estensione aggiornata per rendere effettiva la tua definizione.

  6. Ora riavvia l'emulatore e visita di nuovo la UI dell'emulatore di database.

    Modifica il nodo principale del database utilizzando il percorso definito sopra:

    • Campo: msgs
    • Tipo: json
    • Valore: {"11": {"original": "recipe"}}

    Quando salvi le modifiche al database, il valore makeuppercase dell'estensione dovrebbe attivarsi come in precedenza, ma ora dovrebbe anche stampare il definito dall'utente nel log della console.

7. Fornisci hook di eventi per la logica definita dall'utente

In qualità di autore di un'estensione, hai già visto in che modo un prodotto Firebase può attivare la logica fornita dall'estensione: la creazione di nuovi record in Realtime Database attiva la funzione makeuppercase. L'estensione può avere un comportamento analogo con gli utenti che installano l'estensione: l'estensione può una logica di trigger definita dall'utente.

Un'estensione può fornire hook sincroni, hook asincroni o entrambi. Gli hook sincronizzati offrono agli utenti un modo per eseguire attività che bloccano il completamento una delle funzioni dell'estensione. Ciò può essere utile, ad esempio, per offrire agli utenti un modo per eseguire la preelaborazione personalizzata prima che un'estensione esegua la sua operazione.

In questa guida, aggiungerai un hook asincrono alla tua estensione, che Consenti agli utenti di definire le proprie fasi di elaborazione da eseguire dopo l'estensione scrive il messaggio maiuscolo in Realtime Database. Gli hook asincroni utilizzano Eventarc per attivare a funzioni definite dall'utente. Le estensioni dichiarano i tipi di eventi che emettono. Quando gli utenti installano l'estensione, scelgono di quali tipi di eventi che ti interessa. Se scelgono almeno un evento, Firebase eseguirà il provisioning Canale Eventarc per l'estensione nell'ambito del processo di installazione. Gli utenti possono quindi eseguire il deployment delle proprie funzioni cloud che ascoltano quel canale e si attivano quando l'estensione pubblica nuovi eventi.

Per aggiungere un hook asincrono:

  1. Nel file extension.yaml, aggiungi la seguente sezione, in cui viene dichiarata la un tipo di evento emesso dall'estensione:

    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.
    

    I tipi di eventi devono essere universalmente univoci. Per garantire l'unicità, assegna sempre ai tuoi eventi un nome utilizzando il seguente formato: <publisher-id>.<extension-id>.<version>.<description>. (Non disponi di un ID publisher, quindi per ora utilizza solo test-publisher.)

  2. Al termine della funzione makeuppercase, aggiungi del codice che pubblichi un del tipo appena dichiarato:

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

    Questo codice di esempio sfrutta il fatto che EVENTARC_CHANNEL una variabile di ambiente viene definita solo quando l'utente ha attivato almeno una tipo di evento. Se EVENTARC_CHANNEL non viene definito, il codice non tenta per pubblicare eventi.

    Puoi collegare informazioni aggiuntive a un evento Eventarc. Nell'esempio precedente, l'evento ha un campo subject che contiene un riferimento appena creato e un payload data che contiene i dati in maiuscolo. Le funzioni definite dall'utente che attivano l'evento possono utilizzare queste informazioni.

  3. Solitamente, gli ambienti EVENTARC_CHANNEL e EXT_SELECTED_EVENTS vengono definite in base alle opzioni selezionate dall'utente durante dell'installazione. Per i test con l'emulatore, definisci manualmente queste variabili nel file rtdb-uppercase-messages.env:

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

A questo punto, hai completato i passaggi necessari per aggiungere un evento asincrono. hook all'estensione.

Per provare questa nuova funzionalità che avete appena implementato, nei prossimi passaggi, assume il ruolo di un utente che installa l'estensione:

  1. Dalla directory functions/integration-tests, inizializza un nuovo Firebase progetto:

    firebase init functions

    Quando richiesto, rifiuta di configurare un progetto predefinito, seleziona JavaScript come il linguaggio Cloud Functions e installa le dipendenze richieste. Questo rappresenta il progetto di un utente in cui è installata l'estensione.

  2. Modifica integration-tests/functions/index.js e incolla il seguente codice:

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

    Questo è un esempio di funzione di post-elaborazione che un utente potrebbe scrivere. In questo caso, la funzione ascolta l'evento complete pubblicato dall'estensione e, quando viene attivata, aggiunge tre punti esclamativi al messaggio in maiuscolo.

  3. Riavvia l'emulatore. L'emulatore caricherà le funzioni dell'estensione come così come la funzione di post-elaborazione "utente" definito.

  4. Visita la UI dell'emulatore di database e modifica il nodo radice del database utilizzando il percorso definito sopra:

    • Campo:msgs
    • Tipo: json
    • Valore: {"11": {"original": "recipe"}}

    Quando salvi le modifiche al database, il valore makeuppercase dell'estensione e la funzione extraemphasis dell'utente deve attivarsi in sequenza, di conseguenza il campo upper ottiene il valore RECIPE!!!.

8. Aggiungi gestori di eventi del ciclo di vita

L'estensione che hai scritto finora elabora i messaggi man mano che vengono creati. Ma cosa succede se i tuoi utenti hanno già un database di messaggi quando installano estensione? Firebase Extensions include una funzionalità chiamata hook degli eventi del ciclo di vita che che puoi utilizzare per attivare azioni quando l'estensione viene installata, aggiornata riconfigurate. In questa sezione, utilizzerai gli hook degli eventi del ciclo di vita per eseguire il backfill di un database di messaggi esistente del progetto con messaggi in maiuscolo quando un utente installa l'estensione.

Firebase Extensions utilizza Cloud Tasks per eseguire i gestori di eventi del ciclo di vita. Tu definire gestori di eventi utilizzando Cloud Functions; ogni volta che viene eseguita un'istanza raggiunge uno degli eventi del ciclo di vita supportati, se hai definito , lo aggiungerà a una coda di Cloud Tasks. A questo punto, Cloud Tasks eseguire il gestore in modo asincrono. Mentre è in esecuzione un gestore di eventi del ciclo di vita, la console Firebase segnala all'utente che l'istanza dell'estensione ha un è in corso un'attività di elaborazione. Sta alla tua funzione di gestore segnalare che è in corso e il completamento dell'attività.

Per aggiungere un gestore degli eventi del ciclo di vita che esegue il backfill dei messaggi esistenti:

  1. Definisci una nuova funzione Cloud Functions che viene attivata dagli eventi delle code di attività:

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

    Nota che la funzione elabora solo alcuni record prima di aggiungersi alla coda delle attività. Questa è una strategia di uso comune per di attività che non possono essere completate entro la finestra di timeout di un cloud Funzione. Poiché non puoi prevedere quanti messaggi un utente potrebbe già avere nel proprio database quando installa la tua estensione, questa strategia è adatta.

  2. Nel file extension.yaml, dichiara la funzione di backfill come estensione risorsa con la proprietà taskQueueTrigger:

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

    Poi dichiara la funzione come gestore per il ciclo di vita onInstall dell'evento:

    lifecycleEvents:
      onInstall:
        function: backfilldata
        processingMessage: Uppercasing existing messages
    
  3. Sebbene il backfill dei messaggi esistenti sia un'opzione utile, l'estensione potrebbe funzionare anche senza. In situazioni come questa, devi eseguire i gestori di eventi del ciclo di vita sono facoltativi.

    Per farlo, aggiungi un nuovo parametro a 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
    

    Quindi, all'inizio della funzione di backfill, controlla il valore del parametro DO_BACKFILL ed esci in anticipo se non è impostato:

    functions/index.js

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

Con le modifiche precedenti, l'estensione ora convertirà i messaggi esistenti in in maiuscolo quando è installato.

Fino a questo punto, hai utilizzato l'emulatore di estensioni per sviluppare l'estensione e testare le modifiche in corso. Tuttavia, l'emulatore dell'estensione ignora l'installazione pertanto per testare il gestore di eventi onInstall dovrai installare in un progetto reale. È altrettanto bene, però, dato che con l'aggiunta di questa funzione di backfill automatico, l'estensione per il tutorial è ora completa di codice.

9. Esegui il deployment in un progetto Firebase reale

Sebbene l'emulatore delle estensioni sia un ottimo strumento per eseguire rapidamente l'iterazione durante lo sviluppo. A un certo punto vorrai provarla progetto.

Per farlo, devi prima configurare un nuovo progetto con alcuni servizi abilitati:

  1. Nella Console Firebase, aggiungi un nuovo progetto.
  2. Esegui l'upgrade del progetto al piano Blaze con pagamento a consumo. Cloud Functions per Firebase richiede che il progetto abbia un account di fatturazione, quindi devi disporre di un account di fatturazione anche per installare un'estensione.
  3. Nel nuovo progetto, abilita Real-time Database.
  4. Poiché vuoi verificare la capacità della tua estensione di eseguire il backfill dei dati esistenti su importa alcuni dati di esempio nella tua istanza di database in tempo reale:
    1. Scarica alcuni dati RTDB iniziali.
    2. Nella pagina Database in tempo reale della console Firebase, fai clic su (Altro) > Importa JSON e seleziona il file che hai appena scaricato.
  5. Per attivare la funzione di backfill in modo da utilizzare il metodo orderByChild, configura il database per indicizzare i messaggi sul valore di upper:

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

Ora installa l'estensione dall'origine locale nel nuovo progetto:

  1. Crea una nuova directory per il progetto Firebase:

    mkdir ~/extensions-live-test && cd ~/extensions-live-test
    
  2. Inizializza un progetto Firebase nella directory di lavoro:

    firebase init database

    Quando richiesto, seleziona il progetto appena creato.

  3. Installa l'estensione nel tuo progetto Firebase locale:

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

    Qui puoi vedere come funziona l'esperienza utente durante l'installazione di un'estensione utilizzando lo strumento Firebase CLI. Assicurati di selezionare "Sì". quando di configurazione ti chiede se vuoi eseguire il backfill del database esistente.

    Dopo aver selezionato le opzioni di configurazione, l'interfaccia a riga di comando di Firebase salverà configurazione nella directory extensions e registra l'origine dell'estensione posizione nel file firebase.json. Collettivamente, questi due record chiamato manifest delle estensioni. Gli utenti possono utilizzare il file manifest per salvare configurazione delle estensioni di rete ed eseguirne il deployment in diversi progetti.

  4. Esegui il deployment della configurazione dell'estensione nel progetto pubblicato:

    firebase deploy --only extensions

Se tutto funziona correttamente, l'interfaccia a riga di comando di Firebase dovrebbe caricare l'estensione nel progetto e installarlo. Al termine dell'installazione, verrà eseguita l'attività di backfill e, in pochi minuti, il database verrà aggiornato con i messaggi in maiuscolo. Aggiungi qualche nuovi nodi al database dei messaggi e verificare che anche l'estensione funzioni per i nuovi messaggi.

10. Scrivi la documentazione

Prima di condividere la tua estensione con gli utenti, assicurati di fornire un numero sufficiente di video la documentazione necessaria per avere successo.

Quando hai inizializzato il progetto di estensione, lo stub creato dall'interfaccia a riga di comando di Firebase della documentazione minima richiesta. Aggiorna questi file per riflettere l'estensione che hai creato.

estensione.yaml

Hai già aggiornato questo file con l'estensione che hai sviluppato, quindi non devi fare altri aggiornamenti adesso.

Tuttavia, non trascurare l'importanza della documentazione contenuta in questo . Oltre alle informazioni identificative fondamentali dell'estensione, come nome, descrizione, autore, posizione del repository ufficiale: extension.yaml contiene la documentazione rivolta all'utente per ogni risorsa . Queste informazioni vengono mostrate agli utenti nella console Firebase Extensions Hub e l'interfaccia a riga di comando di Firebase.

PREINSTALL.md

In questo file, fornisci le informazioni di cui l'utente ha bisogno prima di installare il tuo estensione: descrivi brevemente lo scopo dell'estensione, spiega i prerequisiti, e fornisci all'utente informazioni sulle implicazioni di fatturazione dell'installazione . Se hai un sito web con ulteriori informazioni, anche questa è una un buon punto di collegamento.

Il testo di questo file viene mostrato all'utente nell'hub delle estensioni e tramite Comando firebase ext:info.

Ecco un esempio di file 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

Questo file contiene informazioni utili per gli utenti dopo che hanno installato correttamente la tua estensione, ad esempio i passaggi di configurazione successivi, un esempio dell'estensione in azione e così via.

I contenuti di POSTINSTALL.md vengono visualizzati nella console Firebase dopo un sia configurata e installata. Puoi fare riferimento ai parametri utente in questo file e verranno sostituiti dai valori configurati.

Ecco un esempio di file post-installazione per l'estensione tutorial:

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

Devi anche documentare le modifiche apportate tra le release di un'estensione nel file CHANGELOG.md.

Poiché l'estensione di esempio non è mai stata pubblicata prima, il log delle modifiche una sola voce:

## Version 0.0.1

Initial release of the _Convert messages to upper case_ extension.

README.md

La maggior parte delle estensioni fornisce inoltre un file readme a vantaggio degli utenti che visitano il repository delle estensioni. puoi scrivere questo file a mano o generare un prompt utilizzando il comando.

Ai fini di questa guida, salta la scrittura di un file readme.

Documentazione aggiuntiva

La documentazione discussa sopra è l'insieme minimo di documentazione che devi fornire agli utenti. Molte estensioni richiedono una documentazione più dettagliata che consente agli utenti a utilizzarli in modo efficace. In questo caso, è necessario scrivere altre documentazione e ospitarla in una posizione a cui indirizzare gli utenti.

Ai fini di questa guida, evita di scrivere una documentazione più esaustiva.

11. Pubblica nell'hub delle estensioni

Ora che il codice dell'estensione è completo e documentato, puoi condividerlo con il mondo su Extensions Hub. Ma poiché questo è solo un tutorial, non farlo davvero. Inizia a scrivere la tua estensione utilizzando ciò che hai che hai appreso qui e nel resto della documentazione di Firebase Extensions per i publisher, ed esaminando la fonte delle estensioni ufficiali scritte da Firebase.

Quando è tutto pronto per pubblicare il tuo lavoro nell'hub delle estensioni, ecco come farai Questo:

  1. Se pubblichi la tua prima estensione, registrarsi come publisher di estensioni. Quando registrati come publisher di estensioni, crei un ID publisher che ti consente gli utenti ti identificano rapidamente come autore delle estensioni.
  2. Ospita il codice sorgente della tua estensione in una posizione verificabile pubblicamente. Quando il codice sia disponibile da una fonte verificabile, Firebase può pubblicare dell'estensione direttamente da questa posizione. In questo modo puoi assicurarti di pubblicando la versione attualmente rilasciata dell'estensione e aiuta gli utenti consentendo loro di esaminare il codice che installano nei propri progetti.

    Attualmente, ciò significa rendere disponibile l'estensione in un GitHub pubblico repository Git.

  3. Carica la tua estensione nell'hub delle estensioni utilizzando firebase ext:dev:upload .

  4. Vai alla dashboard del publisher nella console Firebase e individua l'estensione che hai appena caricato e fai clic su "Pubblica nell'hub di Extensions". Questa operazione richiede una revisione da parte del nostro personale addetto alle revisioni, che può richiedere alcuni giorni. Se approvata, l'estensione verrà pubblicata nell'hub delle estensioni. In caso di rifiuto, riceverai un messaggio che spiega il motivo; puoi quindi risolvere i problemi segnalati per sottoporli nuovamente a revisione.