Bắt đầu xây dựng tiện ích mở rộng

Trang này hướng dẫn bạn các bước cần thiết để xây dựng Tiện ích mở rộng Firebase đơn giản mà bạn có thể cài đặt trong dự án của mình hoặc chia sẻ với người khác. Ví dụ đơn giản này về Tiện ích mở rộng Firebase sẽ xem Cơ sở dữ liệu thời gian thực của bạn để tìm tin nhắn và chuyển đổi chúng thành chữ hoa.

1. Thiết lập môi trường của bạn và khởi tạo dự án

Trước khi có thể bắt đầu xây dựng tiện ích mở rộng, bạn cần thiết lập môi trường xây dựng bằng các công cụ cần thiết.

  1. Cài đặt Node.js 16 hoặc mới hơn. Một cách để cài đặt Node là sử dụng nvm (hoặc nvm-windows ).

  2. Cài đặt hoặc cập nhật lên phiên bản mới nhất của Firebase CLI . Để cài đặt hoặc cập nhật bằng npm , hãy chạy lệnh này:

    npm install -g firebase-tools
    

Bây giờ hãy sử dụng Firebase CLI để khởi tạo dự án tiện ích mở rộng mới:

  1. Tạo một thư mục cho tiện ích mở rộng của bạn và cd vào đó:

    mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
    
  2. Chạy lệnh ext:dev:init của Firebase CLI:

    firebase ext:dev:init
    

    Khi được nhắc, hãy chọn JavaScript làm ngôn ngữ cho các hàm (nhưng lưu ý rằng bạn cũng có thể sử dụng TypeScript khi phát triển tiện ích mở rộng của riêng mình) và khi được yêu cầu cài đặt các phần phụ thuộc, hãy trả lời "có". (Chấp nhận các giá trị mặc định cho bất kỳ tùy chọn nào khác.) Lệnh này sẽ thiết lập cơ sở mã khung cho tiện ích mở rộng mới, từ đó bạn có thể bắt đầu phát triển tiện ích mở rộng của mình.

2. Thử tiện ích mở rộng mẫu bằng trình mô phỏng

Khi Firebase CLI khởi tạo thư mục tiện ích mở rộng mới, nó đã tạo một hàm ví dụ đơn giản và thư mục integration-tests chứa các tệp cần thiết để chạy tiện ích mở rộng bằng bộ mô phỏng Firebase.

Hãy thử chạy tiện ích mở rộng mẫu trong trình mô phỏng:

  1. Thay đổi thư mục integration-tests :

    cd functions/integration-tests
    
  2. Bắt đầu trình mô phỏng với một dự án demo:

    firebase emulators:start --project=demo-test
    

    Trình mô phỏng tải tiện ích mở rộng vào dự án "giả" được xác định trước ( demo-test ). Tiện ích mở rộng cho đến nay bao gồm một hàm được kích hoạt HTTP duy nhất, greetTheWorld , trả về thông báo "hello world" khi được truy cập.

  3. Khi trình mô phỏng vẫn đang chạy, hãy thử chức năng greetTheWorld của tiện ích mở rộng bằng cách truy cập URL mà tiện ích này đã in khi bạn khởi động.

    Trình duyệt của bạn hiển thị thông báo "Xin chào thế giới từ lời chào thế giới".

  4. Mã nguồn của hàm này nằm trong thư mục hàm của functions mở rộng. Mở nguồn trong trình soạn thảo hoặc IDE bạn chọn:

    hàm/index.js

    const functions = require("firebase-functions");
    
    exports.greetTheWorld = functions.https.onRequest((req, res) => {
      // Here we reference a user-provided parameter
      // (its value is provided by the user during installation)
      const consumerProvidedGreeting = process.env.GREETING;
    
      // And here we reference an auto-populated parameter
      // (its value is provided by Firebase after installation)
      const instanceId = process.env.EXT_INSTANCE_ID;
    
      const greeting = `${consumerProvidedGreeting} World from ${instanceId}`;
    
      res.send(greeting);
    });
    
  5. Trong khi trình mô phỏng đang chạy, nó sẽ tự động tải lại mọi thay đổi bạn thực hiện đối với mã Hàm. Hãy thử thực hiện một thay đổi nhỏ đối với hàm greetTheWorld :

    hàm/index.js

    const greeting = `${consumerProvidedGreeting} everyone, from ${instanceId}`;
    

    Lưu các thay đổi của bạn. Trình mô phỏng sẽ tải lại mã của bạn và bây giờ, khi truy cập URL hàm, bạn sẽ thấy lời chào được cập nhật.

3. Thêm thông tin cơ bản vào Extension.yaml

Bây giờ bạn đã thiết lập môi trường phát triển và đang chạy trình mô phỏng tiện ích mở rộng, bạn có thể bắt đầu viết tiện ích mở rộng của riêng mình.

Bước đầu tiên khiêm tốn, hãy chỉnh sửa siêu dữ liệu tiện ích mở rộng được xác định trước để phản ánh tiện ích mở rộng bạn muốn viết thay vì greet-the-world . Siêu dữ liệu này được lưu trữ trong tệp extension.yaml .

  1. Mở phần mở extension.yaml trong trình chỉnh sửa của bạn và thay thế toàn bộ nội dung của tệp bằng nội dung sau:

    name: rtdb-uppercase-messages
    version: 0.0.1
    specVersion: v1beta  # Firebase Extensions specification version; don't change
    
    # Friendly display name for your extension (~3-5 words)
    displayName: Convert messages to upper case
    
    # Brief description of the task your extension performs (~1 sentence)
    description: >-
      Converts messages in RTDB to upper case
    
    author:
      authorName: Your Name
      url: https://your-site.example.com
    
    license: Apache-2.0  # Required license
    
    # Public URL for the source code of your extension
    sourceUrl: https://github.com/your-name/your-repo
    

    Lưu ý quy ước đặt tên được sử dụng trong trường name : tiện ích mở rộng Firebase chính thức được đặt tên bằng tiền tố cho biết sản phẩm Firebase chính mà tiện ích mở rộng hoạt động, theo sau là mô tả về chức năng của tiện ích mở rộng. Bạn nên sử dụng quy ước tương tự trong tiện ích mở rộng của riêng mình.

  2. Vì bạn đã thay đổi tên tiện ích mở rộng của mình nên bạn cũng nên cập nhật cấu hình trình mô phỏng của mình bằng tên mới:

    1. Trong functions/integration-tests/firebase.json , hãy thay đổi greet-the-world thành rtdb-uppercase-messages .
    2. Đổi functions/integration-tests/extensions/greet-the-world.env thành functions/integration-tests/extensions/rtdb-uppercase-messages.env .

Vẫn còn một số phần còn sót lại của tiện ích mở rộng greet-the-world trong mã tiện ích mở rộng của bạn, nhưng hãy tạm dừng chúng lại. Bạn sẽ cập nhật những điều đó trong một số phần tiếp theo.

4. Viết Hàm đám mây và khai báo nó là tài nguyên mở rộng

Bây giờ bạn có thể bắt đầu viết một số mã. Trong bước này, bạn sẽ viết Hàm đám mây thực hiện nhiệm vụ cốt lõi của tiện ích mở rộng, đó là xem Cơ sở dữ liệu thời gian thực của bạn để tìm tin nhắn và chuyển đổi chúng thành chữ hoa.

  1. Mở nguồn cho các chức năng của tiện ích mở rộng (trong thư mục chức năng của functions mở rộng) trong trình chỉnh sửa hoặc IDE mà bạn chọn. Thay thế nội dung của nó bằng nội dung sau:

    hàm/index.js

    import { database, logger } from "firebase-functions/v1";
    
    const app = initializeApp();
    
    // Listens for new messages added to /messages/{pushId}/original and creates an
    // uppercase version of the message to /messages/{pushId}/uppercase
    // for all databases in 'us-central1'
    export const makeuppercase = database
      .ref("/messages/{pushId}/uppercase")
      .onCreate(async (snapshot, context) => {
        // Grab the current value of what was written to the Realtime Database.
        const original = snapshot.val();
    
        // Convert it to upper case.
        logger.log("Uppercasing", context.params.pushId, original);
        const uppercase = original.toUpperCase();
    
        // Setting an "uppercase" sibling in the Realtime Database.
        const upperRef = snapshot.ref.parent.child("upper");
        await upperRef.set(uppercase);
    });
    

    Hàm cũ mà bạn đã thay thế là hàm được kích hoạt HTTP, chạy khi điểm cuối HTTP được truy cập. Chức năng mới được kích hoạt bởi các sự kiện cơ sở dữ liệu thời gian thực: nó theo dõi các mục mới tại một đường dẫn cụ thể và khi phát hiện thấy một mục, nó sẽ ghi phiên bản chữ hoa của giá trị trở lại cơ sở dữ liệu.

    Nhân tiện, tệp mới này sử dụng cú pháp mô-đun ECMAScript ( importexport ) thay vì CommonJS ( require ). Để sử dụng các mô-đun ES trong Nút, hãy chỉ định "type": "module" trong functions/package.json :

    {
      "name": "rtdb-uppercase-messages",
      "main": "index.js",
      "type": "module",
      …
    }
    
  2. Mọi chức năng trong tiện ích mở rộng của bạn phải được khai báo trong tệp extension.yaml . Tiện ích mở rộng ví dụ đã khai báo greetTheWorld là Chức năng đám mây duy nhất của tiện ích mở rộng; bây giờ bạn đã thay thế nó bằng makeuppercase , bạn cũng cần cập nhật phần khai báo của nó.

    Mở tiện ích mở extension.yaml và thêm trường resources :

    resources:
      - name: makeuppercase
        type: firebaseextensions.v1beta.function
        properties:
          eventTrigger:
            eventType: providers/google.firebase.database/eventTypes/ref.create
            # DATABASE_INSTANCE (project's default instance) is an auto-populated
            # parameter value. You can also specify an instance.
            resource: projects/_/instances/${DATABASE_INSTANCE}/refs/messages/{pushId}/original
          runtime: "nodejs18"
    
  3. Vì tiện ích mở rộng của bạn hiện đang sử dụng Cơ sở dữ liệu thời gian thực làm trình kích hoạt nên bạn cần cập nhật cấu hình trình mô phỏng của mình để chạy trình mô phỏng RTDB cùng với trình mô phỏng Chức năng đám mây:

    1. Nếu trình giả lập vẫn đang chạy, hãy dừng nó bằng cách nhấn Ctrl-C.

    2. Từ thư mục functions/integration-tests , hãy chạy lệnh sau:

      firebase init emulators
      

      Khi được hỏi, hãy bỏ qua việc thiết lập dự án mặc định, sau đó chọn Trình mô phỏng chức năng và cơ sở dữ liệu. Chấp nhận các cổng mặc định và cho phép công cụ thiết lập tải xuống mọi tệp cần thiết.

    3. Khởi động lại trình giả lập:

      firebase emulators:start --project=demo-test
      
  4. Hãy thử tiện ích mở rộng đã cập nhật của bạn:

    1. Mở giao diện người dùng trình mô phỏng cơ sở dữ liệu bằng liên kết mà trình mô phỏng được in khi bạn khởi động nó.

    2. Chỉnh sửa nút gốc của cơ sở dữ liệu:

      • Trường: messages
      • Kiểu: json
      • Giá trị: {"11": {"original": "recipe"}}

      Nếu mọi thứ được thiết lập chính xác, khi bạn lưu các thay đổi cơ sở dữ liệu của mình, chức năng makeuppercase của tiện ích mở rộng sẽ kích hoạt và thêm bản ghi con vào tin nhắn 11 với nội dung "upper": "RECIPE" . Hãy xem nhật ký và tab cơ sở dữ liệu của giao diện người dùng trình mô phỏng để xác nhận kết quả mong đợi.

    3. Hãy thử thêm một số phần tử con khác vào nút messages ( {"original":"any text"} ). Bất cứ khi nào bạn thêm bản ghi mới, tiện ích mở rộng sẽ thêm trường uppercase chứa nội dung viết hoa của trường original .

Bây giờ bạn đã có một tiện ích mở rộng hoàn chỉnh, mặc dù đơn giản, hoạt động trên phiên bản RTDB. Trong các phần tiếp theo, bạn sẽ tinh chỉnh tiện ích mở rộng này bằng một số tính năng bổ sung. Sau đó, bạn sẽ chuẩn bị sẵn tiện ích mở rộng để phân phối cho người khác và cuối cùng, tìm hiểu cách xuất bản tiện ích mở rộng của mình trên Trung tâm tiện ích mở rộng.

5. Khai báo API và vai trò

Firebase cấp cho mỗi phiên bản của tiện ích mở rộng đã cài đặt quyền truy cập có giới hạn vào dự án và dữ liệu của dự án bằng cách sử dụng tài khoản dịch vụ cho từng phiên bản. Mỗi tài khoản có bộ quyền tối thiểu cần thiết để hoạt động. Vì lý do này, bạn phải khai báo rõ ràng mọi vai trò IAM mà tiện ích mở rộng của bạn yêu cầu; khi người dùng cài đặt tiện ích mở rộng của bạn, Firebase sẽ tạo một tài khoản dịch vụ với các vai trò này được cấp và sử dụng tài khoản đó để chạy tiện ích mở rộng.

Bạn không cần khai báo vai trò để kích hoạt các sự kiện của sản phẩm, nhưng bạn cần khai báo vai trò để tương tác với sản phẩm đó. Vì hàm bạn đã thêm ở bước trước ghi vào Cơ sở dữ liệu thời gian thực, nên bạn cần thêm khai báo sau vào extension.yaml :

roles:
  - role: firebasedatabase.admin
    reason: Allows the extension to write to RTDB.

Tương tự, bạn khai báo các API của Google mà tiện ích mở rộng sử dụng trong trường apis . Khi người dùng cài đặt tiện ích mở rộng của bạn, họ sẽ được hỏi liệu họ có muốn tự động bật các API này cho dự án của mình hay không. Điều này thường chỉ cần thiết đối với các API Google không có Firebase và không cần thiết cho hướng dẫn này.

6. Xác định các tham số do người dùng cấu hình

Hàm bạn đã tạo ở hai bước trước đã theo dõi một vị trí RTDB cụ thể cho các tin nhắn đến. Đôi khi, xem một vị trí cụ thể thực sự là điều bạn muốn, chẳng hạn như khi tiện ích mở rộng của bạn hoạt động trên cấu trúc cơ sở dữ liệu mà bạn sử dụng riêng cho tiện ích mở rộng của mình. Tuy nhiên, trong hầu hết các trường hợp, bạn sẽ muốn người dùng cài đặt tiện ích mở rộng của bạn trong dự án của họ có thể định cấu hình các giá trị này. Bằng cách này, người dùng có thể sử dụng tiện ích mở rộng của bạn để làm việc với thiết lập cơ sở dữ liệu hiện có của họ.

Tạo đường dẫn mà tiện ích mở rộng theo dõi tin nhắn mới có thể định cấu hình cho người dùng:

  1. Trong tệp extension.yaml , thêm phần params :

    - param: MESSAGE_PATH
      label: Message path
      description: >-
        What is the path at which the original text of a message can be found?
      type: string
      default: /messages/{pushId}/original
      required: true
      immutable: false
    

    Điều này xác định một tham số chuỗi mới mà người dùng sẽ được nhắc đặt khi họ cài đặt tiện ích mở rộng của bạn.

  2. Vẫn trong tệp extension.yaml , hãy quay lại phần khai báo makeuppercase của bạn và thay đổi trường resource thành như sau:

    resource: projects/_/instances/${DATABASE_INSTANCE}/refs/${param:MESSAGE_PATH}
    

    ${param:MESSAGE_PATH} là tham chiếu đến tham số bạn vừa xác định. Khi tiện ích mở rộng của bạn chạy, mã thông báo này sẽ được thay thế bằng bất kỳ giá trị nào mà người dùng đã định cấu hình cho tham số đó, kết quả là hàm makeuppercase sẽ lắng nghe đường dẫn mà người dùng đã chỉ định. Bạn có thể sử dụng cú pháp này để tham chiếu bất kỳ tham số nào do người dùng xác định ở bất kỳ đâu trong extension.yaml (và trong POSTINSTALL.md —sẽ nói thêm về điều đó sau).

  3. Bạn cũng có thể truy cập các tham số do người dùng xác định từ mã chức năng của mình.

    Trong hàm bạn đã viết ở phần trước, bạn đã mã hóa cứng đường dẫn để theo dõi các thay đổi. Thay đổi định nghĩa trình kích hoạt để tham chiếu giá trị do người dùng xác định:

    hàm/index.js

    export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate
    

    Lưu ý rằng trong Tiện ích mở rộng Firebase, thay đổi này hoàn toàn là vì mục đích tài liệu: khi Hàm đám mây được triển khai như một phần của tiện ích mở rộng, nó sẽ sử dụng định nghĩa trình kích hoạt từ tệp extension.yaml và bỏ qua giá trị được chỉ định trong định nghĩa hàm. Tuy nhiên, bạn nên ghi lại trong mã của mình giá trị này đến từ đâu.

  4. Bạn có thể thấy thất vọng khi thực hiện một thay đổi mã không có hiệu ứng khi chạy, nhưng bài học quan trọng cần rút ra là bạn có thể truy cập bất kỳ tham số nào do người dùng xác định trong mã hàm của mình và sử dụng nó làm giá trị thông thường trong logic của hàm. Để thể hiện khả năng này, hãy thêm câu lệnh nhật ký sau để chứng minh rằng bạn thực sự đang truy cập vào giá trị mà người dùng đã xác định:

    hàm/index.js

    export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate(
      async (snapshot, context) => {
        logger.log("Found new message at ", snapshot.ref);
    
        // Grab the current value of what was written to the Realtime Database.
        ...
    
  5. Thông thường, người dùng được nhắc cung cấp giá trị cho các tham số khi họ cài đặt tiện ích mở rộng. Tuy nhiên, khi bạn sử dụng trình mô phỏng để thử nghiệm và phát triển, bạn sẽ bỏ qua quá trình cài đặt, do đó, thay vào đó, bạn cung cấp các giá trị cho các tham số do người dùng xác định bằng tệp env .

    Mở functions/integration-tests/extensions/rtdb-uppercase-messages.env và thay thế định nghĩa GREETING bằng định nghĩa sau:

    MESSAGE_PATH=/msgs/{pushId}/original
    

    Lưu ý rằng đường dẫn ở trên khác với đường dẫn mặc định và đường dẫn bạn đã xác định trước đó; điều này chỉ để chứng minh cho chính bạn khi bạn thử tiện ích mở rộng đã cập nhật rằng định nghĩa của bạn đang có hiệu lực.

  6. Bây giờ, hãy khởi động lại trình mô phỏng và truy cập lại giao diện người dùng trình mô phỏng cơ sở dữ liệu.

    Chỉnh sửa nút gốc của cơ sở dữ liệu bằng đường dẫn bạn đã xác định ở trên:

    • Trường: msgs
    • Kiểu: json
    • Giá trị: {"11": {"original": "recipe"}}

    Khi bạn lưu các thay đổi cơ sở dữ liệu của mình, chức năng makeuppercase của tiện ích mở rộng sẽ kích hoạt như trước đây nhưng bây giờ nó cũng sẽ in tham số do người dùng xác định vào nhật ký bảng điều khiển.

7. Cung cấp các móc sự kiện cho logic do người dùng xác định

Với tư cách là tác giả tiện ích mở rộng, bạn đã thấy cách một sản phẩm Firebase có thể kích hoạt logic do tiện ích mở rộng của bạn cung cấp: việc tạo bản ghi mới trong Cơ sở dữ liệu thời gian thực sẽ kích hoạt chức năng makeuppercase của bạn. Tiện ích mở rộng của bạn có thể có mối quan hệ tương tự với những người dùng cài đặt tiện ích mở rộng của bạn: tiện ích mở rộng của bạn có thể kích hoạt logic mà người dùng xác định.

Tiện ích mở rộng có thể cung cấp móc đồng bộ , móc không đồng bộ hoặc cả hai. Móc đồng bộ cung cấp cho người dùng cách thực hiện các tác vụ chặn việc hoàn thành một trong các chức năng của tiện ích mở rộng. Điều này có thể hữu ích, ví dụ: để cung cấp cho người dùng cách thực hiện quá trình xử lý trước tùy chỉnh trước khi tiện ích mở rộng hoạt động.

Trong hướng dẫn này, bạn sẽ thêm một hook không đồng bộ vào tiện ích mở rộng của mình, điều này sẽ cho phép người dùng xác định các bước xử lý của riêng họ sẽ chạy sau khi tiện ích mở rộng của bạn ghi thông báo viết hoa vào Cơ sở dữ liệu thời gian thực. Móc không đồng bộ sử dụng Eventarc để kích hoạt các hàm do người dùng xác định. Tiện ích mở rộng khai báo loại sự kiện mà chúng phát ra và khi người dùng cài đặt tiện ích mở rộng, họ sẽ chọn loại sự kiện mà họ quan tâm. Nếu họ chọn ít nhất một sự kiện, Firebase sẽ cung cấp kênh Eventarc cho tiện ích mở rộng như một phần của quá trình cài đặt . Sau đó, người dùng có thể triển khai các chức năng đám mây của riêng mình để lắng nghe trên kênh đó và kích hoạt khi tiện ích mở rộng xuất bản các sự kiện mới.

Hãy làm theo các bước sau để thêm hook không đồng bộ:

  1. Trong tệp extension.yaml , hãy thêm phần sau để khai báo một loại sự kiện mà tiện ích mở rộng phát ra:

    events:
      - type: test-publisher.rtdb-uppercase-messages.v1.complete
        description: >-
          Occurs when message uppercasing completes. The event subject will contain
          the RTDB URL of the uppercase message.
    

    Các loại sự kiện phải là duy nhất trên toàn cầu; để đảm bảo tính duy nhất, hãy luôn đặt tên cho các sự kiện của bạn bằng định dạng sau: <publisher-id>.<extension-id>.<version>.<description> . (Bạn chưa có ID nhà xuất bản nên bây giờ chỉ sử dụng test-publisher .)

  2. Ở cuối hàm makeuppercase , hãy thêm một số mã xuất bản một sự kiện thuộc loại bạn vừa khai báo:

    hàm/index.js

    // Import the Eventarc library:
    import { initializeApp } from "firebase-admin/app";
    import { getEventarc } from "firebase-admin/eventarc";
    
    const app = initializeApp();
    
    // In makeuppercase, after upperRef.set(uppercase), add:
    
    // 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: "test-publisher.rtdb-uppercase-messages.v1.complete",
        subject: upperRef.toString(),
        data: {
          "original": original,
          "uppercase": uppercase,
        },
      });
    

    Mã ví dụ này tận dụng thực tế là biến môi trường EVENTARC_CHANNEL chỉ được xác định khi người dùng kích hoạt ít nhất một loại sự kiện. nếu EVENTARC_CHANNEL không được xác định thì mã sẽ không cố gắng xuất bản bất kỳ sự kiện nào.

    Bạn có thể đính kèm thông tin bổ sung vào sự kiện Eventarc. Trong ví dụ trên, sự kiện có trường subject chứa tham chiếu đến giá trị mới được tạo và tải trọng data chứa thông báo gốc và thông báo viết hoa. Các hàm do người dùng xác định kích hoạt sự kiện có thể sử dụng thông tin này.

  3. Thông thường, các biến môi trường EVENTARC_CHANNELEXT_SELECTED_EVENTS được xác định dựa trên các tùy chọn mà người dùng đã chọn trong quá trình cài đặt. Để thử nghiệm bằng trình mô phỏng, hãy xác định thủ công các biến này trong tệp rtdb-uppercase-messages.env :

    EVENTARC_CHANNEL=locations/us-central1/channels/firebase
    EXT_SELECTED_EVENTS=test-publisher.rtdb-uppercase-messages.v1.complete
    

Tại thời điểm này, bạn đã hoàn thành các bước cần thiết để thêm móc sự kiện không đồng bộ vào tiện ích mở rộng của mình.

Để dùng thử tính năng mới mà bạn vừa triển khai này, trong một số bước tiếp theo, hãy đảm nhận vai trò của người dùng đang cài đặt tiện ích mở rộng:

  1. Từ thư mục functions/integration-tests , khởi tạo dự án Firebase mới:

    firebase init functions
    

    Khi được nhắc, hãy từ chối thiết lập dự án mặc định, chọn JavaScript làm ngôn ngữ Chức năng đám mây và cài đặt các phần phụ thuộc cần thiết. Dự án này đại diện cho dự án của người dùng đã cài đặt tiện ích mở rộng của bạn.

  2. Chỉnh sửa integration-tests/functions/index.js và dán đoạn mã sau:

    import { logger } from "firebase-functions/v1";
    import { onCustomEventPublished } from "firebase-functions/v2/eventarc";
    
    import { initializeApp } from "firebase-admin/app";
    import { getDatabase } from "firebase-admin/database";
    
    const app = initializeApp();
    
    export const extraemphasis = onCustomEventPublished(
      "test-publisher.rtdb-uppercase-messages.v1.complete",
      async (event) => {
        logger.info("Received makeuppercase completed event", event);
    
        const refUrl = event.subject;
        const ref = getDatabase().refFromURL(refUrl);
        const upper = (await ref.get()).val();
        return ref.set(`${upper}!!!`);
      }
    );
    

    Đây là một ví dụ về chức năng xử lý hậu kỳ mà người dùng có thể viết. Trong trường hợp này, hàm sẽ lắng nghe tiện ích mở rộng để xuất bản một sự kiện complete và khi được kích hoạt, sẽ thêm ba dấu chấm than vào thông báo mới được viết hoa.

  3. Khởi động lại trình mô phỏng. Trình mô phỏng sẽ tải các chức năng của tiện ích mở rộng cũng như chức năng xử lý hậu kỳ mà "người dùng" đã xác định.

  4. Truy cập giao diện người dùng trình mô phỏng cơ sở dữ liệu và chỉnh sửa nút gốc của cơ sở dữ liệu bằng đường dẫn bạn đã xác định ở trên:

    • Trường: msgs
    • Kiểu: json
    • Giá trị: {"11": {"original": "recipe"}}

    Khi bạn lưu các thay đổi cơ sở dữ liệu của mình, hàm makeuppercase của tiện ích mở rộng và hàm extraemphasis của người dùng sẽ kích hoạt theo trình tự, dẫn đến trường upper nhận được giá trị RECIPE!!! .

8. Thêm trình xử lý sự kiện vòng đời

Tiện ích mở rộng bạn đã viết cho đến nay sẽ xử lý các tin nhắn khi chúng được tạo. Nhưng điều gì sẽ xảy ra nếu người dùng của bạn đã có cơ sở dữ liệu về tin nhắn khi họ cài đặt tiện ích mở rộng? Tiện ích mở rộng Firebase có một tính năng gọi là móc sự kiện vòng đời mà bạn có thể sử dụng để kích hoạt các hành động khi tiện ích mở rộng của bạn được cài đặt, cập nhật hoặc định cấu hình lại. Trong phần này, bạn sẽ sử dụng móc sự kiện vòng đời để lấp đầy cơ sở dữ liệu tin nhắn hiện có của dự án bằng các tin nhắn được viết hoa khi người dùng cài đặt tiện ích mở rộng của bạn.

Tiện ích mở rộng Firebase sử dụng Nhiệm vụ trên đám mây để chạy trình xử lý sự kiện trong vòng đời của bạn. Bạn xác định trình xử lý sự kiện bằng Chức năng đám mây; bất cứ khi nào phiên bản tiện ích mở rộng của bạn đạt đến một trong các sự kiện vòng đời được hỗ trợ, nếu bạn đã xác định trình xử lý, tiện ích này sẽ thêm trình xử lý đó vào hàng đợi Nhiệm vụ trên đám mây. Nhiệm vụ trên đám mây sau đó sẽ thực thi trình xử lý không đồng bộ. Trong khi trình xử lý sự kiện vòng đời đang chạy, bảng điều khiển Firebase sẽ báo cáo cho người dùng rằng phiên bản tiện ích mở rộng đang thực hiện một tác vụ xử lý. Chức năng xử lý của bạn có thể báo cáo lại trạng thái đang diễn ra và hoàn thành nhiệm vụ cho người dùng.

Để thêm trình xử lý sự kiện trong vòng đời nhằm chèn lấp các thư hiện có, hãy làm như sau:

  1. Xác định Chức năng đám mây mới được kích hoạt bởi các sự kiện trong hàng đợi tác vụ:

    hàm/index.js

    import { tasks } from "firebase-functions/v1";
    
    import { getDatabase } from "firebase-admin/database";
    import { getExtensions } from "firebase-admin/extensions";
    import { getFunctions } from "firebase-admin/functions";
    
    export const backfilldata = tasks.taskQueue().onDispatch(async () => {
      const batch = await getDatabase()
        .ref(process.env.MESSAGE_PATH)
        .parent.parent.orderByChild("upper")
        .limitToFirst(20)
        .get();
    
      const promises = [];
      for (const key in batch.val()) {
        const msg = batch.child(key);
        if (msg.hasChild("original") && !msg.hasChild("upper")) {
          const upper = msg.child("original").val().toUpperCase();
          promises.push(msg.child("upper").ref.set(upper));
        }
      }
      await Promise.all(promises);
    
      if (promises.length > 0) {
        const queue = getFunctions().taskQueue(
          "backfilldata",
          process.env.EXT_INSTANCE_ID
        );
        return queue.enqueue({});
      } else {
        return getExtensions()
          .runtime()
          .setProcessingState("PROCESSING_COMPLETE", "Backfill complete.");
      }
    });
    

    Lưu ý rằng hàm chỉ xử lý một vài bản ghi trước khi thêm chính nó trở lại hàng đợi tác vụ. Đây là chiến lược thường được sử dụng để xử lý các tác vụ xử lý không thể hoàn thành trong khoảng thời gian chờ của Chức năng đám mây. Vì bạn không thể dự đoán số lượng tin nhắn mà người dùng có thể đã có trong cơ sở dữ liệu của họ khi họ cài đặt tiện ích mở rộng của bạn nên chiến lược này rất phù hợp.

  2. Trong tệp extension.yaml , hãy khai báo hàm chèn lấp của bạn dưới dạng tài nguyên tiện ích mở rộng có thuộc tính taskQueueTrigger :

    resources:
      - name: makeuppercase
        ...
      - name: backfilldata
        type: firebaseextensions.v1beta.function
        description: >-
          Backfill existing messages with uppercase versions
        properties:
          runtime: "nodejs18"
          taskQueueTrigger: {}
    

    Sau đó khai báo hàm làm trình xử lý cho sự kiện vòng đời onInstall :

    lifecycleEvents:
      onInstall:
        function: backfilldata
        processingMessage: Uppercasing existing messages
    
  3. Mặc dù việc chèn lấp các tin nhắn hiện có là điều tốt nhưng tiện ích mở rộng vẫn có thể hoạt động mà không cần đến nó. Trong những tình huống như thế này, bạn nên đặt việc chạy trình xử lý sự kiện trong vòng đời là tùy chọn.

    Để làm như vậy, hãy thêm một tham số mới vào extension.yaml :

    - param: DO_BACKFILL
      label: Backfill existing messages
      description: >-
        Generate uppercase versions of existing messages?
      type: select
      required: true
      options:
        - label: Yes
          value: true
        - label: No
          value: false
    

    Sau đó, khi bắt đầu chức năng chèn lấp, hãy kiểm tra giá trị của tham số DO_BACKFILL và thoát sớm nếu nó không được đặt:

    hàm/index.js

    if (!process.env.DO_BACKFILL) {
      return getExtensions()
        .runtime()
        .setProcessingState("PROCESSING_COMPLETE", "Backfill skipped.");
    }
    

Với những thay đổi ở trên, giờ đây tiện ích mở rộng sẽ chuyển đổi các tin nhắn hiện có sang chữ hoa khi được cài đặt.

Cho đến thời điểm này, bạn đã sử dụng trình mô phỏng tiện ích mở rộng để phát triển tiện ích mở rộng của mình và kiểm tra các thay đổi đang diễn ra. Tuy nhiên, trình mô phỏng tiện ích mở rộng sẽ bỏ qua quá trình cài đặt, do đó, để kiểm tra trình xử lý sự kiện onInstall , bạn cần cài đặt tiện ích mở rộng trong một dự án thực. Tuy nhiên, điều đó cũng tốt vì với việc bổ sung tính năng chèn lấp tự động này, tiện ích mở rộng hướng dẫn hiện đã hoàn chỉnh về mã!

9. Triển khai vào dự án Firebase thực sự

Mặc dù trình mô phỏng tiện ích mở rộng là một công cụ tuyệt vời để lặp lại nhanh chóng tiện ích mở rộng trong quá trình phát triển, nhưng đến một lúc nào đó, bạn sẽ muốn thử nó trong một dự án thực tế.

Để làm như vậy, trước tiên hãy thiết lập một dự án mới với một số dịch vụ được kích hoạt:

  1. Trong bảng điều khiển Firebase , thêm một dự án mới.
  2. Nâng cấp dự án của bạn lên gói Blaze trả tiền khi sử dụng. Chức năng đám mây cho Firebase yêu cầu dự án của bạn phải có tài khoản thanh toán, vì vậy bạn cũng cần có tài khoản thanh toán để cài đặt tiện ích mở rộng.
  3. Trong dự án mới của bạn, hãy bật Cơ sở dữ liệu thời gian thực .
  4. Vì bạn muốn kiểm tra khả năng chèn lấp dữ liệu hiện có khi cài đặt của tiện ích mở rộng, hãy nhập một số dữ liệu mẫu vào phiên bản cơ sở dữ liệu thời gian thực của bạn:
    1. Tải xuống một số dữ liệu RTDB hạt giống .
    2. Trên trang Cơ sở dữ liệu thời gian thực của bảng điều khiển Firebase, nhấp vào (thêm) > Nhập JSON và chọn tệp bạn vừa tải xuống.
  5. Để kích hoạt chức năng chèn lấp để sử dụng phương thức orderByChild , hãy định cấu hình cơ sở dữ liệu để lập chỉ mục các thông báo theo giá trị của upper :

    {
      "rules": {
        ".read": false,
        ".write": false,
        "messages": {
          ".indexOn": "upper"
        }
      }
    }
    

Bây giờ hãy cài đặt tiện ích mở rộng của bạn từ nguồn cục bộ vào dự án mới:

  1. Tạo một thư mục mới cho dự án Firebase của bạn:

    mkdir ~/extensions-live-test && cd ~/extensions-live-test
    
  2. Khởi tạo dự án Firebase trong thư mục làm việc:

    firebase init database
    

    Khi được nhắc, hãy chọn dự án bạn vừa tạo.

  3. Cài đặt tiện ích mở rộng vào dự án Firebase cục bộ của bạn:

    firebase ext:install /path/to/rtdb-uppercase-messages
    

    Tại đây, bạn có thể xem trải nghiệm người dùng như thế nào khi cài đặt tiện ích mở rộng bằng công cụ Firebase CLI. Hãy nhớ chọn "có" khi công cụ cấu hình hỏi bạn có muốn chèn lấp cơ sở dữ liệu hiện có của mình không.

    Sau khi bạn chọn các tùy chọn cấu hình, Firebase CLI sẽ lưu cấu hình của bạn trong thư mục extensions và ghi lại vị trí nguồn tiện ích mở rộng trong tệp firebase.json . Nói chung, hai bản ghi này được gọi là bản kê khai tiện ích mở rộng . Người dùng có thể sử dụng tệp kê khai để lưu cấu hình tiện ích mở rộng của mình và triển khai nó cho các dự án khác nhau.

  4. Triển khai cấu hình tiện ích mở rộng cho dự án trực tiếp của bạn:

    firebase deploy --only extensions
    

Nếu mọi việc suôn sẻ, Firebase CLI sẽ tải tiện ích mở rộng lên dự án của bạn và cài đặt nó. Sau khi quá trình cài đặt hoàn tất, tác vụ chèn lấp sẽ chạy và sau vài phút, cơ sở dữ liệu của bạn sẽ được cập nhật bằng các thông báo viết hoa. Thêm một số nút mới vào cơ sở dữ liệu tin nhắn và đảm bảo tiện ích mở rộng cũng hoạt động với các tin nhắn mới.

10. Viết tài liệu

Trước khi bạn chia sẻ tiện ích mở rộng của mình với người dùng, hãy đảm bảo bạn cung cấp đủ tài liệu để họ thành công.

Khi bạn khởi tạo dự án tiện ích mở rộng, Firebase CLI đã tạo các phiên bản sơ khai của tài liệu bắt buộc tối thiểu. Cập nhật các tệp này để phản ánh chính xác tiện ích mở rộng bạn đã tạo.

phần mở rộng.yaml

Bạn đã cập nhật tệp này khi phát triển tiện ích mở rộng này, vì vậy, bạn không cần thực hiện thêm bất kỳ cập nhật nào ngay bây giờ.

Tuy nhiên, đừng bỏ qua tầm quan trọng của tài liệu có trong tệp này. Ngoài thông tin nhận dạng quan trọng của tiện ích mở rộng—tên, mô tả, tác giả, vị trí kho lưu trữ chính thức—tệp tiện ích extension.yaml còn chứa tài liệu hướng tới người dùng về mọi tài nguyên và tham số mà người dùng có thể định cấu hình. Thông tin này được hiển thị cho người dùng trong bảng điều khiển Firebase, Trung tâm tiện ích mở rộng và Firebase CLI.

PREINSTALL.md

Trong tệp này, hãy cung cấp thông tin người dùng cần trước khi họ cài đặt tiện ích mở rộng của bạn: mô tả ngắn gọn chức năng của tiện ích mở rộng, giải thích mọi điều kiện tiên quyết và cung cấp cho người dùng thông tin về ý nghĩa thanh toán của việc cài đặt tiện ích mở rộng. Nếu bạn có một trang web có thông tin bổ sung, đây cũng là một nơi tốt để liên kết nó.

Văn bản của tệp này được hiển thị cho người dùng trong Trung tâm tiện ích mở rộng và bằng lệnh firebase ext:info .

Dưới đây là ví dụ về tệp PREINSTALL:

Use this extension to automatically convert strings to upper case when added to
a specified Realtime Database path.

This extension expects a database layout like the following example:

    "messages": {
      MESSAGE_ID: {
        "original": MESSAGE_TEXT
      },
      MESSAGE_ID: {
        "original": MESSAGE_TEXT
      },
    }

When you create new string records, this extension creates a new sibling record
with upper-cased text:

    MESSAGE_ID: {
      "original": MESSAGE_TEXT,
      "upper": UPPERCASE_MESSAGE_TEXT,
    }

#### Additional setup

Before installing this extension, make sure that you've
[set up Realtime Database](https://firebase.google.com/docs/database/quickstart)
in your Firebase project.

#### Billing

To install an extension, your project must be on the
[Blaze (pay as you go) plan](https://firebase.google.com/pricing).

- This extension uses other Firebase and Google Cloud Platform services, which
  have associated charges if you exceed the service's no-cost tier:
  - Realtime Database
  - Cloud Functions (Node.js 10+ runtime)
    [See FAQs](https://firebase.google.com/support/faq#extensions-pricing)
- If you enable events,
  [Eventarc fees apply](https://cloud.google.com/eventarc/pricing).

POSTINSTALL.md

Tệp này chứa thông tin hữu ích cho người dùng sau khi họ cài đặt thành công tiện ích mở rộng của bạn: ví dụ: các bước thiết lập tiếp theo, ví dụ về tiện ích mở rộng đang hoạt động, v.v.

Nội dung của POSTINSTALL.md được hiển thị trong bảng điều khiển Firebase sau khi tiện ích mở rộng được định cấu hình và cài đặt. Bạn có thể tham chiếu các tham số người dùng trong tệp này và chúng sẽ được thay thế bằng các giá trị được định cấu hình.

Đây là một ví dụ về tệp cài đặt sau cho phần mở rộng hướng dẫn:

### See it in action

You can test out this extension right away!

1.  Go to your
    [Realtime Database dashboard](https://console.firebase.google.com/project/${param:PROJECT_ID}/database/${param:PROJECT_ID}/data) in the Firebase console.

1.  Add a message string to a path that matches the pattern `${param:MESSAGE_PATH}`.

1.  In a few seconds, you'll see a sibling node named `upper` that contains the
    message in upper case.

### Using the extension

We recommend adding data by pushing -- for example,
`firebase.database().ref().push()` -- because pushing assigns an automatically
generated ID to the node in the database. During retrieval, these nodes are
guaranteed to be ordered by the time they were added. Learn more about reading
and writing data for your platform (iOS, Android, or Web) in the
[Realtime Database documentation](https://firebase.google.com/docs/database/).

### Monitoring

As a best practice, you can
[monitor the activity](https://firebase.google.com/docs/extensions/manage-installed-extensions#monitor)
of your installed extension, including checks on its health, usage, and logs.

CHANGELOG.md

Bạn cũng nên ghi lại những thay đổi bạn thực hiện giữa các lần phát hành tiện ích mở rộng trong tệp CHANGELOG.md .

Vì tiện ích mở rộng mẫu chưa bao giờ được xuất bản trước đây nên nhật ký thay đổi chỉ có một mục:

## Version 0.0.1

Initial release of the _Convert messages to upper case_ extension.

README.md

Hầu hết các tiện ích mở rộng cũng cung cấp tệp readme vì lợi ích của người dùng truy cập kho lưu trữ của tiện ích mở rộng. bạn có thể viết tệp này bằng tay hoặc tạo tệp đọc cho tôi bằng lệnh.

Với mục đích của hướng dẫn này, hãy bỏ qua việc ghi tệp readme.

Tài liệu bổ sung

Tài liệu được thảo luận ở trên là bộ tài liệu tối thiểu bạn nên cung cấp cho người dùng. Nhiều tiện ích mở rộng yêu cầu tài liệu chi tiết hơn để người dùng sử dụng thành công. Trong trường hợp này, bạn nên viết tài liệu bổ sung và lưu trữ nó ở nơi nào đó mà bạn có thể hướng người dùng tới.

Vì mục đích của hướng dẫn này, hãy bỏ qua việc viết tài liệu mở rộng hơn.

11. Xuất bản trên Trung tâm tiện ích mở rộng

Giờ đây, tiện ích mở rộng của bạn đã có mã hoàn chỉnh và được ghi lại, bạn đã sẵn sàng chia sẻ tiện ích đó với mọi người trên Trung tâm Tiện ích mở rộng. Nhưng vì đây chỉ là hướng dẫn nên bạn đừng thực sự làm vậy. Hãy bắt đầu viết tiện ích mở rộng của riêng bạn bằng cách sử dụng những gì bạn đã học ở đây và trong phần còn lại của tài liệu dành cho nhà xuất bản Tiện ích mở rộng Firebase, đồng thời bằng cách kiểm tra nguồn của các tiện ích mở rộng chính thức do Firebase viết.

Khi bạn sẵn sàng xuất bản tác phẩm của mình trên Trung tâm tiện ích mở rộng, đây là cách bạn sẽ thực hiện:

  1. Nếu bạn đang xuất bản tiện ích mở rộng đầu tiên của mình, hãy đăng ký làm nhà xuất bản tiện ích mở rộng . Khi đăng ký làm nhà xuất bản tiện ích mở rộng, bạn sẽ tạo ID nhà xuất bản cho phép người dùng nhanh chóng xác định bạn là tác giả của tiện ích mở rộng.
  2. Lưu trữ mã nguồn tiện ích mở rộng của bạn ở vị trí có thể xác minh công khai. Khi mã của bạn có sẵn từ một nguồn có thể xác minh được, Firebase có thể xuất bản tiện ích mở rộng của bạn trực tiếp từ vị trí này. Làm như vậy sẽ giúp đảm bảo rằng bạn đang xuất bản phiên bản tiện ích mở rộng hiện đã được phát hành và giúp ích cho người dùng bằng cách cho phép họ kiểm tra mã họ đang cài đặt vào dự án của mình.

    Hiện tại, điều này có nghĩa là cung cấp tiện ích mở rộng của bạn trong kho lưu trữ GitHub công khai.

  3. Tải tiện ích mở rộng của bạn lên Trung tâm tiện ích mở rộng bằng lệnh firebase ext:dev:upload .

  4. Đi tới trang tổng quan dành cho nhà xuất bản của bạn trong bảng điều khiển Firebase, tìm tiện ích mở rộng bạn vừa tải lên và nhấp vào "Xuất bản lên Trung tâm tiện ích mở rộng". Việc này yêu cầu nhân viên đánh giá của chúng tôi xem xét. Quá trình này có thể mất vài ngày. Nếu được phê duyệt, tiện ích mở rộng sẽ được xuất bản lên Trung tâm tiện ích mở rộng. Nếu bị từ chối, bạn sẽ nhận được thông báo giải thích lý do; sau đó bạn có thể giải quyết các vấn đề được báo cáo và gửi lại để xem xét.