1082815dcSEvan Baconimport type { ExpoConfig } from '@expo/config-types'; 2082815dcSEvan Bacon 3*8a424bebSJames Ideimport type { PropertiesItem } from './Properties'; 4082815dcSEvan Baconimport type { ConfigPlugin } from '../Plugin.types'; 5082815dcSEvan Baconimport { withGradleProperties } from '../plugins/android-plugins'; 6082815dcSEvan Baconimport { BuildPropertiesConfig, ConfigToPropertyRuleType } from '../utils/BuildProperties.types'; 7082815dcSEvan Bacon 8082815dcSEvan Bacon/** 9082815dcSEvan Bacon * Creates a `withGradleProperties` config-plugin based on given config to property mapping rules. 10082815dcSEvan Bacon * 11082815dcSEvan Bacon * The factory supports two modes from generic type inference 12082815dcSEvan Bacon * ```ts 13082815dcSEvan Bacon * // config-plugin without `props`, it will implicitly use the expo config as source config. 14082815dcSEvan Bacon * createBuildGradlePropsConfigPlugin<ExpoConfig>(): ConfigPlugin<void>; 15082815dcSEvan Bacon * 16082815dcSEvan Bacon * // config-plugin with a parameter `props: CustomType`, it will use the `props` as source config. 17082815dcSEvan Bacon * createBuildGradlePropsConfigPlugin<CustomType>(): ConfigPlugin<CustomType>; 18082815dcSEvan Bacon * ``` 19082815dcSEvan Bacon * 20082815dcSEvan Bacon * @param configToPropertyRules config to property mapping rules 21082815dcSEvan Bacon * @param name the config plugin name 22082815dcSEvan Bacon */ 23082815dcSEvan Baconexport function createBuildGradlePropsConfigPlugin<SourceConfigType extends BuildPropertiesConfig>( 24082815dcSEvan Bacon configToPropertyRules: ConfigToPropertyRuleType<SourceConfigType>[], 25082815dcSEvan Bacon name?: string 26082815dcSEvan Bacon) { 27082815dcSEvan Bacon const withUnknown: ConfigPlugin<SourceConfigType extends ExpoConfig ? void : SourceConfigType> = ( 28082815dcSEvan Bacon config, 29082815dcSEvan Bacon sourceConfig 30082815dcSEvan Bacon ) => 31082815dcSEvan Bacon withGradleProperties(config, (config) => { 32082815dcSEvan Bacon config.modResults = updateAndroidBuildPropertiesFromConfig( 33082815dcSEvan Bacon (sourceConfig ?? config) as SourceConfigType, 34082815dcSEvan Bacon config.modResults, 35082815dcSEvan Bacon configToPropertyRules 36082815dcSEvan Bacon ); 37082815dcSEvan Bacon return config; 38082815dcSEvan Bacon }); 39082815dcSEvan Bacon if (name) { 40082815dcSEvan Bacon Object.defineProperty(withUnknown, 'name', { 41082815dcSEvan Bacon value: name, 42082815dcSEvan Bacon }); 43082815dcSEvan Bacon } 44082815dcSEvan Bacon return withUnknown; 45082815dcSEvan Bacon} 46082815dcSEvan Bacon 47082815dcSEvan Bacon/** 48082815dcSEvan Bacon * A config-plugin to update `android/gradle.properties` from the `jsEngine` in expo config 49082815dcSEvan Bacon */ 50082815dcSEvan Baconexport const withJsEngineGradleProps = createBuildGradlePropsConfigPlugin<ExpoConfig>( 51082815dcSEvan Bacon [ 52082815dcSEvan Bacon { 530e8f799bSKudo Chien propName: 'hermesEnabled', 540e8f799bSKudo Chien propValueGetter: (config) => 550e8f799bSKudo Chien ((config.android?.jsEngine ?? config.jsEngine ?? 'hermes') === 'hermes').toString(), 56082815dcSEvan Bacon }, 57082815dcSEvan Bacon ], 58082815dcSEvan Bacon 'withJsEngineGradleProps' 59082815dcSEvan Bacon); 60082815dcSEvan Bacon 61082815dcSEvan Baconexport function updateAndroidBuildPropertiesFromConfig< 62*8a424bebSJames Ide SourceConfigType extends BuildPropertiesConfig, 63082815dcSEvan Bacon>( 64082815dcSEvan Bacon config: SourceConfigType, 65082815dcSEvan Bacon gradleProperties: PropertiesItem[], 66082815dcSEvan Bacon configToPropertyRules: ConfigToPropertyRuleType<SourceConfigType>[] 67082815dcSEvan Bacon) { 68082815dcSEvan Bacon for (const configToProperty of configToPropertyRules) { 69082815dcSEvan Bacon const value = configToProperty.propValueGetter(config); 70082815dcSEvan Bacon updateAndroidBuildProperty(gradleProperties, configToProperty.propName, value); 71082815dcSEvan Bacon } 72082815dcSEvan Bacon 73082815dcSEvan Bacon return gradleProperties; 74082815dcSEvan Bacon} 75082815dcSEvan Bacon 76082815dcSEvan Baconexport function updateAndroidBuildProperty( 77082815dcSEvan Bacon gradleProperties: PropertiesItem[], 78082815dcSEvan Bacon name: string, 79082815dcSEvan Bacon value: string | null | undefined, 80082815dcSEvan Bacon options?: { removePropWhenValueIsNull?: boolean } 81082815dcSEvan Bacon) { 82082815dcSEvan Bacon const oldPropIndex = gradleProperties.findIndex( 83082815dcSEvan Bacon (prop) => prop.type === 'property' && prop.key === name 84082815dcSEvan Bacon ); 85082815dcSEvan Bacon 86082815dcSEvan Bacon if (value) { 87082815dcSEvan Bacon // found the matched value, add or merge new property 88082815dcSEvan Bacon const newProp: PropertiesItem = { 89082815dcSEvan Bacon type: 'property', 90082815dcSEvan Bacon key: name, 91082815dcSEvan Bacon value, 92082815dcSEvan Bacon }; 93082815dcSEvan Bacon 94082815dcSEvan Bacon if (oldPropIndex >= 0) { 95082815dcSEvan Bacon gradleProperties[oldPropIndex] = newProp; 96082815dcSEvan Bacon } else { 97082815dcSEvan Bacon gradleProperties.push(newProp); 98082815dcSEvan Bacon } 99082815dcSEvan Bacon } else if (options?.removePropWhenValueIsNull && oldPropIndex >= 0) { 100082815dcSEvan Bacon gradleProperties.splice(oldPropIndex, 1); 101082815dcSEvan Bacon } 102082815dcSEvan Bacon 103082815dcSEvan Bacon return gradleProperties; 104082815dcSEvan Bacon} 105