在擴充功能中新增使用者掛鉤

您可以讓安裝擴充功能的使用者在執行擴充功能時,插入自己的自訂邏輯。有兩種方法可以完成這項操作:

  • 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 ID 是由多個以點號分隔的欄位組成。請務必填入發布商 ID、擴充功能名稱和事件名稱欄位。建議使用版本欄位。請為每個發布事件類型選擇不重複且具描述性的事件名稱。

    舉例來說,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. 請在擴充功能函式中,從 Admin SDK 匯入 Eventarc API,並使用使用者的安裝設定初始化事件管道。這些設定會透過下列環境變數公開:

    • EVENTARC_CHANNEL:使用者選擇發布事件的 Eventarc 管道完整修飾名稱。
    • EXT_SELECTED_EVENTS:以半形逗號分隔的清單,列出使用者選擇發布的事件類型。當您使用這個值初始化管道時,Admin SDK 會自動篩除使用者未選取的事件。
    • EVENTARC_CLOUD_EVENT_SOURCE:Cloud Event 來源 ID。管理員 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. 在擴充功能中新增參數,讓使用者可透過自訂 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
    
  2. 在擴充功能中要公開鉤子的點,使用其網址呼叫函式。例如:

    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 之前呼叫使用者提供的轉換函式