Добавьте пользовательские перехватчики в расширение

Вы можете предоставить пользователям, которые устанавливают ваше расширение, возможность вставлять свою собственную логику в выполнение вашего расширения. Есть два способа сделать это:

  • События Eventarc : чтобы дать пользователям возможность асинхронно реагировать на события, вы можете публиковать их в Eventarc. Пользователи могут развертывать функции обработчика событий, которые, например, отправляют уведомления после завершения длительных задач, или определять свои собственные функции постобработки.

  • Синхронные перехватчики : чтобы дать пользователям возможность добавлять логику блокировки в ваше расширение, вы можете добавлять синхронные перехватчики в заранее определенные точки работы расширения. На этом этапе вы запускаете функцию поставщика пользователя и продолжаете работу только после ее завершения. Задачи предварительной обработки часто подпадают под эту категорию.

Расширение может использовать один или оба метода.

События Eventarc

Чтобы опубликовать события из расширения:

  1. Объявите типы событий, которые вы будете публиковать, в файле 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.
    

    Пользователи смогут выбирать, на какие события подписываться при установке расширения.

  2. В функциях расширения импортируйте 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,
      });
    
  3. Публикуйте события на канале в тех точках вашего расширения, которые вы хотите показать пользователям. Например:

    // 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: {
          // ...
        }
    });
    
  4. Документируйте события, которые вы публикуете, в файле 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.appspot.com")
          .file(event.subject)
          .delete();
    });

Дополнительные сведения см. в разделе Пользовательские триггеры событий .

Пример

Официальное расширение Resize Images обеспечивает асинхронную перехватку путем публикации в Eventarc после изменения размера изображения.

Синхронные крючки

Если вы хотите предоставить пользователям перехватчик, который должен успешно завершиться для работы одной из ваших функций расширения, используйте синхронные перехватчики .

Синхронный перехват вызывает определяемую пользователем облачную функцию HTTPS и ожидает завершения (возможно, с возвращаемым значением), прежде чем продолжить. Ошибка в предоставленной пользователем функции приводит к ошибке в функции расширения.

Чтобы открыть синхронный хук:

  1. Добавьте в расширение параметр, который позволит пользователям настраивать расширение с помощью URL-адреса своей пользовательской облачной функции. Например:

    - 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
    
  2. В том месте вашего расширения, где вы хотите использовать перехватчик, вызовите функцию, используя ее 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.
          // ...
        });
    
  3. Задокументируйте все перехватчики, которые вы предоставляете в файле PREINSTALL или POSTINSTALL.

    Для каждого крючка задокументируйте следующее:

    • Его целевое назначение
    • Точка в логике вашего расширения, которую он выполняет
    • Ожидаемые входы и результаты
    • Условия (или варианты) его исполнения

    Кроме того, предупредите пользователей, чтобы они не выполняли в функции перехвата никаких действий, которые могут вызвать одно и то же расширение, что приведет к бесконечному циклу.

Пример

Расширение Algolia Search предоставляет синхронный крючок для вызова предоставленной пользователем функции преобразования перед записью в Algolia.