Skip to content

Commit 622a373

Browse files
authored
Added generated angular sdk support (#8291)
1 parent 8850562 commit 622a373

File tree

6 files changed

+71
-33
lines changed

6 files changed

+71
-33
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
- Added support for generated Angular SDKs for Data Connect
12
- App Hosting emulator can now load secret env vars. (#8305)
23
- Fixed webframeworks deployments when using multiple hosting sites in `firebase.json`. (#8314)
34
- Added a new command to setup a cleanup policy for functions artifacts. (#8268)

Diff for: src/dataconnect/fileUtils.spec.ts

+37-25
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as mockfs from "mock-fs";
22

33
import { expect } from "chai";
4-
import { getPlatformFromFolder, SUPPORTED_FRAMEWORKS } from "./fileUtils";
4+
import { frameworksMap, getPlatformFromFolder, SUPPORTED_FRAMEWORKS } from "./fileUtils";
55
import { generateSdkYaml } from "../init/features/dataconnect/sdk";
66
import { ConnectorYaml, Platform } from "./types";
77
import FileSystem from "mock-fs/lib/filesystem";
@@ -137,10 +137,12 @@ describe("getPlatformFromFolder", () => {
137137

138138
describe("generateSdkYaml", () => {
139139
// Test Data
140-
const sampleConnectorYaml: ConnectorYaml = {
141-
connectorId: "default",
142-
generate: {},
143-
};
140+
function getSampleConnectorYaml(): ConnectorYaml {
141+
return {
142+
connectorId: "default",
143+
generate: {},
144+
};
145+
}
144146
const connectorYamlFolder = "/my/app/folder/connector";
145147

146148
const appFolderBase = "/my/app/folder";
@@ -196,7 +198,7 @@ describe("generateSdkYaml", () => {
196198
mockfs({ [appFolderDetectable]: { ["package.json"]: "{}" } });
197199
const modifiedYaml = await generateSdkYaml(
198200
Platform.WEB,
199-
sampleConnectorYaml,
201+
getSampleConnectorYaml(),
200202
connectorYamlFolder,
201203
c.appDir,
202204
);
@@ -209,28 +211,38 @@ describe("generateSdkYaml", () => {
209211
const cases = [
210212
{
211213
desc: `can detect a ${f}`,
212-
depName: f,
214+
deps: frameworksMap[f],
213215
detect: true,
214216
},
215217
{
216218
desc: `can detect not ${f}`,
217-
depName: `not-${f}`,
219+
deps: `not-${f}`,
218220
},
219221
];
222+
async function testDependency(dep: string, shouldDetect: boolean | undefined) {
223+
mockfs({
224+
[appFolderDetectable]: {
225+
["package.json"]: `{"dependencies": {"${dep}": "1"}}`,
226+
},
227+
});
228+
const modifiedYaml = await generateSdkYaml(
229+
Platform.WEB,
230+
getSampleConnectorYaml(),
231+
connectorYamlFolder,
232+
appFolderDetectable,
233+
);
234+
console.log(`{"dependencies": {"${dep}": "1"}}`);
235+
expect(modifiedYaml.generate?.javascriptSdk?.[f]).to.equal(shouldDetect);
236+
}
220237
for (const c of cases) {
221238
it(c.desc, async () => {
222-
mockfs({
223-
[appFolderDetectable]: {
224-
["package.json"]: `{"dependencies": {"${c.depName}": "1"}}`,
225-
},
226-
});
227-
const modifiedYaml = await generateSdkYaml(
228-
Platform.WEB,
229-
sampleConnectorYaml,
230-
connectorYamlFolder,
231-
appFolderDetectable,
232-
);
233-
expect(modifiedYaml.generate?.javascriptSdk?.[f]).to.equal(c.detect);
239+
if (Array.isArray(c.deps)) {
240+
for (const dep of c.deps) {
241+
await testDependency(dep, c.detect);
242+
}
243+
} else {
244+
await testDependency(c.deps as string, c.detect);
245+
}
234246
});
235247
}
236248
});
@@ -271,7 +283,7 @@ describe("generateSdkYaml", () => {
271283
it(c.desc, async () => {
272284
const modifiedYaml = await generateSdkYaml(
273285
Platform.IOS,
274-
sampleConnectorYaml,
286+
getSampleConnectorYaml(),
275287
connectorYamlFolder,
276288
c.appDir,
277289
);
@@ -348,7 +360,7 @@ describe("generateSdkYaml", () => {
348360
});
349361
const modifiedYaml = await generateSdkYaml(
350362
Platform.ANDROID,
351-
sampleConnectorYaml,
363+
getSampleConnectorYaml(),
352364
connectorYamlFolder,
353365
c.appDir,
354366
);
@@ -392,7 +404,7 @@ describe("generateSdkYaml", () => {
392404
it(c.desc, async () => {
393405
const modifiedYaml = await generateSdkYaml(
394406
Platform.FLUTTER,
395-
sampleConnectorYaml,
407+
getSampleConnectorYaml(),
396408
connectorYamlFolder,
397409
c.appDir,
398410
);
@@ -416,11 +428,11 @@ describe("generateSdkYaml", () => {
416428
const unknownPlatform = "unknown" as Platform; // Type assertion for test
417429
const modifiedYaml = await generateSdkYaml(
418430
unknownPlatform,
419-
sampleConnectorYaml,
431+
getSampleConnectorYaml(),
420432
connectorYamlFolder,
421433
appFolderBase,
422434
);
423-
expect(modifiedYaml).to.deep.equal(sampleConnectorYaml); // No changes
435+
expect(modifiedYaml).to.deep.equal(getSampleConnectorYaml()); // No changes
424436
});
425437

426438
afterEach(() => {

Diff for: src/dataconnect/fileUtils.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -177,16 +177,18 @@ export async function resolvePackageJson(
177177
}
178178
}
179179

180-
export const SUPPORTED_FRAMEWORKS: (keyof SupportedFrameworks)[] = ["react"];
180+
export const SUPPORTED_FRAMEWORKS: (keyof SupportedFrameworks)[] = ["react", "angular"];
181+
export const frameworksMap: { [key in keyof SupportedFrameworks]: string[] } = {
182+
react: ["react", "next"],
183+
angular: ["@angular/core"],
184+
};
181185
export function getFrameworksFromPackageJson(
182186
packageJson: PackageJSON,
183187
): (keyof SupportedFrameworks)[] {
184188
const devDependencies = Object.keys(packageJson.devDependencies ?? {});
185189
const dependencies = Object.keys(packageJson.dependencies ?? {});
186-
const matched = new Set(
187-
[...devDependencies, ...dependencies].filter((dep) =>
188-
SUPPORTED_FRAMEWORKS.includes(dep as keyof SupportedFrameworks),
189-
),
190+
const allDeps = Array.from(new Set([...devDependencies, ...dependencies]));
191+
return SUPPORTED_FRAMEWORKS.filter((framework) =>
192+
frameworksMap[framework]!.find((dep) => allDeps.includes(dep)),
190193
);
191-
return Array.from(matched) as (keyof SupportedFrameworks)[];
192194
}

Diff for: src/dataconnect/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ export interface Generate {
148148

149149
export interface SupportedFrameworks {
150150
react?: boolean;
151+
angular?: boolean;
151152
}
152153

153154
export interface JavascriptSDK extends SupportedFrameworks {

Diff for: src/init/features/dataconnect/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export async function doSetup(setup: Setup, config: Config): Promise<void> {
9393
await sdk.doSetup(setup, config);
9494
} else {
9595
logBullet(
96-
`If you'd like to add the generated SDK to your app your, run ${clc.bold("firebase init dataconnect:sdk")}`,
96+
`If you'd like to add the generated SDK to your app later, run ${clc.bold("firebase init dataconnect:sdk")}`,
9797
);
9898
}
9999
if (setup.projectId && !isBillingEnabled) {

Diff for: src/init/features/dataconnect/sdk.ts

+23-1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ async function askQuestions(setup: Setup, config: Config): Promise<SDKInfo> {
118118
const unusedFrameworks = SUPPORTED_FRAMEWORKS.filter(
119119
(framework) => !newConnectorYaml!.generate?.javascriptSdk![framework],
120120
);
121+
const hasFrameworkEnabled = unusedFrameworks.length < SUPPORTED_FRAMEWORKS.length;
121122
if (unusedFrameworks.length > 0) {
122123
const additionalFrameworks: { fdcFrameworks: (keyof SupportedFrameworks)[] } = await prompt(
123124
setup,
@@ -126,7 +127,7 @@ async function askQuestions(setup: Setup, config: Config): Promise<SDKInfo> {
126127
type: "checkbox",
127128
name: "fdcFrameworks",
128129
message:
129-
"Which framework would you like to generate SDKs for? " +
130+
`Which ${hasFrameworkEnabled && "additional "}frameworks would you like to generate SDKs for? ` +
130131
"Press Space to select features, then Enter to confirm your choices.",
131132
choices: unusedFrameworks.map((frameworkStr) => ({
132133
value: frameworkStr,
@@ -182,6 +183,7 @@ export async function generateSdkYaml(
182183
if (packageJson) {
183184
const frameworksUsed = getFrameworksFromPackageJson(packageJson);
184185
for (const framework of frameworksUsed) {
186+
logBullet(`Detected ${framework} app. Enabling ${framework} generated SDKs.`);
185187
javascriptSdk[framework] = true;
186188
}
187189
}
@@ -237,4 +239,24 @@ export async function actuate(sdkInfo: SDKInfo) {
237239
),
238240
);
239241
}
242+
if (sdkInfo.connectorInfo.connectorYaml.generate?.javascriptSdk) {
243+
for (const framework of SUPPORTED_FRAMEWORKS) {
244+
if (sdkInfo.connectorInfo.connectorYaml!.generate!.javascriptSdk![framework]) {
245+
logInfoForFramework(framework);
246+
}
247+
}
248+
}
249+
}
250+
251+
function logInfoForFramework(framework: keyof SupportedFrameworks) {
252+
if (framework === "react") {
253+
logBullet(
254+
"Visit https://firebase.google.com/docs/data-connect/web-sdk#react for more information on how to set up React Generated SDKs for Firebase Data Connect",
255+
);
256+
} else if (framework === "angular") {
257+
// TODO(mtewani): Replace this with `ng add @angular/fire` when ready.
258+
logBullet(
259+
"Run `npm i --save @angular/fire @tanstack-query-firebase/angular @tanstack/angular-query-experimental` to install angular sdk dependencies.\nVisit https://github.com/invertase/tanstack-query-firebase/tree/main/packages/angular for more information on how to set up Angular Generated SDKs for Firebase Data Connect",
260+
);
261+
}
240262
}

0 commit comments

Comments
 (0)