Uzantı oluşturmaya başlayın

Bu sayfada, projelerinize yükleyebileceğiniz veya başkalarıyla paylaşabileceğiniz basit bir Firebase uzantısı oluşturmak için gereken adımlar açıklanmaktadır. Bu basit Firebase uzantısı örneği, Realtime Database'inizdeki mesajları izler ve büyük harfe dönüştürür.

1. Ortamınızı ayarlama ve proje başlatma

Uzantı oluşturmaya başlamadan önce gerekli araçlarla bir derleme ortamı ayarlamanız gerekir.

  1. Node.js 16 veya daha yeni bir sürümü yükleyin. Node'u yüklemenin bir yolu nvm (veya nvm-windows) kullanmaktır.

  2. Firebase CLI'nin en son sürümünü yükleyin veya bu sürüme güncelleyin. npm kullanarak yüklemek veya güncellemek için şu komutu çalıştırın:

    npm install -g firebase-tools

Şimdi yeni bir uzantı projesi başlatmak için Firebase CLI'yı kullanın:

  1. Uzantınız için bir dizin oluşturun ve cd içine gidin:

    mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
  2. Firebase CLI'nın ext:dev:init komutunu çalıştırın:

    firebase ext:dev:init

    İstendiğinde işlevler için dil olarak JavaScript'i seçin (ancak kendi uzantınızı geliştirirken TypeScript'i de kullanabileceğinizi unutmayın) ve bağımlılıkları yüklemeniz istendiğinde "yes" (evet) yanıtını verin. (Diğer seçenekler için varsayılan değerleri kabul edin.) Bu komut, yeni bir uzantı için iskelet kod tabanı oluşturur. Bu kod tabanını kullanarak uzantınızı geliştirmeye başlayabilirsiniz.

2. Emülatörü kullanarak örnek uzantıyı deneme

Firebase CLI, yeni uzantılar dizinini başlattığında basit bir örnek işlev ve Firebase Emulator Suite'i kullanarak uzantı çalıştırmak için gereken dosyaları içeren bir integration-tests dizini oluşturdu.

Örnek uzantıyı emülatörde çalıştırmayı deneyin:

  1. integration-tests dizinine geçin:

    cd functions/integration-tests
  2. Emülatörü bir demo projesiyle başlatın:

    firebase emulators:start --project=demo-test

    Emülatör, uzantıyı önceden tanımlanmış bir "sahte" projeye (demo-test) yükler. Uzantı şu ana kadar tek bir HTTP tetikli işlevden (greetTheWorld) oluşur. Bu işlev, erişildiğinde "hello world" mesajını döndürür.

  3. Emülatör çalışmaya devam ederken, uzantıyı başlattığınızda yazdırdığı URL'yi ziyaret ederek greetTheWorld işlevini deneyin.

    Tarayıcınızda "Hello World from greet-the-world" mesajı gösterilir.

  4. Bu işlevin kaynak kodu, uzantının functions dizinindedir. Kaynağı istediğiniz düzenleyicide veya IDE'de açın:

    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. Emülatör çalışırken, Functions kodunuzda yaptığınız değişiklikler otomatik olarak yeniden yüklenir. greetTheWorld işlevinde küçük bir değişiklik yapmayı deneyin:

    functions/index.js

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

    Yaptığınız değişiklikleri kaydedin. Emülatör, kodunuzu yeniden yükler. Artık işlev URL'sini ziyaret ettiğinizde güncellenmiş selamlama mesajını görürsünüz.

3. extension.yaml dosyasına temel bilgiler ekleme

Geliştirme ortamınızı ayarlayıp uzantı emülatörünü çalıştırdığınıza göre artık kendi uzantınızı yazmaya başlayabilirsiniz.

İlk adım olarak, önceden tanımlanmış uzantı meta verilerini greet-the-world yerine yazmak istediğiniz uzantıyı yansıtacak şekilde düzenleyin. Bu meta veriler extension.yaml dosyasında saklanır.

  1. Düzenleyicinizde extension.yaml dosyasını açın ve dosyanın tüm içeriğini aşağıdakilerle değiştirin:

    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 alanında kullanılan adlandırma kuralına dikkat edin: Resmi Firebase uzantıları, uzantının üzerinde çalıştığı birincil Firebase ürününü belirten bir önekle adlandırılır ve ardından uzantının ne yaptığına dair bir açıklama gelir. Kendi uzantılarınızda da aynı kuralı kullanmalısınız.

  2. Uzantınızın adını değiştirdiğiniz için emülatör yapılandırmanızı da yeni adla güncellemeniz gerekir:

    1. functions/integration-tests/firebase.json içinde greet-the-world ifadesini rtdb-uppercase-messages olarak değiştirin.
    2. functions/integration-tests/extensions/greet-the-world.env öğesini functions/integration-tests/extensions/rtdb-uppercase-messages.env olarak yeniden adlandırın.

Uzantı kodunuzda greet-the-world uzantısının bazı kalıntıları hâlâ mevcut ancak bunları şimdilik bırakın. Bunları sonraki birkaç bölümde güncelleyeceksiniz.

4. Cloud Functions işlevi yazma ve bunu uzantı kaynağı olarak bildirme

Artık kod yazmaya başlayabilirsiniz. Bu adımda, uzantınızın temel görevini gerçekleştiren bir Cloud Function yazacaksınız. Bu görev, Realtime Database'inizdeki mesajları izlemek ve bunları büyük harfe dönüştürmektir.

  1. Uzantının işlevlerinin kaynağını (uzantının functions dizininde) istediğiniz düzenleyicide veya IDE'de açın. İçeriğini aşağıdakiyle değiştirin:

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

    Değiştirdiğiniz eski işlev, bir HTTP uç noktasına erişildiğinde çalışan HTTP tetiklemeli bir işlevdi. Yeni işlev, gerçek zamanlı veritabanı etkinlikleri tarafından tetiklenir: Belirli bir yoldaki yeni öğeleri izler ve bir öğe algılandığında değerin büyük harfli sürümünü veritabanına geri yazar.

    Bu arada, bu yeni dosya CommonJS (require) yerine ECMAScript modülü söz dizimini (import ve export) kullanıyor. Node'da ES modüllerini kullanmak için functions/package.json içinde "type": "module" belirtin:

    {
      "name": "rtdb-uppercase-messages",
      "main": "index.js",
      "type": "module",
      
    }
    
  2. Uzantınızdaki her işlev, extension.yaml dosyasında bildirilmelidir. Örnek uzantı, uzantının tek Cloud Function'ı olarak greetTheWorld'yı bildirmişti. Şimdi bunu makeuppercase ile değiştirdiğiniz için bildirimini de güncellemeniz gerekiyor.

    extension.yaml uygulamasını açın ve resources alanı ekleyin:

    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. Uzantınız artık tetikleyici olarak Realtime Database'i kullandığından, RTDB emülatörünü Cloud Functions emülatörüyle birlikte çalıştırmak için emülatör yapılandırmanızı güncellemeniz gerekir:

    1. Emülatör hâlâ çalışıyorsa Ctrl-C tuşlarına basarak durdurun.

    2. functions/integration-tests dizininden aşağıdaki komutu çalıştırın:

      firebase init emulators

      İstendiğinde varsayılan proje oluşturma adımını atlayın, ardından Functions ve Database emülatörlerini seçin. Varsayılan bağlantı noktalarını kabul edin ve kurulum aracının gerekli dosyaları indirmesine izin verin.

    3. Emülatörü yeniden başlatın:

      firebase emulators:start --project=demo-test
  4. Güncellenen uzantınızı deneyin:

    1. Emülatörü başlattığınızda emülatörün yazdırdığı bağlantıyı kullanarak veritabanı emülatörü kullanıcı arayüzünü açın.

    2. Veritabanının kök düğümünü düzenleme:

      • Alan: messages
      • Tür: json
      • Değer: {"11": {"original": "recipe"}}

      Her şey doğru şekilde ayarlanmışsa veritabanı değişikliklerinizi kaydettiğinizde uzantının makeuppercase işlevi tetiklenir ve "upper": "RECIPE" içeriklerini içeren 11 numaralı mesaja bir alt kayıt eklenir. Beklenen sonuçları onaylamak için günlükleri ve emülatör kullanıcı arayüzünün veritabanı sekmelerini inceleyin.

    3. messages düğümüne ({"original":"any text"}) birkaç çocuk daha eklemeyi deneyin. Yeni bir kayıt eklediğinizde uzantı, original alanının büyük harfli içeriklerini içeren bir uppercase alanı eklemelidir.

Artık RTDB örneğinde çalışan basit ama eksiksiz bir uzantınız var. İlerleyen bölümlerde, bu uzantıyı bazı ek özelliklerle daha iyi hale getireceksiniz. Ardından, uzantıyı başkalarına dağıtmaya hazır hale getirecek ve son olarak uzantınızı Uzantı Merkezi'nde nasıl yayınlayacağınızı öğreneceksiniz.

5. API'leri ve rolleri bildirme

Firebase, yüklenen bir uzantının her örneğine, proje ve verilerine örnek başına hizmet hesabı kullanarak sınırlı erişim izni verir. Her hesap, çalışmak için gereken minimum izinlere sahiptir. Bu nedenle, uzantınızın gerektirdiği tüm IAM rollerini açıkça belirtmeniz gerekir. Kullanıcılar uzantınızı yüklediğinde Firebase, bu rollerin verildiği bir hizmet hesabı oluşturur ve uzantıyı çalıştırmak için bu hesabı kullanır.

Bir ürünün etkinliklerini tetiklemek için rol bildirmeniz gerekmez ancak ürünle başka şekilde etkileşim kurmak için rol bildirmeniz gerekir. Son adımda eklediğiniz işlev Realtime Database'e yazdığından extension.yaml'ya aşağıdaki bildirimi eklemeniz gerekir:

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

Benzer şekilde, bir uzantının kullandığı Google API'lerini apis alanında beyan edersiniz. Kullanıcılar uzantınızı yüklediğinde projelerinde bu API'leri otomatik olarak etkinleştirmek isteyip istemedikleri sorulur. Bu genellikle yalnızca Firebase dışı Google API'leri için gereklidir ve bu kılavuzda gerekli değildir.

6. Kullanıcı tarafından yapılandırılabilen parametreleri tanımlama

Son iki adımda oluşturduğunuz işlev, gelen iletiler için belirli bir RTDB konumunu izledi. Bazen, uzantınızın yalnızca uzantınız için kullandığınız bir veritabanı yapısında çalıştığı durumlarda olduğu gibi, belirli bir konumu izlemek gerçekten de istediğiniz şey olabilir. Ancak çoğu zaman, bu değerlerin, uzantınızı projelerine yükleyen kullanıcılar tarafından yapılandırılabilir olmasını istersiniz. Bu sayede kullanıcılar, mevcut veritabanı kurulumlarıyla çalışmak için uzantınızdan yararlanabilir.

Uzantının yeni mesajlar için izlediği yolu kullanıcı tarafından yapılandırılabilir hale getirin:

  1. extension.yaml dosyasında params bölümü ekleyin:

    - 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
    

    Bu, kullanıcıların uzantınızı yüklerken ayarlamaları istenen yeni bir dize parametresi tanımlar.

  2. Hâlâ extension.yaml dosyasındayken makeuppercase beyanınıza geri dönün ve resource alanını aşağıdaki gibi değiştirin:

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

    ${param:MESSAGE_PATH} jetonu, tanımladığınız parametreye yapılan bir referanstır. Uzantınız çalıştığında bu jeton, kullanıcının söz konusu parametre için yapılandırdığı değerle değiştirilir. Sonuç olarak, makeuppercase işlevi kullanıcının belirttiği yolu dinler. Bu söz dizimini kullanarak extension.yaml içindeki (ve POSTINSTALL.md içindeki) herhangi bir kullanıcı tanımlı parametreye herhangi bir yerden referans verebilirsiniz (POSTINSTALL.md hakkında daha fazla bilgiyi sonraki bölümlerde bulabilirsiniz).

  3. Kullanıcı tanımlı parametrelere işlev kodunuzdan da erişebilirsiniz.

    Son bölümde yazdığınız işlevde, değişikliklerin izleneceği yolu sabit kodladınız. Tetikleyici tanımını, kullanıcı tanımlı değere referans verecek şekilde değiştirin:

    functions/index.js

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

    Firebase Uzantıları'nda bu değişikliğin tamamen doküman oluşturma amacıyla yapıldığını unutmayın: Bir Cloud Function, uzantının parçası olarak dağıtıldığında extension.yaml dosyasındaki tetikleyici tanımını kullanır ve işlev tanımında belirtilen değeri yoksayar. Bununla birlikte, bu değerin nereden geldiğini kodunuzda belirtmeniz iyi bir fikirdir.

  4. Çalışma zamanı etkisi olmayan bir kod değişikliği yapmak hayal kırıklığı yaratabilir ancak buradan çıkarılacak önemli ders, işlev kodunuzdaki kullanıcı tanımlı parametrelere erişebileceğiniz ve bunları işlevin mantığında normal bir değer olarak kullanabileceğinizdir. Bu özelliği göstermek için aşağıdaki günlük ifadesini ekleyerek kullanıcının tanımladığı değere gerçekten eriştiğinizi gösterin:

    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. Normalde, kullanıcılar bir uzantı yüklediklerinde parametreler için değer sağlamaya yönlendirilir. Ancak test ve geliştirme için emülatörü kullandığınızda yükleme işlemini atlar ve bunun yerine env dosyası kullanarak kullanıcı tanımlı parametreler için değerler sağlarsınız.

    functions/integration-tests/extensions/rtdb-uppercase-messages.env bağlantısını açın ve GREETING tanımını aşağıdakiyle değiştirin:

    MESSAGE_PATH=/msgs/{pushId}/original
    

    Yukarıdaki yolun, varsayılan yoldan ve daha önce tanımladığınız yoldan farklı olduğunu unutmayın. Bu yalnızca güncellenmiş uzantınızı denediğinizde tanımınızın etkili olduğunu kendinize kanıtlamak içindir.

  6. Şimdi emülatörü yeniden başlatın ve veritabanı emülatörü kullanıcı arayüzünü tekrar ziyaret edin.

    Yukarıda tanımladığınız yolu kullanarak veritabanının kök düğümünü düzenleyin:

    • Alan: msgs
    • Tür: json
    • Değer: {"11": {"original": "recipe"}}

    Veritabanı değişikliklerinizi kaydettiğinizde, uzantının makeuppercase işlevi daha önce olduğu gibi tetiklenir. Ancak artık kullanıcı tanımlı parametreyi de konsol günlüğüne yazdırır.

7. Kullanıcı tanımlı mantık için etkinlik kancaları sağlama

Uzantı yazarı olarak, bir Firebase ürününün uzantınız tarafından sağlanan mantığı nasıl tetikleyebileceğini zaten görmüşsünüzdür: Realtime Database'de yeni kayıtların oluşturulması makeuppercase işlevinizi tetikler. Uzantınız, uzantınızı yükleyen kullanıcılarla benzer bir ilişkiye sahip olabilir: Uzantınız, kullanıcının tanımladığı mantığı tetikleyebilir.

Uzantılar eşzamanlı kancalar, eşzamansız kancalar veya her ikisini de sağlayabilir. Senkron kancalar, kullanıcıların uzantı işlevlerinden birinin tamamlanmasını engelleyen görevleri gerçekleştirmesine olanak tanır. Örneğin, bu özellik sayesinde kullanıcılar, bir uzantı çalışmaya başlamadan önce özel ön işleme yapabilir.

Bu kılavuzda, uzantınıza eşzamansız bir kanca ekleyeceksiniz. Bu kanca, kullanıcıların uzantınız büyük harfli mesajı Realtime Database'e yazdıktan sonra çalıştırılacak kendi işleme adımlarını tanımlamasına olanak tanır. Asenkron kancalar, kullanıcı tanımlı işlevleri tetiklemek için Eventarc'ı kullanır. Uzantılar, yayınladıkları etkinlik türlerini bildirir ve kullanıcılar uzantıyı yüklediğinde hangi etkinlik türleriyle ilgilendiklerini seçer. Kullanıcılar en az bir etkinlik seçerse Firebase, yükleme işleminin bir parçası olarak uzantı için bir Eventarc kanalı sağlar. Kullanıcılar daha sonra bu kanalı dinleyen ve uzantı yeni etkinlikler yayınladığında tetiklenen kendi bulut işlevlerini dağıtabilir.

Asenkron kanca eklemek için aşağıdaki adımları uygulayın:

  1. extension.yaml dosyasında, uzantının yayınladığı tek etkinlik türünü bildiren aşağıdaki bölümü ekleyin:

    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.
    

    Etkinlik türleri genel olarak benzersiz olmalıdır. Benzersizliği sağlamak için etkinliklerinizi her zaman şu biçimde adlandırın: <publisher-id>.<extension-id>.<version>.<description>. (Henüz yayıncı kimliğiniz yok. Bu nedenle, şimdilik test-publisher değerini kullanın.)

  2. makeuppercase işlevinin sonuna, az önce bildirdiğiniz türde bir etkinlik yayınlayan bir kod ekleyin:

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

    Bu örnek kod, EVENTARC_CHANNEL ortam değişkeninin yalnızca kullanıcı en az bir etkinlik türünü etkinleştirdiğinde tanımlanmasından yararlanır. EVENTARC_CHANNEL tanımlanmamışsa kod, herhangi bir etkinlik yayınlamaya çalışmaz.

    Eventarc etkinliğine ek bilgiler ekleyebilirsiniz. Yukarıdaki örnekte, etkinlikte yeni oluşturulan değere referans içeren bir subject alanı ve orijinal ile büyük harfli mesajları içeren bir data yükü vardır. Etkinliği tetikleyen kullanıcı tanımlı işlevler bu bilgileri kullanabilir.

  3. Normalde, EVENTARC_CHANNEL ve EXT_SELECTED_EVENTS ortam değişkenleri, kullanıcının yükleme sırasında seçtiği seçeneklere göre tanımlanır. Emülatörle test için rtdb-uppercase-messages.env dosyasında bu değişkenleri manuel olarak tanımlayın:

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

Bu noktada, uzantınıza eşzamansız etkinlik kancası eklemek için gereken adımları tamamlamış olursunuz.

Yeni uyguladığınız bu özelliği denemek için sonraki birkaç adımda uzantıyı yükleyen bir kullanıcının rolünü üstlenin:

  1. functions/integration-tests dizininden yeni bir Firebase projesi başlatın:

    firebase init functions

    İstendiğinde varsayılan proje oluşturmayı reddedin, Cloud Functions dili olarak JavaScript'i seçin ve gerekli bağımlılıkları yükleyin. Bu proje, uzantınızın yüklü olduğu bir kullanıcı projesini temsil eder.

  2. integration-tests/functions/index.js dosyasını düzenleyin ve aşağıdaki kodu yapıştırın:

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

    Bu, kullanıcının yazabileceği bir son işleme işlevi örneğidir. Bu örnekte işlev, uzantının bir complete etkinliği yayınlamasını bekler ve tetiklendiğinde yeni büyük harfli mesajın sonuna üç ünlem işareti ekler.

  3. Emülatörü yeniden başlatın. Emülatör, uzantının işlevlerini ve "kullanıcının" tanımladığı son işlem işlevini yükler.

  4. Veritabanı emülatörü kullanıcı arayüzünü ziyaret edin ve yukarıda tanımladığınız yolu kullanarak veritabanının kök düğümünü düzenleyin:

    • Alan:msgs
    • Tür: json
    • Değer: {"11": {"original": "recipe"}}

    Veritabanı değişikliklerinizi kaydettiğinizde, uzantının makeuppercase işlevi ve kullanıcının extraemphasis işlevi sırayla tetiklenir. Bu da upper alanının RECIPE!!! değerini almasına neden olur.

8. Yaşam döngüsü etkinlik işleyicileri ekleme

Şu ana kadar yazdığınız uzantı, mesajları oluşturuldukları sırada işler. Ancak kullanıcılarınız uzantıyı yüklediğinde zaten bir mesaj veritabanına sahipse ne olur? Firebase Extensions'da, uzantınız yüklendiğinde, güncellendiğinde veya yeniden yapılandırıldığında işlemleri tetiklemek için kullanabileceğiniz yaşam döngüsü etkinliği kancaları adlı bir özellik bulunur. Bu bölümde, bir kullanıcı uzantınızı yüklediğinde projenin mevcut mesaj veritabanını büyük harfli mesajlarla doldurmak için yaşam döngüsü etkinlik kancalarını kullanacaksınız.

Firebase Uzantıları, yaşam döngüsü etkinlik işleyicilerinizi çalıştırmak için Cloud Tasks'ı kullanır. Cloud Functions'ı kullanarak etkinlik işleyicileri tanımlarsınız. Uzantınızın bir örneği, desteklenen yaşam döngüsü etkinliklerinden birine ulaştığında, bir işleyici tanımladıysanız işleyiciyi Cloud Tasks kuyruğuna ekler. Cloud Tasks daha sonra işleyiciyi eşzamansız olarak yürütür. Yaşam döngüsü etkinlik işleyicisi çalışırken Firebase konsolu, kullanıcıya uzantı örneğinin devam eden bir işleme görevi olduğunu bildirir. Devam eden durumu ve görevin tamamlanmasını kullanıcıya bildirmek işleyici işlevinize bağlıdır.

Mevcut iletileri dolduran bir yaşam döngüsü etkinlik işleyici eklemek için aşağıdakileri yapın:

  1. Görev sırası etkinlikleri tarafından tetiklenen yeni bir Cloud Functions işlevi tanımlayın:

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

    İşlevin, kendisini görev sırasına geri eklemeden önce yalnızca birkaç kaydı işlediğini unutmayın. Bu, bir Cloud Function'ın zaman aşımı penceresi içinde tamamlanamayan işleme görevleriyle başa çıkmak için yaygın olarak kullanılan bir stratejidir. Kullanıcının uzantınızı yüklediğinde veritabanında kaç mesaj olabileceğini tahmin edemeyeceğiniz için bu strateji uygundur.

  2. extension.yaml dosyasında, doldurma işlevinizi taskQueueTrigger özelliğine sahip bir uzantı kaynağı olarak bildirin:

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

    Ardından, işlevi onInstall yaşam döngüsü etkinliğinin işleyicisi olarak bildirin:

    lifecycleEvents:
      onInstall:
        function: backfilldata
        processingMessage: Uppercasing existing messages
    
  3. Mevcut iletileri doldurmak güzel bir özellik olsa da uzantı bu özellik olmadan da çalışabilir. Bu gibi durumlarda, yaşam döngüsü etkinlik işleyicilerinin çalıştırılmasını isteğe bağlı hale getirmeniz gerekir.

    Bunu yapmak için extension.yaml öğesine yeni bir parametre ekleyin:

    - 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
    

    Ardından, geri doldurma işlevinin başında DO_BACKFILL parametresinin değerini kontrol edin ve ayarlanmamışsa erken çıkın:

    functions/index.js

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

Yukarıdaki değişikliklerle birlikte, uzantı artık yüklendiğinde mevcut mesajları büyük harfe dönüştürecek.

Bu noktaya kadar, uzantınızı geliştirmek ve devam eden değişiklikleri test etmek için uzantı emülatörünü kullandınız. Ancak uzantı emülatörü yükleme işlemini atlar. Bu nedenle onInstall etkinlik işleyicinizi test etmek için uzantıyı gerçek bir projeye yüklemeniz gerekir. Ancak bu otomatik doldurma özelliği eklendiğinden eğitim uzantısı artık kod açısından tamamlanmış durumda.

9. Gerçek bir Firebase projesine dağıtma

Uzantı emülatörü, geliştirme sırasında bir uzantı üzerinde hızlı bir şekilde yineleme yapmak için harika bir araç olsa da bir noktada bunu gerçek bir projede denemek isteyeceksiniz.

Bunu yapmak için öncelikle bazı hizmetlerin etkinleştirildiği yeni bir proje oluşturun:

  1. Firebase konsolunda yeni bir proje ekleyin.
  2. Projenizi kullandıkça öde Blaze planına yükseltin. Firebase için Cloud Functions, projenizin bir faturalandırma hesabına sahip olmasını gerektirir. Bu nedenle, uzantı yüklemek için de bir faturalandırma hesabınızın olması gerekir.
  3. Yeni projenizde Realtime Database'i etkinleştirin.
  4. Uzantınızın yükleme sırasında mevcut verileri doldurma özelliğini test etmek istediğiniz için gerçek zamanlı veritabanı örneğinize bazı örnek veriler aktarın:
    1. Bazı başlangıç RTDB verilerini indirin.
    2. Firebase konsolunun Realtime Database sayfasında (diğer) > JSON'u İçe Aktar'ı tıklayın ve az önce indirdiğiniz dosyayı seçin.
  5. Doldurma işlevinin orderByChild yöntemini kullanmasını sağlamak için veritabanını upper değerine göre mesajları indeksleyecek şekilde yapılandırın:

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

Şimdi uzantınızı yerel kaynaktan yeni projeye yükleyin:

  1. Firebase projeniz için yeni bir dizin oluşturun:

    mkdir ~/extensions-live-test && cd ~/extensions-live-test
    
  2. Çalışma dizininde bir Firebase projesi başlatın:

    firebase init database

    İstendiğinde yeni oluşturduğunuz projeyi seçin.

  3. Uzantıyı yerel Firebase projenize yükleyin:

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

    Burada, Firebase CLI aracını kullanarak uzantı yüklerken kullanıcı deneyiminin nasıl olduğunu görebilirsiniz. Yapılandırma aracı, mevcut veritabanınızı doldurmak isteyip istemediğinizi sorduğunda "Evet"i seçtiğinizden emin olun.

    Yapılandırma seçeneklerini belirledikten sonra Firebase CLI, yapılandırmanızı extensions dizinine kaydeder ve uzantı kaynağının konumunu firebase.json dosyasına kaydeder. Bu iki kayda toplu olarak uzantı manifesti denir. Kullanıcılar, uzantı yapılandırmalarını kaydetmek ve farklı projelerde dağıtmak için manifest dosyasını kullanabilir.

  4. Uzantı yapılandırmanızı canlı projenize dağıtın:

    firebase deploy --only extensions

Her şey yolunda giderse Firebase CLI, uzantınızı projenize yükleyip yükler. Yükleme tamamlandıktan sonra yedek doldurma görevi çalıştırılır ve birkaç dakika içinde veritabanınız büyük harfli mesajlarla güncellenir. İleti veritabanına bazı yeni düğümler ekleyin ve uzantının yeni iletilerde de çalıştığından emin olun.

10. Belge yazma

Uzantınızı kullanıcılarla paylaşmadan önce, başarılı olmaları için yeterli doküman sağladığınızdan emin olun.

Uzantı projesini başlattığınızda Firebase CLI, gerekli minimum dokümanların taslak sürümlerini oluşturur. Bu dosyaları, oluşturduğunuz uzantıyı doğru şekilde yansıtacak biçimde güncelleyin.

extension.yaml

Bu uzantıyı geliştirirken bu dosyayı zaten güncellediğiniz için şu anda başka güncelleme yapmanız gerekmiyor.

Ancak bu dosyada yer alan belgelerin önemini göz ardı etmeyin. Bir uzantının temel tanımlayıcı bilgilerine (ad, açıklama, yazar, resmi depo konumu) ek olarak, extension.yaml dosyası her kaynak ve kullanıcı tarafından yapılandırılabilen parametre için kullanıcıya yönelik dokümanlar içerir. Bu bilgiler Firebase konsolunda, uzantı merkezinde ve Firebase CLI'da kullanıcılara gösterilir.

PREINSTALL.md

Bu dosyada, kullanıcının uzantınızı yüklemeden önce ihtiyaç duyduğu bilgileri sağlayın: Uzantının ne yaptığını kısaca açıklayın, ön koşulları açıklayın ve kullanıcıya uzantıyı yüklemenin faturalandırma açısından sonuçları hakkında bilgi verin. Ek bilgiler içeren bir web siteniz varsa bu siteyi de buraya bağlayabilirsiniz.

Bu dosyanın metni, Uzantı Merkezi'nde ve firebase ext:info komutuyla kullanıcıya gösterilir.

Aşağıda bir PREINSTALL dosyası örneği verilmiştir:

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

Bu dosya, kullanıcıların uzantınızı başarıyla yüklemesinden sonra işlerine yarayacak bilgiler içerir. Örneğin, takip kurulum adımları, uzantının kullanımda olduğu bir örnek vb.

POSTINSTALL.md dosyasının içeriği, bir uzantı yapılandırılıp yüklendikten sonra Firebase konsolunda gösterilir. Bu dosyada kullanıcı parametrelerine referans verebilirsiniz. Bu parametreler, yapılandırılan değerlerle değiştirilir.

Eğitim uzantısı için yükleme sonrası dosya örneğini aşağıda bulabilirsiniz:

### 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

Ayrıca, bir uzantının sürümleri arasında yaptığınız değişiklikleri CHANGELOG.md dosyasında belgelemeniz gerekir.

Örnek uzantı daha önce hiç yayınlanmadığından değişiklik günlüğünde yalnızca bir giriş vardır:

## Version 0.0.1

Initial release of the _Convert messages to upper case_ extension.

README.md

Çoğu uzantı, uzantının deposunu ziyaret eden kullanıcıların yararlanması için bir benioku dosyası da sağlar. Bu dosyayı elle yazabilir veya komutu kullanarak bir benioku dosyası oluşturabilirsiniz.

Bu kılavuzun amacı doğrultusunda, readme dosyası yazmayı atlayın.

Ek belgeler

Yukarıda bahsedilen belgeler, kullanıcılara sağlamanız gereken minimum belgelerdir. Birçok uzantının başarılı bir şekilde kullanılabilmesi için kullanıcıların daha ayrıntılı belgelere ihtiyacı vardır. Bu durumda, ek belgeler yazıp kullanıcıları yönlendirebileceğiniz bir yerde barındırmanız gerekir.

Bu kılavuzun amacı doğrultusunda, daha kapsamlı belgeler yazmayı atlayın.

11. Uzantı Merkezi'nde yayınlama

Uzantınızın kodu tamamlandı ve belgelendirildi. Artık Uzantı Merkezi'nde tüm dünyayla paylaşabilirsiniz. Ancak bu sadece bir eğitim olduğundan bunu yapmayın. Burada ve Firebase Uzantıları yayıncı belgelerinin geri kalanında öğrendiklerinizi kullanarak, resmi ve Firebase tarafından yazılmış uzantıların kaynağını inceleyerek kendi uzantınızı yazmaya başlayın.

Çalışmanızı Uzantı Merkezi'nde yayınlamaya hazır olduğunuzda aşağıdaki adımları uygulayın:

  1. İlk uzantınızı yayınlıyorsanız uzantı yayıncısı olarak kaydolun. Uzantı yayıncısı olarak kaydolduğunuzda, kullanıcıların sizi uzantılarınızın yazarı olarak hızlıca tanımlamasını sağlayan bir yayıncı kimliği oluşturursunuz.
  2. Uzantınızın kaynak kodunu herkese açık olarak doğrulanabilir bir konumda barındırın. Kodunuz doğrulanabilir bir kaynaktan edinilebiliyorsa Firebase, uzantınızı doğrudan bu konumdan yayınlayabilir. Bu sayede, uzantınızın şu anda yayınlanan sürümünü yayınladığınızdan emin olabilirsiniz. Ayrıca, kullanıcıların projelerine yükledikleri kodu incelemelerine olanak tanıyarak onlara yardımcı olabilirsiniz.

    Şu anda bu, uzantınızı herkese açık bir GitHub deposunda kullanıma sunmak anlamına gelir.

  3. firebase ext:dev:upload komutunu kullanarak uzantınızı Uzantı Merkezi'ne yükleyin.

  4. Firebase konsolunda yayıncı kontrol panelinize gidin, yeni yüklediğiniz uzantıyı bulun ve "Uzantı Merkezi'nde yayınla"yı tıklayın. Bu işlem, inceleme ekibimizden inceleme isteğinde bulunmanızı sağlar. İnceleme birkaç gün sürebilir. Onaylanırsa uzantı, Uzantı Merkezi'nde yayınlanır. Reddedilirse nedenini açıklayan bir mesaj alırsınız. Ardından, bildirilen sorunları ele alıp inceleme için yeniden gönderebilirsiniz.