Mantenha tudo organizado com as coleções
Salve e categorize o conteúdo com base nas suas preferências.
É possível fornecer aos usuários que instalam sua extensão a capacidade de inserir a própria
lógica personalizada na execução da extensão. Há duas maneiras de fazer isso:
Eventos do Eventarc: é possível publicar eventos no Eventarc para permitir que os usuários reajam de maneira assíncrona. Os usuários podem implantar funções de manipulador de eventos que, por exemplo, enviam notificações após a conclusão de tarefas de longa duração ou podem definir as próprias funções de pós-processamento.
Ganchos síncronos: para dar aos usuários uma maneira de adicionar lógica de bloqueio à sua extensão, você pode adicionar ganchos síncronos em pontos predefinidos na operação da extensão. Nesse ponto, você executa uma função de provedor de usuário
e continua somente após a conclusão. As tarefas de pré-processamento geralmente se enquadram nessa categoria.
Uma extensão pode usar um dos métodos ou ambos.
Eventos do Eventarc
Para publicar eventos usando uma extensão, siga estas instruções:
Declare os tipos de evento que serão publicados no arquivo extension.yaml:
O identificador type é composto por vários campos delimitados por pontos. Os campos ID do editor, nome da extensão e nome do evento são obrigatórios. O campo de versão é recomendado. Escolha um nome de evento exclusivo e descritivo
para cada tipo de evento publicado.
events:-type:firebase.extensions.storage-resize-images.v1.completedescription:|Occurs when image resizing completes. The event will contain furtherdetails about specific formats and sizes.
Os usuários poderão escolher em quais eventos se inscrever quando instalarem a extensão.
Nas funções de extensão, importe a API Eventarc do Admin SDK
e inicialize um canal de evento usando as configurações de instalação do usuário.
Essas configurações são expostas usando as seguintes variáveis de ambiente:
EVENTARC_CHANNEL: o nome totalmente qualificado do canal do Eventarc em que
o usuário escolheu publicar eventos.
EXT_SELECTED_EVENTS: uma lista separada por vírgulas de tipos de evento que o usuário
escolhe publicar. Quando você inicializa um canal com esse valor, o SDK Admin filtra automaticamente os eventos que o usuário não selecionou.
EVENTARC_CLOUD_EVENT_SOURCE: o identificador de origem do evento do Cloud. O SDK Admin transmite automaticamente esse valor no campo source dos eventos publicados. Normalmente, não é necessário usar explicitamente essa variável.
Se os eventos não foram ativados na instalação, essas variáveis serão indefinidas. Use esse fato para inicializar um canal de evento somente quando os eventos estiverem ativados:
import*asadminfrom"firebase-admin";import{getEventarc}from'firebase-admin/eventarc';admin.initializeApp();// Set eventChannel to a newly-initialized channel, or `undefined` if events// aren't enabled.consteventChannel=process.env.EVENTARC_CHANNEL&&
getEventarc().channel(process.env.EVENTARC_CHANNEL,{allowedEventTypes:process.env.EXT_SELECTED_EVENTS,});
Publique eventos no canal nos pontos da extensão que você quer
expor aos usuários. Exemplo:
// If events are enabled, publish a `complete` event to the configured// channel.eventChannel && eventChannel.publish({type:'firebase.extensions.storage-resize-images.v1.complete',subject:filename,// the name of the original filedata:{// ...}});
Documente os eventos publicados no arquivo PREINSTALL ou POSTINSTALL.
Para cada evento, documente o seguinte:
A finalidade
O ponto na lógica da sua extensão executada
Os dados de saída incluídos
As condições de execução
Além disso, avise os usuários para não executar nenhuma ação nos manipuladores de eventos que possam acionar a mesma extensão, resultando em um loop infinito.
Quando você publica eventos de uma extensão, os usuários podem implantar manipuladores de eventos para responder com lógica personalizada.
Por exemplo, o exemplo a seguir exclui a imagem original depois que ela é redimensionada. Observe que esse gerenciador de exemplo usa a propriedade subject do evento, que nesse caso é o nome de arquivo original da imagem.
exports.onimageresized=onCustomEventPublished("firebase.extensions.storage-resize-images.v1.complete",(event)=>{logger.info("Received image resize completed event",event);// For example, delete the original.returnadmin.storage().bucket("my-project.firebasestorage.app").file(event.subject).delete();});
Quando você quiser fornecer aos usuários um gancho que precise ser concluído com sucesso para que uma das funções de extensão funcione, use ganchos síncronos.
Um hook síncrono chama uma função do Cloud chamável HTTPS definida pelo usuário e aguarda a conclusão (possivelmente com um valor retornado) antes de continuar. Um erro na função fornecida pelo usuário resulta em um erro na função de extensão.
Para expor um hook síncrono, siga estas instruções:
Adicione um parâmetro à extensão que permita aos usuários configurar a extensão com o URL para a Função do Cloud personalizada. Exemplo:
-param:PREPROCESSING_FUNCTIONlabel:Pre-processing function URLdescription:>
An HTTPS callable function that will be called to transform the input databefore it is processed by this function.type:stringexample:https://us-west1-my-project-id.cloudfunctions.net/preprocessDatarequired:false
No ponto da extensão em que você quer expor o gancho, chame a função usando o URL dela. Exemplo:
constfunctions=require('firebase-functions/v1');constfetch=require('node-fetch');constpreprocessFunctionURL=process.env.PREPROCESSING_FUNCTION;exports.yourFunctionName=functions.firestore.document("collection/{doc_id}").onWrite((change,context)=>{// PREPROCESSING_FUNCTION hook begins here.// If a preprocessing function is defined, call it before continuing.if(preprocessFunctionURL){try{awaitfetch(preprocessFunctionURL);// Could also be a POST request if you want to send data.}catch(e){// Preprocessing failure causes the function to fail.functions.logger.error("Preprocessor error:",e);return;}}// End of PREPROCESSING_FUNCTION hook.// Main function logic follows.// ...});
Documente todos os hooks disponibilizados no arquivo PREINSTALL ou
POSTINSTALL.
Para cada hook, documente o seguinte:
A finalidade
O ponto na lógica da sua extensão executada
Entradas e resultados esperados
Condições (ou opções) de execução
Além disso, avise os usuários para não executar nenhuma ação na função de gancho que possa acionar a mesma extensão, resultando em um loop infinito.
[[["Fácil de entender","easyToUnderstand","thumb-up"],["Meu problema foi resolvido","solvedMyProblem","thumb-up"],["Outro","otherUp","thumb-up"]],[["Não contém as informações de que eu preciso","missingTheInformationINeed","thumb-down"],["Muito complicado / etapas demais","tooComplicatedTooManySteps","thumb-down"],["Desatualizado","outOfDate","thumb-down"],["Problema na tradução","translationIssue","thumb-down"],["Problema com as amostras / o código","samplesCodeIssue","thumb-down"],["Outro","otherDown","thumb-down"]],["Última atualização 2025-09-05 UTC."],[],[],null,["\u003cbr /\u003e\n\nYou can provide users who install your extension the ability to insert their own\ncustom logic into the execution of your extension. There are two ways to\naccomplish this:\n\n- **Eventarc events**: to give users a way to asynchronously react to\n events, you can publish to Eventarc. Users can deploy event handler\n functions that, for example, send notifications after long-running\n tasks complete, or they can define their own post-processing functions.\n\n- **Synchronous hooks**: to give users a way to add blocking logic to your\n extension, you can add synchronous hooks at predefined points in the\n extension's operation. At these points, you run a user-provider function\n and proceed only after it completes. Pre-processing tasks often fall under\n this category.\n\nAn extension can use either or both methods.\n\nEventarc events\n\nTo publish events from an extension:\n\n1. Declare the event types you will publish in the `extension.yaml` file:\n\n events:\n - type: publisher-id.extension-name.version.event-name\n description: event-description\n - type: publisher-id.extension-name.version.another-event-name\n description: another-event-description\n\n The `type` identifier is made of several dot-delimited fields. The\n [publisher ID](/docs/extensions/publishers/register), extension name, and event name fields are\n required. The version field is recommended. Choose a unique and descriptive\n event name for each event type you publish.\n\n For example, the [`storage-resize-images` extension](https://github.com/firebase/extensions/blob/next/storage-resize-images/extension.yaml)\n declares a single event type: \n\n events:\n - type: firebase.extensions.storage-resize-images.v1.complete\n description: |\n Occurs when image resizing completes. The event will contain further\n details about specific formats and sizes.\n\n Users will be able to choose which events to subscribe to when they\n install the extension.\n2. In your extension functions, import the Eventarc API from the Admin SDK\n and initialize an event channel using the user's installation settings.\n These settings are exposed using the following environment variables:\n\n - `EVENTARC_CHANNEL`: the fully-qualified name of the Eventarc channel to which the user chose to publish events.\n - `EXT_SELECTED_EVENTS`: a comma-separated list of event types the user chose to publish. When you initialize a channel with this value, the Admin SDK automatically filters out events user did not select.\n - `EVENTARC_CLOUD_EVENT_SOURCE`: the Cloud Event source identifier. The Admin SDK automatically passes this value in the `source` field of published events. You typically don't need to explicitly use this variable.\n\n If events weren't enabled at installation, these variables will be\n undefined. You can use this fact to initialize an event channel only when\n events are enabled: \n\n import * as admin from \"firebase-admin\";\n import {getEventarc} from 'firebase-admin/eventarc';\n\n admin.initializeApp();\n\n // Set eventChannel to a newly-initialized channel, or `undefined` if events\n // aren't enabled.\n const eventChannel =\n process.env.EVENTARC_CHANNEL &&\n getEventarc().channel(process.env.EVENTARC_CHANNEL, {\n allowedEventTypes: process.env.EXT_SELECTED_EVENTS,\n });\n\n3. Publish events to the channel at the points in your extension you want to\n expose to users. For example:\n\n // If events are enabled, publish a `complete` event to the configured\n // channel.\n eventChannel && eventChannel.publish({\n type: 'firebase.extensions.storage-resize-images.v1.complete',\n subject: filename, // the name of the original file\n data: {\n // ...\n }\n });\n\n4. Document the events you publish, in either the PREINSTALL or POSTINSTALL\n file.\n\n For each event, document the following:\n - Its intended purpose\n - The point in your extension's logic it runs\n - The output data it includes\n - The conditions for its execution\n\n Additionally, warn users not to perform any actions in their event\n handlers that might trigger the same extension, resulting in an infinite\n loop.\n\nWhen you publish events from an extension, users can deploy event handlers\nto respond with custom logic.\n\nFor example, the following example deletes the original image after it has been\nresized. Note that this example handler makes use of the `subject` property of\nthe event, which in this case is the image's original filename. \n\n exports.onimageresized = onCustomEventPublished(\n \"firebase.extensions.storage-resize-images.v1.complete\",\n (event) =\u003e {\n logger.info(\"Received image resize completed event\", event);\n // For example, delete the original.\n return admin.storage()\n .bucket(\"my-project.firebasestorage.app\")\n .file(event.subject)\n .delete();\n });\n\nSee [Custom event triggers](/docs/functions/custom-events#handle-events) for more\ninformation.\n\nExample\n\nThe official [Resize Images extension](https://github.com/firebase/extensions/tree/next/storage-resize-images)\nprovides an asynchronous hook by [publishing to Eventarc](https://github.com/firebase/extensions/blob/c29781c7e67c004e2491e4ce3c43b25b05bd3de6/storage-resize-images/functions/src/index.ts#L109-L117)\nafter resizing an image.\n\nSynchronous hooks\n\nWhen you want to provide users with a hook that must complete successfully\nfor one of your extension functions to operate, use *synchronous hooks*.\n\nA synchronous hook calls a user-defined [HTTPS callable Cloud\nFunction](/docs/functions/http-events) and awaits completion (possibly with a\nreturned value) before continuing. An error in the user-provided function\nresults in an error in the extension function.\n\nTo expose a synchronous hook:\n\n1. Add a parameter to your extension that allows users to configure the\n extension with the URL to their custom Cloud Function. For example:\n\n - param: PREPROCESSING_FUNCTION\n label: Pre-processing function URL\n description: \u003e\n An HTTPS callable function that will be called to transform the input data\n before it is processed by this function.\n type: string\n example: https://us-west1-my-project-id.cloudfunctions.net/preprocessData\n required: false\n\n2. At the point in your extension where you want to expose the hook, call the\n function using its URL. For example:\n\n const functions = require('firebase-functions/v1');\n const fetch = require('node-fetch');\n\n const preprocessFunctionURL = process.env.PREPROCESSING_FUNCTION;\n\n exports.yourFunctionName = functions.firestore.document(\"collection/{doc_id}\")\n .onWrite((change, context) =\u003e {\n // PREPROCESSING_FUNCTION hook begins here.\n // If a preprocessing function is defined, call it before continuing.\n if (preprocessFunctionURL) {\n try {\n await fetch(preprocessFunctionURL); // Could also be a POST request if you want to send data.\n } catch (e) {\n // Preprocessing failure causes the function to fail.\n functions.logger.error(\"Preprocessor error:\", e);\n return;\n }\n }\n // End of PREPROCESSING_FUNCTION hook.\n\n // Main function logic follows.\n // ...\n });\n\n3. Document any hooks you make available in either the PREINSTALL or\n POSTINSTALL file.\n\n For each hook, document the following:\n - Its intended purpose\n - The point in your extension's logic it runs\n - Its expected inputs and outputs\n - The conditions (or options) for its execution\n\n Additionally, warn users not to perform any actions in the hook\n function that might trigger the same extension, resulting in an infinite\n loop.\n\nExample\n\nThe [Algolia Search extension](https://github.com/algolia/firestore-algolia-search/)\nprovides a synchronous hook to [call a user-supplied transform function](https://github.com/algolia/firestore-algolia-search/blob/34592d513eac22691d76917874a6466032976f67/functions/src/transform.ts)\nprior to writing to Algolia."]]