Bu kılavuzda, uzantılarınızı desteği sonlandırılan Firebase Extensions ortamından, kullanıcılarınızın kendi Firebase (2. nesil) kod tabanı için Cloud Functions ortamlarına yükleyip dağıttığı bir işleve nasıl taşıyacağınız gösterilmektedir.
Bu, önerilen taşıma yoludur. Firebase, resmi npm eşdeğerleri olan uzantıların bir listesini tutar. Bu kılavuzda, kendi uzantınızı nasıl oluşturacağınız açıklanmaktadır.
Bu kılavuzda, Stream Cloud Firestore to BigQuery uzantısı (firestore-bigquery-export) örnek olarak kullanılmıştır. Her bölüm, ilgili uzantının taşıma işleminden önceki ve sonraki (@firebase-function-kits/firestore-bigquery-export paketi olarak) görünümünü gösteren bir Uygulamalı örnek ile biter.
Uzantıları taşıma hakkında daha fazla bilgi ve yardım almak için kaydolun
Firebase Extensions sürümünden geçişle ilgili sorularınız varsa firebase-extensions-migrator-support-external@google.com adresinden bize ulaşabilirsiniz. Ayrıca 2. nesil işlevlerinizi paketleme, test etme ve dağıtma hakkında daha fazla bilgi ekleyerek kılavuzu güncellediğimizde bu gruba e-posta göndereceğiz.
Bu gruba katılmak için firebase-extensions-migrator-support-external+subscribe@google.com adresine mesaj gönderin. Bu adresten üyelik isteği e-postası gönderilir. Bu e-postayı yanıtlamanız gerekir. "Bu Gruba Katıl" düğmesini tıklamayın.
Başlamadan önce
Bu taşıma işlemini yazılı olarak tamamlamak için Cloud Functions ürününün aşağıdaki özelliklerini kullanacaksınız:
Parameterized Configuration.
extension.yamliçinde tanımladığınız her parametre, paket kodunuzda tanımlı bir parametre haline gelir.Bildirim temelli IAM rolleri ve gerekli API'ler.
extension.yamliçinde tanımladığınız her rol birrequiresRole(...)çağrısı, her API ise paket kodunuzda birrequiresAPI(...)çağrısı olur. Dağıtım sırasında Firebase KSA'sı, belirtilen rolleri yönetilen bir çalışma zamanı hizmet hesabına verir ve belirtilen API'leri sizin adınıza etkinleştirir.Cloud Functions kod tabanları için yaşam döngüsü olayları. Cloud Functions kod tabanları artık Firebase Extensions ile benzer yaşam döngüsü olaylarını destekliyor. Yükleme ve güncelleme zamanı kurulumunu
afterFirstDeploy(...)veafterRedeploy(...)yaşam döngüsü kancalarıyla bildirin. Bunlar,extension.yamliçinde beyan ettiğinizlifecycleEventsdeğerinin yerini alır.
Firebase Extensions kaynağını 2. nesil bir işleve taşıma
(İsteğe bağlı) Firebase Agent Skill ile otomatik taşıma
Resmi extension-to-functions-codebase yapay zeka temsilcisi becerisini kullanarak 1 ile 8 arasındaki adımları (kaynakları envantere ekleme, yükseltmeleri tetikleme, parametre ve gizli anahtar dönüşümleri, açıklayıcı IAM, yaşam döngüsü kancaları ve paketin README dosyasını oluşturma) otomatikleştirebilirsiniz.
Beceriyi yükleme
Siz veya yapay zeka kod yazma asistanınız (Firebase'da Gemini, Cursor, Claude Code, GitHub Copilot) beceriyi henüz yüklemediyseniz beceri CLI'ını kullanarak aşağıdaki komutu çalıştırın:
npx skills add firebase/agent-skills --skill extension-to-functions-codebase
Beceri projenize yüklendikten sonra yapay zeka kod yazma asistanınız, taşıma kurallarını ve dönüşüm adımlarını otomatik olarak uygular. Şu istemi kullanabilirsiniz:
"Lütfen extension-to-functions-codebase becerisindeki talimatları uygulayarak bu Firebase Extensions'ı yayınlanabilir bir 2. nesil Functions kiti paketine taşıyın."
1. Uzantıyı envantere ekleme
Uzantınızın envanterini çıkararak başlayın: Uzantının bildirdiği, gönderdiği ve belgelediği her şeyin tam listesi. Böylece her davranışın 2. nesil işlevde tanımlanmış bir hedefi olur ve taşıma sırasında hiçbir şey kaybolmaz.
Aşağıdakilerin her birini inceleyin ve bulduklarınızı not edin:
Parametrelerinizi, işlevlerinizi, etkinliklerinizi, IAM rollerinizi, gerekli API'lerinizi, gizli anahtarlarınızı ve yaşam döngüsü kancalarınızı tanımlayan
extension.yaml.functions/. Bu dizinde işlev kodunuz, bağımlılıklarınız, derleme yapılandırmanız, tetikleyicileriniz ve görev sırası işlevleriniz bulunur.README.md,PREINSTALL.mdvePOSTINSTALL.md.scripts/: İçe aktarma, dolgu, IAM, onarım veya taşıma yardımcı programlarının yanı sıra uzantıyla birlikte gönderdiğiniz diğer araçları içerir.
Ardından, extension.yaml içindeki her öğenin npm paketinde nereye gideceğine karar verin:
Kullanıcı yapılandırmasını Cloud Functions parametrelerine dönüştürün (4. adım).
Gizli anahtarları Cloud Functions gizli anahtarlarına dönüştürün (4. adım).
IAM rollerini
requiresRole(...)beyanlarına dönüştürün (6. adım).Gerekli Google API'lerini uygun yerlerde
requiresAPI(...)beyanlarına dönüştürün (6. adım).Yükleme ve güncelleme kancalarını
afterFirstDeploy(...)veafterRedeploy(...)beyanlarına dönüştürün (7. adım).Örnek kimliklerini
EXT_INSTANCE_IDbiçimindenFIREBASE_KIT_INSTANCE_IDbiçimine dönüştürün (4. adım).
Örnek: Cloud Firestore'ten BigQuery'e akış
firestore-bigquery-export/extension.yaml ve functions/ okunurken
şu envanter oluşturulur:
extension.yaml içinde |
Sayı/değer | Nereye gider? |
|---|---|---|
params |
25 (COLLECTION_PATH, DATASET_ID, TABLE_ID, DATASET_LOCATION, VIEW_TYPE, …) |
Cloud Functions parametreleri (4. adım) |
apis |
bigquery.googleapis.com |
requiresAPI(...) (6. adım) |
roles |
bigquery.dataEditor, datastore.user, bigquery.user |
requiresRole(...) (6. adım) |
resources |
1 etkinlik tetikleyici (fsexportbigquery) + görev sırası işlevleri (initBigQuerySync, setupBigQuerySync) |
Dışa aktarılan paket işlevleri (3. adım) |
lifecycleEvents |
onInstall → initBigQuerySync; onUpdate / onConfigure → setupBigQuerySync |
afterFirstDeploy/afterRedeploy (7. adım) |
| Örnek Kimliği | Kullanılmıyor (EXT_INSTANCE_ID okuma yok) |
Taşınacak öğe yok |
scripts/ |
import/ (dolgu), gen-schema-view/ |
Komut dosyası olarak tutulur (burada kapsam dışıdır) |
Analiz. Uzantı, type: secret parametresi beyan etmediği için 4. adımda gizli anahtarlar için taşınacak bir şey yoktur. Etkinlik tetikleyici zaten 2. nesildir. Yalnızca görev sırası işlevleri hâlâ 1. nesildir (3. adımda geçerlidir).
2. package.json dosyasını güncelleme
Uzantınızın package.json dosyasını güncelleyin. Bir uzantıyı taşıyorsanız bu, kök package.json olabilir. Tek bir depoda çok sayıda uzantıyı taşıyorsanız her uzantıya kendi paketini verin.
Minimum SDK sürümleri: Bağımlılık olarak firebase-functions >=
7.4.0 ve firebase-admin >=
14.2.0'yi tanımlayın. firebase-functions sürümünüzü eş bağımlılık olarak da beyan edin. Böylece kullanıcılarınızın Cloud Functions projesinde, kitaplığınızın yazıldığı SDK sürümü kullanılır.
{
"name": "<package-name>",
"version": "1.0.0",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"exports": {
".": {
"types": "./lib/index.d.ts",
"default": "./lib/index.js"
}
},
"engines": {
"node": "22"
},
"peerDependencies": {
"firebase-functions": "^7.4.0"
},
"dependencies": {
"firebase-functions": "^7.4.0",
"firebase-admin": "^14.2.0"
}
}
Örnek: Cloud Firestore'den BigQuery'e akış
Önce. Uzantının functions/package.json dosyası gizlidir, uzantı kimliğini adlandırır ve firebase-functions öğesini doğrudan bağımlılık olarak bildirir:
{
"name": "firestore-bigquery-export",
"main": "lib/index.js",
"private": true,
"dependencies": {
"@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4",
"firebase-admin": "^14.2.0",
"firebase-functions": "^6.3.2"
}
}
Sonra. Yayınlanabilir bir paket: kapsamlı ad, exports eşlemesi ve firebase-functions, peerDependencies konumuna taşındı:
{
"name": "@firebase-function-kits/firestore-bigquery-export",
"version": "0.1.0",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"exports": {
".": {
"types": "./lib/index.d.ts",
"default": "./lib/index.js"
}
},
"engines": {
"node": "22"
},
"peerDependencies": {
"firebase-functions": "^7.4.0"
},
"dependencies": {
"@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4",
"firebase-admin": "^14.2.0",
"firebase-functions": "^7.4.0"
}
}
3. İşlevleri 1. nesilden 2. nesle yükseltme
Uzantınız hâlâ 1. nesil işlevleri dışa aktarıyorsa her tetikleyiciyi 2. nesil eşdeğerine dönüştürün. firebase-functions/... modüllerinden içe aktarın ve tetikleyici seçeneklerinde çalışma zamanı ayarlarını iletin.
Cloud Functions 2. nesil yükseltme kılavuzuna bakın. Özellikle, 2. nesil yamalı etkinlik yapı sökümünü kullanarak yeniden yazma çalışmalarını en aza indirebilir ve işlev mantığınızı yeniden yazmaktan kaçınabilirsiniz. Bunun nedeni, 2. nesil SDK'nın v1 parametrelerini etkinlik nesnesinde alanlar olarak göstermesi, yapı sökümü yapılmış/adlandırılmış parametreleri kullanmanıza ve iş mantığınızı değiştirmeden korumanıza olanak tanımasıdır.
Önce. 1. nesil:
import * as functions from "firebase-functions/v1";
export const sync = functions.firestore
.document("{collectionId}/{documentId}")
.onWrite(async (change, context) => {
await handleWrite(change.before, change.after, context.params);
});
Sonra. 2. nesil:
import { onDocumentWritten } from "firebase-functions/firestore";
export const syncV2 = onDocumentWritten(
{ document: "{collectionId}/{documentId}" },
async ({ change, context }) =>
await handleWrite(change.before, change.after, context.params)
);
1. nesil ve 2. nesil işlevler arasındaki farkların kapsamlı bir listesi için Cloud Functions sürüm karşılaştırmasına bakın.
1. ve 2. nesil işlevler arasındaki önemli bir fark, 2. nesil işlevlerin tetikleyici kaynaklarıyla aynı yerde bulunması gerektiğidir. Kullanıcılar, 1. nesil işlevleri kullanan bir uzantıdan 2. nesil işlevleri kullanan bir kite geçiş yaptığında bu koşulu karşılamak için işlev konumlarını değiştirmeleri gerekebilir.
Mevcut konum korunduğundan, kullanıcılarınızın seçtiği Cloud Functions konumları taşıma işlemi sırasında bozulabilir. Uzantınızın etkinlikle tetiklenen işlevleri, kullanıcı tarafından sağlanan işlev konumuna bağlıysa uzantınıza yeni bir parametre ekleyerek etkinlik tetikleme konumunu toplamanızı ve bunu yeni işlev konumuna eşlemenizi öneririz.
Örnek: Cloud Firestore'ten BigQuery'e akış
defineString("DATABASE_REGION", {
label: "Firestore Instance Location",
description:
"Where is the Firestore database located? You can check your current database location at https://console.cloud.google.com/firestore/databases. The functions in this kit deploy to the Cloud Run region closest to this location.",
input: select({
"Multi-region (Europe - Belgium and Netherlands)": "eur3",
"Multi-region (United States)": "nam5",
"Multi-region (Iowa, North Virginia, and Oklahoma)": "nam7",
"Iowa (us-central1)": "us-central1",
// More locations...
})
});
// Firestore multi-region locations are not Cloud Run regions; deploying a
// function to one hard-fails, so they map to a region inside the multi-region.
const MULTI_REGION_TO_FUNCTION_REGION: Record<string, string> = {
nam5: "us-central1",
nam7: "us-central1",
eur3: "europe-west1",
};
/**
* Maps a Firestore database location to the Cloud Run region the functions
* should deploy to. The lookup is case-insensitive and ignores surrounding
* whitespace, as the CLI's own region handling is. Regional locations pass
* through lowercased; an unset or blank location returns `undefined`, meaning
* the functions declare no region.
*/
export function firestoreLocationToFunctionRegion(
location: string | undefined
): string | undefined {
const normalized = location?.trim().toLowerCase();
if (!normalized) {
return undefined;
}
return MULTI_REGION_TO_FUNCTION_REGION[normalized] ?? normalized;
}
const functionRegion = firestoreLocationToFunctionRegion(
process.env.DATABASE_REGION
);
export const fsexportbigquery = onDocumentWritten(
{
region: functionRegion,
// Other configuration
},
(event) => handleDocumentWrite(event, getHandlerContext())
);
Kit ilk kez dağıtıldığında kullanıcılardan DATABASE_REGION istenir ve işlevler yukarıdaki ilgili functionRegion konumuna dağıtılır. Böylece 2. nesil etkinlikle tetiklenen işlevlerindeki konum sorunları düzeltilir.
4. Uzantı parametrelerini ve gizli anahtarlarını dönüştürme
Parametreler
extension.yaml içinde tanımladığınız her parametre bir Cloud Functions parametresi olur.
Doğrudan ortam okumalarını dönüştürme:
const collectionPath = process.env.COLLECTION_PATH;
Cloud Functions parametreye dönüştürün:
import { defineString } from "firebase-functions/params";
import { onDocumentWritten } from "firebase-functions/firestore";
const collectionPath = defineString("COLLECTION_PATH");
// Pass the param directly when used as a placeholder (e.g. trigger path)
export const sync = onDocumentWritten(
{ document: collectionPath },
async (event) => {
// Call .value() to read the string inside a handler
const path = collectionPath.value();
await handleWrite(path, event);
}
);
İşleyici içindeki dizeyi okumak için collectionPath.value() kullanın. İşlev tetikleyici yolu gibi bir yer tutucunun beklendiği yerlerde doğrudan collectionPath kullanın.
Firebase CLI, parametrelerinizi bulur ve değerlerini .env, .env.<projectId> üzerinden okur veya dağıtım sırasında kullanıcılarınıza sorar. Mevcut bir kurulumdaki değerlerin aktarılması için aynı parametre adlarını kullanın.
Kodunuzda belirtilen parametre adlarını hiçbir şekilde değiştirmemeniz önemlidir. Uzantı taşıma işlemi, mevcut son kullanıcı parametre değerlerini otomatik olarak korur ancak bu yalnızca adlar değişmediğinde geçerlidir.
Örnek: Cloud Firestore'ten BigQuery'e akış
Önce. extension.yaml içinde tanımlanan ve config.ts içinde ham ortam değişkeni olarak okunan bir parametre:
# extension.yaml
- param: COLLECTION_PATH
label: Collection path
type: string
required: true
// functions/src/config.ts
collectionPath: process.env.COLLECTION_PATH,
Sonra. Bir defineString; CLI bunu keşfeder ve .env'den okur:
// src/config.ts
import { defineString } from "firebase-functions/params";
collectionPath: defineString("COLLECTION_PATH", {
label: "Collection path",
// We now support "nonEmpty: true" to ensure a value other than the empty string
// is entered, analogous to "required: true" in extension.yaml
input: { text: { nonEmpty: true } }
}),
Parametre adı değişmediğinden mevcut .env çalışmaya devam eder.
Örnek Kimliği
Uzantılar, örnek kimliklerini Uzantılar çalışma zamanı tarafından eklenen EXT_INSTANCE_ID konumundan okur. İşlev kitleri, örnek kimliklerini FIREBASE_KIT_INSTANCE_ID adresinden okur. Firebase CLI, her kit örneği için bu kimliği firebase.json içindeki instances eşlemesinde örneğin anahtarına ayarlar. CLI, bu bilgileri dağıtım zamanı keşfi sırasında, emülatörde ve dağıtılan işlevlere sağlar.
Örnek kimliği bir parametre olmadığından defineString ile tanımlamayın. Aslında FIREBASE_..., .env dosyalarında ayrılmış bir önek olduğundan kullanıcılar bu öneki ayarlayamaz veya geçersiz kılamaz. CLI'nın eklediği değerler, params sistemi tarafından görülemez. Doğrudan ortamdan okuyun:
// Before
const instanceId = process.env.EXT_INSTANCE_ID;
// After
const instanceId = process.env.FIREBASE_KIT_INSTANCE_ID;
Değişken yalnızca paketiniz kit olarak dağıtıldığında ayarlanır. Kodunuz bağımsız bir kod tabanı olarak da dağıtılıyorsa (9. adıma bakın) bunu isteğe bağlı olarak değerlendirin veya eksik olduğunda net bir mesajla hızlı bir şekilde başarısız olun. Uzantınız, örnek kimliğini kullanıcılara yönelik bir parametre olarak gösteriyorsa Firebase CLI artık değere sahip olduğundan bu parametreyi kaldırmanız gerekir.
Örnek: Kullanıcı verilerini silme
(Stream Cloud Firestore to BigQuery uzantısı, örnek kimliğini okumadığı için taşınacak bir şey yoktur. Kullanıcı Verilerini Silme uzantısı, Pub/Sub konularını adlandırmak için bu kimliği kullanır.)
Önce. Uzantılar'ın kaynakları için kullandığı ext- ön ekiyle config.ts içinde ham ortam değişkeni olarak okunur:
// functions/src/config.ts
discoveryTopic: `ext-${process.env.EXT_INSTANCE_ID}-discovery`,
deletionTopic: `ext-${process.env.EXT_INSTANCE_ID}-deletion`,
Sonra. Kullanıcıların konu adlarını geçersiz kılabilmesi için iki sıradan parametre için kullanılan FIREBASE_KIT_INSTANCE_ID'in basit bir process.env okuması:
// src/config.ts
const instanceId = process.env.FIREBASE_KIT_INSTANCE_ID;
// Non-empty defaults so Pub/Sub trigger bindings resolve during deploy
// discovery without freezing an empty topic name into the manifest.
discoveryTopicName: defineString("DISCOVERY_TOPIC_NAME", {
default: `kit-${instanceId}-discovery`,
}),
deletionTopicName: defineString("DELETION_TOPIC_NAME", {
default: `kit-${instanceId}-deletion`,
}),
Tetikleyici bağlamaları keşif sırasında çözümlendiğinden varsayılan değerler boş olmamalıdır. Dağıtım manifestine konu adı olarak boş bir varsayılan değer yazılır. Kit, kit bağlamı dışında çalıştırılmaya karşı da koruma sağlar. Değişken eksikse modül düzeyindeki varsayılan değer kit-undefined-discovery olarak değerlendirilir. Bu nedenle, yapılandırma yükleyici açıklayıcı bir hata ile başarısız olur:
// ...
const instanceId = process.env.FIREBASE_KIT_INSTANCE_ID;
if (!instanceId) {
throw new Error(
"FIREBASE_KIT_INSTANCE_ID is not set. It is provided automatically to " +
"kit instances by firebase-tools >= 15.32.0; deploy or emulate this " +
"kit with a supported CLI version."
);
}
// ...
Bu kontrol, bir işleyici yapılandırmasını ilk kez çözdüğünde çalışır. Bu nedenle, eksik bir değişken, kit-undefined-* konularına sessizce bağlı işlevler yerine net bir çalışma zamanı hatası oluşturur. Dağıtımın kendisini reddetmek için kontrolü modül kapsamında gerçekleştirin. Böylece kontrol, keşif sırasında çalışır. CLI, örnek kimliğini firebase.json öğesinden türettiği için yapılandırılabilir bir INSTANCE_ID yoktur ve birden fazla örnek arasında senkronize edilecek bir şey yoktur.
Gizli Anahtarlar
extension.yaml içinde, gizli anahtarları type: secret ile bildirirsiniz. Uzantılar çalışma zamanı bunları depolar ve bağlar. Böylece uzantı kodunuz process.env.PARAM_NAME değerini doğrudan okuyabilir. Tipik bir Cloud Functions kod tabanında her gizli anahtarı açıkça tanımlayıp bağlarsınız:
import { defineSecret } from "firebase-functions/params";
import { onRequest } from "firebase-functions/https";
const apiKey = defineSecret("API_KEY");
export const fn = onRequest({ secrets: [apiKey] }, handler);
Uzantınız bir npm paketine/kitine taşındıktan sonra gizli referanslar, son kullanıcının .env dosyasında yönetilir. Kodunuzda belirtilen gizli adları hiçbir şekilde değiştirmemeniz önemlidir. Taşıma sırasında son kullanıcı gizli anahtarları da taşınır.
Uygulamalı örnek: Cloud Firestore adresinden e-posta tetikleme
Önce. MAIL_COLLECTION ve SMTP_PASSWORD, config.ts içinde ham ortam değişkenleri olarak okunur:
# extension.yaml
- param: MAIL_COLLECTION
label: Email documents collection
type: string
default: mail
required: true
- param: SMTP_PASSWORD
label: SMTP password
type: secret
// functions/src/config.ts
mailCollection: process.env.MAIL_COLLECTION,
smtpPassword: process.env.SMTP_PASSWORD,
Sonra. Bir defineString ve bir defineSecret; CLI her ikisini de bulur ve .env dosyasından okur:
import { defineString, defineSecret } from "firebase-functions/params";
import { onDocumentWritten } from "firebase-functions/firestore";
const mailCollection = defineString("MAIL_COLLECTION", {
label: "Email documents collection",
default: "mail"
});
const smtpPassword = defineSecret("SMTP_PASSWORD", { label: "SMTP password" });
export const processQueue = onDocumentWritten(
{ document: `${mailCollection}/{documentId}`, secrets: [smtpPassword] },
async (event) => {
const collection = mailCollection.value();
const password = smtpPassword.value();
// ...
}
);
5. Dahili görev sırası çağrılarını taşıma
Bazı uzantılar, Firebase Admin SDK kullanarak işlev kodlarının içinden kendi görev sıralarına iş ekler. Bu, gönderilen bir görevi almaktan farklıdır (İşlevleri yükseltme ve Yaşam döngüsü kancalarını dönüştürme bölümlerinde ele alınmıştır). Burada kodunuz, queue.enqueue(...) yöntemini çağıran üreticidir.
Admin SDK'ın önceki sürümlerinde, aynı uzantıdaki bir görev sırası işlevini hedeflemek için uzantıların kendi uzantı örneği kimliklerini ikinci bir parametre olarak iletmesi gerekiyordu. firebase-admin 14.2.0 sürümünden itibaren bu işlem gerekli değildir ve önerilmez. Task Queue API artık varsayılan olarak aynı bağlamdaki (ör. bir uzantı veya kit) görev sıralarını hedefliyor. Kodunuzda bu parametreyi hem uzantı hem de bağımsız işlev olarak kaldırmak güvenlidir ve önerilir.
Bu parametrenin kaldırılması, taşınabilirlik ve ileriye dönük uyumluluk sağlar.
Sıraya alma çağrısıyla ilgili diğer her şey (locations/<region>/functions/<name> kaynak yolu, görev yükü ve yeniden deneme mantığınız) aynı kalır.
Cloud Tasks ile işlevleri sıraya ekleme hakkında daha fazla bilgi için Cloud Tasks ile işlevleri sıraya ekleme başlıklı makaleyi inceleyin.
Önce. 1. nesil uzantı:
import { getFunctions } from "firebase-admin/functions";
const queue = getFunctions().taskQueue(
`locations/${config.location}/functions/syncBigQuery`,
process.env.EXT_INSTANCE_ID, // extension instance ID, injected by the runtime
);
await queue.enqueue(taskData);
Sonra. 2. nesil uzantı:
import { getFunctions } from "firebase-admin/functions";
const queue = getFunctions().taskQueue(
`locations/${process.env.FUNCTION_REGION}/functions/syncBigQuery`
);
await queue.enqueue(taskData);
Sıraya alma çağrınız ön ekli bir kod tabanını hedefliyorsa keşfedilen işlev adı da ön ekli olur (örneğin, orders-syncBigQuery). Yedek işlev kiti örneğini inceleme ve yükleme ve İşlev kiti olarak test etme bölümlerine bakın.
6. Gerekli API'leri ve IAM rollerini bildirme
Uzantınızın IAM ve API gereksinimlerini extension.yaml yerine koda taşıyın:
import { requiresAPI, requiresRole } from "firebase-functions";
requiresAPI("bigquery.googleapis.com", "Needed to write changelog rows");
requiresRole("roles/bigquery.dataEditor");
requiresRole("roles/bigquery.user");
Bildirim temelli güvenlikte Firebase CLI, kod tabanı için yönetilen bir çalışma zamanı hizmet hesabı oluşturur veya günceller ve bu hesaba tüm beyan edilen rollerin birleşimini verir. Son API daha dar bir modeli desteklemediği sürece kod tabanındaki tüm işlevlerin bu rollerle çalıştığını kullanıcılarınız için belgeleyin.
Örnek: Cloud Firestore'ten BigQuery'e akış
Önce. extension.yaml içinde tanımlanır. Extensions çalışma zamanı, API'yi etkinleştirir ve rolleri yönetilen bir hesaba verir:
apis:
- apiName: bigquery.googleapis.com
roles:
- role: bigquery.dataEditor
- role: datastore.user
- role: bigquery.user
Sonra. requiresAPI ve requiresRole ile kodda beyan edilir:
import { requiresAPI, requiresRole } from "firebase-functions";
requiresAPI(
"bigquery.googleapis.com",
"Needed to write changelog rows and views"
);
requiresRole("roles/bigquery.dataEditor");
requiresRole("roles/datastore.user");
requiresRole("roles/bigquery.user");
Uzantınız Eventarc etkinlikleri yayınlıyorsa etkinlik yayınlamak için gerekli rolleri ve API'leri de ayarlamanız gerekir. Bu işlem daha önce extensions.yaml üzerinde herhangi bir değişiklik yapılmasına gerek kalmadan uzantılar tarafından gerçekleştiriliyordu. Bu işlemi kodunuzda koşullu olarak yapabilirsiniz. Böylece kit, bu izinleri yalnızca özel bir Eventarc kanalı kullanıldığında ister.
if (!!process.env.EVENTARC_CHANNEL) {
requiresRole("roles/eventarc.publisher");
requiresAPI(
"eventarcpublishing.googleapis.com",
"Publishes the extension's custom events to its Eventarc channel."
);
}
7. Yaşam döngüsü kancalarını dönüştürme
Uzantınız getExtensions().runtime() (ör. setProcessingState veya setFatalError) çağrısı yapıyorsa normal şekilde dağıtılan 2. nesil bir işlevden çağrıldığında hata vereceğinden bu çağrıları silin. Yaşam döngüsü durumu artık afterFirstDeploy ve afterRedeploy tarafından yönetiliyor. Bu durum izleme özelliği kullanılmıyor.
Firebase Extensions, bir kullanıcı bir uzantıyı yüklediğinde, güncellediğinde veya yeniden yapılandırdığında kurulumu çalıştırabilir. npm paketinizde, kodda eşdeğer yaşam döngüsü işlemlerini bildirin.
Tek seferlik kurulum için:
import { afterFirstDeploy } from "firebase-functions/lifecycle";
import { onTaskDispatched } from "firebase-functions/tasks";
export const runInitialSetup = onTaskDispatched(async (request) => {
await initializeResources(request.data);
});
afterFirstDeploy({
task: {
function: "runInitialSetup",
body: {}
}
});
Yapılandırma veya kod güncellemeleri için:
import { afterRedeploy } from "firebase-functions/lifecycle";
afterRedeploy({
task: {
function: "runInitialSetup",
body: { reconcile: true }
}
});
Yaşam döngüsü işlemlerinizi idempotent yapın. Gönderme veya yürütme başarısız olursa kullanıcılarınızın bunları manuel olarak yeniden çalıştırması gerekebilir:
firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME
firebase functions:lifecycle:run afterRedeploy CODEBASE_NAME
Örnek: Cloud Firestore'ten BigQuery'e akış
Önce. lifecycleEvents, extension.yaml içinde, Uzantılar çalışma zamanı tarafından desteklenir:
lifecycleEvents:
onInstall:
function: initBigQuerySync
processingMessage: Configuring BigQuery Sync.
onUpdate:
function: setupBigQuerySync
processingMessage: Configuring BigQuery Sync
onConfigure:
function: setupBigQuerySync
processingMessage: Configuring BigQuery Sync
Sonra. Kodda tanımlanır; görev, ilk dağıtımda BigQuery sağlar:
import { afterFirstDeploy, afterRedeploy } from "firebase-functions/lifecycle";
afterFirstDeploy({ task: { function: "initBigQuerySync" } });
afterRedeploy({ task: { function: "setupBigQuerySync" } });
Temel hazırlık işlemi idempotent olduğundan yeniden çalıştırma işlemi veri kümesini, tabloyu ve görünümleri mutabık kılar.
Kullanıcılar firebase functions:lifecycle:run afterFirstDeploy
CODEBASE_NAME ile manuel olarak yeniden çalıştırabilir.
8. Kullanıcılarınız için doküman kurulumu
En azından aşağıdakileri açıklayan bir paket README yazın:
- Paketin gerektirdiği
.envdeğerleri. - Paketin gerektirdiği gizli anahtarlar ve mevcut gizli anahtar değerlerinin nasıl taşınacağı.
- Paketin
requiresRole(...)ile beyan ettiği IAM rolleri. - Paketin etkinleştirdiği veya gerektirdiği Google API'leri.
- Paketin bildirdiği yaşam döngüsü kancaları ve bunları manuel olarak yeniden çalıştırma yöntemi.
- Faturalandırma notları.
- Orijinal uzantıya kıyasla nelerin değiştiği.
- Paketin örnek kimliğini (CLI tarafından ayarlanan
FIREBASE_KIT_INSTANCE_ID) nasıl aldığı ve tüm örnek işlevlerininkit-<instanceId>-ön ekiyle nasıl dağıtıldığı.
Örnek: Cloud Firestore'ten BigQuery'e akış
README paketi, somut bir "değişiklikler" tablosu içerir:
| Endişe | Uzantı olarak | @firebase-function-kits/firestore-bigquery-export olarak |
|---|---|---|
| Yapılandırma | Uzantı parametreleri | .env üzerinden Cloud Functions parametre |
| IAM ile yönetin. | Uzantılar tarafından verilen izinler | requiresRole(...), dağıtım sırasında uygulandı |
| Temel hazırlık yapılıyor | Uzantılar tarafından gerçekleştirilen yaşam döngüsü görevi | afterFirstDeploy/afterRedeploy görev |
| İşlev adları | ext-<instanceId>-fsexportbigquery |
fsexportbigquery (isteğe bağlı olarak ön ekli) |
| Örnek Kimliği | Uzantılar tarafından yerleştirilen EXT_INSTANCE_ID |
FIREBASE_KIT_INSTANCE_ID, firebase.json tarafından KSA'dan ayarlandı |
9. 2. nesil işlevinizi test etme
Artık dağıtıldığında uzantınızın yeni bir yüklemesiyle aynı şekilde davranan 2. nesil bir işleviniz olmalıdır. Sonraki adım, süreçte yanlışlıkla ortaya çıkan sorunları doğrulamak ve düzeltmektir.
Varsayılan bölge veya CPU gibi genel seçenekleri ayarlamak için setGlobalOptions işlevini yalnızca kitinizi bağımsız bir 2. nesil işlev olarak dağıtırken çağırabilirsiniz. Kitiniz bir npm paketi olarak yüklendiğinde kullanıcılarınız bu parametreleri yapılandırmak için sarmalama kodlarında setGlobalOptions işlevini çağırır ve bu işlem iki kez gerçekleşirse uyarı alırlar.
FIREBASE_KIT_INSTANCE_ID ortam değişkenini kontrol ederek bu çağrıyı koruyabilirsiniz:
import { setGlobalOptions } from "firebase-functions";
if (!process.env.FIREBASE_KIT_INSTANCE_ID) {
setGlobalOptions({
region: "us-east1",
maxInstances: 10,
});
}
firebase-tools
>= 15.32.0 kullandığınızdan emin olun ve dönüştürülen 2. nesil işlevinizi, davranışını test etmek için uygun kaynaklara sahip bir test projesine dağıtın. Uzantınızı test etmek için oluşturduğunuz bir test projeniz varsa aşağıdaki komutu çalıştırın:
firebase deploy --only functions
Parametre değerlerini girmenizi isteyen sihirbazı, uzantı için Firebase konsolundaki yükleme formunu doldurduğunuz şekilde doldurun.
Örnek: Cloud Firestore'ten BigQuery'e akış
Cloud Firestore ile BigQuery arasındaki senkronizasyonu uçtan uca doğrularız:
- Firebase konsolunun Cloud Firestore sayfasında,
COLLECTION_PATH(users) olarak ayarladığınız koleksiyonu oluşturun (henüz oluşturulmamışsa). - Herhangi bir değer içeren alanlara sahip
bigquery-mirror-testadlı bir doküman oluşturun. Google Cloud konsolunun BigQuery sayfasında ham değişiklik günlüğü tablosunu sorgulayın. Doküman oluşturma işlemini kaydeden tek bir satır içermelidir:
SELECT * FROM `PROJECT_ID.analytics.users_raw_changelog`Mevcut tek doküman (
bigquery-mirror-test) için en son değişiklik etkinliğini döndürmesi gereken en son görünümü sorgulayın:SELECT * FROM `PROJECT_ID.analytics.users_raw_latest`Cloud Firestore içindeki
bigquery-mirror-testdokümanını silin. En son görünümden kaybolur ve ham değişiklik günlüğü tablosuna birDELETEetkinliği eklenir.Tek bir dokümanın tüm geçmişini şunlarla inceleyebilirsiniz:
SELECT * FROM `PROJECT_ID.analytics.users_raw_changelog` WHERE document_name = "bigquery-mirror-test" ORDER BY timestamp ASC
Uzantıyı test etme işleminden farkları:
- Tetikleyici,
ext-<instanceId>-fsexportbigqueryolarak değil,fsexportbigquery(normal bir 2. nesil işlev olarak dağıtıldığında ve kit olmadığında ön ek kullanılmaz) olarak dağıtılır. Cloud Functions kontrol panelinde ve günlüklerinde bu adı arayın. - Kodunuz artık Firebase Local Emulator Suite içinde normal işlevler olarak çalışır.
Emülatörde kullanılacak parametrelerin değerini
.env.localile ayarlayabilirsiniz. Cloud Functions birim testi bölümünde açıklandığı gibifirebase-functions-testSDK'sını kullanarak kodunuzu birim testine de tabi tutabilirsiniz. - Temel hazırlık artık Uzantılar çalışma zamanı tarafından yönetilmez. Dağıtımdan sonra değişiklik günlüğü tablosu eksikse kurulum görevini manuel olarak yeniden çalıştırın:
firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME. Görev, eş güçlü olduğundan yeniden çalıştırıldığında veri kümesini, tabloyu ve görünümleri mutabık kılar. - Parametre değerleri, yükleme formu yerine
.envüzerinden alınır. Bu nedenle,.envtamamlandıktan sonrafirebase deployyeniden çalıştırıldığında etkileşimli olmaz.
10. İşlev kitinizi npm'de yayınlama
Uzantıdan 2. nesil işleve dönüşümünüzü doğruladıktan sonra, aşağıdaki kılavuzlardan birini kullanarak uçtan uca test için npm'de bir sürüm adayı yayınlayabilirsiniz:
- Kapsamsız herkese açık paketler oluşturma ve yayınlama
- Kapsamlı herkese açık paketler oluşturma ve yayınlama
Kitiniz npm'de yayınlandığında firebase functions:kits:install ile yüklenebilir ve uzantınızın resmi alternatifi olarak listelenir.
Öncelikle bir sürüm adayı yayınlamanızı önemle tavsiye ederiz. Kitler paket adı ve sürümüne göre yüklenir. Bu nedenle, yayın öncesi sürüm sayesinde tamamlanmamış bir paketi varsayılan latest etiketiyle yükleyen kullanıcılara göstermeden gerçek yükleme akışını kayıt defterine göre test edebilirsiniz.
Yayınlamadan önce:
- Bir paket adı seçin. Hem kapsamlı hem de kapsamsız adlar kullanılabilir (yukarıdaki kılavuzlara bakın). Kapsamlı paketlerin varsayılan olarak gizli olduğunu unutmayın. Bu nedenle
--access publicparametresini iletin. - Derleme yapın ve nelerin gönderildiğini kontrol edin.
mainvetypes, derlenmiş çıkışınızı (örneğimizdelib/) işaret eder. Bu nedenle, bu dizin yayınlanan tar dosyasına dahil edilmelidir..npmignoreveyafilesizin verilenler listesi kullanın ve sonucunpm pack --dry-runile inceleyin. Derlemenizi çalıştıran birprepublishOnlykomut dosyası, eski çıkışın yayınlanmasını önler.
Yayınlamayı varsayılan olarak güvenli hale getiren package.json ekleme:
{
"files": ["lib", "README.md", "CHANGELOG.md"],
"publishConfig": { "access": "public", "tag": "next" },
"scripts": {
"build": "tsc -b",
"prepublishOnly": "npm run build && npm test"
}
}
"publishConfig": { "tag": "next" } alanı, düz bir npm
publish değerinin hiçbir zaman latest değerinin üzerine yazmamasını sağlar.
Sürüm adayı oluşturma:
Örneğin, sürümü yerel olarak 0.0.2-rc.3 değerinden 0.0.2-rc.4 değerine yükseltmek için
(package.json, depo kökündeyse bu işlem Git'te kaydeder ve etiketler):
npm version prerelease --preid rc
Sürüm adayını yayınlamak ve @your-org/your-kit@0.0.2-rc.4 paketini npm'de next etiketiyle kaydetmek için:
npm publish
npm web sitesinin yeni sürümü göstermesi birkaç dakika sürebilir. npm view, kayıt defterini doğrudan okur:
npm view @your-org/your-kit versions dist-tags
Bu kılavuzdaki 11. adım ve 12. adım tamamlandıktan sonra paketi kararlı sürüme yükseltebilirsiniz:
npm version 0.0.2
npm publish --tag latest
npm dist-tag add @your-org/your-kit@0.0.2 next
npm-shrinkwrap.json ile ilgili not: Paketinize bir npm-shrinkwrap.json dosyası eklemenizi önemle tavsiye ederiz. Eklememeniz durumunda CLI, yükleme sırasında kullanıcıları uyarır. Bu sayede kullanıcılar, test ettiğiniz bağımlılıkları kullanır ve tedarik zinciri saldırılarına karşı korunur. Ancak shrinkwrap, kullanıcılarınızın projelerinde Cloud Functions derlemesi (npm ci) de dahil olmak üzere kelimesi kelimesine uygulanır. Bu durumda, yalnızca geliştirme amaçlı girişler EBADPLATFORM ile başarısız olabilir. Yayınlanan shrinkwrap kopyasından "dev": true girişlerini ve devDependencies öğesini çıkarmanız gerekebilir.
Örnek: Cloud Firestore'ten BigQuery'e akış
Dördüncü sürüm adayı yayınlandığında kitin package.json:
{
"name": "@firebase-function-kits/firestore-bigquery-export",
"version": "0.0.2-rc.4",
"repository": {
"type": "git",
"url": "https://github.com/firebase/extensions.git",
"directory": "kits/firestore-bigquery-export"
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
"engines": { "node": "22" },
"scripts": { "build": "tsc -b" }
}
Bu durumda kitin bir monorepo'da bulunduğunu unutmayın. Bu nedenle, npm kayıt defteri bağlantısının doğru klasörü işaret etmesi için repository.directory ifadesini eklemek önemlidir. CHANGELOG.md, bekleyen sürümle ilgili notları içerir.
11. İşlev kiti olarak test etme
Kitinizi yayınladıktan sonra npm kullanarak test etmenizi öneririz.
firebase-tools'in >= 15.32.0 sürümünü kullandığınızdan emin olun ve kiti yükleyin:
firebase functions:kits:install --package <your-package-name>@<your-prerelease-version>
Bu komut, paketinizi npm'den indirir, kitiniz için yeni bir kaynak dizininde ayarlar ve uzantı yükleme akışına benzer şekilde ilk örneği yapılandırma konusunda size yol gösterir. Paketinizi yerel olarak yükleyip ayarladıktan sonra Google Cloud projenizde kaynakları oluşturmak için bir dağıtım çalıştırın:
firebase deploy --only functions:<your-kit-instance-id>
Yükleme işleminden sonra Firebase CLI, yükleme sırasında seçtiğiniz örnek kimliğini içeren benzer bir dağıtım komutu yazdırır.
9. adımda 2. nesil işlevinizi test etme Artık kitleri kullanarak dağıtım yaptığınız için işlevleriniz kit-<instance-id>-<method-name> ön ekiyle adlandırılır. Bu sayede kitler birden fazla örneğe sahip olabilir ve aynı işlevi bir projede her biri benzersiz bir ada sahip olacak şekilde birden fazla kez dağıtabilir.
12. Test taşıma işlemini değiştirme
Çalışan bir uzantı örneği oluşturabilir ve ardından işlev kitinizi geçiş alternatifi olarak test etmeyi tamamlamak için kullanıcı geçiş rehberini (firebase ext:migrate --package veya işlev kiti CLI komutlarını kullanarak) kullanabilirsiniz.
13. Kullanıcıları ve Google'ı resmi uzantı değişikliğiniz hakkında bilgilendirme
İşlev kiti değişiminiz hazır olduğunda ve kullanıcıların geçiş yapması gereken bir npm paketi olarak sunulduğunda hem kullanıcılarınızı hem de Google'ı bu resmi değişim hakkında bilgilendirin. Uzantınızı barındıran GitHub deposundaki README.md dosyasını aşağıdaki bilgilerle güncelleyin:
<!-- FIREBASE_EXTENSION_REPLACEMENT: extension="<your-extesion-id>" package="<your-npm-package-name>" -->
> [!WARNING]
> **Deprecation Notice:** The Firebase Extension `<your-extension>` is deprecated. Migrate to the [<your-npm-package-name>](<link-to-your-npm-package>) package.
Google, bilinen uzantıların BENİOKU dosyalarını <!--
FIREBASE_EXTENSION_REPLACEMENT: extension="firebase/firestore-bigquery-export"
package="@firebase-function-kits/firestore-bigquery-export" --> gibi yorumlar için tarar ve bunu, firebase-tools deposunda replacements.json olarak depolanan resmi değişiklik kayıt defterimizi doldurmak için kullanır.
Uzantınız için hangi README.md öğelerinin taranacağını görmek üzere replacements.json sayfasını da kontrol edebilirsiniz. Resmi yedek listesi haftalık olarak güncellenir.
Örnek: Cloud Firestore'ten BigQuery'e akış
firestore-bigquery-export uzantısı
README.md
şunları içerir:
<!-- FIREBASE_EXTENSION_REPLACEMENT: extension="firebase/firestore-bigquery-export" package="@firebase-function-kits/firestore-bigquery-export" -->
> [!WARNING]
> **Deprecation Notice:** The Firebase Extension `firebase/firestore-bigquery-export` is deprecated. Please migrate to the [`@firebase-function-kits/firestore-bigquery-export`](https://www.npmjs.com/package/@firebase-function-kits/firestore-bigquery-export) package.