Questa pagina ti guida attraverso i passaggi necessari per creare una semplice estensione Firebase, che puoi installare nei tuoi progetti o condividere con altri. Questo semplice esempio di estensione Firebase controllerà i messaggi nel tuo database Realtime e li convertirà in maiuscolo.
1. Configura il tuo ambiente e inizializza un progetto
Prima di poter iniziare a creare un'estensione, dovrai configurare un ambiente di creazione con gli strumenti richiesti.
Installa Node.js 16 o versione successiva. Un modo per installare Node è utilizzare nvm (o nvm-windows ).
Installa o aggiorna alla versione più recente della CLI Firebase . Per installare o aggiornare utilizzando
npm
, esegui questo comando:npm install -g firebase-tools
Ora utilizza la CLI Firebase per inizializzare un nuovo progetto di estensione:
Crea una directory per la tua estensione e
cd
:mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
Esegui il comando
ext:dev:init
della CLI di Firebase:firebase ext:dev:init
Quando richiesto, scegli JavaScript come linguaggio per le funzioni (ma tieni presente che puoi anche utilizzare TypeScript quando sviluppi la tua estensione) e, quando ti viene chiesto di installare le dipendenze, rispondi "sì". (Accetta le impostazioni predefinite per qualsiasi altra opzione.) Questo comando imposterà una base di codice scheletro per una nuova estensione, da cui potrai iniziare a sviluppare la tua estensione.
Utilizza firebase ext:dev:init
per inizializzare una nuova directory di estensione.
2. Prova l'estensione di esempio utilizzando l'emulatore
Quando la CLI Firebase ha inizializzato la nuova directory delle estensioni, ha creato una semplice funzione di esempio e una directory di integration-tests
che contiene i file necessari per eseguire un'estensione utilizzando la suite di emulatore Firebase.
Prova a eseguire l'estensione di esempio nell'emulatore:
Passare alla directory
integration-tests
:cd functions/integration-tests
Avvia l'emulatore con un progetto demo:
firebase emulators:start --project=demo-test
L'emulatore carica l'estensione in un progetto "fittizio" predefinito (
demo-test
). L'estensione finora consiste in una singola funzione attivata da HTTP,greetTheWorld
, che restituisce un messaggio "ciao mondo" quando si accede.Con l'emulatore ancora in esecuzione, prova la funzione
greetTheWorld
dell'estensione visitando l'URL stampato all'avvio.Il tuo browser visualizza il messaggio "Hello World da greet-the-world".
Il codice sorgente per questa funzione si trova nella directory delle
functions
dell'estensione. Apri il sorgente nell'editor o nell'IDE di tua scelta:funzioni/index.js
const functions = require("firebase-functions"); exports.greetTheWorld = functions.https.onRequest((req, res) => { // Here we reference a user-provided parameter // (its value is provided by the user during installation) const consumerProvidedGreeting = process.env.GREETING; // And here we reference an auto-populated parameter // (its value is provided by Firebase after installation) const instanceId = process.env.EXT_INSTANCE_ID; const greeting = `${consumerProvidedGreeting} World from ${instanceId}`; res.send(greeting); });
Mentre l'emulatore è in esecuzione, ricaricherà automaticamente tutte le modifiche apportate al codice Funzioni. Prova ad apportare una piccola modifica alla funzione
greetTheWorld
:funzioni/index.js
const greeting = `${consumerProvidedGreeting} everyone, from ${instanceId}`;
Salva le modifiche. L'emulatore ricaricherà il tuo codice e ora, quando visiti l'URL della funzione, vedrai il saluto aggiornato.
L'uso dell'emulatore di estensioni può accelerare lo sviluppo consentendoti di testare e iterare rapidamente il tuo codice.
Maggiori informazioni
Ulteriori informazioni sull'utilizzo dell'emulatore di estensioni .
3. Aggiungi le informazioni di base a extension.yaml
Ora che hai configurato un ambiente di sviluppo e stai eseguendo l'emulatore delle estensioni, puoi iniziare a scrivere la tua estensione.
Come primo passo, modifica i metadati dell'estensione predefinita per riflettere l'estensione che desideri scrivere invece di greet-the-world
. Questi metadati sono archiviati nel file extension.yaml
.
Apri
extension.yaml
nel tuo editor e sostituisci l'intero contenuto del file con quanto segue: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
Nota la convenzione di denominazione utilizzata nel campo
name
: le estensioni ufficiali Firebase sono denominate con un prefisso che indica il prodotto Firebase principale su cui opera l'estensione, seguito da una descrizione di ciò che fa l'estensione. Dovresti usare la stessa convenzione nelle tue estensioni.Dato che hai cambiato il nome della tua estensione, dovresti aggiornare anche la configurazione dell'emulatore con il nuovo nome:
-
functions/integration-tests/firebase.json
, cambiagreet-the-world
inrtdb-uppercase-messages
. -
functions/integration-tests/extensions/greet-the-world.env
functions/integration-tests/extensions/rtdb-uppercase-messages.env
.
-
Nel codice dell'estensione sono ancora presenti alcuni residui dell'estensione greet-the-world
, ma per ora lasciali stare. Li aggiornerai nelle prossime sezioni.
Il file
extension.yaml
contiene metadati sulla tua estensione. Il più elementare di questi metadati è il nome della tua estensione e una descrizione di ciò che fa.Assegna un nome alle estensioni con il seguente formato:
<firebase-product>-<description-of-tasks-performed>
.
Maggiori informazioni
Il riferimento extension.yaml
ha una specifica completa del file; tuttavia, questa documentazione discuterà gli usi specifici di questo file quando è necessario utilizzarlo.
4. Scrivi una funzione Cloud e dichiarala come risorsa di estensione
Ora puoi iniziare a scrivere del codice. In questo passaggio, scriverai una Cloud Function che esegue il compito principale della tua estensione, ovvero controllare i messaggi del tuo Realtime Database e convertirli in maiuscolo.
Apri il sorgente delle funzioni dell'estensione (nella directory delle
functions
dell'estensione) nell'editor o nell'IDE di tua scelta. Sostituisci il suo contenuto con quanto segue:funzioni/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 veniva eseguita quando si accedeva a un endpoint HTTP. La nuova funzione viene attivata da eventi del database in tempo reale: controlla i nuovi elementi in un percorso particolare e, quando ne viene rilevato uno, riscrive la versione maiuscola del valore nel database.
A proposito, questo nuovo file utilizza la sintassi del modulo ECMAScript (
import
edexport
) invece di CommonJS (require
). Per utilizzare i moduli ES in Node, specifica"type": "module"
infunctions/package.json
:{ "name": "rtdb-uppercase-messages", "main": "index.js", "type": "module", … }
Ogni funzione nella tua estensione deve essere dichiarata nel file
extension.yaml
. L'estensione di esempio ha dichiaratogreetTheWorld
come l'unica funzione Cloud dell'estensione; ora che lo hai sostituito conmakeuppercase
, devi aggiornare anche la sua dichiarazione.Apri
extension.yaml
e aggiungi un camporesources
: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"
Poiché la tua estensione ora utilizza Realtime Database come trigger, devi aggiornare la configurazione dell'emulatore per eseguire l'emulatore RTDB insieme all'emulatore Cloud Functions:
Se l'emulatore è ancora in esecuzione, interrompilo premendo Ctrl-C.
Dalla directory
functions/integration-tests
, esegui il comando seguente:firebase init emulators
Quando richiesto, salta la configurazione di un progetto predefinito, quindi seleziona le funzioni e gli emulatori di database. Accetta le porte predefinite e consenti allo strumento di configurazione di scaricare tutti i file richiesti.
Riavviare l'emulatore:
firebase emulators:start --project=demo-test
Prova la tua estensione aggiornata:
Apri l'interfaccia utente dell'emulatore di database utilizzando il collegamento stampato dall'emulatore quando lo hai avviato.
Modifica il nodo radice del database:
- Campo:
messages
- Tipo:
json
- Valore:
{"11": {"original": "recipe"}}
Se tutto è impostato correttamente, quando salvi le modifiche al database, la funzione
makeuppercase
dell'estensione dovrebbe attivarsi e aggiungere un record figlio al messaggio 11 con il contenuto"upper": "RECIPE"
. Dai un'occhiata ai registri e alle schede del database dell'interfaccia utente dell'emulatore per confermare i risultati attesi.- Campo:
Prova ad aggiungere altri figli al nodo
messages
({"original":"any text"}
). Ogni volta che aggiungi un nuovo record, l'estensione dovrebbe aggiungere un campouppercase
contenente il contenuto in maiuscolo del campooriginal
.
Ora disponi di un'estensione completa, anche se semplice, che opera su un'istanza RTDB. Nelle sezioni che seguono, perfezionerai questa estensione con alcune funzionalità aggiuntive. Quindi, avrai l'estensione pronta per essere distribuita ad altri e, infine, imparerai come pubblicare la tua estensione su Extensions Hub.
- Le funzioni che compongono la logica dell'estensione devono essere sia definite come codice Cloud Functions sia dichiarate come risorsa di estensione nel file
extension.yaml
. - Puoi scrivere funzioni che si attivano quando viene effettuato l'accesso agli endpoint HTTP o in risposta a eventi emessi dai prodotti Firebase, dai prodotti Google Cloud e da altre estensioni.
Maggiori informazioni
- Ulteriori informazioni sulla scrittura di Cloud Functions per le estensioni , incluse ulteriori informazioni sugli attivatori di eventi supportati.
- Il riferimento
extension.yaml
ha una specifica completa del file; tuttavia, questa documentazione discuterà gli usi specifici di questo file quando è necessario utilizzarlo. - La documentazione di Cloud Functions for Firebase contiene informazioni generali sull'utilizzo di Cloud Functions, non specifiche per Firebase Extensions.
5. Dichiarare API e ruoli
Firebase concede a ciascuna istanza di un'estensione installata un accesso limitato al progetto e ai relativi dati utilizzando un account di servizio per istanza. Ogni account dispone del set minimo di autorizzazioni necessarie per operare. Per questo motivo, devi dichiarare esplicitamente tutti i ruoli IAM richiesti dalla tua estensione; quando gli utenti installano la tua estensione, Firebase crea un account di servizio con questi ruoli concessi e lo utilizza per eseguire l'estensione.
Non è necessario dichiarare ruoli per attivare gli eventi di un prodotto, ma è necessario dichiarare un ruolo per interagire con esso in altro modo. Poiché la funzione che hai aggiunto nell'ultimo passaggio scrive su Realtime Database, 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à loro chiesto se desiderano abilitare automaticamente queste API per il loro progetto. Questo in genere è necessario solo per le API Google non Firebase e non è necessario per questa guida.
- Dichiara qualsiasi ruolo IAM di cui la tua estensione ha bisogno nel campo
roles
diextensions.yaml
. Una volta installate, alle estensioni vengono concessi automaticamente questi ruoli. - Dichiara eventuali API Google necessarie alla tua estensione nel campo
apis
diextensions.yaml
. Quando gli utenti installano la tua estensione, possono scegliere di abilitare automaticamente queste API per il loro progetto. - A scopo di documentazione, dichiara eventuali API non Google necessarie alla tua estensione nel campo
externalServices
diextensions.yaml
.
Maggiori informazioni
- Ulteriori informazioni sulla configurazione dell'accesso appropriato per un'estensione .
- Il riferimento
extension.yaml
ha una specifica completa del file; tuttavia, questa documentazione discuterà gli usi specifici di questo file quando è necessario utilizzarlo.
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, guardare una posizione specifica è davvero ciò che desideri, 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, vorrai rendere questi valori configurabili dagli utenti che installano la tua estensione nei loro progetti. In questo modo, gli utenti possono utilizzare la tua estensione per lavorare con la configurazione del database esistente.
Rendi configurabile dall'utente il percorso che l'estensione controlla per i nuovi messaggi:
Nel file
extension.yaml
, aggiungi una sezioneparams
:- 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
Ciò definisce un nuovo parametro di stringa che agli utenti verrà richiesto di impostare quando installano l'estensione.
Sempre nel file
extension.yaml
, torna alla dichiarazionemakeuppercase
e modifica il camporesource
come segue: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 da qualsiasi valore configurato dall'utente per quel parametro, con il risultato che la funzionemakeuppercase
ascolterà il percorso specificato dall'utente. Puoi utilizzare questa sintassi per fare riferimento a qualsiasi parametro definito dall'utente ovunque inextension.yaml
(e inPOSTINSTALL.md
, ne parleremo più avanti).È inoltre possibile accedere ai parametri definiti dall'utente dal codice delle funzioni.
Nella funzione che hai scritto nell'ultima sezione, hai codificato il percorso per verificare le modifiche. Modificare invece la definizione del trigger per fare riferimento al valore definito dall'utente:
funzioni/index.js
export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate
Tieni presente che in Firebase Extensions questa modifica è puramente a scopo di documentazione: quando una funzione Cloud viene distribuita come parte di un'estensione, utilizza la definizione di trigger dal file
extension.yaml
e ignora il valore specificato nella definizione della funzione. Tuttavia, è una buona idea documentare nel codice da dove proviene questo valore.Potresti trovare deludente apportare una modifica al codice che non abbia alcun effetto sul runtime, ma la lezione importante da imparare è che puoi 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 la seguente istruzione di log per dimostrare che stai effettivamente accedendo al valore definito dall'utente:
funzioni/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. ...
Normalmente, agli utenti viene richiesto di fornire valori per i parametri quando installano un'estensione. Quando utilizzi l'emulatore per test e sviluppo, tuttavia, salti il processo di installazione e fornisci invece valori per i parametri definiti dall'utente utilizzando un file
env
.functions/integration-tests/extensions/rtdb-uppercase-messages.env
e sostituisci la definizioneGREETING
con la seguente:MESSAGE_PATH=/msgs/{pushId}/original
Nota che il percorso sopra è diverso dal percorso predefinito e dal percorso definito in precedenza; questo è solo per dimostrare a te stesso quando provi l'estensione aggiornata che la tua definizione sta avendo effetto.
Ora riavvia l'emulatore e visita nuovamente l'interfaccia utente dell'emulatore del database.
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, la funzione
makeuppercase
dell'estensione dovrebbe attivarsi come prima, ma ora dovrebbe anche stampare il parametro definito dall'utente nel registro della console.- Campo:
- Puoi offrire agli utenti la possibilità di personalizzare la tua estensione in base alle loro esigenze dichiarando i parametri definiti dall'utente nel file
extension.yaml
. Agli utenti viene richiesto di definire questi valori quando installano l'estensione. - È possibile fare riferimento ai valori dei parametri definiti dall'utente nel file
extension.yaml
e nel filePOSTINSTALL.md
utilizzando la seguente sintassi:${param:PARAMETER_NAME}
- Puoi accedere ai valori dei parametri definiti dall'utente all'interno del codice Cloud Functions come variabili di ambiente:
process.env.PARAMETER_NAME
- Durante il test utilizzando l'emulatore, definire i parametri utente nel file
<extension-name>.env
.
Maggiori informazioni
Ulteriori informazioni sulla configurazione e sull'utilizzo dei parametri nella tua estensione .
7. Fornire hook di eventi per la logica definita dall'utente
Hai già visto, come autore di estensioni, come un prodotto Firebase può attivare la logica fornita dall'estensione: la creazione di nuovi record in Realtime Database attiva la tua funzione makeuppercase
. La tua estensione può avere una relazione analoga con gli utenti che installano la tua estensione: la tua estensione può attivare la logica definita dall'utente .
Un'estensione può fornire hook sincroni , hook asincroni o entrambi. Gli hook sincroni offrono agli utenti un modo per eseguire attività che bloccano il completamento di una delle funzioni dell'estensione. Ciò può essere utile, ad esempio, per offrire agli utenti la possibilità di eseguire una preelaborazione personalizzata prima che un'estensione esegua il proprio lavoro.
In questa guida aggiungerai un hook asincrono alla tua estensione, che consentirà agli utenti di definire i propri passaggi di elaborazione da eseguire dopo che l'estensione avrà scritto il messaggio in maiuscolo su Realtime Database. Gli hook asincroni utilizzano Eventarc per attivare funzioni definite dall'utente. Le estensioni dichiarano i tipi di eventi che emettono e, quando gli utenti installano l'estensione, scelgono i tipi di eventi a cui sono interessati. Se scelgono almeno un evento, Firebase fornirà un canale Eventarc per l'estensione come parte del processo di installazione . Gli utenti possono quindi distribuire le proprie funzioni cloud che restano in ascolto su quel canale e si attivano quando l'estensione pubblica nuovi eventi.
Seguire questi passaggi per aggiungere un hook asincrono:
Nel file
extension.yaml
, aggiungi la seguente sezione, che dichiara l'unico 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 unici; Per garantire l'unicità, assegna sempre un nome agli eventi utilizzando il seguente formato:
<publisher-id>.<extension-id>.<version>.<description>
. (Non hai ancora un ID editore, quindi per ora utilizza semplicementetest-publisher
.)Alla fine della funzione
makeuppercase
, aggiungi del codice che pubblica un evento del tipo che hai appena dichiarato:funzioni/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 la variabile di ambiente
EVENTARC_CHANNEL
è definita solo quando l'utente ha abilitato almeno un tipo di evento. seEVENTARC_CHANNEL
non è definito, il codice non tenta di pubblicare alcun evento.Puoi allegare informazioni aggiuntive a un evento Eventarc. Nell'esempio precedente, l'evento ha un campo
subject
che contiene un riferimento al valore appena creato e un payloaddata
che contiene i messaggi originali e in maiuscolo. Le funzioni definite dall'utente che attivano l'evento possono utilizzare queste informazioni.Normalmente, le variabili d'ambiente
EVENTARC_CHANNEL
eEXT_SELECTED_EVENTS
vengono definite in base alle opzioni selezionate dall'utente durante l'installazione. Per testare con l'emulatore, definisci manualmente queste variabili nel filertdb-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 hook di evento asincrono alla tua estensione.
Per provare questa nuova funzionalità che hai appena implementato, nei prossimi passaggi, assumi il ruolo di un utente che sta installando l'estensione:
Dalla directory
functions/integration-tests
, inizializza un nuovo progetto Firebase:firebase init functions
Quando richiesto, rifiuta di impostare un progetto predefinito, seleziona JavaScript come linguaggio Cloud Functions e installa le dipendenze richieste. Questo progetto rappresenta il progetto di un utente su cui è installata la tua estensione.
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 una funzione di post-elaborazione che un utente potrebbe scrivere. In questo caso, la funzione ascolta l'estensione per pubblicare un evento
complete
e, una volta attivata, aggiunge tre punti esclamativi al nuovo messaggio in maiuscolo.Riavviare l'emulatore. L'emulatore caricherà le funzioni dell'estensione così come la funzione di post-elaborazione definita dall'utente.
Visita l'interfaccia utente 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, la funzione
makeuppercase
dell'estensione e la funzioneextraemphasis
dell'utente dovrebbero attivarsi in sequenza, facendo sì che il campoupper
ottenga il valoreRECIPE!!!
.- Campo:
- Le tue estensioni possono includere hook che consentono agli utenti di inserire la propria logica nelle operazioni di base della tua estensione.
- Gli hook dell'utente possono essere sincroni, ovvero bloccare l'esecuzione di un'estensione finché non viene completata. Le estensioni utilizzano spesso hook sincroni per eseguire attività di preelaborazione definite dall'utente.
- Gli hook utente possono anche essere asincroni, come nell'esempio sopra. È possibile utilizzare hook asincroni per eseguire la logica definita dall'utente che non è fondamentale per il corretto funzionamento dell'estensione.
Maggiori informazioni
Ulteriori informazioni sull'aggiunta di hook per la logica definita dall'utente , inclusi hook asincroni e sincroni.
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 dispongono già di un database di messaggi quando installano l'estensione? Firebase Extensions dispone di una funzionalità chiamata hook degli eventi del ciclo di vita che puoi utilizzare per attivare azioni quando l'estensione viene installata, aggiornata o riconfigurata. In questa sezione utilizzerai gli hook degli eventi del ciclo di vita per riempire il database dei messaggi esistente di un progetto con messaggi in maiuscolo quando un utente installa la tua estensione.
Firebase Extensions utilizza Cloud Tasks per eseguire i gestori di eventi del ciclo di vita. Puoi definire i gestori eventi utilizzando Cloud Functions; ogni volta che un'istanza della tua estensione raggiunge uno degli eventi del ciclo di vita supportati, se hai definito un gestore, il gestore verrà aggiunto a una coda di Cloud Tasks. Cloud Tasks eseguirà quindi il gestore in modo asincrono. Mentre un gestore eventi del ciclo di vita è in esecuzione, la console Firebase segnalerà all'utente che l'istanza dell'estensione ha un'attività di elaborazione in corso. Spetta alla funzione del tuo gestore segnalare all'utente lo stato in corso e il completamento dell'attività.
Per aggiungere un gestore eventi del ciclo di vita che riempia i messaggi esistenti, procedi come segue:
Definisci una nuova funzione Cloud che viene attivata dagli eventi della coda di attività:
funzioni/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."); } });
Tieni presente che la funzione elabora solo alcuni record prima di aggiungersi nuovamente alla coda delle attività. Questa è una strategia comunemente utilizzata per gestire attività di elaborazione che non possono essere completate entro la finestra di timeout di una Funzione Cloud. Poiché non puoi prevedere quanti messaggi un utente potrebbe già avere nel proprio database quando installa la tua estensione, questa strategia è una buona soluzione.
Nel file
extension.yaml
, dichiara la funzione di backfill come risorsa di estensione con la proprietàtaskQueueTrigger
:resources: - name: makeuppercase ... - name: backfilldata type: firebaseextensions.v1beta.function description: >- Backfill existing messages with uppercase versions properties: runtime: "nodejs18" taskQueueTrigger: {}
Quindi dichiara la funzione come gestore per l'evento del ciclo di vita
onInstall
:lifecycleEvents: onInstall: function: backfilldata processingMessage: Uppercasing existing messages
Sebbene sia utile eseguire il backfill dei messaggi esistenti, l'estensione potrebbe comunque funzionare senza di essa. In situazioni come questa, dovresti rendere facoltativa l'esecuzione dei gestori di eventi del ciclo di vita.
Per fare ciò, 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 recupero, controlla il valore del parametro
DO_BACKFILL
ed esci prima se non è impostato:funzioni/index.js
if (!process.env.DO_BACKFILL) { return getExtensions() .runtime() .setProcessingState("PROCESSING_COMPLETE", "Backfill skipped."); }
Con le modifiche di cui sopra, l'estensione ora convertirà i messaggi esistenti in maiuscolo quando verrà installata.
Fino a questo punto, hai utilizzato l'emulatore di estensione per sviluppare la tua estensione e testare le modifiche in corso. Tuttavia, l'emulatore dell'estensione salta il processo di installazione, quindi per testare il gestore eventi onInstall
, dovrai installare l'estensione in un progetto reale. Meglio così, dato che con l'aggiunta di questa funzionalità di recupero automatico, l'estensione del tutorial è ora completa di codice!
Gli eventi del ciclo di vita vengono attivati quando gli utenti eseguono determinate attività di gestione delle estensioni:
- Installazione di un'istanza di un'estensione
- Aggiornamento di un'istanza di un'estensione a una nuova versione
- Riconfigurazione di un'istanza di un'estensione
Puoi definire funzioni che si attivano in base agli eventi del ciclo di vita della tua estensione.
Utilizza l'API runtime dell'estensione di Admin SDK per segnalare all'utente lo stato di un gestore di eventi del ciclo di vita. Gli utenti vedranno lo stato di elaborazione corrente di un'estensione nella console Firebase.
Le funzioni che operano sull'intero database (come le operazioni di recupero) spesso non possono essere completate prima che la Cloud Function scada. È possibile evitare questo problema suddividendo l'attività in più chiamate di funzioni.
Se l'estensione include gestori di eventi del ciclo di vita che non sono fondamentali per il funzionamento dell'estensione, è necessario rendere configurabile dall'utente l'esecuzione del gestore.
Maggiori informazioni
Ulteriori informazioni sulla gestione degli eventi del ciclo di vita della tua estensione .
9. Distribuisci in un vero progetto Firebase
Sebbene l'emulatore di estensioni sia un ottimo strumento per eseguire rapidamente l'iterazione di un'estensione durante lo sviluppo, ad un certo punto vorrai provarlo in un progetto reale.
Per fare ciò, imposta prima un nuovo progetto con alcuni servizi abilitati:
- Nella console Firebase , aggiungi un nuovo progetto.
- Aggiorna il tuo progetto al piano Blaze con pagamento in base al consumo. Cloud Functions for Firebase richiede che il tuo progetto disponga di un account di fatturazione, quindi avrai bisogno anche di un account di fatturazione per installare un'estensione.
- Nel tuo nuovo progetto, abilita Real-time Database .
- Poiché desideri testare la capacità della tua estensione di eseguire il backfill dei dati esistenti al momento dell'installazione, importa alcuni dati di esempio nell'istanza del database in tempo reale:
- Scarica alcuni dati RTDB seed .
- Nella pagina Database in tempo reale della console Firebase, fai clic su (altro) > Importa JSON e seleziona il file appena scaricato.
Per consentire alla funzione di recupero di utilizzare il metodo
orderByChild
, configurare il database per indicizzare i messaggi sul valore diupper
:{ "rules": { ".read": false, ".write": false, "messages": { ".indexOn": "upper" } } }
Ora installa la tua estensione dalla sorgente locale nel nuovo progetto:
Crea una nuova directory per il tuo progetto Firebase:
mkdir ~/extensions-live-test && cd ~/extensions-live-test
Inizializza un progetto Firebase nella directory di lavoro:
firebase init database
Quando richiesto, seleziona il progetto appena creato.
Installa l'estensione nel tuo progetto Firebase locale:
firebase ext:install /path/to/rtdb-uppercase-messages
Qui puoi vedere com'è l'esperienza utente quando installi un'estensione utilizzando lo strumento CLI Firebase. Assicurati di selezionare "sì" quando lo strumento di configurazione ti chiede se desideri riempire il database esistente.
Dopo aver selezionato le opzioni di configurazione, la CLI Firebase salverà la configurazione nella directory
extensions
e registrerà la posizione di origine dell'estensione nel filefirebase.json
. Collettivamente, questi due record sono chiamati manifest delle estensioni . Gli utenti possono utilizzare il manifest per salvare la configurazione delle estensioni e distribuirlo su diversi progetti.Distribuisci la configurazione dell'estensione al tuo progetto live:
firebase deploy --only extensions
Se tutto va bene, la CLI di Firebase dovrebbe caricare la tua estensione nel tuo progetto e installarla. Al termine dell'installazione, verrà eseguita l'attività di recupero e, in pochi minuti, il database verrà aggiornato con messaggi in maiuscolo. Aggiungi alcuni nuovi nodi al database dei messaggi e assicurati che l'estensione funzioni anche per i nuovi messaggi.
- Gli utenti possono creare un manifest dell'estensione utilizzando il comando
firebase ext:install
. Puoi anche utilizzare questo comando per installare un'estensione dall'origine locale. - Distribuisci una configurazione di estensione da un manifest in un progetto live utilizzando
firebase deploy
. - Sebbene non sia dimostrato qui, gli utenti possono anche installare estensioni nei propri progetti da Extensions Hub.
Maggiori informazioni
Consulta la documentazione per l'utente sulla gestione delle configurazioni del progetto con il manifest delle estensioni .
10. Scrivere la documentazione
Prima di condividere la tua estensione con gli utenti, assicurati di fornire documentazione sufficiente affinché possano avere successo.
Quando hai inizializzato il progetto di estensione, la CLI di Firebase ha creato versioni stub della documentazione minima richiesta. Aggiorna questi file per riflettere accuratamente l'estensione che hai creato.
estensione.yaml
Hai già aggiornato questo file man mano che hai sviluppato questa estensione, quindi non è necessario apportare altri aggiornamenti in questo momento.
Tuttavia, non trascurare l'importanza della documentazione contenuta in questo file. Oltre alle informazioni identificative cruciali di un'estensione (nome, descrizione, autore, posizione ufficiale del repository), il file extension.yaml
contiene documentazione rivolta all'utente per ogni risorsa e parametro configurabile dall'utente. Queste informazioni vengono presentate agli utenti nella console Firebase, nell'hub estensioni e nella CLI Firebase.
PREINSTALL.md
In questo file, fornisci le informazioni necessarie all'utente prima di installare l'estensione: descrivi brevemente cosa fa l'estensione, spiega eventuali prerequisiti e fornisci all'utente informazioni sulle implicazioni di fatturazione dell'installazione dell'estensione. Se hai un sito web con informazioni aggiuntive, anche questo è un buon posto per collegarlo.
Il testo di questo file viene visualizzato all'utente nell'hub estensioni e dal 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 aver installato correttamente l'estensione: ad esempio, passaggi di configurazione successivi, un esempio dell'estensione in azione e così via.
Il contenuto di POSTINSTALL.md viene visualizzato nella console Firebase dopo la configurazione e l'installazione di un'estensione. È possibile fare riferimento ai parametri utente in questo file e verranno sostituiti dai valori configurati.
Ecco un esempio di file post-installazione per l'estensione del 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
Dovresti anche documentare le modifiche apportate tra i rilasci di un'estensione nel file CHANGELOG.md
.
Poiché l'estensione di esempio non è mai stata pubblicata prima, il registro delle modifiche ha 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 anche un file leggimi a vantaggio degli utenti che visitano il repository dell'estensione. puoi scrivere questo file a mano o generare un leggimi usando il comando.
Ai fini di questa guida, salta la scrittura di un file leggimi.
Documentazione aggiuntiva
La documentazione discussa sopra è l'insieme minimo di documentazione che dovresti fornire agli utenti. Molte estensioni richiedono una documentazione più dettagliata affinché gli utenti possano utilizzarle con successo. In questo caso, dovresti scrivere documentazione aggiuntiva e ospitarla da qualche parte a cui puoi indirizzare gli utenti.
Ai fini di questa guida, evita di scrivere documentazione più estesa.
- Come minimo, ogni estensione dovrebbe fornire la documentazione dell'utente nei seguenti file:
extension.yaml
,PREINSTALL.md
,POSTINSTALL.md
eCHANGELOG.md
. - Dovresti anche fornire agli utenti una documentazione più dettagliata quando necessario.
Maggiori informazioni
Vedere la documentazione sulla scrittura della documentazione .
11. Pubblica su Extensions Hub
Ora che il codice della tua estensione è completo e documentato, sei pronto per condividerlo con il mondo su Extensions Hub. Ma poiché questo è solo un tutorial, non farlo davvero. Vai e inizia a scrivere la tua estensione utilizzando ciò che hai imparato qui e nel resto della documentazione dell'editore di Firebase Extensions ed esaminando la fonte delle estensioni ufficiali, scritte da Firebase.
Quando sarai pronto per pubblicare il tuo lavoro su Extensions Hub, ecco come lo farai:
- Se stai pubblicando la tua prima estensione, registrati come editore di estensioni . Quando ti registri come editore di estensioni, crei un ID editore che consente agli utenti di identificarti rapidamente come autore delle tue estensioni.
Ospita il codice sorgente della tua estensione in una posizione verificabile pubblicamente. Quando il tuo codice è disponibile da una fonte verificabile, Firebase può pubblicare la tua estensione direttamente da questa posizione. Ciò aiuta a garantire che stai pubblicando la versione attualmente rilasciata della tua estensione e aiuta gli utenti consentendo loro di esaminare il codice che stanno installando nei loro progetti.
Attualmente, ciò significa rendere la tua estensione disponibile in un repository GitHub pubblico.
Carica la tua estensione nell'hub estensioni utilizzando il comando
firebase ext:dev:upload
.Vai alla dashboard del tuo editore nella console Firebase, trova l'estensione che hai appena caricato e fai clic su "Pubblica nell'hub delle estensioni". Ciò richiede una revisione da parte del nostro staff di revisione, che può richiedere alcuni giorni. Se approvata, l'estensione verrà pubblicata nell'hub estensioni. In caso di rifiuto riceverai un messaggio che ne spiega il motivo; è quindi possibile risolvere i problemi segnalati e inviarli nuovamente per la revisione.
- Per condividere le estensioni su Extensions Hub, devi essere registrato come editore.
- È necessaria la pubblicazione da una fonte verificabile e offre agli utenti la garanzia che il codice che stanno installando è lo stesso codice che possono esaminare su GitHub.
- Utilizza il comando
firebase ext:dev:upload
per caricare un'estensione nell'hub estensioni. - Invia le tue estensioni per la revisione dalla dashboard dell'editore.
Maggiori informazioni
Ulteriori informazioni sulla registrazione come editore e sulla pubblicazione di un'estensione .