1. Antes de comenzar
Una extensión de Firebase realiza una tarea o un conjunto de tareas específicos en respuesta a solicitudes HTTP o a eventos de activación de otros productos de Firebase y Google, como Firebase Cloud Messaging, Cloud Firestore o Pub/Sub.
Qué compilarás
En este codelab, crearás una extensión de Firebase para el geohashing. Una vez implementada, la extensión convierte las coordenadas X e Y en geohashes en respuesta a eventos de Firestore o mediante invocaciones de funciones que admiten llamadas. Esto se puede usar como alternativa a implementar la biblioteca de geofire en todas tus plataformas de destino para almacenar datos, lo que te ahorrará tiempo.
Qué aprenderás
- Cómo tomar el código existente de Cloud Functions y convertirlo en una extensión de Firebase distribuible
- Cómo configurar un archivo
extension.yaml
- Cómo almacenar cadenas sensibles (claves de API) en una extensión
- Cómo permitir que los desarrolladores de la extensión la configuren según sus necesidades
- Cómo probar e implementar la extensión
Requisitos
- Firebase CLI (instalación y acceso)
- Una Cuenta de Google, como una cuenta de Gmail
- Node.js y
npm
- Tu entorno de desarrollo favorito
2. Prepárate
Obtén el código
Todo lo que necesitas para esta extensión se encuentra en un repositorio de GitHub. Para comenzar, toma el código y ábrelo en tu entorno de desarrollo favorito.
- Descomprime el archivo ZIP que se descargó.
- Para instalar las dependencias requeridas, abre la terminal en el directorio
functions
y ejecuta el comandonpm install
.
Configura Firebase
En este codelab, se recomienda encarecidamente el uso de emuladores de Firebase. Si quieres probar el desarrollo de extensiones con un proyecto de Firebase real, consulta Cómo crear un proyecto de Firebase. En este codelab, se usa Cloud Functions. Por lo tanto, si utilizas un proyecto real de Firebase en lugar de los emuladores, debes actualizar al plan de precios Blaze.
¿Quieres avanzar?
Puedes descargar una versión completa del codelab. Si no puedes avanzar o si quieres ver cómo se ve una extensión completada, consulta la rama codelab-end
del repositorio de GitHub o descarga el archivo ZIP completado.
3. Revisa el código
- Abre el archivo
index.ts
del archivo ZIP. Ten en cuenta que contiene dos declaraciones de Cloud Functions.
¿Qué hacen estas funciones?
Estas funciones de demostración se usan para el geohashing. Toman un par de coordenadas y las convierten en un formato optimizado para consultas geográficas en Firestore. Las funciones simulan el uso de una llamada a la API para que puedas obtener más información sobre el manejo de tipos de datos sensibles en las extensiones. Para obtener más información, revisa la documentación sobre cómo ejecutar consultas de ubicación geográfica en datos en Firestore.
Constantes de función
Las constantes se declaran al principio, en la parte superior del archivo index.ts
. Se hace referencia a algunas de estas constantes en los activadores definidos de la extensión.
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);
Activador de Firestore
La primera función en el archivo index.ts
se ve de la siguiente manera:
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,
}
);
});
Esta función es un activador de Firestore. Cuando ocurre un evento de escritura en la base de datos, la función reacciona a ese evento mediante la búsqueda de un campo xv
y un campo yv
y, si ambos campos existen, calcula el geohash y escribe el resultado en una ubicación de salida del documento especificada. La constante users/{uid}
define el documento de entrada, lo que significa que la función lee todos los documentos escritos en la colección users/
y, luego, procesa un geohash para esos documentos. Luego, genera el hash en un campo de hash en el mismo documento.
Funciones que admiten llamadas
La siguiente función en el archivo index.ts
se ve de la siguiente manera:
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};
});
Observa la función onCall
. Indica que esta es una función que admite llamadas, a la que se puede llamar desde el código de tu aplicación cliente. Esta función que se puede llamar toma los parámetros x
y y
y muestra un geohash. Aunque no se llamará a esta función directamente en este codelab, se incluye aquí como ejemplo de algo que se debe configurar en la extensión de Firebase.
4. Configura un archivo extension.yaml
Ahora que sabes qué hace el código de Cloud Functions en tu extensión, puedes empaquetarlo para su distribución. Cada extensión de Firebase incluye un archivo extension.yaml
que describe lo que hace y su comportamiento.
Un archivo extension.yaml
requiere algunos metadatos iniciales sobre tu extensión. Cada uno de los siguientes pasos te ayudará a comprender qué significan todos los campos y por qué los necesitas.
- Crea un archivo
extension.yaml
en el directorio raíz del proyecto que descargaste antes. Comienza por agregar lo siguiente:
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
El nombre de la extensión se usa como base del ID de instancia de la extensión (los usuarios pueden instalar varias instancias de una extensión, cada una con su propio ID). Luego, Firebase genera el nombre de las cuentas de servicio y los recursos específicos de la extensión con ese ID de instancia. El número de versión indica la versión de tu extensión. Debe cumplir con el control de versiones semántico y debes actualizarlo cada vez que realices cambios en la funcionalidad de la extensión. La versión de la especificación de la extensión se usa para determinar qué especificación de Extensiones de Firebase debe seguirse. En este caso, se usa v1beta
.
- Agrega algunos detalles fáciles de usar al archivo YAML:
...
displayName: Latitude and longitude to GeoHash converter
description: A converter for changing your Latitude and longitude coordinates to geohashes.
El nombre visible es una representación amigable del nombre de tu extensión cuando los desarrolladores interactúan con ella. La descripción proporciona una breve descripción general de lo que hace la extensión. Cuando la extensión se implementa en extensions.dev, se ve de la siguiente manera:
- Especifica la licencia del código de tu extensión.
...
license: Apache-2.0 # The license you want for the extension
- Indica quién escribió la extensión y si se requiere facturación para instalarla:
...
author:
authorName: AUTHOR_NAME
url: https://github.com/Firebase
billingRequired: true
La sección author
se usa para que los usuarios sepan con quién comunicarse en caso de que tengan problemas con la extensión o quieran más información sobre ella. billingRequired
es un parámetro obligatorio y se debe establecer en true
, ya que todas las extensiones dependen de Cloud Functions, que requiere el plan Blaze.
Aquí se incluye la cantidad mínima de campos requeridos en el archivo extension.yaml
para identificar esta extensión. Para obtener más detalles sobre otra información de identificación que puedes especificar en una extensión, consulta la documentación.
5. Convierte el código de Cloud Functions en un recurso de Extensiones
Un recurso de extensión es un elemento que Firebase crea en el proyecto durante la instalación de una extensión. Luego, la extensión es propietaria de esos recursos y tiene una cuenta de servicio específica que opera en ellos. En este proyecto, esos recursos son Cloud Functions, que se deben definir en el archivo extension.yaml
porque la extensión no creará recursos automáticamente a partir del código en la carpeta de funciones. Si tus Cloud Functions no se declaran explícitamente como un recurso, no se podrán implementar cuando se implemente la extensión.
Ubicación de implementación definida por el usuario
- Permite que el usuario especifique la ubicación en la que desea implementar esta extensión y decida si es mejor alojar la extensión más cerca de sus usuarios finales o de su base de datos. En el archivo
extension.yaml
, incluye la opción para elegir una ubicación.
extension.yaml
Ya está todo listo para escribir la configuración del recurso de la función.
- En el archivo
extension.yaml
, crea un objeto de recurso para la funciónlocationUpdate
. Agrega lo siguiente al archivoextension.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}
Define name
como el nombre de la función definido en el archivo index.ts
del proyecto. Especificas el type
de la función que se implementará, que por ahora siempre debe ser firebaseextensions.v1beta.function
. Luego, defines el properties
de esta función. La primera propiedad que defines es el eventTrigger
asociado con esta función. Para duplicar lo que la extensión admite actualmente, usa el eventType
de providers/cloud.firestore/eventTypes/document.write
, que se encuentra en la documentación Escribe Cloud Functions para tu extensión. Define resource
como la ubicación de los documentos. Dado que tu objetivo actual es duplicar lo que existe en el código, la ruta de acceso del documento escucha users/{uid}
, con la ubicación predeterminada de la base de datos que la precede.
- La extensión necesita permisos de lectura y escritura para la base de datos de Firestore. Al final del archivo
extension.yaml
, especifica los roles de IAM a los que debe tener acceso la extensión para trabajar con la base de datos en el proyecto de Firebase del desarrollador.
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
El rol datastore.user
proviene de la lista de roles de IAM admitidos para extensiones. Como la extensión será de lectura y escritura, el rol de datastore.user
es una buena opción en este caso.
- También se debe agregar la función que admite llamadas. En el archivo
extension.yaml
, crea un recurso nuevo en la propiedad resources. Estas propiedades son específicas de una función que se puede llamar:
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
Aunque el recurso anterior usaba un eventTrigger
, aquí debes usar un httpsTrigger
, que abarca funciones que admiten llamadas y funciones HTTPS.
Verificación de código
Fue mucha configuración para que tu extension.yaml
coincida con todo lo que hace el código en tu archivo index.ts
. El archivo extension.yaml
completo debería verse de la siguiente manera en este momento:
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.
Verificación de estado
En este punto, tienes configuradas las partes funcionales iniciales de la extensión, por lo que puedes probarla con los emuladores de Firebase.
- Si aún no lo hiciste, llama a
npm run build
en la carpeta de funciones del proyecto de extensiones descargado. - Crea un directorio nuevo en tu sistema host y conéctalo a tu proyecto de Firebase con
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.
- Desde el mismo directorio, ejecuta
firebase ext:install
. Reemplaza/path/to/extension
por la ruta de acceso absoluta al directorio que contiene tu archivoextension.yaml
.
firebase ext:install /path/to/extension
This command does two things:
- Te solicitará que especifiques la configuración de la instancia de extensión y crea un archivo
*.env
que contiene la información de configuración de la instancia. - Agrega la instancia de extensión a la sección
extensions
de tufirebase.json
. Esto actúa como una asignación del ID de instancia a la versión de la extensión. - Como implementarás el proyecto de forma local, puedes especificar que deseas usar un archivo local en lugar de Secret Manager de Google Cloud.
- Inicia los emuladores de Firebase con la nueva configuración:
firebase emulators:start
- Después de ejecutar
emulators:start
, navega a la pestaña de Firestore en la WebView de los emuladores. - Agrega un documento a la colección
users
con un campo de númeroxv
y un campo de númeroyv
.
- Si instalaste correctamente la extensión, esta creará un campo nuevo llamado
hash
en el documento.
Realiza una limpieza para evitar conflictos
- Una vez que hayas terminado la prueba, desinstala la extensión. Actualizarás el código de la extensión y no querrás entrar en conflicto con la extensión actual.
Las extensiones permiten instalar varias versiones de la misma extensión a la vez, por lo que, cuando las desinstalas, te aseguras de que no haya conflictos con una extensión instalada anteriormente.
firebase ext:uninstall geohash-ext
La solución actual funciona, pero como se mencionó al comienzo del proyecto, hay una clave de API hard-coded para simular la comunicación con un servicio. ¿Cómo puedes usar la clave de API del usuario final en lugar de la que se proporcionó originalmente? Continúa leyendo y descúbrelo.
6. Haz que el usuario pueda configurar la extensión
En este punto del codelab, tienes una extensión que está configurada para usar con la configuración definida de las funciones que ya escribiste, pero ¿qué sucede si el usuario quiere usar latitud y longitud en lugar de y y x para los campos que indican la ubicación en un plano cartesiano? Además, ¿cómo puedes hacer que el usuario final proporcione su propia clave de API, en lugar de permitir que consuma la clave de API proporcionada? Podrías sobrepasar rápidamente la cuota para esa API. En este caso, configuras y usas parámetros.
Define los parámetros básicos en el archivo extension.yaml
Comienza por convertir los elementos para los que los desarrolladores puedan tener una configuración personalizada. El primero serían los parámetros XFIELD
y YFIELD
.
- En el archivo
extension.yaml
, agrega el siguiente código, que usa los parámetros de campoXFIELD
yYFIELD
. Estos parámetros se encuentran dentro de la propiedad YAMLparams
definida anteriormente:
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 asigna un nombre al parámetro de una manera que tú, el productor de la extensión, puedas ver. Usa este valor más adelante cuando especifiques los valores de los parámetros.
- label es un identificador legible por humanos para el desarrollador que le permite saber qué hace el parámetro.
- description proporciona una descripción detallada del valor. Dado que admite Markdown, puede vincular a documentación adicional o destacar palabras que podrían ser importantes para el desarrollador.
- type define el mecanismo de entrada sobre la forma en que un usuario establecería el valor del parámetro. Existen muchos tipos, incluidos
string
,select
,multiSelect
,selectResource
ysecret
. Para obtener más información sobre cada una de estas opciones, consulta la documentación. - validationRegex restringe la entrada del desarrollador a un valor de regex determinado (en el ejemplo, se basa en los lineamientos de nombres de campos simples que se encuentran aquí). Si eso falla…
- validationErrorMessage alerta al desarrollador sobre el valor de error.
- default es el valor que tendría si el desarrollador no ingresara texto.
- obligatorio significa que el desarrollador no tiene la obligación de ingresar texto.
- inmutable permite al desarrollador actualizar esta extensión y cambiar este valor. En este caso, el desarrollador debería poder modificar los nombres de campo a medida que cambian los requisitos.
- example brinda una idea de cómo se vería una entrada válida.
¡Eso fue mucho para entender!
- Tienes tres parámetros más para agregar al archivo
extension.yaml
antes de agregar un parámetro especial.
- 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
Define parámetros sensibles
Ahora, debes administrar la clave de API que especifica el usuario. Esta es una cadena sensible que no se debe almacenar en texto sin formato en la función. En su lugar, almacena este valor en Cloud Secret Manager. Esta es una ubicación especial en la nube que almacena secretos encriptados y evita que se filtren accidentalmente. Esto requiere que el desarrollador pague por el uso de este servicio, pero agrega una capa adicional de seguridad a sus claves de API y, potencialmente, limita la actividad fraudulenta. La documentación para el usuario le informa al desarrollador que se trata de un servicio pagado para que no haya sorpresas en la facturación. En general, el uso es similar al de los otros recursos de cadenas mencionados anteriormente. La única diferencia es el tipo, que se llama secret
.
- En el archivo
extension.yaml
, agrega el siguiente código:
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
Actualiza los atributos resource
para usar parámetros
Como se mencionó anteriormente, el recurso (no la función) define cómo se observa el recurso, por lo que se debe actualizar el recurso locationUpdate
para usar el nuevo parámetro.
- En el archivo
extension.yaml
, agrega el siguiente código:
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}
Revisa el archivo extension.yaml
.
- Revisa el archivo
extension.yaml
. Debería verse algo similar a esto:
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.
Cómo acceder a los parámetros en el código
Ahora que todos los parámetros están configurados en el archivo extension.yaml
, agrégalos al archivo index.ts
.
- En el archivo
index.ts
, reemplaza los valores predeterminados porprocess.env.PARAMETER_NAME
, que recupera los valores de parámetros adecuados y los propaga en el código de la función implementado en el proyecto de Firebase del desarrollador.
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!;
Por lo general, debes realizar verificaciones nulas con los valores de las variables de entorno, pero en este caso, confías en que los valores de los parámetros se copian correctamente. Ahora, el código está configurado para funcionar con los parámetros de la extensión.
7. Crear documentación para el usuario
Antes de probar el código en emuladores o en el mercado de extensiones de Firebase, se debe documentar la extensión para que los desarrolladores sepan qué obtienen cuando la usan.
- Comienza por crear el archivo
PREINSTALL.md
, que se usa para describir la funcionalidad, los requisitos previos para la instalación y las posibles implicaciones de facturación.
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)
- Para ahorrar tiempo en la escritura del
README.md
de este proyecto, usa el método útil:
firebase ext:info . --markdown > README.md
Esto combina el contenido del archivo PREINSTALL.md
y los detalles adicionales sobre la extensión del archivo extension.yaml
.
Por último, infórmale al desarrollador de la extensión algunos detalles adicionales sobre la extensión que se acaba de instalar. Es posible que el desarrollador reciba instrucciones y más información después de completar la instalación, así como tareas detalladas posteriores a la instalación, como configurar el código del cliente aquí.
- Crea un archivo
POSTINSTALL.md
y, luego, incluye la siguiente información posterior a la instalación:
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);
});
Supervisión
Como práctica recomendada, puedes supervisar la actividad de la extensión instalada, incluidas las verificaciones de estado, uso y registros.
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
Esto vuelve a compilar las funciones para que el código fuente más reciente esté listo para implementarse junto con la extensión cuando se implemente en un emulador o directamente en Firebase.
A continuación, crea un directorio nuevo para probar la extensión. Dado que la extensión se desarrolló a partir de funciones existentes, no realices pruebas desde la carpeta en la que se configuró la extensión, ya que esto también intenta implementar las funciones y las reglas de Firebase junto con ella.
Instala y prueba con los emuladores de Firebase
- Crea un directorio nuevo en tu sistema host y conéctalo a tu proyecto de Firebase con
firebase init
.
mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Desde ese directorio, ejecuta
firebase ext:install
para instalar la extensión. Reemplaza/path/to/extension
por la ruta de acceso absoluta al directorio que contiene tu archivoextension.yaml
. Esto inicia el proceso de instalación de tu extensión y crea un archivo.env
que contiene tus parámetros de configuración antes de enviarlos a Firebase o a los emuladores.
firebase ext:install /path/to/extension
- Dado que implementarás el proyecto de manera local, especifica que te gustaría usar un archivo local en lugar de Secret Manager de Google Cloud.
- Inicia Local Emulator Suite:
firebase emulators:start
Instala y prueba con un proyecto real de Firebase
Puedes instalar tu extensión en un proyecto real de Firebase. Se recomienda usar un proyecto de prueba. Usa este flujo de trabajo de prueba si quieres probar el flujo de extremo a extremo de tu extensión o si el activador de la extensión aún no es compatible con Firebase Emulator Suite (consulta la opción del emulador de extensiones). Actualmente, los emuladores admiten funciones que se activan por medio de solicitudes HTTP y por eventos en segundo plano para Cloud Firestore, Realtime Database y Pub/Sub.
- Crea un directorio nuevo en tu sistema host y conéctalo a tu proyecto de Firebase con
firebase init
.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Luego, desde ese directorio, ejecuta
firebase ext:install
para instalar la extensión. Reemplaza/path/to/extension
por la ruta de acceso absoluta al directorio que contiene tu archivoextension.yaml
. Esto inicia el proceso de instalación de tu extensión y crea un archivo.env
que contiene tus parámetros de configuración antes de enviarlos a Firebase o a los emuladores.
firebase ext:install /path/to/extension
- Como quieres realizar implementaciones directamente en Firebase y usar Secret Manager de Google Cloud, debes activar la API de Secret Manager antes de instalar la extensión.
- Realiza la implementación en tu proyecto de Firebase.
firebase deploy
Prueba la extensión
- Después de ejecutar
firebase deploy
ofirebase emulators:start
, navega a la pestaña de Firestore de Firebase console o la WebView de los emuladores, según corresponda. - Agrega un documento a la colección especificada por los campos
x
yy
. En este caso, los documentos actualizados se encuentran enu/{uid}
con un campox
dexv
y un campoy
deyv
.
- Si pudiste instalar la extensión correctamente, esta crea un nuevo campo en el documento llamado
hash
después de guardar los dos campos.
8. ¡Felicitaciones!
Convertiste correctamente tu primera Cloud Function en una extensión de Firebase.
Agregaste un archivo extension.yaml
y lo configuraste para que los desarrolladores puedan seleccionar cómo desean que se implemente tu extensión. Luego, creaste documentación para el usuario que brinda orientación sobre lo que los desarrolladores de la extensión deben hacer antes de configurarla y los pasos que podrían tener que seguir después de instalarla correctamente.
Ahora conoces los pasos clave necesarios para convertir una función de Firebase en una extensión de Firebase distribuible.