شروع به ساخت یک افزونه کنید

این صفحه شما را از طریق مراحل مورد نیاز برای ساختن یک افزونه Firebase ساده راهنمایی می کند که می توانید آن را در پروژه های خود نصب کنید یا با دیگران به اشتراک بگذارید. این مثال ساده از یک افزونه Firebase، پایگاه داده Realtime شما را برای پیام‌ها مشاهده می‌کند و آنها را به حروف بزرگ تبدیل می‌کند.

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. دستور ext:dev:init Firebase CLI را اجرا کنید:

    firebase ext:dev:init
    

    وقتی از شما خواسته شد، جاوا اسکریپت را به‌عنوان زبان توابع انتخاب کنید (اما توجه داشته باشید که می‌توانید هنگام توسعه برنامه افزودنی خود نیز از TypeScript استفاده کنید)، و وقتی از شما خواسته شد که وابستگی‌ها را نصب کنید، به «بله» پاسخ دهید. (پیش‌فرض‌ها را برای هر گزینه دیگری بپذیرید.) این دستور یک پایگاه کد اسکلت برای یک برنامه افزودنی جدید راه‌اندازی می‌کند، که از آن می‌توانید توسعه برنامه افزودنی خود را شروع کنید.

2. پسوند مثال را با استفاده از شبیه ساز امتحان کنید

هنگامی که Firebase CLI فهرست برنامه های افزودنی جدید را مقداردهی اولیه کرد، یک تابع مثال ساده و یک پوشه integration-tests ایجاد کرد که حاوی فایل های لازم برای اجرای یک برنامه افزودنی با استفاده از مجموعه شبیه ساز Firebase است.

پسوند نمونه را در شبیه ساز اجرا کنید:

  1. تغییر به دایرکتوری integration-tests :

    cd functions/integration-tests
    
  2. شبیه ساز را با یک پروژه آزمایشی شروع کنید:

    firebase emulators:start --project=demo-test
    

    شبیه ساز برنامه افزودنی را در یک پروژه از پیش تعریف شده "ساختگی" بارگذاری می کند ( demo-test ). برنامه افزودنی تا کنون از یک تابع راه‌اندازی HTTP، greetTheWorld تشکیل شده است که در صورت دسترسی، پیام «سلام جهان» را برمی‌گرداند.

  3. در حالی که شبیه ساز هنوز در حال اجرا است، تابع greetTheWorld افزونه را با مراجعه به URL که هنگام شروع آن چاپ شده است، امتحان کنید.

    مرورگر شما پیام "Hello World from greet-the-world" را نمایش می دهد.

  4. کد منبع این تابع در فهرست functions برنامه افزودنی است. منبع را در ویرایشگر یا IDE انتخابی خود باز کنید:

    functions/index.js

    const functions = require("firebase-functions");
    
    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. هنگامی که شبیه ساز در حال اجرا است، به طور خودکار هر تغییری را که در کد توابع خود ایجاد می کنید بارگیری می کند. سعی کنید یک تغییر کوچک در تابع 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 Function بنویسید و آن را به عنوان یک منبع افزونه اعلام کنید

حالا می توانید شروع به نوشتن چند کد کنید. در این مرحله، یک Cloud Function می نویسید که وظیفه اصلی برنامه افزودنی شما را انجام می دهد، یعنی مشاهده پایگاه داده Realtime شما برای پیام ها و تبدیل آنها به حروف بزرگ.

  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 به عنوان تنها عملکرد ابری برنامه افزودنی اعلام کرد. اکنون که آن را با 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 به عنوان یک راه‌انداز استفاده می‌کند، باید پیکربندی شبیه‌ساز خود را به‌روزرسانی کنید تا شبیه‌ساز 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 برنامه افزودنی باید یک رکورد فرزند را با محتوای "upper": "RECIPE" . برای تأیید نتایج مورد انتظار، به گزارش‌ها و برگه‌های پایگاه داده رابط کاربری شبیه‌ساز نگاهی بیندازید.

    3. سعی کنید چند فرزند دیگر را به گره messages اضافه کنید ( {"original":"any text"} ). هر زمان که یک رکورد جدید اضافه می کنید، برنامه افزودنی باید یک فیلد uppercase حاوی محتویات حروف بزرگ فیلد original اضافه کند.

اکنون یک برنامه افزودنی کامل، هرچند ساده، دارید که بر روی یک نمونه RTDB کار می کند. در بخش‌های بعدی، این افزونه را با برخی ویژگی‌های اضافی اصلاح خواهید کرد. سپس، برنامه افزودنی را برای توزیع به دیگران آماده خواهید کرد و در نهایت، نحوه انتشار برنامه افزودنی خود را در Extensions Hub یاد خواهید گرفت.

5. API ها و نقش ها را اعلام کنید

Firebase به هر نمونه از یک برنامه افزودنی نصب شده دسترسی محدود به پروژه و داده های آن را با استفاده از یک حساب سرویس هر نمونه اعطا می کند. هر حساب دارای حداقل مجموعه مجوزهای مورد نیاز برای فعالیت است. به همین دلیل، شما باید به صراحت هر نقش IAM مورد نیاز برنامه افزودنی خود را اعلام کنید. وقتی کاربران برنامه افزودنی شما را نصب می‌کنند، Firebase یک حساب سرویس با این نقش‌ها ایجاد می‌کند و از آن برای اجرای برنامه افزودنی استفاده می‌کند.

برای فعال کردن رویدادهای یک محصول، نیازی به اعلام نقش ندارید، اما باید نقشی را برای تعامل با آن اعلام کنید. از آنجا که تابعی که در مرحله آخر اضافه کردید در پایگاه داده Realtime می نویسد، باید اعلان زیر را به extension.yaml اضافه کنید:

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

به طور مشابه، API های Google را که یک برنامه افزودنی در فیلد apis استفاده می کند، اعلام می کنید. هنگامی که کاربران برنامه افزودنی شما را نصب می کنند، از آنها پرسیده می شود که آیا می خواهند به طور خودکار این API ها را برای پروژه خود فعال کنند. این معمولاً فقط برای APIهای Google غیر Firebase ضروری است و برای این راهنما لازم نیست.

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 Extensions، این تغییر صرفاً برای مستندسازی است: وقتی یک Cloud Function به عنوان بخشی از یک برنامه افزودنی مستقر می‌شود، از تعریف ماشه از فایل extension.yaml استفاده می‌کند و مقدار مشخص‌شده در تعریف تابع را نادیده می‌گیرد. با این وجود، ایده خوبی است که در کد خود مستند کنید که این مقدار از کجا آمده است.

  4. ممکن است تغییر کدی که اثر زمان اجرا ندارد، ناامیدکننده باشد، اما درس مهمی که باید از آن حذف کرد این است که می‌توانید به هر پارامتر تعریف‌شده توسط کاربر در کد تابع خود دسترسی داشته باشید و از آن به عنوان یک مقدار معمولی در منطق تابع استفاده کنید. به عنوان اشاره ای به این قابلیت، عبارت log زیر را اضافه کنید تا نشان دهید که واقعاً به مقداری که کاربر تعریف کرده است دسترسی دارید:

    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 می‌تواند منطق ارائه‌شده توسط برنامه افزودنی شما را راه‌اندازی کند: ایجاد رکوردهای جدید در پایگاه داده Realtime عملکرد 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 انتخاب کنید و وابستگی های مورد نیاز را نصب کنید. این پروژه نشان دهنده پروژه یک کاربر است که پسوند شما را نصب کرده است.

  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 Extensions دارای یک ویژگی به نام قلاب رویداد چرخه حیات است که می‌توانید هنگام نصب، به‌روزرسانی یا پیکربندی مجدد برنامه افزودنی، برای فعال کردن اقدامات استفاده کنید. در این بخش، از قلاب‌های رویداد چرخه حیات برای پر کردن پایگاه داده پیام موجود پروژه با پیام‌های بزرگ، زمانی که کاربر برنامه افزودنی شما را نصب می‌کند، استفاده می‌کنید.

Firebase Extensions از Cloud Tasks برای اجرای مدیریت رویدادهای چرخه حیات شما استفاده می کند. شما کنترل کننده رویداد را با استفاده از توابع ابری تعریف می کنید. هر زمان که یک نمونه از برنامه افزودنی شما به یکی از رویدادهای چرخه حیات پشتیبانی شده برسد، اگر یک handler تعریف کرده باشید، کنترل کننده را به صف وظایف Cloud اضافه می کند. سپس 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.");
      }
    });
    

    توجه داشته باشید که تابع فقط چند رکورد را قبل از اینکه دوباره به صف کار اضافه شود پردازش می کند. این یک استراتژی متداول برای مقابله با وظایف پردازشی است که نمی‌توانند در پنجره زمان‌بندی یک عملکرد ابری کامل شوند. از آنجایی که نمی‌توانید پیش‌بینی کنید که کاربر در هنگام نصب برنامه افزودنی شما چند پیام ممکن است در پایگاه داده خود داشته باشد، این استراتژی مناسب است.

  2. در فایل extension.yaml ، تابع backfill خود را به عنوان یک منبع پسوندی که دارای ویژگی 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
    

    سپس در ابتدای تابع backfill، مقدار پارامتر 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. در پروژه جدید خود، پایگاه داده بلادرنگ را فعال کنید .
  4. از آنجایی که می‌خواهید توانایی برنامه افزودنی خود را برای تکمیل داده‌های موجود در هنگام نصب آزمایش کنید، برخی از داده‌های نمونه را به نمونه پایگاه داده بی‌درنگ خود وارد کنید:
    1. برخی از داده‌های RTDB را دانلود کنید.
    2. در صفحه Real-time Database کنسول Firebase، روی (بیشتر) > Import JSON کلیک کنید و فایلی را که به تازگی دانلود کرده اید انتخاب کنید.
  5. برای فعال کردن تابع backfill برای استفاده از متد 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 باید افزونه شما را در پروژه شما آپلود کرده و آن را نصب کند. پس از اتمام نصب، کار Backfill اجرا می شود و ظرف چند دقیقه، پایگاه داده شما با پیام های بزرگ به روز می شود. چند گره جدید به پایگاه داده پیام‌ها اضافه کنید و مطمئن شوید که برنامه افزودنی برای پیام‌های جدید نیز کار می‌کند.

10. مستندات را بنویسید

قبل از اینکه برنامه افزودنی خود را با کاربران به اشتراک بگذارید، مطمئن شوید که اسناد کافی برای موفقیت آنها ارائه می کنید.

هنگامی که پروژه برنامه افزودنی را مقداردهی اولیه کردید، Firebase CLI نسخه‌های خرد حداقل اسناد مورد نیاز را ایجاد کرد. این فایل‌ها را به‌روزرسانی کنید تا پسوندی که ساخته‌اید به‌طور دقیق منعکس شود.

extension.yaml

شما در حال به روز رسانی این فایل با توسعه این پسوند بوده اید، بنابراین در حال حاضر نیازی به به روز رسانی بیشتری ندارید.

با این حال، اهمیت مستندات موجود در این فایل را نادیده نگیرید. علاوه بر اطلاعات شناسایی حیاتی یک برنامه افزودنی - نام، توضیحات، نویسنده، مکان مخزن رسمی - فایل extension.yaml حاوی اسناد رو به رو کاربر برای هر منبع و پارامتر قابل تنظیم توسط کاربر است. این اطلاعات در اختیار کاربران کنسول Firebase، Extensions Hub و Firebase CLI قرار می‌گیرد.

PREINSTALL.md

در این فایل، اطلاعات مورد نیاز کاربر را قبل از نصب برنامه افزودنی خود ارائه دهید: به طور مختصر توضیح دهید که برنامه افزودنی چه کاری انجام می دهد، پیش نیازها را توضیح دهید و اطلاعات مربوط به پیامدهای صورتحساب نصب برنامه افزودنی را به کاربر ارائه دهید. اگر وب سایتی با اطلاعات اضافی دارید، این نیز مکان خوبی برای پیوند دادن آن است.

متن این فایل در Extensions Hub و توسط دستور 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 را برای کاربرانی که از مخزن برنامه افزودنی بازدید می‌کنند، ارائه می‌کنند. می توانید این فایل را با دست بنویسید یا با استفاده از دستور یک read me ایجاد کنید.

برای هدف این راهنما، از نوشتن یک فایل readme صرفنظر کنید.

اسناد اضافی

مستنداتی که در بالا مورد بحث قرار گرفت حداقل مجموعه اسنادی است که باید به کاربران ارائه دهید. بسیاری از برنامه های افزودنی به مستندات دقیق تری نیاز دارند تا کاربران بتوانند با موفقیت از آنها استفاده کنند. در این صورت، باید اسناد اضافی بنویسید و در جایی میزبانی کنید که بتوانید کاربران را به آن راهنمایی کنید.

برای هدف این راهنما، از نوشتن مستندات گسترده تر صرف نظر کنید.

11. در Extensions Hub منتشر کنید

اکنون که کد برنامه افزودنی شما کامل و مستند شده است، آماده به اشتراک گذاری آن با جهان در Extensions Hub هستید. اما از آنجایی که این فقط یک آموزش است، در واقع این کار را انجام ندهید. بروید و با استفاده از آنچه در اینجا و سایر اسناد ناشر Firebase Extensions آموخته‌اید، و با بررسی منبع برنامه‌های افزودنی رسمی، نوشته شده توسط Firebase، شروع به نوشتن برنامه افزودنی خود کنید.

هنگامی که آماده انتشار کار خود در Extensions Hub هستید، در اینجا نحوه انجام این کار را می‌بینید:

  1. اگر اولین برنامه افزودنی خود را منتشر می کنید، به عنوان ناشر برنامه افزودنی ثبت نام کنید . هنگامی که به عنوان ناشر برنامه های افزودنی ثبت نام می کنید، یک شناسه ناشر ایجاد می کنید که به کاربران امکان می دهد به سرعت شما را به عنوان نویسنده برنامه های افزودنی خود شناسایی کنند.
  2. کد منبع برنامه افزودنی خود را در مکانی قابل تأیید عمومی میزبانی کنید. وقتی کد شما از یک منبع قابل تأیید در دسترس است، Firebase می‌تواند برنامه افزودنی شما را مستقیماً از این مکان منتشر کند. انجام این کار به شما کمک می کند تا مطمئن شوید که نسخه منتشر شده فعلی برنامه افزودنی خود را منتشر می کنید و به کاربران کمک می کند تا کدی را که در حال نصب در پروژه های خود نصب می کنند بررسی کنند.

    در حال حاضر، این به معنای در دسترس قرار دادن برنامه افزودنی خود در یک مخزن عمومی GitHub است.

  3. برنامه افزودنی خود را با استفاده از فرمان firebase ext:dev:upload در Extensions Hub آپلود کنید.

  4. به داشبورد ناشر خود در کنسول Firebase بروید، افزونه‌ای را که اخیراً آپلود کرده‌اید پیدا کنید و روی «انتشار در مرکز برنامه‌های افزودنی» کلیک کنید. این درخواست از کارکنان بازبینی ما دارد که ممکن است چند روز طول بکشد. در صورت تایید، برنامه افزودنی در Extensions Hub منتشر خواهد شد. اگر رد شد، پیامی دریافت خواهید کرد که دلیل آن را توضیح می دهد. سپس می توانید به مشکلات گزارش شده رسیدگی کنید و مجددا برای بررسی ارسال کنید.