import { ConfigPlugin, IOSConfig, WarningAggregator, XcodeProject, withInfoPlist, withXcodeProject, } from 'expo/config-plugins'; import type { PluginConfigType } from './pluginConfig'; const { createBuildPodfilePropsConfigPlugin } = IOSConfig.BuildProperties; export const withIosBuildProperties = createBuildPodfilePropsConfigPlugin( [ { propName: 'newArchEnabled', propValueGetter: (config) => { if (config.ios?.newArchEnabled !== undefined) { WarningAggregator.addWarningIOS( 'withIosBuildProperties', 'ios.newArchEnabled is deprecated, use app config `newArchEnabled` instead.\n' + 'https://docs.expo.dev/versions/latest/config/app/#newarchenabled' ); } return config.ios?.newArchEnabled?.toString(); }, }, { propName: 'ios.useFrameworks', propValueGetter: (config) => config.ios?.useFrameworks, }, { propName: 'ios.forceStaticLinking', propValueGetter: (config) => JSON.stringify(config.ios?.forceStaticLinking ?? []), }, { propName: 'EX_DEV_CLIENT_NETWORK_INSPECTOR', propValueGetter: (config) => (config.ios?.networkInspector ?? true).toString(), }, { propName: 'apple.extraPods', propValueGetter: (config) => { const extraPods = config.ios?.extraPods ?? []; return extraPods.length > 0 ? JSON.stringify(extraPods) : undefined; }, }, { propName: 'apple.ccacheEnabled', propValueGetter: (config) => config.ios?.ccacheEnabled?.toString(), }, { propName: 'apple.privacyManifestAggregationEnabled', propValueGetter: (config) => (config.ios?.privacyManifestAggregationEnabled ?? true).toString(), }, { propName: 'ios.buildReactNativeFromSource', propValueGetter: (config) => config.ios?.buildReactNativeFromSource?.toString(), }, ], 'withIosBuildProperties' ); export const withIosDeploymentTarget: ConfigPlugin = (config, props) => { const deploymentTarget = props.ios?.deploymentTarget; if (!deploymentTarget) { return config; } // Updates deployment target in app xcodeproj config = withIosDeploymentTargetXcodeProject(config, { deploymentTarget }); // Updates deployement target in Podfile (Pods project) config = withIosDeploymentTargetPodfile(config, props); return config; }; export const withIosInfoPlist: ConfigPlugin = (config, props) => { const reactNativeReleaseLevel = props.ios?.reactNativeReleaseLevel; if (reactNativeReleaseLevel) { config = withIosReactNativeReleaseLevel(config, { reactNativeReleaseLevel }); } return config; }; const withIosReactNativeReleaseLevel: ConfigPlugin<{ reactNativeReleaseLevel: 'stable' | 'canary' | 'experimental'; }> = (config, { reactNativeReleaseLevel }) => { return withInfoPlist(config, (config) => { config.modResults['ReactNativeReleaseLevel'] = reactNativeReleaseLevel; return config; }); }; const withIosDeploymentTargetXcodeProject: ConfigPlugin<{ deploymentTarget: string }> = ( config, props ) => { return withXcodeProject(config, (config) => { config.modResults = updateDeploymentTargetXcodeProject( config.modResults, props.deploymentTarget ); return config; }); }; function updateDeploymentTargetXcodeProject( project: XcodeProject, deploymentTarget: string ): XcodeProject { const { Target } = IOSConfig; const targetBuildConfigListIds = Target.getNativeTargets(project) .filter(([_, target]) => Target.isTargetOfType(target, Target.TargetType.APPLICATION)) .map(([_, target]) => target.buildConfigurationList); for (const buildConfigListId of targetBuildConfigListIds) { for (const [, configurations] of IOSConfig.XcodeUtils.getBuildConfigurationsForListId( project, buildConfigListId )) { const { buildSettings } = configurations; if (buildSettings?.IPHONEOS_DEPLOYMENT_TARGET) { buildSettings.IPHONEOS_DEPLOYMENT_TARGET = deploymentTarget; } } } return project; } const withIosDeploymentTargetPodfile = createBuildPodfilePropsConfigPlugin( [ { propName: 'ios.deploymentTarget', propValueGetter: (config) => config.ios?.deploymentTarget, }, ], 'withIosDeploymentTargetPodfile' );