From 004652b0ae1ce3bd7174ed3a375bc0ae909b8875 Mon Sep 17 00:00:00 2001 From: Akhil Raveendran Date: Thu, 12 Mar 2026 00:28:57 -0700 Subject: [PATCH 01/14] Include clientCache field during init --- src/init/features/dataconnect/sdk.spec.ts | 28 ++++++++++++++++++++++- src/init/features/dataconnect/sdk.ts | 4 ++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/init/features/dataconnect/sdk.spec.ts b/src/init/features/dataconnect/sdk.spec.ts index 7c5365fa5c1..2b1875584a3 100644 --- a/src/init/features/dataconnect/sdk.spec.ts +++ b/src/init/features/dataconnect/sdk.spec.ts @@ -58,6 +58,7 @@ describe("addSdkGenerateToConnectorYaml", () => { packageJsonDir: "../app", react: false, angular: false, + clientCache: {}, }, ]); }); @@ -72,6 +73,7 @@ describe("addSdkGenerateToConnectorYaml", () => { packageJsonDir: "../app", react: true, angular: false, + clientCache: {}, }, ]); }); @@ -83,6 +85,7 @@ describe("addSdkGenerateToConnectorYaml", () => { { outputDir: "../app/lib/dataconnect_generated", package: "dataconnect_generated/generated.dart", + clientCache: {}, }, ]); }); @@ -94,6 +97,7 @@ describe("addSdkGenerateToConnectorYaml", () => { { outputDir: "../app/src/main/kotlin", package: "com.google.firebase.dataconnect.generated", + clientCache: {}, }, ]); }); @@ -105,11 +109,12 @@ describe("addSdkGenerateToConnectorYaml", () => { { outputDir: "../FirebaseDataConnectGenerated", package: "DataConnectGenerated", + clientCache: {}, }, ]); }); - it("should add adminSdk for admin node platform", () => { + it("should add adminSdk for admin node platform and NOT include clientCache", () => { app.platform = Platform.ADMIN_NODE; addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); expect(connectorYaml.generate?.adminNodeSdk).to.deep.equal([ @@ -119,9 +124,30 @@ describe("addSdkGenerateToConnectorYaml", () => { packageJsonDir: "../app", }, ]); + expect((connectorYaml.generate?.adminNodeSdk as any)[0].clientCache).to.be.undefined; + }); + + it("should add clientCache: {} to all new generated SDKs when multiple are added", () => { + // Add Web SDK + app.platform = Platform.WEB; + addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); + + // Add Flutter SDK + const flutterApp: App = { + directory: "/users/test/project/flutter_app", + platform: Platform.FLUTTER, + }; + addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, flutterApp); + + expect(connectorYaml.generate?.javascriptSdk).to.have.lengthOf(1); + expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({}); + + expect(connectorYaml.generate?.dartSdk).to.have.lengthOf(1); + expect((connectorYaml.generate?.dartSdk as any)[0].clientCache).to.deep.equal({}); }); }); + describe("chooseApp", () => { let detectAppsStub: sinon.SinonStub; let promptStub: sinon.SinonStub; diff --git a/src/init/features/dataconnect/sdk.ts b/src/init/features/dataconnect/sdk.ts index 5eba5e07aaf..a1d4662f361 100644 --- a/src/init/features/dataconnect/sdk.ts +++ b/src/init/features/dataconnect/sdk.ts @@ -386,6 +386,7 @@ export function addSdkGenerateToConnectorYaml( packageJsonDir: path.relative(connectorDir, appDir), react: false, angular: false, + clientCache: {}, }; for (const f of app.frameworks || []) { javascriptSdk[f] = true; @@ -402,6 +403,7 @@ export function addSdkGenerateToConnectorYaml( const dartSdk: DartSDK = { outputDir: path.relative(connectorDir, path.join(appDir, `lib/dataconnect_generated`)), package: "dataconnect_generated/generated.dart", + clientCache: {}, }; if (!isArray(generate?.dartSdk)) { generate.dartSdk = generate.dartSdk ? [generate.dartSdk] : []; @@ -415,6 +417,7 @@ export function addSdkGenerateToConnectorYaml( const kotlinSdk: KotlinSDK = { outputDir: path.relative(connectorDir, path.join(appDir, `src/main/kotlin`)), package: `com.google.firebase.dataconnect.generated`, + clientCache: {}, }; if (!isArray(generate?.kotlinSdk)) { generate.kotlinSdk = generate.kotlinSdk ? [generate.kotlinSdk] : []; @@ -431,6 +434,7 @@ export function addSdkGenerateToConnectorYaml( path.join(app.directory, `../FirebaseDataConnectGenerated`), ), package: "DataConnectGenerated", + clientCache: {}, }; if (!isArray(generate?.swiftSdk)) { generate.swiftSdk = generate.swiftSdk ? [generate.swiftSdk] : []; From c8af9bdcc1d637da792e6cb4ec76760254f2f5b3 Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Thu, 12 Mar 2026 00:59:12 -0700 Subject: [PATCH 02/14] Update sdk.spec.ts --- src/init/features/dataconnect/sdk.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/init/features/dataconnect/sdk.spec.ts b/src/init/features/dataconnect/sdk.spec.ts index 2b1875584a3..f2c00df3978 100644 --- a/src/init/features/dataconnect/sdk.spec.ts +++ b/src/init/features/dataconnect/sdk.spec.ts @@ -147,7 +147,6 @@ describe("addSdkGenerateToConnectorYaml", () => { }); }); - describe("chooseApp", () => { let detectAppsStub: sinon.SinonStub; let promptStub: sinon.SinonStub; From d5e7b435356799c5c49688143a2764f39311800e Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Thu, 12 Mar 2026 00:59:12 -0700 Subject: [PATCH 03/14] Update sdk.spec.ts --- src/experiments.ts | 5 +++++ src/init/features/dataconnect/sdk.spec.ts | 16 +++++++++------- src/init/features/dataconnect/sdk.ts | 20 +++++++++++++++----- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/experiments.ts b/src/experiments.ts index fea640ef3a3..cba1b25db76 100644 --- a/src/experiments.ts +++ b/src/experiments.ts @@ -175,6 +175,11 @@ export const ALL_EXPERIMENTS = experiments({ default: true, public: false, }, + fdcrealtime: { + shortDescription: "Enable Firebase Data Connect realtime feature.", + default: false, + public: false, + }, }); export type ExperimentName = keyof typeof ALL_EXPERIMENTS; diff --git a/src/init/features/dataconnect/sdk.spec.ts b/src/init/features/dataconnect/sdk.spec.ts index f2c00df3978..69f6b79a1e9 100644 --- a/src/init/features/dataconnect/sdk.spec.ts +++ b/src/init/features/dataconnect/sdk.spec.ts @@ -22,6 +22,7 @@ import * as dcLoad from "../../../dataconnect/load"; import * as fsutils from "../../../fsutils"; import * as auth from "../../../auth"; import * as utils from "../../../utils"; +import * as experiments from "../../../experiments"; import * as prompt from "../../../prompt"; const expect = chai.expect; @@ -58,7 +59,6 @@ describe("addSdkGenerateToConnectorYaml", () => { packageJsonDir: "../app", react: false, angular: false, - clientCache: {}, }, ]); }); @@ -73,7 +73,6 @@ describe("addSdkGenerateToConnectorYaml", () => { packageJsonDir: "../app", react: true, angular: false, - clientCache: {}, }, ]); }); @@ -85,7 +84,6 @@ describe("addSdkGenerateToConnectorYaml", () => { { outputDir: "../app/lib/dataconnect_generated", package: "dataconnect_generated/generated.dart", - clientCache: {}, }, ]); }); @@ -97,7 +95,6 @@ describe("addSdkGenerateToConnectorYaml", () => { { outputDir: "../app/src/main/kotlin", package: "com.google.firebase.dataconnect.generated", - clientCache: {}, }, ]); }); @@ -109,7 +106,6 @@ describe("addSdkGenerateToConnectorYaml", () => { { outputDir: "../FirebaseDataConnectGenerated", package: "DataConnectGenerated", - clientCache: {}, }, ]); }); @@ -140,10 +136,16 @@ describe("addSdkGenerateToConnectorYaml", () => { addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, flutterApp); expect(connectorYaml.generate?.javascriptSdk).to.have.lengthOf(1); - expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({}); + expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.be.undefined; expect(connectorYaml.generate?.dartSdk).to.have.lengthOf(1); - expect((connectorYaml.generate?.dartSdk as any)[0].clientCache).to.deep.equal({}); + expect((connectorYaml.generate?.dartSdk as any)[0].clientCache).to.be.undefined; + }); + + it("should add clientCache: {} when fdcrealtime experiment is enabled", () => { + sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(true); + addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); + expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({}); }); }); diff --git a/src/init/features/dataconnect/sdk.ts b/src/init/features/dataconnect/sdk.ts index a1d4662f361..28ce27ef473 100644 --- a/src/init/features/dataconnect/sdk.ts +++ b/src/init/features/dataconnect/sdk.ts @@ -15,7 +15,9 @@ import { DartSDK, JavascriptSDK, KotlinSDK, + SwiftSDK, } from "../../../dataconnect/types"; +import * as experiments from "../../../experiments"; import { FirebaseError } from "../../../error"; import { isArray } from "lodash"; import { @@ -386,8 +388,10 @@ export function addSdkGenerateToConnectorYaml( packageJsonDir: path.relative(connectorDir, appDir), react: false, angular: false, - clientCache: {}, }; + if (experiments.isEnabled("fdcrealtime")) { + javascriptSdk.clientCache = {}; + } for (const f of app.frameworks || []) { javascriptSdk[f] = true; } @@ -403,8 +407,10 @@ export function addSdkGenerateToConnectorYaml( const dartSdk: DartSDK = { outputDir: path.relative(connectorDir, path.join(appDir, `lib/dataconnect_generated`)), package: "dataconnect_generated/generated.dart", - clientCache: {}, }; + if (experiments.isEnabled("fdcrealtime")) { + dartSdk.clientCache = {}; + } if (!isArray(generate?.dartSdk)) { generate.dartSdk = generate.dartSdk ? [generate.dartSdk] : []; } @@ -417,8 +423,10 @@ export function addSdkGenerateToConnectorYaml( const kotlinSdk: KotlinSDK = { outputDir: path.relative(connectorDir, path.join(appDir, `src/main/kotlin`)), package: `com.google.firebase.dataconnect.generated`, - clientCache: {}, }; + if (experiments.isEnabled("fdcrealtime")) { + kotlinSdk.clientCache = {}; + } if (!isArray(generate?.kotlinSdk)) { generate.kotlinSdk = generate.kotlinSdk ? [generate.kotlinSdk] : []; } @@ -428,14 +436,16 @@ export function addSdkGenerateToConnectorYaml( break; } case Platform.IOS: { - const swiftSdk = { + const swiftSdk: SwiftSDK = { outputDir: path.relative( connectorDir, path.join(app.directory, `../FirebaseDataConnectGenerated`), ), package: "DataConnectGenerated", - clientCache: {}, }; + if (experiments.isEnabled("fdcrealtime")) { + swiftSdk.clientCache = {}; + } if (!isArray(generate?.swiftSdk)) { generate.swiftSdk = generate.swiftSdk ? [generate.swiftSdk] : []; } From 17837aca332f0b8b24ef7e37f4a68e1ad3ae9abb Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Thu, 12 Mar 2026 00:59:12 -0700 Subject: [PATCH 04/14] Update sdk.spec.ts --- src/experiments.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/experiments.ts b/src/experiments.ts index cba1b25db76..53ca122b304 100644 --- a/src/experiments.ts +++ b/src/experiments.ts @@ -177,7 +177,7 @@ export const ALL_EXPERIMENTS = experiments({ }, fdcrealtime: { shortDescription: "Enable Firebase Data Connect realtime feature.", - default: false, + default: true, public: false, }, }); From ca7ad4bd84ab2e9e0e0a18c68ad9eb3232f8c2c4 Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Thu, 12 Mar 2026 00:59:12 -0700 Subject: [PATCH 05/14] Update sdk.spec.ts --- src/init/features/dataconnect/sdk.spec.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/init/features/dataconnect/sdk.spec.ts b/src/init/features/dataconnect/sdk.spec.ts index 69f6b79a1e9..60a695aed8c 100644 --- a/src/init/features/dataconnect/sdk.spec.ts +++ b/src/init/features/dataconnect/sdk.spec.ts @@ -59,6 +59,7 @@ describe("addSdkGenerateToConnectorYaml", () => { packageJsonDir: "../app", react: false, angular: false, + clientCache: {}, }, ]); }); @@ -73,6 +74,7 @@ describe("addSdkGenerateToConnectorYaml", () => { packageJsonDir: "../app", react: true, angular: false, + clientCache: {}, }, ]); }); @@ -84,6 +86,7 @@ describe("addSdkGenerateToConnectorYaml", () => { { outputDir: "../app/lib/dataconnect_generated", package: "dataconnect_generated/generated.dart", + clientCache: {}, }, ]); }); @@ -95,6 +98,7 @@ describe("addSdkGenerateToConnectorYaml", () => { { outputDir: "../app/src/main/kotlin", package: "com.google.firebase.dataconnect.generated", + clientCache: {}, }, ]); }); @@ -106,6 +110,7 @@ describe("addSdkGenerateToConnectorYaml", () => { { outputDir: "../FirebaseDataConnectGenerated", package: "DataConnectGenerated", + clientCache: {}, }, ]); }); @@ -136,10 +141,10 @@ describe("addSdkGenerateToConnectorYaml", () => { addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, flutterApp); expect(connectorYaml.generate?.javascriptSdk).to.have.lengthOf(1); - expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.be.undefined; + expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({}); expect(connectorYaml.generate?.dartSdk).to.have.lengthOf(1); - expect((connectorYaml.generate?.dartSdk as any)[0].clientCache).to.be.undefined; + expect((connectorYaml.generate?.dartSdk as any)[0].clientCache).to.deep.equal({}); }); it("should add clientCache: {} when fdcrealtime experiment is enabled", () => { From 68e90f2260d2f03885fd23156628c2a56d1ae70b Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Thu, 12 Mar 2026 00:59:12 -0700 Subject: [PATCH 06/14] Update sdk.spec.ts --- src/init/features/dataconnect/sdk.spec.ts | 119 ++++++++++++++++++++++ src/init/features/dataconnect/sdk.ts | 72 ++++++++----- 2 files changed, 166 insertions(+), 25 deletions(-) diff --git a/src/init/features/dataconnect/sdk.spec.ts b/src/init/features/dataconnect/sdk.spec.ts index 60a695aed8c..67eb00ceefa 100644 --- a/src/init/features/dataconnect/sdk.spec.ts +++ b/src/init/features/dataconnect/sdk.spec.ts @@ -6,6 +6,7 @@ import { chooseApp, askQuestions, actuate, + ensureClientCache, FDC_SDK_PLATFORM_ENV, FDC_SDK_FRAMEWORKS_ENV, FDC_APP_FOLDER, @@ -50,6 +51,10 @@ describe("addSdkGenerateToConnectorYaml", () => { }; }); + afterEach(() => { + sinon.restore(); + }); + it("should add javascriptSdk for web platform", () => { addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); expect(connectorYaml.generate?.javascriptSdk).to.deep.equal([ @@ -152,6 +157,120 @@ describe("addSdkGenerateToConnectorYaml", () => { addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({}); }); + + it("should upgrade existing SDK entry with clientCache: {} if missing", () => { + sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(true); + connectorYaml.generate = { + javascriptSdk: [ + { + outputDir: "../app/src/dataconnect-generated", + package: "@dataconnect/generated", + packageJsonDir: "../app", + react: false, + angular: false, + }, + ], + }; + addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); + expect(connectorYaml.generate?.javascriptSdk).to.have.lengthOf(1); + expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({}); + }); + + it("should NOT overwrite existing clientCache configuration", () => { + sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(true); + connectorYaml.generate = { + javascriptSdk: [ + { + outputDir: "../app/src/dataconnect-generated", + package: "@dataconnect/generated", + packageJsonDir: "../app", + react: false, + angular: false, + clientCache: { + type: "memory", + } as any, + }, + ], + }; + addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); + expect(connectorYaml.generate?.javascriptSdk).to.have.lengthOf(1); + expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({ + type: "memory", + }); + }); +}); + +describe("ensureClientCache", () => { + let connectorYaml: ConnectorYaml; + + beforeEach(() => { + connectorYaml = { + connectorId: "test-connector", + }; + sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(true); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("should upgrade all client SDKs to include clientCache: {} if missing", () => { + connectorYaml.generate = { + javascriptSdk: [{ outputDir: "js", package: "js", packageJsonDir: "." }], + swiftSdk: [{ outputDir: "swift", package: "swift" }], + kotlinSdk: [{ outputDir: "kotlin", package: "kotlin" }], + dartSdk: [{ outputDir: "dart", package: "dart" }], + }; + ensureClientCache(connectorYaml); + expect((connectorYaml.generate.javascriptSdk as any)[0].clientCache).to.deep.equal({}); + expect((connectorYaml.generate.swiftSdk as any)[0].clientCache).to.deep.equal({}); + expect((connectorYaml.generate.kotlinSdk as any)[0].clientCache).to.deep.equal({}); + expect((connectorYaml.generate.dartSdk as any)[0].clientCache).to.deep.equal({}); + }); + + it("should handle single SDK objects (non-array) and normalize them", () => { + connectorYaml.generate = { + javascriptSdk: { outputDir: "js", package: "js", packageJsonDir: "." } as any, + }; + ensureClientCache(connectorYaml); + expect(connectorYaml.generate.javascriptSdk).to.be.an("array"); + expect((connectorYaml.generate.javascriptSdk as any)[0].clientCache).to.deep.equal({}); + }); + + it("should preserve existing clientCache configurations", () => { + connectorYaml.generate = { + javascriptSdk: [ + { + outputDir: "js", + package: "js", + packageJsonDir: ".", + clientCache: { type: "memory" } as any, + }, + ], + }; + ensureClientCache(connectorYaml); + expect((connectorYaml.generate.javascriptSdk as any)[0].clientCache).to.deep.equal({ + type: "memory", + }); + }); + + it("should NOT add clientCache to adminNodeSdk", () => { + connectorYaml.generate = { + adminNodeSdk: [{ outputDir: "admin", package: "admin", packageJsonDir: "." }], + }; + ensureClientCache(connectorYaml); + expect((connectorYaml.generate.adminNodeSdk as any)[0].clientCache).to.be.undefined; + }); + + it("should NOT upgrade SDKs if fdcrealtime experiment is disabled", () => { + sinon.restore(); + sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(false); + connectorYaml.generate = { + javascriptSdk: [{ outputDir: "js", package: "js", packageJsonDir: "." }], + }; + ensureClientCache(connectorYaml); + expect((connectorYaml.generate.javascriptSdk as any)[0].clientCache).to.be.undefined; + }); }); describe("chooseApp", () => { diff --git a/src/init/features/dataconnect/sdk.ts b/src/init/features/dataconnect/sdk.ts index 28ce27ef473..d8f5640c6f0 100644 --- a/src/init/features/dataconnect/sdk.ts +++ b/src/init/features/dataconnect/sdk.ts @@ -251,6 +251,7 @@ async function actuateWithInfo(setup: Setup, config: Config, info: SdkRequiredIn } addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); } + ensureClientCache(connectorYaml); // TODO: Prompt user about adding generated paths to .gitignore const connectorYamlContents = yaml.stringify(connectorYaml); @@ -383,22 +384,20 @@ export function addSdkGenerateToConnectorYaml( case Platform.WEB: { const javascriptSdk: JavascriptSDK = { - outputDir: path.relative(connectorDir, path.join(appDir, `src/dataconnect-generated`)), - package: `@dataconnect/generated`, - packageJsonDir: path.relative(connectorDir, appDir), - react: false, - angular: false, + outputDir: path.relative( + connectorDir, + path.join(app.directory, "src/dataconnect-generated"), + ), + package: "@dataconnect/generated", + packageJsonDir: path.relative(connectorDir, app.directory), + react: app.frameworks?.includes(Framework.REACT) ?? false, + angular: app.frameworks?.includes(Framework.ANGULAR) ?? false, }; - if (experiments.isEnabled("fdcrealtime")) { - javascriptSdk.clientCache = {}; - } - for (const f of app.frameworks || []) { - javascriptSdk[f] = true; - } if (!isArray(generate?.javascriptSdk)) { generate.javascriptSdk = generate.javascriptSdk ? [generate.javascriptSdk] : []; } - if (!generate.javascriptSdk.some((s) => s.outputDir === javascriptSdk.outputDir)) { + const existing = generate.javascriptSdk.find((s) => s.outputDir === javascriptSdk.outputDir); + if (!existing) { generate.javascriptSdk.push(javascriptSdk); } break; @@ -408,29 +407,25 @@ export function addSdkGenerateToConnectorYaml( outputDir: path.relative(connectorDir, path.join(appDir, `lib/dataconnect_generated`)), package: "dataconnect_generated/generated.dart", }; - if (experiments.isEnabled("fdcrealtime")) { - dartSdk.clientCache = {}; - } if (!isArray(generate?.dartSdk)) { generate.dartSdk = generate.dartSdk ? [generate.dartSdk] : []; } - if (!generate.dartSdk.some((s) => s.outputDir === dartSdk.outputDir)) { + const existing = generate.dartSdk.find((s) => s.outputDir === dartSdk.outputDir); + if (!existing) { generate.dartSdk.push(dartSdk); } break; } case Platform.ANDROID: { const kotlinSdk: KotlinSDK = { - outputDir: path.relative(connectorDir, path.join(appDir, `src/main/kotlin`)), + outputDir: path.relative(connectorDir, path.join(app.directory, "src/main/kotlin")), package: `com.google.firebase.dataconnect.generated`, }; - if (experiments.isEnabled("fdcrealtime")) { - kotlinSdk.clientCache = {}; - } if (!isArray(generate?.kotlinSdk)) { generate.kotlinSdk = generate.kotlinSdk ? [generate.kotlinSdk] : []; } - if (!generate.kotlinSdk.some((s) => s.outputDir === kotlinSdk.outputDir)) { + const existing = generate.kotlinSdk.find((s) => s.outputDir === kotlinSdk.outputDir); + if (!existing) { generate.kotlinSdk.push(kotlinSdk); } break; @@ -443,13 +438,11 @@ export function addSdkGenerateToConnectorYaml( ), package: "DataConnectGenerated", }; - if (experiments.isEnabled("fdcrealtime")) { - swiftSdk.clientCache = {}; - } if (!isArray(generate?.swiftSdk)) { generate.swiftSdk = generate.swiftSdk ? [generate.swiftSdk] : []; } - if (!generate.swiftSdk.some((s) => s.outputDir === swiftSdk.outputDir)) { + const existing = generate.swiftSdk.find((s) => s.outputDir === swiftSdk.outputDir); + if (!existing) { generate.swiftSdk.push(swiftSdk); } break; @@ -461,6 +454,35 @@ export function addSdkGenerateToConnectorYaml( ).join(", ")}\n${JSON.stringify(app)}`, ); } + ensureClientCache(connectorYaml); +} + +/** + * Ensures all supported client SDKs in the connector.yaml have clientCache: {} if missing and experiment is on. + */ +export function ensureClientCache(connectorYaml: ConnectorYaml): void { + if (!connectorYaml.generate || !experiments.isEnabled("fdcrealtime")) { + return; + } + const generate = connectorYaml.generate; + const sdkFields: (keyof typeof generate)[] = [ + "javascriptSdk", + "swiftSdk", + "kotlinSdk", + "dartSdk", + ]; + for (const field of sdkFields) { + const val = generate[field]; + if (val) { + const sdkList = isArray(val) ? val : [val]; + (generate as any)[field] = sdkList; + for (const sdk of sdkList as any[]) { + if (!sdk.clientCache) { + sdk.clientCache = {}; + } + } + } + } } function dedupeAppsByPlatformAndDirectory(apps: App[]): App[] { From 7d22b75a1426dfc611bf2f2f8836c20bce6fbdfb Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:57:28 -0700 Subject: [PATCH 07/14] Update sdk.spec.ts --- src/init/features/dataconnect/sdk.spec.ts | 86 ++--------------------- 1 file changed, 7 insertions(+), 79 deletions(-) diff --git a/src/init/features/dataconnect/sdk.spec.ts b/src/init/features/dataconnect/sdk.spec.ts index 67eb00ceefa..074fc0aacd8 100644 --- a/src/init/features/dataconnect/sdk.spec.ts +++ b/src/init/features/dataconnect/sdk.spec.ts @@ -6,7 +6,6 @@ import { chooseApp, askQuestions, actuate, - ensureClientCache, FDC_SDK_PLATFORM_ENV, FDC_SDK_FRAMEWORKS_ENV, FDC_APP_FOLDER, @@ -133,7 +132,9 @@ describe("addSdkGenerateToConnectorYaml", () => { expect((connectorYaml.generate?.adminNodeSdk as any)[0].clientCache).to.be.undefined; }); - it("should add clientCache: {} to all new generated SDKs when multiple are added", () => { + it("should NOT add clientCache: {} to all new generated SDKs when fdcrealtime is disabled", () => { + sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(false); + // Add Web SDK app.platform = Platform.WEB; addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); @@ -146,10 +147,10 @@ describe("addSdkGenerateToConnectorYaml", () => { addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, flutterApp); expect(connectorYaml.generate?.javascriptSdk).to.have.lengthOf(1); - expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({}); + expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.be.undefined; expect(connectorYaml.generate?.dartSdk).to.have.lengthOf(1); - expect((connectorYaml.generate?.dartSdk as any)[0].clientCache).to.deep.equal({}); + expect((connectorYaml.generate?.dartSdk as any)[0].clientCache).to.be.undefined; }); it("should add clientCache: {} when fdcrealtime experiment is enabled", () => { @@ -158,7 +159,7 @@ describe("addSdkGenerateToConnectorYaml", () => { expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({}); }); - it("should upgrade existing SDK entry with clientCache: {} if missing", () => { + it("should NOT upgrade existing SDK entry with clientCache: {} if missing", () => { sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(true); connectorYaml.generate = { javascriptSdk: [ @@ -173,7 +174,7 @@ describe("addSdkGenerateToConnectorYaml", () => { }; addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); expect(connectorYaml.generate?.javascriptSdk).to.have.lengthOf(1); - expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({}); + expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.be.undefined; }); it("should NOT overwrite existing clientCache configuration", () => { @@ -200,79 +201,6 @@ describe("addSdkGenerateToConnectorYaml", () => { }); }); -describe("ensureClientCache", () => { - let connectorYaml: ConnectorYaml; - - beforeEach(() => { - connectorYaml = { - connectorId: "test-connector", - }; - sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(true); - }); - - afterEach(() => { - sinon.restore(); - }); - - it("should upgrade all client SDKs to include clientCache: {} if missing", () => { - connectorYaml.generate = { - javascriptSdk: [{ outputDir: "js", package: "js", packageJsonDir: "." }], - swiftSdk: [{ outputDir: "swift", package: "swift" }], - kotlinSdk: [{ outputDir: "kotlin", package: "kotlin" }], - dartSdk: [{ outputDir: "dart", package: "dart" }], - }; - ensureClientCache(connectorYaml); - expect((connectorYaml.generate.javascriptSdk as any)[0].clientCache).to.deep.equal({}); - expect((connectorYaml.generate.swiftSdk as any)[0].clientCache).to.deep.equal({}); - expect((connectorYaml.generate.kotlinSdk as any)[0].clientCache).to.deep.equal({}); - expect((connectorYaml.generate.dartSdk as any)[0].clientCache).to.deep.equal({}); - }); - - it("should handle single SDK objects (non-array) and normalize them", () => { - connectorYaml.generate = { - javascriptSdk: { outputDir: "js", package: "js", packageJsonDir: "." } as any, - }; - ensureClientCache(connectorYaml); - expect(connectorYaml.generate.javascriptSdk).to.be.an("array"); - expect((connectorYaml.generate.javascriptSdk as any)[0].clientCache).to.deep.equal({}); - }); - - it("should preserve existing clientCache configurations", () => { - connectorYaml.generate = { - javascriptSdk: [ - { - outputDir: "js", - package: "js", - packageJsonDir: ".", - clientCache: { type: "memory" } as any, - }, - ], - }; - ensureClientCache(connectorYaml); - expect((connectorYaml.generate.javascriptSdk as any)[0].clientCache).to.deep.equal({ - type: "memory", - }); - }); - - it("should NOT add clientCache to adminNodeSdk", () => { - connectorYaml.generate = { - adminNodeSdk: [{ outputDir: "admin", package: "admin", packageJsonDir: "." }], - }; - ensureClientCache(connectorYaml); - expect((connectorYaml.generate.adminNodeSdk as any)[0].clientCache).to.be.undefined; - }); - - it("should NOT upgrade SDKs if fdcrealtime experiment is disabled", () => { - sinon.restore(); - sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(false); - connectorYaml.generate = { - javascriptSdk: [{ outputDir: "js", package: "js", packageJsonDir: "." }], - }; - ensureClientCache(connectorYaml); - expect((connectorYaml.generate.javascriptSdk as any)[0].clientCache).to.be.undefined; - }); -}); - describe("chooseApp", () => { let detectAppsStub: sinon.SinonStub; let promptStub: sinon.SinonStub; From b62fd034d247e78f80c5fbf99edd49e9a4976ecd Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:57:41 -0700 Subject: [PATCH 08/14] Update sdk.ts --- src/init/features/dataconnect/sdk.ts | 42 ++++++++-------------------- 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/src/init/features/dataconnect/sdk.ts b/src/init/features/dataconnect/sdk.ts index d8f5640c6f0..8f98b8b6725 100644 --- a/src/init/features/dataconnect/sdk.ts +++ b/src/init/features/dataconnect/sdk.ts @@ -251,7 +251,6 @@ async function actuateWithInfo(setup: Setup, config: Config, info: SdkRequiredIn } addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); } - ensureClientCache(connectorYaml); // TODO: Prompt user about adding generated paths to .gitignore const connectorYamlContents = yaml.stringify(connectorYaml); @@ -393,6 +392,9 @@ export function addSdkGenerateToConnectorYaml( react: app.frameworks?.includes(Framework.REACT) ?? false, angular: app.frameworks?.includes(Framework.ANGULAR) ?? false, }; + if (experiments.isEnabled("fdcrealtime")) { + javascriptSdk.clientCache = {}; + } if (!isArray(generate?.javascriptSdk)) { generate.javascriptSdk = generate.javascriptSdk ? [generate.javascriptSdk] : []; } @@ -407,6 +409,9 @@ export function addSdkGenerateToConnectorYaml( outputDir: path.relative(connectorDir, path.join(appDir, `lib/dataconnect_generated`)), package: "dataconnect_generated/generated.dart", }; + if (experiments.isEnabled("fdcrealtime")) { + dartSdk.clientCache = {}; + } if (!isArray(generate?.dartSdk)) { generate.dartSdk = generate.dartSdk ? [generate.dartSdk] : []; } @@ -421,6 +426,9 @@ export function addSdkGenerateToConnectorYaml( outputDir: path.relative(connectorDir, path.join(app.directory, "src/main/kotlin")), package: `com.google.firebase.dataconnect.generated`, }; + if (experiments.isEnabled("fdcrealtime")) { + kotlinSdk.clientCache = {}; + } if (!isArray(generate?.kotlinSdk)) { generate.kotlinSdk = generate.kotlinSdk ? [generate.kotlinSdk] : []; } @@ -438,6 +446,9 @@ export function addSdkGenerateToConnectorYaml( ), package: "DataConnectGenerated", }; + if (experiments.isEnabled("fdcrealtime")) { + swiftSdk.clientCache = {}; + } if (!isArray(generate?.swiftSdk)) { generate.swiftSdk = generate.swiftSdk ? [generate.swiftSdk] : []; } @@ -454,35 +465,6 @@ export function addSdkGenerateToConnectorYaml( ).join(", ")}\n${JSON.stringify(app)}`, ); } - ensureClientCache(connectorYaml); -} - -/** - * Ensures all supported client SDKs in the connector.yaml have clientCache: {} if missing and experiment is on. - */ -export function ensureClientCache(connectorYaml: ConnectorYaml): void { - if (!connectorYaml.generate || !experiments.isEnabled("fdcrealtime")) { - return; - } - const generate = connectorYaml.generate; - const sdkFields: (keyof typeof generate)[] = [ - "javascriptSdk", - "swiftSdk", - "kotlinSdk", - "dartSdk", - ]; - for (const field of sdkFields) { - const val = generate[field]; - if (val) { - const sdkList = isArray(val) ? val : [val]; - (generate as any)[field] = sdkList; - for (const sdk of sdkList as any[]) { - if (!sdk.clientCache) { - sdk.clientCache = {}; - } - } - } - } } function dedupeAppsByPlatformAndDirectory(apps: App[]): App[] { From 8bccae6d736183d91a686df50f0a7e91862b7d27 Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Fri, 20 Mar 2026 18:35:50 -0700 Subject: [PATCH 09/14] Update experiments.ts --- src/experiments.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/experiments.ts b/src/experiments.ts index 06107d200dd..b1106d154d6 100644 --- a/src/experiments.ts +++ b/src/experiments.ts @@ -186,7 +186,7 @@ export const ALL_EXPERIMENTS = experiments({ }, fdcrealtime: { shortDescription: "Enable Firebase Data Connect realtime feature.", - default: true, + default: false, public: false, }, }); From bab80cabd3e18a83bd3df1dd88e1cab2990efdc7 Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Fri, 20 Mar 2026 18:36:51 -0700 Subject: [PATCH 10/14] Update sdk.spec.ts --- src/init/features/dataconnect/sdk.spec.ts | 55 ++--------------------- 1 file changed, 4 insertions(+), 51 deletions(-) diff --git a/src/init/features/dataconnect/sdk.spec.ts b/src/init/features/dataconnect/sdk.spec.ts index 074fc0aacd8..8e081b9a1c6 100644 --- a/src/init/features/dataconnect/sdk.spec.ts +++ b/src/init/features/dataconnect/sdk.spec.ts @@ -22,8 +22,8 @@ import * as dcLoad from "../../../dataconnect/load"; import * as fsutils from "../../../fsutils"; import * as auth from "../../../auth"; import * as utils from "../../../utils"; -import * as experiments from "../../../experiments"; import * as prompt from "../../../prompt"; +import * as experiments from "../../../experiments"; const expect = chai.expect; @@ -63,7 +63,6 @@ describe("addSdkGenerateToConnectorYaml", () => { packageJsonDir: "../app", react: false, angular: false, - clientCache: {}, }, ]); }); @@ -78,7 +77,6 @@ describe("addSdkGenerateToConnectorYaml", () => { packageJsonDir: "../app", react: true, angular: false, - clientCache: {}, }, ]); }); @@ -90,7 +88,6 @@ describe("addSdkGenerateToConnectorYaml", () => { { outputDir: "../app/lib/dataconnect_generated", package: "dataconnect_generated/generated.dart", - clientCache: {}, }, ]); }); @@ -102,7 +99,6 @@ describe("addSdkGenerateToConnectorYaml", () => { { outputDir: "../app/src/main/kotlin", package: "com.google.firebase.dataconnect.generated", - clientCache: {}, }, ]); }); @@ -114,12 +110,11 @@ describe("addSdkGenerateToConnectorYaml", () => { { outputDir: "../FirebaseDataConnectGenerated", package: "DataConnectGenerated", - clientCache: {}, }, ]); }); - it("should add adminSdk for admin node platform and NOT include clientCache", () => { + it("should add adminSdk for admin node platform", () => { app.platform = Platform.ADMIN_NODE; addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); expect(connectorYaml.generate?.adminNodeSdk).to.deep.equal([ @@ -129,54 +124,14 @@ describe("addSdkGenerateToConnectorYaml", () => { packageJsonDir: "../app", }, ]); - expect((connectorYaml.generate?.adminNodeSdk as any)[0].clientCache).to.be.undefined; - }); - - it("should NOT add clientCache: {} to all new generated SDKs when fdcrealtime is disabled", () => { - sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(false); - - // Add Web SDK - app.platform = Platform.WEB; - addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); - - // Add Flutter SDK - const flutterApp: App = { - directory: "/users/test/project/flutter_app", - platform: Platform.FLUTTER, - }; - addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, flutterApp); - - expect(connectorYaml.generate?.javascriptSdk).to.have.lengthOf(1); - expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.be.undefined; - - expect(connectorYaml.generate?.dartSdk).to.have.lengthOf(1); - expect((connectorYaml.generate?.dartSdk as any)[0].clientCache).to.be.undefined; }); - it("should add clientCache: {} when fdcrealtime experiment is enabled", () => { + it("should conditionally inject clientCache if fdcrealtime is enabled", () => { sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(true); addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({}); }); - it("should NOT upgrade existing SDK entry with clientCache: {} if missing", () => { - sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(true); - connectorYaml.generate = { - javascriptSdk: [ - { - outputDir: "../app/src/dataconnect-generated", - package: "@dataconnect/generated", - packageJsonDir: "../app", - react: false, - angular: false, - }, - ], - }; - addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); - expect(connectorYaml.generate?.javascriptSdk).to.have.lengthOf(1); - expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.be.undefined; - }); - it("should NOT overwrite existing clientCache configuration", () => { sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(true); connectorYaml.generate = { @@ -195,9 +150,7 @@ describe("addSdkGenerateToConnectorYaml", () => { }; addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); expect(connectorYaml.generate?.javascriptSdk).to.have.lengthOf(1); - expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({ - type: "memory", - }); + expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({ type: "memory" }); }); }); From 8f306553719d492aee6cbb2f76d983a6500ef200 Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Sat, 21 Mar 2026 18:57:49 -0700 Subject: [PATCH 11/14] Update sdk.spec.ts --- src/init/features/dataconnect/sdk.spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/init/features/dataconnect/sdk.spec.ts b/src/init/features/dataconnect/sdk.spec.ts index 8e081b9a1c6..17e428614e9 100644 --- a/src/init/features/dataconnect/sdk.spec.ts +++ b/src/init/features/dataconnect/sdk.spec.ts @@ -150,7 +150,9 @@ describe("addSdkGenerateToConnectorYaml", () => { }; addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); expect(connectorYaml.generate?.javascriptSdk).to.have.lengthOf(1); - expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({ type: "memory" }); + expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({ + type: "memory", + }); }); }); From c5c754d99c77f7a79446818bd73abb701ed41fdf Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Tue, 24 Mar 2026 14:16:37 -0700 Subject: [PATCH 12/14] Include empty clientCache configs on init --- src/init/features/dataconnect/sdk.ts | 44 ++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/init/features/dataconnect/sdk.ts b/src/init/features/dataconnect/sdk.ts index 5eba5e07aaf..8f98b8b6725 100644 --- a/src/init/features/dataconnect/sdk.ts +++ b/src/init/features/dataconnect/sdk.ts @@ -15,7 +15,9 @@ import { DartSDK, JavascriptSDK, KotlinSDK, + SwiftSDK, } from "../../../dataconnect/types"; +import * as experiments from "../../../experiments"; import { FirebaseError } from "../../../error"; import { isArray } from "lodash"; import { @@ -381,19 +383,23 @@ export function addSdkGenerateToConnectorYaml( case Platform.WEB: { const javascriptSdk: JavascriptSDK = { - outputDir: path.relative(connectorDir, path.join(appDir, `src/dataconnect-generated`)), - package: `@dataconnect/generated`, - packageJsonDir: path.relative(connectorDir, appDir), - react: false, - angular: false, + outputDir: path.relative( + connectorDir, + path.join(app.directory, "src/dataconnect-generated"), + ), + package: "@dataconnect/generated", + packageJsonDir: path.relative(connectorDir, app.directory), + react: app.frameworks?.includes(Framework.REACT) ?? false, + angular: app.frameworks?.includes(Framework.ANGULAR) ?? false, }; - for (const f of app.frameworks || []) { - javascriptSdk[f] = true; + if (experiments.isEnabled("fdcrealtime")) { + javascriptSdk.clientCache = {}; } if (!isArray(generate?.javascriptSdk)) { generate.javascriptSdk = generate.javascriptSdk ? [generate.javascriptSdk] : []; } - if (!generate.javascriptSdk.some((s) => s.outputDir === javascriptSdk.outputDir)) { + const existing = generate.javascriptSdk.find((s) => s.outputDir === javascriptSdk.outputDir); + if (!existing) { generate.javascriptSdk.push(javascriptSdk); } break; @@ -403,39 +409,51 @@ export function addSdkGenerateToConnectorYaml( outputDir: path.relative(connectorDir, path.join(appDir, `lib/dataconnect_generated`)), package: "dataconnect_generated/generated.dart", }; + if (experiments.isEnabled("fdcrealtime")) { + dartSdk.clientCache = {}; + } if (!isArray(generate?.dartSdk)) { generate.dartSdk = generate.dartSdk ? [generate.dartSdk] : []; } - if (!generate.dartSdk.some((s) => s.outputDir === dartSdk.outputDir)) { + const existing = generate.dartSdk.find((s) => s.outputDir === dartSdk.outputDir); + if (!existing) { generate.dartSdk.push(dartSdk); } break; } case Platform.ANDROID: { const kotlinSdk: KotlinSDK = { - outputDir: path.relative(connectorDir, path.join(appDir, `src/main/kotlin`)), + outputDir: path.relative(connectorDir, path.join(app.directory, "src/main/kotlin")), package: `com.google.firebase.dataconnect.generated`, }; + if (experiments.isEnabled("fdcrealtime")) { + kotlinSdk.clientCache = {}; + } if (!isArray(generate?.kotlinSdk)) { generate.kotlinSdk = generate.kotlinSdk ? [generate.kotlinSdk] : []; } - if (!generate.kotlinSdk.some((s) => s.outputDir === kotlinSdk.outputDir)) { + const existing = generate.kotlinSdk.find((s) => s.outputDir === kotlinSdk.outputDir); + if (!existing) { generate.kotlinSdk.push(kotlinSdk); } break; } case Platform.IOS: { - const swiftSdk = { + const swiftSdk: SwiftSDK = { outputDir: path.relative( connectorDir, path.join(app.directory, `../FirebaseDataConnectGenerated`), ), package: "DataConnectGenerated", }; + if (experiments.isEnabled("fdcrealtime")) { + swiftSdk.clientCache = {}; + } if (!isArray(generate?.swiftSdk)) { generate.swiftSdk = generate.swiftSdk ? [generate.swiftSdk] : []; } - if (!generate.swiftSdk.some((s) => s.outputDir === swiftSdk.outputDir)) { + const existing = generate.swiftSdk.find((s) => s.outputDir === swiftSdk.outputDir); + if (!existing) { generate.swiftSdk.push(swiftSdk); } break; From bc44b4226b59a6cebe0dac8b2acbeca1b994cd9a Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Tue, 24 Mar 2026 14:18:14 -0700 Subject: [PATCH 13/14] Update sdk.spec.ts --- src/init/features/dataconnect/sdk.spec.ts | 34 +++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/init/features/dataconnect/sdk.spec.ts b/src/init/features/dataconnect/sdk.spec.ts index 7c5365fa5c1..17e428614e9 100644 --- a/src/init/features/dataconnect/sdk.spec.ts +++ b/src/init/features/dataconnect/sdk.spec.ts @@ -23,6 +23,7 @@ import * as fsutils from "../../../fsutils"; import * as auth from "../../../auth"; import * as utils from "../../../utils"; import * as prompt from "../../../prompt"; +import * as experiments from "../../../experiments"; const expect = chai.expect; @@ -49,6 +50,10 @@ describe("addSdkGenerateToConnectorYaml", () => { }; }); + afterEach(() => { + sinon.restore(); + }); + it("should add javascriptSdk for web platform", () => { addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); expect(connectorYaml.generate?.javascriptSdk).to.deep.equal([ @@ -120,6 +125,35 @@ describe("addSdkGenerateToConnectorYaml", () => { }, ]); }); + + it("should conditionally inject clientCache if fdcrealtime is enabled", () => { + sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(true); + addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); + expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({}); + }); + + it("should NOT overwrite existing clientCache configuration", () => { + sinon.stub(experiments, "isEnabled").withArgs("fdcrealtime").returns(true); + connectorYaml.generate = { + javascriptSdk: [ + { + outputDir: "../app/src/dataconnect-generated", + package: "@dataconnect/generated", + packageJsonDir: "../app", + react: false, + angular: false, + clientCache: { + type: "memory", + } as any, + }, + ], + }; + addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app); + expect(connectorYaml.generate?.javascriptSdk).to.have.lengthOf(1); + expect((connectorYaml.generate?.javascriptSdk as any)[0].clientCache).to.deep.equal({ + type: "memory", + }); + }); }); describe("chooseApp", () => { From 9a6a20528ecb3be1c52bccec2afd5b054a8c5b86 Mon Sep 17 00:00:00 2001 From: Akhil Raveendran <153134308+itsrakhil@users.noreply.github.com> Date: Tue, 24 Mar 2026 14:18:58 -0700 Subject: [PATCH 14/14] Update experiments.ts --- src/experiments.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/experiments.ts b/src/experiments.ts index 87168a1f716..909a9a89425 100644 --- a/src/experiments.ts +++ b/src/experiments.ts @@ -193,6 +193,11 @@ export const ALL_EXPERIMENTS = experiments({ default: true, public: false, }, + fdcrealtime: { + shortDescription: "Enable Firebase Data Connect realtime feature.", + default: false, + public: false, + }, }); export type ExperimentName = keyof typeof ALL_EXPERIMENTS;