1. ก่อนเริ่มต้น
ส่วนขยาย Firebase จะดำเนินงานหนึ่งๆ หรือชุดงานเพื่อตอบสนองคำขอ HTTP หรือทริกเกอร์เหตุการณ์จาก Firebase และผลิตภัณฑ์อื่นๆ ของ Google เช่น Firebase Cloud Messaging, Cloud Firestore หรือ Pub/Sub
สิ่งที่คุณจะสร้าง
ใน Codelab นี้ คุณจะได้สร้างส่วนขยาย Firebase สำหรับการระบุพิกัดทางภูมิศาสตร์ เมื่อทำให้ใช้งานได้แล้ว ส่วนขยายจะแปลงพิกัด X และ Y เป็นพิกัดทางภูมิศาสตร์เพื่อตอบสนองต่อเหตุการณ์ของ Firestore หรือผ่านการเรียกใช้ฟังก์ชันที่เรียกใช้ได้ ข้อมูลนี้สามารถใช้เป็นทางเลือกในการติดตั้งคลังไฟทางภูมิศาสตร์ในทุกแพลตฟอร์มเป้าหมายเพื่อจัดเก็บข้อมูล ซึ่งช่วยประหยัดเวลาได้
สิ่งที่คุณจะได้เรียนรู้
- วิธีการนำโค้ด Cloud Functions ที่มีอยู่มาเปลี่ยนเป็นส่วนขยาย Firebase ที่กระจายได้
- วิธีตั้งค่าไฟล์
extension.yaml
- วิธีจัดเก็บสตริงที่มีความละเอียดอ่อน (คีย์ API) ในส่วนขยาย
- วิธีอนุญาตให้นักพัฒนาส่วนขยายกำหนดค่าให้เหมาะกับความต้องการของตน
- วิธีทดสอบและใช้งานส่วนขยาย
สิ่งที่คุณต้องมี
- Firebase CLI (ติดตั้งและเข้าสู่ระบบ)
- บัญชี Google เช่น บัญชี Gmail
- Node.js และ
npm
- สภาพแวดล้อมในการพัฒนาซอฟต์แวร์ที่คุณชื่นชอบ
2. ตั้งค่าเลย
รับโค้ด
ทุกสิ่งที่คุณต้องการสำหรับส่วนขยายนี้อยู่ในที่เก็บ GitHub ในการเริ่มต้นใช้งาน ให้รับโค้ดและเปิดในสภาพแวดล้อมในการพัฒนาซอฟต์แวร์ที่คุณชื่นชอบ
- แตกไฟล์ ZIP ที่ดาวน์โหลด
- หากต้องการติดตั้งทรัพยากร Dependency ที่จำเป็น ให้เปิดเทอร์มินัลในไดเรกทอรี
functions
และเรียกใช้คำสั่งnpm install
ตั้งค่า Firebase
Codelab นี้สนับสนุนให้ใช้โปรแกรมจำลอง Firebase เป็นอย่างมาก หากต้องการลองใช้การพัฒนาส่วนขยายด้วยโปรเจ็กต์ Firebase จริง โปรดดูสร้างโปรเจ็กต์ Firebase Codelab นี้ใช้ฟังก์ชันระบบคลาวด์ ดังนั้นหากคุณใช้โปรเจ็กต์ Firebase จริงแทนโปรแกรมจำลอง คุณต้องอัปเกรดเป็นแพ็กเกจราคา Blaze
หากต้องการข้ามไปข้างหน้า
คุณดาวน์โหลด Codelab เวอร์ชันที่สมบูรณ์ได้ หากยังพบปัญหาอยู่หรือต้องการดูลักษณะของส่วนขยายที่เสร็จสมบูรณ์แล้ว โปรดดูที่ codelab-end
Branch ของที่เก็บ 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/
แล้วประมวลผลธรณีแปรสัณฐานสำหรับเอกสารเหล่านั้น จากนั้นระบบจะส่งแฮชไปยังช่องแฮชในเอกสารเดียวกัน
ฟังก์ชันที่เรียกใช้ได้
ฟังก์ชันถัดไปในไฟล์ index.ts
มีลักษณะดังนี้
ดัชนี.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
และแสดงผลพิกัดทางภูมิศาสตร์ แม้ว่าจะไม่มีการเรียกฟังก์ชันนี้ใน Codelab โดยตรง แต่ก็รวมมาไว้ที่นี่เพื่อเป็นตัวอย่างของการกำหนดค่าในส่วนขยาย Firebase
4. ตั้งค่าไฟล์ extensions.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
ซึ่งอยู่ในเอกสารประกอบเขียนฟังก์ชันระบบคลาวด์สำหรับส่วนขยาย คุณกําหนด 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
วิธีนี้เป็นแมปรหัสอินสแตนซ์ไปยังเวอร์ชันส่วนขยาย - เนื่องจากคุณทำให้โปรเจ็กต์ใช้งานได้ภายในเครื่อง คุณจึงระบุได้ว่าต้องการใช้ไฟล์ในเครื่องแทนการใช้ Secret Manager ของ Google Cloud
- เริ่มโปรแกรมจำลอง Firebase ด้วยการกำหนดค่าใหม่
firebase emulators:start
- หลังจากเรียกใช้
emulators:start
แล้ว ให้ไปที่แท็บ Firestore ใน WebView ของโปรแกรมจำลอง - เพิ่มเอกสารลงในคอลเล็กชัน
users
ด้วยช่องตัวเลขxv
และช่องตัวเลขyv
- หากคุณติดตั้งส่วนขยายสำเร็จ ส่วนขยายจะสร้างช่องใหม่ชื่อ
hash
ในเอกสาร
ล้างข้อมูลเพื่อหลีกเลี่ยงความขัดแย้ง
- เมื่อทดสอบเสร็จแล้ว ให้ถอนการติดตั้งส่วนขยาย คุณจะอัปเดตโค้ดส่วนขยายและไม่ต้องการให้ขัดแย้งกับส่วนขยายปัจจุบันในภายหลัง
ส่วนขยายจะอนุญาตให้มีการติดตั้งส่วนขยายเดียวกันได้หลายเวอร์ชันพร้อมกัน ดังนั้นเมื่อถอนการติดตั้ง คุณจะมั่นใจได้ว่าจะไม่มีความขัดแย้งกับส่วนขยายที่ติดตั้งไว้ก่อนหน้านี้
firebase ext:uninstall geohash-ext
โซลูชันในปัจจุบันใช้งานได้ แต่อย่างที่กล่าวไปในตอนต้นของโปรเจ็กต์ มีคีย์ API แบบฮาร์ดโค้ดเพื่อจำลองการสื่อสารกับบริการ คุณจะใช้คีย์ API ของผู้ใช้ปลายทางแทนคีย์ API ที่ให้มาตั้งแต่แรกได้อย่างไร ถ้าอยากรู้ก็อ่านต่อเลย
6. ทำให้ผู้ใช้กำหนดค่าส่วนขยายได้
ณ จุดนี้ของ Codelab คุณมีส่วนขยายที่กำหนดค่าเพื่อใช้กับการตั้งค่าตามความเห็นของฟังก์ชันที่เขียนไว้แล้ว แต่หากผู้ใช้ต้องการใช้ละติจูดและลองจิจูดแทน 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
โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับแต่ละตัวเลือกเหล่านี้ในเอกสารประกอบ - verifyationRegex จำกัดรายการของนักพัฒนาซอฟต์แวร์ให้เป็นค่านิพจน์ทั่วไปที่กำหนด (ในตัวอย่างนี้เป็นไปตามหลักเกณฑ์ชื่อช่องง่ายๆ ที่ระบุไว้ที่นี่) และหากไม่ได้ผล...
- checkationErrorMessage แจ้งเตือนนักพัฒนาซอฟต์แวร์เกี่ยวกับค่าความล้มเหลว
- default คือค่าที่จะเป็นถ้านักพัฒนาแอปไม่ได้ป้อนข้อความใดๆ
- ต้องระบุหมายความว่านักพัฒนาแอปไม่จำเป็นต้องป้อนข้อความใดๆ
- เปลี่ยนแปลงไม่ได้ช่วยให้นักพัฒนาซอฟต์แวร์อัปเดตส่วนขยายนี้และเปลี่ยนค่านี้ได้ ในกรณีนี้ นักพัฒนาแอปควรเปลี่ยนชื่อช่องได้เมื่อมีการเปลี่ยนแปลงข้อกำหนด
- example ช่วยให้เห็นภาพว่าข้อมูลที่ถูกต้องควรมีลักษณะอย่างไร
เราเข้าใจเป็นอย่างมาก
- คุณมีพารามิเตอร์อีก 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 ที่ผู้ใช้ระบุ นี่เป็นสตริงที่มีความละเอียดอ่อนซึ่งไม่ควรเก็บไว้ในข้อความธรรมดาในฟังก์ชัน แต่ให้เก็บค่านี้ในเครื่องมือจัดการข้อมูลลับของ 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
- เนื่องจากคุณกำลังทำให้โปรเจ็กต์ใช้งานได้ภายในเครื่อง ให้ระบุว่าคุณต้องการใช้ไฟล์ในเครื่องแทนการใช้ Secret Manager ของ Google Cloud
- เริ่มชุดโปรแกรมจำลองในเครื่องด้วยคำสั่งต่อไปนี้
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 โดยตรง และต้องการใช้ Secret Manager ของ Google Cloud คุณจึงต้องเปิดใช้งาน 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 Function แรกเป็นส่วนขยาย Firebase เรียบร้อยแล้ว
คุณเพิ่มไฟล์ extension.yaml
และกำหนดค่าไฟล์แล้วเพื่อให้นักพัฒนาซอฟต์แวร์เลือกวิธีที่ต้องการทำให้ส่วนขยายของคุณใช้งานได้ จากนั้น คุณได้สร้างเอกสารของผู้ใช้ที่ให้คำแนะนำว่านักพัฒนาซอฟต์แวร์ของส่วนขยายควรทำอย่างไรก่อนที่จะตั้งค่าส่วนขยาย รวมทั้งขั้นตอนที่นักพัฒนาต้องดำเนินการหลังจากติดตั้งส่วนขยายสำเร็จแล้ว
ตอนนี้คุณก็ได้ทราบขั้นตอนสำคัญที่จำเป็นในการแปลงฟังก์ชัน Firebase เป็นส่วนขยาย Firebase ที่กระจายได้แล้ว