Cloud Functions kodunuzu Firebase Uzantısı olarak yeniden kullanma

1. Başlamadan önce

Firebase uzantıları, HTTP isteklerine veya Firebase Cloud Messaging, Cloud Firestore ya da Pub/Sub gibi diğer Firebase ve Google ürünlerinden gelen tetikleyici etkinliklere yanıt olarak belirli bir görevi ya da görev grubunu yerine getirir.

Ne oluşturacaksınız?

Bu codelab'de, geohashing için bir Firebase uzantısı oluşturacaksınız. Dağıtıldıktan sonra uzantınız, Firestore etkinliklerine yanıt olarak veya çağrılabilir işlev çağrıları aracılığıyla X ve Y koordinatlarını coğrafi karma değerlerine dönüştürür. Bu, verileri depolamak için Geofire kitaplığını tüm hedef platformlarınızda uygulama seçeneğine alternatif olarak kullanılabilir ve zamandan tasarruf etmenizi sağlar.

Firebase konsolunda gösterilen geohash uzantısı

Neler öğreneceksiniz?

  • Mevcut Cloud Functions kodunu alıp dağıtılabilir bir Firebase uzantısına dönüştürme
  • extension.yaml dosyası oluşturma
  • Hassas dizeleri (API anahtarları) uzantıda depolama
  • Uzantının geliştiricilerinin, uzantıyı kendi ihtiyaçlarına göre yapılandırmasına izin verme
  • Uzantıyı test etme ve dağıtma

Gerekenler

  • Firebase CLI (yükleme ve oturum açma)
  • Gmail hesabı gibi bir Google Hesabı
  • Node.js ve npm
  • En sevdiğiniz geliştirme ortamı

2. Ayarları yapma

Kodu alma

Bu uzantı için ihtiyacınız olan her şey GitHub deposunda yer alır. Başlamak için kodu alın ve en sevdiğiniz geliştirme ortamında açın.

  1. İndirilen ZIP dosyasını açın.
  2. Gerekli bağımlılıkları yüklemek için functions dizininde terminali açın ve npm install komutunu çalıştırın.

Firebase'i ayarlama

Bu codelab'de Firebase emülatörlerinin kullanılması önemle tavsiye edilir. Uzantı geliştirme sürecini gerçek bir Firebase projesiyle denemek istiyorsanız Firebase projesi oluşturma başlıklı makaleyi inceleyin. Bu codelab'de Cloud Functions kullanılıyor. Bu nedenle, emülatörler yerine gerçek bir Firebase projesi kullanıyorsanız Blaze fiyatlandırma planına geçmeniz gerekir.

İleri sarmak mı istiyorsunuz?

Tamamlanmış bir codelab sürümünü indirebilirsiniz. Yolda takılırsanız veya tamamlanmış bir uzantının nasıl göründüğünü görmek isterseniz GitHub deposunun codelab-end dalına göz atın ya da tamamlanmış zip dosyasını indirin.

3. Kodu inceleme

  • Zip dosyasındaki index.ts dosyasını açın. İçinde iki Cloud Functions bildirimi olduğunu unutmayın.

Bu işlevler ne işe yarar?

Bu demo işlevleri, coğrafi karma oluşturma için kullanılır. Koordinat çiftini alıp Firestore'daki coğrafi sorgular için optimize edilmiş bir biçime dönüştürür. Bu işlevler, uzantılarda hassas veri türlerinin işlenmesi hakkında daha fazla bilgi edinebilmeniz için API çağrısının kullanımını simüle eder. Daha fazla bilgi için Firestore'daki verilerde coğrafi sorgular çalıştırma ile ilgili dokümanlara bakın.

İşlev sabitleri

Sabitler, index.ts dosyasının en üstünde, erken aşamada tanımlanır. Bu sabitlerden bazıları, uzantının tanımlı tetikleyicilerinde referans olarak kullanılır.

index.ts

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

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

initializeApp();

const service = new GeoHashService(apiKey);

Firestore tetikleyicisi

index.ts dosyasındaki ilk işlev şu şekilde görünür:

index.ts

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

Bu işlev bir Firestore tetikleyicisidir. Veritabanında bir yazma etkinliği gerçekleştiğinde işlev, xv alanı ve yv alanını arayarak bu etkinliğe tepki verir. Bu alanların her ikisi de varsa coğrafi karma oluşturur ve çıkışı belirtilen bir belge çıkış konumuna yazar. Giriş dokümanı, users/{uid} sabitiyle tanımlanır. Bu, işlevin users/ koleksiyonuna yazılan her dokümanı okuduğu ve ardından bu dokümanlar için bir coğrafi karma işlediği anlamına gelir. Ardından karma, aynı dokümandaki bir karma alanına çıkış olarak verilir.

Çağrılabilir İşlevler

index.ts dosyasındaki bir sonraki işlev şu şekilde görünür:

index.ts

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

onCall işlevine dikkat edin. Bu, işlevin çağrılabilir bir işlev olduğunu ve istemci uygulama kodunuzdan çağrılabileceğini gösterir. Bu çağrılabilir işlev, x ve y parametrelerini alır ve bir geohash döndürür. Bu işlev bu codelab'de doğrudan çağrılmayacak olsa da Firebase uzantısında yapılandırılacak bir öğe örneği olarak buraya dahil edilmiştir.

4. extension.yaml dosyası oluşturma

Uzantınızdaki Cloud Functions kodunun ne işe yaradığını öğrendiğinize göre artık dağıtım için paketlemeye hazırsınız. Her Firebase uzantısı, uzantının ne yaptığını ve nasıl davrandığını açıklayan bir extension.yaml dosyasıyla birlikte gelir.

extension.yaml dosyası için uzantınızla ilgili bazı başlangıç meta verileri gerekir. Aşağıdaki adımların her biri, tüm alanların ne anlama geldiğini ve neden gerekli olduklarını anlamanıza yardımcı olur.

  1. Daha önce indirdiğiniz projenin kök dizininde bir extension.yaml dosyası oluşturun. Şunları ekleyerek başlayın:
name: geohash-ext
version: 0.0.1
specVersion: v1beta  # Firebase Extensions specification version (do not edit)

Uzantının adı, uzantının örnek kimliğinin temeli olarak kullanılır (kullanıcılar, her biri kendi kimliğine sahip birden fazla uzantı örneği yükleyebilir). Ardından Firebase, bu örnek kimliğini kullanarak uzantının hizmet hesaplarının ve uzantıya özgü kaynakların adını oluşturur. Sürüm numarası, uzantınızın sürümünü gösterir. Anlamsal sürüm oluşturma kurallarına uymalıdır ve uzantının işlevselliğinde değişiklik yaptığınızda güncellenmelidir. Hangi Firebase uzantıları spesifikasyonunun izleneceğini belirlemek için uzantı spesifikasyon sürümü kullanılır. Bu durumda v1beta kullanılır.

  1. YAML dosyasına kullanıcı dostu bazı ayrıntılar ekleyin:
...

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

Görünen ad, geliştiriciler uzantınızla etkileşimde bulunduğunda uzantınızın adının kolay anlaşılır bir gösterimidir. Açıklamada, uzantının ne yaptığına dair kısa bir özet verilir. Uzantı extensions.dev adresine dağıtıldığında şöyle görünür:

extensions.dev'de görünen Geohash Converter uzantısı

  1. Uzantınızdaki kodun lisansını belirtin.
...

license: Apache-2.0  # The license you want for the extension
  1. Uzantıyı kimin yazdığını ve yüklemek için faturalandırma gerekip gerekmediğini belirtin:
...

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

billingRequired: true

author bölümü, kullanıcılarınızın uzantıyla ilgili sorun yaşamaları veya uzantı hakkında daha fazla bilgi edinmek istemeleri durumunda kiminle iletişime geçmeleri gerektiğini bildirmek için kullanılır. billingRequired, zorunlu bir parametredir ve tüm uzantılar Blaze planı gerektiren Cloud Functions'a dayandığından true olarak ayarlanmalıdır.

Bu, uzantıyı tanımlamak için extension.yaml dosyasında gereken minimum alan sayısını kapsar. Bir uzantıda belirtebileceğiniz diğer tanımlayıcı bilgiler hakkında daha fazla ayrıntı için dokümanları inceleyin.

5. Cloud Functions kodunu bir uzantı kaynağına dönüştürme

Uzantı kaynağı, Firebase'in bir uzantının yüklenmesi sırasında projede oluşturduğu öğedir. Uzantı daha sonra bu kaynakların sahibi olur ve bu kaynaklarda çalışan belirli bir hizmet hesabına sahip olur. Bu projedeki kaynaklar, Cloud Functions'tır. Uzantı, functions klasöründeki kodlardan otomatik olarak kaynak oluşturmayacağından bu kaynaklar extension.yaml dosyasında tanımlanmalıdır. Cloud Functions işlevleriniz açıkça kaynak olarak bildirilmemişse uzantı dağıtıldığında bu işlevler dağıtılamaz.

Kullanıcı tanımlı dağıtım konumu

  1. Kullanıcının bu uzantıyı dağıtmak istediği konumu belirtmesine izin verin ve uzantıyı son kullanıcılara daha yakın mı yoksa veritabanına daha yakın mı barındırmanın daha iyi olacağına karar verin. extension.yaml dosyasında konum seçme seçeneğini ekleyin.

extension.yaml

Artık işlev kaynağının yapılandırmasını yazmaya hazırsınız.

  1. extension.yaml dosyasında, locationUpdate işlevi için bir kaynak nesnesi oluşturun. extension.yaml dosyasına aşağıdakileri ekleyin:
resources:
  - name: locationUpdate
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: providers/cloud.firestore/eventTypes/document.write
        resource: projects/${PROJECT_ID}/databases/(default)/documents/users/{uid}

name, projenin index.ts dosyasında tanımlanan işlev adı olarak tanımlanır. Dağıtılan işlevin type değerini belirtirsiniz. Bu değer şimdilik her zaman firebaseextensions.v1beta.function olmalıdır. Ardından, bu işlevin properties değerini tanımlarsınız. Tanımladığınız ilk özellik, bu işlevle ilişkili eventTrigger değeridir. Uzantının şu anda desteklediği işlevleri yansıtmak için Uzantınız için Cloud Functions yazma dokümanında bulunan eventType of providers/cloud.firestore/eventTypes/document.write işlevini kullanırsınız. resource konumunu belgelerin konumu olarak tanımlarsınız. Mevcut hedefiniz kodda bulunanları yansıtmak olduğundan doküman yolu, önünde varsayılan veritabanı konumuyla birlikte users/{uid} öğesini dinler.

  1. Uzantının Firestore veritabanı için okuma ve yazma izinlerine ihtiyacı vardır. extension.yaml dosyasının en sonunda, uzantının geliştiricinin Firebase projesindeki veri tabanıyla çalışmak için erişmesi gereken IAM rollerini belirtin.
roles:
  - role: datastore.user
    reason: Allows the extension to read / write to your Firestore instance.

datastore.user rolü, uzantılar için desteklenen IAM rolleri listesinden gelir. Uzantı okuma ve yazma işlemleri yapacağından burada datastore.user rolü uygundur.

  1. Çağrılabilir işlev de eklenmelidir. extension.yaml dosyasında, kaynaklar özelliği altında yeni bir kaynak oluşturun. Bu özellikler, çağrılabilir bir işlev için geçerlidir:
  - name: callableHash
    type: firebaseextensions.v1beta.function
    properties:
      httpsTrigger: {}

Önceki kaynakta eventTrigger kullanılmış olsa da burada hem çağrılabilir işlevleri hem de HTTPS işlevlerini kapsayan bir httpsTrigger kullanıyorsunuz.

Kod kontrolü

extension.yaml dosyanızın, index.ts dosyanızdaki kod tarafından yapılan her şeyle eşleşmesi için çok fazla yapılandırma yapmanız gerekiyordu. Tamamlanan extension.yaml dosyası şu anda aşağıdaki gibi görünmelidir:

extension.yaml

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

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

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

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

billingRequired: true

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

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

Durum kontrolü

Bu noktada, uzantının ilk işlevsel parçalarını kurmuş olursunuz. Bu nedenle, Firebase emülatörlerini kullanarak uzantıyı deneyebilirsiniz.

  1. Henüz yapmadıysanız indirilen uzantılar projesinin functions klasöründe npm run build işlevini çağırın.
  2. Ana makine sisteminizde yeni bir dizin oluşturun ve firebase init kullanarak bu dizini Firebase projenize bağlayın.
cd ..
mkdir sample-proj
cd sample-proj
firebase init --project=projectID-or-alias
    This command creates a `firebase.json` file in the directory. In the following steps, you push the configuration specified in this file to Firebase.
  1. Aynı dizinden firebase ext:install komutunu çalıştırın. /path/to/extension bölümünü, extension.yaml dosyanızı içeren dizinin mutlak yoluyla değiştirin.
firebase ext:install /path/to/extension
    This command does two things:
  • Uzantı örneğinin yapılandırmasını belirtmenizi ister ve örnekle ilgili yapılandırma bilgilerini içeren bir *.env dosyası oluşturur.
  • Uzantı örneğini firebase.json bölümünün extensions kısmına ekler. Bu, örnek kimliğinin uzantı sürümüyle eşlendiği bir harita görevi görür.
  • Projeyi yerel olarak dağıttığınız için Google Cloud Secret Manager yerine yerel bir dosya kullanmak istediğinizi belirtebilirsiniz.

Bu uzantı yüklenirken sırları saklamak için yerel dosyanın kullanıldığını gösteren uzantı yükleme işleminin ekran görüntüsü

  1. Firebase emülatörlerini yeni yapılandırmayla başlatın:
firebase emulators:start
  1. emulators:start komutunu çalıştırdıktan sonra emülatörlerin web görünümündeki Firestore sekmesine gidin.
  2. users koleksiyonuna xv sayı alanı ve yv sayı alanı içeren bir belge ekleyin.

Firebase Emulators'da gösterilen ve şu ifadeyi içeren koleksiyon kimliğiyle koleksiyon başlatmak için kullanılan iletişim kutusu:

  1. Uzantıyı başarıyla yüklediyseniz uzantı, dokümanda hash adlı yeni bir alan oluşturur.

xv, yv ve karma alanı olan bir kullanıcı dokümanı içeren kullanıcılar koleksiyonu.

Çakışmaları önlemek için temizleme

  • Testi tamamladıktan sonra uzantıyı kaldırın. Uzantı kodunu güncelleyeceğiniz için daha sonra mevcut uzantıyla çakışmak istemezsiniz.

Uzantılar, aynı uzantının birden fazla sürümünün aynı anda yüklenmesine olanak tanır. Bu nedenle, uzantıyı kaldırarak daha önce yüklenen bir uzantıyla çakışma olmamasını sağlarsınız.

firebase ext:uninstall geohash-ext

Mevcut çözüm çalışıyor ancak projenin başında belirtildiği gibi, bir hizmetle iletişimi simüle etmek için sabit kodlanmış bir API anahtarı var. Başlangıçta sağlanan API anahtarı yerine son kullanıcının API anahtarını nasıl kullanabilirsiniz? Öğrenmek için okumaya devam edin.

6. Uzantıyı kullanıcı tarafından yapılandırılabilir hale getirme

Bu aşamada, yazdığınız işlevlerin belirli bir şekilde ayarlanmış sürümüyle kullanılmak üzere yapılandırılmış bir uzantınız var. Ancak kullanıcınız, bir Kartezyen düzlemdeki konumu belirten alanlar için y ve x yerine enlem ve boylam kullanmak isterse ne olur? Ayrıca, son kullanıcının sağlanan API anahtarını kullanmasına izin vermek yerine kendi API anahtarını sağlamasını nasıl sağlayabilirsiniz? Bu API'nin kotasını hızla aşabilirsiniz. Bu durumda, parametreleri ayarlayıp kullanırsınız.

extension.yaml Dosyasında temel parametreleri tanımlayın.

Geliştiricilerin özel yapılandırması olabilecek öğeleri dönüştürerek başlayın. Bunlardan ilki XFIELD ve YFIELD parametreleridir.

  1. extension.yaml dosyasında, XFIELD ve YFIELD alan parametrelerini kullanan aşağıdaki kodu ekleyin. Bu parametreler, daha önce tanımlanan params YAML özelliği içinde yer alır:

extension.yaml

params:
  - param: XFIELD
    label: The X Field Name
    description: >-
      The X Field is also known as the **longitude** value. What does
      your Firestore instance refer to as the X value or the longitude
      value. If no value is specified, the extension searches for
      field 'xv'.
    type: string
    validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
    validationErrorMessage: >-
      The field can only contain uppercase or lowercase letter, numbers,
      _, and . characters and must be less than 1500 bytes long. The field
      must also not start with a number.
    default: xv
    required: false
    immutable: false
    example: xv
  - param: YFIELD
    label: The Y Field Name
    description: >-
      The Y Field is also known as the **latitude** value. What does
      your Firestore instance refer to as the Y value or the latitude
      value. If no value is specified, the extension searches for
      field 'yv'.
    type: string
    validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
    validationErrorMessage: >-
      The field can only contain uppercase or lowercase letter, numbers,
      _, and . characters and must be less than 1500 bytes long. The field
      must also not start with a number.
    default: yv
    required: false
    immutable: false
    example: yv
  • param, parametreyi uzantı üreticisi olarak size görünür şekilde adlandırır. Parametre değerlerini belirtirken bu değeri daha sonra kullanın.
  • label, geliştiriciye parametrenin ne yaptığını bildirmek için kullanılan, kullanıcılar tarafından okunabilen bir tanımlayıcıdır.
  • description, değerin ayrıntılı bir açıklamasını sağlar. Bu özellik Markdown'ı desteklediği için ek belgelere bağlantı verilebilir veya geliştirici için önemli olabilecek kelimeler vurgulanabilir.
  • type, kullanıcının parametre değerini nasıl ayarlayacağıyla ilgili giriş mekanizmasını tanımlar. string, select, multiSelect, selectResource ve secret gibi birçok tür vardır. Bu seçeneklerin her biri hakkında daha fazla bilgi edinmek için belgelere göz atın.
  • validationRegex, geliştirici girişini belirli bir normal ifade değeriyle (örnekte burada bulunan basit alan adı yönergelerine göre) kısıtlar ve bu başarısız olursa...
  • validationErrorMessage, geliştiriciyi hata değeri konusunda uyarır.
  • default, geliştirici herhangi bir metin girmediğinde değerin ne olacağını gösterir.
  • required (gerekli) ifadesi, geliştiricinin herhangi bir metin girmesinin gerekmediği anlamına gelir.
  • immutable, geliştiricinin bu uzantıyı güncellemesine ve bu değeri değiştirmesine olanak tanır. Bu durumda, geliştirici, gereksinimleri değiştikçe alan adlarını değiştirebilmelidir.
  • example, geçerli bir girişin nasıl görünebileceği hakkında fikir verir.

Anlaşılması gereken çok şey var!

  1. Özel bir parametre eklemeden önce extension.yaml dosyasına eklemeniz gereken üç parametre daha var.
  - param: INPUTPATH
    label: The input document to listen to for changes
    description: >-
      This is the document where you write an x and y value to. Once
      that document has received a value, it notifies the extension to
      calculate a geohash and store that in an output document in a certain
      field. This accepts function [wildcard parameters](https://firebase.google.com/docs/functions/firestore-events#wildcards-parameters)
    type: string
    validationRegex: ^[^/]+(/[^/]*/[^/]*)*/[^/]+$
    validationErrorMessage: >-
      This must point to a document path, not a collection path from the root
      of the database. It must also not start or end with a '/' character.
    required: true
    immutable: false
    example: users/{uid}
  - param: OUTPUTFIELD
    label: Geohash field
    description: >-
      This specifies the field in the output document to store the geohash in.
    type: string
    validationRegex: ^\D([0-9a-zA-Z_.]{0,375})$
    validationErrorMessage: >-
      The field can only contain uppercase or lowercase letter, numbers,
      _, and . characters and must be less than 1500 bytes long. The field
      must also not start with a number.
    required: false
    default: hash
    immutable: false
    example: hash

Hassas parametreleri tanımlama

Artık kullanıcının belirttiği API anahtarını yönetmeniz gerekiyor. Bu, işlevde düz metin olarak depolanmaması gereken hassas bir dizedir. Bunun yerine, bu değeri Cloud Secret Manager'da saklayın. Bu, şifrelenmiş sırları depolayan ve bunların yanlışlıkla sızdırılmasını önleyen, buluttaki özel bir konumdur. Bu hizmetin kullanımı için geliştiricinin ödeme yapması gerekir ancak bu hizmet, API anahtarlarına ek bir güvenlik katmanı ekler ve sahtekarlık faaliyetlerini sınırlayabilir. Kullanıcı belgeleri, geliştiriciyi bunun ücretli bir hizmet olduğu konusunda uyarır. Böylece, faturalandırmada sürprizlerle karşılaşılmaz. Genel olarak, kullanımı yukarıda bahsedilen diğer dize kaynaklarına benzer. Tek fark, secret olarak adlandırılan türdür.

  • extension.yaml dosyasına aşağıdaki kodu ekleyin:

extension.yaml

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

resource özelliklerini parametre kullanacak şekilde güncelleyin

Daha önce de belirtildiği gibi, kaynağın nasıl gözlemlendiğini işlev değil kaynak tanımlar. Bu nedenle, yeni parametreyi kullanmak için locationUpdate kaynağının güncellenmesi gerekir.

  • extension.yaml dosyasına aşağıdaki kodu ekleyin:

extension.yaml

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

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

extension.yaml dosyasını kontrol edin

  • extension.yaml dosyasını inceleyin. Şuna benzer bir görünümde olacaktır:

extension.yaml

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

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

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

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

billingRequired: true

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

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

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

Koddaki parametrelere erişme

Tüm parametreler extension.yaml dosyasında yapılandırıldığına göre bunları index.ts dosyasına ekleyin.

  • index.ts dosyasında, varsayılan değerleri process.env.PARAMETER_NAME ile değiştirin. Bu, uygun parametre değerlerini getirir ve geliştiricinin Firebase projesinde dağıtılan işlev koduna yerleştirir.

index.ts

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

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

Normalde, ortam değişkeni değerleriyle boşluk kontrolleri yapmak istersiniz ancak bu durumda, parametre değerlerinin doğru şekilde kopyalandığına güvenirsiniz. Kod artık uzantı parametreleriyle çalışacak şekilde yapılandırıldı.

7. Kullanıcı belgeleri oluşturma

Kod, emülatörlerde veya Firebase uzantıları pazar yerinde test edilmeden önce uzantının dokümanı oluşturulmalıdır. Böylece geliştiriciler, uzantıyı kullandıklarında ne elde edeceklerini bilirler.

  1. İşlevselliği, yüklemeyle ilgili ön koşulları ve olası faturalandırma etkilerini açıklamak için kullanılan PREINSTALL.md dosyasını oluşturarak başlayın.

PREINSTALL.md

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

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

#### Third Party API Key

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

#### Additional setup

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

After installing this extension, you'll need to:

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

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

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

- This extension uses other Firebase and Google Cloud Platform services,
which have associated charges if you exceed the service's no-cost tier:
 - Cloud Firestore
 - Cloud Functions (Node.js 16+ runtime. [See
FAQs](https://firebase.google.com/support/faq#extensions-pricing))
 - [Cloud Secret Manager](https://cloud.google.com/secret-manager/pricing)
  1. Bu proje için README.md yazarken zaman kazanmak istiyorsanız kolaylık yöntemini kullanın:
firebase ext:info . --markdown > README.md

Bu işlem, PREINSTALL.md dosyanızın içeriğini ve extension.yaml dosyanızdaki uzantınızla ilgili ek ayrıntıları birleştirir.

Son olarak, uzantının geliştiricisini yeni yüklenen uzantıyla ilgili bazı ek ayrıntılar hakkında bilgilendirin. Geliştirici, yüklemeyi tamamladıktan sonra bazı ek talimatlar ve bilgiler alabilir. Ayrıca, yükleme sonrası bazı ayrıntılı görevler (ör. istemci kodunu ayarlama) alabilir.

  1. POSTINSTALL.md dosyası oluşturun ve aşağıdaki yükleme sonrası bilgilerini ekleyin:

POSTINSTALL.md

Congratulations on installing the geohash extension!

#### Function information

* **Firestore Trigger** - ${function:locationUpdate.name} was installed
and is invoked when both an x field (${param:XFIELD}) and y field
(${param:YFIELD}) contain a value.

* **Callable Trigger** - ${function:callableHash.name} was installed and
can be invoked by writing the following client code:
 ```javascript
import { getFunctions, httpsCallable } from "firebase/functions";
const functions = getFunctions();
const geoHash = httpsCallable(functions, '${function:callableHash.name}');
geoHash({ ${param:XFIELD}: -122.0840, ${param:YFIELD}: 37.4221 })
  .then((result) => {
    // Read result of the Cloud Function.
    /** @type {any} */
    const data = result.data;
    const error = data.error;
    if (error != null) {
        console.error(`callable error : ${error}`);
    }
    const result = data.result;
    console.log(result);
  });

İzleme

En iyi uygulama olarak, yüklü uzantınızın durumunu, kullanımını ve günlüklerini kontrol etme dahil olmak üzere etkinliğini izleyebilirsiniz.

The output rendering looks something like this when it's deployed:

<img src="img/82b54a5c6ca34b3c.png" alt="A preview of the latitude and longitude geohash converter extension in the firebase console"  width="957.00" />


## Test the extension with the full configuration
Duration: 03:00


It's time to make sure that the user-configurable extension is working the way it is intended.

* Change into the functions folder and ensure that the latest compiled version of the extensions exists. In the extensions project functions directory, call:

```console
npm run build

Bu işlem, işlevleri yeniden derleyerek en son kaynak kodun, bir emülatöre veya doğrudan Firebase'e dağıtıldığında uzantıyla birlikte dağıtıma hazır olmasını sağlar.

Ardından, uzantıyı test etmek için yeni bir dizin oluşturun. Uzantı mevcut işlevlerden geliştirildiği için, uzantının yapılandırıldığı klasörden test yapmayın. Bu klasörden test yapıldığında işlevler ve Firebase kuralları da dağıtılmaya çalışılır.

Firebase emülatörlerini kullanarak yükleme ve test etme

  1. Ana makine sisteminizde yeni bir dizin oluşturun ve firebase init kullanarak bu dizini Firebase projenize bağlayın.
mkdir sample-proj
cd sample-proj
firebase init --project=projectID-or-alias
  1. Uzantıyı yüklemek için bu dizinden firebase ext:install komutunu çalıştırın. /path/to/extension bölümünü, extension.yaml dosyanızı içeren dizinin mutlak yoluyla değiştirin. Bu işlem, uzantınızın yükleme sürecini başlatır ve yapılandırmayı Firebase'e veya emülatörlere göndermeden önce yapılandırmalarınızı içeren bir .env dosyası oluşturur.
firebase ext:install /path/to/extension
  • Projeyi yerel olarak dağıttığınız için Google Cloud Secret Manager yerine yerel bir dosya kullanmak istediğinizi belirtin.

da928c65ffa8ce15.png

  1. Yerel Emulator Suite'i başlatın:
firebase emulators:start

Gerçek bir Firebase projesiyle yükleme ve test etme

Uzantınızı gerçek bir Firebase projesine yükleyebilirsiniz. Testiniz için bir test projesi kullanmanız önerilir. Uzantınızın uçtan uca akışını test etmek istiyorsanız veya uzantınızın tetikleyicisi henüz Firebase Emulator Suite tarafından desteklenmiyorsa (Uzantılar Emulator seçeneğine bakın) bu test iş akışını kullanın. Emülatörler şu anda Cloud Firestore, Realtime Database ve Pub/Sub için HTTP isteğiyle tetiklenen işlevleri ve arka plan etkinliğiyle tetiklenen işlevleri desteklemektedir.

  1. Ana makine sisteminizde yeni bir dizin oluşturun ve firebase init kullanarak bu dizini Firebase projenize bağlayın.
cd ..
mkdir sample-proj
cd sample-proj
firebase init --project=projectID-or-alias
  1. Ardından, uzantıyı yüklemek için bu dizinden firebase ext:install komutunu çalıştırın. /path/to/extension bölümünü, extension.yaml dosyanızı içeren dizinin mutlak yoluyla değiştirin. Bu işlem, uzantınızın yükleme sürecini başlatır ve yapılandırmayı Firebase'e veya emülatörlere göndermeden önce yapılandırmalarınızı içeren bir .env dosyası oluşturur.
firebase ext:install /path/to/extension
  1. Firebase projenize dağıtın.
firebase deploy

Uzantıyı test etme

  1. firebase deploy veya firebase emulators:start komutunu çalıştırdıktan sonra, uygun şekilde Firebase konsolunun veya emülatörlerin web görünümünün Firestore sekmesine gidin.
  2. x alanı ve y alanı tarafından belirtilen koleksiyona bir belge ekleyin. Bu durumda, güncellenen dokümanlar u/{uid} konumunda bulunur. x alanı xv, y alanı ise yv değerini içerir.

Firestore kaydı eklemek için Firebase Emulators ekranı

  1. Uzantıyı başarıyla yüklediyseniz uzantı, iki alanı kaydettikten sonra dokümanda hash adlı yeni bir alan oluşturur.

Emülatörde, karma eklenmiş Firestore veritabanı ekranı

8. Tebrikler!

İlk Cloud Functions işlevinizi başarıyla Firebase uzantısına dönüştürdünüz.

Bir extension.yaml dosyası eklediniz ve geliştiricilerin uzantınızın nasıl dağıtılacağını seçebilmesi için bu dosyayı yapılandırdınız. Ardından, uzantının geliştiricilerinin uzantıyı ayarlamadan önce yapması gerekenler ve uzantıyı başarıyla yükledikten sonra atması gerekebilecek adımlar hakkında rehberlik sağlayan kullanıcı belgeleri oluşturdunuz.

Artık bir Firebase işlevini dağıtılabilir bir Firebase uzantısına dönüştürmek için gereken temel adımları biliyorsunuz.

Sırada ne var?