1. Prima di iniziare
Un'estensione Firebase esegue un'attività o un insieme di attività specifiche in risposta a richieste HTTP o all'attivazione di eventi da altri prodotti Firebase e Google come Firebase Cloud Messaging, Cloud Firestore o Pub/Sub.
Cosa creerai
In questo codelab creerai un'estensione Firebase per l'geohashing. Una volta eseguito il deployment, l'estensione converte le coordinate X e Y in geohash in risposta agli eventi Firestore o tramite chiamate di funzioni richiamabili. Può essere utilizzato come alternativa all'implementazione della libreria Geofire su tutte le piattaforme di destinazione per l'archiviazione dei dati, risparmiando tempo.
Cosa imparerai a fare
- Come prendere il codice Cloud Functions esistente e trasformarlo in un'estensione Firebase distribuibile
- Come configurare un file
extension.yaml
- Come archiviare stringhe sensibili (chiavi API) in un'estensione
- Come consentire agli sviluppatori dell'estensione di configurarla in base alle loro esigenze
- Come testare ed eseguire il deployment dell'estensione
Che cosa ti serve
- Interfaccia a riga di comando di Firebase (installazione e accesso)
- Un Account Google, ad esempio un account Gmail
- Node.js e
npm
- Il tuo ambiente di sviluppo preferito
2. Configurazione
Ottieni il codice
Tutto ciò che ti serve per questa estensione è disponibile in un repository GitHub. Per iniziare, prendi il codice e aprilo nel tuo ambiente di sviluppo preferito.
- Decomprimi il file ZIP scaricato.
- Per installare le dipendenze richieste, apri il terminale nella directory
functions
ed esegui il comandonpm install
.
Configura Firebase
Questo codelab consiglia vivamente l'utilizzo degli emulatori Firebase. Se vuoi provare a sviluppare estensioni con un progetto Firebase reale, consulta Creare un progetto Firebase. Questo codelab utilizza Cloud Functions, quindi se utilizzi un progetto Firebase reale anziché gli emulatori, devi eseguire l'upgrade al piano tariffario Blaze.
Vuoi andare avanti?
Puoi scaricare una versione completata del codelab. Se riscontri difficoltà durante la procedura o se vuoi vedere l'aspetto di un'estensione completata, consulta il ramo codelab-end
del repository GitHub o scarica il file ZIP completato.
3. Esamina il codice
- Apri il file
index.ts
dal file ZIP. Tieni presente che contiene due dichiarazioni di Cloud Functions.
A cosa servono queste funzioni?
Queste funzioni demo vengono utilizzate per il geohashing. Prendono una coppia di coordinate e la trasformano in un formato ottimizzato per le query geografiche in Firestore. Le funzioni simulano l'utilizzo di una chiamata API per consentirti di scoprire di più sulla gestione dei tipi di dati sensibili nelle estensioni. Per ulteriori informazioni, consulta la documentazione sull'esecuzione di query geografiche sui dati in Firestore.
Costanti di funzione
Le costanti vengono dichiarate all'inizio, nella parte superiore del file index.ts
. Alcune di queste costanti vengono utilizzate nei trigger definiti dell'estensione.
index.ts
import {firestore} from "firebase-functions";
import {initializeApp} from "firebase-admin/app";
import {GeoHashService, ResultStatusCode} from "./fake-geohash-service";
import {onCall} from "firebase-functions/v1/https";
import {fieldValueExists} from "./utils";
const documentPath = "users/{uid}";
const xField = "xv";
const yField = "yv";
const apiKey = "1234567890";
const outputField = "hash";
initializeApp();
const service = new GeoHashService(apiKey);
Trigger di Firestore
La prima funzione nel file index.ts
ha il seguente aspetto:
index.ts
export const locationUpdate = firestore.document(documentPath)
.onWrite((change) => {
// item deleted
if (change.after == null) {
return 0;
}
// double check that both values exist for computation
if (
!fieldValueExists(change.after.data(), xField) ||
!fieldValueExists(change.after.data(), yField)
) {
return 0;
}
const x: number = change.after.data()![xField];
const y: number = change.after.data()![yField];
const hash = service.convertToHash(x, y);
// This is to check whether the hash value has changed. If
// it hasn't, you don't want to write to the document again as it
// would create a recursive write loop.
if (fieldValueExists(change.after.data(), outputField)
&& change.after.data()![outputField] == hash) {
return 0;
}
return change.after.ref
.update(
{
[outputField]: hash.hash,
}
);
});
Questa funzione è un trigger Firestore. Quando si verifica un evento di scrittura nel database, la funzione reagisce a questo evento cercando un campo xv
e un campo yv
e, se entrambi i campi esistono, calcola il geohash e scrive l'output in una posizione di output del documento specificata. Il documento di input è definito dalla costante users/{uid}
, il che significa che la funzione legge ogni documento scritto nella raccolta users/
e poi elabora un geohash per questi documenti. Quindi, restituisce l'hash a un campo hash nello stesso documento.
Funzioni richiamabili
La funzione successiva nel file index.ts
ha il seguente aspetto:
index.ts
export const callableHash = onCall((data, context) => {
if (context.auth == undefined) {
return {error: "Only authorized users are allowed to call this endpoint"};
}
const x = data[xField];
const y = data[yField];
if (x == undefined || y == undefined) {
return {error: "Either x or y parameter was not declared"};
}
const result = service.convertToHash(x, y);
if (result.status != ResultStatusCode.ok) {
return {error: `Something went wrong ${result.message}`};
}
return {result: result.hash};
});
Nota la funzione onCall
. Indica che questa funzione è una funzione richiamabile, che può essere chiamata dal codice dell'applicazione client. Questa funzione chiamabile accetta i parametri x
e y
e restituisce un geohash. Sebbene questa funzione non venga chiamata direttamente in questo codelab, è inclusa qui come esempio di elemento da configurare nell'estensione Firebase.
4. Configurare un file extension.yaml
Ora che sai cosa fa il codice Cloud Functions nella tua estensione, puoi prepararlo per la distribuzione. Ogni estensione Firebase è dotata di un file extension.yaml
che descrive cosa fa l'estensione e come si comporta.
Un file extension.yaml
richiede alcuni metadati iniziali sulla tua estensione. Ciascuno dei passaggi seguenti ti aiuta a capire il significato di tutti i campi e perché sono necessari.
- Crea un file
extension.yaml
nella directory principale del progetto che hai scaricato in precedenza. Inizia aggiungendo quanto segue:
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
Il nome dell'estensione viene utilizzato come base dell'ID istanza dell'estensione (gli utenti possono installare più istanze di un'estensione, ognuna con il proprio ID). Firebase genera quindi il nome dei service account dell'estensione e delle risorse specifiche dell'estensione utilizzando l'ID istanza. Il numero di versione indica la versione dell'estensione. Deve seguire il controllo delle versioni semantico e devi aggiornarlo ogni volta che apporti modifiche alla funzionalità dell'estensione. La versione della specifica dell'estensione viene utilizzata per determinare quale specifica delle estensioni Firebase seguire. In questo caso, viene utilizzata v1beta
.
- Aggiungi alcuni dettagli intuitivi al file YAML:
...
displayName: Latitude and longitude to GeoHash converter
description: A converter for changing your Latitude and longitude coordinates to geohashes.
Il nome visualizzato è una rappresentazione intuitiva del nome dell'estensione quando gli sviluppatori interagiscono con l'estensione. La descrizione fornisce una breve panoramica delle funzioni dell'estensione. Quando l'estensione viene implementata su extensions.dev, ha un aspetto simile a questo:
- Specifica la licenza per il codice nell'estensione.
...
license: Apache-2.0 # The license you want for the extension
- Indica chi ha scritto l'estensione e se è necessaria la fatturazione per installarla:
...
author:
authorName: AUTHOR_NAME
url: https://github.com/Firebase
billingRequired: true
La sezione author
viene utilizzata per comunicare agli utenti a chi rivolgersi in caso di problemi con l'estensione o se vogliono saperne di più. billingRequired
è un parametro obbligatorio e deve essere impostato su true
poiché tutte le estensioni si basano su Cloud Functions, che richiede il piano Blaze.
Ciò copre il numero minimo di campi richiesti nel file extension.yaml
per identificare questa estensione. Per ulteriori dettagli su altre informazioni identificative che puoi specificare in un'estensione, consulta la documentazione.
5. Converti il codice di Cloud Functions in una risorsa Extensions
Una risorsa di estensione è un elemento che Firebase crea nel progetto durante l'installazione di un'estensione. L'estensione diventa quindi proprietaria di queste risorse e dispone di un service account specifico che le gestisce. In questo progetto, queste risorse sono Cloud Functions, che devono essere definite nel file extension.yaml
perché l'estensione non crea automaticamente risorse dal codice nella cartella delle funzioni. Se le tue funzioni Cloud Functions non sono dichiarate esplicitamente come risorsa, non possono essere implementate quando viene implementata l'estensione.
Posizione di deployment definita dall'utente
- Consenti all'utente di specificare la posizione in cui vuole eseguire il deployment di questa estensione e decidere se è meglio ospitarla più vicino agli utenti finali o al database. Nel file
extension.yaml
, includi l'opzione per scegliere una posizione.
extension.yaml
Ora puoi scrivere la configurazione per la risorsa della funzione.
- Nel file
extension.yaml
, crea un oggetto risorsa per la funzionelocationUpdate
. Aggiungi quanto segue al fileextension.yaml
:
resources:
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}
Definisci name
come nome della funzione definito nel file index.ts
del progetto. Specifica il type
della funzione di cui viene eseguito il deployment, che per il momento deve sempre essere firebaseextensions.v1beta.function
. Poi, definisci il properties
di questa funzione. La prima proprietà che definisci è il eventTrigger
associato a questa funzione. Per rispecchiare ciò che l'estensione supporta attualmente, utilizza eventType
di providers/cloud.firestore/eventTypes/document.write
, che si trova nella documentazione Scrivere Cloud Functions per l'estensione. Definisci resource
come posizione dei documenti. Poiché il tuo obiettivo attuale è rispecchiare ciò che esiste nel codice, il percorso del documento è in ascolto di users/{uid}
, con la posizione predefinita del database che lo precede.
- L'estensione richiede le autorizzazioni di lettura e scrittura per il database Firestore. Alla fine del file
extension.yaml
, specifica i ruoli IAM a cui l'estensione deve avere accesso per interagire con il database nel progetto Firebase dello sviluppatore.
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
Il ruolo datastore.user
proviene dall'elenco dei ruoli IAM supportati per le estensioni. Poiché l'estensione leggerà e scriverà, il ruolo datastore.user
è una buona scelta.
- Deve essere aggiunta anche la funzione chiamabile. Nel file
extension.yaml
, crea una nuova risorsa nella proprietà resources. Queste proprietà sono specifiche per una funzione chiamabile:
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
Anche se la risorsa precedente utilizzava un eventTrigger
, qui utilizzi un httpsTrigger
, che copre sia le funzioni chiamabili che le funzioni HTTPS.
Controllo del codice
È stata necessaria molta configurazione per fare in modo che extension.yaml
corrisponda a tutto ciò che viene eseguito dal codice nel file index.ts
. Ecco l'aspetto che dovrebbe avere il file extension.yaml
completato a questo punto:
extension.yaml
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
displayName: Latitude and Longitude to GeoHash converter
description: A converter for changing your Latitude and Longitude coordinates to geohashes.
license: Apache-2.0 # The license you want for the extension
author:
authorName: Sparky
url: https://github.com/Firebase
billingRequired: true
resources:
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
Controllo dello stato
A questo punto, hai configurato i componenti funzionali iniziali dell'estensione, quindi puoi provarla utilizzando gli emulatori Firebase.
- Se non l'hai ancora fatto, chiama
npm run build
nella cartella delle funzioni del progetto di estensioni scaricato. - Crea una nuova directory sul sistema host e connettila al tuo progetto Firebase utilizzando
firebase init
.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
This command creates a `firebase.json` file in the directory. In the following steps, you push the configuration specified in this file to Firebase.
- Dalla stessa directory, esegui
firebase ext:install
. Sostituisci/path/to/extension
con il percorso assoluto della directory che contiene il fileextension.yaml
.
firebase ext:install /path/to/extension
This command does two things:
- Ti viene chiesto di specificare la configurazione per l'istanza dell'estensione e viene creato un file
*.env
contenente le informazioni di configurazione per l'istanza. - Aggiunge l'istanza dell'estensione alla sezione
extensions
delfirebase.json
. Funziona come una mappa dell'ID istanza alla versione dell'estensione. - Poiché stai eseguendo il deployment del progetto localmente, puoi specificare che vuoi utilizzare un file locale anziché Google Cloud Secret Manager.
- Avvia gli emulatori Firebase con la nuova configurazione:
firebase emulators:start
- Dopo aver eseguito
emulators:start
, vai alla scheda Firestore nella webview degli emulatori. - Aggiungi un documento alla raccolta
users
con un campo numericoxv
e un campo numericoyv
.
- Se l'installazione dell'estensione è andata a buon fine, questa crea un nuovo campo denominato
hash
nel documento.
Eseguire la pulizia per evitare conflitti
- Al termine del test, disinstalla l'estensione. In seguito aggiornerai il codice dell'estensione e non vuoi che si verifichino conflitti con l'estensione attuale.
Le estensioni consentono di installare più versioni della stessa estensione contemporaneamente, quindi la disinstallazione garantisce che non ci siano conflitti con un'estensione installata in precedenza.
firebase ext:uninstall geohash-ext
La soluzione attuale funziona, ma come accennato all'inizio del progetto, esiste una chiave API hardcoded per simulare la comunicazione con un servizio. Come puoi utilizzare la chiave API dell'utente finale anziché quella fornita originariamente? Continua a leggere per scoprirlo.
6. Rendere l'estensione configurabile dall'utente
A questo punto del codelab, hai un'estensione configurata per l'utilizzo con la configurazione predefinita delle funzioni che hai già scritto. Ma cosa succede se l'utente vuole utilizzare la latitudine e la longitudine anziché y e x per i campi che indicano la posizione su un piano cartesiano? Inoltre, come puoi fare in modo che l'utente finale fornisca la propria chiave API, anziché utilizzare quella fornita? Potresti superare rapidamente la quota per questa API. In questo caso, devi configurare e utilizzare i parametri.
Definisci i parametri di base nel extension.yaml
file
Inizia convertendo gli elementi per i quali gli sviluppatori potrebbero avere una configurazione personalizzata. Il primo sarebbe i parametri XFIELD
e YFIELD
.
- Nel file
extension.yaml
, aggiungi il seguente codice, che utilizza i parametri dei campiXFIELD
eYFIELD
. Questi parametri si trovano all'interno della proprietà YAMLparams
definita in precedenza:
extension.yaml
params:
- param: XFIELD
label: The X Field Name
description: >-
The X Field is also known as the **longitude** value. What does
your Firestore instance refer to as the X value or the longitude
value. If no value is specified, the extension searches for
field 'xv'.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: xv
required: false
immutable: false
example: xv
- param: YFIELD
label: The Y Field Name
description: >-
The Y Field is also known as the **latitude** value. What does
your Firestore instance refer to as the Y value or the latitude
value. If no value is specified, the extension searches for
field 'yv'.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: yv
required: false
immutable: false
example: yv
- param assegna un nome al parametro in modo che sia visibile a te, il produttore dell'estensione. Utilizza questo valore in un secondo momento quando specifichi i valori dei parametri.
- label è un identificatore leggibile per lo sviluppatore che gli consente di sapere cosa fa il parametro.
- description fornisce una descrizione dettagliata del valore. Poiché supporta Markdown, può collegarsi a documentazione aggiuntiva o evidenziare parole che potrebbero essere importanti per lo sviluppatore.
- type definisce il meccanismo di input per il modo in cui un utente imposta il valore del parametro. Esistono molti tipi, tra cui
string
,select
,multiSelect
,selectResource
esecret
. Per saperne di più su ciascuna di queste opzioni, consulta la documentazione. - validationRegex vincola l'inserimento dello sviluppatore a un determinato valore regex (nell'esempio si basa sulle semplici linee guida per i nomi dei campi disponibili qui) e, in caso di errore…
- validationErrorMessage avvisa lo sviluppatore del valore di errore.
- default è il valore che avrebbe se lo sviluppatore non avesse inserito alcun testo.
- Obbligatorio significa che lo sviluppatore non è tenuto a inserire alcun testo.
- immutable consente allo sviluppatore di aggiornare questa estensione e modificare questo valore. In questo caso, lo sviluppatore dovrebbe essere in grado di modificare i nomi dei campi man mano che cambiano i suoi requisiti.
- example fornisce un'idea di come potrebbe essere un input valido.
Quante cose da capire!
- Prima di aggiungere un parametro speciale, devi aggiungere altri tre parametri al file
extension.yaml
.
- param: INPUTPATH
label: The input document to listen to for changes
description: >-
This is the document where you write an x and y value to. Once
that document has received a value, it notifies the extension to
calculate a geohash and store that in an output document in a certain
field. This accepts function [wildcard parameters](https://firebase.google.com/docs/functions/firestore-events#wildcards-parameters)
type: string
validationRegex: ^[^/]+(/[^/]*/[^/]*)*/[^/]+$
validationErrorMessage: >-
This must point to a document path, not a collection path from the root
of the database. It must also not start or end with a '/' character.
required: true
immutable: false
example: users/{uid}
- param: OUTPUTFIELD
label: Geohash field
description: >-
This specifies the field in the output document to store the geohash in.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
required: false
default: hash
immutable: false
example: hash
Definire i parametri sensibili
Ora devi gestire la chiave API specificata dall'utente. Si tratta di una stringa sensibile che non deve essere archiviata in testo normale nella funzione. Archivia invece questo valore in Cloud Secret Manager. Si tratta di una posizione speciale nel cloud che archivia i secret criptati e ne impedisce la divulgazione accidentale. Ciò richiede allo sviluppatore di pagare per l'utilizzo di questo servizio, ma aggiunge un ulteriore livello di sicurezza alle chiavi API e potenzialmente limita le attività fraudolente. La documentazione utente avvisa lo sviluppatore che si tratta di un servizio a pagamento, in modo che non ci siano sorprese nella fatturazione. Nel complesso, l'utilizzo è simile a quello delle altre risorse stringa menzionate sopra. L'unica differenza è il tipo, chiamato secret
.
- Nel file
extension.yaml
, aggiungi il seguente codice:
extension.yaml
- param: APIKEY
label: GeohashService API Key
description: >-
Your geohash service API Key. Since this is a demo, and not a real
service, you can use : 1234567890.
type: secret
required: true
immutable: false
Aggiorna gli attributi resource
per utilizzare i parametri
Come accennato in precedenza, la risorsa (non la funzione) definisce il modo in cui viene osservata, pertanto la risorsa locationUpdate
deve essere aggiornata per utilizzare il nuovo parametro.
- Nel file
extension.yaml
, aggiungi il seguente codice:
extension.yaml
## Change from this
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}]
## To this
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/${INPUTPATH}
Controlla il file extension.yaml
- Rivedi il file
extension.yaml
. Il sito dovrebbe avere il seguente aspetto:
extension.yaml
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
displayName: Latitude and Longitude to GeoHash converter
description: A converter for changing your Latitude and Longitude coordinates to geohashes.
license: Apache-2.0 # The license you want to use for the extension
author:
authorName: Sparky
url: https://github.com/Firebase
billingRequired: true
params:
- param: XFIELD
label: The X Field Name
description: >-
The X Field is also known as the **longitude** value. What does
your Firestore instance refer to as the X value or the longitude
value. If you don't provide a value for this field, the extension will use 'xv' as the default value.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: xv
required: false
immutable: false
example: xv
- param: YFIELD
label: The Y Field Name
description: >-
The Y Field is also known as the **latitude** value. What does
your Firestore instance refer to as the Y value or the latitude
Value. If you don't provide a value for this field, the extension will use 'yv' as the default value.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: yv
required: false
immutable: false
example: yv
- param: INPUTPATH
label: The input document to listen to for changes
description: >-
This is the document where you write an x and y value to. Once
that document has been modified, it notifies the extension to
compute a geohash and store that in an output document in a certain
field. This accepts function [wildcard parameters](https://firebase.google.com/docs/functions/firestore-events#wildcards-parameters)
type: string
validationRegex: ^[^/]+(/[^/]*/[^/]*)*/[^/]+$
validationErrorMessage: >-
This must point to a document path, not a collection path from the root
of the database. It must also not start or end with a '/' character.
required: true
immutable: false
example: users/{uid}
- param: OUTPUTFIELD
label: Geohash field
description: >-
This specifies the field in the output document to store the geohash in.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
required: false
default: hash
immutable: false
example: hash
- param: APIKEY
label: GeohashService API Key
description: >-
Your geohash service API Key. Since this is a demo, and not a real
service, you can use : 1234567890.
type: secret
required: true
immutable: false
resources:
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/${INPUTPATH}
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
Accedere ai parametri nel codice
Ora che tutti i parametri sono configurati nel file extension.yaml
, aggiungili al file index.ts
.
- Nel file
index.ts
, sostituisci i valori predefiniti conprocess.env.PARAMETER_NAME
, che recupera i valori dei parametri appropriati e li inserisce nel codice della funzione di cui è stato eseguito il deployment nel progetto Firebase dello sviluppatore.
index.ts
// Replace this:
const documentPath = "users/{uid}";
const xField = "xv";
const yField = "yv";
const apiKey = "1234567890";
const outputField = "hash";
// with this:
const documentPath = process.env.INPUTPATH!; // this value is ignored since its read from the resource
const xField = process.env.XFIELD!;
const yField = process.env.YFIELD!;
const apiKey = process.env.APIKEY!;
const outputField = process.env.OUTPUTFIELD!;
In genere, vuoi eseguire controlli null con i valori delle variabili di ambiente, ma in questo caso ritieni che i valori dei parametri vengano copiati correttamente. Ora il codice è configurato per funzionare con i parametri dell'estensione.
7. Creare la documentazione per gli utenti
Prima di testare il codice su emulatori o nel marketplace delle estensioni Firebase, l'estensione deve essere documentata in modo che gli sviluppatori sappiano cosa ottengono quando la utilizzano.
- Inizia creando il file
PREINSTALL.md
, che viene utilizzato per descrivere la funzionalità, eventuali prerequisiti per l'installazione e potenziali implicazioni di fatturazione.
PREINSTALL.md
Use this extension to automatically convert documents with a latitude and
longitude to a geohash in your database. Additionally, this extension includes a callable function that allows users to make one-time calls
to convert an x,y coordinate into a geohash.
Geohashing is supported for latitudes between 90 and -90 and longitudes
between 180 and -180.
#### Third Party API Key
This extension uses a fictitious third-party API for calculating the
geohash. You need to supply your own API keys. (Since it's fictitious,
you can use 1234567890 as an API key).
#### Additional setup
Before installing this extension, make sure that you've [set up a Cloud
Firestore database](https://firebase.google.com/docs/firestore/quickstart) in your Firebase project.
After installing this extension, you'll need to:
- Update your client code to point to the callable geohash function if you
want to perform arbitrary geohashes.
Detailed information for these post-installation tasks are provided after
you install this extension.
#### 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:
- Cloud Firestore
- Cloud Functions (Node.js 16+ runtime. [See
FAQs](https://firebase.google.com/support/faq#extensions-pricing))
- [Cloud Secret Manager](https://cloud.google.com/secret-manager/pricing)
- Per risparmiare tempo nella scrittura di
README.md
per questo progetto, utilizza il metodo pratico:
firebase ext:info . --markdown > README.md
Questa operazione combina i contenuti del file PREINSTALL.md
e i dettagli aggiuntivi sull'estensione del file extension.yaml
.
Infine, comunica allo sviluppatore dell'estensione alcuni dettagli aggiuntivi relativi all'estensione appena installata. Lo sviluppatore potrebbe ricevere ulteriori istruzioni e informazioni dopo aver completato l'installazione e potrebbe ricevere alcune attività post-installazione dettagliate, come la configurazione del codice client.
- Crea un file
POSTINSTALL.md
e includi le seguenti informazioni post-installazione:
POSTINSTALL.md
Congratulations on installing the geohash extension!
#### Function information
* **Firestore Trigger** - ${function:locationUpdate.name} was installed
and is invoked when both an x field (${param:XFIELD}) and y field
(${param:YFIELD}) contain a value.
* **Callable Trigger** - ${function:callableHash.name} was installed and
can be invoked by writing the following client code:
```javascript
import { getFunctions, httpsCallable } from "firebase/functions";
const functions = getFunctions();
const geoHash = httpsCallable(functions, '${function:callableHash.name}');
geoHash({ ${param:XFIELD}: -122.0840, ${param:YFIELD}: 37.4221 })
.then((result) => {
// Read result of the Cloud Function.
/** @type {any} */
const data = result.data;
const error = data.error;
if (error != null) {
console.error(`callable error : ${error}`);
}
const result = data.result;
console.log(result);
});
Monitoraggio
Come best practice, puoi monitorare l'attività dell'estensione installata, inclusi i controlli su integrità, utilizzo e log.
The output rendering looks something like this when it's deployed:
<img src="img/82b54a5c6ca34b3c.png" alt="A preview of the latitude and longitude geohash converter extension in the firebase console" width="957.00" />
## Test the extension with the full configuration
Duration: 03:00
It's time to make sure that the user-configurable extension is working the way it is intended.
* Change into the functions folder and ensure that the latest compiled version of the extensions exists. In the extensions project functions directory, call:
```console
npm run build
In questo modo, le funzioni vengono ricompilate in modo che il codice sorgente più recente sia pronto per il deployment insieme all'estensione quando viene eseguito il deployment in un emulatore o direttamente in Firebase.
Successivamente, crea una nuova directory da cui testare l'estensione. Poiché l'estensione è stata sviluppata a partire da funzioni esistenti, non eseguire il test dalla cartella in cui è stata configurata l'estensione, in quanto tenta anche di eseguire il deployment delle funzioni e delle regole di Firebase.
Installare ed eseguire test con gli emulatori Firebase
- Crea una nuova directory sul sistema host e connettila al tuo progetto Firebase utilizzando
firebase init
.
mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Da questa directory, esegui
firebase ext:install
per installare l'estensione. Sostituisci/path/to/extension
con il percorso assoluto della directory che contiene il fileextension.yaml
. Inizia il processo di installazione dell'estensione e crea un file.env
che contiene le configurazioni prima di eseguirne il push su Firebase o sugli emulatori.
firebase ext:install /path/to/extension
- Poiché stai eseguendo il deployment del progetto localmente, specifica che vuoi utilizzare un file locale anziché Google Cloud Secret Manager.
- Avvia la suite di emulatori locale:
firebase emulators:start
Installare ed eseguire test con un progetto Firebase reale
Puoi installare l'estensione in un progetto Firebase effettivo. Ti consigliamo di utilizzare un progetto di test per i test. Utilizza questo flusso di lavoro di test se vuoi testare il flusso end-to-end della tua estensione o se il trigger dell'estensione non è ancora supportato da Firebase Emulator Suite (vedi l'opzione dell'emulatore di estensioni). Gli emulatori attualmente supportano le funzioni attivate da richieste HTTP e le funzioni attivate da eventi in background per Cloud Firestore, Realtime Database e Pub/Sub.
- Crea una nuova directory sul sistema host e connettila al tuo progetto Firebase utilizzando
firebase init
.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Dopodiché, esegui
firebase ext:install
da questa directory per installare l'estensione. Sostituisci/path/to/extension
con il percorso assoluto della directory che contiene il fileextension.yaml
. Inizia il processo di installazione dell'estensione e crea un file.env
che contiene le configurazioni prima di eseguirne il push su Firebase o sugli emulatori.
firebase ext:install /path/to/extension
- Poiché vuoi eseguire il deployment direttamente su Firebase e utilizzare Google Cloud Secret Manager, devi attivare l'API Secret Manager prima di installare l'estensione.
- Esegui il deployment nel tuo progetto Firebase.
firebase deploy
Provare l'estensione
- Dopo aver eseguito
firebase deploy
ofirebase emulators:start
, vai alla scheda Firestore della console Firebase o della webview degli emulatori, a seconda dei casi. - Aggiungi un documento alla raccolta specificata dai campi
x
ey
. In questo caso, i documenti aggiornati si trovano inu/{uid}
con un campox
dixv
e un campoy
diyv
.
- Se l'installazione dell'estensione è andata a buon fine, dopo aver salvato i due campi, l'estensione crea un nuovo campo chiamato
hash
nel documento.
8. Complimenti!
Hai convertito correttamente la tua prima Cloud Function in un'estensione Firebase.
Hai aggiunto un file extension.yaml
e lo hai configurato in modo che gli sviluppatori possano selezionare la modalità di deployment dell'estensione. Poi hai creato la documentazione per gli utenti che fornisce indicazioni su cosa devono fare gli sviluppatori dell'estensione prima di configurarla e quali passaggi potrebbero dover eseguire dopo averla installata correttamente.
Ora conosci i passaggi chiave necessari per convertire una funzione Firebase in un'estensione Firebase distribuibile.