Skip to content

Conversation

schnecle
Copy link
Contributor

@schnecle schnecle commented Oct 8, 2025

Description

  • Refactor dataconnect tools to use common appUtils
  • Increase test coverage

Scenarios Tested

  • Platform detection in /firebase:init for web, ios, android and multiple. Example output:
> /firebase:init


ℹRequest cancelled.
 

> Can you print out the prompt you just received

✦ Your goal is to help the user setup Firebase services in this workspace. Firebase is a large platform with many potential uses, so you will:

   1. Detect which Firebase services are already in use in the workspace, if any
   2. Determine which new Firebase services will help the user build their app
   3. Provision and configure the services requested by the user

  Workspace Info

  Use this information to determine which Firebase services the user is already using (if any).

  Workspace platform(s): ANDROID, IOS
  • Ran firebase init on a web application

Sample Commands

  • /firebase:init
  • firebase init

// Detect what platform based on current user
let targetPlatform = await getPlatformFromFolder(appDir);
if (targetPlatform === Platform.NONE) {
let targetPlatforms = await getPlatformsFromFolder(appDir);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maneesht is the right person to take a look at management/apps.ts~

I took a glance. Don't see any issues.

@schnecle schnecle requested a review from maneesht October 9, 2025 15:04
@schnecle schnecle force-pushed the schnecle/cleanup-dataconnect-apputils branch from b6bdceb to 79b8215 Compare October 9, 2025 19:51
@schnecle schnecle marked this pull request as ready for review October 9, 2025 19:51
@schnecle schnecle force-pushed the schnecle/cleanup-dataconnect-apputils branch from 79b8215 to 0eca209 Compare October 9, 2025 19:52
@schnecle schnecle requested a review from joehan October 9, 2025 19:55
Copy link
Contributor

@fredzqm fredzqm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

I am able to verify the FDC app detection logics still work.

@joehan
Copy link
Contributor

joehan commented Oct 9, 2025

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request does a great job of refactoring the app detection logic into a common appUtils module, which improves code organization and reusability. The increased test coverage is also a welcome addition. I've found a critical issue with a new deduplication function and a couple of other points that I've detailed in the specific comments. Once these are addressed, this will be a solid improvement.

Comment on lines +389 to +405
function dedupeAppsByPlatformAndDirectory(apps: App[]): App[] {
// detectApps creates unique apps by appId and bundleId, but this method operates
// on platform, directory, and frameworks alone. Deduping here to retain the
// same behavior
return [
...new Set(
apps.map(
(app) =>
({
platform: app.platform,
directory: app.directory,
frameworks: app.frameworks,
}) as App,
),
),
];
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The dedupeAppsByPlatformAndDirectory function is implemented using new Set() on newly created objects inside a map. This will not correctly deduplicate the apps because objects in JavaScript are compared by reference, and each iteration of map creates a new object instance. This can lead to duplicate app configurations being processed downstream.

To fix this, you should generate a unique key for each app based on its properties and use a Map to ensure uniqueness.

Suggested change
function dedupeAppsByPlatformAndDirectory(apps: App[]): App[] {
// detectApps creates unique apps by appId and bundleId, but this method operates
// on platform, directory, and frameworks alone. Deduping here to retain the
// same behavior
return [
...new Set(
apps.map(
(app) =>
({
platform: app.platform,
directory: app.directory,
frameworks: app.frameworks,
}) as App,
),
),
];
}
function dedupeAppsByPlatformAndDirectory(apps: App[]): App[] {
// detectApps creates unique apps by appId and bundleId, but this method operates
// on platform, directory, and frameworks alone. Deduping here to retain the
// same behavior
const uniqueApps = new Map<string, App>();
for (const app of apps) {
// Sorting frameworks for consistent key generation
const frameworkKey = app.frameworks ? [...app.frameworks].sort().join(",") : "";
const key = `${app.platform}:${app.directory}:${frameworkKey}`;
if (!uniqueApps.has(key)) {
// Create a new object with only the desired properties to avoid carrying over others like appId
uniqueApps.set(key, {
platform: app.platform,
directory: app.directory,
frameworks: app.frameworks,
});
}
}
return Array.from(uniqueApps.values());
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does seem legit and worth fixing.

Comment on lines +195 to +211
it("should deduplicate apps with the same platform and directory", async () => {
const apps: App[] = [
{ platform: Platform.WEB, directory: "web", frameworks: [Framework.REACT], appId: "app1" },
{ platform: Platform.WEB, directory: "web", frameworks: [Framework.REACT], appId: "app2" },
{ platform: Platform.ANDROID, directory: "android" },
];
detectAppsStub.resolves(apps);
promptStub.resolves([
{ platform: Platform.WEB, directory: "web", frameworks: [Framework.REACT] },
]);

const selectedApps = await chooseApp();

expect(selectedApps).to.deep.equal([
{ platform: Platform.WEB, directory: "web", frameworks: [Framework.REACT] },
]);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This test case should deduplicate apps with the same platform and directory doesn't properly validate the deduplication logic. It mocks the result of the user prompt, which hides the fact that chooseApp would present duplicated choices to the user due to the faulty dedupeAppsByPlatformAndDirectory function.

To make this test more robust, you should assert that the choices argument passed to the prompt.checkbox stub contains deduplicated entries.


if (targetPlatforms.length !== 1) {
if (targetPlatforms.length === 0) {
logBullet(`Couldn't automatically detect app your in directory ${appDir}.`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There's a minor typo in this log message.

Suggested change
logBullet(`Couldn't automatically detect app your in directory ${appDir}.`);
logBullet(`Couldn't automatically detect your app in directory ${appDir}.`);

// Check for environment variables override.
const envAppFolder = envOverride(FDC_APP_FOLDER, "");
const envPlatform = envOverride(FDC_SDK_PLATFORM_ENV, Platform.NONE) as Platform;
const envPlatform: Platform | undefined = envOverride(FDC_SDK_PLATFORM_ENV, "") as Platform;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This typing seems a little wonky to me? I believe this will either be a string from the env var, or "", neither of which are undefined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants