הכנת תוספים ל-Firebase להעברה ל-Cloud Functions

במדריך הזה מוסבר איך להעביר את התוספים שלכם מהסביבה Firebase Extensions שיצאה משימוש לפונקציה שהמשתמשים שלכם מתקינים ומפעילים ב-Cloud Functions שלהם עבור Firebase (דור שני) בסיס קוד.

זו הדרך המומלצת להעברה. ‫Firebase ינהל רשימה של תוספים עם מקבילות רשמיות ב-npm. במדריך הזה מוסבר איך ליצור תוסף משלכם.

במדריך הזה, נעשה שימוש בתוסף Stream Firestore to BigQuery (firestore-bigquery-export) כדוגמה. בסוף כל קטע יש דוגמה עם הסבר שמראה איך התוסף נראה לפני ההעברה ואיך הוא נראה אחרי ההעברה, בתור חבילת ‎@firebase/firestore-bigquery-export.

הרשמה לקבלת מידע נוסף ועזרה בהעברת תוספים

אם יש לך שאלות לגבי המעבר מ-Firebase Extensions, אפשר לפנות אלינו בכתובת firebase-extensions-migrator-support-external@google.com. נשלח אימייל לקבוצה הזו גם כשנעדכן את המדריך עם מידע נוסף על אריזה, בדיקה והפצה של פונקציות מהדור השני.

כדי להצטרף לקבוצה הזו, צריך לשלוח הודעה לכתובת firebase-extensions-migrator-support-external+subscribe@google.com, ולקבל בתגובה אימייל עם בקשה להצטרפות. צריך להשיב לאימייל הזה ולא ללחוץ על הלחצן 'הצטרפות לקבוצה הזו'.

לפני שמתחילים

כדי להשלים את ההעברה הזו, תשתמשו בתכונות הבאות של Cloud Functions:

  • הגדרה עם פרמטרים. כל פרמטר שמצהירים עליו ב-extension.yaml הופך לפרמטר מוגדר בקוד החבילה.

  • תפקידי IAM דקלרטיביים וממשקי API נדרשים כל תפקיד שמצהירים עליו ב-extension.yaml הופך לקריאה ל-requiresRole(...), וכל API הופך לקריאה ל-requiresAPI(...) בקוד הפונקציה. בזמן הפריסה, Firebase CLI מקצה את התפקידים שהוגדרו לחשבון של שירות זמן ריצה מנוהל, ומפעיל את ממשקי ה-API שהוגדרו בשמכם.

  • אירועים במחזור החיים של בסיסי קוד Cloud Functions. בבסיסי קוד Cloud Functions יש עכשיו תמיכה באירועים של מחזור חיים בדומה ל-Firebase Extensions. הצהרה על הגדרות בזמן ההתקנה ובזמן העדכון באמצעות ה-lifecycle hooks‏ afterFirstDeploy(...) ו-afterRedeploy(...). הם מחליפים את התג lifecycleEvents שמוצהר ב-extension.yaml.

יהיו זמינים.

מלאי התוסף

מתחילים במלאי של התוסף: רשימה מלאה של כל מה שהתוסף מצהיר, שולח ומתעד, כך שלכל התנהגות תהיה יעד מוגדר בפונקציה מהדור השני, ושום דבר לא יאבד במהלך ההעברה.

צריך לבדוק את כל אחד מהדברים הבאים ולרשום את מה שמוצאים:

  • extension.yaml, שבו מצהירים על הפרמטרים, הפונקציות, האירועים, תפקידי ה-IAM, ממשקי ה-API הנדרשים, הסודות וה-lifecycle hooks.

  • functions/, שמכיל את קוד הפונקציה, יחסי התלות, הגדרות הבנייה, הטריגרים והפונקציות של תור המשימות.

  • README.md,‏ PREINSTALL.md ו-POSTINSTALL.md, שכוללים שלבי הגדרה, אזהרות והערות בנושא חיוב.

  • scripts/, שמכיל כלי ייבוא, מילוי חוסרים, IAM, תיקון או העברה, וכל כלי אחר שאתם שולחים יחד עם התוסף.

לאחר מכן, לכל פריט ב-extension.yaml, מחליטים איפה הוא יופיע בחבילת npm:

  • המרת הגדרות משתמשים לפרמטרים של Cloud Functions (קטע 5).

  • המרת סודות לCloud Functions סודות (קטע 6).

  • המרת תפקידי IAM להצהרות requiresRole(...) (סעיף 8).

  • המרת ממשקי Google API נדרשים להצהרות requiresAPI(...) במקומות המתאימים (סעיף 8).

  • המרת ווים של התקנה ועדכון להצהרות afterFirstDeploy(...) ו-afterRedeploy(...) (סעיף 8).

דוגמה מעשית: העברת נתונים מ-Firestore ל-BigQuery

קריאה של firestore-bigquery-export/extension.yaml ושל functions/ יוצרת את המלאי הבא:

ב-extension.yaml ספירה / ערך לאן המידע מועבר
params ‫25 (COLLECTION_PATH, DATASET_ID, TABLE_ID, DATASET_LOCATION, VIEW_TYPE, …) Cloud Functions פרמטרים (סעיף 5)
apis bigquery.googleapis.com requiresAPI(...) (סעיף 7)
roles bigquery.dataEditor, datastore.user, bigquery.user requiresRole(...) (section 7)
משאבים טריגר אחד לאירוע (fsexportbigquery) + פונקציות של תור משימות (initBigQuerySync, ‏ setupBigQuerySync) פונקציות של חבילה שיוצאו (סעיף 3)
lifecycleEvents onInstall → initBigQuerySync; onUpdate / onConfigure → setupBigQuerySync afterFirstDeploy / afterRedeploy (סעיף 9)
scripts/‎ import/ (backfill), gen-schema-view/ נשמרים כסקריפטים (לא רלוונטיים כאן)

התוסף לא מגדיר סוג: פרמטרים סודיים, ולכן אין מה להעביר בסעיף 6 במדריך הזה. הטריגר לאירוע כבר שייך לדור השני. רק הפונקציות של תור המשימות עדיין שייכות לדור הראשון (רלוונטי בקטע 3).

עדכון הקובץ package.json

מעדכנים את קובץ package.json של התוסף. אם מעבירים תוסף אחד, אפשר להשתמש בתיקיית הבסיס package.json. אם מעבירים הרבה תוספים במאגר אחד, צריך לתת לכל תוסף חבילה משלו.

גרסאות SDK מינימליות. מגדירים את firebase-functions >= 7.3 ואת firebase-admin >= 14.2.0 כתלות. צריך להצהיר על הגרסה של firebase-functions כעל peer dependency

{
  "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.3.0"
  },
  "dependencies": {
    "firebase-functions": "^7.3.0",
    "firebase-admin": "^14.2.0"
  }
}

צריך להצהיר על firebase-functions כתלות ברמת העמיתים בנוסף לתלות הרגילה, כדי שלפרויקט Cloud Functions של המשתמשים תהיה אותה גרסה של ה-SDK שבה נכתבה הספרייה.

דוגמה מעשית: העברת נתונים מ-Firestore ל-BigQuery

לפני. הקובץ functions/package.json של התוסף הוא פרטי, מצוין בו מזהה התוסף ומוצהר בו ש-firebase-functions הוא תלות ישירה:

{
  "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"
  }
}

אחרי. חבילה שאפשר לפרסם: שם עם היקף, מפת ייצוא ו-firebase-functions הועבר אל peerDependencies:

{
  "name": "@firebase/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.3.0" },
  "dependencies": {
      "@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4",
      "firebase-admin": "^14.2.0",
      "firebase-functions": "^7.3.0"
    }
}

שדרוג פונקציות מדור ראשון לדור שני

אם התוסף עדיין מייצא פונקציות מהדור הראשון, צריך להמיר כל פונקציה למקבילה שלה מהדור השני. מייבאים ממודולי firebase-functions/... ומעבירים הגדרות של זמן ריצה באפשרויות הפונקציה.

אתם יכולים לצמצם את המאמצים הנדרשים לכתיבה מחדש באמצעות פירוק מובנה של אירועים בגרסה השנייה של ה-SDK, ולהימנע מכתיבה מחדש של הלוגיקה של הפונקציה, כי גרסה 2 של ה-SDK חושפת עכשיו את הפרמטרים של גרסה 1 כשדות באובייקט האירוע. כך תוכלו להשתמש בפרמטרים מפורקים או בעלי שם, ולשמור על הלוגיקה העסקית שלכם ללא שינוי.

לפני. דור ראשון:

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

אחרי. דור שני:

import { onDocumentWritten } from "firebase-functions/firestore";

export const syncV2 = onDocumentWritten(
  { document: "{collectionId}/{documentId}" },
  async ({change,context}) =>
    await handleWrite(change.before, change.after, context.params);
);
יהיו זמינים.

ראו את Cloud Functions השוואת גרסאות לקבלת רשימה מקיפה של הבדלים בין פונקציות דור ראשון לדור שני.

המרת פרמטרים וסודות של תוספים

פרמטרים של המרה

כל פרמטר שמצהירים עליו ב-extension.yaml הופך לפרמטר Cloud Functions.

המרת קריאות ישירות של הסביבה:

const collectionPath = process.env.COLLECTION_PATH;

לתוך הפרמטרים Cloud Functions:

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

משתמשים ב-collectionPath.value() כדי לקרוא את המחרוזת בתוך handler, וב-collectionPath ישירות במקום שבו צפוי פלייסהולדר, כמו נתיב להפעלת פונקציה.

ממשק Firebase CLI מאתר את הפרמטרים וקורא את הערכים שלהם מ-‎ .env,‏ ‎.env.projectId או מציג למשתמשים הנחיות במהלך הפריסה. חשוב להשתמש באותם שמות פרמטרים כדי שהערכים מההתקנה הקיימת יועברו.

חשוב לא לשנות את שמות הפרמטרים שהוגדרו בקוד בשום אופן. העברת התוסף תשמור באופן אוטומטי את ערך הפרמטר הקיים של משתמש הקצה, אבל רק אם השמות לא ישתנו.

דוגמה: העברת נתונים מ-Firestore ל-BigQuery לפני. פרמטר שהוגדר ב-extension.yaml, נקרא כמשתנה סביבה גולמי ב-config.ts:

# extension.yaml
-   param: COLLECTION_PATH
  label: Collection path
  type: string
  required: true
// functions/src/config.ts
collectionPath: process.env.COLLECTION_PATH,

אחרי.defineString אחד; ה-CLI מאתר אותו וקורא מ-.env:

// 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, analagous to "required: true" in extensions.yaml
  input: { text: { nonEmpty: true} }
}),

שם הפרמטר לא משתנה, כך שקובץ ‎ .env קיים ימשיך לפעול.

המרת סודות

ב-extension.yaml, מגדירים סודות באמצעות type: secret. סביבת זמן הריצה של התוספים מאחסנת אותם ומקשרת אותם, כך שקוד התוסף יכול לקרוא את process.env.PARAM_NAME ישירות. בבסיס קוד טיפוסי של Cloud Functions, אתם מצהירים על כל סוד ומקשרים אותו באופן מפורש:

import { defineSecret } from "firebase-functions/params";
import { onRequest } from "firebase-functions/https";

const apiKey = defineSecret("API_KEY");
export const fn = onRequest({ secrets: [apiKey] }, handler);

אחרי שההרחבה תועבר לחבילת npm או לערכת כלים, ההפניות לסודות ינוהלו בקובץ .env של משתמש הקצה. חשוב לא לשנות את שמות הסודות שמוצהרים בקוד בכלל. במהלך ההעברה, הסודות של משתמשי הקצה יועברו בהתאם.

דוגמה: שליחת אימייל מ-Cloud Firestore

לפני. המשתנים MAIL_COLLECTION ו-SMTP_PASSWORD נקראים כמשתני סביבה גולמיים בקובץ config.ts:

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

אחרי.defineString אחד ו-defineSecret אחד; ה-CLI מאתר את שניהם וקורא מ-.env

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

העברת קריאות פנימיות לתור משימות

חלק מהתוספים מוסיפים עבודות לתורי המשימות שלהם מתוך קוד הפונקציה שלהם, באמצעות Firebase Admin SDK. זה שונה מקבלת משימה שנשלחה (הנושאים האלה מוסברים בקטע שדרוג פונקציות ובקטע המרת ווים של מחזור חיים). הקוד שלכם הוא producer שקורא ל-queue.enqueue(...).

בגרסאות קודמות של Admin SDK, תוספים נדרשו להעביר את מזהה מופע התוסף שלהם כפרמטר שני כדי לטרגט פונקציה של תור משימות באותו תוסף. החל מגרסה 14.2.0 של `firebase-admin`, אין צורך בכך ולא מומלץ לעשות זאת. ה-API של תור המשימות יכוון עכשיו כברירת מחדל לתורי משימות באותו ההקשר (למשל, תוסף). מומלץ להסיר את הפרמטר הזה מהקוד, גם כתוסף וגם כפונקציות עצמאיות. הסרה של הפרמטר הזה מבטיחה ניידות ותאימות קדימה.

כל שאר הפרטים לגבי הקריאה להוספה לתור – נתיב המשאב locations/region/functions/name, מטען הייעודי (payload) של המשימה והלוגיקה של הניסיון החוזר – נשארים ללא שינוי.

פרטים נוספים על הוספת פונקציות לתור באמצעות Cloud Tasks זמינים במאמר /docs/functions/task-functions.

לפני. תוסף דור ראשון

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

אחרי. תוסף דור שני

import { getFunctions } from "firebase-admin/functions";
import { region } from "firebase-functions/params";

const queue = getFunctions().taskQueue(
  `locations/${region.value()}/functions/syncBigQuery`);
await queue.enqueue(taskData);

אם הקריאה לפונקציה enqueue מכוונת לבסיס קוד עם קידומת, גם לשם הפונקציה שמתגלה תתווסף קידומת (לדוגמה, orders-syncBigQuery).

הצהרה על ממשקי API ותפקידים ב-IAM שנדרשים

מעבירים את דרישות ה-IAM וה-API של התוסף מ-extension.yaml אל code:

import { requiresAPI, requiresRole } from "firebase-functions"

requiresAPI("bigquery.googleapis.com", "Needed to write changelog rows");
requiresRole("roles/bigquery.dataEditor");
requiresRole("roles/bigquery.user");

באמצעות אבטחה הצהרתית, ה-CLI של Firebase יוצר או מעדכן חשבון שירות מנוהל של זמן ריצה עבור בסיס הקוד, ומעניק לו את כל התפקידים שהוגדרו. צריך לציין למשתמשים שכל הפונקציות בבסיס הקוד פועלות עם התפקידים האלה, אלא אם ה-API הסופי תומך במודל מצומצם יותר.

דוגמה מעשית: העברת נתונים מ-Firestore ל-BigQuery

לפני. ההצהרה מופיעה בקובץ extension.yaml. זמן הריצה של התוספים הפעיל את ה-API והעניק את התפקידים לחשבון מנוהל:

apis:
  -   apiName: bigquery.googleapis.com
roles:
  -   role: bigquery.dataEditor
  -   role: datastore.user
  -   role: bigquery.user

אחרי. מוצהר בקוד באמצעות requiresAPI ו-requiresRole:

import { requiresAPI, requiresRole } from "firebase-functions/";
requiresAPI("bigquery.googleapis.com",
  "Needed to write changelog rows and views");
requiresRole("roles/biguqery.dataEditor");
requiresRole("roles/datastore.user");
requiresRole("roles/bigquery.user");

המרת טיזרים של מחזור חיים

לדוגמה, אם התוסף קורא ל-getExtensions().runtime(), ל-setProcessingState או ל-setFatalError, צריך למחוק את הקריאות האלה, כי אם הן יתבצעו מפונקציה מהדור השני שנפרסה כרגיל, תוצג שגיאה. מצב מחזור החיים מבוסס עכשיו על afterFirstDeploy ו-afterRedeploy במקרים שבהם לא נעשה שימוש במעקב אחרי המצב הזה.

Firebase Extensions יכול להפעיל הגדרה כשמשתמש מתקין, מעדכן או מגדיר מחדש תוסף. בחבילת npm, צריך להצהיר על פעולות מחזור חיים מקבילות בקוד.

כדי להגדיר את האפליקציה בפעם הראשונה:

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

לעדכוני קוד או הגדרות:

import { afterRedeploy } from "firebase-functions/lifecycle";

afterRedeploy({
  task: {
    function: "runInitialSetup",
    body: { reconcile: true }
  }
});

הופכים את הפעולות במחזור החיים לאידמפוטנטיות. יכול להיות שהמשתמשים יצטרכו להריץ אותם מחדש באופן ידני אם השליחה או ההפעלה ייכשלו:

firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME
firebase functions:lifecycle:run afterRedeploy CODEBASE_NAME

דוגמה מעשית: העברת נתונים מ-Firestore ל-BigQuery

לפני.lifecycleEvents ב-extension.yaml, מופעל על ידי זמן הריצה של התוספים:

lifecycleEvents:
  onInstall:
    function: initBigQuerySync
    processingMessage: Configuring BigQuery Sync.
  onUpdate:
    function: setupBigQuerySync
    processingMessage: Configuring BigQuery Sync
  onConfigure:
    function: setupBigQuerySync
    processingMessage: Configuring BigQuery Sync

אחרי. מוצהר בקוד; המשימה מספקת BigQuery בפריסה הראשונה:

import { afterFirstDeploy, afterRedeploy } from "firebase-functions/lifecycle";

afterFirstDeploy({ task: { function: "initBigQuerySync" } });
afterRedeploy({ task: { function: "setupBigQuerySync" } });

הקצאת הרשאות היא אידמפוטנטית, ולכן הפעלה חוזרת מתקנת את מערך הנתונים, הטבלה והתצוגות. המשתמשים יכולים להפעיל מחדש באופן ידני באמצעות firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME.

הגדרת מסמכים למשתמשים

  • כותבים README של חבילה שכולל לפחות את הפרטים הבאים:

  • הערכים של .env שהחבילה דורשת.

  • הסודות שנדרשים לחבילה, ואיך להעביר ערכי סודות קיימים.

  • תפקידי ה-IAM שהחבילה מצהירה עליהם באמצעות requiresRole(...).

  • ממשקי Google API שהחבילה מפעילה או שנדרשים להפעלה.

  • ה-lifecycle hooks שהחבילה מצהירה עליהם, ואיך להריץ אותם מחדש באופן ידני.

  • הערות לגבי חיובים.

  • מה השתנה בהשוואה לתוסף המקורי.

דוגמה מעשית: העברת נתונים מ-Firestore ל-BigQuery

קובץ ה-README של החבילה כולל טבלה קונקרטית עם פירוט השינויים:

סוג הטיפול כתוסף ‫As @firebase/firestore-bigquery-export
הגדרה פרמטרים של תוספים פרמטרים של פונקציות דרך ‎ .env
IAM ההרשאה ניתנה על ידי Extensions requiresRole(...), applied at deploy
ניהול הקצאות (Provisioning) משימה במחזור החיים באמצעות Extensions משימה afterFirstDeploy / afterRedeploy
שמות הפונקציות ext-instanceId-fsexportbigquery fsexportbigquery (עם קידומת אופציונלית)

בדיקת פונקציה מדור שני

עכשיו אמורה להיות לכם פונקציה מדור שני, שכשתפרסו אותה, היא תתנהג בדיוק כמו התקנה חדשה של התוסף. השלב האחרון הוא לאמת ולתקן בעיות שנוצרו בטעות במהלך התהליך.

חשוב לוודא שאתם משתמשים ב-firebase-tools בגרסה >= 15.24.0, ומבצעים פריסה של הפונקציה שהומרה מדור שני לפרויקט בדיקה עם המשאבים המתאימים כדי לבדוק את ההתנהגות שלה. אם כבר הגדרתם פרויקט בדיקה כדי לבדוק את התוסף, משתמשים בפקודה:

firebase deploy --only functions

אחרי שמזינים את הפקודה הזו, ממלאים את האשף שמופיע עם ערכי הפרמטרים, בדיוק כמו שממלאים את טופס ההתקנה במסוף Firebase של התוסף.

דוגמה מעשית: העברת נתונים מ-Firestore ל-BigQuery

אנחנו מאמתים את הסנכרון מקצה לקצה של Cloud Firestore ל-BigQuery:

  1. במסוף Cloud Firestore, יוצרים את האוסף שהגדרתם כ-COLLECTION_PATH (משתמשים) אם הוא עדיין לא קיים.
  2. יוצרים מסמך בשם bigquery-mirror-test שמכיל שדות עם ערכים כלשהם.
  3. במסוף BigQuery, מריצים שאילתה על טבלת יומן השינויים הגולמי. הוא צריך להכיל שורה אחת שמתעדת את יצירת המסמך:
SELECT * FROM `PROJECT_ID.analytics.users_raw_changelog`
  1. מריצים שאילתה על התצוגה האחרונה, שאמורה להחזיר את אירוע השינוי האחרון עבור המסמך היחיד שקיים: bigquery-mirror-test
SELECT * FROM `PROJECT_ID.analytics.users_raw_latest`
  1. מוחקים את המסמך bigquery-mirror-test ב-Cloud Firestore. הוא נעלם מהתצוגה האחרונה, ואירוע DELETE מצורף לטבלת יומן השינויים הגולמי.

אפשר לבדוק את ההיסטוריה המלאה של מסמך יחיד באמצעות:

SELECT *
   FROM `PROJECT_ID.analytics.users_raw_changelog`
   WHERE document_name = "bigquery-mirror-test"
   ORDER BY timestamp ASC

ההבדלים מבדיקת התוסף:

  • הטריגר נפרס כ-fsexportbigquery (אפשר להוסיף קידומת של בסיס הקוד), ולא כ-ext-&lt;instanceId&gt;-fsexportbigquery. מחפשים את השם הזה בלוח הבקרה וברישומים.Cloud Functions
  • הקוד יפעל עכשיו ב-Firebase Local Emulator Suite כפונקציות רגילות. אפשר להגדיר את ערך הפרמטרים לשימוש באמולטור באמצעות .env.local. אפשר גם לבצע בדיקות יחידה של הקוד באמצעות firebase-functions-test SDK, כמו שמתואר במאמר בדיקות יחידה של Cloud Functions
  • הקצאת ההרשאות כבר לא מתבצעת על ידי זמן הריצה של התוספים. אם טבלת יומן השינויים חסרה אחרי הפריסה, מריצים מחדש את משימת ההגדרה באופן ידני: firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME. המשימה היא אידמפוטנטית, ולכן הפעלה חוזרת שלה תתאים בין מערך הנתונים, הטבלה והתצוגות.
  • ערכי הפרמטרים מגיעים מ-.env ולא מטופס ההתקנה, ולכן הפעלות חוזרות של firebase deploy לא אינטראקטיביות אחרי ש-.env מסתיים.