Dodawanie do rozszerzenia elementów, które zaciągają użytkowników
Zadbaj o dobrą organizację dzięki kolekcji
Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.
Użytkownicy, którzy zainstalują Twoje rozszerzenie, mogą wstawiać własną logikę niestandardową do jego działania. Możesz to zrobić na 2 sposoby:
Zdarzenia Eventarc: aby umożliwić użytkownikom asynchroniczne reagowanie na zdarzenia, możesz publikować je w Eventarc. Użytkownicy mogą wdrażać funkcje obsługi zdarzeń, które np. wysyłają powiadomienia po zakończeniu długotrwałych zadań, lub definiować własne funkcje przetwarzania końcowego.
Synchroniczne punkty zaczepienia: aby umożliwić użytkownikom dodawanie logiki blokowania do rozszerzenia, możesz dodać synchroniczne punkty zaczepienia w określonych miejscach działania rozszerzenia. W tych miejscach uruchamiasz funkcję dostawcy użytkownika i kontynuujesz działanie dopiero po jej zakończeniu. Zadania wstępnego przetwarzania często należą do tej kategorii.
Rozszerzenie może korzystać z jednej lub obu tych metod.
Zdarzenia Eventarc
Aby publikować wydarzenia z rozszerzenia:
Zadeklaruj typy zdarzeń, które będziesz publikować, w pliku extension.yaml:
Identyfikator type składa się z kilku pól oddzielonych kropkami. Pola Identyfikator wydawcy, nazwa rozszerzenia i nazwa zdarzenia są wymagane. Pole wersji jest zalecane. Wybierz unikalną i opisową nazwę zdarzenia dla każdego publikowanego typu zdarzenia.
events:-type:firebase.extensions.storage-resize-images.v1.completedescription:|Occurs when image resizing completes. The event will contain furtherdetails about specific formats and sizes.
Użytkownicy będą mogli wybrać, które wydarzenia chcą subskrybować, gdy zainstalują rozszerzenie.
W funkcjach rozszerzenia zaimportuj interfejs Eventarc API z Admin SDKi zainicjuj kanał zdarzeń, używając ustawień instalacji użytkownika.
Te ustawienia są udostępniane za pomocą tych zmiennych środowiskowych:
EVENTARC_CHANNEL: pełna nazwa kanału Eventarc, na którym użytkownik zdecydował się publikować zdarzenia.
EXT_SELECTED_EVENTS: lista typów wydarzeń wybranych przez użytkownika do opublikowania, oddzielona przecinkami. Gdy zainicjujesz kanał z tą wartością, pakiet Admin SDK automatycznie odfiltruje zdarzenia, których użytkownik nie wybrał.
EVENTARC_CLOUD_EVENT_SOURCE: identyfikator źródła Cloud Event. Pakiet Admin SDK automatycznie przekazuje tę wartość w polu source opublikowanych zdarzeń. Zwykle nie musisz używać tej zmiennej w sposób jawny.
Jeśli zdarzenia nie zostały włączone podczas instalacji, te zmienne będą miały wartość undefined. Możesz wykorzystać ten fakt, aby zainicjować kanał zdarzeń tylko wtedy, gdy zdarzenia są włączone:
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,});
Publikuj zdarzenia na kanale w miejscach w rozszerzeniu, które chcesz udostępnić użytkownikom. Przykład:
// 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:{// ...}});
Zapisz opublikowane zdarzenia w pliku PREINSTALL lub POSTINSTALL.
W przypadku każdego zdarzenia udokumentuj te informacje:
zamierzone przeznaczenie,
Moment w logice rozszerzenia, w którym jest ono uruchamiane.
Dane wyjściowe, które zawiera
warunki jego wykonania,
Dodatkowo ostrzegaj użytkowników, aby nie wykonywali w procedurach obsługi zdarzeń żadnych działań, które mogłyby wywołać to samo rozszerzenie, co spowodowałoby nieskończoną pętlę.
Gdy publikujesz zdarzenia z rozszerzenia, użytkownicy mogą wdrażać procedury obsługi zdarzeń, aby odpowiadać za pomocą niestandardowej logiki.
Na przykład poniższy kod usuwa oryginalny obraz po zmianie jego rozmiaru. Zwróć uwagę, że ten przykładowy moduł obsługi korzysta z właściwości subject zdarzenia, która w tym przypadku jest oryginalną nazwą pliku obrazu.
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();});
Jeśli chcesz udostępnić użytkownikom punkt zaczepienia, który musi zostać wykonany, aby jedna z funkcji rozszerzenia działała, użyj synchronicznych punktów zaczepienia.
Synchroniczny wywołuje zdefiniowaną przez użytkownika funkcję Cloud Function wywoływaną przez HTTPS i czeka na jej zakończenie (ewentualnie z wartością zwracaną) przed kontynuowaniem. Błąd w funkcji podanej przez użytkownika
powoduje błąd w funkcji rozszerzenia.
Aby udostępnić synchroniczny hook:
Dodaj do rozszerzenia parametr, który umożliwi użytkownikom skonfigurowanie rozszerzenia za pomocą adresu URL niestandardowej funkcji w Cloud Functions. Przykład:
-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
W miejscu rozszerzenia, w którym chcesz udostępnić hook, wywołaj funkcję za pomocą jej adresu URL. Przykład:
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.// ...});
W pliku PREINSTALL lub POSTINSTALL udokumentuj wszystkie udostępniane przez siebie punkty zaczepienia.
W przypadku każdego haka udokumentuj te informacje:
zamierzone przeznaczenie,
Moment w logice rozszerzenia, w którym jest ono uruchamiane.
oczekiwane dane wejściowe i wyjściowe,
warunki (lub opcje) jego wykonania;
Dodatkowo ostrzegaj użytkowników, aby nie wykonywali w funkcji hook żadnych działań, które mogłyby wywołać to samo rozszerzenie, co spowodowałoby nieskończoną pętlę.
[[["Łatwo zrozumieć","easyToUnderstand","thumb-up"],["Rozwiązało to mój problem","solvedMyProblem","thumb-up"],["Inne","otherUp","thumb-up"]],[["Brak potrzebnych mi informacji","missingTheInformationINeed","thumb-down"],["Zbyt skomplikowane / zbyt wiele czynności do wykonania","tooComplicatedTooManySteps","thumb-down"],["Nieaktualne treści","outOfDate","thumb-down"],["Problem z tłumaczeniem","translationIssue","thumb-down"],["Problem z przykładami/kodem","samplesCodeIssue","thumb-down"],["Inne","otherDown","thumb-down"]],["Ostatnia aktualizacja: 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."]]