1. Antes de começar
Uma extensão do Firebase executa uma tarefa específica ou um conjunto de tarefas em resposta a solicitações HTTP ou acionando eventos de outros produtos do Firebase e do Google, como Firebase Cloud Messaging, Cloud Firestore ou Pub/Sub.
O que você construirá
Neste codelab, você criará uma extensão do Firebase para geohashing . Depois de implantada, sua extensão converte as coordenadas X e Y em geohashes em resposta a eventos do Firestore ou por meio de invocações de funções que podem ser chamadas. Isso pode ser usado como uma alternativa à implementação da biblioteca geofire em todas as plataformas de destino para armazenamento de dados, economizando seu tempo.
O que você aprenderá
- Como pegar o código existente do Cloud Functions e transformá-lo em uma extensão distribuível do Firebase
- Como configurar um arquivo
extension.yaml
- Como armazenar strings confidenciais (chaves de API) em uma extensão
- Como permitir que os desenvolvedores da extensão a configurem para atender às suas necessidades
- Como testar e implantar a extensão
O que você precisará
- Firebase CLI (instalar e fazer login)
- Uma conta do Google, como uma conta do Gmail
- Node.js e
npm
- Seu ambiente de desenvolvimento favorito
2. Prepare-se
Obtenha o código
Tudo que você precisa para esta extensão está em um repositório GitHub. Para começar, pegue o código e abra-o em seu ambiente de desenvolvimento favorito.
- Descompacte o arquivo zip baixado.
- Para instalar as dependências necessárias, abra o terminal no diretório
functions
e execute o comandonpm install
.
Configurar o Firebase
Este codelab incentiva fortemente o uso de emuladores do Firebase. Se você quiser experimentar o desenvolvimento de extensões com um projeto real do Firebase, consulte criar um projeto do Firebase . Este codelab usa o Cloud Functions. Portanto, se você estiver usando um projeto real do Firebase em vez dos emuladores, será necessário fazer upgrade para o plano de preços Blaze .
Quer avançar?
Você pode fazer download de uma versão completa do codelab. Se você tiver dúvidas ao longo do caminho ou quiser ver a aparência de uma extensão concluída, confira a ramificação codelab-end
do repositório GitHub ou baixe o zip completo.
3. Revise o código
- Abra o arquivo
index.ts
do arquivo zip. Observe que ele contém duas declarações do Cloud Functions.
O que essas funções fazem?
Essas funções de demonstração são usadas para geohashing. Eles pegam um par de coordenadas e os transformam em um formato otimizado para consultas geográficas no Firestore. As funções simulam o uso de uma chamada de API para que você possa aprender mais sobre como lidar com tipos de dados confidenciais em extensões. Para obter mais informações, consulte a documentação sobre como executar consultas geográficas em dados no Firestore .
Constantes de função
As constantes são declaradas logo no início, no topo do arquivo index.ts
. Algumas dessas constantes são referenciadas nos gatilhos definidos da extensão.
índice.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);
Gatilho do Firestore
A primeira função no arquivo index.ts
é assim:
índice.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 função é um gatilho do Firestore . Quando ocorre um evento de gravação no banco de dados, a função reage a esse evento procurando um campo xv
e um campo yv
e, se ambos os campos existirem, ela calcula o geohash e grava a saída em um local de saída de documento especificado. O documento de entrada é definido pela constante users/{uid}
, o que significa que a função lê todos os documentos escritos na coleção users/
e então processa um geohash para esses documentos. Em seguida, ele envia o hash para um campo hash no mesmo documento.
Funções que podem ser chamadas
A próxima função no arquivo index.ts
é semelhante a esta:
índice.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};
});
Observe a função onCall
. Indica que esta função é uma função que pode ser chamada , que pode ser chamada de dentro do código do seu aplicativo cliente. Esta função que pode ser chamada recebe y
x
retorna um geohash. Embora essa função não seja chamada diretamente neste codelab, ela está incluída aqui como exemplo de algo a ser configurado na extensão do Firebase.
4. Configure um arquivo extension.yaml
Agora que você sabe o que o código do Cloud Functions na sua extensão faz, está pronto para empacotá-lo para distribuição. Cada extensão do Firebase vem com um arquivo extension.yaml
que descreve o que a extensão faz e como ela se comporta.
Um arquivo extension.yaml
requer alguns metadados iniciais sobre sua extensão. Cada uma das etapas a seguir ajuda você a entender o significado de todos os campos e por que você precisa deles.
- Crie um arquivo
extension.yaml
no diretório raiz do projeto que você baixou anteriormente. Comece adicionando o seguinte:
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
O nome da extensão é usado como base do ID da instância da extensão (os usuários podem instalar várias instâncias de uma extensão, cada uma com seu próprio ID). Em seguida, o Firebase gera o nome das contas de serviço da extensão e dos recursos específicos da extensão usando esse ID de instância. O número da versão indica a versão da sua extensão. Ele deve seguir o versionamento semântico , e você precisa atualizá-lo sempre que fizer alterações na funcionalidade da extensão. A versão da especificação da extensão é usada para determinar qual especificação de extensões do Firebase seguir; neste caso, v1beta
é usada.
- Adicione alguns detalhes fáceis de usar ao arquivo YAML:
...
displayName: Latitude and longitude to GeoHash converter
description: A converter for changing your Latitude and longitude coordinates to geohashes.
O nome de exibição é uma representação amigável do nome da sua extensão quando os desenvolvedores interagem com ela. A descrição fornece uma breve visão geral do que a extensão faz. Quando a extensão é implantada em extensions.dev , ela se parece com isto:
- Especifique a licença para o código na sua extensão.
...
license: Apache-2.0 # The license you want for the extension
- Indique quem escreveu a extensão e se é necessário ou não cobrança para instalá-la:
...
author:
authorName: AUTHOR_NAME
url: https://github.com/Firebase
billingRequired: true
A seção author
é usada para permitir que seus usuários saibam com quem entrar em contato caso tenham problemas com a extensão ou desejem mais informações sobre ela. billingRequired
é um parâmetro obrigatório e deve ser definido como true
, pois todas as extensões dependem do Cloud Functions, que requer o plano Blaze.
Isso cobre o número mínimo de campos necessários no arquivo extension.yaml
para identificar esta extensão. Para obter mais detalhes sobre outras informações de identificação que você pode especificar em uma extensão, consulte a documentação .
5. Converta o código do Cloud Functions em um recurso de extensões
Um recurso de extensão é um item que o Firebase cria no projeto durante a instalação de uma extensão. A extensão então possui esses recursos e possui uma conta de serviço específica que opera neles. Neste projeto, esses recursos são Cloud Functions, que devem ser definidos no arquivo extension.yaml
porque a extensão não criará recursos automaticamente a partir do código na pasta de funções. Se suas Cloud Functions não forem declaradas explicitamente como um recurso, elas não poderão ser implantadas quando a extensão for implantada.
Local de implantação definido pelo usuário
- Permita que o usuário especifique o local onde deseja implantar esta extensão e decida se seria melhor hospedar a extensão mais perto de seus usuários finais ou mais perto de seu banco de dados. No arquivo
extension.yaml
, inclua a opção de escolher um local.
extensão.yaml
Agora você está pronto para gravar a configuração do recurso de função.
- No arquivo
extension.yaml
, crie um objeto de recurso para a funçãolocationUpdate
. Anexe o seguinte ao arquivoextension.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}
Você define o name
como o nome da função definido no arquivo index.ts
do projeto. Você especifica o type
de função que está sendo implantada, que deve ser sempre firebaseextensions.v1beta.function
, por enquanto. Em seguida, você define as properties
desta função. a primeira propriedade que você define é o eventTrigger
associado a esta função. Para espelhar o que a extensão suporta atualmente, use o eventType
de providers/cloud.firestore/eventTypes/document.write
, que é encontrado na documentação do Write Cloud Functions para sua extensão . Você define o resource
como o local dos documentos. Como seu objetivo atual é espelhar o que existe no código, o caminho do documento escuta users/{uid}
, com o local padrão do banco de dados precedendo-o.
- A extensão precisa de permissões de leitura e gravação para o banco de dados Firestore. No final do arquivo
extension.yaml
, especifique as funções do IAM às quais a extensão deve ter acesso para trabalhar com o banco de dados no projeto Firebase do desenvolvedor.
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
A função datastore.user
vem da lista de funções do IAM suportadas para extensões . Como a extensão será de leitura e gravação, a função datastore.user
é uma boa opção aqui.
- A função que pode ser chamada também deve ser adicionada. No arquivo
extension.yaml
, crie um novo recurso na propriedade resources. Estas propriedades são específicas para uma função que pode ser chamada:
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
Embora o recurso anterior usasse um eventTrigger
, aqui você usa um httpsTrigger
, que abrange funções que podem ser chamadas e funções HTTPS.
Verificação de código
Foram muitas configurações para fazer com que sua extension.yaml
correspondesse a tudo feito pelo código em seu arquivo index.ts
. Esta é a aparência do arquivo extension.yaml
concluído neste momento:
extensão.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.
Verificação de status
Neste ponto, você tem as peças funcionais iniciais da extensão configuradas, para que possa testá-la usando os emuladores do Firebase!
- Se ainda não o fez, chame
npm run build
na pasta de funções do projeto de extensões baixado. - Crie um novo diretório em seu sistema host e conecte-o ao seu projeto Firebase usando
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.
- No mesmo diretório, execute
firebase ext:install
. Substitua/path/to/extension
pelo caminho absoluto para o diretório que contém seu arquivoextension.yaml
.
firebase ext:install /path/to/extension
This command does two things:
- Ele solicita que você especifique a configuração da instância de extensão e cria um arquivo
*.env
que contém as informações de configuração da instância. - Ele adiciona a instância da extensão à seção
extensions
do seufirebase.json
. Isso funciona como um mapa do ID da instância para a versão da extensão. - Como você está implantando o projeto localmente, você pode especificar que deseja usar um arquivo local em vez do Google Cloud Secret Manager.
- Inicie os emuladores do Firebase com a nova configuração:
firebase emulators:start
- Depois de executar
emulators:start
, navegue até a guia Firestore na webview dos emuladores. - Adicione um documento à coleção
users
com um campo de númeroxv
e um campo de númeroyv
.
- Se você instalou a extensão com sucesso, ela criará um novo campo chamado
hash
no documento.
Limpe para evitar conflitos
- Depois de concluir o teste, desinstale a extensão – você atualizará o código da extensão e não deseja entrar em conflito com a extensão atual posteriormente.
As extensões permitem que várias versões da mesma extensão sejam instaladas ao mesmo tempo; portanto, ao desinstalar, você garante que não haja conflitos com uma extensão instalada anteriormente.
firebase ext:uninstall geohash-ext
A solução atual funciona, mas conforme mencionado no início do projeto, existe uma chave de API codificada para simular a comunicação com um serviço. Como você pode usar a chave API do usuário final em vez daquela fornecida originalmente? Leia mais para descobrir.
6. Torne o usuário da extensão configurável
Neste ponto do codelab, você tem uma extensão configurada para uso com a configuração opinativa das funções que você já escreveu, mas e se o usuário quiser usar latitude e longitude em vez de y e x para os campos que indicam o localização em um plano cartesiano? Além disso, como você pode fazer com que o usuário final forneça sua própria chave de API, em vez de permitir que ele consuma a chave de API fornecida? Você pode ultrapassar rapidamente a cota dessa API. Nesse caso, você configura e usa parâmetros.
Defina parâmetros básicos no arquivo extension.yaml
Comece convertendo os itens para os quais os desenvolvedores podem ter uma configuração personalizada. O primeiro seriam os parâmetros XFIELD
e YFIELD
.
- No arquivo
extension.yaml
, adicione o código a seguir, que usa os parâmetros de campoXFIELD
eYFIELD
. Esses parâmetros residem dentro da propriedade YAMLparams
definida anteriormente:
extensão.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 nomeia o parâmetro de uma forma que seja visível para você, o produtor da extensão. Use esse valor posteriormente ao especificar os valores dos parâmetros.
- label é um identificador legível para o desenvolvedor para que ele saiba o que o parâmetro faz.
- description fornece uma descrição detalhada do valor. Como oferece suporte a markdown, pode vincular a documentação extra ou destacar palavras que podem ser importantes para o desenvolvedor.
- type define o mecanismo de entrada de como um usuário definiria o valor do parâmetro. Existem muitos tipos, incluindo
string
,select
,multiSelect
,selectResource
esecret
. Para saber mais sobre cada uma dessas opções, consulte a documentação . - validaçãoRegex restringe a entrada do desenvolvedor a um determinado valor regex (no exemplo é baseado nas diretrizes simples de nome de campo encontradas aqui ); e se isso falhar...
- validaçãoErrorMessage alerta o desenvolvedor sobre o valor da falha.
- padrão é qual seria o valor se o desenvolvedor não inserisse nenhum texto.
- obrigatório significa que o desenvolvedor não é obrigado a inserir nenhum texto.
- imutável permite ao desenvolvedor atualizar esta extensão e alterar este valor. Nesse caso, o desenvolvedor deve ser capaz de alterar os nomes dos campos à medida que seus requisitos mudam.
- O exemplo fornece uma ideia de como pode ser uma entrada válida.
Isso foi muito para entender!
- Você tem mais três parâmetros para adicionar ao arquivo
extension.yaml
antes de adicionar um 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
Definir parâmetros sensíveis
Agora, você precisa gerenciar a chave de API especificada pelo usuário. Esta é uma string confidencial que não deve ser armazenada em texto simples na função. Em vez disso, armazene esse valor no Cloud secret manager . Este é um local especial na nuvem que armazena segredos criptografados e evita que sejam vazados acidentalmente. Isso exige que o desenvolvedor pague pelo uso deste serviço, mas adiciona uma camada extra de segurança às suas chaves de API e limita potencialmente atividades fraudulentas. A documentação do usuário alerta o desenvolvedor que se trata de um serviço pago, para que não haja surpresas no faturamento. No geral, o uso é semelhante aos outros recursos de string mencionados acima. A única diferença é o tipo chamado secret
.
- No arquivo
extension.yaml
, adicione o seguinte código:
extensão.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
Atualize os atributos resource
para usar parâmetros
Conforme mencionado anteriormente, o recurso (não a função) define como o recurso é observado, portanto o recurso locationUpdate
precisa ser atualizado para usar o novo parâmetro.
- No arquivo
extension.yaml
, adicione o seguinte código:
extensão.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}
Verifique o arquivo extension.yaml
- Revise o arquivo
extension.yaml
. Deve ser algo assim:
extensão.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.
Acessar parâmetros no código
Agora que todos os parâmetros estão configurados no arquivo extension.yaml
, adicione-os ao arquivo index.ts
.
- No arquivo
index.ts
, substitua os valores padrão porprocess.env.PARAMETER_NAME
, que busca os valores de parâmetro apropriados e os preenche no código de função implantado no projeto Firebase do desenvolvedor.
índice.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!;
Normalmente, você deseja realizar verificações nulas com os valores das variáveis de ambiente, mas, neste caso, você confia que os valores dos parâmetros foram copiados corretamente. O código agora está configurado para funcionar com os parâmetros de extensão.
7. Crie documentação do usuário
Antes de testar o código em emuladores ou no mercado de extensões do Firebase, a extensão precisa ser documentada para que os desenvolvedores saibam o que estão obtendo ao usá-la.
- Comece criando o arquivo
PREINSTALL.md
, que é usado para descrever a funcionalidade, quaisquer pré-requisitos para instalação e possíveis implicações de faturamento.
PRÉ-INSTALAR.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 economizar tempo escrevendo o
README.md
para este projeto, use o método de conveniência:
firebase ext:info . --markdown > README.md
Isso combina o conteúdo do arquivo PREINSTALL.md
e detalhes adicionais sobre a extensão do arquivo extension.yaml
.
Por fim, informe ao desenvolvedor da extensão alguns detalhes adicionais sobre a extensão que acabou de ser instalada. O desenvolvedor pode obter algumas instruções e informações adicionais após concluir a instalação e pode obter algumas tarefas detalhadas de pós-instalação, como configurar o código do cliente aqui.
- Crie um arquivo
POSTINSTALL.md
e inclua as seguintes informações pós-instalação:
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);
});
Monitoramento
Como prática recomendada, você pode monitorar a atividade da extensão instalada, incluindo verificações de integridade, uso e 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
Isso recompila as funções para que o código-fonte mais recente esteja pronto para implantação junto com a extensão quando for implantado em um emulador ou diretamente no Firebase.
Em seguida, crie um novo diretório para testar a extensão. Como a extensão foi desenvolvida a partir de funções existentes, não teste na pasta em que a extensão foi configurada, pois ela também tenta implantar as funções e as regras do Firebase junto com ela.
Instale e teste com os emuladores do Firebase
- Crie um novo diretório em seu sistema host e conecte-o ao seu projeto Firebase usando
firebase init
.
mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Nesse diretório, execute
firebase ext:install
para instalar a extensão. Substitua/path/to/extension
pelo caminho absoluto para o diretório que contém seu arquivoextension.yaml
. Isso inicia o processo de instalação da sua extensão e cria um arquivo.env
que contém suas configurações antes de enviar a configuração para o Firebase ou para os emuladores.
firebase ext:install /path/to/extension
- Como você está implantando o projeto localmente, especifique que deseja usar um arquivo local em vez do Google Cloud Secret Manager.
- Inicie o conjunto de emuladores locais:
firebase emulators:start
Instale e teste com um projeto real do Firebase
Você pode instalar sua extensão em um projeto real do Firebase. Recomenda-se usar um projeto de teste para seus testes. Use este fluxo de trabalho de teste se quiser testar o fluxo de ponta a ponta da sua extensão ou se o gatilho da sua extensão ainda não for compatível com o conjunto de emuladores do Firebase (consulte a opção Emulador de extensões ). Atualmente, os emuladores são compatíveis com funções acionadas por solicitação HTTP e funções acionadas por eventos em segundo plano para Cloud Firestore, Realtime Database e Pub/Sub.
- Crie um novo diretório em seu sistema host e conecte-o ao seu projeto Firebase usando
firebase init
.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Em seguida, nesse diretório, execute
firebase ext:install
para instalar a extensão. Substitua/path/to/extension
pelo caminho absoluto para o diretório que contém seu arquivoextension.yaml
. Isso inicia o processo de instalação da sua extensão e cria um arquivo.env
que contém suas configurações antes de enviar a configuração para o Firebase ou para os emuladores.
firebase ext:install /path/to/extension
- Como você deseja implantar diretamente no Firebase e usar o Google Cloud Secret Manager, é necessário ativar a API Secret Manager antes de instalar a extensão.
- Implante em seu projeto do Firebase.
firebase deploy
Teste a extensão
- Depois de executar
firebase deploy
oufirebase emulators:start
, navegue até a guia Firestore do console do Firebase ou o webview dos emuladores, conforme apropriado. - Adicione um documento à coleção especificada pelos campos
x
ey
. Nesse caso, os documentos atualizados estão localizados emu/{uid}
com um campox
dexv
e um campoy
deyv
.
- Se você instalou a extensão com sucesso, ela criará um novo campo chamado
hash
no documento após salvar os dois campos.
8. Parabéns!
Você converteu com sucesso sua primeira Cloud Function em uma extensão do Firebase!
Você adicionou um arquivo extension.yaml
e o configurou para que os desenvolvedores possam selecionar como gostariam que sua extensão fosse implantada. Em seguida, você criou a documentação do usuário que fornece orientação sobre o que os desenvolvedores da extensão devem fazer antes de configurar a extensão e quais etapas eles podem precisar seguir após instalarem a extensão com êxito.
Agora você conhece as principais etapas necessárias para converter uma função do Firebase em uma extensão do Firebase distribuível.