Mit Sammlungen den Überblick behalten
Sie können Inhalte basierend auf Ihren Einstellungen speichern und kategorisieren.
Sie können Nutzern, die Ihre Erweiterung installieren, die Möglichkeit geben, ihre eigene benutzerdefinierte Logik in die Ausführung Ihrer Erweiterung einzufügen. Dafür gibt es zwei Möglichkeiten:
Eventarc-Ereignisse: Wenn Sie Nutzern die Möglichkeit geben möchten, asynchron auf Ereignisse zu reagieren, können Sie Ereignisse in Eventarc veröffentlichen. Nutzer können Event-Handler-Funktionen bereitstellen, die beispielsweise Benachrichtigungen senden, nachdem lang andauernde Aufgaben abgeschlossen sind. Sie können auch eigene Nachbearbeitungsfunktionen definieren.
Synchrone Hooks: Damit Nutzer Ihrer Erweiterung Blockierungslogik hinzufügen können, können Sie synchrone Hooks an vordefinierten Stellen im Betrieb der Erweiterung hinzufügen. An diesen Stellen führen Sie eine Nutzeranbieterfunktion aus und fahren erst fort, wenn sie abgeschlossen ist. Vorverarbeitungsaufgaben fallen häufig in diese Kategorie.
Eine Erweiterung kann eine oder beide Methoden verwenden.
Eventarc-Ereignisse
So veröffentlichen Sie Ereignisse über eine Erweiterung:
Deklarieren Sie die Ereignistypen, die Sie veröffentlichen möchten, in der Datei extension.yaml:
Die type-Kennung besteht aus mehreren durch Punkte getrennten Feldern. Die Felder Publisher-ID, Erweiterungsname und Ereignisname sind erforderlich. Das Feld „version“ wird empfohlen. Wählen Sie für jeden veröffentlichten Ereignistyp einen eindeutigen und aussagekräftigen Ereignisnamen aus.
events:-type:firebase.extensions.storage-resize-images.v1.completedescription:|Occurs when image resizing completes. The event will contain furtherdetails about specific formats and sizes.
Nutzer können bei der Installation der Erweiterung auswählen, welche Ereignisse sie abonnieren möchten.
Importieren Sie in Ihren Erweiterungsfunktionen die Eventarc API aus Admin SDK und initialisieren Sie einen Ereigniskanal mit den Installationseinstellungen des Nutzers.
Diese Einstellungen werden über die folgenden Umgebungsvariablen verfügbar gemacht:
EVENTARC_CHANNEL: Der vollständig qualifizierte Name des Eventarc-Kanals, in dem der Nutzer Ereignisse veröffentlichen möchte.
EXT_SELECTED_EVENTS: Eine durch Kommas getrennte Liste der Ereignistypen, die der Nutzer veröffentlichen möchte. Wenn Sie einen Channel mit diesem Wert initialisieren, werden Ereignisse, die der Nutzer nicht ausgewählt hat, automatisch vom Admin SDK herausgefiltert.
EVENTARC_CLOUD_EVENT_SOURCE: die Cloud-Ereignisquellen-ID. Das Admin SDK übergibt diesen Wert automatisch im Feld source veröffentlichter Ereignisse. Normalerweise müssen Sie diese Variable nicht explizit verwenden.
Wenn Ereignisse bei der Installation nicht aktiviert wurden, sind diese Variablen nicht definiert. Sie können dies nutzen, um einen Ereigniskanal nur zu initialisieren, wenn Ereignisse aktiviert sind:
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,});
Veröffentliche Ereignisse für den Kanal an den Stellen in deiner Erweiterung, die du Nutzern präsentieren möchtest. Beispiel:
// 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:{// ...}});
Dokumentieren Sie die Ereignisse, die Sie veröffentlichen, entweder in der Datei „PREINSTALL“ oder „POSTINSTALL“.
Dokumentieren Sie für jedes Ereignis Folgendes:
Verwendungszweck
Der Punkt in der Logik Ihrer Erweiterung, an dem sie ausgeführt wird
Die enthaltenen Ausgabedaten
Die Bedingungen für die Ausführung
Weisen Sie Nutzer außerdem darauf hin, dass sie in ihren Ereignishandlern keine Aktionen ausführen dürfen, die dieselbe Erweiterung auslösen und so zu einer Endlosschleife führen könnten.
Wenn Sie Ereignisse über eine Erweiterung veröffentlichen, können Nutzer Event-Handler bereitstellen, um mit benutzerdefinierter Logik zu reagieren.
Im folgenden Beispiel wird das Originalbild gelöscht, nachdem es in der Größe angepasst wurde. In diesem Beispiel-Handler wird die subject-Eigenschaft des Ereignisses verwendet, die in diesem Fall der ursprüngliche Dateiname des Bildes ist.
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();});
Wenn Sie Nutzern einen Hook zur Verfügung stellen möchten, der erfolgreich abgeschlossen werden muss, damit eine Ihrer Erweiterungsfunktionen ausgeführt werden kann, verwenden Sie synchrone Hooks.
Bei einem synchronen Hook wird eine benutzerdefinierte per HTTPS aufrufbare Cloud-Funktion aufgerufen und auf den Abschluss gewartet (möglicherweise mit einem zurückgegebenen Wert), bevor fortgefahren wird. Ein Fehler in der vom Nutzer bereitgestellten Funktion führt zu einem Fehler in der Erweiterungsfunktion.
So stellen Sie einen synchronen Hook bereit:
Fügen Sie Ihrer Erweiterung einen Parameter hinzu, mit dem Nutzer die Erweiterung mit der URL zu ihrer benutzerdefinierten Cloud-Funktion konfigurieren können. Beispiel:
-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
Rufen Sie die Funktion an der Stelle in Ihrer Erweiterung, an der Sie den Hook verfügbar machen möchten, über die URL auf. Beispiel:
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.// ...});
Dokumentieren Sie alle Hooks, die Sie in der PREINSTALL- oder POSTINSTALL-Datei zur Verfügung stellen.
Dokumentieren Sie für jeden Hook Folgendes:
Verwendungszweck
Der Punkt in der Logik Ihrer Erweiterung, an dem sie ausgeführt wird
Die erwarteten Ein- und Ausgaben
Die Bedingungen (oder Optionen) für die Ausführung
Weisen Sie Nutzer außerdem darauf hin, dass sie in der Hook-Funktion keine Aktionen ausführen dürfen, die dieselbe Erweiterung auslösen könnten, da dies zu einer Endlosschleife führen würde.
[[["Leicht verständlich","easyToUnderstand","thumb-up"],["Mein Problem wurde gelöst","solvedMyProblem","thumb-up"],["Sonstiges","otherUp","thumb-up"]],[["Benötigte Informationen nicht gefunden","missingTheInformationINeed","thumb-down"],["Zu umständlich/zu viele Schritte","tooComplicatedTooManySteps","thumb-down"],["Nicht mehr aktuell","outOfDate","thumb-down"],["Problem mit der Übersetzung","translationIssue","thumb-down"],["Problem mit Beispielen/Code","samplesCodeIssue","thumb-down"],["Sonstiges","otherDown","thumb-down"]],["Zuletzt aktualisiert: 2025-07-25 (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."]]