अपने Cloud Functions कोड को Firebase एक्सटेंशन के तौर पर फिर से इस्तेमाल करें

1. शुरू करने से पहले

Firebase एक्सटेंशन, एचटीटीपी अनुरोधों या दूसरे Firebase और Google प्रॉडक्ट, जैसे कि Firebase क्लाउड से मैसेज, Cloud Firestore या Pub/Sub से इवेंट ट्रिगर करने के जवाब में एक खास टास्क या कई तरह के टास्क करता है.

आपको क्या बनाना होगा

इस कोडलैब में, geoहैशिंग के लिए Firebase एक्सटेंशन बनाया जा सकता है. लागू होने के बाद, आपका एक्सटेंशन X- और Y-कोऑर्डिनेट को Firestore इवेंट के जवाब में या कॉल करने लायक फ़ंक्शन शुरू करने के बाद भौगोलिक स्थिति में बदल देता है. इसका इस्तेमाल आपके सभी टारगेट प्लैटफ़ॉर्म पर जियोफ़ायर लाइब्रेरी लागू करने के विकल्प के तौर पर भी किया जा सकता है. इससे आपका समय बचेगा और डेटा सेव किया जा सकेगा.

Firebase कंसोल में जियोहैश एक्सटेंशन दिख रहा है

आपको इनके बारे में जानकारी मिलेगी

  • मौजूदा Cloud Functions कोड को लेने और उसे डिस्ट्रिब्यूट किए जा सकने वाले Firebase एक्सटेंशन में बदलने का तरीका
  • extension.yaml फ़ाइल को सेट अप करने का तरीका
  • किसी एक्सटेंशन में संवेदनशील स्ट्रिंग (एपीआई पासकोड) सेव करने का तरीका
  • एक्सटेंशन के डेवलपर को अपनी ज़रूरतों के हिसाब से इसे कॉन्फ़िगर करने की अनुमति कैसे दें
  • एक्सटेंशन की जांच करने और उसे डिप्लॉय करने का तरीका

आपको इन चीज़ों की ज़रूरत होगी

  • Firebase सीएलआई (इंस्टॉल करना और लॉगिन करना)
  • Google खाता, जैसे कि Gmail खाता
  • Node.js और npm
  • आपका पसंदीदा डेवलपमेंट एनवायरमेंट

2. सेट अप शुरू करें

कोड पाएं

इस एक्सटेंशन के लिए आपको जो कुछ भी चाहिए वह GitHub के रेपो में है. शुरू करने के लिए, कोड लें और उसे अपने पसंदीदा डेवलपमेंट एनवायरमेंट में खोलें.

  1. डाउनलोड की गई ZIP फ़ाइल को अनपैक करें.
  2. ज़रूरी डिपेंडेंसी इंस्टॉल करने के लिए, टर्मिनल को functions डायरेक्ट्री में खोलें और npm install कमांड चलाएं.

Firebase सेट अप करना

यह कोडलैब Firebase एम्युलेटर के इस्तेमाल को बढ़ावा देता है. अगर आपको किसी असल Firebase प्रोजेक्ट की मदद से एक्सटेंशन डेवलपमेंट आज़माना है, तो Firebase प्रोजेक्ट बनाना लेख पढ़ें. यह कोडलैब, Cloud Functions का इस्तेमाल करता है. इसलिए, अगर एम्युलेटर के बजाय किसी असली Firebase प्रोजेक्ट का इस्तेमाल किया जा रहा है, तो आपको Blaze प्राइसिंग प्लान पर अपग्रेड करना होगा.

क्या आपको इसे छोड़कर आगे बढ़ना है?

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

3. कोड की समीक्षा करें

  • ZIP फ़ाइल से index.ts फ़ाइल खोलें. ध्यान दें कि उसमें दो Cloud Functions एलान शामिल हैं.

ये फ़ंक्शन क्या करते हैं?

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

फ़ंक्शन कॉन्सटेंट

index.ts फ़ाइल में सबसे ऊपर, कॉन्सटेंट की जानकारी जल्दी दे दी जाती है. एक्सटेंशन के तय किए गए ट्रिगर में इनमें से कुछ कॉन्सटेंट का रेफ़रंस दिया गया है.

index.ts

import {firestore} from "firebase-functions";
import {initializeApp} from "firebase-admin/app";
import {GeoHashService, ResultStatusCode} from "./fake-geohash-service";
import {onCall} from "firebase-functions/v1/https";
import {fieldValueExists} from "./utils";

const documentPath = "users/{uid}";
const xField = "xv";
const yField = "yv";
const apiKey = "1234567890";
const outputField = "hash";

initializeApp();

const service = new GeoHashService(apiKey);

फ़ायरस्टोर ट्रिगर

index.ts फ़ाइल में पहला फ़ंक्शन इस तरह दिखता है:

index.ts

export const locationUpdate = firestore.document(documentPath)
  .onWrite((change) => {
    // item deleted
    if (change.after == null) {
      return 0;
    }
    // double check that both values exist for computation
    if (
      !fieldValueExists(change.after.data(), xField) ||
      !fieldValueExists(change.after.data(), yField)
    ) {
      return 0;
    }
    const x: number = change.after.data()![xField];
    const y: number = change.after.data()![yField];
    const hash = service.convertToHash(x, y);
    // This is to check whether the hash value has changed. If
    // it hasn't, you don't want to write to the document again as it
    // would create a recursive write loop.
    if (fieldValueExists(change.after.data(), outputField)
      && change.after.data()![outputField] == hash) {
      return 0;
    }
    return change.after.ref
      .update(
        {
          [outputField]: hash.hash,
        }
      );
  });

यह फ़ंक्शन एक फ़ायरस्टोर ट्रिगर है. जब डेटाबेस में राइट इवेंट होता है, तो फ़ंक्शन xv फ़ील्ड और yv फ़ील्ड को खोजकर, उस इवेंट पर प्रतिक्रिया देता है. अगर ये दोनों फ़ील्ड मौजूद हैं, तो यह जियोहैश का हिसाब लगाता है और आउटपुट को दस्तावेज़ की आउटपुट की जगह पर लिखता है. इनपुट दस्तावेज़ users/{uid} कॉन्सटेंट से तय किया जाता है. इसका मतलब है कि फ़ंक्शन, users/ कलेक्शन में लिखे गए हर दस्तावेज़ को पढ़ता है. इसके बाद, उन दस्तावेज़ों के लिए जियोहैश प्रोसेस करता है. इसके बाद, यह हैश को उसी दस्तावेज़ के हैश फ़ील्ड में आउटपुट करता है.

कॉल करने लायक फ़ंक्शन

index.ts फ़ाइल में अगला फ़ंक्शन इस तरह दिखता है:

इंडेक्स.

export const callableHash = onCall((data, context) => {
  if (context.auth == undefined) {
    return {error: "Only authorized users are allowed to call this endpoint"};
  }
  const x = data[xField];
  const y = data[yField];
  if (x == undefined || y == undefined) {
    return {error: "Either x or y parameter was not declared"};
  }
  const result = service.convertToHash(x, y);
  if (result.status != ResultStatusCode.ok) {
    return {error: `Something went wrong ${result.message}`};
  }
  return {result: result.hash};
});

onCall फ़ंक्शन पर ध्यान दें. इससे पता चलता है कि यह फ़ंक्शन एक कॉल करने लायक फ़ंक्शन है, जिसे आपके क्लाइंट ऐप्लिकेशन कोड से कॉल किया जा सकता है. कॉल करने लायक यह फ़ंक्शन, x और y पैरामीटर लेता है और जियोहैश नतीजे दिखाता है. हालांकि, इस कोडलैब को सीधे तौर पर इस कोडलैब में कॉल नहीं किया जाएगा, लेकिन इसे Firebase एक्सटेंशन में कॉन्फ़िगर करने के लिए, उदाहरण के तौर पर यहां शामिल किया गया है.

4. extensions.yaml फ़ाइल सेट अप करना

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

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

  1. पहले डाउनलोड किए गए प्रोजेक्ट की रूट डायरेक्ट्री में extension.yaml फ़ाइल बनाएं. इन्हें जोड़कर शुरू करें:
name: geohash-ext
version: 0.0.1
specVersion: v1beta  # Firebase Extensions specification version (do not edit)

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

  1. YAML फ़ाइल में उपयोगकर्ता को आसानी से समझ में आने वाली जानकारी जोड़ें:
...

displayName: Latitude and longitude to GeoHash converter
description: A converter for changing your Latitude and longitude coordinates to geohashes.

जब डेवलपर आपके एक्सटेंशन के साथ इंटरैक्ट करते हैं, तो डिसप्ले नेम आपके एक्सटेंशन के नाम को सही तरीके से दिखाता है. एक्सटेंशन, एक्सटेंशन के काम करने के तरीके की खास जानकारी देता है. जब एक्सटेंशन को extensions.dev पर डिप्लॉय किया जाता है, तो यह कुछ ऐसा दिखता है:

Geohash Converter एक्सटेंशन, जैसा कि extensions.dev पर देखा गया है

  1. अपने एक्सटेंशन में कोड के लिए लाइसेंस की जानकारी दें.
...

license: Apache-2.0  # The license you want for the extension
  1. बताएं कि एक्सटेंशन किसने लिखा था और इसे इंस्टॉल करने के लिए बिलिंग की ज़रूरत है या नहीं:
...

author:
  authorName: AUTHOR_NAME
  url: https://github.com/Firebase

billingRequired: true

author सेक्शन का इस्तेमाल, उपयोगकर्ताओं को यह बताने के लिए किया जाता है कि एक्सटेंशन से जुड़ी समस्याएं आने पर या उन्हें इसके बारे में ज़्यादा जानकारी चाहिए या नहीं. ऐसा होने पर, वे किससे संपर्क कर सकते हैं. billingRequired एक ज़रूरी पैरामीटर है और इसे true पर सेट किया जाना चाहिए, क्योंकि सभी एक्सटेंशन Cloud Functions पर निर्भर होते हैं, जिसके लिए ब्लेज़ प्लान की ज़रूरत होती है.

इसमें इस एक्सटेंशन की पहचान करने के लिए, extension.yaml फ़ाइल में ज़रूरी फ़ील्ड की कम से कम संख्या शामिल है. एक्सटेंशन में दी जा सकने वाली पहचान ज़ाहिर करने वाली दूसरी जानकारी के बारे में ज़्यादा जानने के लिए, दस्तावेज़ देखें.

5. Cloud Functions कोड को एक्सटेंशन संसाधन में बदलें

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

उपयोगकर्ता की ओर से तय किए गए डिप्लॉयमेंट की जगह

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

extension.yaml

अब आप फ़ंक्शन संसाधन के लिए कॉन्फ़िगरेशन लिखने के लिए तैयार हैं.

  1. 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 है, जो इस फ़ंक्शन से जुड़ी है. फ़िलहाल, एक्सटेंशन जिन सुविधाओं के साथ काम करता है उनकी डुप्लीकेट कॉपी बनाने के लिए, providers/cloud.firestore/eventTypes/document.write के eventType का इस्तेमाल करें. इसकी जानकारी, अपने एक्सटेंशन के लिए Cloud Functions लिखें दस्तावेज़ में दी गई है. resource को दस्तावेज़ों की जगह के तौर पर बताया जाता है. आपका मौजूदा लक्ष्य, कोड में मौजूद जानकारी का डुप्लीकेट वर्शन बनाना है. इसलिए, दस्तावेज़ का पाथ, users/{uid} के हिसाब से काम करेगा. साथ ही, इसमें डेटाबेस की डिफ़ॉल्ट लोकेशन भी होगी.

  1. एक्सटेंशन को Firestore डेटाबेस के लिए पढ़ने और लिखने की अनुमतियां चाहिए. extension.yaml फ़ाइल के सबसे आखिर में, आईएएम की उन भूमिकाओं के बारे में बताएं जिनका ऐक्सेस एक्सटेंशन के पास होना चाहिए, ताकि डेवलपर के Firebase प्रोजेक्ट में मौजूद डेटाबेस के साथ काम किया जा सके.
roles:
  - role: datastore.user
    reason: Allows the extension to read / write to your Firestore instance.

datastore.user भूमिका, एक्सटेंशन के लिए इस्तेमाल की जा सकने वाली IAM भूमिकाओं की सूची से मिलती है. एक्सटेंशन, पढ़ने और लिखने वाला है, इसलिए datastore.user की भूमिका यहां सही है.

  1. कॉल करने लायक फ़ंक्शन भी जोड़ा जाना चाहिए. extension.yaml फ़ाइल में, रिसॉर्स प्रॉपर्टी में जाकर एक नया संसाधन बनाएं. ये प्रॉपर्टी, खास तौर पर कॉल किए जा सकने वाले फ़ंक्शन के लिए हैं:
  - name: callableHash
    type: firebaseextensions.v1beta.function
    properties:
      httpsTrigger: {}

हालांकि, पिछले संसाधन में eventTrigger का इस्तेमाल किया गया था, लेकिन यहां आपने httpsTrigger का इस्तेमाल किया है. इसमें, कॉल किए जा सकने वाले फ़ंक्शन और एचटीटीपीएस, दोनों फ़ंक्शन के बारे में जानकारी दी गई है.

कोड की जांच

यह बहुत ज़्यादा कॉन्फ़िगरेशन था, ताकि 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 एम्युलेटर का इस्तेमाल करके इसे आज़मा सकें!

  1. अगर आपने पहले से ऐसा नहीं किया है, तो डाउनलोड किए गए एक्सटेंशन प्रोजेक्ट के फ़ंक्शन फ़ोल्डर में npm run build को कॉल करें.
  2. अपने होस्ट सिस्टम पर एक नई डायरेक्ट्री बनाएं और firebase init का इस्तेमाल करके उस डायरेक्ट्री को अपने Firebase प्रोजेक्ट से जोड़ें.
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.
  1. उसी डायरेक्ट्री से, firebase ext:install चलाएं. /path/to/extension को उस डायरेक्ट्री के ऐब्सलूट पाथ से बदलें जिसमें आपकी extension.yaml फ़ाइल है.
firebase ext:install /path/to/extension
    This command does two things:
  • यह आपको एक्सटेंशन इंस्टेंस के लिए कॉन्फ़िगरेशन तय करने का निर्देश देता है. इससे एक *.env फ़ाइल बन जाती है, जिसमें इंस्टेंस की कॉन्फ़िगरेशन की जानकारी होती है.
  • यह एक्सटेंशन इंस्टेंस को आपके firebase.json के extensions सेक्शन में जोड़ देता है. यह एक्सटेंशन वर्शन के इंस्टेंस आईडी के मैप के तौर पर काम करता है.
  • प्रोजेक्ट को स्थानीय तौर पर डिप्लॉय किया जा रहा है. इसलिए, आपके पास यह तय करने का विकल्प है कि आपको Google Cloud सीक्रेट मैनेजर के बजाय, किसी स्थानीय फ़ाइल का इस्तेमाल करना है.

एक्सटेंशन इंस्टॉल करने की प्रोसेस का स्क्रीनशॉट, जिसमें यह दिखाया गया है कि इस एक्सटेंशन को इंस्टॉल करते समय, सीक्रेट के लिए लोकल फ़ाइल का इस्तेमाल किया जा रहा है

  1. नए कॉन्फ़िगरेशन के साथ Firebase एम्युलेटर शुरू करें:
firebase emulators:start
  1. emulators:start चलाने के बाद, एम्युलेटर के वेबव्यू में Firestore टैब पर जाएं.
  2. users कलेक्शन में कोई दस्तावेज़ जोड़ें. इसके लिए, xv नंबर फ़ील्ड और yv नंबर फ़ील्ड का इस्तेमाल करें.

वाक्यांश वाला संग्रह आईडी वाला संग्रह शुरू करने के लिए Firebase एम्युलेटर में दिखने वाला एक डायलॉग बॉक्स

  1. अगर एक्सटेंशन इंस्टॉल हो गया है, तो एक्सटेंशन, दस्तावेज़ में hash नाम का एक नया फ़ील्ड बना देता है.

उपयोगकर्ताओं का कलेक्शन, जिसमें उपयोगकर्ता का ऐसा दस्तावेज़ होता है जिसमें xv, yv, और हैश फ़ील्ड मौजूद होता है.

एक ही समय पर अलग-अलग अपॉइंटमेंट बुक किए जाने से बचने के लिए, स्टोरेज खाली करना

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

एक्सटेंशन की मदद से, एक ही एक्सटेंशन के कई वर्शन एक साथ इंस्टॉल किए जा सकते हैं. इसलिए, अनइंस्टॉल करके यह पक्का किया जा सकता है कि पहले से इंस्टॉल किए गए एक्सटेंशन में कोई अंतर नहीं है.

firebase ext:uninstall geohash-ext

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

6. एक्सटेंशन को उपयोगकर्ता कॉन्फ़िगर करने योग्य बनाएं

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

extension.yaml फ़ाइल में बेसिक पैरामीटर तय करें

उन आइटम को कन्वर्ट करें जो डेवलपर के पास कस्टम कॉन्फ़िगरेशन हो सकते हैं. पहला पैरामीटर, XFIELD और YFIELD पैरामीटर होगा.

  1. extension.yaml फ़ाइल में, यह कोड जोड़ें. यह कोड XFIELD और YFIELD फ़ील्ड पैरामीटर का इस्तेमाल करता है. ये पैरामीटर, पहले से तय की गई params YAML प्रॉपर्टी में मौजूद होते हैं:

extension.yaml

params:
  - param: XFIELD
    label: The X Field Name
    description: >-
      The X Field is also known as the **longitude** value. What does
      your Firestore instance refer to as the X value or the longitude
      value. If no value is specified, the extension searches for
      field 'xv'.
    type: string
    validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
    validationErrorMessage: >-
      The field can only contain uppercase or lowercase letter, numbers,
      _, and . characters and must be less than 1500 bytes long. The field
      must also not start with a number.
    default: xv
    required: false
    immutable: false
    example: xv
  - param: YFIELD
    label: The Y Field Name
    description: >-
      The Y Field is also known as the **latitude** value. What does
      your Firestore instance refer to as the Y value or the latitude
      value. If no value is specified, the extension searches for
      field 'yv'.
    type: string
    validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
    validationErrorMessage: >-
      The field can only contain uppercase or lowercase letter, numbers,
      _, and . characters and must be less than 1500 bytes long. The field
      must also not start with a number.
    default: yv
    required: false
    immutable: false
    example: yv
  • param पैरामीटर को ऐसे नाम देता है जो आपको एक्सटेंशन प्रोड्यूसर को दिखता है. बाद में, पैरामीटर वैल्यू तय करते समय इस वैल्यू का इस्तेमाल करें.
  • label एक ऐसा आइडेंटिफ़ायर है जिसे कोई भी व्यक्ति आसानी से पढ़ सकता है. इससे डेवलपर को पता चलता है कि पैरामीटर क्या करता है.
  • description से वैल्यू के बारे में पूरी जानकारी मिलती है. इससे मार्कडाउन की सुविधा काम करती है, इसलिए यह अतिरिक्त दस्तावेज़ से जुड़ा हो सकता है या इससे उन शब्दों को हाइलाइट किया जा सकता है जो डेवलपर के लिए ज़रूरी हो सकते हैं.
  • type वह इनपुट मैकेनिज़्म तय करता है, जिससे यह पता चलता है कि उपयोगकर्ता पैरामीटर वैल्यू को कैसे सेट करेगा. कई टाइप मौजूद हैं. इनमें string, select, multiSelect, selectResource, और secret शामिल हैं. इनमें से हर विकल्प के बारे में ज़्यादा जानने के लिए, दस्तावेज़ देखें.
  • VerifyationRegex, डेवलपर एंट्री को किसी खास रेगुलर एक्सप्रेशन वैल्यू के लिए सीमित करता है (उदाहरण में, यह यहां बताए गए फ़ील्ड के आसान नाम वाले दिशा-निर्देशों पर आधारित है); और अगर यह काम नहीं करता है...
  • validationErrorMessage की मदद से डेवलपर को फ़ेल होने की वैल्यू के बारे में पता चलता है.
  • अगर डेवलपर कोई टेक्स्ट नहीं डालता है, तो default वैल्यू वही होगी.
  • ज़रूरी का मतलब है कि डेवलपर को कुछ भी लिखने की ज़रूरत नहीं है.
  • नहीं बदला जा सकता, डेवलपर इस एक्सटेंशन को अपडेट करने और इस वैल्यू को बदलने की अनुमति देता है. इस मामले में, डेवलपर के पास ज़रूरी शर्तों में बदलाव होने पर, फ़ील्ड के नाम बदलने की अनुमति होनी चाहिए.
  • example से पता चलता है कि एक मान्य इनपुट कैसा दिख सकता है.

यह समझने में बहुत बड़ी बात थी!

  1. कोई खास पैरामीटर जोड़ने से पहले, 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

संवेदनशील पैरामीटर तय करना

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

  • extension.yaml फ़ाइल में, यह कोड जोड़ें:

extension.yaml

  - param: APIKEY
    label: GeohashService API Key
    description: >-
      Your geohash service API Key. Since this is a demo, and not a real
      service, you can use : 1234567890.
    type: secret
    required: true
    immutable: false

resource पैरामीटर का इस्तेमाल करने के लिए एट्रिब्यूट अपडेट करें

जैसा कि पहले बताया गया था, रिसॉर्स (फ़ंक्शन नहीं) यह बताता है कि रिसॉर्स की निगरानी कैसे की जाती है. इसलिए, नए पैरामीटर का इस्तेमाल करने के लिए locationUpdate रिसॉर्स को अपडेट करना ज़रूरी है.

  • extension.yaml फ़ाइल में, यह कोड जोड़ें:

extension.yaml

## Change from this
  - name: locationUpdate
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: providers/cloud.firestore/eventTypes/document.write
        resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}]

## To this
  - name: locationUpdate
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: providers/cloud.firestore/eventTypes/document.write
        resource: projects/${PROJECT_ID}/databases/(default)/documents/${INPUTPATH}

extension.yaml फ़ाइल की जांच करें

  • extension.yaml फ़ाइल की जांच करें. यह कुछ ऐसी नज़र आनी चाहिए:

extension.yaml

name: geohash-ext
version: 0.0.1
specVersion: v1beta  # Firebase Extensions specification version (do not edit)

displayName: Latitude and Longitude to GeoHash converter
description: A converter for changing your Latitude and Longitude coordinates to geohashes.

license: Apache-2.0  # The license you want to use for the extension

author:
  authorName: Sparky
  url: https://github.com/Firebase

billingRequired: true

params:
  - param: XFIELD
    label: The X Field Name
    description: >-
      The X Field is also known as the **longitude** value. What does
      your Firestore instance refer to as the X value or the longitude
      value. If you don't provide a value for this field, the extension will use 'xv' as the default value.
    type: string
    validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
    validationErrorMessage: >-
      The field can only contain uppercase or lowercase letter, numbers,
      _, and . characters and must be less than 1500 bytes long. The field
      must also not start with a number.
    default: xv
    required: false
    immutable: false
    example: xv
  - param: YFIELD
    label: The Y Field Name
    description: >-
      The Y Field is also known as the **latitude** value. What does
      your Firestore instance refer to as the Y value or the latitude
      Value. If you don't provide a value for this field, the extension will use 'yv' as the default value.
    type: string
    validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
    validationErrorMessage: >-
      The field can only contain uppercase or lowercase letter, numbers,
      _, and . characters and must be less than 1500 bytes long. The field
      must also not start with a number.
    default: yv
    required: false
    immutable: false
    example: yv
  - param: INPUTPATH
    label: The input document to listen to for changes
    description: >-
      This is the document where you write an x and y value to. Once
      that document has been modified, it notifies the extension to
      compute a geohash and store that in an output document in a certain
      field. This accepts function [wildcard parameters](https://firebase.google.com/docs/functions/firestore-events#wildcards-parameters)
    type: string
    validationRegex: ^[^/]+(/[^/]*/[^/]*)*/[^/]+$
    validationErrorMessage: >-
      This must point to a document path, not a collection path from the root
      of the database. It must also not start or end with a '/' character.
    required: true
    immutable: false
    example: users/{uid}
  - param: OUTPUTFIELD
    label: Geohash field
    description: >-
      This specifies the field in the output document to store the geohash in.
    type: string
    validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
    validationErrorMessage: >-
      The field can only contain uppercase or lowercase letter, numbers,
      _, and . characters and must be less than 1500 bytes long. The field
      must also not start with a number.
    required: false
    default: hash
    immutable: false
    example: hash
  - param: APIKEY
    label: GeohashService API Key
    description: >-
      Your geohash service API Key. Since this is a demo, and not a real
      service, you can use : 1234567890.
    type: secret
    required: true
    immutable: false

resources:
  - name: locationUpdate
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: providers/cloud.firestore/eventTypes/document.write
        resource: projects/${PROJECT_ID}/databases/(default)/documents/${INPUTPATH}
  - name: callableHash
    type: firebaseextensions.v1beta.function
    properties:
      httpsTrigger: {}

roles:
  - role: datastore.user
    reason: Allows the extension to read / write to your Firestore instance.

कोड में ऐक्सेस पैरामीटर

अब सभी पैरामीटर, extension.yaml फ़ाइल में कॉन्फ़िगर हो गए हैं, इसलिए उन्हें index.ts फ़ाइल में जोड़ें.

  • index.ts फ़ाइल में, डिफ़ॉल्ट वैल्यू को process.env.PARAMETER_NAME से बदलें. इससे पैरामीटर की सही वैल्यू फ़ेच की जाती हैं और उन्हें डेवलपर के Firebase प्रोजेक्ट पर डिप्लॉय किए गए फ़ंक्शन कोड में अपने-आप भर दिया जाता है.

index.ts

// Replace this:
const documentPath = "users/{uid}";
const xField = "xv";
const yField = "yv";
const apiKey = "1234567890";
const outputField = "hash";

// with this:
const documentPath = process.env.INPUTPATH!; // this value is ignored since its read from the resource
const xField = process.env.XFIELD!;
const yField = process.env.YFIELD!;
const apiKey = process.env.APIKEY!;
const outputField = process.env.OUTPUTFIELD!;

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

7. उपयोगकर्ता दस्तावेज़ बनाएं

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

  1. सबसे पहले PREINSTALL.md फ़ाइल बनाएं. इस फ़ाइल का इस्तेमाल, ऐप्लिकेशन के काम करने के तरीके, उसे इंस्टॉल करने से जुड़ी ज़रूरी शर्तों, और बिलिंग की संभावित बातों के बारे में बताने के लिए किया जाता है.

PREINSTALL.md

Use this extension to automatically convert documents with a latitude and
longitude to a geohash in your database. Additionally, this extension includes a callable function that allows users to make one-time calls
to convert an x,y coordinate into a geohash.

Geohashing is supported for latitudes between 90 and -90 and longitudes
between 180 and -180.

#### Third Party API Key

This extension uses a fictitious third-party API for calculating the
geohash. You need to supply your own API keys. (Since it's fictitious,
you can use 1234567890 as an API key).

#### Additional setup

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

After installing this extension, you'll need to:

- Update your client code to point to the callable geohash function if you
want to perform arbitrary geohashes.

Detailed information for these post-installation tasks are provided after
you install this extension.

#### Billing
To install an extension, your project must be on the [Blaze (pay as you
go) plan](https://firebase.google.com/pricing)

- This extension uses other Firebase and Google Cloud Platform services,
which have associated charges if you exceed the service's no-cost tier:
 - Cloud Firestore
 - Cloud Functions (Node.js 16+ runtime. [See
FAQs](https://firebase.google.com/support/faq#extensions-pricing))
 - [Cloud Secret Manager](https://cloud.google.com/secret-manager/pricing)
  1. इस प्रोजेक्ट के लिए README.md लिखने में लगने वाला समय बचाने के लिए, आसान तरीका इस्तेमाल करें:
firebase ext:info . --markdown > README.md

इसमें आपकी PREINSTALL.md फ़ाइल के कॉन्टेंट और आपकी extension.yaml फ़ाइल में मौजूद एक्सटेंशन के बारे में अन्य जानकारी शामिल होती है.

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

  1. 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 एम्युलेटर की मदद से इंस्टॉल और टेस्ट करना

  1. अपने होस्ट सिस्टम पर एक नई डायरेक्ट्री बनाएं और firebase init का इस्तेमाल करके उस डायरेक्ट्री को अपने Firebase प्रोजेक्ट से जोड़ें.
mkdir sample-proj
cd sample-proj
firebase init --project=projectID-or-alias
  1. एक्सटेंशन इंस्टॉल करने के लिए, उस डायरेक्ट्री से firebase ext:install चलाएं. /path/to/extension को उस डायरेक्ट्री के ऐब्सलूट पाथ से बदलें जिसमें आपकी extension.yaml फ़ाइल है. इससे आपके एक्सटेंशन के लिए इंस्टॉलेशन की प्रोसेस शुरू हो जाती है और एक .env फ़ाइल बन जाती है, जिसमें Firebase या एम्युलेटर में कॉन्फ़िगरेशन को पुश करने से पहले आपके कॉन्फ़िगरेशन शामिल होते हैं.
firebase ext:install /path/to/extension
  • प्रोजेक्ट को स्थानीय तौर पर डिप्लॉय किया जा रहा है. इसलिए, यह बताएं कि आपको Google Cloud के सीक्रेट मैनेजर के बजाय, किसी लोकल फ़ाइल का इस्तेमाल करना है.

da928c65ffa8ce15.png

  1. लोकल एम्युलेटर सुइट शुरू करें:
firebase emulators:start

असली Firebase प्रोजेक्ट की मदद से इंस्टॉल करें और टेस्ट करें

आपके पास अपने एक्सटेंशन को असल Firebase प्रोजेक्ट में इंस्टॉल करने का विकल्प होता है. हमारा सुझाव है कि आप टेस्ट करने के लिए, किसी टेस्ट प्रोजेक्ट का इस्तेमाल करें. अगर आपको अपने एक्सटेंशन के एंड-टू-एंड फ़्लो की जांच करनी है या आपके एक्सटेंशन का ट्रिगर अभी तक Firebase एम्युलेटर सुइट पर काम नहीं करता है, तो इस टेस्टिंग वर्कफ़्लो का इस्तेमाल करें (एक्सटेंशन एम्युलेटर विकल्प देखें). एम्युलेटर पर, फ़िलहाल Cloud Firestore, रीयलटाइम डेटाबेस, और Pub/Sub के लिए, एचटीटीपी अनुरोध से ट्रिगर किए गए फ़ंक्शन और बैकग्राउंड इवेंट से ट्रिगर किए गए फ़ंक्शन का इस्तेमाल किया जा सकता है.

  1. अपने होस्ट सिस्टम पर एक नई डायरेक्ट्री बनाएं और firebase init का इस्तेमाल करके उस डायरेक्ट्री को अपने Firebase प्रोजेक्ट से जोड़ें.
cd ..
mkdir sample-proj
cd sample-proj
firebase init --project=projectID-or-alias
  1. इसके बाद, उस डायरेक्ट्री से एक्सटेंशन इंस्टॉल करने के लिए, firebase ext:install चलाएं. /path/to/extension को उस डायरेक्ट्री के ऐब्सलूट पाथ से बदलें जिसमें आपकी extension.yaml फ़ाइल है. इससे आपके एक्सटेंशन के लिए इंस्टॉलेशन की प्रोसेस शुरू हो जाती है और एक .env फ़ाइल बन जाती है, जिसमें Firebase या एम्युलेटर में कॉन्फ़िगरेशन को पुश करने से पहले आपके कॉन्फ़िगरेशन शामिल होते हैं.
firebase ext:install /path/to/extension
  • आपको Firebase को सीधे तौर पर डिप्लॉय करना है और Google Cloud Secret Manager का इस्तेमाल करना है. इसलिए, एक्सटेंशन इंस्टॉल करने से पहले आपको Secret Manager API चालू करना होगा.
  1. अपने Firebase प्रोजेक्ट में डिप्लॉय करें.
firebase deploy

एक्सटेंशन की जांच करना

  1. firebase deploy या firebase emulators:start चलाने के बाद, ज़रूरत के मुताबिक Firebase कंसोल या एम्युलेटर के वेबव्यू के Firestore टैब पर जाएं.
  2. x फ़ील्ड और y फ़ील्ड के ज़रिए तय किए गए कलेक्शन में कोई दस्तावेज़ जोड़ें. इस मामले में, अपडेट किए गए दस्तावेज़ u/{uid} में हैं. इनमें x फ़ील्ड xv और y फ़ील्ड yv है.

Firestore रिकॉर्ड जोड़ने के लिए, Firebase एम्युलेटर स्क्रीन

  1. अगर एक्सटेंशन इंस्टॉल हो गया है, तो दोनों फ़ील्ड को सेव करने के बाद एक्सटेंशन, दस्तावेज़ में hash नाम से एक नया फ़ील्ड बना देता है.

एम्युलेटर की डेटाबेस स्क्रीन, जिसमें हैश किया गया डेटा दिख रहा है

8. बधाई हो!

आपने अपने पहले Cloud Function को Firebase एक्सटेंशन में बदल दिया है!

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

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

आगे क्या होगा?