Organiza tus páginas con colecciones
Guarda y categoriza el contenido según tus preferencias.
Puedes proporcionar a los usuarios que instalan tu extensión la capacidad de insertar su propia
lógica personalizada en la ejecución de la extensión. Hay dos maneras de
lograrlo:
Eventos de Eventarc: Para brindarles a los usuarios una forma de reaccionar
de forma asíncrona a los eventos, puedes publicar en Eventarc. Los usuarios pueden implementar funciones del
controlador de eventos que, por ejemplo, envían notificaciones después de que se completan
las tareas de larga duración, o pueden definir sus propias funciones de procesamiento posterior.
Hooks síncronos: Para brindarles a los usuarios una forma de agregar lógica de bloqueo a tu
extensión, puedes agregar hooks síncronos en puntos predefinidos en el
funcionamiento de la extensión. En este punto, ejecutas una función proporcionada por el usuario
y continúas solo después de que se complete. Las tareas de procesamiento previo suelen corresponder a
esta categoría.
Una extensión puede usar uno o ambos métodos.
Eventos de Eventarc
Para publicar eventos desde una extensión, sigue estos pasos:
Declara los tipos de eventos que publicarás en el archivo extension.yaml:
El identificador type consta de varios campos delimitados por puntos. Los campos
ID de publicador, nombre de la extensión y nombre del evento son
obligatorios. Se recomienda completar el campo de versión. Elige un nombre de evento único y descriptivo
para cada tipo de evento que publiques.
events:-type:firebase.extensions.storage-resize-images.v1.completedescription:|Occurs when image resizing completes. The event will contain furtherdetails about specific formats and sizes.
Los usuarios podrán elegir a qué eventos suscribirse cuando
instalen la extensión.
En tus funciones de extensión, importa la API de Eventarc desde el Admin SDK
y, luego, inicializa un canal de eventos mediante la configuración de instalación del usuario.
Esta configuración se expone mediante las siguientes variables de entorno:
EVENTARC_CHANNEL: Es el nombre completo del canal de Eventarc en el
que el usuario eligió publicar eventos.
EXT_SELECTED_EVENTS: Es una lista separada por comas de los tipos de eventos que el usuario
eligió publicar. Cuando inicializas un canal con este valor, el
SDK de Admin filtra automáticamente los eventos que el usuario no seleccionó.
EVENTARC_CLOUD_EVENT_SOURCE: Es el identificador de origen del evento de Cloud. El
SDK de Admin pasa automáticamente este valor en el campo source de los
eventos publicados. Por lo general, no necesitas usar esta variable de forma
explícita.
Si no se habilitaron los eventos en la instalación, estas variables no
se definirán. Puedes usar este hecho para inicializar un canal de eventos solo cuando
están habilitados los eventos:
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,});
Publica eventos en el canal en los puntos de la extensión que deseas
exponer a los usuarios. Por ejemplo:
// 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:{// ...}});
Documenta los eventos que publicas, en el archivo
PREINSTALL o POSTINSTALL.
Para cada evento, documenta la siguiente información:
Su propósito previsto
El punto en la lógica de la extensión que ejecuta
Los datos de salida que incluye
Las condiciones para su ejecución
Además, advierte a los usuarios que no realicen ninguna acción en sus controladores
de eventos que pueda activar la misma extensión, lo que podría generar un bucle
infinito.
Cuando publicas eventos desde una extensión, los usuarios pueden implementar controladores
de eventos para responder con una lógica personalizada.
En el siguiente ejemplo, se borra la imagen original después de
cambiar de tamaño. Ten en cuenta que este controlador de ejemplo usa la propiedad subject del
evento, que en este caso es el nombre de archivo original de la imagen.
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();});
Usa hooks síncronos cuando desees proporcionar a los usuarios un hook que se deba completar correctamente
para que funcione una de las funciones de la extensión.
Un hook síncrono llama a una Cloud
Function que admite llamadas HTTPS definida por el usuario y espera que se complete (posiblemente con
un valor mostrado) antes de continuar. Un error en la función proporcionada por el usuario
genera un error en la función de la extensión.
Para exponer un hook síncrono, haz lo siguiente:
Agrega un parámetro a tu extensión que permita a los usuarios configurar la
extensión con la URL a su Cloud Function personalizada. Por ejemplo:
-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
En el punto de la extensión en el que deseas exponer el hook, llama a la
función con la URL. Por ejemplo:
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.// ...});
Documenta los hooks que tengas disponibles en el archivo PREINSTALL o
POSTINSTALL.
Para cada hook, documenta la siguiente información:
Su propósito previsto
El punto en la lógica de la extensión que ejecuta
Sus entradas y salidas esperadas
Las condiciones (o las opciones) para su ejecución
Además, advierte a los usuarios que no realicen ninguna acción en la función
del hook que pueda activar la misma extensión, lo que generará un bucle
infinito.
[[["Fácil de comprender","easyToUnderstand","thumb-up"],["Resolvió mi problema","solvedMyProblem","thumb-up"],["Otro","otherUp","thumb-up"]],[["Falta la información que necesito","missingTheInformationINeed","thumb-down"],["Muy complicado o demasiados pasos","tooComplicatedTooManySteps","thumb-down"],["Desactualizado","outOfDate","thumb-down"],["Problema de traducción","translationIssue","thumb-down"],["Problema con las muestras o los códigos","samplesCodeIssue","thumb-down"],["Otro","otherDown","thumb-down"]],["Última actualización: 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."]]