1/** 2 * These are the versioned first-party plugins with some of the future third-party plugins mixed in for legacy support. 3 */ 4import { 5 AndroidConfig, 6 ConfigPlugin, 7 IOSConfig, 8 StaticPlugin, 9 withPlugins, 10 withStaticPlugin, 11} from '@expo/config-plugins'; 12import { ExpoConfig } from '@expo/config-types'; 13import Debug from 'debug'; 14 15import { shouldSkipAutoPlugin } from '../getAutolinkedPackages'; 16import { withAndroidIcons } from './icons/withAndroidIcons'; 17import { withIosIcons } from './icons/withIosIcons'; 18import withAdMob from './unversioned/expo-ads-admob/expo-ads-admob'; 19import withAppleAuthentication from './unversioned/expo-apple-authentication'; 20import withBranch from './unversioned/expo-branch/expo-branch'; 21import withContacts from './unversioned/expo-contacts'; 22import withDocumentPicker from './unversioned/expo-document-picker'; 23import withFacebook from './unversioned/expo-facebook/expo-facebook'; 24import withNavigationBar from './unversioned/expo-navigation-bar/expo-navigation-bar'; 25import withNotifications from './unversioned/expo-notifications/expo-notifications'; 26import withSplashScreen from './unversioned/expo-splash-screen/expo-splash-screen'; 27import withSystemUI from './unversioned/expo-system-ui/expo-system-ui'; 28import withUpdates from './unversioned/expo-updates'; 29import withMaps from './unversioned/react-native-maps'; 30 31const debug = Debug('expo:prebuild-config'); 32 33/** 34 * Config plugin to apply all of the custom Expo iOS config plugins we support by default. 35 * TODO: In the future most of this should go into versioned packages like expo-facebook, expo-updates, etc... 36 */ 37export const withIosExpoPlugins: ConfigPlugin<{ 38 bundleIdentifier: string; 39}> = (config, { bundleIdentifier }) => { 40 // Set the bundle ID ahead of time. 41 if (!config.ios) config.ios = {}; 42 config.ios.bundleIdentifier = bundleIdentifier; 43 44 return withPlugins(config, [ 45 [IOSConfig.BundleIdentifier.withBundleIdentifier, { bundleIdentifier }], 46 IOSConfig.Swift.withSwiftBridgingHeader, 47 IOSConfig.Swift.withNoopSwiftFile, 48 IOSConfig.Google.withGoogle, 49 IOSConfig.Name.withDisplayName, 50 IOSConfig.Name.withProductName, 51 IOSConfig.Orientation.withOrientation, 52 IOSConfig.RequiresFullScreen.withRequiresFullScreen, 53 IOSConfig.Scheme.withScheme, 54 IOSConfig.UsesNonExemptEncryption.withUsesNonExemptEncryption, 55 IOSConfig.Version.withBuildNumber, 56 IOSConfig.Version.withVersion, 57 IOSConfig.Google.withGoogleServicesFile, 58 IOSConfig.BuildProperties.withJsEnginePodfileProps, 59 // Entitlements 60 IOSConfig.Entitlements.withAssociatedDomains, 61 // XcodeProject 62 IOSConfig.DeviceFamily.withDeviceFamily, 63 IOSConfig.Bitcode.withBitcode, 64 IOSConfig.Locales.withLocales, 65 // Dangerous 66 withIosIcons, 67 ]); 68}; 69 70/** 71 * Config plugin to apply all of the custom Expo Android config plugins we support by default. 72 * TODO: In the future most of this should go into versioned packages like expo-facebook, expo-updates, etc... 73 */ 74export const withAndroidExpoPlugins: ConfigPlugin<{ 75 package: string; 76}> = (config, props) => { 77 // Set the package name ahead of time. 78 if (!config.android) config.android = {}; 79 config.android.package = props.package; 80 81 return withPlugins(config, [ 82 // gradle.properties 83 AndroidConfig.BuildProperties.withJsEngineGradleProps, 84 85 // settings.gradle 86 AndroidConfig.Name.withNameSettingsGradle, 87 88 // project build.gradle 89 AndroidConfig.GoogleServices.withClassPath, 90 91 // app/build.gradle 92 AndroidConfig.GoogleServices.withApplyPlugin, 93 AndroidConfig.Package.withPackageGradle, 94 AndroidConfig.Version.withVersion, 95 96 // AndroidManifest.xml 97 AndroidConfig.Package.withPackageManifest, 98 AndroidConfig.AllowBackup.withAllowBackup, 99 AndroidConfig.WindowSoftInputMode.withWindowSoftInputMode, 100 // Note: The withAndroidIntentFilters plugin must appear before the withScheme 101 // plugin or withScheme will override the output of withAndroidIntentFilters. 102 AndroidConfig.IntentFilters.withAndroidIntentFilters, 103 AndroidConfig.Scheme.withScheme, 104 AndroidConfig.Orientation.withOrientation, 105 AndroidConfig.Permissions.withInternalBlockedPermissions, 106 AndroidConfig.Permissions.withPermissions, 107 108 // strings.xml 109 AndroidConfig.Name.withName, 110 111 // Dangerous -- these plugins run in reverse order. 112 AndroidConfig.GoogleServices.withGoogleServicesFile, 113 114 // Modify colors.xml and styles.xml 115 AndroidConfig.StatusBar.withStatusBar, 116 AndroidConfig.PrimaryColor.withPrimaryColor, 117 118 withAndroidIcons, 119 // If we renamed the package, we should also move it around and rename it in source files 120 // Added last to ensure this plugin runs first. Out of tree solutions will mistakenly resolve the package incorrectly otherwise. 121 AndroidConfig.Package.withPackageRefactor, 122 ]); 123}; 124 125// Must keep in sync with `withVersionedExpoSDKPlugins` 126const versionedExpoSDKPackages: string[] = [ 127 'react-native-maps', 128 'expo-ads-admob', 129 'expo-apple-authentication', 130 'expo-contacts', 131 'expo-notifications', 132 'expo-updates', 133 'expo-branch', 134 'expo-navigation-bar', 135 'expo-document-picker', 136 'expo-facebook', 137 'expo-splash-screen', 138 'expo-system-ui', 139]; 140 141export const withVersionedExpoSDKPlugins: ConfigPlugin<{ expoUsername: string | null }> = ( 142 config, 143 { expoUsername } 144) => { 145 return withPlugins(config, [ 146 withMaps, 147 withAdMob, 148 withAppleAuthentication, 149 withContacts, 150 withNotifications, 151 [withUpdates, { expoUsername }], 152 withBranch, 153 withDocumentPicker, 154 withFacebook, 155 // System UI must come before splash screen as they overlap 156 // and splash screen will warn about conflicting rules. 157 withSystemUI, 158 withSplashScreen, 159 withNavigationBar, 160 ]); 161}; 162 163export function getAutoPlugins() { 164 return versionedExpoSDKPackages.concat(legacyExpoPlugins).concat(expoManagedVersionedPlugins); 165} 166 167export function getLegacyExpoPlugins() { 168 return legacyExpoPlugins; 169} 170 171// Expo managed packages that require extra update. 172// These get applied automatically to create parity with expo build in eas build. 173const legacyExpoPlugins = [ 174 'expo-app-auth', 175 'expo-av', 176 'expo-background-fetch', 177 'expo-barcode-scanner', 178 'expo-brightness', 179 'expo-calendar', 180 'expo-camera', 181 'expo-cellular', 182 'expo-dev-menu', 183 'expo-dev-launcher', 184 'expo-dev-client', 185 'expo-image-picker', 186 'expo-file-system', 187 'expo-ads-facebook', 188 'expo-location', 189 'expo-media-library', 190 'expo-screen-orientation', 191 'expo-sensors', 192 'expo-task-manager', 193 'expo-local-authentication', 194]; 195 196// Plugins that need to be automatically applied, but also get applied by expo-cli if the versioned plugin isn't available. 197// These are split up because the user doesn't need to be prompted to setup these packages. 198const expoManagedVersionedPlugins = [ 199 'expo-firebase-analytics', 200 'expo-firebase-core', 201 'expo-google-sign-in', 202]; 203 204const withOptionalLegacyPlugins: ConfigPlugin<(StaticPlugin | string)[]> = (config, plugins) => { 205 return plugins.reduce((prev, plugin) => { 206 if (shouldSkipAutoPlugin(config, plugin)) { 207 debug('Skipping unlinked auto plugin:', plugin); 208 return prev; 209 } 210 211 return withStaticPlugin(prev, { 212 // hide errors 213 _isLegacyPlugin: true, 214 plugin, 215 // If a plugin doesn't exist, do nothing. 216 fallback: (config) => config, 217 }); 218 }, config); 219}; 220 221export function withLegacyExpoPlugins(config: ExpoConfig) { 222 return withOptionalLegacyPlugins(config, [ 223 ...new Set(expoManagedVersionedPlugins.concat(legacyExpoPlugins)), 224 ]); 225} 226