import Debug from 'debug' ; import path from 'path' ; import { ExportedConfig , Mod , ModConfig , ModPlatform } from '../Plugin.types' ; import { getHackyProjectName } from '../ios/utils/Xcodeproj' ; import { PluginError } from '../utils/errors' ; import * as Warnings from '../utils/warnings' ; import { assertModResults , ForwardedBaseModOptions } from './createBaseMod' ; import { withAndroidBaseMods } from './withAndroidBaseMods' ; import { withIosBaseMods } from './withIosBaseMods' ; const debug = Debug ( 'expo:config-plugins:mod-compiler' ) ; export function withDefaultBaseMods ( config , props = { } ) { config = withIosBaseMods ( config , props ) ; config = withAndroidBaseMods ( config , props ) ; return config ; } /**
 * Get a prebuild config that safely evaluates mods without persisting any changes to the file system.
 * Currently this only supports infoPlist, entitlements, androidManifest, strings, gradleProperties, and expoPlist mods.
 * This plugin should be evaluated directly:
 */ export function withIntrospectionBaseMods ( config , props = { } ) { config = withIosBaseMods ( config , { saveToInternal : true , skipEmptyMod : false , ... props } ) ; config = withAndroidBaseMods ( config , { saveToInternal : true , skipEmptyMod : false , ... props } ) ; if ( config . mods ) { for ( const platform of Object . keys ( config . mods ) as ModPlatform [ ] ) { for ( const key of Object . keys ( config . mods [ platform ] || { } ) ) { if ( ! config . mods [ platform ] ?. [ key ] ?. isIntrospective ) { debug ( `removing non-idempotent mod: ${ platform }.${ key }` ) ; delete config . mods [ platform ] ?. [ key ] ; } } } } return config ; } param projectRoot param config export async function compileModsAsync ( config , props ) { if ( props . introspect === true ) { config = withIntrospectionBaseMods ( config ) ; } else { config = withDefaultBaseMods ( config ) ; } return await evalModsAsync ( config , props ) ; } function sortMods ( commands , order ) { const allKeys = commands . map ( ( [ key ] ) => key ) ; const completeOrder = [ ... new Set ( [ ... order , ... allKeys ] ) ] ; const sorted = [ ] ; while ( completeOrder . length ) { const group = completeOrder . shift ( ) ! ; const commandSet = commands . find ( ( [ key ] ) => key === group ) ; if ( commandSet ) { sorted . push ( commandSet ) ; } } return sorted ; } const orders = { ios : [ 'dangerous' , 'xcodeproj' , ] , android : [ 'dangerous' ] } ; param config export async function evalModsAsync ( config , { projectRoot , introspect , platforms , assertMissingModProviders , } ) { for ( const [ platformName , platform ] of Object . entries ( config . mods ?? ( { } as ModConfig ) ) ) { if ( platforms && ! platforms . includes ( platformName as any ) ) { debug ( `skip platform: ${ platformName }` ) ; continue ; } let entries = Object . entries ( platform ) ; if ( entries . length ) { entries = sortMods ( entries , orders [ platformName ] ! ) ; debug ( `run in order: ${ entries . map ( ( [ name ] ) => name ) . join ( ', ' ) }` ) ; const platformProjectRoot = path . join ( projectRoot , platformName ) ; const projectName = platformName === 'ios' ? getHackyProjectName ( projectRoot , config ) : undefined ; for ( const [ modName , mod ] of entries ) { const modRequest = { projectRoot , projectName , platformProjectRoot , platform : platformName as ModPlatform , modName , introspect : ! ! introspect } ; if ( ! ( mod as Mod ) . isProvider ) { const errorMessage = `Initial base modifier for "${ platformName }.${ modName }" is not a provider and therefore will not provide modResults to child mods` ; if ( assertMissingModProviders !== false ) { throw new PluginError ( errorMessage , 'MISSING_PROVIDER' ) ; } else { Warnings . addWarningForPlatform ( platformName as ModPlatform , `${ platformName }.${ modName }` , `Skipping: Initial base modifier for "${ platformName }.${ modName }" is not a provider and therefore will not provide modResults to child mods. This may be due to an outdated version of Expo CLI.` ) ; continue ; } } const results = await ( mod as Mod ) ( { ... config , modResults : null , modRequest } ) ; config = assertModResults ( results , platformName , modName ) ; delete config . modResults ; delete config . modRequest ; } } } return config ; }