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

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

  • 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。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.firebasestorage.app")
          .file(event.subject)
          .delete();
    });

詳情請參閱「自訂事件觸發條件」。

範例

官方的 Resize Images 擴充功能會在調整圖片大小後發布至 Eventarc,提供非同步掛鉤。

同步掛鉤

如要為使用者提供必須成功完成的掛鉤,才能運作其中一個擴充功能,請使用同步掛鉤

同步掛鉤會呼叫使用者定義的 HTTPS 可呼叫 Cloud Function,並等待完成 (可能會有傳回值),然後再繼續。使用者提供的函式發生錯誤,導致擴充功能函式發生錯誤。

如要公開同步掛鉤:

  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. 在擴充功能中要公開 Hook 的位置,使用網址呼叫函式。例如:

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