Вы можете предоставить пользователям, которые устанавливают ваше расширение, возможность вставлять свою собственную логику в выполнение вашего расширения. Есть два способа сделать это:
События 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
: идентификатор источника событий Cloud. 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.