1. ก่อนเริ่มต้น
ส่วนขยาย Firebase จะทำงานเฉพาะอย่างหรือชุดงานเพื่อตอบสนองต่อคำขอ HTTP หรือเหตุการณ์ที่ทริกเกอร์จากผลิตภัณฑ์อื่นๆ ของ Firebase และ Google เช่น Firebase Cloud Messaging, Cloud Firestore หรือ Pub/Sub
สิ่งที่คุณจะสร้าง
ในโค้ดแล็บนี้ คุณจะได้สร้างส่วนขยาย Firebase สำหรับการเข้ารหัสตำแหน่งทางภูมิศาสตร์ เมื่อติดตั้งใช้งานแล้ว ส่วนขยายจะแปลงพิกัด X และ Y เป็น Geohash เพื่อตอบสนองต่อเหตุการณ์ Firestore หรือผ่านการเรียกใช้ฟังก์ชันที่เรียกใช้ได้ ซึ่งสามารถใช้แทนการติดตั้งใช้งานไลบรารี GeoFire ในแพลตฟอร์มเป้าหมายทั้งหมดเพื่อจัดเก็บข้อมูล ซึ่งช่วยประหยัดเวลาได้
สิ่งที่คุณจะได้เรียนรู้
- วิธีนำโค้ด Cloud Functions ที่มีอยู่มาเปลี่ยนให้เป็น Firebase Extension ที่แจกจ่ายได้
- วิธีตั้งค่าไฟล์
extension.yaml
- วิธีจัดเก็บสตริงที่ละเอียดอ่อน (คีย์ API) ในส่วนขยาย
- วิธีอนุญาตให้นักพัฒนาส่วนขยายกำหนดค่าให้เหมาะกับความต้องการ
- วิธีทดสอบและติดตั้งใช้งานส่วนขยาย
สิ่งที่คุณต้องมี
- Firebase CLI (ติดตั้งและเข้าสู่ระบบ)
- บัญชี Google เช่น บัญชี Gmail
- Node.js และ
npm
- สภาพแวดล้อมในการพัฒนาที่คุณชื่นชอบ
2. ตั้งค่า
รับรหัส
ทุกอย่างที่คุณต้องการสำหรับส่วนขยายนี้อยู่ในที่เก็บ GitHub หากต้องการเริ่มต้นใช้งาน ให้คัดลอกโค้ดแล้วเปิดในสภาพแวดล้อมในการพัฒนาที่คุณชื่นชอบ
- คลายไฟล์ ZIP ที่ดาวน์โหลด
- หากต้องการติดตั้งทรัพยากร Dependency ที่จำเป็น ให้เปิดเทอร์มินัลในไดเรกทอรี
functions
แล้วเรียกใช้คำสั่งnpm install
ตั้งค่า Firebase
Codelab นี้ขอแนะนำให้ใช้โปรแกรมจำลอง Firebase หากต้องการลองพัฒนาส่วนขยายด้วยโปรเจ็กต์ Firebase จริง โปรดดูสร้างโปรเจ็กต์ Firebase Codelab นี้ใช้ Cloud Functions ดังนั้นหากคุณใช้โปรเจ็กต์ Firebase จริงแทนโปรแกรมจำลอง คุณจะต้องอัปเกรดเป็นแพ็กเกจราคา Blaze
หากต้องการข้ามไปข้างหน้า
คุณสามารถดาวน์โหลดเวอร์ชันที่สมบูรณ์ของโค้ดแล็บได้ หากติดขัดระหว่างทางหรือต้องการดูว่าส่วนขยายที่เสร็จสมบูรณ์แล้วมีลักษณะอย่างไร ให้ดูcodelab-end
สาขาของที่เก็บ GitHub หรือดาวน์โหลดไฟล์ ZIP ที่เสร็จสมบูรณ์แล้ว
3. ตรวจสอบโค้ด
- เปิดไฟล์
index.ts
จากไฟล์ ZIP โปรดทราบว่ามีประกาศ Cloud Functions 2 รายการอยู่ภายใน
ฟังก์ชันเหล่านี้ทำอะไร
ฟังก์ชันการสาธิตเหล่านี้ใช้สำหรับการแฮชทางภูมิศาสตร์ โดยจะใช้คู่พิกัดและเปลี่ยนเป็นรูปแบบที่เพิ่มประสิทธิภาพสำหรับการค้นหาทางภูมิศาสตร์ใน 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
และหากมีทั้ง 2 ฟิลด์ ฟังก์ชันจะคำนวณ Geohash และเขียนเอาต์พุตไปยังตำแหน่งเอาต์พุตของเอกสารที่ระบุ เอกสารอินพุตกำหนดโดยค่าคงที่ users/{uid}
ซึ่งหมายความว่าฟังก์ชันจะอ่านทุกเอกสารที่เขียนไปยังคอลเล็กชัน users/
แล้วประมวลผล Geohash สำหรับเอกสารเหล่านั้น จากนั้นจะแสดงผลแฮชไปยังช่องแฮชในเอกสารเดียวกัน
ฟังก์ชันที่เรียกใช้ได้
ฟังก์ชันถัดไปในไฟล์ 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
และแสดงผล Geohash แม้ว่าฟังก์ชันนี้จะไม่ได้รับการเรียกใช้โดยตรงในโค้ดแล็บนี้ แต่เราได้รวมฟังก์ชันนี้ไว้ที่นี่เป็นตัวอย่างของสิ่งที่ต้องกำหนดค่าในส่วนขยาย 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)
ชื่อของส่วนขยายจะใช้เป็นฐานของรหัสอินสแตนซ์ของส่วนขยาย (ผู้ใช้สามารถติดตั้งส่วนขยายหลายอินสแตนซ์ โดยแต่ละอินสแตนซ์จะมีรหัสของตัวเอง) จากนั้น Firebase จะสร้างชื่อบัญชีบริการของส่วนขยายและทรัพยากรเฉพาะส่วนขยายโดยใช้รหัสอินสแตนซ์นั้น หมายเลขเวอร์ชันจะระบุเวอร์ชันของส่วนขยาย โดยต้องเป็นไปตามการกำหนดเวอร์ชันเชิงความหมาย และคุณต้องอัปเดตทุกครั้งที่เปลี่ยนแปลงฟังก์ชันการทำงานของส่วนขยาย ระบบจะใช้เวอร์ชันข้อกำหนดของส่วนขยายเพื่อกำหนดข้อกำหนดของส่วนขยาย 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 เป็นทรัพยากรส่วนขยาย
ทรัพยากรส่วนขยายคือรายการที่ Firebase สร้างในโปรเจ็กต์ระหว่างการติดตั้งส่วนขยาย จากนั้นส่วนขยายจะเป็นเจ้าของทรัพยากรเหล่านั้นและมีบัญชีบริการเฉพาะที่ดำเนินการกับทรัพยากรเหล่านั้น ในโปรเจ็กต์นี้ ทรัพยากรเหล่านั้นคือ Cloud Functions ซึ่งต้องกำหนดไว้ในไฟล์ extension.yaml
เนื่องจากส่วนขยายจะไม่สร้างทรัพยากรจากโค้ดในโฟลเดอร์ฟังก์ชันโดยอัตโนมัติ หากไม่ได้ประกาศ 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
ที่เชื่อมโยงกับฟังก์ชันนี้ หากต้องการจำลองสิ่งที่ส่วนขยายรองรับในปัจจุบัน คุณต้องใช้ eventType
ของ providers/cloud.firestore/eventTypes/document.write
ซึ่งอยู่ในเอกสารประกอบเขียน 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 โดยใช้
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.
- เรียกใช้
firebase ext:install
จากไดเรกทอรีเดียวกัน แทนที่/path/to/extension
ด้วยเส้นทางสัมบูรณ์ไปยังไดเรกทอรีที่มีไฟล์extension.yaml
firebase ext:install /path/to/extension
This command does two things:
- โดยจะแจ้งให้คุณระบุการกำหนดค่าสำหรับอินสแตนซ์ส่วนขยาย และสร้างไฟล์
*.env
ที่มีข้อมูลการกำหนดค่าสำหรับอินสแตนซ์ - ซึ่งจะเพิ่มอินสแตนซ์ของส่วนขยายไปยังส่วน
extensions
ของfirebase.json
ซึ่งทำหน้าที่เป็นแผนที่ของรหัสอินสแตนซ์ไปยังเวอร์ชันส่วนขยาย - เนื่องจากคุณกำลังติดตั้งใช้งานโปรเจ็กต์ในเครื่อง คุณจึงระบุได้ว่าต้องการใช้ไฟล์ในเครื่องแทน Google Cloud Secret Manager
- เริ่มโปรแกรมจำลอง Firebase ด้วยการกำหนดค่าใหม่
firebase emulators:start
- หลังจากเรียกใช้
emulators:start
แล้ว ให้ไปที่แท็บ Firestore ใน WebView ของโปรแกรมจำลอง - เพิ่มเอกสารลงใน
users
คอลเล็กชันที่มีฟิลด์xv
หมายเลขและฟิลด์yv
หมายเลข
- หากติดตั้งส่วนขยายสำเร็จ ส่วนขยายจะสร้างฟิลด์ใหม่ชื่อ
hash
ในเอกสาร
ล้างข้อมูลเพื่อหลีกเลี่ยงความขัดแย้ง
- เมื่อทดสอบเสร็จแล้ว ให้ถอนการติดตั้งส่วนขยาย เนื่องจากคุณจะอัปเดตโค้ดส่วนขยายและไม่ต้องการให้เกิดข้อขัดแย้งกับส่วนขยายปัจจุบันในภายหลัง
ส่วนขยายอนุญาตให้ติดตั้งส่วนขยายเดียวกันหลายเวอร์ชันพร้อมกันได้ ดังนั้นการถอนการติดตั้งจะช่วยให้มั่นใจได้ว่าจะไม่มีความขัดแย้งกับส่วนขยายที่ติดตั้งไว้ก่อนหน้านี้
firebase ext:uninstall geohash-ext
โซลูชันปัจจุบันใช้งานได้ แต่ดังที่กล่าวไว้ในช่วงต้นของโปรเจ็กต์ มีคีย์ 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 ตั้งชื่อพารามิเตอร์ในลักษณะที่มองเห็นได้สำหรับคุณ ซึ่งเป็นผู้ผลิตส่วนขยาย ใช้ค่านี้ในภายหลังเมื่อระบุค่าพารามิเตอร์
- label คือตัวระบุที่มนุษย์อ่านได้ซึ่งมีไว้สำหรับนักพัฒนาแอปเพื่อให้ทราบว่าพารามิเตอร์ทำอะไร
- description ให้คำอธิบายโดยละเอียดเกี่ยวกับมูลค่า เนื่องจากรองรับมาร์กดาวน์ จึงสามารถลิงก์ไปยังเอกสารประกอบเพิ่มเติม หรือไฮไลต์คำที่อาจมีความสำคัญต่อนักพัฒนาแอปได้
- type จะกำหนดกลไกการป้อนข้อมูลสำหรับวิธีที่ผู้ใช้จะตั้งค่าพารามิเตอร์ โดยมีหลายประเภท เช่น
string
,select
,multiSelect
,selectResource
และsecret
ดูข้อมูลเพิ่มเติมเกี่ยวกับตัวเลือกแต่ละรายการได้ที่เอกสารประกอบ - validationRegex จะจำกัดรายการของนักพัฒนาแอปให้เป็นค่า Regex ที่แน่นอน (ในตัวอย่างนี้อิงตามหลักเกณฑ์ชื่อฟิลด์อย่างง่ายที่นี่) และหากไม่สำเร็จ...
- validationErrorMessage จะแจ้งให้นักพัฒนาแอปทราบค่าที่ล้มเหลว
- default คือค่าที่จะเป็นหากนักพัฒนาแอปไม่ได้ป้อนข้อความใดๆ
- required หมายความว่านักพัฒนาแอปไม่จำเป็นต้องป้อนข้อความใดๆ
- เปลี่ยนแปลงไม่ได้ช่วยให้นักพัฒนาแอปอัปเดตส่วนขยายนี้และเปลี่ยนค่านี้ได้ ในกรณีนี้ นักพัฒนาแอปควรเปลี่ยนชื่อฟิลด์ได้เมื่อข้อกำหนดเปลี่ยนแปลง
- ตัวอย่างจะช่วยให้คุณเห็นภาพว่าอินพุตที่ถูกต้องมีลักษณะอย่างไร
ข้อมูลเยอะมากเลยนะ
- คุณมีพารามิเตอร์อีก 3 รายการที่จะเพิ่มลงในไฟล์
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 ที่ผู้ใช้ระบุ นี่คือสตริงที่ละเอียดอ่อนซึ่งไม่ควรจัดเก็บเป็นข้อความธรรมดาในฟังก์ชัน ให้จัดเก็บค่านี้ไว้ใน Secret Manager ของ Cloud แทน ซึ่งเป็นตำแหน่งพิเศษในระบบคลาวด์ที่จัดเก็บข้อมูลลับที่เข้ารหัส และป้องกันไม่ให้ข้อมูลลับรั่วไหลโดยไม่ตั้งใจ ซึ่งกำหนดให้นักพัฒนาแอปต้องชำระเงินสำหรับการใช้บริการนี้ แต่จะช่วยเพิ่มความปลอดภัยอีกขั้นให้กับคีย์ 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!;
โดยปกติแล้ว คุณจะต้องตรวจสอบค่าตัวแปรสภาพแวดล้อมว่ามีค่าเป็น Null หรือไม่ แต่ในกรณีนี้ คุณเชื่อมั่นว่าค่าพารามิเตอร์จะได้รับการคัดลอกอย่างถูกต้อง ตอนนี้โค้ดได้รับการกำหนดค่าให้ทำงานกับพารามิเตอร์ส่วนขยายแล้ว
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 โดยใช้
firebase init
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, Realtime Database และ Pub/Sub
- สร้างไดเรกทอรีใหม่ในระบบโฮสต์และเชื่อมต่อไดเรกทอรีนั้นกับโปรเจ็กต์ Firebase โดยใช้
firebase init
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
แล้ว ให้ไปที่แท็บ Firestore ของคอนโซล Firebase หรือ WebView ของโปรแกรมจำลองตามความเหมาะสม - เพิ่มเอกสารลงในคอลเล็กชันที่ระบุโดยฟิลด์
x
และฟิลด์y
ในกรณีนี้ เอกสารที่อัปเดตจะอยู่ที่u/{uid}
โดยมีฟิลด์x
เป็นxv
และฟิลด์y
เป็นyv
- หากติดตั้งส่วนขยายสำเร็จ ส่วนขยายจะสร้างช่องใหม่ชื่อ
hash
ในเอกสารหลังจากที่คุณบันทึกช่องทั้ง 2 ช่อง
8. ยินดีด้วย
คุณแปลง Cloud Functions แรกเป็น Firebase Extension เรียบร้อยแล้ว
คุณได้เพิ่มไฟล์ extension.yaml
และกำหนดค่าเพื่อให้ผู้พัฒนาเลือกวิธีที่ต้องการให้ติดตั้งใช้งานส่วนขยายของคุณได้ จากนั้นคุณได้สร้างเอกสารประกอบสำหรับผู้ใช้ซึ่งให้คำแนะนำเกี่ยวกับสิ่งที่นักพัฒนาส่วนขยายควรทำก่อนตั้งค่าส่วนขยาย และขั้นตอนที่อาจต้องดำเนินการหลังจากติดตั้งส่วนขยายเรียบร้อยแล้ว
ตอนนี้คุณทราบขั้นตอนสำคัญที่จำเป็นในการแปลงฟังก์ชันของ Firebase ให้เป็น Firebase Extension ที่แจกจ่ายได้แล้ว