Вы можете предоставить пользователям, установившим ваше расширение, возможность добавлять собственную логику в его работу. Есть два способа сделать это:
- События Eventarc : чтобы предоставить пользователям возможность асинхронно реагировать на события, можно опубликовать их в Eventarc. Пользователи могут развернуть функции обработчика событий, например, отправляющие уведомления после завершения длительных задач, или определить собственные функции постобработки. 
- Синхронные хуки : чтобы предоставить пользователям возможность добавлять блокирующую логику в ваше расширение, вы можете добавить синхронные хуки в предопределённые точки работы расширения. В этих точках вы запускаете функцию поставщика пользователя и продолжаете работу только после её завершения. Задачи предварительной обработки часто попадают в эту категорию. 
Расширение может использовать один или оба метода.
События Eventarc
Чтобы опубликовать события из расширения:
- Объявите типы событий, которые вы будете публиковать, в файле - extension.yaml:- events: - type: publisher-id.extension-name.version.event-name description: event-description - type: publisher-id.extension-name.version.another-event-name description: another-event-description- Идентификатор - typeсостоит из нескольких полей, разделенных точками. Поля «Идентификатор издателя» , «Название расширения» и «Название события» являются обязательными. Рекомендуется указать поле «Версия». Выберите уникальное и описательное имя для каждого публикуемого типа событий.- Например, расширение - storage-resize-imagesобъявляет один тип события:- events: - type: firebase.extensions.storage-resize-images.v1.complete description: | Occurs when image resizing completes. The event will contain further details about specific formats and sizes.- После установки расширения пользователи смогут выбирать, на какие события подписываться. 
- В функциях расширения импортируйте API Eventarc из Admin SDK и инициализируйте канал событий, используя параметры установки пользователя. Эти параметры доступны с помощью следующих переменных среды: -  EVENTARC_CHANNEL: полное имя канала Eventarc, на котором пользователь решил публиковать события.
-  EXT_SELECTED_EVENTS: список типов событий, выбранных пользователем для публикации, через запятую. При инициализации канала с этим значением Admin SDK автоматически отфильтровывает события, которые пользователь не выбирал.
-  EVENTARC_CLOUD_EVENT_SOURCE: идентификатор источника события в облаке. Admin SDK автоматически передаёт это значение в полеsourceпубликуемых событий. Обычно нет необходимости явно использовать эту переменную.
 - Если события не были включены при установке, эти переменные будут неопределенными. Вы можете использовать этот факт для инициализации канала событий только при включенных событиях: - import * as admin from "firebase-admin"; import {getEventarc} from 'firebase-admin/eventarc'; admin.initializeApp(); // Set eventChannel to a newly-initialized channel, or `undefined` if events // aren't enabled. const eventChannel = process.env.EVENTARC_CHANNEL && getEventarc().channel(process.env.EVENTARC_CHANNEL, { allowedEventTypes: process.env.EXT_SELECTED_EVENTS, });
-  
- Публикуйте события в канале в тех местах вашего расширения, которые вы хотите показать пользователям. Например: - // 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 file data: { // ... } });
- Документируйте публикуемые вами события в файле PREINSTALL или POSTINSTALL. - Для каждого события задокументируйте следующее: - Его предполагаемое назначение
- Точка в логике вашего расширения, которая работает
- Выходные данные, которые он включает
- Условия его исполнения
 - Кроме того, предупредите пользователей, чтобы они не выполняли никаких действий в своих обработчиках событий, которые могут вызвать срабатывание того же расширения, что приведет к бесконечному циклу. 
При публикации событий из расширения пользователи могут развертывать обработчики событий для реагирования с использованием пользовательской логики.
 Например, в следующем примере исходное изображение удаляется после изменения его размера. Обратите внимание, что обработчик в этом примере использует свойство subject события, которым в данном случае является исходное имя файла изображения.
exports.onimageresized = onCustomEventPublished(
    "firebase.extensions.storage-resize-images.v1.complete",
    (event) => {
      logger.info("Received image resize completed event", event);
      // For example, delete the original.
      return admin.storage()
          .bucket("my-project.firebasestorage.app")
          .file(event.subject)
          .delete();
    });
Дополнительную информацию см. в разделе Пользовательские триггеры событий .
Пример
Официальное расширение Resize Images обеспечивает асинхронный хук, публикуя данные в Eventarc после изменения размера изображения.
Синхронные крючки
Если вы хотите предоставить пользователям хук, который должен успешно завершиться для работы одной из функций расширения, используйте синхронные хуки .
Синхронный хук вызывает пользовательскую HTTPS-вызываемую облачную функцию и ожидает завершения (возможно, с возвращением значения) перед продолжением. Ошибка в пользовательской функции приводит к ошибке в функции расширения.
Чтобы раскрыть синхронный хук:
- Добавьте в расширение параметр, позволяющий пользователям настраивать расширение с URL-адресом своей пользовательской функции Cloud. Например: - - param: PREPROCESSING_FUNCTION label: Pre-processing function URL description: > An HTTPS callable function that will be called to transform the input data before it is processed by this function. type: string example: https://us-west1-my-project-id.cloudfunctions.net/preprocessData required: false
- В том месте расширения, где вы хотите реализовать хук, вызовите функцию, используя её URL. Например: - const functions = require('firebase-functions/v1'); const fetch = require('node-fetch'); const preprocessFunctionURL = 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 { await fetch(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. // ... });
- Задокументируйте все доступные вами хуки в файле PREINSTALL или POSTINSTALL. - Для каждого крючка задокументируйте следующее: - Его предполагаемое назначение
- Точка в логике вашего расширения, которая работает
- Его ожидаемые входы и выходы
- Условия (или варианты) его исполнения
 - Кроме того, предупредите пользователей, чтобы они не выполняли никаких действий в функции перехвата, которые могут привести к запуску того же расширения, что приведет к бесконечному циклу. 
Пример
Расширение Algolia Search предоставляет синхронный хук для вызова предоставленной пользователем функции преобразования перед записью в Algolia.