1import { ExpoConfig, getConfig, PackageJSONConfig } from '@expo/config'; 2import { ModPlatform } from '@expo/config-plugins'; 3import JsonFile, { JSONObject } from '@expo/json-file'; 4import path from 'path'; 5 6import * as Log from '../log'; 7import { CommandError } from '../utils/errors'; 8import { 9 getOrPromptForBundleIdentifier, 10 getOrPromptForPackage, 11} from '../utils/getOrPromptApplicationId'; 12 13/** 14 * If an Expo config file does not exist, write a new one using the in-memory config. 15 * 16 * @param projectRoot 17 */ 18export async function ensureConfigExistsAsync(projectRoot: string) { 19 try { 20 const config = getConfig(projectRoot, { skipSDKVersionRequirement: false }); 21 // If no config exists in the file system then we should generate one so the process doesn't fail. 22 if (!config.dynamicConfigPath && !config.staticConfigPath) { 23 // Remove the internal object before writing. 24 delete config.exp._internal; 25 26 // Write the generated config. 27 await JsonFile.writeAsync( 28 path.join(projectRoot, 'app.json'), 29 { expo: config.exp as unknown as JSONObject }, 30 { json5: false } 31 ); 32 } 33 } catch (error: any) { 34 // TODO(Bacon): Currently this is already handled in the command 35 Log.log(); 36 throw new CommandError(`${error.message}\n`); 37 } 38} 39 40/** Ensure config is written, prompts for application identifiers, and removes entryPoint value. */ 41export async function ensureConfigAsync( 42 projectRoot: string, 43 { 44 platforms, 45 }: { 46 platforms: ModPlatform[]; 47 } 48): Promise<{ exp: ExpoConfig; pkg: PackageJSONConfig }> { 49 await ensureConfigExistsAsync(projectRoot); 50 51 // Prompt for the Android package first because it's more strict than the bundle identifier 52 // this means you'll have a better chance at matching the bundle identifier with the package name. 53 if (platforms.includes('android')) { 54 await getOrPromptForPackage(projectRoot); 55 } 56 57 if (platforms.includes('ios')) { 58 await getOrPromptForBundleIdentifier(projectRoot); 59 } 60 61 // We need the SDK version to proceed 62 const { exp, pkg } = getConfig(projectRoot); 63 64 // TODO(EvanBacon): Remove the requirement for this once we have a 65 // custom bundle script that respects Expo entry point resolution. 66 if (exp.entryPoint) { 67 delete exp.entryPoint; 68 Log.log(`\u203A expo.entryPoint is not needed and has been removed.`); 69 } 70 71 // Read config again because prompting for bundle id or package name may have mutated the results. 72 return { exp, pkg }; 73} 74