1. Trước khi bắt đầu
Tiện ích Firebase thực hiện một tác vụ hoặc nhóm tác vụ cụ thể để phản hồi yêu cầu HTTP hoặc sự kiện kích hoạt từ các sản phẩm khác của Firebase và Google 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 được triển khai, tiện ích của bạn sẽ chuyển đổi toạ độ X và Y thành hàm băm địa lý để phản hồi sự kiện Firestore hoặc thông qua các lệnh gọi hàm có thể gọi. Giải pháp này có thể được dùng thay cho việc triển khai thư viện geofire trên tất cả các nền tảng mục tiêu của bạn để 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à chuyể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 thử nghiệm và triển khai tiện ích
Bạn cần có
- Firebase CLI (cài đặt và đăng nhập)
- Một 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 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 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 đặc biệt khuyến khích bạn sử dụng trình mô phỏng Firebase. Nếu bạn muốn thử phát triển phần mở rộng bằng một dự án Firebase thực tế, hãy xem bài viết 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 tế 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 có muốn bỏ qua không?
Bạn có thể tải phiên bản đã hoàn thà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 nếu bạn muốn xem phần mở rộng hoàn chỉ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 chỉnh xuống.
3. Xem lại đoạn mã
- Mở tệp
index.ts
từ tệp zip. Lưu ý rằng trong thư viện này có chứa hai nội dung khai báo Cloud Functions.
Những chức năng 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à biến chúng 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 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ề cách chạy truy vấn địa lý trên dữ liệu trong Firestore.
Hằng số hàm
Hằng số được khai báo từ sớm, ở đầu tệp index.ts
. Một số hằng 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);
Trình kích hoạt khôi phục
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à điều kiện kích hoạt Firerestore. 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 trường xv
và trường yv
. Nếu cả hai trường đó đều tồn tại, hàm này sẽ tính toán giá trị băm địa lý và ghi kết quả vào một vị trí đầu ra 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 bộ sưu tập users/
, sau đó xử lý hàm băm địa lý cho các tài liệu đó. Sau đó, hàm băm sẽ xuất ra 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
sẽ có dạng như sau:
các tệp chỉ mục
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 ý hàm onCall
. Mã 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ã xử lý ứng dụng của bạn. Hàm có thể gọi này nhận các tham số x
và y
rồi trả về một hàm băm 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 nó được đưa vào đây dưới dạng một ví dụ về nội dung bạn có thể định cấu hình trong tiện ích Firebase.
4. Thiết lập tệp extensions.yaml
Giờ thì bạn đã biết mã Cloud Functions trong tiện ích của mình có chức năng gì, bạn đã sẵn sàng đóng gói để phân phối. Mỗi tiện ích Firebase đ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 các 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 đoạn mã sau:
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
Tên tiện ích được dùng làm cơ sở cho mã 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ột mã riêng). Sau đó, Firebase sẽ tạo tên cho tài khoản dịch vụ và tài nguyên dành riêng cho tiện ích của tiện ích bằng cách sử dụng mã phiên bản đó. Số phiên bản cho biết phiên bản của tiện ích. Tiện ích này phải tuân theo phiên bản ngữ nghĩa và bạn cần được cập nhật mỗi khi thay đổi chức năng của tiện ích. Phiên bản thông số kỹ thuật của tiện ích được dùng để xác định thông số kỹ thuật của tiện ích Firebase cần tuân thủ, trong trường hợp này, v1beta
sẽ được sử 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ị thể hiện tên tiện ích một cách thân thiện 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 đượ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 người viết tiện ích và liệu người dùng có bắt buộc phải 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
dùng để cho người dùng biết cần liên hệ với ai trong trường hợp họ 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ả tiện ích đều dựa vào Chức năng đám mây, do đó cần có Gói linh hoạt.
Việc này là về số lượng trường tối thiểu bắt buộc trong tệp extension.yaml
để xác định phần mở rộng này. Để biết thêm thông tin về thông tin nhận dạng khác mà bạn có thể chỉ định trong tiện ích, hãy xem tài liệu.
5. Chuyển đổi mã Cloud Functions thành tài nguyên Tiện ích
Tài nguyên tiện ích là một mục mà Firebase tạo ra trong dự án trong quá trình cài đặt tiện ích. Khi đó, tiện ích sẽ sở hữu các 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, những tài nguyên đó là Cloud Functions và bạn phải định nghĩa các hàm này trong tệp extension.yaml
vì tiện ích này sẽ không tự động tạo tài nguyên qua mã trong thư mục hàm. Nếu các Hàm đám mây của bạn không được khai báo rõ ràng là một tài nguyên, thì bạn sẽ không thể triển khai các hàm đó khi triển khai tiện ích.
Vị trí triển khai do người dùng xác định
- Cho phép người dùng chỉ định vị trí họ muốn triển khai tiện ích này và quyết định xem 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 tuỳ chọn chọn vị trí.
extension.yaml
Giờ đây, 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 phần sau đây 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àm 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 (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
liên kết với hàm này. Để phản chiếu những nội dung mà tiện ích này hỗ trợ, bạn sử dụng eventType
của providers/cloud.firestore/eventTypes/document.write
trong tài liệu về Viết hàm đám mây cho tiện ích của bạn. Bạn xác định resource
làm vị trí của tài liệu. Vì mục tiêu hiện tại của bạn là phản chiếu nội dung tồn tại 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 phía trước.
- Tiện ích này cần có quyền đọc và ghi đối với 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 để hoạt động 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
được lấy trong danh sách các vai trò IAM được hỗ trợ cho tiện ích. Vì tiện ích sẽ là đọc và ghi, nên vai trò datastore.user
là 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. Dưới đâ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
, ở đâ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 để giúp extension.yaml
khớp với mọi thứ do mã trong tệp index.ts
của bạn thực hiện. Lúc này, tệp extension.yaml
hoàn chỉnh sẽ có dạ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 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
Tại thời điểm này, bạn đã thiết lập các thành phần chức năng ban đầu của tiện ích, vì vậy, bạn có thể dùng thử tính năng này bằng trình mô phỏng Firebase!
- Nếu bạn chưa thực hiện việc này, hãy gọi
npm run build
trong thư mục hàm 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 lưu trữ và kết nối thư mục đó với dự án Firebase bằ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:
- Tiện ích này nhắc bạn chỉ định cấu hình cho thực thể tiện ích đó, đồng thời tạo một tệp
*.env
chứa thông tin cấu hình của phiên bản đó. - Thao tác này sẽ thêm bản sao tiện ích này vào phần
extensions
củafirebase.json
. Đối tượng này đóng vai trò liên kết mã phiên bản thực thể với phiên bản tiện ích. - Vì đang triển khai dự án cục bộ, nên bạn có thể chỉ định rằng bạn muốn sử dụng tệp trên máy chứ không phải Trình quản lý bí mật trên Google Cloud.
- Khởi động trình mô phỏng Firebase với cấu hình mới:
firebase emulators:start
- Sau khi chạy
emulators:start
, hãy chuyển đến thẻ Firestore trong chế độ xem web của trình mô phỏng. - Thêm một tài liệu vào tập hợ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, 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 thử nghiệm xong, hãy gỡ cài đặt tiện ích — bạn sẽ cập nhật mã tiện ích và không muốn xung đột với tiện ích hiện tại về sau.
Tiện ích cho phép cài đặt nhiều phiên bản của cùng một tiện ích cùng lúc. Vì vậy, bằng cách gỡ cài đặt, bạn đảm bảo rằng không có xung đột với tiện ích đã cài đặt trước đó.
firebase ext:uninstall geohash-ext
Giải pháp hiện tại đang hoạt động, nhưng như đã đề cập trong phần đầu của dự án, có một khoá API được mã hoá cứng để mô phỏng hoạt động giao tiếp với dịch vụ. Làm cách nào để 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. Làm cho tiện ích có thể định cấu hình người dùng
Tại thời điểm này của 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 việc thiết lập cố định của các hàm mà bạn đã viết, nhưng nếu người dùng của bạn 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 cartesian thì sao? Ngoài ra, làm cách nào để bạn khiến 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 sẽ 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
Hãy 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à tham số XFIELD
và YFIELD
.
- Trong tệp
extension.yaml
, hãy thêm mã sau. Mã này sử dụng các tham số trườngXFIELD
vàYFIELD
. Các tham số này nằm bên trong thuộc tính YAMLparams
đã 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 thông số theo cách hiển thị cho bạn, trình tạo tiện ích. Sau này, bạn có thể sử dụng giá trị này khi chỉ định giá trị thông số.
- label là giá trị nhận dạng mà con người có thể đọc được để nhà phát triển biết chức năng của tham số đó.
- description cung cấp nội dung mô tả chi tiết về giá trị. Vì có hỗ trợ công cụ đánh dấu nên công cụ này có thể liên kết đến tài liệu bổ sung hoặc có thể 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ế đầu vào về cách người dùng đặt giá trị thông số. Có nhiều loại tồn tại, bao gồm
string
,select
,multiSelect
,selectResource
vàsecret
. Để tìm hiểu thêm về từng lựa chọn, hãy xem tài liệu này. - ValidRegex ràng buộc mục nhập của nhà phát triển với một giá trị biểu thức chính quy nhất định (trong ví dụ, giá trị này dựa trên nguyên tắc về tên trường đơn giản có tại đây); và nếu không thành công...
- ValidErrorMessage cảnh báo nhà phát triển về giá trị lỗi.
- default (mặc định) là giá trị sẽ xuất hiện nếu nhà phát triển không nhập bất kỳ văn bản nào.
- 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.
- không thể thay đổi 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 phải có thể thay đổi tên trường khi yêu cầu của họ thay đổi.
- example cho biết giá trị nhập vào hợp lệ sẽ như thế nào.
Tôi hiểu rồi!
- Bạn có thêm 3 tham số khác để thêm 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 tham 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ạng văn bản thuần tuý trong hàm. Thay vào đó, hãy lưu trữ giá trị này trong Cloud Secret Manager (Trình quản lý bí mật của đám mây). Đây là một vị trí đặc biệt trên đám mây, lưu trữ các khoá bí mật đã mã hoá và ngăn không cho những bí mật đó vô tình bị rò rỉ. Theo đó, nhà phát triển phải trả phí để sử dụng dịch vụ này. Tuy nhiên, dịch vụ này bổ sung thêm một lớp bảo mật đối với khoá API của họ và hạn chế hoạt động gian lận. Tài liệu người dùng sẽ cảnh báo cho nhà phát triển rằng đây là một dịch vụ có tính phí để việc thanh toán không gây ra vấn đề bất ngờ. Nhìn chung, cách sử dụng này tương tự như các tài nguyên chuỗi khác đã đề cập ở trên. Điểm khác biệt duy nhất là loại có tên secret
.
- Trong tệp
extension.yaml
, hãy thêm 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 các thuộc tính resource
để sử dụng các tham số
Như đã đề cập trước đó, tài nguyên (không phải hàm) xác định cách quan sát tài nguyên, 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 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 thông số trong mã
Giờ đây, tất 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
. Các giá trị này sẽ tìm nạp các giá trị thông 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 kiểm tra giá trị rỗng bằng các giá trị biến môi trường. Tuy nhiên, trong trường hợp này, bạn tin tưởng rằng các giá trị tham số sẽ được sao chép chính xác. Mã hiện được định cấu hình để làm việc với các tham số tiện ích.
7. Tạo tài liệu người dùng
Trước khi kiểm tra mã trên trình mô phỏng hoặc trên trang web thương mại tiện ích của Firebase, bạn cần ghi lại tiện ích để nhà phát triển biết họ nhận được gì khi sử dụng tiện ích.
- Hãy 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 khi cài đặt cũng như các hệ quả về 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:
firebase ext:info . --markdown > README.md
Tệp này kết hợp nội dung của tệp PREINSTALL.md
và thông tin chi tiết khác về tiện ích trong tệp extension.yaml
.
Cuối cùng, thông báo cho nhà phát triển tiện ích này về một số thông tin chi tiết 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 việc cài đặt và có thể nhận một số thao tác chi tiết sau khi cài đặt như thiết lập mã ứng dụng khách tại đây.
- Tạo tệp
POSTINSTALL.md
, sau đó đưa vào thông tin cài đặt bài đăng sau đây:
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
Phương pháp hay nhất là 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 được triển khai trực tiếp trên trình mô phỏng hoặc 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 này được phát triển từ các hàm hiện có, bạn không nên thử nghiệm trong thư mục đã định cấu hình tiện ích, vì điều đó cũng sẽ tìm cách 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 lưu trữ và kết nối thư mục đó với dự án Firebase bằng
firebase init
.
mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- 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ấu hình của bạn trước khi đẩy cấu hình đó lên Firebase hoặc vào trình mô phỏng.
firebase ext:install /path/to/extension
- Vì bạn đang triển khai dự án cục bộ, nên hãy nêu rõ rằng bạn muốn sử dụng tệp trên máy chứ không phải Trình quản lý bí mật trên Google Cloud.
- Khởi động bộ 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 tế
Bạn có thể cài đặt phần mở rộng này trong một dự án Firebase thực tế. Bạn nên sử dụng dự án kiểm thử để kiểm thử. 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ợ điều kiện kích hoạt của tiện ích (xem Tuỳ chọn Trình mô phỏng tiện ích). Trình mô phỏng hiện hỗ trợ các hàm kích hoạt yêu cầu HTTP và hàm kích hoạt sự kiện ở chế độ nền cho Cloud Firestore, Cơ sở dữ liệu theo thời gian thực và Pub/Sub.
- Tạo một thư mục mới trên hệ thống lưu trữ và kết nối thư mục đó với dự án Firebase bằ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ấu hình của bạn trước khi đẩy cấu hình đó lên Firebase hoặc vào trình mô phỏng.
firebase ext:install /path/to/extension
- Vì muốn trực tiếp triển khai cho Firebase và muốn sử dụng Google Cloud Secret Manager, nên 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
Kiểm 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 chế độ xem web của trình mô phỏng (nếu phù hợp). - Thêm một tài liệu vào tập hợp được chỉ định bởi 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, 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 2 trường trên.
8. Xin chúc mừng!
Bạn đã chuyển đổi thành công Hàm đám mây đầu tiên của mình 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 này để các nhà phát triển có thể chọn cách họ muốn triển khai tiện ích của mình. Sau đó, bạn tạo tài liệu người dùng cung cấp hướng dẫn về những việc nhà phát triển tiện ích nê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 thành công tiện ích.
Giờ đây, bạn đã biết các bước chính cần thiết để chuyển đổi Hàm Firebase thành Tiện ích Firebase có thể phân phối.