diff --git a/CHANGELOG.md b/CHANGELOG.md index 09d1ac47d2c..bdb67db9ec4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ - Removed MCP tools and prompts that required Gemini in Firebase terms of service. - Fixes an issue where the `--only` flag was not always respected for `firebase mcp` - Removed timeout when connecting to Cloud SQL. Hopefully, should mitigate issue #9314. (#9725) +- Added `firebase dataconnect:compile` command. diff --git a/src/commands/dataconnect-compile.ts b/src/commands/dataconnect-compile.ts new file mode 100644 index 00000000000..b7e6219c9fd --- /dev/null +++ b/src/commands/dataconnect-compile.ts @@ -0,0 +1,81 @@ +import * as clc from "colorette"; + +import { Command } from "../command"; +import { Options } from "../options"; +import { DataConnectEmulator } from "../emulator/dataconnectEmulator"; +import { getProjectId } from "../projectUtils"; +import { pickServices } from "../dataconnect/load"; +import { getProjectDefaultAccount } from "../auth"; +import { logLabeledSuccess } from "../utils"; +import { EmulatorHub } from "../emulator/hub"; +import { handleBuildErrors } from "../dataconnect/build"; +import { FirebaseError } from "../error"; + +type CompileOptions = Options & { service?: string; location?: string }; + +export const command = new Command("dataconnect:compile") + .description("compile your Data Connect schema and connector config and GQL files.") + .option( + "--service ", + "the serviceId of the Data Connect service. If not provided, compiles all services.", + ) + .option( + "--location ", + "the location of the Data Connect service. Only needed if service ID is used in multiple locations.", + ) + .action(async (options: CompileOptions) => { + const projectId = getProjectId(options); + + const config = options.config; + if (!config || !config.has("dataconnect")) { + throw new FirebaseError( + `No Data Connect project directory found. Please run ${clc.bold("firebase init dataconnect")} to set it up first.`, + ); + } + + const serviceInfos = await pickServices( + projectId || EmulatorHub.MISSING_PROJECT_PLACEHOLDER, + config, + options.service, + options.location, + ); + + if (!serviceInfos.length) { + throw new FirebaseError("No Data Connect services found to compile."); + } + + for (const serviceInfo of serviceInfos) { + const configDir = serviceInfo.sourceDirectory; + const account = getProjectDefaultAccount(options.projectRoot); + + // 1. Build (Validate Schema/Connectors + Generate .dataconnect) + const buildArgs = { + configDir, + projectId, // Optional, passes to fdc build --project_id if present + account, + }; + + const buildResult = await DataConnectEmulator.build(buildArgs); + + if (buildResult?.errors?.length) { + await handleBuildErrors( + buildResult.errors, + options.nonInteractive, + options.force, + !!options.dryRun, + ); + } + + // 2. Generate SDKs + // api-proposal says: "Generates or updates the local .dataconnect/ metadata folder and generated SDKs" + await DataConnectEmulator.generate({ + configDir, + account, + }); + + logLabeledSuccess( + "dataconnect", + `Successfully compiled Data Connect service: ${clc.bold(serviceInfo.dataConnectYaml.serviceId)}`, + ); + } + }); diff --git a/src/commands/index.ts b/src/commands/index.ts index ad89eff7136..81e885ec9ea 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -254,6 +254,7 @@ export function load(client: CLIClient): CLIClient { client.dataconnect.sql.migrate = loadCommand("dataconnect-sql-migrate"); client.dataconnect.sql.grant = loadCommand("dataconnect-sql-grant"); client.dataconnect.sql.shell = loadCommand("dataconnect-sql-shell"); + client.dataconnect.compile = loadCommand("dataconnect-compile"); client.dataconnect.sdk = {}; client.dataconnect.sdk.generate = loadCommand("dataconnect-sdk-generate"); client.target = loadCommand("target");