Dodawanie do rozszerzenia elementów, które zaciągają użytkowników

Możesz zapewnić użytkownikom, którzy zainstalowali Twoje rozszerzenie, możliwość wstawiania własnych reguł logiki podczas jego wykonywania. Można to zrobić na 2 sposoby:

  • Zdarzenia Eventarc: aby umożliwić użytkownikom asynchroniczne reagowanie na zdarzenia, możesz publikować w Eventarc. Użytkownicy mogą wdrażać funkcje obsługi zdarzeń, które np. wysyłają powiadomienia po ukończeniu długotrwałych zadań, lub definiować własne funkcje końcowe.

  • Synchroniczne hooki: aby umożliwić użytkownikom dodanie logiki blokującej do rozszerzenia, możesz dodać synchroniczne punkty zaczepienia w zdefiniowanych wstępnie punktach działania rozszerzenia. W tym momencie uruchomisz funkcję dostawcy danych i kontynuujesz dopiero po jej zakończeniu. Do tej kategorii często zaliczają się zadania wstępnego przetwarzania.

Rozszerzenie może korzystać z jednej z tych metod lub z obu tych metod.

Zdarzenia Eventarc

Aby opublikować wydarzenia z rozszerzenia:

  1. Zadeklaruj typy zdarzeń, które będziesz publikować w pliku 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
    

    Identyfikator type składa się z kilku pól rozdzielonych kropką. Pola identyfikator wydawcy, nazwa rozszerzenia i nazwa zdarzenia są wymagane. Pole wersji jest zalecane. Każdemu rodzajowi zdarzenia, które publikujesz, wybierz unikalną i opisową nazwę.

    Na przykład rozszerzenie storage-resize-images deklaruje jeden typ zdarzenia:

    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.
    

    Podczas instalowania rozszerzenia użytkownicy będą mogli wybrać, które wydarzenia chcą subskrybować.

  2. W funkcjach rozszerzeń zaimportuj Eventarc API z pakietu Admin SDK i zainicjuj kanał zdarzeń za pomocą ustawień instalacji użytkownika. Te ustawienia są ujawniane przy użyciu następujących zmiennych środowiskowych:

    • EVENTARC_CHANNEL: pełna nazwa kanału Eventarc, w którym użytkownik postanowił opublikować zdarzenia.
    • EXT_SELECTED_EVENTS: rozdzielana przecinkami lista typów zdarzeń, które użytkownik zdecydował się opublikować. Gdy zainicjujesz kanał przy użyciu tej wartości, pakiet Admin SDK automatycznie odfiltruje zdarzenia, które nie zostały wybrane przez użytkownika.
    • EVENTARC_CLOUD_EVENT_SOURCE: identyfikator źródła zdarzeń Cloud. Pakiet Admin SDK automatycznie przekazuje tę wartość w polu source opublikowanych zdarzeń. Zwykle nie trzeba jej bezpośrednio używać.

    Jeśli zdarzenia nie były włączone podczas instalacji, zmienne te pozostaną niezdefiniowane. Możesz skorzystać z tych informacji, aby zainicjować kanał zdarzeń tylko wtedy, gdy zdarzenia są włączone:

    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. Publikuj zdarzenia w kanale w punktach rozszerzenia, które chcesz udostępnić użytkownikom. Przykład:

    // 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. Zapisz publikowane zdarzenia w pliku PREINSTALL lub POSTINSTALL.

    W przypadku każdego wydarzenia udokumentuj te informacje:

    • Przeznaczenie
    • punkt w logice rozszerzenia,
    • zawarte w nim dane wyjściowe,
    • warunki jego wykonania.

    Dodatkowo ostrzegaj użytkowników, aby nie wykonywali w ich modułach obsługi zdarzeń żadnych działań, które mogą aktywować to samo rozszerzenie i stworzyć pętlę nieskończoną.

Po opublikowaniu zdarzeń z rozszerzenia użytkownicy mogą wdrażać moduły obsługi zdarzeń, aby odpowiadać za pomocą niestandardowej logiki.

W przykładzie poniżej widać usunięcie oryginalnego obrazu po zmianie jego rozmiaru. Zwróć uwagę, że w tym przykładowym module obsługi używana jest właściwość subject zdarzenia – w tym przypadku jest to pierwotna nazwa pliku obrazu.

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();
    });

Więcej informacji znajdziesz w artykule Reguły zdarzeń niestandardowych.

Przykład

Oficjalne rozszerzenie Resize Images zapewnia asynchroniczny element przykuwający uwagę, publikując w Eventarc po zmianie rozmiaru obrazu.

Synchroniczne haki

Jeśli chcesz udostępnić użytkownikom element zaczepienia, który musi pomyślnie wykonać działanie jednej z funkcji rozszerzenia, użyj funkcji zaczepienia synchronicznego.

Synchroniczny punkt zaczepienia wywołuje zdefiniowaną przez użytkownika funkcję wywoływaną przez HTTPS w Cloud Functions i czeka na zakończenie (być może z zwróconą wartością), zanim przejdziesz dalej. Błąd w funkcji podanej przez użytkownika powoduje błąd w funkcji rozszerzenia.

Aby udostępnić synchroniczny punkt zaczepienia:

  1. Dodaj do rozszerzenia parametr, który pozwoli użytkownikom skonfigurować rozszerzenie z adresem URL ich niestandardowej funkcji w Cloud Functions. Przykład:

    - 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. W punkcie rozszerzenia, w którym chcesz udostępnić zaczep, wywołaj funkcję za pomocą jej adresu URL. Przykład:

    const functions = require('firebase-functions');
    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. Wszystkie udostępnione punkty zaczepienia zapisz w pliku PREINSTALL lub POSTINSTALL.

    Dla każdego zaczepienia udokumentuj te kwestie:

    • Przeznaczenie
    • punkt w logice rozszerzenia,
    • Oczekiwane dane wejściowe i wyjściowe
    • warunki (lub opcje) wykonania kodu;

    Dodatkowo ostrzegaj użytkowników, aby nie wykonywali żadnych czynności, które mogą aktywować to samo rozszerzenie, powodując pętlę nieskończoną.

Przykład

Rozszerzenie Algolia Search zawiera synchroniczny punkt zaczepienia służący do wywoływania funkcji transformacji dostarczonej przez użytkownika przed zapisem do Algolii.