1082815dcSEvan Baconimport type { ExpoConfig } from '@expo/config-types'; 2082815dcSEvan Baconimport type { JSONObject } from '@expo/json-file'; 3082815dcSEvan Baconimport type { XcodeProject } from 'xcode'; 4082815dcSEvan Bacon 5*8a424bebSJames Ideimport { withMod } from './withMod'; 6082815dcSEvan Baconimport type { ConfigPlugin, Mod } from '../Plugin.types'; 7082815dcSEvan Baconimport type { ExpoPlist, InfoPlist } from '../ios/IosConfig.types'; 8082815dcSEvan Baconimport type { AppDelegateProjectFile } from '../ios/Paths'; 9082815dcSEvan Baconimport { get } from '../utils/obj'; 10082815dcSEvan Baconimport { addWarningIOS } from '../utils/warnings'; 11082815dcSEvan Bacon 12082815dcSEvan Bacontype MutateInfoPlistAction = ( 13082815dcSEvan Bacon expo: ExpoConfig, 14082815dcSEvan Bacon infoPlist: InfoPlist 15082815dcSEvan Bacon) => Promise<InfoPlist> | InfoPlist; 16082815dcSEvan Bacon 17082815dcSEvan Bacon/** 18082815dcSEvan Bacon * Helper method for creating mods from existing config functions. 19082815dcSEvan Bacon * 20082815dcSEvan Bacon * @param action 21082815dcSEvan Bacon */ 22082815dcSEvan Baconexport function createInfoPlistPlugin(action: MutateInfoPlistAction, name?: string): ConfigPlugin { 23082815dcSEvan Bacon const withUnknown: ConfigPlugin = (config) => 24082815dcSEvan Bacon withInfoPlist(config, async (config) => { 25082815dcSEvan Bacon config.modResults = await action(config, config.modResults); 26082815dcSEvan Bacon return config; 27082815dcSEvan Bacon }); 28082815dcSEvan Bacon if (name) { 29082815dcSEvan Bacon Object.defineProperty(withUnknown, 'name', { 30082815dcSEvan Bacon value: name, 31082815dcSEvan Bacon }); 32082815dcSEvan Bacon } 33082815dcSEvan Bacon return withUnknown; 34082815dcSEvan Bacon} 35082815dcSEvan Bacon 36082815dcSEvan Baconexport function createInfoPlistPluginWithPropertyGuard( 37082815dcSEvan Bacon action: MutateInfoPlistAction, 38082815dcSEvan Bacon settings: { 39082815dcSEvan Bacon infoPlistProperty: string; 40082815dcSEvan Bacon expoConfigProperty: string; 41082815dcSEvan Bacon expoPropertyGetter?: (config: ExpoConfig) => string; 42082815dcSEvan Bacon }, 43082815dcSEvan Bacon name?: string 44082815dcSEvan Bacon): ConfigPlugin { 45082815dcSEvan Bacon const withUnknown: ConfigPlugin = (config) => 46082815dcSEvan Bacon withInfoPlist(config, async (config) => { 47082815dcSEvan Bacon const existingProperty = settings.expoPropertyGetter 48082815dcSEvan Bacon ? settings.expoPropertyGetter(config) 49082815dcSEvan Bacon : get(config, settings.expoConfigProperty); 50082815dcSEvan Bacon // If the user explicitly sets a value in the infoPlist, we should respect that. 51082815dcSEvan Bacon if (config.modRawConfig.ios?.infoPlist?.[settings.infoPlistProperty] === undefined) { 52082815dcSEvan Bacon config.modResults = await action(config, config.modResults); 53082815dcSEvan Bacon } else if (existingProperty !== undefined) { 54082815dcSEvan Bacon // Only warn if there is a conflict. 55082815dcSEvan Bacon addWarningIOS( 56082815dcSEvan Bacon settings.expoConfigProperty, 57082815dcSEvan Bacon `"ios.infoPlist.${settings.infoPlistProperty}" is set in the config. Ignoring abstract property "${settings.expoConfigProperty}": ${existingProperty}` 58082815dcSEvan Bacon ); 59082815dcSEvan Bacon } 60082815dcSEvan Bacon 61082815dcSEvan Bacon return config; 62082815dcSEvan Bacon }); 63082815dcSEvan Bacon if (name) { 64082815dcSEvan Bacon Object.defineProperty(withUnknown, 'name', { 65082815dcSEvan Bacon value: name, 66082815dcSEvan Bacon }); 67082815dcSEvan Bacon } 68082815dcSEvan Bacon return withUnknown; 69082815dcSEvan Bacon} 70082815dcSEvan Bacon 71082815dcSEvan Bacontype MutateEntitlementsPlistAction = (expo: ExpoConfig, entitlements: JSONObject) => JSONObject; 72082815dcSEvan Bacon 73082815dcSEvan Bacon/** 74082815dcSEvan Bacon * Helper method for creating mods from existing config functions. 75082815dcSEvan Bacon * 76082815dcSEvan Bacon * @param action 77082815dcSEvan Bacon */ 78082815dcSEvan Baconexport function createEntitlementsPlugin( 79082815dcSEvan Bacon action: MutateEntitlementsPlistAction, 80082815dcSEvan Bacon name: string 81082815dcSEvan Bacon): ConfigPlugin { 82082815dcSEvan Bacon const withUnknown: ConfigPlugin = (config) => 83082815dcSEvan Bacon withEntitlementsPlist(config, async (config) => { 84082815dcSEvan Bacon config.modResults = await action(config, config.modResults); 85082815dcSEvan Bacon return config; 86082815dcSEvan Bacon }); 87082815dcSEvan Bacon if (name) { 88082815dcSEvan Bacon Object.defineProperty(withUnknown, 'name', { 89082815dcSEvan Bacon value: name, 90082815dcSEvan Bacon }); 91082815dcSEvan Bacon } 92082815dcSEvan Bacon return withUnknown; 93082815dcSEvan Bacon} 94082815dcSEvan Bacon 95082815dcSEvan Bacon/** 96082815dcSEvan Bacon * Provides the AppDelegate file for modification. 97082815dcSEvan Bacon * 98082815dcSEvan Bacon * @param config 99082815dcSEvan Bacon * @param action 100082815dcSEvan Bacon */ 101082815dcSEvan Baconexport const withAppDelegate: ConfigPlugin<Mod<AppDelegateProjectFile>> = (config, action) => { 102082815dcSEvan Bacon return withMod(config, { 103082815dcSEvan Bacon platform: 'ios', 104082815dcSEvan Bacon mod: 'appDelegate', 105082815dcSEvan Bacon action, 106082815dcSEvan Bacon }); 107082815dcSEvan Bacon}; 108082815dcSEvan Bacon 109082815dcSEvan Bacon/** 110082815dcSEvan Bacon * Provides the Info.plist file for modification. 111082815dcSEvan Bacon * Keeps the config's expo.ios.infoPlist object in sync with the data. 112082815dcSEvan Bacon * 113082815dcSEvan Bacon * @param config 114082815dcSEvan Bacon * @param action 115082815dcSEvan Bacon */ 116082815dcSEvan Baconexport const withInfoPlist: ConfigPlugin<Mod<InfoPlist>> = (config, action) => { 117082815dcSEvan Bacon return withMod<InfoPlist>(config, { 118082815dcSEvan Bacon platform: 'ios', 119082815dcSEvan Bacon mod: 'infoPlist', 120082815dcSEvan Bacon async action(config) { 121082815dcSEvan Bacon config = await action(config); 122082815dcSEvan Bacon if (!config.ios) { 123082815dcSEvan Bacon config.ios = {}; 124082815dcSEvan Bacon } 125082815dcSEvan Bacon config.ios.infoPlist = config.modResults; 126082815dcSEvan Bacon return config; 127082815dcSEvan Bacon }, 128082815dcSEvan Bacon }); 129082815dcSEvan Bacon}; 130082815dcSEvan Bacon 131082815dcSEvan Bacon/** 132082815dcSEvan Bacon * Provides the main .entitlements file for modification. 133082815dcSEvan Bacon * Keeps the config's expo.ios.entitlements object in sync with the data. 134082815dcSEvan Bacon * 135082815dcSEvan Bacon * @param config 136082815dcSEvan Bacon * @param action 137082815dcSEvan Bacon */ 138082815dcSEvan Baconexport const withEntitlementsPlist: ConfigPlugin<Mod<JSONObject>> = (config, action) => { 139082815dcSEvan Bacon return withMod<JSONObject>(config, { 140082815dcSEvan Bacon platform: 'ios', 141082815dcSEvan Bacon mod: 'entitlements', 142082815dcSEvan Bacon async action(config) { 143082815dcSEvan Bacon config = await action(config); 144082815dcSEvan Bacon if (!config.ios) { 145082815dcSEvan Bacon config.ios = {}; 146082815dcSEvan Bacon } 147082815dcSEvan Bacon config.ios.entitlements = config.modResults; 148082815dcSEvan Bacon return config; 149082815dcSEvan Bacon }, 150082815dcSEvan Bacon }); 151082815dcSEvan Bacon}; 152082815dcSEvan Bacon 153082815dcSEvan Bacon/** 154082815dcSEvan Bacon * Provides the Expo.plist for modification. 155082815dcSEvan Bacon * 156082815dcSEvan Bacon * @param config 157082815dcSEvan Bacon * @param action 158082815dcSEvan Bacon */ 159082815dcSEvan Baconexport const withExpoPlist: ConfigPlugin<Mod<ExpoPlist>> = (config, action) => { 160082815dcSEvan Bacon return withMod(config, { 161082815dcSEvan Bacon platform: 'ios', 162082815dcSEvan Bacon mod: 'expoPlist', 163082815dcSEvan Bacon action, 164082815dcSEvan Bacon }); 165082815dcSEvan Bacon}; 166082815dcSEvan Bacon 167082815dcSEvan Bacon/** 168082815dcSEvan Bacon * Provides the main .xcodeproj for modification. 169082815dcSEvan Bacon * 170082815dcSEvan Bacon * @param config 171082815dcSEvan Bacon * @param action 172082815dcSEvan Bacon */ 173082815dcSEvan Baconexport const withXcodeProject: ConfigPlugin<Mod<XcodeProject>> = (config, action) => { 174082815dcSEvan Bacon return withMod(config, { 175082815dcSEvan Bacon platform: 'ios', 176082815dcSEvan Bacon mod: 'xcodeproj', 177082815dcSEvan Bacon action, 178082815dcSEvan Bacon }); 179082815dcSEvan Bacon}; 180082815dcSEvan Bacon 181082815dcSEvan Bacon/** 182082815dcSEvan Bacon * Provides the Podfile.properties.json for modification. 183082815dcSEvan Bacon * 184082815dcSEvan Bacon * @param config 185082815dcSEvan Bacon * @param action 186082815dcSEvan Bacon */ 187082815dcSEvan Baconexport const withPodfileProperties: ConfigPlugin<Mod<Record<string, string>>> = ( 188082815dcSEvan Bacon config, 189082815dcSEvan Bacon action 190082815dcSEvan Bacon) => { 191082815dcSEvan Bacon return withMod(config, { 192082815dcSEvan Bacon platform: 'ios', 193082815dcSEvan Bacon mod: 'podfileProperties', 194082815dcSEvan Bacon action, 195082815dcSEvan Bacon }); 196082815dcSEvan Bacon}; 197