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