เริ่มต้นสร้างส่วนขยาย

หน้านี้จะอธิบายขั้นตอนที่จำเป็นในการสร้างส่วนขยาย Firebase ง่ายๆ ซึ่งคุณสามารถติดตั้งในโปรเจ็กต์หรือแชร์กับผู้อื่นได้ ตัวอย่างง่ายๆ ของส่วนขยาย Firebase นี้จะคอยตรวจสอบฐานข้อมูลเรียลไทม์เพื่อหาข้อความและแปลงเป็นอักษรตัวพิมพ์ใหญ่

1. ตั้งค่าสภาพแวดล้อมและเริ่มต้นโปรเจ็กต์

คุณจะต้องตั้งค่าสภาพแวดล้อมบิลด์ด้วยเครื่องมือที่จำเป็นก่อน จึงจะเริ่มสร้างส่วนขยายได้

  1. ติดตั้ง Node.js 16 ขึ้นไป วิธีหนึ่งในการติดตั้งโหนดคือการใช้ nvm (หรือ nvm-windows)

  2. ติดตั้งหรืออัปเดต Firebase CLI เป็นเวอร์ชันล่าสุด หากต้องการติดตั้งหรืออัปเดตโดยใช้ npm ให้เรียกใช้คำสั่งนี้

    npm install -g firebase-tools

ตอนนี้ ให้ใช้ Firebase CLI เพื่อเริ่มต้นโปรเจ็กต์ส่วนขยายใหม่

  1. สร้างไดเรกทอรีสำหรับส่วนขยายและcdลงในไดเรกทอรีนั้น

    mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
  2. เรียกใช้คำสั่ง ext:dev:init ของ Firebase CLI โดยทำดังนี้

    firebase ext:dev:init

    เมื่อได้รับข้อความแจ้ง ให้เลือก JavaScript เป็นภาษาของฟังก์ชัน (แต่โปรดทราบว่าคุณใช้ TypeScript ได้เมื่อพัฒนาส่วนขยายของคุณเอง) และเมื่อระบบขอให้ติดตั้ง Dependencies ให้ตอบว่า "ใช่" (ยอมรับค่าเริ่มต้นสำหรับตัวเลือกอื่นๆ) คำสั่งนี้จะสร้างโค้ดสแควร์โครงสําหรับส่วนขยายใหม่ ซึ่งคุณจะใช้เริ่มพัฒนาส่วนขยายได้

2. ลองใช้ส่วนขยายตัวอย่างโดยใช้โปรแกรมจำลอง

เมื่อ Firebase CLI เริ่มต้นไดเรกทอรีส่วนขยายใหม่ ก็จะสร้างฟังก์ชันตัวอย่างง่ายๆ และไดเรกทอรี integration-tests ที่มีไฟล์ที่จําเป็นต่อการใช้งานส่วนขยายโดยใช้ชุดโปรแกรมจําลอง Firebase

ลองเรียกใช้ส่วนขยายตัวอย่างในโปรแกรมจำลอง

  1. การเปลี่ยนแปลงในไดเรกทอรี integration-tests

    cd functions/integration-tests
  2. เริ่มโปรแกรมจำลองด้วยโปรเจ็กต์เดโม โดยทำดังนี้

    firebase emulators:start --project=demo-test

    โปรแกรมจำลองจะโหลดส่วนขยายลงในโปรเจ็กต์ "จำลอง" ที่กําหนดไว้ล่วงหน้า (demo-test) จนถึงตอนนี้ ส่วนขยายประกอบด้วยฟังก์ชัน greetTheWorld ที่ทริกเกอร์ HTTP รายการเดียว ซึ่งแสดงผลข้อความ "Hello World" เมื่อเข้าถึง

  3. เมื่อโปรแกรมจําลองยังทํางานอยู่ ให้ลองใช้greetTheWorld ฟังก์ชันของส่วนขยายโดยไปที่ URL ที่แสดงเมื่อคุณเริ่มใช้งาน

    เบราว์เซอร์จะแสดงข้อความ "สวัสดีโลกจากทักทายโลก"

  4. ซอร์สโค้ดของฟังก์ชันนี้จะอยู่ในfunctions ไดเรกทอรีของส่วนขยาย เปิดซอร์สโค้ดในเครื่องมือแก้ไขหรือ IDE ที่ต้องการ

    functions/index.js

    const functions = require("firebase-functions/v1");
    
    exports.greetTheWorld = functions.https.onRequest((req, res) => {
      // Here we reference a user-provided parameter
      // (its value is provided by the user during installation)
      const consumerProvidedGreeting = process.env.GREETING;
    
      // And here we reference an auto-populated parameter
      // (its value is provided by Firebase after installation)
      const instanceId = process.env.EXT_INSTANCE_ID;
    
      const greeting = `${consumerProvidedGreeting} World from ${instanceId}`;
    
      res.send(greeting);
    });
    
  5. ขณะทำงานอยู่ โปรแกรมจำลองจะโหลดการเปลี่ยนแปลงที่คุณทำกับโค้ด Functions ซ้ำโดยอัตโนมัติ ลองเปลี่ยนแปลงฟังก์ชัน greetTheWorld เพียงเล็กน้อย

    functions/index.js

    const greeting = `${consumerProvidedGreeting} everyone, from ${instanceId}`;
    

    บันทึกการเปลี่ยนแปลง โปรแกรมจำลองจะโหลดโค้ดของคุณอีกครั้ง และเมื่อคุณไปที่ URL ของฟังก์ชัน คุณจะเห็นคําทักทายที่อัปเดตแล้ว

3. เพิ่มข้อมูลพื้นฐานลงใน extension.yaml

เมื่อตั้งค่าสภาพแวดล้อมการพัฒนาซอฟต์แวร์และเรียกใช้โปรแกรมจำลองส่วนขยายแล้ว คุณก็เริ่มเขียนส่วนขยายของคุณเองได้

ขั้นตอนแรกคือแก้ไขข้อมูลเมตาของส่วนขยายที่กําหนดไว้ล่วงหน้าให้ตรงกับส่วนขยายที่คุณต้องการเขียนแทน greet-the-world ระบบจะจัดเก็บข้อมูลเมตานี้ไว้ในไฟล์ extension.yaml

  1. เปิด extension.yaml ในเครื่องมือแก้ไข แล้วแทนที่เนื้อหาทั้งหมดของไฟล์ด้วยข้อมูลต่อไปนี้

    name: rtdb-uppercase-messages
    version: 0.0.1
    specVersion: v1beta  # Firebase Extensions specification version; don't change
    
    # Friendly display name for your extension (~3-5 words)
    displayName: Convert messages to upper case
    
    # Brief description of the task your extension performs (~1 sentence)
    description: >-
      Converts messages in RTDB to upper case
    
    author:
      authorName: Your Name
      url: https://your-site.example.com
    
    license: Apache-2.0  # Required license
    
    # Public URL for the source code of your extension
    sourceUrl: https://github.com/your-name/your-repo
    

    โปรดสังเกตรูปแบบการตั้งชื่อที่ใช้ในช่อง name: ส่วนขยาย Firebase อย่างเป็นทางการจะมีชื่อเป็นคำนำหน้าซึ่งระบุผลิตภัณฑ์ Firebase หลักที่ส่วนขยายทำงานอยู่ ตามด้วยคำอธิบายของสิ่งที่ส่วนขยายทํา คุณควรใช้รูปแบบเดียวกันในส่วนขยายของคุณเอง

  2. เนื่องจากคุณเปลี่ยนชื่อส่วนขยายแล้ว คุณจึงควรอัปเดตการกําหนดค่าโปรแกรมจําลองด้วยชื่อใหม่ด้วย โดยทําดังนี้

    1. ใน functions/integration-tests/firebase.json ให้เปลี่ยน greet-the-world เป็น rtdb-uppercase-messages
    2. เปลี่ยนชื่อ functions/integration-tests/extensions/greet-the-world.env เป็น functions/integration-tests/extensions/rtdb-uppercase-messages.env

ยังมีส่วนที่เหลือของส่วนขยาย greet-the-world อยู่ในโค้ดส่วนขยายของคุณ แต่ไม่ต้องลบออกในตอนนี้ คุณจะอัปเดตข้อมูลเหล่านั้นได้ในส่วนถัดไป

4. เขียน Cloud Functions และประกาศเป็นทรัพยากรส่วนขยาย

ตอนนี้คุณก็เริ่มเขียนโค้ดได้แล้ว ในขั้นตอนนี้ คุณจะต้องเขียน Cloud Function ที่จะทำงานหลักของส่วนขยาย ซึ่งก็คือการดูฐานข้อมูลแบบเรียลไทม์เพื่อดูข้อความและแปลงเป็นตัวพิมพ์ใหญ่

  1. เปิดซอร์สโค้ดของฟังก์ชันของเวิร์กชีต (ในไดเรกทอรีfunctionsของเวิร์กชีต) ในเครื่องมือแก้ไขหรือ IDE ที่ต้องการ แทนที่เนื้อหาด้วยข้อมูลต่อไปนี้

    functions/index.js

    import { database, logger } from "firebase-functions/v1";
    
    const app = initializeApp();
    
    // Listens for new messages added to /messages/{pushId}/original and creates an
    // uppercase version of the message to /messages/{pushId}/uppercase
    // for all databases in 'us-central1'
    export const makeuppercase = database
      .ref("/messages/{pushId}/uppercase")
      .onCreate(async (snapshot, context) => {
        // Grab the current value of what was written to the Realtime Database.
        const original = snapshot.val();
    
        // Convert it to upper case.
        logger.log("Uppercasing", context.params.pushId, original);
        const uppercase = original.toUpperCase();
    
        // Setting an "uppercase" sibling in the Realtime Database.
        const upperRef = snapshot.ref.parent.child("upper");
        await upperRef.set(uppercase);
    });
    

    ฟังก์ชันเดิมที่คุณแทนที่คือฟังก์ชันที่ทริกเกอร์ HTTP ซึ่งจะทํางานเมื่อมีการเข้าถึงปลายทาง HTTP ฟังก์ชันใหม่จะทริกเกอร์โดยเหตุการณ์ฐานข้อมูลที่ทำงานแบบเรียลไทม์ โดยจะคอยตรวจหารายการใหม่ในเส้นทางหนึ่งๆ และเมื่อตรวจพบรายการดังกล่าว ก็จะเขียนค่าเวอร์ชันตัวพิมพ์ใหญ่กลับไปยังฐานข้อมูล

    โปรดทราบว่าไฟล์ใหม่นี้ใช้ไวยากรณ์โมดูล ECMAScript (import และ export) แทน CommonJS (require) หากต้องการใช้โมดูล ES ใน Node ให้ระบุ "type": "module" ใน functions/package.json ดังนี้

    {
      "name": "rtdb-uppercase-messages",
      "main": "index.js",
      "type": "module",
      
    }
    
  2. คุณต้องประกาศฟังก์ชันทั้งหมดในส่วนขยายในไฟล์ extension.yaml ตัวอย่างส่วนขยายประกาศ greetTheWorld เป็นฟังก์ชัน Cloud เพียงรายการเดียวของส่วนขยาย เมื่อคุณแทนที่ด้วย makeuppercase แล้ว คุณก็ต้องอัปเดตการประกาศด้วย

    เปิด extension.yaml และเพิ่มช่อง resources โดยทำดังนี้

    resources:
      - name: makeuppercase
        type: firebaseextensions.v1beta.function
        properties:
          eventTrigger:
            eventType: providers/google.firebase.database/eventTypes/ref.create
            # DATABASE_INSTANCE (project's default instance) is an auto-populated
            # parameter value. You can also specify an instance.
            resource: projects/_/instances/${DATABASE_INSTANCE}/refs/messages/{pushId}/original
          runtime: "nodejs18"
    
  3. เนื่องจากตอนนี้ส่วนขยายใช้ Realtime Database เป็นทริกเกอร์ คุณจึงต้องอัปเดตการกำหนดค่าโปรแกรมจำลองเพื่อเรียกใช้โปรแกรมจำลอง RTDB พร้อมกับโปรแกรมจำลอง Cloud Functions โดยทำดังนี้

    1. หากโปรแกรมจำลองยังทำงานอยู่ ให้หยุดโดยกด Ctrl-C

    2. จากไดเรกทอรี functions/integration-tests ให้เรียกใช้คำสั่งต่อไปนี้

      firebase init emulators

      เมื่อระบบถาม ให้ข้ามการตั้งค่าโปรเจ็กต์เริ่มต้น จากนั้นเลือกโปรแกรมจำลองฟังก์ชันและฐานข้อมูล ยอมรับพอร์ตเริ่มต้นและอนุญาตให้เครื่องมือการตั้งค่าดาวน์โหลดไฟล์ที่จำเป็น

    3. รีสตาร์ทโปรแกรมจำลองโดยทำดังนี้

      firebase emulators:start --project=demo-test
  4. ลองใช้ส่วนขยายที่อัปเดตแล้ว

    1. เปิด UI โปรแกรมจำลองฐานข้อมูลโดยใช้ลิงก์ที่โปรแกรมจำลองแสดงเมื่อคุณเริ่มใช้งาน

    2. แก้ไขโหนดรูทของฐานข้อมูล

      • ฟิลด์: messages
      • ประเภท: json
      • ค่า: {"11": {"original": "recipe"}}

      หากตั้งค่าทุกอย่างอย่างถูกต้องแล้ว เมื่อคุณบันทึกการเปลี่ยนแปลงฐานข้อมูล ฟังก์ชัน makeuppercase ของส่วนขยายควรทริกเกอร์และเพิ่มระเบียนย่อยลงในข้อความ 11 ที่มีเนื้อหา "upper": "RECIPE" ดูที่บันทึกและแท็บฐานข้อมูลของ UI โปรแกรมจำลองเพื่อยืนยันผลลัพธ์ที่คาดหวัง

    3. ลองเพิ่มระดับย่อยในโหนด messages ({"original":"any text"}) ทุกครั้งที่คุณเพิ่มระเบียนใหม่ ส่วนขยายควรเพิ่มช่อง uppercase ที่มีเนื้อหาของช่อง original เป็นตัวพิมพ์ใหญ่

ตอนนี้คุณมีส่วนขยายที่สมบูรณ์ แต่ก็ใช้ง่ายซึ่งทำงานบนอินสแตนซ์ RTDB ในส่วนต่อๆ ไป คุณจะปรับแต่งส่วนขยายนี้ด้วยฟีเจอร์เพิ่มเติมบางอย่าง จากนั้น คุณก็พร้อมที่จะเผยแพร่ส่วนขยายให้กับผู้อื่น และสุดท้าย เรียนรู้วิธีเผยแพร่ส่วนขยายในฮับส่วนขยาย

5. ประกาศ API และบทบาท

Firebase จะมอบสิทธิ์เข้าถึงแบบจํากัดแก่อินสแตนซ์แต่ละรายการของส่วนขยายที่ติดตั้งให้กับโปรเจ็กต์และข้อมูลโดยใช้บัญชีบริการต่ออินสแตนซ์ แต่ละบัญชีจะมีชุดสิทธิ์ขั้นต่ำที่จำเป็นในการทำงาน ด้วยเหตุนี้ คุณต้องประกาศบทบาท IAM ที่จําเป็นสําหรับส่วนขยายอย่างชัดเจน เมื่อผู้ใช้ติดตั้งส่วนขยาย Firebase จะสร้างบัญชีบริการที่มีบทบาทเหล่านี้และนำไปใช้เพื่อเรียกใช้ส่วนขยาย

คุณไม่จำเป็นต้องประกาศบทบาทเพื่อทริกเกอร์เหตุการณ์ของผลิตภัณฑ์ แต่ต้องประกาศบทบาทเพื่อโต้ตอบกับผลิตภัณฑ์ เนื่องจากฟังก์ชันที่คุณเพิ่มในขั้นตอนสุดท้ายจะเขียนลงใน Realtime Database คุณจึงต้องเพิ่มการประกาศต่อไปนี้ลงใน extension.yaml

roles:
  - role: firebasedatabase.admin
    reason: Allows the extension to write to RTDB.

ในทำนองเดียวกัน คุณประกาศ Google API ที่ส่วนขยายใช้ในช่อง apis ได้ เมื่อผู้ใช้ติดตั้งส่วนขยาย ระบบจะถามว่าผู้ใช้ต้องการเปิดใช้ API เหล่านี้โดยอัตโนมัติสําหรับโปรเจ็กต์หรือไม่ โดยปกติแล้ว ขั้นตอนนี้จําเป็นสำหรับ Google API ที่ไม่ใช่ Firebase เท่านั้น และไม่จำเป็นต้องใช้สำหรับคู่มือนี้

6. กำหนดพารามิเตอร์ที่ผู้ใช้กำหนดค่าได้

ฟังก์ชันที่คุณสร้างใน 2 ขั้นตอนที่ผ่านมาจะเฝ้าดูตำแหน่ง RTDB ที่เฉพาะเจาะจงเพื่อหาข้อความขาเข้า บางครั้ง การตรวจสอบตำแหน่งที่เฉพาะเจาะจงคือสิ่งที่คุณต้องการจริงๆ เช่น เมื่อส่วนขยายทำงานบนโครงสร้างฐานข้อมูลที่คุณใช้สำหรับส่วนขยายของคุณโดยเฉพาะ อย่างไรก็ตาม ในกรณีส่วนใหญ่ คุณจะต้องทำให้ผู้ใช้ที่ติดตั้งส่วนขยายในโปรเจ็กต์สามารถกําหนดค่าเหล่านี้ได้ วิธีนี้จะช่วยให้ผู้ใช้สามารถใช้ส่วนขยายของคุณเพื่อทำงานร่วมกับการตั้งค่าฐานข้อมูลที่มีอยู่ได้

ทำให้เส้นทางที่ส่วนขยายใช้ค้นหาข้อความใหม่ที่ผู้ใช้กำหนดค่าได้

  1. ในไฟล์ extension.yaml ให้เพิ่มส่วน params โดยทำดังนี้

    - param: MESSAGE_PATH
      label: Message path
      description: >-
        What is the path at which the original text of a message can be found?
      type: string
      default: /messages/{pushId}/original
      required: true
      immutable: false
    

    การดำเนินการนี้จะกำหนดพารามิเตอร์สตริงใหม่ที่ผู้ใช้จะได้รับแจ้งให้ตั้งค่าเมื่อติดตั้งส่วนขยาย

  2. ยังคงอยู่ในไฟล์ extension.yaml ให้กลับไปที่ประกาศ makeuppercase แล้วเปลี่ยนช่อง resource เป็นข้อมูลต่อไปนี้

    resource: projects/_/instances/${DATABASE_INSTANCE}/refs/${param:MESSAGE_PATH}
    

    โทเค็น ${param:MESSAGE_PATH} เป็นการอ้างอิงพารามิเตอร์ที่คุณเพิ่งกําหนด เมื่อส่วนขยายทํางาน โทเค็นนี้จะแทนที่ด้วยค่าใดก็ตามที่ผู้ใช้กําหนดค่าไว้สําหรับพารามิเตอร์นั้น ผลที่ได้คือฟังก์ชัน makeuppercase จะรับฟังเส้นทางที่ผู้ใช้ระบุ คุณใช้ไวยากรณ์นี้เพื่ออ้างอิงพารามิเตอร์ที่ผู้ใช้กําหนดได้ทุกที่ใน extension.yaml (และใน POSTINSTALL.md - ดูข้อมูลเพิ่มเติมในภายหลัง)

  3. คุณยังเข้าถึงพารามิเตอร์ที่กำหนดโดยผู้ใช้จากโค้ดฟังก์ชันได้อีกด้วย

    ในฟังก์ชันที่คุณเขียนในส่วนที่แล้ว คุณได้กำหนดเส้นทางแบบฮาร์ดโค้ดเพื่อเฝ้าดูการเปลี่ยนแปลง เปลี่ยนคําจํากัดความทริกเกอร์ให้อ้างอิงค่าที่ผู้ใช้กําหนดแทน

    functions/index.js

    export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate
    

    โปรดทราบว่าใน Firebase Extensions การเปลี่ยนแปลงนี้มีไว้เพื่อเอกสารประกอบเท่านั้น เมื่อมีการทำให้ Cloud Functions ใช้งานได้เป็นส่วนหนึ่งของส่วนขยาย ระบบจะใช้การกําหนดทริกเกอร์จากไฟล์ extension.yaml และจะไม่สนใจค่าที่ระบุในการกําหนดฟังก์ชัน อย่างไรก็ตาม คุณควรบันทึกแหล่งที่มาของค่านี้ในโค้ด

  4. คุณอาจรู้สึกผิดหวังที่ทําการเปลี่ยนแปลงโค้ดที่ไม่มีผลกับรันไทม์ แต่บทเรียนสําคัญที่ควรทราบคือคุณสามารถเข้าถึงพารามิเตอร์ที่กําหนดโดยผู้ใช้ในโค้ดฟังก์ชันและใช้พารามิเตอร์ดังกล่าวเป็นค่าปกติในตรรกะของฟังก์ชัน เพื่อเป็นการแสดงให้เห็นถึงความสามารถนี้ ให้เพิ่มคำสั่งบันทึกต่อไปนี้เพื่อแสดงให้เห็นว่าคุณกำลังเข้าถึงค่าที่ผู้ใช้กําหนดไว้

    functions/index.js

    export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate(
      async (snapshot, context) => {
        logger.log("Found new message at ", snapshot.ref);
    
        // Grab the current value of what was written to the Realtime Database.
        ...
    
  5. โดยปกติแล้ว ผู้ใช้จะได้รับแจ้งให้ระบุค่าสำหรับพารามิเตอร์เมื่อติดตั้งส่วนขยาย อย่างไรก็ตาม เมื่อใช้โปรแกรมจำลองสำหรับการทดสอบและการพัฒนา คุณจะไม่ต้องทำตามกระบวนการติดตั้ง ดังนั้นคุณจะต้องระบุค่าสำหรับพารามิเตอร์ที่ผู้ใช้กำหนดโดยใช้ไฟล์ env แทน

    เปิด functions/integration-tests/extensions/rtdb-uppercase-messages.env และแทนที่คำจำกัดความ GREETING ด้วยข้อความต่อไปนี้

    MESSAGE_PATH=/msgs/{pushId}/original
    

    โปรดทราบว่าเส้นทางด้านบนแตกต่างจากเส้นทางเริ่มต้นและเส้นทางที่คุณกําหนดไว้ก่อนหน้านี้ นี่เป็นเพียงแค่การพิสูจน์ให้คุณเห็นเมื่อคุณลองใช้ส่วนขยายที่อัปเดตแล้วว่าคําจํากัดความของคุณมีผล

  6. ตอนนี้ให้รีสตาร์ทโปรแกรมจำลองและไปที่ UI โปรแกรมจำลองฐานข้อมูลอีกครั้ง

    แก้ไขโหนดรากของฐานข้อมูลโดยใช้เส้นทางที่คุณกำหนดไว้ข้างต้น

    • ฟิลด์: msgs
    • ประเภท: json
    • ค่า: {"11": {"original": "recipe"}}

    เมื่อบันทึกการเปลี่ยนแปลงฐานข้อมูลแล้ว makeuppercase ฟังก์ชันของส่วนขยายควรทริกเกอร์เหมือนที่เคยทํา แต่ตอนนี้ก็ควรพิมพ์พารามิเตอร์ที่ผู้ใช้กําหนดไปยังบันทึกคอนโซลด้วย

7. ระบุฮุกเหตุการณ์สําหรับตรรกะที่กําหนดโดยผู้ใช้

ในฐานะผู้เขียนส่วนขยาย คุณได้เห็นว่าผลิตภัณฑ์ Firebase สามารถทริกเกอร์ตรรกะที่ส่วนขยายระบุได้อย่างไร นั่นคือ การสร้างระเบียนใหม่ใน Realtime Database จะทริกเกอร์ฟังก์ชัน makeuppercase ส่วนขยายของคุณอาจมีความสัมพันธ์ที่คล้ายคลึงกับผู้ใช้ที่ติดตั้งส่วนขยาย นั่นคือส่วนขยายสามารถทริกเกอร์ตรรกะที่ผู้ใช้กําหนด

ส่วนขยายอาจมีฮุกแบบซิงโครนัส ฮุกอะซิงโครนัส หรือทั้ง 2 อย่างก็ได้ ฮุกแบบซิงค์ช่วยให้ผู้ใช้มีวิธีดำเนินการที่บล็อกไม่ให้ฟังก์ชันการทำงานอย่างใดอย่างหนึ่งของส่วนขยายเสร็จสมบูรณ์ ซึ่งอาจมีประโยชน์ เช่น การให้ผู้ใช้มีวิธีดำเนินการประมวลผลข้อมูลล่วงหน้าที่กำหนดเองก่อนที่ส่วนขยายจะทำงาน

ในคู่มือนี้ คุณจะได้เพิ่มฮุกแบบไม่พร้อมกันลงในส่วนขยาย ซึ่งจะช่วยให้ผู้ใช้กำหนดขั้นตอนการประมวลผลของตนเองที่จะให้เรียกใช้หลังจากที่ส่วนขยายเขียนข้อความตัวพิมพ์ใหญ่ไปยัง Realtime Database ฮุกแบบไม่พร้อมกันใช้ Eventarc เพื่อเรียกใช้ฟังก์ชันที่ผู้ใช้กําหนด ส่วนขยายจะประกาศประเภทของเหตุการณ์ที่แสดง และเมื่อผู้ใช้ติดตั้งส่วนขยาย ก็จะเลือกประเภทเหตุการณ์ที่สนใจ หากเลือกเหตุการณ์อย่างน้อย 1 รายการ Firebase จะจัดสรรแชแนล Eventarc สําหรับส่วนขยายนั้นเป็นส่วนหนึ่งของกระบวนการติดตั้ง จากนั้นผู้ใช้สามารถติดตั้งใช้งานฟังก์ชันระบบคลาวด์ของตนเองซึ่งจะคอยรับฟังในช่องนั้นและทริกเกอร์เมื่อส่วนขยายเผยแพร่เหตุการณ์ใหม่

ทําตามขั้นตอนต่อไปนี้เพื่อเพิ่มฮุกแบบไม่พร้อมกัน

  1. ในไฟล์ extension.yaml ให้เพิ่มส่วนต่อไปนี้ ซึ่งจะประกาศประเภทเหตุการณ์เดียวที่ส่วนขยายจะส่งออก

    events:
      - type: test-publisher.rtdb-uppercase-messages.v1.complete
        description: >-
          Occurs when message uppercasing completes. The event subject will contain
          the RTDB URL of the uppercase message.
    

    ประเภทเหตุการณ์ต้องไม่ซ้ำกันทั่วโลก ดังนั้นให้ตั้งชื่อเหตุการณ์โดยใช้รูปแบบต่อไปนี้เสมอเพื่อไม่ให้ซ้ำกัน <publisher-id>.<extension-id>.<version>.<description> (คุณยังไม่มีรหัสผู้เผยแพร่โฆษณา ดังนั้นโปรดใช้ test-publisher ไปก่อน)

  2. ในส่วนท้ายของฟังก์ชัน makeuppercase ให้เพิ่มโค้ดที่เผยแพร่เหตุการณ์ประเภทที่คุณเพิ่งประกาศ ดังนี้

    functions/index.js

    // Import the Eventarc library:
    import { initializeApp } from "firebase-admin/app";
    import { getEventarc } from "firebase-admin/eventarc";
    
    const app = initializeApp();
    
    // In makeuppercase, after upperRef.set(uppercase), add:
    
    // Set eventChannel to a newly-initialized channel, or `undefined` if events
    // aren't enabled.
    const eventChannel =
      process.env.EVENTARC_CHANNEL &&
      getEventarc().channel(process.env.EVENTARC_CHANNEL, {
        allowedEventTypes: process.env.EXT_SELECTED_EVENTS,
      });
    
    // If events are enabled, publish a `complete` event to the configured
    // channel.
    eventChannel &&
      eventChannel.publish({
        type: "test-publisher.rtdb-uppercase-messages.v1.complete",
        subject: upperRef.toString(),
        data: {
          "original": original,
          "uppercase": uppercase,
        },
      });
    

    โค้ดตัวอย่างนี้ใช้ประโยชน์จากข้อเท็จจริงที่ว่าตัวแปรสภาพแวดล้อม EVENTARC_CHANNEL จะได้รับการกําหนดก็ต่อเมื่อผู้ใช้เปิดใช้เหตุการณ์อย่างน้อย 1 ประเภทเท่านั้น หากไม่ได้กําหนด EVENTARC_CHANNEL โค้ดจะไม่พยายามเผยแพร่เหตุการณ์ใดๆ

    คุณสามารถแนบข้อมูลเพิ่มเติมไปกับเหตุการณ์ Eventarc ได้ ในตัวอย่างข้างต้น เหตุการณ์มีช่อง subject ที่มีการอ้างอิงถึงค่าที่สร้างขึ้นใหม่ และพายโหลด data ที่มีข้อความต้นฉบับและข้อความตัวพิมพ์ใหญ่ ฟังก์ชันที่ผู้ใช้กําหนดซึ่งทริกเกอร์เหตุการณ์สามารถใช้ข้อมูลนี้ได้

  3. โดยปกติแล้ว ระบบจะกําหนดตัวแปรสภาพแวดล้อม EVENTARC_CHANNEL และ EXT_SELECTED_EVENTS ตามตัวเลือกที่ผู้ใช้เลือกระหว่างการติดตั้ง สําหรับการทดสอบด้วยโปรแกรมจําลอง ให้กําหนดตัวแปรเหล่านี้ด้วยตนเองในไฟล์ rtdb-uppercase-messages.env

    EVENTARC_CHANNEL=locations/us-central1/channels/firebase
    EXT_SELECTED_EVENTS=test-publisher.rtdb-uppercase-messages.v1.complete
    

ตอนนี้คุณได้ทำตามขั้นตอนที่จำเป็นเพื่อเพิ่มฮุกเหตุการณ์แบบไม่พร้อมกันลงในส่วนขยายแล้ว

หากต้องการลองใช้ฟีเจอร์ใหม่ที่เพิ่งติดตั้ง คุณจะสวมบทบาทเป็นผู้ใช้ที่ติดตั้งส่วนขยายได้ในขั้นตอนถัดไป

  1. จากไดเรกทอรี functions/integration-tests ให้เริ่มต้นโปรเจ็กต์ Firebase ใหม่โดยทำดังนี้

    firebase init functions

    เมื่อได้รับข้อความแจ้ง ให้ปฏิเสธที่จะตั้งค่าโปรเจ็กต์เริ่มต้น เลือก JavaScript เป็นภาษา Cloud Functions และติดตั้งทรัพยากร Dependency ที่จำเป็น โปรเจ็กต์นี้แสดงถึงโปรเจ็กต์ของผู้ใช้ซึ่งติดตั้งส่วนขยายของคุณไว้

  2. แก้ไข integration-tests/functions/index.js แล้ววางโค้ดต่อไปนี้

    import { logger } from "firebase-functions/v1";
    import { onCustomEventPublished } from "firebase-functions/v2/eventarc";
    
    import { initializeApp } from "firebase-admin/app";
    import { getDatabase } from "firebase-admin/database";
    
    const app = initializeApp();
    
    export const extraemphasis = onCustomEventPublished(
      "test-publisher.rtdb-uppercase-messages.v1.complete",
      async (event) => {
        logger.info("Received makeuppercase completed event", event);
    
        const refUrl = event.subject;
        const ref = getDatabase().refFromURL(refUrl);
        const upper = (await ref.get()).val();
        return ref.set(`${upper}!!!`);
      }
    );
    

    นี่คือตัวอย่างฟังก์ชันหลังการประมวลผลที่ผู้ใช้อาจเขียน ในกรณีนี้ ฟังก์ชันจะคอยตรวจสอบว่าส่วนขยายเผยแพร่เหตุการณ์ complete หรือไม่ และเมื่อทริกเกอร์ ระบบจะเพิ่มเครื่องหมายตกใจ 3 ตัวลงในข้อความที่เปลี่ยนเป็นอักษรตัวพิมพ์ใหญ่

  3. รีสตาร์ทโปรแกรมจำลอง โปรแกรมจําลองจะโหลดฟังก์ชันของส่วนขยาย รวมถึงฟังก์ชันหลังการประมวลผลที่ "ผู้ใช้" กำหนด

  4. ไปที่ UI โปรแกรมจำลองฐานข้อมูลและแก้ไขโหนดรูทของฐานข้อมูลโดยใช้เส้นทางที่คุณกำหนดไว้ด้านบน

    • ฟิลด์:msgs
    • ประเภท: json
    • ค่า: {"11": {"original": "recipe"}}

    เมื่อคุณบันทึกการเปลี่ยนแปลงฐานข้อมูล ฟังก์ชัน makeuppercase ของส่วนขยายและฟังก์ชัน extraemphasis ของผู้ใช้ควรทริกเกอร์ตามลำดับ ซึ่งจะทำให้ช่อง upper ได้รับค่า RECIPE!!!

8. เพิ่มเครื่องจัดการเหตุการณ์ในวงจรของลูกค้า

ส่วนขยายที่คุณเขียนจนถึงตอนนี้จะประมวลผลข้อความเมื่อสร้าง แต่จะเกิดอะไรขึ้นหากผู้ใช้มีฐานข้อมูลข้อความอยู่แล้วเมื่อติดตั้งส่วนขยาย ส่วนขยาย Firebase มีฟีเจอร์ที่เรียกว่า Lifecycle Event Hook ซึ่งคุณใช้เพื่อทริกเกอร์การดำเนินการได้เมื่อติดตั้ง อัปเดต หรือกำหนดค่าส่วนขยายใหม่ ในส่วนนี้ คุณจะใช้ฮุกเหตุการณ์วงจรเพื่อทดแทนฐานข้อมูลข้อความที่มีอยู่ของโปรเจ็กต์ด้วยข้อความตัวพิมพ์ใหญ่เมื่อผู้ใช้ติดตั้งส่วนขยาย

ส่วนขยาย Firebase ใช้ Cloud Tasks เพื่อเรียกใช้ตัวแฮนเดิลเหตุการณ์ของวงจร คุณกำหนดตัวแฮนเดิลเหตุการณ์โดยใช้ Cloud Functions เมื่ออินสแตนซ์ของส่วนขยายถึงเหตุการณ์วงจรที่รองรับรายการใดรายการหนึ่ง หากคุณได้กำหนดตัวแฮนเดิลไว้ ระบบจะเพิ่มตัวแฮนเดิลลงในคิว Cloud Tasks จากนั้น Cloud Tasks จะดำเนินการกับเครื่องจัดการแบบไม่พร้อมกัน ขณะที่ตัวแฮนเดิลเหตุการณ์วงจรกำลังทำงานอยู่ คอนโซล Firebase จะรายงานผู้ใช้ว่าอินสแตนซ์ส่วนขยายมีงานที่กำลังประมวลผลอยู่ระหว่างดำเนินการ ฟังก์ชันแฮนเดิลจะเป็นผู้รายงานสถานะปัจจุบันและงานที่เสร็จสมบูรณ์กลับไปยังผู้ใช้

หากต้องการเพิ่มตัวแฮนเดิลเหตุการณ์วงจรที่ทดแทนข้อความที่มีอยู่ ให้ทําดังนี้

  1. กําหนด Cloud Function ใหม่ที่ทริกเกอร์โดยเหตุการณ์คิวงาน

    functions/index.js

    import { tasks } from "firebase-functions/v1";
    
    import { getDatabase } from "firebase-admin/database";
    import { getExtensions } from "firebase-admin/extensions";
    import { getFunctions } from "firebase-admin/functions";
    
    export const backfilldata = tasks.taskQueue().onDispatch(async () => {
      const batch = await getDatabase()
        .ref(process.env.MESSAGE_PATH)
        .parent.parent.orderByChild("upper")
        .limitToFirst(20)
        .get();
    
      const promises = [];
      for (const key in batch.val()) {
        const msg = batch.child(key);
        if (msg.hasChild("original") && !msg.hasChild("upper")) {
          const upper = msg.child("original").val().toUpperCase();
          promises.push(msg.child("upper").ref.set(upper));
        }
      }
      await Promise.all(promises);
    
      if (promises.length > 0) {
        const queue = getFunctions().taskQueue(
          "backfilldata",
          process.env.EXT_INSTANCE_ID
        );
        return queue.enqueue({});
      } else {
        return getExtensions()
          .runtime()
          .setProcessingState("PROCESSING_COMPLETE", "Backfill complete.");
      }
    });
    

    โปรดทราบว่าฟังก์ชันจะประมวลผลเพียงไม่กี่ระเบียนก่อนที่จะเพิ่มตัวเองกลับไปยังคิวงาน กลยุทธ์นี้เป็นกลยุทธ์ที่ใช้กันโดยทั่วไปเพื่อจัดการกับงานประมวลผลที่ไม่สามารถทำได้ภายในกรอบเวลาระยะหมดเวลาของ Cloud Function กลยุทธ์นี้เหมาะอย่างยิ่งเนื่องจากคุณไม่สามารถคาดเดาจำนวนข้อความที่ผู้ใช้อาจมีอยู่แล้วในฐานข้อมูลเมื่อติดตั้งส่วนขยาย

  2. ในไฟล์ extension.yaml ให้ประกาศฟังก์ชันโฆษณาทดแทนเป็นทรัพยากรส่วนขยายที่มีพร็อพเพอร์ตี้ taskQueueTrigger ดังนี้

    resources:
      - name: makeuppercase
        ...
      - name: backfilldata
        type: firebaseextensions.v1beta.function
        description: >-
          Backfill existing messages with uppercase versions
        properties:
          runtime: "nodejs18"
          taskQueueTrigger: {}
    

    จากนั้นประกาศฟังก์ชันเป็นตัวแฮนเดิลสําหรับonInstallเหตุการณ์ในวงจรการทํางาน ดังนี้

    lifecycleEvents:
      onInstall:
        function: backfilldata
        processingMessage: Uppercasing existing messages
    
  3. แม้ว่าการทดแทนข้อความที่มีอยู่จะเป็นสิ่งที่ดี แต่ส่วนขยายก็ยังคงทํางานได้หากไม่มี ในกรณีเช่นนี้ คุณควรทําให้การเรียกใช้ตัวแฮนเดิลเหตุการณ์ในวงจรเป็นตัวเลือก

    โดยเพิ่มพารามิเตอร์ใหม่ลงใน extension.yaml ดังนี้

    - param: DO_BACKFILL
      label: Backfill existing messages
      description: >-
        Generate uppercase versions of existing messages?
      type: select
      required: true
      options:
        - label: Yes
          value: true
        - label: No
          value: false
    

    จากนั้นที่จุดเริ่มต้นของฟังก์ชันทดแทน ให้ตรวจสอบค่าของพารามิเตอร์ DO_BACKFILL และออกก่อนเวลาหากไม่ได้ตั้งค่าไว้

    functions/index.js

    if (!process.env.DO_BACKFILL) {
      return getExtensions()
        .runtime()
        .setProcessingState("PROCESSING_COMPLETE", "Backfill skipped.");
    }
    

เมื่อติดตั้งส่วนขยายแล้ว การเปลี่ยนแปลงข้างต้นจะทำให้ส่วนขยายแปลงข้อความที่มีอยู่เป็นอักษรตัวพิมพ์ใหญ่

จนถึงตอนนี้ คุณใช้โปรแกรมจำลองส่วนขยายเพื่อพัฒนาส่วนขยายและทดสอบการเปลี่ยนแปลงอย่างต่อเนื่อง แต่โปรแกรมจำลองส่วนขยายจะข้ามขั้นตอนการติดตั้ง ดังนั้นในการทดสอบเครื่องจัดการเหตุการณ์ onInstall คุณจะต้องติดตั้งส่วนขยายในโปรเจ็กต์จริง ก็มีเพียงเท่านี้ เนื่องจากการเพิ่มคุณลักษณะโฆษณาทดแทนอัตโนมัตินี้ ทำให้ส่วนขยายบทแนะนำสมบูรณ์แบบแล้ว

9. ติดตั้งใช้งานในโปรเจ็กต์ Firebase จริง

แม้ว่าโปรแกรมจำลองส่วนขยายจะเป็นเครื่องมือที่ยอดเยี่ยมสำหรับการปรับปรุงส่วนขยายอย่างรวดเร็วในระหว่างการพัฒนา แต่บางครั้งคุณก็อาจต้องการลองใช้ส่วนขยายในโปรเจ็กต์จริง

เริ่มจากตั้งค่าโปรเจ็กต์ใหม่ที่เปิดใช้บริการบางอย่างก่อน

  1. ในคอนโซล Firebase ให้เพิ่มโปรเจ็กต์ใหม่
  2. อัปเกรดโปรเจ็กต์เป็นแพ็กเกจ Blaze แบบชําระเงินตามการใช้งาน Cloud Functions สำหรับ Firebase กำหนดให้โปรเจ็กต์ของคุณต้องมีบัญชีการเรียกเก็บเงิน คุณจึงต้องมีบัญชีการเรียกเก็บเงินด้วยเพื่อติดตั้งส่วนขยาย
  3. ในโปรเจ็กต์ใหม่ ให้เปิดใช้ Realtime Database
  4. เนื่องจากคุณต้องการทดสอบความสามารถของส่วนขยายในการทดแทนข้อมูลที่มีอยู่เมื่อติดตั้ง ให้นําเข้าข้อมูลตัวอย่างบางส่วนไปยังอินสแตนซ์ฐานข้อมูลแบบเรียลไทม์ ดังนี้
    1. ดาวน์โหลดข้อมูล Seed RTDB บางส่วน
    2. ในหน้าฐานข้อมูลเรียลไทม์ของคอนโซล Firebase ให้คลิก (เพิ่มเติม) > นําเข้า JSON แล้วเลือกไฟล์ที่เพิ่งดาวน์โหลด
  5. หากต้องการเปิดใช้ฟังก์ชันทดแทนข้อมูลให้ใช้เมธอด orderByChild ให้กําหนดค่าฐานข้อมูลเพื่อจัดทำดัชนีข้อความตามค่าของ upper ดังนี้

    {
      "rules": {
        ".read": false,
        ".write": false,
        "messages": {
          ".indexOn": "upper"
        }
      }
    }
    

ตอนนี้ให้ติดตั้งส่วนขยายจากแหล่งที่มาในเครื่องลงในโปรเจ็กต์ใหม่ด้วยคำสั่งต่อไปนี้

  1. สร้างไดเรกทอรีใหม่สำหรับโปรเจ็กต์ Firebase โดยใช้คำสั่งต่อไปนี้

    mkdir ~/extensions-live-test && cd ~/extensions-live-test
    
  2. เริ่มต้นโปรเจ็กต์ Firebase ในไดเรกทอรีทํางาน

    firebase init database

    เมื่อได้รับข้อความแจ้ง ให้เลือกโปรเจ็กต์ที่คุณเพิ่งสร้าง

  3. ติดตั้งส่วนขยายในโปรเจ็กต์ Firebase ในพื้นที่ โดยทำดังนี้

    firebase ext:install /path/to/rtdb-uppercase-messages

    ในส่วนนี้ คุณจะเห็นประสบการณ์ของผู้ใช้เมื่อติดตั้งส่วนขยายโดยใช้เครื่องมือ Firebase CLI อย่าลืมเลือก "ใช่" เมื่อเครื่องมือกําหนดค่าถามว่าคุณต้องการทดแทนข้อมูลในฐานข้อมูลที่มีอยู่หรือไม่

    หลังจากเลือกตัวเลือกการกําหนดค่าแล้ว Firebase CLI จะบันทึกการกําหนดค่าในไดเรกทอรี extensions และบันทึกตําแหน่งแหล่งที่มาของส่วนขยายในไฟล์ firebase.json ข้อมูลระเบียนทั้ง 2 รายการนี้เรียกว่าไฟล์ Manifest ของชิ้นงาน ผู้ใช้สามารถใช้ไฟล์ Manifest เพื่อบันทึกการกำหนดค่าส่วนขยายและนำไปใช้ในโปรเจ็กต์ต่างๆ ได้

  4. ติดตั้งใช้งานการกําหนดค่าชิ้นงานในโปรเจ็กต์ที่ใช้งานอยู่ โดยทําดังนี้

    firebase deploy --only extensions

หากทุกอย่างเรียบร้อยดี Firebase CLI ควรอัปโหลดส่วนขยายไปยังโปรเจ็กต์และติดตั้ง หลังจากการติดตั้งเสร็จสมบูรณ์แล้ว งานทดแทนข้อมูลจะทำงานและฐานข้อมูลจะอัปเดตด้วยข้อความตัวพิมพ์ใหญ่ในอีก 2-3 นาที เพิ่มโหนดใหม่ลงในฐานข้อมูลข้อความและตรวจสอบว่าส่วนขยายทํางานกับข้อความใหม่ด้วย

10. เขียนเอกสารประกอบ

ก่อนแชร์ส่วนขยายกับผู้ใช้ โปรดตรวจสอบว่าคุณให้เอกสารประกอบเพียงพอเพื่อให้ผู้ใช้ใช้งานส่วนขยายได้อย่างราบรื่น

เมื่อคุณเริ่มต้นโปรเจ็กต์ส่วนขยาย Firebase CLI จะสร้างเวอร์ชัน Stub ของเอกสารขั้นต่ำที่จำเป็น อัปเดตไฟล์เหล่านี้ให้ตรงกับส่วนขยายที่คุณสร้าง

extensions.yaml

คุณอัปเดตไฟล์นี้ไปเมื่อพัฒนาส่วนขยายนี้แล้ว คุณจึงไม่ต้องอัปเดตอีกในตอนนี้

อย่างไรก็ตาม อย่ามองข้ามความสำคัญของเอกสารประกอบที่อยู่ในไฟล์นี้ นอกจากข้อมูลการระบุที่สำคัญของส่วนขยายแล้ว เช่น ชื่อ คำอธิบาย ผู้เขียน ตำแหน่งที่เก็บอย่างเป็นทางการ ไฟล์ extension.yaml ยังมีเอกสารประกอบที่แสดงต่อผู้ใช้สำหรับทรัพยากรและพารามิเตอร์ทั้งหมดที่ผู้ใช้กำหนดค่าได้ ข้อมูลนี้จะแสดงต่อผู้ใช้ในคอนโซล Firebase, ฮับส่วนขยาย และ Firebase CLI

PREINSTALL.md

ในไฟล์นี้ ให้ข้อมูลที่ผู้ใช้ต้องมีก่อนติดตั้งส่วนขยายของคุณ โดยอธิบายคร่าวๆ ถึงสิ่งที่ส่วนขยายทำ อธิบายข้อกำหนดเบื้องต้น และให้ข้อมูลผู้ใช้เกี่ยวกับผลการเรียกเก็บเงินของการติดตั้งส่วนขยาย หากคุณมีเว็บไซต์ที่มีข้อมูลเพิ่มเติม ก็สามารถลิงก์เว็บไซต์ดังกล่าวได้ที่นี่

ข้อความของไฟล์นี้จะปรากฏต่อผู้ใช้ในฮับส่วนขยายและตามคำสั่ง firebase ext:info

ตัวอย่างไฟล์ PREINSTALL มีดังนี้

Use this extension to automatically convert strings to upper case when added to
a specified Realtime Database path.

This extension expects a database layout like the following example:

    "messages": {
      MESSAGE_ID: {
        "original": MESSAGE_TEXT
      },
      MESSAGE_ID: {
        "original": MESSAGE_TEXT
      },
    }

When you create new string records, this extension creates a new sibling record
with upper-cased text:

    MESSAGE_ID: {
      "original": MESSAGE_TEXT,
      "upper": UPPERCASE_MESSAGE_TEXT,
    }

#### Additional setup

Before installing this extension, make sure that you've
[set up Realtime Database](https://firebase.google.com/docs/database/quickstart)
in your Firebase project.

#### 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:
  - Realtime Database
  - Cloud Functions (Node.js 10+ runtime)
    [See FAQs](https://firebase.google.com/support/faq#extensions-pricing)
- If you enable events,
  [Eventarc fees apply](https://cloud.google.com/eventarc/pricing).

POSTINSTALL.md

ไฟล์นี้มีข้อมูลที่เป็นประโยชน์สําหรับผู้ใช้หลังจากติดตั้งส่วนขยายเรียบร้อยแล้ว เช่น ขั้นตอนการตั้งค่าติดตามผล ตัวอย่างการใช้งานส่วนขยาย และอื่นๆ

เนื้อหาของ POSTINSTALL.md จะแสดงในคอนโซล Firebase หลังจากที่กําหนดค่าและติดตั้งส่วนขยายแล้ว คุณสามารถอ้างอิงพารามิเตอร์ผู้ใช้ในไฟล์นี้ได้ โดยระบบจะแทนที่พารามิเตอร์เหล่านั้นด้วยค่าที่กำหนดค่าไว้

ต่อไปนี้คือตัวอย่างไฟล์หลังการติดตั้งสําหรับส่วนขยายบทแนะนํา

### See it in action

You can test out this extension right away!

1.  Go to your
    [Realtime Database dashboard](https://console.firebase.google.com/project/${param:PROJECT_ID}/database/${param:PROJECT_ID}/data) in the Firebase console.

1.  Add a message string to a path that matches the pattern `${param:MESSAGE_PATH}`.

1.  In a few seconds, you'll see a sibling node named `upper` that contains the
    message in upper case.

### Using the extension

We recommend adding data by pushing -- for example,
`firebase.database().ref().push()` -- because pushing assigns an automatically
generated ID to the node in the database. During retrieval, these nodes are
guaranteed to be ordered by the time they were added. Learn more about reading
and writing data for your platform (iOS, Android, or Web) in the
[Realtime Database documentation](https://firebase.google.com/docs/database/).

### Monitoring

As a best practice, you can
[monitor the activity](https://firebase.google.com/docs/extensions/manage-installed-extensions#monitor)
of your installed extension, including checks on its health, usage, and logs.

CHANGELOG.md

นอกจากนี้คุณควรบันทึกการเปลี่ยนแปลงที่ทำระหว่างส่วนขยายต่างๆ ไว้ในไฟล์ CHANGELOG.md ด้วย

เนื่องจากส่วนขยายตัวอย่างไม่เคยเผยแพร่มาก่อน บันทึกการเปลี่ยนแปลงจึงมีเพียงรายการเดียว ดังนี้

## Version 0.0.1

Initial release of the _Convert messages to upper case_ extension.

README.md

ส่วนขยายส่วนใหญ่ยังมีไฟล์ Readme ไว้ให้ผู้ใช้ที่ไปที่ที่เก็บของส่วนขยายด้วย คุณสามารถเขียนไฟล์นี้ด้วยตนเองหรือสร้างไฟล์ Readme โดยใช้คำสั่งก็ได้

ข้ามการเขียนไฟล์ Readme ในส่วนนี้

เอกสารประกอบเพิ่มเติม

เอกสารประกอบที่กล่าวถึงข้างต้นเป็นชุดเอกสารประกอบขั้นต่ำที่คุณควรมอบให้ผู้ใช้ ส่วนขยายจำนวนมากต้องการเอกสารที่ละเอียดกว่าผู้ใช้เพื่อให้ใช้งานได้สำเร็จ ในกรณีนี้ คุณควรเขียนเอกสารประกอบเพิ่มเติมและโฮสต์ไว้ที่ใดก็ได้ที่คุณชี้ให้ผู้ใช้ดู

สำหรับคู่มือนี้ ให้ข้ามการเขียนเอกสารประกอบที่ครอบคลุมยิ่งขึ้น

11. เผยแพร่ใน Extensions Hub

เมื่อเขียนโค้ดและจัดทำเอกสารส่วนขยายเสร็จแล้ว คุณก็พร้อมที่จะแชร์ส่วนขยายกับโลกใน Extensions Hub แต่เนื่องจากนี่เป็นเพียงบทแนะนำ คุณจึงไม่ต้องดำเนินการดังกล่าว เริ่มเขียนส่วนขยายของคุณเองโดยใช้สิ่งที่คุณได้เรียนรู้จากที่นี่และในเอกสารอื่นๆ สำหรับผู้เผยแพร่โฆษณาของ Firebase Extensions รวมถึงตรวจสอบแหล่งที่มาของส่วนขยายอย่างเป็นทางการที่ Firebase เขียนขึ้น

เมื่อพร้อมเผยแพร่ผลงานใน Extensions Hub ให้ทำดังนี้

  1. หากคุณเผยแพร่ส่วนขยายเป็นครั้งแรก ให้ลงทะเบียนเป็นผู้เผยแพร่ส่วนขยาย เมื่อลงทะเบียนเป็นผู้เผยแพร่ส่วนขยาย คุณจะสร้างรหัสผู้เผยแพร่โฆษณาที่ช่วยให้ผู้ใช้ระบุตัวตนของคุณได้อย่างรวดเร็วในฐานะผู้เขียนส่วนขยาย
  2. โฮสต์ซอร์สโค้ดของส่วนขยายในตำแหน่งที่ตรวจสอบได้แบบสาธารณะ เมื่อรหัสของคุณพร้อมใช้งานจากแหล่งที่มาที่ยืนยันได้ Firebase จะเผยแพร่ชิ้นงานจากตำแหน่งนี้โดยตรงได้ ซึ่งจะช่วยให้มั่นใจว่าคุณเผยแพร่ส่วนขยายเวอร์ชันที่เผยแพร่อยู่ในปัจจุบัน และช่วยให้ผู้ใช้ตรวจสอบโค้ดที่จะติดตั้งในโปรเจ็กต์ได้

    ปัจจุบันการดำเนินการนี้หมายถึงการทำให้ส่วนขยายพร้อมใช้งานในที่เก็บ GitHub แบบสาธารณะ

  3. อัปโหลดส่วนขยายไปยัง Extensions Hub โดยใช้คำสั่ง firebase ext:dev:upload

  4. ไปที่แดชบอร์ดผู้เผยแพร่โฆษณาในคอนโซล Firebase แล้วค้นหาส่วนขยายที่เพิ่งอัปโหลด แล้วคลิก "เผยแพร่ไปยัง Extensions Hub" การดำเนินการนี้จะขอรับการตรวจสอบจากเจ้าหน้าที่ตรวจสอบ ซึ่งอาจใช้เวลา 2-3 วัน หากได้รับอนุมัติ ระบบจะเผยแพร่ส่วนขยายไปยังฮับส่วนขยาย หากถูกปฏิเสธ คุณจะได้รับข้อความอธิบายเหตุผล จากนั้นคุณสามารถแก้ไขปัญหาที่รายงานแล้วส่งเข้ารับการตรวจสอบอีกครั้ง