1. ก่อนที่คุณจะเริ่ม
ส่วนขยาย Firebase ทำงานเฉพาะหรือชุดงานเพื่อตอบสนองต่อคำขอ HTTP หรือทริกเกอร์เหตุการณ์จาก Firebase และผลิตภัณฑ์อื่นๆ ของ Google เช่น Firebase Cloud Messaging, Cloud Firestore หรือ Pub/Sub
สิ่งที่คุณจะสร้าง
ใน Codelab นี้ คุณจะสร้างส่วนขยาย Firebase สำหรับ geohashing เมื่อปรับใช้แล้ว ส่วนขยายของคุณจะแปลงพิกัด X และ Y เป็น Geohash เพื่อตอบสนองต่อเหตุการณ์ Firestore หรือผ่านการเรียกใช้ฟังก์ชันที่เรียกใช้ได้ ซึ่งสามารถใช้เป็นอีกทางเลือกหนึ่งใน การนำไลบรารี geofire ไปใช้ ในทุกแพลตฟอร์มเป้าหมายของคุณสำหรับการจัดเก็บข้อมูล ซึ่งจะช่วยประหยัดเวลา
สิ่งที่คุณจะได้เรียนรู้
- วิธีนำโค้ด Cloud Functions ที่มีอยู่มาแปลงเป็น Firebase Extension ที่แจกจ่ายได้
- วิธีการตั้งค่าไฟล์
extension.yaml
- วิธีจัดเก็บสตริงที่ละเอียดอ่อน (คีย์ API) ในส่วนขยาย
- วิธีอนุญาตให้นักพัฒนาส่วนขยายกำหนดค่าให้เหมาะกับความต้องการของพวกเขา
- วิธีทดสอบและปรับใช้ส่วนขยาย
สิ่งที่คุณต้องการ
- Firebase CLI (ติดตั้งและเข้าสู่ระบบ)
- บัญชี Google เช่น บัญชี Gmail
- Node.js และ
npm
- สภาพแวดล้อมการพัฒนาที่คุณชื่นชอบ
2. ตั้งค่า
รับรหัส
ทุกสิ่งที่คุณต้องการสำหรับส่วนขยายนี้อยู่ใน repo GitHub ในการเริ่มต้น ให้คว้าโค้ดและเปิดมันในสภาพแวดล้อมการพัฒนาที่คุณชื่นชอบ
- แตกไฟล์ zip ที่ดาวน์โหลดมา
- หากต้องการติดตั้งการขึ้นต่อกันที่จำเป็น ให้เปิดเทอร์มินัลใน
functions
ฟังก์ชั่นแล้วรันคำสั่งnpm install
ตั้งค่า Firebase
Codelab นี้สนับสนุนการใช้โปรแกรมจำลอง Firebase เป็นอย่างยิ่ง หากคุณต้องการทดลองใช้การพัฒนาส่วนขยายด้วยโปรเจ็กต์ Firebase จริง โปรดดู สร้างโปรเจ็กต์ Firebase Codelab นี้ใช้ฟังก์ชันคลาวด์ ดังนั้นหากคุณใช้โปรเจ็กต์ Firebase จริงแทนโปรแกรมจำลอง คุณจะต้อง อัปเกรดเป็นแผนการกำหนดราคา Blaze
ต้องการที่จะข้ามไปข้างหน้า?
คุณสามารถดาวน์โหลด Codelab เวอร์ชันสมบูรณ์ได้ หากคุณติดขัดระหว่างการทำงานหรือถ้าคุณต้องการดูว่าส่วนขยายที่เสร็จสมบูรณ์แล้วเป็นอย่างไร ให้ตรวจสอบสาขา codelab-end
ของ พื้นที่เก็บข้อมูล GitHub หรือดาวน์โหลดไฟล์ zip ที่เสร็จสมบูรณ์
3. ตรวจสอบโค้ด
- เปิดไฟล์
index.ts
จากไฟล์ zip โปรดสังเกตว่ามีการประกาศ Cloud Functions สองรายการอยู่ภายใน
ฟังก์ชั่นเหล่านี้มีไว้ทำอะไร?
ฟังก์ชันสาธิตเหล่านี้ใช้สำหรับ geohashing พวกเขาใช้คู่พิกัดและแปลงเป็นรูปแบบที่ปรับให้เหมาะสมสำหรับการสืบค้นทางภูมิศาสตร์ใน Firestore ฟังก์ชันนี้จะจำลองการใช้การเรียก API เพื่อให้คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับการจัดการประเภทข้อมูลที่ละเอียดอ่อนในส่วนขยาย สำหรับข้อมูลเพิ่มเติม โปรดดูเอกสารประกอบเกี่ยวกับ การเรียกใช้คำสั่ง Geo กับข้อมูลใน Firestore
ค่าคงที่ของฟังก์ชัน
ค่าคงที่จะถูกประกาศตั้งแต่เนิ่นๆ ที่ด้านบนของไฟล์ index.ts
ค่าคงที่เหล่านี้บางส่วนมีการอ้างอิงในทริกเกอร์ที่กำหนดของส่วนขยาย
ดัชนี.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
มีลักษณะดังนี้:
ดัชนี.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
และหากมีทั้งสองฟิลด์ดังกล่าว ฟังก์ชันจะคำนวณ geohash และเขียนเอาต์พุตไปยังตำแหน่งเอาต์พุตเอกสารที่ระบุ เอกสารอินพุตถูกกำหนดโดยค่าคงที่ users/{uid}
ซึ่งหมายความว่าฟังก์ชันจะอ่านเอกสารทุกฉบับที่เขียนถึง users/
คอลเลกชัน จากนั้นจึงประมวลผล geohash สำหรับเอกสารเหล่านั้น จากนั้นจะส่งออกแฮชไปยังช่องแฮชในเอกสารเดียวกัน
ฟังก์ชั่นที่สามารถเรียกได้
ฟังก์ชั่นถัดไปในไฟล์ 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
และส่งคืน geohash แม้ว่าฟังก์ชันนี้จะไม่ถูกเรียกใช้โดยตรงใน Codelab นี้ แต่ฟังก์ชันนี้ก็รวมไว้ที่นี่เป็นตัวอย่างของสิ่งที่ต้องกำหนดค่าในส่วนขยาย 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 จะสร้างชื่อบัญชีบริการของส่วนขยายและทรัพยากรเฉพาะส่วนขยายโดยใช้รหัสอินสแตนซ์นั้น หมายเลขเวอร์ชันระบุเวอร์ชันของส่วนขยายของคุณ ต้องเป็นไปตาม การกำหนดเวอร์ชันเชิงความหมาย และคุณต้องอัปเดตทุกครั้งที่คุณทำการเปลี่ยนแปลงฟังก์ชันการทำงานของส่วนขยาย เวอร์ชันข้อกำหนดส่วนขยายใช้เพื่อกำหนดข้อกำหนดส่วนขยาย 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
เนื่องจากส่วนขยายจะไม่สร้างทรัพยากรจากโค้ดในโฟลเดอร์ 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
ที่เชื่อมโยงกับฟังก์ชันนี้ หากต้องการจำลองสิ่งที่ส่วนขยายรองรับในปัจจุบัน คุณใช้ eventType
ของ providers/cloud.firestore/eventTypes/document.write
ซึ่งพบได้ใน 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 ของ emulators - เพิ่มเอกสารลงในคอลเลกชัน
users
ด้วยฟิลด์หมายเลขxv
และฟิลด์หมายเลขyv
- หากคุณติดตั้งส่วนขยายได้สำเร็จ ส่วนขยายจะสร้างฟิลด์ใหม่ที่เรียกว่า
hash
ในเอกสาร
ทำความสะอาดเพื่อหลีกเลี่ยงความขัดแย้ง
- เมื่อคุณทดสอบเสร็จแล้ว ให้ถอนการติดตั้งส่วนขยาย คุณจะต้องอัปเดตโค้ดส่วนขยายและไม่ต้องการขัดแย้งกับส่วนขยายปัจจุบันในภายหลัง
ส่วนขยายอนุญาตให้ติดตั้งส่วนขยายเดียวกันได้หลายเวอร์ชันพร้อมกัน ดังนั้นการถอนการติดตั้งจะทำให้คุณมั่นใจได้ว่าไม่มีข้อขัดแย้งกับส่วนขยายที่ติดตั้งไว้ก่อนหน้านี้
firebase ext:uninstall geohash-ext
โซลูชันปัจจุบันใช้งานได้ แต่ตามที่กล่าวไว้ในตอนต้นของโปรเจ็กต์ มีคีย์ API แบบฮาร์ดโค้ดเพื่อจำลองการสื่อสารกับบริการ คุณจะใช้คีย์ API ของผู้ใช้ปลายทางแทนคีย์ที่ให้มาแต่แรกได้อย่างไร การอ่านเพื่อหา.
6. ทำให้ผู้ใช้สามารถกำหนดค่าส่วนขยายได้
ณ จุดนี้ใน Codelab คุณมีส่วนขยายที่ได้รับการกำหนดค่าเพื่อใช้กับการตั้งค่าฟังก์ชันที่คุณเขียนไว้แล้ว แต่จะเกิดอะไรขึ้นหากผู้ใช้ของคุณต้องการใช้ละติจูดและลองจิจูดแทน y และ x สำหรับฟิลด์ที่ระบุ ตำแหน่งบนเครื่องบินคาร์ทีเซียน? นอกจากนี้ คุณจะให้ผู้ใช้ระบุคีย์ API ของตนเองแทนที่จะปล่อยให้พวกเขาใช้คีย์ API ที่ให้มาได้อย่างไร คุณสามารถใช้งานโควต้าของ API นั้นเกินโควต้าได้อย่างรวดเร็ว ในกรณีนี้ คุณตั้งค่าและใช้พารามิเตอร์
กำหนดพารามิเตอร์พื้นฐานใน ไฟล์ extension.yaml
เริ่มต้นด้วยการแปลงรายการที่นักพัฒนาอาจมีการกำหนดค่าแบบกำหนดเอง ตัวแรกจะเป็นพารามิเตอร์ XFIELD
และ YFIELD
- ในไฟล์
extension.yaml
ให้เพิ่มโค้ดต่อไปนี้ ซึ่งใช้พารามิเตอร์ฟิลด์XFIELD
และYFIELD
พารามิเตอร์เหล่านี้อยู่ภายในคุณสมบัติ YAML ของparams
ที่กำหนดไว้ก่อนหน้านี้:
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 แจ้งเตือนผู้พัฒนาถึงค่าความล้มเหลว
- ค่า เริ่มต้น คือค่าที่จะเป็นหากนักพัฒนาไม่ได้ป้อนข้อความใดๆ
- จำเป็น หมายความว่านักพัฒนาไม่จำเป็นต้องป้อนข้อความใด ๆ
- ไม่เปลี่ยนรูป ช่วยให้นักพัฒนาสามารถอัปเดตส่วนขยายนี้และเปลี่ยนแปลงค่านี้ได้ ในกรณีนี้ นักพัฒนาควรสามารถเปลี่ยนชื่อฟิลด์ได้ตามความต้องการที่เปลี่ยนไป
- ตัวอย่าง ให้แนวคิดว่าอินพุตที่ถูกต้องอาจมีหน้าตาเป็นอย่างไร
นั่นเป็นเรื่องที่ต้องเข้าใจมาก!
- คุณมีพารามิเตอร์อีกสามตัวที่จะเพิ่มลงในไฟล์
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 ของนักพัฒนา
ดัชนี.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
ซึ่งใช้เพื่ออธิบายฟังก์ชันการทำงาน ข้อกำหนดเบื้องต้นสำหรับการติดตั้ง และผลกระทบต่อการเรียกเก็บเงินที่อาจเกิดขึ้น
ติดตั้งล่วงหน้า.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, ฐานข้อมูลเรียลไทม์ และ 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 ของ emulators ตามความเหมาะสม - เพิ่มเอกสารลงในคอลเลกชันที่ระบุโดยฟิลด์
x
และฟิลด์y
ในกรณีนี้ เอกสารที่อัปเดตจะอยู่ที่u/{uid}
โดยมีฟิลด์x
เป็นxv
และฟิลด์y
เป็นyv
- หากคุณติดตั้งส่วนขยายได้สำเร็จ ส่วนขยายจะสร้างฟิลด์ใหม่ที่เรียกว่า
hash
ในเอกสารหลังจากที่คุณบันทึกทั้งสองฟิลด์
8. ขอแสดงความยินดี!
คุณได้แปลงฟังก์ชันคลาวด์แรกของคุณเป็นส่วนขยาย Firebase สำเร็จแล้ว!
คุณได้เพิ่มไฟล์ extension.yaml
และกำหนดค่าเพื่อให้นักพัฒนาสามารถเลือกได้ว่าต้องการให้ส่วนขยายของคุณใช้งานได้อย่างไร จากนั้น คุณได้สร้างเอกสารสำหรับผู้ใช้ที่ให้คำแนะนำว่านักพัฒนาส่วนขยายควรทำอะไรก่อนตั้งค่าส่วนขยาย และขั้นตอนใดที่พวกเขาอาจต้องทำหลังจากติดตั้งส่วนขยายสำเร็จแล้ว
ตอนนี้คุณรู้ขั้นตอนสำคัญที่จำเป็นในการแปลงฟังก์ชัน Firebase ให้เป็นส่วนขยาย Firebase ที่สามารถแจกจ่ายได้