एक्सटेंशन बनाना शुरू करें

इस पेज पर, Firebase का आसान एक्सटेंशन बनाने का तरीका बताया गया है. इसे अपने प्रोजेक्ट में इंस्टॉल किया जा सकता है या दूसरों के साथ शेयर किया जा सकता है. Firebase एक्सटेंशन के इस आसान उदाहरण में, आपके रीयलटाइम डेटाबेस में मौजूद मैसेज को देखा जाएगा और उन्हें अपरकेस में बदल दिया जाएगा.

1. अपना एनवायरमेंट सेट अप करना और प्रोजेक्ट को शुरू करना

एक्सटेंशन बनाने से पहले, आपको ज़रूरी टूल के साथ एक बिल्ड एनवायरमेंट सेट अप करना होगा.

  1. Node.js 16 या इसके बाद का वर्शन इंस्टॉल करें. Node को इंस्टॉल करने का एक तरीका यह है कि आप 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. Firebase CLI का ext:dev:init कमांड चलाएं:

    firebase ext:dev:init

    जब आपसे कहा जाए, तो फ़ंक्शन के लिए JavaScript को भाषा के तौर पर चुनें. हालांकि, ध्यान दें कि अपना एक्सटेंशन बनाते समय, TypeScript का भी इस्तेमाल किया जा सकता है. साथ ही, डिपेंडेंसी इंस्टॉल करने के लिए कहा जाने पर, "हां" में जवाब दें. (किसी भी अन्य विकल्प के लिए डिफ़ॉल्ट तौर पर सेट की गई वैल्यू स्वीकार करें.) यह कमांड, नए एक्सटेंशन के लिए स्केलेटन कोडबेस सेट अप करेगा. इसके बाद, इस एक्सटेंशन को डेवलप किया जा सकता है.

2. एमुलेटर का इस्तेमाल करके, एक्सटेंशन का उदाहरण आज़माना

जब Firebase CLI ने नई एक्सटेंशन डायरेक्ट्री को शुरू किया, तो उसने एक आसान उदाहरण फ़ंक्शन और एक integration-tests डायरेक्ट्री बनाई. इस डायरेक्ट्री में, Firebase एमुलेटर सुइट का इस्तेमाल करके एक्सटेंशन चलाने के लिए ज़रूरी फ़ाइलें होती हैं.

एमुलेटर में सैंपल एक्सटेंशन चलाने की कोशिश करें:

  1. integration-tests डायरेक्ट्री पर जाएं:

    cd functions/integration-tests
  2. डेमो प्रोजेक्ट के साथ एमुलेटर शुरू करें:

    firebase emulators:start --project=demo-test

    एमुलेटर, एक्सटेंशन को पहले से तय किए गए "डमी" प्रोजेक्ट (demo-test) में लोड करता है. फ़िलहाल, एक्सटेंशन में एक एचटीटीपी ट्रिगर वाला फ़ंक्शन, greetTheWorld है. इसे ऐक्सेस करने पर, "हैलो वर्ल्ड" मैसेज दिखता है.

  3. एमुलेटर के चालू रहने पर, एक्सटेंशन के greetTheWorld फ़ंक्शन को आज़माएं. इसके लिए, उस यूआरएल पर जाएं जिसे एमुलेटर शुरू करने पर प्रिंट किया गया था.

    आपके ब्राउज़र में "greet-the-world से नमस्ते दुनिया" मैसेज दिखता है.

  4. इस फ़ंक्शन का सोर्स कोड, एक्सटेंशन की functions डायरेक्ट्री में मौजूद होता है. सोर्स को अपनी पसंद के एडिटर या आईडीई में खोलें:

    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}`;
    

    बदलावों को सेव करें. एमुलेटर आपके कोड को फिर से लोड करेगा. अब, फ़ंक्शन के यूआरएल पर जाने पर, आपको अपडेट किया गया ग्रीटिंग मैसेज दिखेगा.

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 फ़ंक्शन लिखना और उसे एक्सटेंशन संसाधन के तौर पर एलान करना

अब कुछ कोड लिखना शुरू किया जा सकता है. इस चरण में, आपको एक Cloud Function लिखना होगा. यह आपके एक्सटेंशन का मुख्य काम करता है. इसका मकसद, आपके रीयल टाइम डेटाबेस में मैसेज देखना और उन्हें अपरकेस में बदलना है.

  1. अपनी पसंद के एडिटर या आईडीई में, एक्सटेंशन के फ़ंक्शन के सोर्स (एक्सटेंशन की functions डायरेक्ट्री में) को खोलें. इसके कॉन्टेंट को इनके साथ बदलें:

    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);
    });
    

    आपने जिस पुराने फ़ंक्शन को बदला है वह एचटीटीपी से ट्रिगर होने वाला फ़ंक्शन था. यह फ़ंक्शन, एचटीटीपी एंडपॉइंट को ऐक्सेस करने पर चलता था. नया फ़ंक्शन, रीयल-टाइम डेटाबेस इवेंट से ट्रिगर होता है: यह किसी खास पाथ पर नए आइटम को देखता है और जब कोई आइटम मिलता है, तो वह वैल्यू के अपरकेस वर्शन को डेटाबेस में वापस लिखता है.

    वैसे, यह नई फ़ाइल CommonJS (require) के बजाय, ECMAScript मॉड्यूल सिंटैक्स (import और export) का इस्तेमाल करती है. Node में ES मॉड्यूल इस्तेमाल करने के लिए, functions/package.json में "type": "module" बताएं:

    {
      "name": "rtdb-uppercase-messages",
      "main": "index.js",
      "type": "module",
      
    }
    
  2. आपके एक्सटेंशन के हर फ़ंक्शन को extension.yaml फ़ाइल में एलान किया जाना चाहिए. उदाहरण के तौर पर, एक्सटेंशन में greetTheWorld को एक्सटेंशन के एकमात्र क्लाउड फ़ंक्शन के तौर पर एलान किया गया था. अब इसे 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. आपका एक्सटेंशन अब ट्रिगर के तौर पर रीयल टाइम डेटाबेस का इस्तेमाल कर रहा है. इसलिए, आपको Cloud Functions एमुलेटर के साथ-साथ RTDB एमुलेटर को चलाने के लिए, अपने एमुलेटर कॉन्फ़िगरेशन को अपडेट करना होगा:

    1. अगर एमुलेटर अब भी चल रहा है, तो Ctrl-C दबाकर उसे बंद करें.

    2. functions/integration-tests डायरेक्ट्री में जाकर, यह कमांड चलाएं:

      firebase init emulators

      पूछे जाने पर, डिफ़ॉल्ट प्रोजेक्ट सेट अप करने की प्रोसेस को छोड़ें. इसके बाद, फ़ंक्शन और डेटाबेस एमुलेटर चुनें. डिफ़ॉल्ट पोर्ट स्वीकार करें और सेटअप टूल को ज़रूरी फ़ाइलें डाउनलोड करने की अनुमति दें.

    3. एम्युलेटर को रीस्टार्ट करें:

      firebase emulators:start --project=demo-test
  4. अपडेट किया गया एक्सटेंशन आज़माएं:

    1. डेटाबेस एमुलेटर का यूज़र इंटरफ़ेस (यूआई) खोलने के लिए, उस लिंक का इस्तेमाल करें जिसे एमुलेटर ने शुरू करने पर प्रिंट किया था.

    2. डेटाबेस के रूट नोड में बदलाव करें:

      • फ़ील्ड: messages
      • टाइप: json
      • वैल्यू: {"11": {"original": "recipe"}}

      अगर सब कुछ सही तरीके से सेट अप किया गया है, तो डेटाबेस में किए गए बदलावों को सेव करने पर, एक्सटेंशन का makeuppercase फ़ंक्शन ट्रिगर हो जाना चाहिए. साथ ही, मैसेज 11 में कॉन्टेंट "upper": "RECIPE" के साथ चाइल्ड रिकॉर्ड जोड़ना चाहिए. उम्मीद के मुताबिक नतीजों की पुष्टि करने के लिए, एमुलेटर यूज़र इंटरफ़ेस (यूआई) के लॉग और डेटाबेस टैब देखें.

    3. messages नोड ({"original":"any text"}) में कुछ और चाइल्ड जोड़ें. नया रिकॉर्ड जोड़ने पर, एक्सटेंशन को original फ़ील्ड के अपरकेस कॉन्टेंट वाला uppercase फ़ील्ड जोड़ना चाहिए.

अब आपके पास एक पूरा, लेकिन आसान एक्सटेंशन है, जो RTDB इंस्टेंस पर काम करता है. आगे दिए गए सेक्शन में, आपको कुछ और सुविधाओं के साथ इस एक्सटेंशन को बेहतर बनाने का तरीका पता चलेगा. इसके बाद, आपके पास एक्सटेंशन को दूसरों को डिस्ट्रिब्यूट करने का विकल्प होगा. साथ ही, एक्सटेंशन हब पर अपना एक्सटेंशन पब्लिश करने का तरीका भी जानें.

5. एपीआई और भूमिकाओं की जानकारी देना

Firebase, इंस्टॉल किए गए एक्सटेंशन के हर इंस्टेंस को प्रोजेक्ट और उसके डेटा का सीमित ऐक्सेस देता है. इसके लिए, हर इंस्टेंस के लिए एक सेवा खाता इस्तेमाल किया जाता है. हर खाते के पास, काम करने के लिए ज़रूरी अनुमतियों का कम से कम सेट होता है. इस वजह से, आपको अपने एक्सटेंशन के लिए ज़रूरी IAM भूमिकाओं के बारे में साफ़ तौर पर बताना होगा. जब उपयोगकर्ता आपका एक्सटेंशन इंस्टॉल करते हैं, तो Firebase इन भूमिकाओं के साथ एक सेवा खाता बनाता है और एक्सटेंशन को चलाने के लिए इसका इस्तेमाल करता है.

किसी प्रॉडक्ट के इवेंट को ट्रिगर करने के लिए, आपको भूमिकाएं तय करने की ज़रूरत नहीं है. हालांकि, उससे इंटरैक्ट करने के लिए, आपको भूमिका तय करनी होगी. पिछले चरण में जोड़ा गया फ़ंक्शन, रीयलटाइम डेटाबेस में डेटा लिखता है. इसलिए, आपको extension.yaml में यह एलान जोड़ना होगा:

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

इसी तरह, apis फ़ील्ड में उन Google API के बारे में बताया जाता है जिनका इस्तेमाल कोई एक्सटेंशन करता है. जब उपयोगकर्ता आपका एक्सटेंशन इंस्टॉल करेंगे, तो उनसे पूछा जाएगा कि क्या उन्हें अपने प्रोजेक्ट के लिए, इन एपीआई को अपने-आप चालू करना है. आम तौर पर, यह सिर्फ़ Firebase के अलावा अन्य Google API के लिए ज़रूरी है. इस गाइड के लिए, इसकी ज़रूरत नहीं है.

6. उपयोगकर्ता के कॉन्फ़िगर किए जा सकने वाले पैरामीटर तय करना

पिछले दो चरणों में आपने जो फ़ंक्शन बनाया था वह आने वाले मैसेज के लिए, 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 एक्सटेंशन में, यह बदलाव सिर्फ़ दस्तावेज़ के लिए किया गया है: जब किसी एक्सटेंशन के हिस्से के तौर पर Cloud फ़ंक्शन को डिप्लॉय किया जाता है, तो वह 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. अब, एम्युलेटर को रीस्टार्ट करें और फिर से डेटाबेस एम्युलेटर के यूज़र इंटरफ़ेस (यूआई) पर जाएं.

    ऊपर बताए गए पाथ का इस्तेमाल करके, डेटाबेस के रूट नोड में बदलाव करें:

    • फ़ील्ड: msgs
    • टाइप: json
    • वैल्यू: {"11": {"original": "recipe"}}

    डेटाबेस में किए गए बदलावों को सेव करने पर, एक्सटेंशन का makeuppercase फ़ंक्शन पहले की तरह ही ट्रिगर होना चाहिए. हालांकि, अब यह कंसोल लॉग में उपयोगकर्ता के तय किए गए पैरामीटर को भी प्रिंट करेगा.

7. उपयोगकर्ता के तय किए गए लॉजिक के लिए इवेंट हुक उपलब्ध कराना

एक्सटेंशन के लेखक के तौर पर, आपने पहले ही देखा है कि Firebase प्रॉडक्ट, आपके एक्सटेंशन में दिए गए लॉजिक को कैसे ट्रिगर कर सकता है: रीयलटाइम डेटाबेस में नए रिकॉर्ड बनाने से, आपका makeuppercase फ़ंक्शन ट्रिगर होता है. आपके एक्सटेंशन को इंस्टॉल करने वाले उपयोगकर्ताओं के साथ, आपके एक्सटेंशन का मिलता-जुलता संबंध हो सकता है: आपका एक्सटेंशन, उपयोगकर्ता के तय किए गए लॉजिक को ट्रिगर कर सकता है.

कोई एक्सटेंशन, सिंक्रोनस हुक, असिंक्रोनस हुक या दोनों उपलब्ध करा सकता है. सिंक्रोनस हुक की मदद से, उपयोगकर्ता ऐसे टास्क पूरे कर सकते हैं जो एक्सटेंशन के किसी फ़ंक्शन को पूरा होने से रोकते हैं. उदाहरण के लिए, यह उपयोगकर्ताओं को एक्सटेंशन के काम करने से पहले, पसंद के मुताबिक डेटा को पहले से प्रोसेस करने का तरीका देने में मददगार हो सकता है.

इस गाइड में, आपको अपने एक्सटेंशन में एक असाइनोक्रोनस हुक जोड़ना होगा. इससे उपयोगकर्ताओं को, प्रोसेसिंग के अपने चरण तय करने में मदद मिलेगी. ये चरण, आपके एक्सटेंशन के रीयल टाइम डेटाबेस में अपरकेस मैसेज लिखने के बाद चलेंगे. उपयोगकर्ता के तय किए गए फ़ंक्शन को ट्रिगर करने के लिए, असाइनोक्रोनस हुक, Eventarc का इस्तेमाल करते हैं. एक्सटेंशन, उन इवेंट के टाइप की जानकारी देते हैं जिन्हें वे उत्सर्जित करते हैं. साथ ही, जब उपयोगकर्ता एक्सटेंशन इंस्टॉल करते हैं, तो वे यह चुनते हैं कि उन्हें किस तरह के इवेंट में दिलचस्पी है. अगर वे कम से कम एक इवेंट चुनते हैं, तो 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 एनवायरमेंट वैरिएबल सिर्फ़ तब तय किया जाता है, जब उपयोगकर्ता ने कम से कम एक तरह का इवेंट चालू किया हो. अगर 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

    जब कहा जाए, तो डिफ़ॉल्ट प्रोजेक्ट सेट अप करने से मना करें. साथ ही, Cloud Functions की भाषा के तौर पर JavaScript चुनें और ज़रूरी डिपेंडेंसी इंस्टॉल करें. यह प्रोजेक्ट, उपयोगकर्ता के उस प्रोजेक्ट को दिखाता है जिसमें आपका एक्सटेंशन इंस्टॉल है.

  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. एमुलेटर को रीस्टार्ट करें. एमुलेटर, एक्सटेंशन के फ़ंक्शन के साथ-साथ, "उपयोगकर्ता" के तय किए गए पोस्ट-प्रोसेसिंग फ़ंक्शन को भी लोड करेगा.

  4. डेटाबेस एमुलेटर के यूज़र इंटरफ़ेस (यूआई) पर जाएं और ऊपर बताए गए पाथ का इस्तेमाल करके, डेटाबेस के रूट नोड में बदलाव करें:

    • फ़ील्ड:msgs
    • टाइप: json
    • वैल्यू: {"11": {"original": "recipe"}}

    डेटाबेस में किए गए बदलावों को सेव करने पर, एक्सटेंशन का makeuppercase फ़ंक्शन और उपयोगकर्ता का extraemphasis फ़ंक्शन क्रम से ट्रिगर होना चाहिए. इससे upper फ़ील्ड में वैल्यू RECIPE!!! दिखेगी.

8. लाइफ़साइकल इवेंट हैंडलर जोड़ना

आपने जो एक्सटेंशन लिखा है वह मैसेज बनने के साथ ही उन्हें प्रोसेस कर देता है. हालांकि, अगर आपके उपयोगकर्ताओं के पास एक्सटेंशन इंस्टॉल करने के समय, मैसेज का डेटाबेस पहले से मौजूद है, तो क्या होगा? Firebase एक्सटेंशन में लाइफ़साइकल इवेंट हुक नाम की एक सुविधा होती है. इसका इस्तेमाल, एक्सटेंशन के इंस्टॉल, अपडेट या फिर कॉन्फ़िगर होने पर कार्रवाइयां ट्रिगर करने के लिए किया जा सकता है. इस सेक्शन में, लाइफ़साइकल इवेंट हुक का इस्तेमाल करके, किसी प्रोजेक्ट के मौजूदा मैसेज डेटाबेस को अपरकेस मैसेज से बैकफ़िल किया जाएगा. ऐसा तब किया जाएगा, जब कोई उपयोगकर्ता आपका एक्सटेंशन इंस्टॉल करेगा.

Firebase एक्सटेंशन, आपके लाइफ़साइकल इवेंट हैंडलर को चलाने के लिए Cloud Tasks का इस्तेमाल करता है. Cloud Functions का इस्तेमाल करके, इवेंट हैंडलर तय किए जाते हैं. अगर आपने हैंडलर तय किया है, तो जब भी आपके एक्सटेंशन का कोई इंस्टेंस, लाइफ़साइकल के किसी इवेंट तक पहुंचता है, तो वह हैंडलर को Cloud Tasks की सूची में जोड़ देगा. इसके बाद, Cloud Tasks, हैंडलर को असाइन किए गए टास्क को एक साथ नहीं, बल्कि अलग-अलग समय पर पूरा करेगा. लाइफ़साइकल इवेंट हैंडलर के चलने के दौरान, Firebase कंसोल उपयोगकर्ता को बताएगा कि एक्सटेंशन इंस्टेंस में प्रोसेसिंग टास्क जारी है. उपयोगकर्ता को टास्क के मौजूदा स्टेटस और उसके पूरा होने की जानकारी देना, आपके हैंडलर फ़ंक्शन पर निर्भर करता है.

मौजूदा मैसेज को बैकफ़िल करने वाला लाइफ़साइकल इवेंट हैंडलर जोड़ने के लिए, यह तरीका अपनाएं:

  1. टास्क सूची के इवेंट से ट्रिगर होने वाला नया Cloud फ़ंक्शन तय करें:

    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 फ़ंक्शन की टाइम आउट विंडो में पूरे नहीं हो सकते. आपके पास यह अनुमान लगाने का विकल्प नहीं है कि आपका एक्सटेंशन इंस्टॉल करने पर, उपयोगकर्ता के डेटाबेस में पहले से कितने मैसेज मौजूद हो सकते हैं. इसलिए, यह रणनीति सबसे सही है.

  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. अपने प्रोजेक्ट को, 'इस्तेमाल के हिसाब से पैसे चुकाएं' वाले ब्लेज़ प्लान पर अपग्रेड करें. Cloud Functions for Firebase के लिए, आपके प्रोजेक्ट में बिलिंग खाता होना ज़रूरी है. इसलिए, एक्सटेंशन इंस्टॉल करने के लिए भी आपके पास बिलिंग खाता होना चाहिए.
  3. अपने नए प्रोजेक्ट में, रीयल-टाइम डेटाबेस चालू करें.
  4. आपको अपने एक्सटेंशन की जांच करनी है कि वह इंस्टॉल होने पर, मौजूदा डेटा को बैकफ़िल कर सकता है या नहीं. इसके लिए, अपने रीयल-टाइम डेटाबेस इंस्टेंस में कुछ सैंपल डेटा इंपोर्ट करें:
    1. कुछ सीड आरटीडीबी डेटा डाउनलोड करें.
    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 फ़ाइल में एक्सटेंशन के सोर्स की जगह को रिकॉर्ड कर देगा. इन दोनों रिकॉर्ड को एक साथ, एक्सटेंशन मेनिफ़ेस्ट कहा जाता है. उपयोगकर्ता, एक्सटेंशन के कॉन्फ़िगरेशन को सेव करने और उसे अलग-अलग प्रोजेक्ट में डिप्लॉय करने के लिए, मेनिफ़ेस्ट का इस्तेमाल कर सकते हैं.

  4. अपने लाइव प्रोजेक्ट में एक्सटेंशन कॉन्फ़िगरेशन को डिप्लॉय करें:

    firebase deploy --only extensions

अगर सब कुछ ठीक रहा, तो Firebase CLI आपके एक्सटेंशन को प्रोजेक्ट में अपलोड कर देगा और उसे इंस्टॉल कर देगा. इंस्टॉलेशन पूरा होने के बाद, बैकफ़िल टास्क चलेगा और कुछ ही मिनटों में, आपका डेटाबेस अपरकेस मैसेज के साथ अपडेट हो जाएगा. मैसेज डेटाबेस में कुछ नए नोड जोड़ें और पक्का करें कि एक्सटेंशन नए मैसेज के लिए भी काम कर रहा हो.

10. दस्तावेज़ लिखना

उपयोगकर्ताओं के साथ अपना एक्सटेंशन शेयर करने से पहले, पक्का करें कि आपने उन्हें एक्सटेंशन इस्तेमाल करने के लिए ज़रूरी दस्तावेज़ उपलब्ध कराए हों.

एक्सटेंशन प्रोजेक्ट को शुरू करने पर, Firebase CLI ने कम से कम ज़रूरी दस्तावेज़ों के स्टब वर्शन बनाए. आपने जो एक्सटेंशन बनाया है उसे सही तरीके से दिखाने के लिए, इन फ़ाइलों को अपडेट करें.

extension.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

ज़्यादातर एक्सटेंशन, रीड मी फ़ाइल भी उपलब्ध कराते हैं. इससे, एक्सटेंशन के रिपॉज़िटरी पर आने वाले उपयोगकर्ताओं को फ़ायदा मिलता है. इस फ़ाइल को मैन्युअल तरीके से लिखा जा सकता है या कमांड का इस्तेमाल करके रीड मी फ़ाइल जनरेट की जा सकती है.

इस गाइड के लिए, रीड मी फ़ाइल न लिखें.

अन्य दस्तावेज़

ऊपर बताए गए दस्तावेज़, उन दस्तावेज़ों का कम से कम सेट है जिन्हें आपको उपयोगकर्ताओं को उपलब्ध कराना चाहिए. कई एक्सटेंशन के लिए, उपयोगकर्ताओं को ज़्यादा जानकारी वाले दस्तावेज़ की ज़रूरत होती है, ताकि वे उन्हें सही तरीके से इस्तेमाल कर सकें. ऐसे में, आपको ज़्यादा दस्तावेज़ लिखने चाहिए और उन्हें ऐसी जगह पर होस्ट करना चाहिए जहां उपयोगकर्ताओं को भेजा जा सके.

इस गाइड के लिए, ज़्यादा जानकारी वाला दस्तावेज़ न लिखें.

11. एक्सटेंशन हब पर पब्लिश करना

अब आपका एक्सटेंशन पूरा हो गया है और उसका दस्तावेज़ तैयार हो गया है. अब इसे एक्सटेंशन हब पर दुनिया के साथ शेयर किया जा सकता है. हालांकि, यह सिर्फ़ एक ट्यूटोरियल है. इसलिए, ऐसा असल में न करें. यहां और Firebase एक्सटेंशन पब्लिशर के दस्तावेज़ों में बताई गई बातों का इस्तेमाल करके, अपना एक्सटेंशन लिखना शुरू करें. साथ ही, Firebase के लिखे गए आधिकारिक एक्सटेंशन के सोर्स की जांच करें.

जब आप एक्सटेंशन हब पर अपना एक्सटेंशन पब्लिश करने के लिए तैयार हों, तो यहां बताया गया तरीका अपनाएं:

  1. अगर पहली बार एक्सटेंशन पब्लिश किया जा रहा है, तो एक्सटेंशन पब्लिशर के तौर पर रजिस्टर करें. एक्सटेंशन पब्लिशर के तौर पर रजिस्टर करने पर, एक पब्लिशर आईडी बनता है. इससे उपयोगकर्ता, एक्सटेंशन के लेखक के तौर पर आपकी पहचान तुरंत कर पाते हैं.
  2. अपने एक्सटेंशन के सोर्स कोड को सार्वजनिक तौर पर पुष्टि की जा सकने वाली जगह पर होस्ट करें. जब आपका कोड, पुष्टि किए जा सकने वाले किसी सोर्स से उपलब्ध होता है, तो Firebase सीधे उस सोर्स से आपका एक्सटेंशन पब्लिश कर सकता है. ऐसा करने से यह पक्का करने में मदद मिलती है कि आपने अपने एक्सटेंशन का वह वर्शन पब्लिश किया है जो फ़िलहाल रिलीज़ किया गया है. साथ ही, इससे उपयोगकर्ताओं को अपने प्रोजेक्ट में इंस्टॉल किए जा रहे कोड की जांच करने में मदद मिलती है.

    फ़िलहाल, इसका मतलब है कि आपके एक्सटेंशन को सार्वजनिक GitHub रिपॉज़िटरी में उपलब्ध कराना.

  3. firebase ext:dev:upload कमांड का इस्तेमाल करके, एक्सटेंशन हब में अपना एक्सटेंशन अपलोड करें.

  4. Firebase कंसोल में अपने पब्लिशर डैशबोर्ड पर जाएं. इसके बाद, वह एक्सटेंशन ढूंढें जिसे आपने अभी अपलोड किया है और "एक्सटेंशन हब पर पब्लिश करें" पर क्लिक करें. इससे, समीक्षा करने वाले हमारे कर्मचारियों से समीक्षा का अनुरोध किया जाता है. इसमें कुछ दिन लग सकते हैं. अनुमति मिलने पर, एक्सटेंशन को एक्सटेंशन हब में पब्लिश कर दिया जाएगा. अगर आपका अनुरोध अस्वीकार कर दिया जाता है, तो आपको इसकी वजह बताने वाला एक मैसेज मिलेगा. इसके बाद, आपके पास शिकायत की गई समस्याओं को ठीक करने और समीक्षा के लिए फिर से सबमिट करने का विकल्प होगा.