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, mesajlar için Realtime Database'inizi izler ve bunları büyük harfe dönüştürür.

1. Ortamınızı kurma ve projeyi başlatma

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

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

  2. Firebase CLI'ı yükleyin veya en son sürümüne 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ı projesini başlatmak için Firebase CLI'ı kullanın:

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

    mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
    
  2. Firebase CLI'ı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" yanıtını verin. (Diğer seçenekler için varsayılanları kabul edin.) Bu komut, uzantınızı geliştirmeye başlayabileceğiniz yeni uzantı için iskelet bir kod tabanı oluşturur.

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

Firebase CLI, yeni uzantı dizinini ilk kullanıma sunduğunda basit bir örnek işlev ve Firebase emülatör paketini kullanarak uzantı çalıştırmak için gereken dosyaları içeren bir integration-tests dizini oluşturur.

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

  1. integration-tests dizinine geçin:

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

    firebase emulators:start --project=demo-test
    

    Emülatör, uzantıyı önceden tanımlanmış "sahte" bir projeye (demo-test) yükler. Şu ana kadarki uzantı, şimdiye kadarki HTTP tetiklenmiş tek bir işlevden (greetTheWorld) oluşmaktadır. Bu işlev, erişildiğinde bir "hello world" mesajı döndürmektedir.

  3. Emülatör hâlâ çalışıyorken, uzantıyı başlatırken yazdırdığı URL'yi ziyaret ederek uzantının greetTheWorld işlevini deneyin.

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

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

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

    fonksiyonlar/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ş karşılama mesajını görürsünüz.

3. uzantı.yaml dosyasına temel bilgileri ekleyin

Artık bir geliştirme ortamınız kurduğunuza ve uzantı emülatörünü çalıştırdığınıza göre, kendi uzantınızı yazmaya başlayabilirsiniz.

Mütevazı bir ilk 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 veri extension.yaml dosyasında depolanır.

  1. Düzenleyicinizde extension.yaml uygulamasını açın ve dosyanın tüm içeriğini aşağıdakiyle 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 çalıştığı birincil Firebase ürününü belirten bir önek ve ardından uzantının ne yaptığına dair açıklama ile adlandırılır. Aynı kuralı kendi uzantılarınızda da 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 değerini rtdb-uppercase-messages olarak değiştirin.
    2. functions/integration-tests/extensions/greet-the-world.env öğesinin adını functions/integration-tests/extensions/rtdb-uppercase-messages.env olarak değiştirin.

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

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

Artık kod yazmaya başlayabilirsiniz. Bu adımda, uzantınızın temel görevini yerine getiren bir Cloud Functions işlevi yazacaksınız. Bu işlev, mesajlar için Realtime Database'inizi izlemek ve bunları büyük harfe dönüştürmektir.

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

    fonksiyonlar/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 tetiklenmiş 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 dosyada CommonJS (require) yerine ECMAScript modülü söz dizimi (import ve export) kullanılıyor. Node'da ES modüllerini kullanmak için functions/package.json içinde "type": "module" değerini belirtin:

    {
      "name": "rtdb-uppercase-messages",
      "main": "index.js",
      "type": "module",
      …
    }
    
  2. Uzantınızdaki her işlev, extension.yaml dosyasında tanımlanmalıdır. Örnek uzantı, uzantının tek Cloud Functions işlevi olarak greetTheWorld beyan etti. Bu işlevi makeuppercase ile değiştirdiğinize göre açıklamasını da güncellemeniz gerekiyor.

    extension.yaml sayfasını açın ve bir 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 kullandığından, emülatör yapılandırmanızı Cloud Functions emülatörüyle birlikte RTDB emülatörünü çalıştıracak şekilde 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
      

      Sorulduğunda, varsayılan proje ayarlamayı 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 tüm 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. Başlattığınız 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üzenleyin:

      • 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 tetiklenmeli ve "upper": "RECIPE" içeriğini içeren mesaj 11'e bir alt kayıt eklemelidir. Beklenen sonuçları onaylamak için emülatör kullanıcı arayüzünün günlüklere ve veritabanı sekmelerine göz atın.

    3. messages düğümüne ({"original":"any text"}) biraz daha alt öğe eklemeyi deneyin. Yeni bir kayıt eklediğinizde uzantı, original alanında büyük harfli içeriklerin bulunduğu bir uppercase alanı eklemelidir.

Artık bir RTDB örneğinde çalışan, eksiksiz ama basit bir uzantınız var. Sonraki bölümlerde, bu uzantıyı bazı ek özelliklerle geliştireceksiniz. Ardından, uzantıyı başkalarına dağıtıma hazır hale getirir ve son olarak uzantılarınızı Extensions Hub'da nasıl yayınlayacağınızı öğrenebilirsiniz.

5. API'leri ve rolleri tanımlama

Firebase, örnek başına bir hizmet hesabı kullanarak yüklenen bir uzantının her örneğine projeye ve verilerine sınırlı erişim izni verir. Her hesabın, çalışması için gereken minimum izin grubu bulunur. Bu nedenle, uzantınızın gerektirdiği tüm IAM rollerini açıkça beyan etmeniz 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 rolleri tanımlamanız gerekmez, ancak ürünle başka bir şekilde etkileşimde bulunmak için bir rol tanımlamanız gerekir. Son adımda eklediğiniz işlev Realtime Database'e yazdığından aşağıdaki bildirimi extension.yaml öğesine 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 açıklarsınız. Kullanıcılar uzantınızı yüklediklerinde, projeleri için bu API'leri otomatik olarak etkinleştirmek isteyip istemedikleri sorulur. Bu genellikle yalnızca Firebase harici Google API'leri için gereklidir ve bu kılavuz için gerekli değildir.

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

Son iki adımda oluşturduğunuz işlev, gelen mesajlar için belirli bir RTDB konumunu izlemiştir. Bazen belirli bir konumu izlemek istediğiniz şeydir. Örneğin, uzantınız uzantınız için özel olarak kullandığınız bir veritabanı yapısında çalışıyorsa bu durum geçerlidir. Ancak çoğu zaman bu değerleri, uzantınızı projelerine yükleyen kullanıcılar tarafından yapılandırılabilir hale getirmek istersiniz. Böylece 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ına bir 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ılardan uzantınızı yüklediklerinde ayarlamaları yapmaları istenecek yeni bir dize parametresi tanımlar.

  2. Yine extension.yaml dosyasında, makeuppercase beyanınıza geri dönün ve resource alanını aşağıdaki şekilde değiştirin:

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

    ${param:MESSAGE_PATH} jetonu, az önce tanımladığınız parametreye referanstır. Uzantınız çalıştığında bu jeton, kullanıcının ilgili parametre için yapılandırdığı değerle değiştirilir. Böylece makeuppercase işlevi, kullanıcının belirttiği yolu dinler. Bu söz dizimini kullanarak extension.yaml içindeki (ve POSTINSTALL.md içinde) herhangi bir kullanıcı tanımlı parametreye referans verebilirsiniz. Bu konuda daha fazla bilgi verilecektir.

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

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

    fonksiyonlar/index.js

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

    Firebase Extensions'da bu değişikliğin tamamen belgeleme amaçlı olduğunu unutmayın: Bir Cloud Functions işlevi 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 yok sayar. Yine de kodunuzda bu değerin nereden geldiğini belgelemek iyi bir fikirdir.

  4. Çalışma zamanı etkisi olmayan bir kod değişikliği yapmak umut kırıklığı yaratabilir ancak bundan çıkarmanız gereken önemli ders, işlev kodunuzdaki kullanıcı tanımlı herhangi bir parametreye erişip bunu işlevin mantığında normal bir değer olarak kullanabilmenizdir. Bu yeteneğinize bir örnek olarak, kullanıcının tanımladığı değere gerçekten eriştiğinizi göstermek için aşağıdaki günlük ifadesini ekleyin:

    fonksiyonlar/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, bir uzantıyı yüklerken kullanıcılardan parametreler için değer girmeleri istenir. Test ve geliştirme için emülatörü kullandığınızda yükleme işlemini atlarsınız. Bu durumda, bir env dosyası kullanarak kullanıcı tanımlı parametreler için değer sağlarsınız.

    functions/integration-tests/extensions/rtdb-uppercase-messages.env dosyası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ğuna dikkat edin. Bu, güncellenmiş uzantınızı denediğinizde tanımınızın yürürlüğe girdiğini 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 önceden olduğu gibi tetiklenir, ancak artık kullanıcı tanımlı parametreyi konsol günlüğüne yazdırması gerekir.

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

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

Uzantı, eşzamanlı kancalar, eşzamansız kancalar veya her ikisini de sağlayabilir. Eşzamanlı kancalar, kullanıcılara uzantının işlevlerinden birinin tamamlanmasını engelleyen görevleri gerçekleştirebilmelerini sağlar. Bu, örneğin bir uzantı çalışmadan önce kullanıcılara özel bir ön işleme seçeneği sunmak için yararlı olabilir.

Bu kılavuzda, uzantınıza eşzamansız bir kanca ekleyeceksiniz. Bu sayede, kullanıcılar, 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ımlayabilirler. Eşzamansız kancalar, kullanıcı tanımlı işlevleri tetiklemek için Eventarc'ı kullanır. Uzantılar, yayınladığı etkinlik türlerini bildirir ve kullanıcılar uzantıyı yüklediğinde ilgilendikleri etkinlik türlerini 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.

Eşzamansız kanca eklemek için şu adımları izleyin:

  1. extension.yaml dosyasına, uzantının yayınladığı bir etkinlik türünü tanımlayan 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 evrensel olarak benzersiz olmalıdır. Benzersizlik sağlamak için etkinliklerinizi her zaman şu biçimi kullanarak adlandırın: <publisher-id>.<extension-id>.<version>.<description>. (Henüz bir yayıncı kimliğiniz olmadığından şimdilik test-publisher kullanın.)

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

    fonksiyonlar/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ımlanmış olmasından faydalanır. EVENTARC_CHANNEL tanımlı değilse kod, herhangi bir etkinliği yayınlamayı denemez.

    Bir Eventarc etkinliğine daha fazla bilgi 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 data yükü bulunmaktadır. Etkinliği tetikleyen kullanıcı tanımlı işlevler bu bilgiyi kullanabilir.

  3. Normalde EVENTARC_CHANNEL ve EXT_SELECTED_EVENTS ortam değişkenleri, kullanıcının yükleme sırasında belirlediği seçeneklere göre tanımlanır. Emülatörle test yapmak için rtdb-uppercase-messages.env dosyasında şu 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ı tamamladınız.

Az önce uyguladığınız bu yeni ö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 projeyi ayarlamayı 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 ediyor.

  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 işleme sonrası işlevi örneğidir. Bu durumda işlev, uzantının bir complete etkinliği yayınlamasını bekler ve tetiklendiğinde yeni büyük harfle yazılmış mesaja üç ü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ığı işleme sonrası 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 tetiklenmelidir. Bunun sonucunda, upper alanı RECIPE!!! değerini alır.

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

Şu ana kadar yazdığınız uzantı, mesajları oluşturuldukları anda işler. Peki, kullanıcılarınız uzantıyı yüklediklerinde zaten bir mesaj veritabanına sahipse ne olur? Firebase Extensions, 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ü olay kancaları adlı bir özelliğe sahiptir. 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 Extensions, yaşam döngüsü etkinlik işleyicilerinizi çalıştırmak için Cloud Tasks'ı kullanır. Etkinlik işleyicileri Cloud Functions'ı kullanarak tanımlarsınız. Bir işleyici tanımladıysanız uzantınızın bir örneği desteklenen yaşam döngüsü etkinliklerinden birine ulaştığında bu, işleyiciyi bir Cloud Tasks sırasına ekler. Ardından Cloud Tasks, işleyiciyi eşzamansız olarak yürütür. Bir yaşam döngüsü etkinlik işleyici ç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 tamamlanma durumunu kullanıcıya bildirmek, işleyici fonksiyonunuza bağlıdır.

Mevcut mesajları dolduran bir yaşam döngüsü etkinlik işleyicisi 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:

    fonksiyonlar/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, kendini görev sırasına tekrar eklemeden önce yalnızca birkaç kayıt işlediğine dikkat edin. Bu strateji, bir Cloud Functions işlevinin zaman aşımı aralığı içinde tamamlanamayan işleme görevleriyle ilgilenmek için yaygın olarak kullanılan bir stratejidir. Uzantınızı yükleyen bir kullanıcının veritabanında kaç mesaj olabileceğini tahmin edemeyeceğiniz için bu strateji sizin için uygundur.

  2. extension.yaml dosyasında, dolgu 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 tanımlayın:

    lifecycleEvents:
      onInstall:
        function: backfilldata
        processingMessage: Uppercasing existing messages
    
  3. Mevcut mesajların yeniden doldurulması güzel olsa da, uzantı olmadan da çalışmaya devam edebilir. Bu gibi durumlarda, yaşam döngüsü etkinlik işleyicilerini çalıştırmayı 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 dolgu işlevinin başında DO_BACKFILL parametresinin değerini kontrol edin ve ayarlanmadıysa erkenden çıkış yapın:

    fonksiyonlar/index.js

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

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

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. Bununla birlikte, 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. Aynı zamanda bu otomatik dolgu özelliğinin eklenmesiyle eğitim uzantısı artık kodla tamamlanmış durumda.

9. Gerçek bir Firebase projesine dağıtın

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

Bunu yapmak için önce bazı hizmetlerin etkin olduğu yeni bir proje oluşturun:

  1. Firebase konsolunda yeni bir proje ekleyin.
  2. Projenizi kullandıkça öde Blaze planına yükseltin. Cloud Functions for Firebase, projenizde bir faturalandırma hesabının olmasını gerektirir. Bu nedenle, uzantı yüklemek için faturalandırma hesabınızın da olması gerekir.
  3. Yeni projenizde Real-time Database'i etkinleştirin.
  4. Uzantınızın yükleme sırasında mevcut verileri doldurma özelliğini test etmek istediğinizden bazı örnek verileri gerçek zamanlı veritabanı örneğinize aktarın:
    1. Bazı çekirdek RTDB verileri indirin.
    2. Firebase konsolunun Real-time Database sayfasında (diğer) > Import JSON (JSON'u içe aktar) seçeneğini tıklayın ve yeni indirdiğiniz dosyayı seçin.
  5. orderByChild yöntemini kullanmak üzere dolgu işlevini etkinleştirmek için veritabanını upper değerindeki mesajları dizine ekleyecek ş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 projesini 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 bir 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ı kaynak konumunu firebase.json dosyasına kaydeder. Bu iki kayıt toplu olarak uzantılar manifesti olarak adlandırılır. Kullanıcılar, uzantı yapılandırmalarını kaydetmek ve farklı projelere dağıtmak için manifesti kullanabilir.

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

    firebase deploy --only extensions
    

Her şey yolunda giderse Firebase CLI, uzantınızı projenize yüklemeli ve yüklemelidir. Yükleme tamamlandıktan sonra dolgu görevi çalıştırılır ve veritabanınız birkaç dakika içinde büyük harfli mesajlarla güncellenir. İleti veritabanına yeni düğümler ekleyin ve uzantının yeni mesajlar için 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 sayıda belge sağladığınızdan emin olun.

Uzantı projesini başlattığınızda Firebase CLI, gerekli minimum belgelerin saplama sürümlerini oluşturdu. Oluşturduğunuz uzantıyı doğru şekilde yansıtacak şekilde bu dosyaları güncelleyin.

uzantı.yaml

Bu uzantıyı geliştirdiğiniz için dosyayı zaten güncelliyorsunuz. Bu nedenle, şu anda başka güncelleme yapmanız gerekmiyor.

Ancak bu dosyada yer alan belgelerin önemini de göz ardı etmeyin. extension.yaml dosyası, bir uzantının önemli tanımlayıcı bilgilerinin (ad, açıklama, yazar, resmi depo konumu) yanı sıra her kaynak ve kullanıcı tarafından yapılandırılabilir parametre için kullanıcılara yönelik belgeler içerir. Bu bilgiler Firebase konsolu, Extensions Hub ve Firebase CLI'da kullanıcılara gösterilir.

PREINSTALL.md

Bu dosyada, uzantınızı yüklemeden önce kullanıcının ihtiyaç duyduğu bilgileri sağlayın: Uzantının ne işe yaradığını kısaca açıklayın, ön koşulları açıklayın ve kullanıcıya uzantıyı yüklemenin faturalandırma sonuçları hakkında bilgi verin. Ek bilgiler içeren bir web siteniz varsa burası da bağlantı vermek için iyi bir yerdir.

Bu dosyanın metni, kullanıcıya Extensions Hub'da ve firebase ext:info komutuyla gösterilir.

Aşağıda bir ÖN YÜKLEME 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, uzantınızı başarıyla yükleyen kullanıcılar için yararlı olacak bilgileri içerir: Örneğin, sonraki kurulum adımları, uzantının nasıl çalıştığını gösteren 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 başvurabilirsiniz. Bu parametreler, yapılandırılmış değerlerle değiştirilir.

Aşağıda, eğitim uzantısı için örnek bir yükleme sonrası dosya örneği verilmiştir:

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

BENİOKU.md

Çoğu uzantı, uzantının deposunu ziyaret eden kullanıcıların yararına bir beni oku dosyası da sağlar. Bu dosyayı elle yazabilir veya şu komutu kullanarak "oku" komutunu oluşturabilirsiniz.

Bu kılavuzu kullanmak için, Benioku dosyası yazma adımını atlayın.

Ek belgeler

Yukarıda açıklanan dokümanlar, kullanıcılara sağlamanız gereken minimum belge grubudur. Birçok uzantı, kullanıcıların uzantıları başarıyla kullanabilmesi için daha ayrıntılı belgelere ihtiyaç duyar. Böyle bir durumda ek belgeler yazmalı ve kullanıcıları yönlendirebileceğiniz bir yerde barındırmalısınız.

Bu kılavuzun amacı gereği, daha kapsamlı belgeler yazmayı atlayın.

11. Uzantı Merkezi'nde yayınla

Uzantınız kod tamamlanıp belgelendirildiğine göre artık Extensions Hub'da tüm dünyayla paylaşmaya hazırsınız. Ancak bu yalnızca bir eğitim olduğundan bunu yapmayın. Burada ve Firebase Extensions yayıncı belgelerinin diğer bölümlerinde öğrendiklerinizi kullanarak ve Firebase tarafından yazılan resmi uzantıların kaynağını inceleyerek kendi uzantınızı yazmaya başlayın.

Çalışmanızı Extensions Hub'da yayınlamaya hazır olduğunuzda nasıl yapacağınız aşağıda açıklanmıştır:

  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ı bir şekilde tanımlamasını sağlayan bir yayıncı kimliği oluşturursunuz.
  2. Uzantınızın kaynak kodunu herkes tarafından doğrulanabilecek bir konumda barındırın. Kodunuz doğrulanabilir bir kaynaktan mevcut olduğunda Firebase, uzantınızı doğrudan bu konumdan yayınlayabilir. Bunu yapmak, uzantınızın şu anda yayınlanan sürümünü yayınladığınızdan emin olmanıza ve kullanıcıların, projelerine yükledikleri kodu incelemelerine izin vererek onlara yardımcı olur.

    Şu anda bunun için uzantınızın herkese açık bir GitHub deposunda kullanıma sunulması gerekiyor.

  3. firebase ext:dev:upload komutunu kullanarak uzantınızı Extensions Hub'a yükleyin.

  4. Firebase konsolunda yayıncı kontrol panelinize gidin, yeni yüklediğiniz uzantıyı bulun ve "Uzantılar Merkezi'nde yayınla"yı tıklayın. Bunun için, inceleme ekibimizden bir inceleme isteği göndermeniz gerekiyor. Bu işlem birkaç gün sürebilir. Uzantı, onaylanırsa Extensions Hub'da yayınlanır. İtirazın reddedilmesinin nedenini açıklayan bir mesaj alırsınız. Ardından, bildirilen sorunları giderebilir ve inceleme için yeniden gönderebilirsiniz.