From d15c815bac38f2d459d77b76fbca5e6515df575d Mon Sep 17 00:00:00 2001 From: Wes Johnson Date: Mon, 9 Feb 2026 18:27:38 -0500 Subject: [PATCH] fix: config plugin should add all enabled flags to native manifests --- src/api/generateOverrides.ts | 20 ++++++++++++ src/api/index.ts | 12 +++++-- src/config-plugin/index.ts | 61 +++++++++++++++++++++++++++--------- test/test-config-plugin.js | 4 ++- 4 files changed, 79 insertions(+), 18 deletions(-) diff --git a/src/api/generateOverrides.ts b/src/api/generateOverrides.ts index c4efc2b..0d62eae 100644 --- a/src/api/generateOverrides.ts +++ b/src/api/generateOverrides.ts @@ -1,6 +1,26 @@ import { BuildFlags } from "./BuildFlags"; import { readConfig } from "./readConfig"; +export const resolveEnabledFlagNames = async ({ + flagsToEnable, + flagsToDisable, +}: { + flagsToEnable?: Set; + flagsToDisable?: Set; +}): Promise => { + const { flags: defaultFlags } = await readConfig(); + const flags = new BuildFlags(defaultFlags); + if (flagsToEnable) { + flags.enable(flagsToEnable); + } + if (flagsToDisable) { + flags.disable(flagsToDisable); + } + return Object.entries(flags.flags) + .filter(([_, config]) => config.value) + .map(([name]) => name); +}; + export const generateOverrides = async ({ flagsToEnable, flagsToDisable, diff --git a/src/api/index.ts b/src/api/index.ts index fee8b28..a5c1425 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,5 +1,13 @@ -import { generateOverrides } from "./generateOverrides"; +import { + generateOverrides, + resolveEnabledFlagNames, +} from "./generateOverrides"; import { resolveFlagsToInvert } from "./resolveFlagsToInvert"; import { readConfig } from "./readConfig"; -export { generateOverrides, resolveFlagsToInvert, readConfig }; +export { + generateOverrides, + resolveEnabledFlagNames, + resolveFlagsToInvert, + readConfig, +}; diff --git a/src/config-plugin/index.ts b/src/config-plugin/index.ts index 86c314f..20eec1b 100644 --- a/src/config-plugin/index.ts +++ b/src/config-plugin/index.ts @@ -7,16 +7,42 @@ import { withInfoPlist, } from "@expo/config-plugins"; import { ExpoConfig } from "@expo/config-types"; -import { generateOverrides, resolveFlagsToInvert } from "../api"; +import { + generateOverrides, + resolveEnabledFlagNames, + resolveFlagsToInvert, +} from "../api"; import pkg from "../../package.json"; import { withFlaggedAutolinking } from "./withFlaggedAutolinking"; import { mergeSets } from "../api/mergeSets"; -const withAndroidBuildFlags: ConfigPlugin<{ flags: string[] }> = ( +type NativeFlagPluginProps = { envFlags: string[]; expoConfig: ExpoConfig }; + +let cachedResolvedFlags: string[] | null = null; +const resolveAllEnabledFlags = async ( + envFlags: string[], + expoConfig: ExpoConfig +): Promise => { + if (cachedResolvedFlags) { + return cachedResolvedFlags; + } + let flagsToEnable = new Set(envFlags); + const invertable = await resolveFlagsToInvert(expoConfig); + if (invertable.flagsToEnable.size > 0) { + flagsToEnable = mergeSets(flagsToEnable, invertable.flagsToEnable); + } + cachedResolvedFlags = await resolveEnabledFlagNames({ + flagsToEnable, + flagsToDisable: invertable.flagsToDisable, + }); + return cachedResolvedFlags; +}; + +const withAndroidBuildFlags: ConfigPlugin = ( config, props ) => { - return withAndroidManifest(config, (config) => { + return withAndroidManifest(config, async (config) => { if (!config.modResults) { throw new Error("AndroidManifest.xml not found in the project"); } @@ -26,13 +52,18 @@ const withAndroidBuildFlags: ConfigPlugin<{ flags: string[] }> = ( throw new Error("Application node not found in AndroidManifest.xml"); } + const resolvedFlags = await resolveAllEnabledFlags( + props.envFlags, + props.expoConfig + ); + const meta = mainApplication["meta-data"]; mainApplication["meta-data"] = [ ...(meta ?? []), { $: { "android:name": "EXBuildFlags", - "android:value": props.flags.join(","), + "android:value": resolvedFlags.join(","), }, }, ]; @@ -41,12 +72,16 @@ const withAndroidBuildFlags: ConfigPlugin<{ flags: string[] }> = ( }); }; -const withAppleBuildFlags: ConfigPlugin<{ flags: string[] }> = ( +const withAppleBuildFlags: ConfigPlugin = ( config, props ) => { - return withInfoPlist(config, (config) => { - config.modResults.EXBuildFlags = props.flags; + return withInfoPlist(config, async (config) => { + const resolvedFlags = await resolveAllEnabledFlags( + props.envFlags, + props.expoConfig + ); + config.modResults.EXBuildFlags = resolvedFlags; return config; }); }; @@ -124,15 +159,11 @@ type ConfigPluginProps = type WithBuildFlagsProps = { skipBundleOverride?: boolean; flags: string[] }; const withBuildFlags: ConfigPlugin = (config, props) => { - const flags = props.flags; - if (!flags.length) { - return props?.skipBundleOverride - ? config - : withBundleFlags(config, { flags }); - } + const { flags } = props; + const nativeProps = { envFlags: flags, expoConfig: config }; - const nativeConfig = withAndroidBuildFlags(config, { flags }); - const mergedNativeConfig = withAppleBuildFlags(nativeConfig, { flags }); + const nativeConfig = withAndroidBuildFlags(config, nativeProps); + const mergedNativeConfig = withAppleBuildFlags(nativeConfig, nativeProps); if (props?.skipBundleOverride) { return mergedNativeConfig; } diff --git a/test/test-config-plugin.js b/test/test-config-plugin.js index 8934c49..aeb74d7 100644 --- a/test/test-config-plugin.js +++ b/test/test-config-plugin.js @@ -13,13 +13,15 @@ export const BuildFlags = { `; const expectedManifestTag = - ''; + ''; const expectedPlistFlagArray = ` EXBuildFlags secretFeature + publishedFeatured newFeature + bundleIdScopedFeature `;