Loading...
Loading...
将已安装的Firebase Extension(或扩展源码)转换为独立的Cloud Functions for Firebase代码库或可发布的npm包的技能,包括将触发器从V1升级到V2,以及配置生命周期钩子和声明式安全
npx skill4agent add firebase/agent-skills extension-to-functions-codebasefirebase-functionsfunctions/src/.envdefineStringdefineSecretfirebase deploy --only functionspackage.jsonexportsfirebase-functionsdependenciespeerDependenciesnpm i <package-name>index.tsgit cp"Copying [extension-name] extension to [directory] in preparation for rewrite"gcloudrequiresAPIrequiresRole.value()onInit()import { defineString } from "firebase-functions/params";
import { onInit } from "firebase-functions/v2";
const bqDataset = defineString("DATASET_ID");
let bqClient: BigQuery;
onInit(() => {
bqClient = new BigQuery({ datasetId: bqDataset.value() });
});cpu: "gcf_gen1"extension.yamlparamsdefineStringdefineSecretapisrequiresAPI(...)rolesrequiresRole(...)lifecycleEventsonInstallonUpdateonConfigureafterFirstDeployafterRedeployresourcesfirebase-functions/v1firebase-functions/v2onTaskDispatchedfunctions/README.mdPREINSTALL.mdPOSTINSTALL.mdscripts/package.jsonname: "<package-name>"functions/package.jsonpackage.jsondevDependenciesjestts-jest@types/jestmocha@types/mocha"test": "..."dependenciespeerDependenciesfirebase-functions^7.0.0{
"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"
},
"dependencies": {
"firebase-admin": "^12.0.0",
"firebase-functions": "^7.0.0"
}
}src/index.tsexport * from "<package-name>";
// 或命名导出:
// export { syncV2, initBigQuerySync } from "<package-name>";import "<package-name>"onWriteonRequesttasks.taskQueue().onDispatchfirebase-functions/v2/...onDocumentWrittenonRequestonTaskDispatched{ shimmedKey, context }auth.user().onCreate()auth.user().onDelete()firebase-functionsextension.yamlstringdefineString("PARAM_NAME", { label: "...", description: "...", default: "..." })secretdefineSecret("PARAM_NAME")intdefineInt("PARAM_NAME", { label: "...", default: 123 })booleandefineBoolean("PARAM_NAME", { default: true })selectmultiSelectoptionsinputdefineString("PARAM_NAME", { input: { select: { options: [{ value: "val", label: "Val" }] } } })validationRegexdefineString("PARAM_NAME", { input: { text: { validationRegex: "^[a-z]+$" } } })required: truenonEmpty: truedefineString("PARAM_NAME", { input: { text: { nonEmpty: true } } })paramName.value()COLLECTION_PATHDATASET_ID.envqueue.enqueue(...)getFunctions().taskQueue(...)process.env.EXT_INSTANCE_IDEXT_INSTANCE_ID// 之前(扩展运行时):
// const queue = getFunctions().taskQueue(`locations/${region}/functions/syncBigQuery`, process.env.EXT_INSTANCE_ID);
// 之后(npm包):
const queue = getFunctions().taskQueue(`locations/${region}/functions/syncBigQuery`);
await queue.enqueue(taskData);type: secretimport { defineSecret } from "firebase-functions/params";
const apiKey = defineSecret("API_KEY");export const fn = onRequest({ secrets: [apiKey] }, handler);extension.yamlapisrolesimport { requiresAPI, requiresRole } from "firebase-functions";
requiresAPI("bigquery.googleapis.com", "Needed to write changelog rows");
requiresRole("roles/bigquery.dataEditor");
requiresRole("roles/bigquery.user");afterFirstDeployafterRedeploylifecycleEventsonInstallonUpdateonConfigureinitBigQuerySyncsetupBigQuerySynconTaskDispatchedfirebase-functions/v2/tasksgetExtensions().runtime().setProcessingState(...)import { afterFirstDeploy, afterRedeploy } from "firebase-functions/v2";
// 替代onInstall:
afterFirstDeploy({
task: {
function: "runInitialSetup",
body: {}
}
});
// 替代onUpdate & onConfigure:
afterRedeploy({
task: {
function: "runInitialSetup",
body: { reconcile: true }
}
});firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME
firebase functions:lifecycle:run afterRedeploy CODEBASE_NAMEREADME.mdREADME.mdPREINSTALL.mdPOSTINSTALL.mdextension.yamlext-*.envdefineString.envexport * from "<package-name>";index.tsnpm run buildtscsrc/__tests__/test/@types/jestdevDependencies({ change: mockChange, context: mockContext })(mockChange, mockContext)npm testnpx tsc --noEmitfirebase-extensions-migrator-support-external@google.comfirebase-extensions-migrator-support-external+subscribe@google.comrunWith