1. 事前準備
Firebase 擴充功能會因應 HTTP 要求,或來自其他 Firebase 和 Google 產品 (例如 Firebase 雲端通訊、Cloud Firestore 或 Pub/Sub) 的觸發事件,執行特定工作或一組工作。
建構項目
在本程式碼研究室中,您將建構 geohashing 的 Firebase 擴充功能。部署完成後,擴充功能就會在回應 Firestore 事件或透過可呼叫函式叫用時,將 X 和 Y 座標轉換為地理雜湊。您可以將這項功能做為替代方案,在所有目標平台上實作 geofire 程式庫來儲存資料,節省時間。
課程內容
- 如何將現有的 Cloud Functions 程式碼轉換為可發布的 Firebase 擴充功能
- 如何設定
extension.yaml
檔案 - 如何在擴充功能中儲存機密字串 (API 金鑰)
- 如何允許擴充功能開發人員根據需求設定擴充功能
- 如何測試及部署擴充功能
軟硬體需求
- Firebase CLI (安裝並登入)
- Google 帳戶,例如 Gmail 帳戶
- Node.js 和
npm
- 您偏好的開發環境
2. 做好準備
取得程式碼
這個擴充功能所需的一切都位於 GitHub 存放區中。如要開始進行本專案,請先取得程式碼並在慣用的開發環境中開啟。
- 將下載的 ZIP 檔案解壓縮。
- 如要安裝必要的依附元件,請在
functions
目錄中開啟終端機,然後執行npm install
指令。
設定 Firebase
本程式碼研究室強烈建議使用 Firebase 模擬器。如要使用實際的 Firebase 專案試用擴充功能開發作業,請參閱「建立 Firebase 專案」。本程式碼研究室使用 Cloud Functions,因此如果您使用實際的 Firebase 專案 (而非模擬器),請升級至 Blaze 定價方案。
想直接跳到某個單元嗎?
您可以下載完成的程式碼研究室版本。如果遇到問題,或想查看完成的擴充功能,請查看 GitHub 存放區的 codelab-end
分支,或下載完成的 zip 檔案。
3. 檢查程式碼
- 開啟 zip 檔案中的
index.ts
檔案。請注意,其中包含兩個 Cloud 函式宣告。
這些函式有什麼作用?
這些示範函式用於地理雜湊。這類函式會採用座標對,並轉換為 Firestore 地理查詢的最佳化格式。這些函式會模擬使用 API 呼叫,方便您進一步瞭解如何在擴充功能中處理機密資料類型。詳情請參閱對 Firestore 中的資料執行地理位置查詢的說明文件。
函式常數
常數會在 index.ts
檔案頂端提早宣告。其中部分常數會參照擴充功能定義的觸發條件。
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);
Firestore 觸發條件
index.ts
檔案中的第一個函式如下所示:
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,
}
);
});
這個函式是 Firestore 觸發程序。資料庫中發生寫入事件時,函式會對該事件做出反應,搜尋 xv
欄位和 yv
欄位,如果這兩個欄位都存在,函式就會計算地理雜湊,並將輸出內容寫入指定的文件輸出位置。輸入文件是由 users/{uid}
常數定義,這表示函式會讀取寫入 users/
集合的每份文件,然後處理這些文件的地理雜湊。然後將雜湊值輸出至同一份文件中的雜湊值欄位。
可呼叫函式
index.ts
檔案中的下一個函式如下所示:
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};
});
請注意 onCall
函式。這表示該函式是可呼叫的函式,可從用戶端應用程式程式碼內呼叫。這個可呼叫函式會採用 x
和 y
參數,並傳回地理雜湊。雖然在本程式碼研究室中不會直接呼叫這個函式,但這裡會納入這個函式,做為在 Firebase 擴充功能中設定的範例。
4. 設定 extension.yaml 檔案
瞭解擴充功能中的 Cloud Functions 程式碼用途後,即可將其封裝以供發布。每個 Firebase 擴充功能都附有 extension.yaml
檔案,說明擴充功能的用途和行為。
extension.yaml
檔案需要擴充功能的一些初始中繼資料。以下步驟將說明各個欄位的意義,以及為何需要這些欄位。
- 在先前下載的專案根目錄中建立
extension.yaml
檔案。請先新增下列項目:
name: geohash-ext
version: 0.0.1
specVersion: v1beta # Firebase Extensions specification version (do not edit)
擴充功能的名稱會做為擴充功能執行個體 ID 的基礎 (使用者可以安裝多個擴充功能執行個體,每個執行個體都有自己的 ID)。Firebase 接著會使用該執行個體 ID,產生擴充功能服務帳戶和擴充功能專屬資源的名稱。版本號碼代表擴充功能版本。版本號碼必須符合語意版本控管規定,且每當擴充功能的功能有變更時,您都必須更新版本號碼。擴充功能規格版本用於判斷要遵循的 Firebase 擴充功能規格,在本例中為 v1beta
。
- 在 YAML 檔案中加入一些方便使用者閱讀的詳細資料:
...
displayName: Latitude and longitude to GeoHash converter
description: A converter for changing your Latitude and longitude coordinates to geohashes.
開發人員與擴充功能互動時,會看到擴充功能名稱的友善顯示名稱。說明會簡要介紹擴充功能的功能。在 extensions.dev 上部署擴充功能時,畫面會顯示類似下列內容:
- 指定擴充功能中程式碼的授權。
...
license: Apache-2.0 # The license you want for the extension
- 指出擴充功能的作者,以及安裝擴充功能是否需要付費:
...
author:
authorName: AUTHOR_NAME
url: https://github.com/Firebase
billingRequired: true
author
部分可讓使用者知道,如果擴充功能發生問題或想瞭解更多資訊,該與誰聯絡。billingRequired
是必要參數,且必須設為 true
,因為所有擴充功能都依賴 Cloud Functions,而這項服務需要 Blaze 方案。
這涵蓋 extension.yaml
檔案中識別擴充功能所需的最少欄位數。如要進一步瞭解可在擴充功能中指定的其他識別資訊,請參閱說明文件。
5. 將 Cloud Functions 程式碼轉換為 Extensions 資源
擴充功能資源是 Firebase 在擴充功能安裝期間,於專案中建立的項目。擴充功能隨後會擁有這些資源,並使用特定服務帳戶來操作資源。在這個專案中,這些資源是 Cloud Functions,必須在 extension.yaml
檔案中定義,因為擴充功能不會自動從 functions 資料夾中的程式碼建立資源。如果 Cloud Functions 未明確宣告為資源,擴充功能部署時就無法部署這些函式。
使用者定義的部署位置
- 允許使用者指定要部署這個擴充功能的所在位置,並決定將擴充功能託管在靠近終端使用者或靠近資料庫的位置較好。在
extension.yaml
檔案中,加入選取位置的選項。
extension.yaml
您現在可以開始撰寫函式資源的設定。
- 在
extension.yaml
檔案中,為locationUpdate
函式建立資源物件。在extension.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}
您定義的 name
是專案 index.ts
檔案中定義的函式名稱。您要指定部署的函式 type
,目前應一律為 firebaseextensions.v1beta.function
。接著,您要定義這個函式的 properties
。您定義的第一個屬性是與這個函式相關聯的 eventTrigger
。如要反映擴充功能目前支援的內容,請使用 providers/cloud.firestore/eventTypes/document.write
中的 eventType
,這可在「為擴充功能編寫 Cloud Functions」說明文件中找到。您可將 resource
定義為文件位置。由於您目前的目標是反映程式碼中的內容,因此文件路徑會監聽 users/{uid}
,並以預設資料庫位置為前置。
- 擴充功能需要 Firestore 資料庫的讀取和寫入權限。在
extension.yaml
檔案的最後,指定擴充功能應具備的 IAM 角色,以便在開發人員的 Firebase 專案中使用資料庫。
roles:
- role: datastore.user
reason: Allows the extension to read / write to your Firestore instance.
datastore.user
角色來自擴充功能支援的 IAM 角色清單。由於擴充功能會讀取及寫入資料,因此 datastore.user
角色很適合。
- 您也必須新增可呼叫的函式。在
extension.yaml
檔案中,於資源屬性下建立新資源。這些屬性是可呼叫函式專屬的屬性:
- name: callableHash
type: firebaseextensions.v1beta.function
properties:
httpsTrigger: {}
雖然先前的資源使用 eventTrigger
,但這裡使用 httpsTrigger
,涵蓋可呼叫函式和 HTTPS 函式。
程式碼檢查
您需要進行許多設定,才能讓 extension.yaml
檔案中的程式碼比對 index.ts
檔案中的所有內容。此時,完成的 extension.yaml
檔案應如下所示:
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.
狀態檢查
此時,您已設定擴充功能的初始功能,因此可以使用 Firebase 模擬器試用擴充功能!
- 如果尚未呼叫
npm run build
,請在下載的擴充功能專案的函式資料夾中呼叫。 - 在主機系統上建立新目錄,並使用
firebase init
將該目錄連結至 Firebase 專案。
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.
- 在相同目錄中執行
firebase ext:install
。將/path/to/extension
替換為包含extension.yaml
檔案的目錄絕對路徑。
firebase ext:install /path/to/extension
This command does two things:
- 系統會提示您指定擴充功能執行個體的設定,並建立包含執行個體設定資訊的
*.env
檔案。 - 這會將擴充功能例項新增至
firebase.json
的extensions
區段。這會做為執行個體 ID 對應擴充功能版本的對應。 - 由於您是在本機部署專案,因此可以指定要使用本機檔案,而非 Google Cloud Secret Manager。
- 使用新設定啟動 Firebase 模擬器:
firebase emulators:start
- 執行
emulators:start
後,請前往模擬器網頁檢視中的 Firestore 分頁。 - 在
users
集合中新增文件,並包含xv
數字欄位和yv
數字欄位。
- 如果擴充功能安裝成功,系統會在文件中建立名為
hash
的新欄位。
清除項目以避免衝突
- 測試完成後,請解除安裝擴充功能,因為您要更新擴充功能程式碼,以免日後與目前的擴充功能發生衝突。
擴充功能可同時安裝多個相同擴充功能版本,因此解除安裝可確保先前安裝的擴充功能不會發生衝突。
firebase ext:uninstall geohash-ext
目前的解決方案可以運作,但如專案一開始所述,其中有硬式編碼的 API 金鑰,用於模擬與服務通訊。如何使用原始提供的 API 金鑰,改為使用終端使用者的 API 金鑰?請繼續閱讀下文瞭解詳情。
6. 讓擴充功能可供使用者設定
在本程式碼研究室中,您已設定擴充功能,可搭配您已編寫的函式使用,但如果使用者想改用經緯度,而非 y 和 x,來表示笛卡兒平面上的位置,該怎麼辦?此外,如何讓使用者提供自己的 API 金鑰,而不是使用您提供的 API 金鑰?您可能會快速超出該 API 的配額。在這種情況下,您需要設定及使用參數。
在 extension.yaml
檔案中定義基本參數
首先,請轉換開發人員可能需要自訂設定的項目。第一個是 XFIELD
和 YFIELD
參數。
- 在
extension.yaml
檔案中,加入下列程式碼,使用XFIELD
和YFIELD
欄位參數。這些參數位於先前定義的params
YAML 屬性內:
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 會以擴充功能製作人可見的方式命名參數。稍後指定參數值時,請使用這個值。
- 標籤是開發人員可理解的 ID,可讓他們瞭解參數的用途。
- description 則會詳細說明值。由於這項功能支援 Markdown,因此可以連結至額外說明文件,或醒目顯示對開發人員來說可能很重要的字詞。
- type 定義使用者設定參數值時的輸入機制。包括
string
、select
、multiSelect
、selectResource
和secret
等。如要進一步瞭解這些選項,請參閱說明文件。 - validationRegex 會將開發人員輸入的內容限制為特定 regex 值 (範例是根據這裡的簡單欄位名稱規範);如果失敗...
- validationErrorMessage 會向開發人員發出警示,指出失敗值。
- 如果開發人員未輸入任何文字,值會是 default。
- 必要表示開發人員不必輸入任何文字。
- 不可變動:開發人員可以更新這個擴充功能並變更這個值。在這種情況下,開發人員應能隨著需求變更欄位名稱。
- 範例可讓您瞭解有效輸入內容的格式。
這段內容資訊量很大!
- 您還需要將三個參數新增至
extension.yaml
檔案,才能新增特殊參數。
- 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
定義機密參數
現在,您需要管理使用者指定的 API 金鑰。這是機密字串,不應以純文字形式儲存在函式中。請改為將這個值儲存在 Cloud Secret Manager 中。這是雲端中的特殊位置,可儲存加密密鑰,防止密鑰意外洩漏。開發人員必須付費才能使用這項服務,但這能為 API 金鑰增添一層安全保障,並可能限制詐欺活動。使用者文件會提醒開發人員這是付費服務,以免帳單出現意外費用。整體而言,使用方式與上述其他字串資源類似。唯一的差別在於呼叫的型別是 secret
。
- 在
extension.yaml
檔案中,新增下列程式碼:
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
更新resource
屬性以使用參數
如先前所述,資源 (而非函式) 會定義資源的觀察方式,因此如要使用新參數,必須更新 locationUpdate
資源。
- 在
extension.yaml
檔案中,新增下列程式碼:
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}
檢查 extension.yaml
檔案
- 查看
extension.yaml
檔案。範例如下:
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.
在程式碼中存取參數
現在所有參數都已在 extension.yaml
檔案中設定完成,請將這些參數新增至 index.ts
檔案。
- 在
index.ts
檔案中,將預設值替換為process.env.PARAMETER_NAME
,這會擷取適當的參數值,並在部署至開發人員 Firebase 專案的函式程式碼中填入這些值。
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!;
一般來說,您會想對環境變數值執行空值檢查,但在這個情況下,您相信參數值已正確複製。程式碼現在已設定完畢,可搭配擴充功能參數運作。
7. 建立使用者文件
在模擬器上或 Firebase 擴充功能市集中測試程式碼之前,請先記錄擴充功能,讓開發人員瞭解使用擴充功能時會取得哪些內容。
- 首先,請建立
PREINSTALL.md
檔案,用於說明功能、安裝的任何必要條件,以及可能的帳單影響。
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)
- 如要節省編寫這個專案
README.md
的時間,請使用便利方法:
firebase ext:info . --markdown > README.md
這會合併 PREINSTALL.md
檔案的內容,以及 extension.yaml
檔案中額外資訊的詳細資料。
最後,請將剛安裝的擴充功能相關詳細資訊告知擴充功能開發人員。安裝完成後,開發人員可能會收到一些額外的指示和資訊,以及詳細的安裝後工作,例如在此設定用戶端程式碼。
- 建立
POSTINSTALL.md
檔案,然後加入下列安裝後資訊:
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);
});
監控
建議您監控已安裝擴充功能的活動,包括檢查健康狀態、使用情況和記錄。
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
這會重新編譯函式,以便在擴充功能部署至模擬器或 Firebase 時,一併部署最新的原始碼。
接著,請建立新目錄來測試擴充功能。由於擴充功能是從現有函式開發而來,請勿從設定擴充功能的資料夾進行測試,因為這樣也會嘗試一併部署函式和 Firebase 規則。
使用 Firebase 模擬器安裝及測試
- 在主機系統上建立新目錄,並使用
firebase init
將該目錄連結至 Firebase 專案。
mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- 從該目錄執行
firebase ext:install
,安裝擴充功能。將/path/to/extension
替換為包含extension.yaml
檔案的目錄絕對路徑。系統會開始安裝擴充功能,並建立包含設定的「.env
」檔案,然後將設定推送至 Firebase 或模擬器。
firebase ext:install /path/to/extension
- 由於您是在本機部署專案,請指定要使用本機檔案,而非 Google Cloud Secret Manager。
- 啟動本機模擬器套件:
firebase emulators:start
使用實際的 Firebase 專案安裝及測試
您可以在實際的 Firebase 專案中安裝擴充功能。建議您使用測試專案進行測試。如要測試擴充功能的端對端流程,或 Firebase 模擬器套件尚未支援擴充功能的觸發條件 (請參閱擴充功能模擬器選項),請使用這個測試工作流程。模擬器目前支援由 HTTP 要求觸發的函式,以及由 Cloud Firestore、即時資料庫和 Pub/Sub 的背景事件觸發的函式。
- 在主機系統上建立新目錄,並使用
firebase init
將該目錄連結至 Firebase 專案。
cd .. mkdir sample-proj cd sample-proj firebase init --project=projectID-or-alias
- 接著,從該目錄執行
firebase ext:install
安裝擴充功能。將/path/to/extension
替換為包含extension.yaml
檔案的目錄絕對路徑。系統會開始安裝擴充功能,並建立包含設定的「.env
」檔案,然後將設定推送至 Firebase 或模擬器。
firebase ext:install /path/to/extension
- 由於您想直接部署至 Firebase,並使用 Google Cloud Secret Manager,因此請先啟用 Secret Manager API,再安裝擴充功能。
- 部署至 Firebase 專案。
firebase deploy
測試擴充功能
- 執行
firebase deploy
或firebase emulators:start
後,請視需要前往 Firebase 控制台或模擬器的網頁檢視畫面,然後點選 Firestore 分頁。 - 將文件新增至
x
欄位和y
欄位指定的集合。在本例中,更新後的文件位於u/{uid}
,且x
欄位為xv
,y
欄位為yv
。
- 如果成功安裝擴充功能,儲存這兩個欄位後,擴充功能會在文件中建立名為
hash
的新欄位。
8. 恭喜!
您已成功將第一個 Cloud Functions 轉換為 Firebase 擴充功能!
您已新增 extension.yaml
檔案並完成設定,開發人員可以選擇要如何部署擴充功能。然後,您建立使用者文件,提供擴充功能開發人員在設定擴充功能前應執行的操作,以及成功安裝擴充功能後可能需要採取的步驟。
您現在已瞭解將 Firebase 函式轉換為可發布的 Firebase 擴充功能所需的重要步驟。