1. Trước khi bắt đầu
Tiện ích Firebase thực hiện một nhiệm vụ hoặc một nhóm nhiệm vụ cụ thể để phản hồi các yêu cầu HTTP hoặc các sự kiện kích hoạt từ các sản phẩm khác của Firebase và Google, chẳng hạn như Giải pháp gửi thông báo qua đám mây của Firebase, Cloud Firestore hoặc Pub/Sub.
Sản phẩm bạn sẽ tạo ra
Trong lớp học lập trình này, bạn sẽ tạo một tiện ích Firebase để băm địa lý. Sau khi triển khai, tiện ích của bạn sẽ chuyển đổi toạ độ X và Y thành geohash để phản hồi các sự kiện Firestore hoặc thông qua lệnh gọi hàm có thể gọi. Bạn có thể sử dụng tính năng này thay vì triển khai thư viện geofire trên tất cả các nền tảng mục tiêu để lưu trữ dữ liệu, giúp bạn tiết kiệm thời gian.
Kiến thức bạn sẽ học được
- Cách lấy mã Cloud Functions hiện có và biến mã đó thành một Tiện ích Firebase có thể phân phối
- Cách thiết lập tệp
extension.yaml
- Cách lưu trữ các chuỗi nhạy cảm (khoá API) trong một tiện ích
- Cách cho phép nhà phát triển tiện ích định cấu hình tiện ích đó cho phù hợp với nhu cầu của họ
- Cách kiểm thử và triển khai tiện ích
Bạn cần
- Giao diện dòng lệnh (CLI) của Firebase (cài đặt và đăng nhập)
- Tài khoản Google, chẳng hạn như tài khoản Gmail
- Node.js và
npm
- Môi trường phát triển mà bạn yêu thích
2. Bắt đầu thiết lập
Lấy mã nguồn
Mọi thứ bạn cần cho tiện ích này đều nằm trong một kho lưu trữ GitHub. Để bắt đầu, hãy lấy mã và mở mã đó trong môi trường phát triển mà bạn yêu thích.
- Giải nén tệp zip đã tải xuống.
- Để cài đặt các phần phụ thuộc bắt buộc, hãy mở cửa sổ dòng lệnh trong thư mục
functions
rồi chạy lệnhnpm install
.
Thiết lập Firebase
Lớp học lập trình này khuyến khích bạn sử dụng trình mô phỏng Firebase. Nếu bạn muốn dùng thử tính năng phát triển tiện ích bằng một dự án Firebase thực, hãy xem phần tạo dự án Firebase. Lớp học lập trình này sử dụng Cloud Functions, vì vậy, nếu đang dùng một dự án Firebase thực thay vì trình mô phỏng, bạn cần nâng cấp lên gói giá linh hoạt.
Bạn muốn bỏ qua?
Bạn có thể tải phiên bản hoàn chỉnh của lớp học lập trình này xuống. Nếu bạn gặp khó khăn trong quá trình thực hiện hoặc muốn xem tiện ích đã hoàn thành trông như thế nào, hãy xem nhánh codelab-end
của kho lưu trữ GitHub hoặc tải tệp zip đã hoàn thành xuống.
3. Xem lại mã
- Mở tệp
index.ts
trong tệp zip. Xin lưu ý rằng tệp này chứa 2 khai báo Cloud Functions.
Những hàm này có chức năng gì?
Các hàm minh hoạ này được dùng để băm địa lý. Chúng lấy một cặp toạ độ và chuyển đổi cặp toạ độ đó thành một định dạng được tối ưu hoá cho các truy vấn địa lý trong Firestore. Các hàm này mô phỏng việc sử dụng một lệnh gọi API để bạn có thể tìm hiểu thêm về cách xử lý các loại dữ liệu nhạy cảm trong tiện ích. Để biết thêm thông tin, hãy xem tài liệu về chạy truy vấn Geo trên dữ liệu trong Firestore.
Hằng số hàm
Các hằng số được khai báo từ sớm, ở đầu tệp index.ts
. Một số hằng số trong số này được tham chiếu trong các điều kiện kích hoạt đã xác định của tiện ích.
index.ts
import {firestore} from "firebase-functions";
import {initializeApp} from "firebase-admin/app";
import {GeoHashService, ResultStatusCode} from "./fake-geohash-service";
import {onCall} from "firebase-functions/v1/https";
import {fieldValueExists} from "./utils";
const documentPath = "users/{uid}";
const xField = "xv";
const yField = "yv";
const apiKey = "1234567890";
const outputField = "hash";
initializeApp();
const service = new GeoHashService(apiKey);
Điều kiện kích hoạt Firestore
Hàm đầu tiên trong tệp index.ts
có dạng như sau:
index.ts
export const locationUpdate = firestore.document(documentPath)
.onWrite((change) => {
// item deleted
if (change.after == null) {
return 0;
}
// double check that both values exist for computation
if (
!fieldValueExists(change.after.data(), xField) ||
!fieldValueExists(change.after.data(), yField)
) {
return 0;
}
const x: number = change.after.data()![xField];
const y: number = change.after.data()![yField];
const hash = service.convertToHash(x, y);
// This is to check whether the hash value has changed. If
// it hasn't, you don't want to write to the document again as it
// would create a recursive write loop.
if (fieldValueExists(change.after.data(), outputField)
&& change.after.data()![outputField] == hash) {
return 0;
}
return change.after.ref
.update(
{
[outputField]: hash.hash,
}
);
});
Hàm này là một trình kích hoạt Firestore. Khi một sự kiện ghi xảy ra trong cơ sở dữ liệu, hàm sẽ phản ứng với sự kiện đó bằng cách tìm kiếm một trường xv
và một trường yv
. Nếu cả hai trường đó đều tồn tại, hàm sẽ tính toán geohash và ghi đầu ra vào một vị trí đầu ra của tài liệu được chỉ định. Tài liệu đầu vào được xác định bằng hằng số users/{uid}
, tức là hàm sẽ đọc mọi tài liệu được ghi vào tập hợp users/
rồi xử lý một geohash cho những tài liệu đó. Sau đó, hàm này sẽ xuất hàm băm vào một trường băm trong cùng một tài liệu.
Hàm có thể gọi
Hàm tiếp theo trong tệp index.ts
có dạng như sau:
index.ts
export const callableHash = onCall((data, context) => {
if (context.auth == undefined) {
return {error: "Only authorized users are allowed to call this endpoint"};
}
const x = data[xField];
const y = data[yField];
if (x == undefined || y == undefined) {
return {error: "Either x or y parameter was not declared"};
}
const result = service.convertToHash(x, y);
if (result.status != ResultStatusCode.ok) {
return {error: `Something went wrong ${result.message}`};
}
return {result: result.hash};
});
Hãy lưu ý đến hàm onCall
. Điều này cho biết hàm này là một hàm có thể gọi, có thể được gọi từ trong mã ứng dụng khách của bạn. Hàm có thể gọi này lấy các tham số x
và y
rồi trả về một geohash. Mặc dù hàm này sẽ không được gọi trực tiếp trong lớp học lập trình này, nhưng hàm này được đưa vào đây làm ví dụ về một nội dung cần định cấu hình trong tiện ích Firebase.
4. Thiết lập tệp extension.yaml
Giờ đây, khi đã biết mã Cloud Functions trong tiện ích của bạn làm gì, bạn đã sẵn sàng đóng gói mã đó để phân phối. Mỗi Tiện ích Firebase đều đi kèm với một tệp extension.yaml
mô tả chức năng và cách hoạt động của tiện ích.
Tệp extension.yaml
yêu cầu một số siêu dữ liệu ban đầu về tiện ích của bạn. Từng bước sau đây sẽ giúp bạn hiểu ý nghĩa của tất cả các trường và lý do bạn cần những trường đó.
- Tạo một tệp
extension.yaml
trong thư mục gốc của dự án mà bạn đã tải xuống trước đó. Bắt đầu bằng cách thêm những nội dung sau:
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
Tên của tiện ích được dùng làm cơ sở cho mã nhận dạng phiên bản của tiện ích (người dùng có thể cài đặt nhiều phiên bản của một tiện ích, mỗi phiên bản có mã nhận dạng riêng). Sau đó, Firebase sẽ tạo tên cho tài khoản dịch vụ của tiện ích và các tài nguyên dành riêng cho tiện ích bằng cách sử dụng mã nhận dạng phiên bản đó. Số phiên bản cho biết phiên bản của tiện ích. Bạn phải tuân theo phiên bản ngữ nghĩa và cần cập nhật phiên bản này bất cứ khi nào bạn thay đổi chức năng của tiện ích. Phiên bản đặc tả tiện ích được dùng để xác định đặc tả tiện ích Firebase cần tuân theo, trong trường hợp này, v1beta
sẽ được dùng.
- Thêm một số thông tin chi tiết thân thiện với người dùng vào tệp YAML:
...
displayName: Latitude and longitude to GeoHash converter
description: A converter for changing your Latitude and longitude coordinates to geohashes.
Tên hiển thị là một phiên bản thân thiện của tên tiện ích khi nhà phát triển tương tác với tiện ích của bạn. Nội dung mô tả cung cấp thông tin tổng quan ngắn gọn về chức năng của tiện ích. Khi tiện ích được triển khai trên extensions.dev, tiện ích sẽ có dạng như sau:
- Chỉ định giấy phép cho mã trong tiện ích của bạn.
...
license: Apache-2.0 # The license you want for the extension
- Cho biết ai đã viết tiện ích và liệu người dùng có cần thanh toán để cài đặt tiện ích đó hay không:
...
author:
authorName: AUTHOR_NAME
url: https://github.com/Firebase
billingRequired: true
Mục author
được dùng để cho người dùng biết họ cần liên hệ với ai trong trường hợp gặp vấn đề với tiện ích hoặc muốn biết thêm thông tin về tiện ích đó. billingRequired
là một tham số bắt buộc và phải được đặt thành true
vì tất cả các tiện ích đều dựa vào Cloud Functions, mà Cloud Functions yêu cầu gói Blaze.
Phần này đề cập đến số lượng tối thiểu các trường bắt buộc trong tệp extension.yaml
để xác định tiện ích này. Để biết thêm thông tin về những thông tin nhận dạng khác mà bạn có thể chỉ định trong một tiện ích, hãy xem tài liệu này.
5. Chuyển đổi mã Cloud Functions thành tài nguyên Extensions
Tài nguyên tiện ích là một mục mà Firebase tạo trong dự án trong quá trình cài đặt tiện ích. Sau đó, tiện ích sẽ sở hữu những tài nguyên đó và có một tài khoản dịch vụ cụ thể hoạt động trên các tài nguyên đó. Trong dự án này, các tài nguyên đó là Cloud Functions. Bạn phải xác định các tài nguyên này trong tệp extension.yaml
vì tiện ích sẽ không tự động tạo tài nguyên từ mã trong thư mục functions. Nếu Cloud Functions không được khai báo rõ ràng là một tài nguyên, thì chúng không thể được triển khai khi tiện ích được triển khai.
Vị trí triển khai do người dùng xác định
- Cho phép người dùng chỉ định vị trí mà họ muốn triển khai tiện ích này và quyết định xem có nên lưu trữ tiện ích gần người dùng cuối hơn hay gần cơ sở dữ liệu hơn. Trong tệp
extension.yaml
, hãy thêm lựa chọn chọn vị trí.
extension.yaml
Bây giờ, bạn đã sẵn sàng viết cấu hình cho tài nguyên hàm.
- Trong tệp
extension.yaml
, hãy tạo một đối tượng tài nguyên cho hàmlocationUpdate
. Thêm nội dung sau vào tệpextension.yaml
:
resources:
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}
Bạn xác định name
là tên hàm được xác định trong tệp index.ts
của dự án. Bạn chỉ định type
của hàm đang được triển khai, hàm này hiện tại phải luôn là firebaseextensions.v1beta.function
. Sau đó, bạn xác định properties
của hàm này. Thuộc tính đầu tiên mà bạn xác định là eventTrigger
được liên kết với hàm này. Để phản ánh những gì mà tiện ích hiện hỗ trợ, bạn hãy sử dụng eventType
của providers/cloud.firestore/eventTypes/document.write
. Bạn có thể tìm thấy thông tin này trong tài liệu Viết Cloud Functions cho tiện ích của bạn. Bạn xác định resource
là vị trí của các tài liệu. Vì mục tiêu hiện tại của bạn là phản ánh những gì có trong mã, nên đường dẫn tài liệu sẽ theo dõi users/{uid}
, với vị trí cơ sở dữ liệu mặc định đứng trước.
- Tiện ích này cần có quyền đọc và ghi cho cơ sở dữ liệu Firestore. Ở cuối tệp
extension.yaml
, hãy chỉ định các vai trò IAM mà tiện ích cần có quyền truy cập để làm việc với cơ sở dữ liệu trong dự án Firebase của nhà phát triển.
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
Vai trò datastore.user
nằm trong danh sách các vai trò IAM được hỗ trợ cho tiện ích. Vì tiện ích sẽ đọc và ghi nên vai trò datastore.user
là lựa chọn phù hợp ở đây.
- Bạn cũng phải thêm hàm có thể gọi. Trong tệp
extension.yaml
, hãy tạo một tài nguyên mới trong thuộc tính tài nguyên. Đây là các thuộc tính dành riêng cho một hàm có thể gọi:
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
Mặc dù tài nguyên trước đó sử dụng eventTrigger
, nhưng ở đây bạn sử dụng httpsTrigger
, bao gồm cả hàm có thể gọi và hàm HTTPS.
Kiểm tra mã
Đó là rất nhiều cấu hình để extension.yaml
của bạn khớp với mọi thứ mà mã trong tệp index.ts
của bạn thực hiện. Đây là nội dung của tệp extension.yaml
hoàn chỉnh tại thời điểm này:
extension.yaml
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
displayName: Latitude and Longitude to GeoHash converter
description: A converter for changing your Latitude and Longitude coordinates to geohashes.
license: Apache-2.0 # The license you want for the extension
author:
authorName: Sparky
url: https://github.com/Firebase
billingRequired: true
resources:
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
Kiểm tra trạng thái
Đến đây, bạn đã thiết lập các phần chức năng ban đầu của tiện ích, vì vậy, bạn có thể dùng thử bằng trình mô phỏng Firebase!
- Nếu chưa, hãy gọi
npm run build
trong thư mục functions của dự án tiện ích đã tải xuống. - Tạo một thư mục mới trên hệ thống máy chủ và kết nối thư mục đó với dự án Firebase bằng cách sử dụng
firebase init
.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
This command creates a `firebase.json` file in the directory. In the following steps, you push the configuration specified in this file to Firebase.
- Trong cùng thư mục đó, hãy chạy
firebase ext:install
. Thay thế/path/to/extension
bằng đường dẫn tuyệt đối đến thư mục chứa tệpextension.yaml
.
firebase ext:install /path/to/extension
This command does two things:
- Thao tác này sẽ nhắc bạn chỉ định cấu hình cho phiên bản tiện ích và tạo một tệp
*.env
chứa thông tin cấu hình cho phiên bản đó. - Thao tác này sẽ thêm thực thể tiện ích vào phần
extensions
củafirebase.json
. Đây là bản đồ mã nhận dạng phiên bản cho phiên bản tiện ích. - Vì đang triển khai dự án trên máy, nên bạn có thể chỉ định rằng bạn muốn sử dụng một tệp cục bộ thay vì Google Cloud Secret Manager.
- Khởi động trình mô phỏng Firebase bằng cấu hình mới:
firebase emulators:start
- Sau khi chạy
emulators:start
, hãy chuyển đến thẻ Firestore trong webview của trình mô phỏng. - Thêm một tài liệu vào bộ sưu tập
users
bằng trường sốxv
và trường sốyv
.
- Nếu bạn cài đặt thành công tiện ích này, thì tiện ích sẽ tạo một trường mới có tên là
hash
trong tài liệu.
Dọn dẹp để tránh xung đột
- Sau khi kiểm thử xong, hãy gỡ cài đặt tiện ích vì bạn sẽ cập nhật mã tiện ích và không muốn xảy ra xung đột với tiện ích hiện tại sau này.
Tiện ích cho phép bạn cài đặt nhiều phiên bản của cùng một tiện ích cùng một lúc. Vì vậy, khi gỡ cài đặt, bạn sẽ đảm bảo không xảy ra xung đột với một tiện ích đã cài đặt trước đó.
firebase ext:uninstall geohash-ext
Giải pháp hiện tại hoạt động, nhưng như đã đề cập ở phần đầu dự án, có một khoá API được mã hoá cứng để mô phỏng việc giao tiếp với một dịch vụ. Làm cách nào để bạn có thể sử dụng khoá API của người dùng cuối thay vì khoá được cung cấp ban đầu? Hãy đọc tiếp để tìm hiểu.
6. Cho phép người dùng định cấu hình tiện ích
Đến thời điểm này trong lớp học lập trình, bạn đã có một tiện ích được định cấu hình để sử dụng với chế độ thiết lập có chủ đích của các hàm mà bạn đã viết. Tuy nhiên, điều gì sẽ xảy ra nếu người dùng muốn sử dụng vĩ độ và kinh độ thay vì y và x cho các trường cho biết vị trí trên mặt phẳng Đề các? Ngoài ra, làm cách nào để người dùng cuối cung cấp khoá API của riêng họ thay vì để họ sử dụng khoá API được cung cấp? Bạn có thể nhanh chóng vượt quá hạn mức cho API đó. Trong trường hợp này, bạn thiết lập và sử dụng các tham số.
Xác định các tham số cơ bản trong tệp extension.yaml
Bắt đầu bằng cách chuyển đổi những mục mà nhà phát triển có thể có cấu hình tuỳ chỉnh. Tham số đầu tiên sẽ là XFIELD
và YFIELD
.
- Trong tệp
extension.yaml
, hãy thêm mã sau. Mã này sử dụngXFIELD
và các tham số trườngYFIELD
. Các tham số này nằm trong thuộc tính YAMLparams
mà bạn đã xác định trước đó:
extension.yaml
params:
- param: XFIELD
label: The X Field Name
description: >-
The X Field is also known as the **longitude** value. What does
your Firestore instance refer to as the X value or the longitude
value. If no value is specified, the extension searches for
field 'xv'.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: xv
required: false
immutable: false
example: xv
- param: YFIELD
label: The Y Field Name
description: >-
The Y Field is also known as the **latitude** value. What does
your Firestore instance refer to as the Y value or the latitude
value. If no value is specified, the extension searches for
field 'yv'.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: yv
required: false
immutable: false
example: yv
- param đặt tên cho tham số theo cách mà bạn (nhà sản xuất tiện ích) có thể thấy. Hãy sử dụng giá trị này sau khi chỉ định các giá trị tham số.
- label là một giá trị nhận dạng mà con người có thể đọc được để cho nhà phát triển biết tham số này làm gì.
- description cung cấp nội dung mô tả chi tiết về giá trị. Vì hỗ trợ markdown nên bạn có thể liên kết đến tài liệu bổ sung hoặc làm nổi bật những từ có thể quan trọng đối với nhà phát triển.
- type xác định cơ chế nhập để người dùng đặt giá trị tham số. Có nhiều loại, bao gồm
string
,select
,multiSelect
,selectResource
vàsecret
. Để tìm hiểu thêm về từng lựa chọn này, hãy xem tài liệu. - validationRegex hạn chế mục nhập của nhà phát triển đối với một giá trị regex nhất định (trong ví dụ này, giá trị đó dựa trên các nguyên tắc đơn giản về tên trường tại đây); và nếu không thành công...
- validationErrorMessage cảnh báo cho nhà phát triển về giá trị thất bại.
- default là giá trị sẽ xuất hiện nếu nhà phát triển không nhập văn bản nào.
- required (bắt buộc) có nghĩa là nhà phát triển không bắt buộc phải nhập bất kỳ văn bản nào.
- immutable cho phép nhà phát triển cập nhật tiện ích này và thay đổi giá trị này. Trong trường hợp này, nhà phát triển có thể thay đổi tên trường khi yêu cầu của họ thay đổi.
- example cho biết một đầu vào hợp lệ có thể trông như thế nào.
Có rất nhiều điều cần hiểu!
- Bạn cần thêm 3 tham số nữa vào tệp
extension.yaml
trước khi thêm một tham số đặc biệt.
- param: INPUTPATH
label: The input document to listen to for changes
description: >-
This is the document where you write an x and y value to. Once
that document has received a value, it notifies the extension to
calculate a geohash and store that in an output document in a certain
field. This accepts function [wildcard parameters](https://firebase.google.com/docs/functions/firestore-events#wildcards-parameters)
type: string
validationRegex: ^[^/]+(/[^/]*/[^/]*)*/[^/]+$
validationErrorMessage: >-
This must point to a document path, not a collection path from the root
of the database. It must also not start or end with a '/' character.
required: true
immutable: false
example: users/{uid}
- param: OUTPUTFIELD
label: Geohash field
description: >-
This specifies the field in the output document to store the geohash in.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
required: false
default: hash
immutable: false
example: hash
Xác định các thông số nhạy cảm
Bây giờ, bạn cần quản lý khoá API mà người dùng chỉ định. Đây là một chuỗi nhạy cảm không được lưu trữ dưới dạng văn bản thuần tuý trong hàm. Thay vào đó, hãy lưu trữ giá trị này trong Trình quản lý khoá bí mật trên đám mây. Đây là một vị trí đặc biệt trên đám mây, nơi lưu trữ các bí mật đã mã hoá và ngăn chặn tình trạng vô tình để lộ các bí mật đó. Điều này đòi hỏi nhà phát triển phải trả phí khi sử dụng dịch vụ này, nhưng nó sẽ bổ sung thêm một lớp bảo mật cho khoá API của họ và có khả năng hạn chế hoạt động gian lận. Tài liệu người dùng cảnh báo nhà phát triển rằng đây là một dịch vụ có tính phí, để không có bất kỳ điều gì bất ngờ trong việc thanh toán. Nhìn chung, cách sử dụng tương tự như các tài nguyên chuỗi khác được đề cập ở trên. Điểm khác biệt duy nhất là loại được gọi là secret
.
- Trong tệp
extension.yaml
, hãy thêm đoạn mã sau:
extension.yaml
- param: APIKEY
label: GeohashService API Key
description: >-
Your geohash service API Key. Since this is a demo, and not a real
service, you can use : 1234567890.
type: secret
required: true
immutable: false
Cập nhật resource
các thuộc tính để sử dụng tham số
Như đã đề cập trước đó, tài nguyên (không phải hàm) xác định cách tài nguyên được quan sát, vì vậy, bạn cần cập nhật tài nguyên locationUpdate
để sử dụng tham số mới.
- Trong tệp
extension.yaml
, hãy thêm đoạn mã sau:
extension.yaml
## Change from this
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}]
## To this
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/${INPUTPATH}
Kiểm tra tệp extension.yaml
- Xem lại tệp
extension.yaml
. Danh sách sẽ trông giống như sau:
extension.yaml
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
displayName: Latitude and Longitude to GeoHash converter
description: A converter for changing your Latitude and Longitude coordinates to geohashes.
license: Apache-2.0 # The license you want to use for the extension
author:
authorName: Sparky
url: https://github.com/Firebase
billingRequired: true
params:
- param: XFIELD
label: The X Field Name
description: >-
The X Field is also known as the **longitude** value. What does
your Firestore instance refer to as the X value or the longitude
value. If you don't provide a value for this field, the extension will use 'xv' as the default value.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: xv
required: false
immutable: false
example: xv
- param: YFIELD
label: The Y Field Name
description: >-
The Y Field is also known as the **latitude** value. What does
your Firestore instance refer to as the Y value or the latitude
Value. If you don't provide a value for this field, the extension will use 'yv' as the default value.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
default: yv
required: false
immutable: false
example: yv
- param: INPUTPATH
label: The input document to listen to for changes
description: >-
This is the document where you write an x and y value to. Once
that document has been modified, it notifies the extension to
compute a geohash and store that in an output document in a certain
field. This accepts function [wildcard parameters](https://firebase.google.com/docs/functions/firestore-events#wildcards-parameters)
type: string
validationRegex: ^[^/]+(/[^/]*/[^/]*)*/[^/]+$
validationErrorMessage: >-
This must point to a document path, not a collection path from the root
of the database. It must also not start or end with a '/' character.
required: true
immutable: false
example: users/{uid}
- param: OUTPUTFIELD
label: Geohash field
description: >-
This specifies the field in the output document to store the geohash in.
type: string
validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
validationErrorMessage: >-
The field can only contain uppercase or lowercase letter, numbers,
_, and . characters and must be less than 1500 bytes long. The field
must also not start with a number.
required: false
default: hash
immutable: false
example: hash
- param: APIKEY
label: GeohashService API Key
description: >-
Your geohash service API Key. Since this is a demo, and not a real
service, you can use : 1234567890.
type: secret
required: true
immutable: false
resources:
- name: locationUpdate
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/${INPUTPATH}
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
Truy cập vào các tham số trong mã
Bây giờ, khi tất cả các tham số đã được định cấu hình trong tệp extension.yaml
, hãy thêm các tham số đó vào tệp index.ts
.
- Trong tệp
index.ts
, hãy thay thế các giá trị mặc định bằngprocess.env.PARAMETER_NAME
. Thao tác này sẽ tìm nạp các giá trị tham số thích hợp và điền các giá trị đó vào mã hàm được triển khai trên dự án Firebase của nhà phát triển.
index.ts
// Replace this:
const documentPath = "users/{uid}";
const xField = "xv";
const yField = "yv";
const apiKey = "1234567890";
const outputField = "hash";
// with this:
const documentPath = process.env.INPUTPATH!; // this value is ignored since its read from the resource
const xField = process.env.XFIELD!;
const yField = process.env.YFIELD!;
const apiKey = process.env.APIKEY!;
const outputField = process.env.OUTPUTFIELD!;
Thông thường, bạn muốn thực hiện các quy trình kiểm tra giá trị rỗng bằng các giá trị biến môi trường, nhưng trong trường hợp này, bạn tin rằng các giá trị tham số được sao chép chính xác. Giờ đây, mã này được định cấu hình để hoạt động với các tham số của tiện ích.
7. Tạo tài liệu người dùng
Trước khi kiểm thử mã trên trình mô phỏng hoặc trong trang web thương mại của các tiện ích Firebase, bạn cần lập tài liệu cho tiện ích để nhà phát triển biết họ sẽ nhận được gì khi sử dụng tiện ích đó.
- Bắt đầu bằng cách tạo tệp
PREINSTALL.md
. Tệp này dùng để mô tả chức năng, mọi điều kiện tiên quyết để cài đặt và những tác động tiềm ẩn đến việc thanh toán.
PREINSTALL.md
Use this extension to automatically convert documents with a latitude and
longitude to a geohash in your database. Additionally, this extension includes a callable function that allows users to make one-time calls
to convert an x,y coordinate into a geohash.
Geohashing is supported for latitudes between 90 and -90 and longitudes
between 180 and -180.
#### Third Party API Key
This extension uses a fictitious third-party API for calculating the
geohash. You need to supply your own API keys. (Since it's fictitious,
you can use 1234567890 as an API key).
#### Additional setup
Before installing this extension, make sure that you've [set up a Cloud
Firestore database](https://firebase.google.com/docs/firestore/quickstart) in your Firebase project.
After installing this extension, you'll need to:
- Update your client code to point to the callable geohash function if you
want to perform arbitrary geohashes.
Detailed information for these post-installation tasks are provided after
you install this extension.
#### 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:
- Cloud Firestore
- Cloud Functions (Node.js 16+ runtime. [See
FAQs](https://firebase.google.com/support/faq#extensions-pricing))
- [Cloud Secret Manager](https://cloud.google.com/secret-manager/pricing)
- Để tiết kiệm thời gian viết
README.md
cho dự án này, hãy sử dụng phương thức thuận tiện sau:
firebase ext:info . --markdown > README.md
Thao tác này kết hợp nội dung của tệp PREINSTALL.md
và thông tin chi tiết bổ sung về tiện ích từ tệp extension.yaml
.
Cuối cùng, hãy thông báo cho nhà phát triển tiện ích về một số thông tin bổ sung liên quan đến tiện ích vừa được cài đặt. Nhà phát triển có thể nhận được một số hướng dẫn và thông tin bổ sung sau khi hoàn tất quá trình cài đặt và có thể nhận được một số nhiệm vụ chi tiết sau khi cài đặt, chẳng hạn như thiết lập mã ứng dụng ở đây.
- Tạo tệp
POSTINSTALL.md
, sau đó thêm thông tin sau khi cài đặt:
POSTINSTALL.md
Congratulations on installing the geohash extension!
#### Function information
* **Firestore Trigger** - ${function:locationUpdate.name} was installed
and is invoked when both an x field (${param:XFIELD}) and y field
(${param:YFIELD}) contain a value.
* **Callable Trigger** - ${function:callableHash.name} was installed and
can be invoked by writing the following client code:
```javascript
import { getFunctions, httpsCallable } from "firebase/functions";
const functions = getFunctions();
const geoHash = httpsCallable(functions, '${function:callableHash.name}');
geoHash({ ${param:XFIELD}: -122.0840, ${param:YFIELD}: 37.4221 })
.then((result) => {
// Read result of the Cloud Function.
/** @type {any} */
const data = result.data;
const error = data.error;
if (error != null) {
console.error(`callable error : ${error}`);
}
const result = data.result;
console.log(result);
});
Giám sát
Theo phương pháp hay nhất, bạn có thể giám sát hoạt động của tiện ích đã cài đặt, bao gồm cả việc kiểm tra tình trạng, mức sử dụng và nhật ký của tiện ích.
The output rendering looks something like this when it's deployed:
<img src="img/82b54a5c6ca34b3c.png" alt="A preview of the latitude and longitude geohash converter extension in the firebase console" width="957.00" />
## Test the extension with the full configuration
Duration: 03:00
It's time to make sure that the user-configurable extension is working the way it is intended.
* Change into the functions folder and ensure that the latest compiled version of the extensions exists. In the extensions project functions directory, call:
```console
npm run build
Thao tác này sẽ biên dịch lại các hàm để mã nguồn mới nhất sẵn sàng triển khai cùng với tiện ích khi tiện ích được triển khai đến một trình mô phỏng hoặc trực tiếp đến Firebase.
Tiếp theo, hãy tạo một thư mục mới để kiểm thử tiện ích. Vì tiện ích được phát triển từ các hàm hiện có, nên đừng kiểm thử từ thư mục mà tiện ích được định cấu hình vì thao tác đó cũng sẽ cố gắng triển khai các hàm và quy tắc Firebase cùng với tiện ích.
Cài đặt và kiểm thử bằng trình mô phỏng Firebase
- Tạo một thư mục mới trên hệ thống máy chủ và kết nối thư mục đó với dự án Firebase bằng cách sử dụng
firebase init
.
mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Trong thư mục đó, hãy chạy
firebase ext:install
để cài đặt tiện ích. Thay thế/path/to/extension
bằng đường dẫn tuyệt đối đến thư mục chứa tệpextension.yaml
. Thao tác này sẽ bắt đầu quá trình cài đặt tiện ích và tạo một tệp.env
chứa các cấu hình của bạn trước khi đẩy cấu hình đó lên Firebase hoặc trình mô phỏng.
firebase ext:install /path/to/extension
- Vì bạn đang triển khai dự án cục bộ, hãy chỉ định rằng bạn muốn sử dụng một tệp cục bộ thay vì Google Cloud Secret Manager.
- Khởi động bộ công cụ mô phỏng cục bộ:
firebase emulators:start
Cài đặt và thử nghiệm bằng một dự án Firebase thực
Bạn có thể cài đặt tiện ích trong một dự án Firebase thực tế. Bạn nên sử dụng một dự án kiểm thử để kiểm thử. Hãy sử dụng quy trình kiểm thử này nếu bạn muốn kiểm thử quy trình toàn diện của tiện ích hoặc nếu bộ mô phỏng Firebase chưa hỗ trợ trình kích hoạt của tiện ích (xem Lựa chọn về trình mô phỏng tiện ích). Các trình mô phỏng hiện hỗ trợ các hàm được kích hoạt bằng yêu cầu HTTP và các hàm được kích hoạt bằng sự kiện nền cho Cloud Firestore, Realtime Database và Pub/Sub.
- Tạo một thư mục mới trên hệ thống máy chủ và kết nối thư mục đó với dự án Firebase bằng cách sử dụng
firebase init
.
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- Sau đó, từ thư mục đó, hãy chạy
firebase ext:install
để cài đặt tiện ích. Thay thế/path/to/extension
bằng đường dẫn tuyệt đối đến thư mục chứa tệpextension.yaml
. Thao tác này sẽ bắt đầu quá trình cài đặt tiện ích và tạo một tệp.env
chứa các cấu hình của bạn trước khi đẩy cấu hình đó lên Firebase hoặc trình mô phỏng.
firebase ext:install /path/to/extension
- Vì muốn triển khai trực tiếp lên Firebase và sử dụng Google Cloud Secret Manager, bạn cần kích hoạt Secret Manager API trước khi cài đặt tiện ích.
- Triển khai cho dự án Firebase của bạn.
firebase deploy
Dùng thử tiện ích
- Sau khi chạy
firebase deploy
hoặcfirebase emulators:start
, hãy chuyển đến thẻ Firestore của bảng điều khiển của Firebase hoặc webview của trình mô phỏng, tuỳ theo trường hợp. - Thêm một tài liệu vào bộ sưu tập được chỉ định theo trường
x
và trườngy
. Trong trường hợp này, các tài liệu đã cập nhật nằm tạiu/{uid}
với trườngx
làxv
và trườngy
làyv
.
- Nếu bạn cài đặt thành công tiện ích này, thì tiện ích sẽ tạo một trường mới có tên là
hash
trong tài liệu sau khi bạn lưu hai trường này.
8. Xin chúc mừng!
Bạn đã chuyển đổi thành công Cloud Functions đầu tiên thành một Tiện ích Firebase!
Bạn đã thêm một tệp extension.yaml
và định cấu hình tệp đó để nhà phát triển có thể chọn cách họ muốn triển khai tiện ích của bạn. Sau đó, bạn đã tạo tài liệu người dùng hướng dẫn những việc mà nhà phát triển tiện ích cần làm trước khi thiết lập tiện ích và những bước họ có thể cần thực hiện sau khi cài đặt tiện ích thành công.
Giờ đây, bạn đã biết các bước quan trọng cần thiết để chuyển đổi một Hàm Firebase thành một Tiện ích Firebase có thể phân phối.