Questa pagina illustra 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 monitora il tuo Realtime Database alla ricerca di messaggi e li converte in maiuscolo.
1. Configura l'ambiente e inizializza un progetto
Prima di poter iniziare a creare un'estensione, devi configurare un ambiente di compilazione con gli strumenti richiesti.
Installa Node.js 16 o versioni successive. Un modo per installare Node è utilizzare nvm (o nvm-windows).
Installa o esegui l'upgrade alla versione più recente dell'interfaccia a riga di comando di Firebase. Per eseguire l'installazione o l'aggiornamento 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:
Crea una directory per l'estensione e
cd
al suo interno:mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
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 utilizzare TypeScript quando sviluppi la tua estensione) e, quando ti viene chiesto di installare le dipendenze, rispondi "Sì". Accetta i valori predefiniti per tutte le altre opzioni. Questo comando configurerà una base di codice di base per una nuova estensione, da cui potrai iniziare a svilupparla.
2. Prova l'estensione di esempio utilizzando l'emulatore
Quando l'interfaccia a riga di comando di Firebase ha inizializzato la nuova directory delle estensioni, ha creato una semplice funzione di esempio e una directory integration-tests
contenente i file necessari per eseguire un'estensione utilizzando la suite di emulatori Firebase.
Prova a eseguire l'estensione di esempio nell'emulatore:
Passa alla directory
integration-tests
:cd functions/integration-tests
Avvia l'emulatore con un progetto dimostrativo:
firebase emulators:start --project=demo-test
L'emulatore carica l'estensione in un progetto "fantasma" predefinito (
demo-test
). Finora l'estensione è costituita da una singola funzione attivata tramite HTTP,greetTheWorld
, che restituisce un messaggio "hello world" quando viene invocata.Con l'emulatore ancora in esecuzione, prova la funzione
greetTheWorld
dell'estensione visitando l'URL stampato quando l'hai avviato.Il browser mostra il messaggio "Hello World da greet-the-world".
Il codice sorgente di questa funzione si trova nella directory
functions
dell'estensione. Apri il codice sorgente nell'editor o nell'IDE che preferisci: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); });
Mentre l'emulatore è in esecuzione, ricarica automaticamente le modifiche apportate al codice di Functions. Prova ad apportare una piccola modifica alla funzione
greetTheWorld
:functions/index.js
const greeting = `${consumerProvidedGreeting} everyone, from ${instanceId}`;
Salva le modifiche. L'emulatore ricaricherà il codice e, ora, quando visiterai l'URL della funzione, vedrai il messaggio di benvenuto aggiornato.
3. Aggiungi informazioni di base a extension.yaml
Ora che hai configurato un ambiente di sviluppo e stai eseguendo l'emulatore di estensioni, puoi iniziare a scrivere la tua estensione.
Come primo passaggio, modifica i metadati dell'estensione predefinita in modo che riflettano l'estensione che vuoi scrivere anziché greet-the-world
. Questi metadati vengono memorizzati nel file extension.yaml
.
Apri
extension.yaml
nell'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
Tieni presente la convenzione di denominazione utilizzata nel campo
name
: le estensioni Firebase ufficiali sono denominate con un prefisso che indica il prodotto Firebase principale su cui operano, seguito da una descrizione della funzionalità dell'estensione. Devi utilizzare la stessa convenzione nelle tue estensioni.Poiché hai modificato il nome dell'estensione, devi aggiornare anche la configurazione dell'emulatore con il nuovo nome:
- In
functions/integration-tests/firebase.json
, cambiagreet-the-world
inrtdb-uppercase-messages
. - Rinomina
functions/integration-tests/extensions/greet-the-world.env
infunctions/integration-tests/extensions/rtdb-uppercase-messages.env
.
- In
Nel codice dell'estensione sono ancora presenti alcuni resti dell'estensione greet-the-world
, ma per il momento non farne caso. Le aggiornerai nelle sezioni seguenti.
4. Scrivi una funzione Cloud Functions e dichiarala come risorsa di estensione
Ora puoi iniziare a scrivere del codice. In questo passaggio, scriverai una funzione Cloud che esegue l'attività principale dell'estensione, ovvero monitorare il database in tempo reale per rilevare i messaggi e convertirli in maiuscolo.
Apri il codice sorgente delle funzioni dell'estensione (nella directory
functions
dell'estensione) nell'editor o nell'IDE che preferisci. Sostituisci i contenuti con quanto segue: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 tramite HTTP, che veniva eseguita quando si accedeva a un endpoint HTTP. La nuova funzione viene attivata da eventi del database in tempo reale: cerca nuovi elementi in un determinato percorso e, quando ne viene rilevato uno, scrive la versione in maiuscolo del valore nel database.
A proposito, questo nuovo file utilizza la sintassi dei moduli ECMAScript (
import
eexport
) anziché 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 nell'estensione deve essere dichiarata nel file
extension.yaml
. L'estensione di esempio ha dichiaratogreetTheWorld
come unica funzione Cloud dell'estensione. Ora che l'hai sostituita conmakeuppercase
, devi anche aggiornarne la 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é ora l'estensione utilizza Realtime Database come attivatore, 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 seguente comando:firebase init emulators
Quando ti viene chiesto, salta la configurazione di un progetto predefinito, quindi seleziona gli emulatori Functions e Database. Accetta le porte predefinite e consenti allo strumento di configurazione di scaricare i file richiesti.
Riavvia l'emulatore:
firebase emulators:start --project=demo-test
Prova l'estensione aggiornata:
Apri l'interfaccia utente dell'emulatore di database utilizzando il link stampato dall'emulatore quando lo hai avviato.
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 dovrebbe attivarsi e aggiungere un record secondario al messaggio 11 con i contenuti"upper": "RECIPE"
. Dai un'occhiata ai log e alle schede del database dell'interfaccia utente dell'emulatore per confermare i risultati previsti.- Campo:
Prova ad aggiungere altri elementi secondari al nodo
messages
({"original":"any text"}
). Ogni volta che aggiungi un nuovo record, l'estensione deve aggiungere un campouppercase
contenente i contenuti in maiuscolo del campooriginal
.
Ora hai un'estensione completa, anche se semplice, che opera su un'istanza RTDB. Nelle sezioni che seguono perfezionerai questa estensione con alcune funzionalità aggiuntive. Dopodiché, potrai distribuire l'estensione ad altri utenti e infine scoprire come pubblicarla nell'hub delle estensioni.
5. Dichiarare API e ruoli
Firebase concede a ogni istanza di un'estensione installata l'accesso limitato al progetto e ai relativi dati 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, ma è necessario dichiarare un ruolo per interagire con il prodotto 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.
Analogamente, dichiari le API Google utilizzate da un'estensione nel campo apis
. Quando gli utenti installano l'estensione, viene chiesto loro se vogliono attivare automaticamente queste API per il loro progetto. In genere, questo passaggio è necessario solo per le API di Google non Firebase e non è necessario 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, ti consigliamo di far sì che questi valori siano 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 in cui l'estensione cerca 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
Viene definito un nuovo parametro di stringa che verrà chiesto agli utenti di impostare quando installano l'estensione.
Sempre nel file
extension.yaml
, torna alla dichiarazionemakeuppercase
e modifica il camporesource
in quanto segue:resource: projects/_/instances/${DATABASE_INSTANCE}/refs/${param:MESSAGE_PATH}
Il token
${param:MESSAGE_PATH}
è un riferimento al parametro 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 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
; di seguito sono riportate ulteriori informazioni).Puoi anche accedere ai parametri definiti dall'utente dal codice delle funzioni.
Nella funzione che hai scritto nell'ultima sezione, hai inserito in modo hardcoded il percorso da monitorare per rilevare le modifiche. Modifica la definizione dell'attivatore in modo che faccia riferimento al valore definito dall'utente:
functions/index.js
export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate
Tieni presente che in Firebase Extensions questa modifica è puramente per motivi di documentazione: quando una funzione Cloud viene dispiattata all'interno di un'estensione, utilizza la definizione dell'attivatore dal file
extension.yaml
e ignora il valore specificato nella definizione della funzione. Tuttavia, è buona norma documentare nel codice la provenienza di questo valore.Potresti trovare deludente apportare una modifica al codice che non ha alcun effetto in fase di runtime, ma la lezione importante da ricordare è che puoi accedere a qualsiasi parametro definito dall'utente nel codice della funzione e utilizzarlo come un valore normale nella logica della funzione. Come riferimento a questa funzionalità, aggiungi la seguente dichiarazione di log per dimostrare che stai effettivamente accedendo al valore 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. ...
Di solito, agli utenti viene chiesto di fornire i valori per i parametri quando installano un'estensione. Tuttavia, quando utilizzi l'emulatore per i test e lo sviluppo, salti la procedura di installazione, quindi fornisci i valori per i parametri definiti dall'utente utilizzando un file
env
.Apri
functions/integration-tests/extensions/rtdb-uppercase-messages.env
e sostituisci la definizione diGREETING
con la seguente:MESSAGE_PATH=/msgs/{pushId}/original
Tieni presente che il percorso riportato sopra è diverso da quello predefinito e da quello che hai definito in precedenza. Questo è solo per verificare, quando provi l'estensione aggiornata, che la definizione venga applicata.
Ora riavvia l'emulatore e torna all'interfaccia utente dell'emulatore del 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, la funzione
makeuppercase
dell'estensione dovrebbe attivarsi come prima, ma ora dovrebbe anche stampare il parametro definito dall'utente nel log della console.- Campo:
7. Fornire hook di evento per la logica definita dall'utente
In qualità di autore di estensioni, hai già visto come un prodotto Firebase può attivare la logica fornita dall'estensione: la creazione di nuovi record in Realtime Database attiva la funzione makeuppercase
. La tua estensione può avere un rapporto analogo con gli utenti che la installano: la tua estensione può attivare la logica definita dall'utente.
Un'estensione può fornire hook sincroni, hook asincroni o entrambi. Gli hook sincroni consentono agli utenti di eseguire attività che bloccano il completamento di 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 all'estensione, che consentirà agli utenti di definire i propri passaggi di elaborazione da eseguire dopo che l'estensione avrà scritto il messaggio in maiuscolo nel database in tempo reale. Gli hook asincroni utilizzano Eventarc per attivare funzioni definite dall'utente. Le estensioni dichiarano i tipi di eventi che emettono e, quando gli utenti le installano, scelgono i tipi di eventi che li interessano. Se sceglie almeno un evento, Firebase eseguirà il provisioning di un canale Eventarc per l'estensione nell'ambito della procedura 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:
Nel file
extension.yaml
, aggiungi la seguente sezione, che dichiara il 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 hai ancora un ID editore, quindi per il momento utilizzatest-publisher
.Alla fine della funzione
makeuppercase
, aggiungi del codice che pubblichi un evento 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 la variabile di ambiente
EVENTARC_CHANNEL
viene definita solo quando l'utente ha attivato almeno un tipo di evento. SeEVENTARC_CHANNEL
non è definito, il codice non tenta di pubblicare eventi.Puoi allegare informazioni aggiuntive a un evento Eventarc. Nell'esempio riportato sopra, 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.In genere, le variabili di ambiente
EVENTARC_CHANNEL
eEXT_SELECTED_EVENTS
vengono definite in base alle opzioni selezionate dall'utente durante l'installazione. Per i test 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 evento asincrono alla tua estensione.
Per provare questa nuova funzionalità che hai appena implementato, nei prossimi passaggi assumere 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 configurare un progetto predefinito, seleziona JavaScript come linguaggio Cloud Functions e installa le dipendenze richieste. Questo progetto rappresenta un progetto di un utente in 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 funzione di post-elaborazione che un utente potrebbe scrivere. In questo caso, la funzione ascolta la pubblicazione di un evento
complete
da parte dell'estensione e, quando viene attivata, aggiunge tre punti esclamativi al messaggio appena impostato in maiuscolo.Riavvia l'emulatore. L'emulatore caricherà le funzioni dell'estensione nonché la funzione di post-elaborazione definita dall'utente.
Visita l'interfaccia utente dell'emulatore del database e 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, la funzione
makeuppercase
dell'estensione e la funzioneextraemphasis
dell'utente devono essere attivate in sequenza, in modo che il campoupper
riceva il valoreRECIPE!!!
.- Campo:
8. Aggiungere 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 l'estensione? Firebase Extensions dispone di una funzionalità chiamata hook per eventi di ciclo di vita che puoi utilizzare per attivare azioni quando l'estensione viene installata, aggiornata o riconfigurata. In questa sezione utilizzerai gli hook per gli eventi del ciclo di vita per eseguire il backfill del database dei messaggi esistente di un progetto con messaggi in maiuscolo quando un utente installa la tua estensione.
Le Estensioni Firebase utilizzano Cloud Tasks per eseguire i gestori degli eventi del ciclo di vita. Puoi definire i gestori di 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, questo verrà aggiunto a una coda di Cloud Tasks. Cloud Tasks eseguirà quindi il gestore in modo asincrono. Mentre è in esecuzione un gestore di eventi del ciclo di vita, la Console Firebase segnala all'utente che nell'istanza dell'estensione è in corso un'attività di elaborazione. Spetta alla funzione di gestore segnalare all'utente lo stato in corso e il completamento delle attività.
Per aggiungere un gestore degli eventi del ciclo di vita che esegue il backfill dei messaggi esistenti:
Definisci una nuova funzione Cloud Functions attivata dagli eventi della coda 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."); } });
Tieni presente che la funzione elabora solo alcuni record prima di aggiungersi nuovamente alla coda delle attività. Si tratta di una strategia di uso comune per gestire le attività di elaborazione che non possono essere completate entro il periodo di tempo 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 è adatta.
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: {}
Dichiara poi la funzione come gestore per l'evento di ciclo di vita
onInstall
:lifecycleEvents: onInstall: function: backfilldata processingMessage: Uppercasing existing messages
Sebbene il backfill dei messaggi esistenti sia un'opzione utile, l'estensione potrebbe funzionare anche senza. In situazioni come questa, devi rendere facoltativo l'esecuzione degli eventi di gestione del ciclo di vita.
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
Poi, all'inizio della funzione di backfill, controlla il valore del parametro
DO_BACKFILL
ed esci anticipatamente 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 lettere maiuscole quando è installata.
Fino a questo punto, hai utilizzato l'emulatore di estensioni per sviluppare l'estensione e
testare le modifiche in corso. Tuttavia, l'emulatore di estensioni salta il processo di installazione, quindi per testare il gestore eventi onInstall
devi installare l'estensione in un progetto reale. Per fortuna, con l'aggiunta di questa funzionalità di backfill automatico, l'estensione del tutorial ora è completa di codice.
9. Esegui il deployment in un progetto Firebase reale
Sebbene l'emulatore di estensioni sia un ottimo strumento per eseguire rapidamente l'iterazione di un'estensione durante lo sviluppo, a un certo punto ti consigliamo di provarlo in un progetto reale.
Per farlo, configura innanzitutto un nuovo progetto con alcuni servizi abilitati:
- Nella Console Firebase, aggiungi un nuovo progetto.
- Esegui l'upgrade del tuo 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.
- Nel nuovo progetto, abilita Realtime Database.
- Poiché vuoi testare la capacità dell'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 di base del DBRT.
- Nella pagina Database in tempo reale della console Firebase, fai clic su (Altro) > Importa JSON e seleziona il file che hai appena scaricato.
Per consentire alla funzione di backfill di utilizzare il metodo
orderByChild
, configura il database in modo da indicizzare i messaggi in base al valore diupper
:{ "rules": { ".read": false, ".write": false, "messages": { ".indexOn": "upper" } } }
Ora installa l'estensione dall'origine locale nel nuovo progetto:
Crea una nuova directory per il 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 come funziona l'esperienza utente durante l'installazione di un'estensione utilizzando lo strumento Firebase CLI. Assicurati di selezionare "Sì" quando lo strumento di configurazione ti chiede se vuoi eseguire il backfill del database esistente.
Dopo aver selezionato le opzioni di configurazione, Firebase CLI salverà la configurazione nella directory
extensions
e registrerà la posizione della fonte dell'estensione nel filefirebase.json
. Insieme, questi due record sono chiamati manifest delle estensioni. Gli utenti possono utilizzare il manifest per salvare la configurazione delle estensioni e implementarla in progetti diversi.Esegui il deployment della configurazione dell'estensione nel progetto pubblicato:
firebase deploy --only extensions
Se tutto va bene, l'interfaccia a riga di comando di Firebase dovrebbe caricare l'estensione nel progetto e installarla. Al termine dell'installazione, verrà eseguita l'attività di backfill e, in pochi minuti, il database verrà aggiornato con i messaggi in maiuscolo. Aggiungi alcuni nuovi nodi al database dei messaggi e assicurati che l'estensione funzioni anche per i nuovi messaggi.
10. Scrivere la documentazione
Prima di condividere l'estensione con gli utenti, assicurati di fornire documentazione sufficiente per consentirne l'utilizzo.
Quando hai inizializzato il progetto di estensione, l'interfaccia a riga di comando di Firebase ha creato versioni stub della documentazione minima richiesta. Aggiorna questi file in modo che riflettano con precisione l'estensione che hai creato.
extension.yaml
Hai già aggiornato questo file durante lo sviluppo dell'estensione, quindi non devi apportare altri aggiornamenti al momento.
Tuttavia, non trascurare l'importanza della documentazione contenuta in questo
file. Oltre alle informazioni di identificazione fondamentali di un'estensione (nome, descrizione, autore, posizione del repository ufficiale), il file extension.yaml
contiene la documentazione rivolta agli utenti per ogni risorsa e parametro configurabile dall'utente. Queste informazioni vengono mostrate agli utenti nella Console Firebase, nell'hub delle estensioni e nella CLI di Firebase.
PREINSTALL.md
In questo file, fornisci le informazioni di cui l'utente ha bisogno prima di installare la tua estensione: descrivi brevemente la funzionalità dell'estensione, spiega gli eventuali prerequisiti e fornisci all'utente informazioni sulle implicazioni di fatturazione dell'installazione dell'estensione. Se hai un sito web con informazioni aggiuntive, questo è anche un buon posto per collegarlo.
Il testo di questo file viene mostrato all'utente in 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 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 la configurazione e l'installazione di un'estensione. 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 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
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 contiene 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 readme per gli utenti che visitano il repository dell'estensione. Puoi scrivere questo file manualmente o generare un file readme 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 per consentirne agli utenti un utilizzo corretto. In questo caso, devi scrivere ulteriore documentazione e ospitarla in un luogo a cui puoi indirizzare gli utenti.
Ai fini di questa guida, salta la scrittura di una documentazione più completa.
11. Pubblicare su Extensions Hub
Ora che il codice dell'estensione è completo e documentato, puoi condividerla con il resto del mondo nell'hub delle estensioni. Tuttavia, poiché si tratta solo di un tutorial, non farlo. Inizia a scrivere la tua estensione utilizzando ciò che hai imparato qui e nel resto della documentazione per i publisher di Firebase Extensions, nonché esaminando il codice sorgente delle estensioni ufficiali scritte da Firebase.
Quando è tutto pronto per pubblicare il tuo lavoro su Extensions Hub, ecco come fare:
- Se stai pubblicando la tua prima estensione, registrati come publisher di estensioni. Quando ti registri come publisher di estensioni, crei un ID publisher che consente agli utenti di identificarti rapidamente come autore delle tue estensioni.
Ospita il codice sorgente dell'estensione in una posizione verificabile pubblicamente. Quando il codice è disponibile da una fonte verificabile, Firebase può pubblicare l'estensione direttamente da questa posizione. In questo modo, puoi assicurarti di pubblicare la versione attualmente rilasciata dell'estensione e aiutare gli utenti consentendo loro di esaminare il codice che stanno installando nei loro progetti.
Al momento, ciò significa rendere disponibile l'estensione in un repository pubblico GitHub.
Carica l'estensione nell'hub delle estensioni utilizzando il comando
firebase ext:dev:upload
.Vai alla dashboard del publisher nella console Firebase, trova l'estensione appena caricata e fai clic su "Pubblica nell'hub delle estensioni". 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. Potrai quindi risolvere i problemi segnalati e inviare nuovamente la richiesta di revisione.