1import { IOSConfig } from '@expo/config-plugins'; 2import plist from '@expo/plist'; 3import fs from 'fs'; 4 5import { AppIdResolver } from '../AppIdResolver'; 6 7const debug = require('debug')('expo:start:platforms:ios:AppleAppIdResolver') as typeof console.log; 8 9/** Resolves the iOS bundle identifier from the Expo config or native files. */ 10export class AppleAppIdResolver extends AppIdResolver { 11 constructor(projectRoot: string) { 12 super(projectRoot, 'ios', 'ios.bundleIdentifier'); 13 } 14 15 async hasNativeProjectAsync(): Promise<boolean> { 16 try { 17 // Never returns nullish values. 18 return !!IOSConfig.Paths.getAppDelegateFilePath(this.projectRoot); 19 } catch (error: any) { 20 debug('Expected error checking for native project:', error); 21 return false; 22 } 23 } 24 25 async resolveAppIdFromNativeAsync(): Promise<string | null> { 26 // Check xcode project 27 try { 28 const bundleId = IOSConfig.BundleIdentifier.getBundleIdentifierFromPbxproj(this.projectRoot); 29 if (bundleId) { 30 return bundleId; 31 } 32 } catch (error: any) { 33 debug('Expected error resolving the bundle identifier from the pbxproj:', error); 34 } 35 36 // Check Info.plist 37 try { 38 const infoPlistPath = IOSConfig.Paths.getInfoPlistPath(this.projectRoot); 39 const data = await plist.parse(fs.readFileSync(infoPlistPath, 'utf8')); 40 if (data.CFBundleIdentifier && !data.CFBundleIdentifier.startsWith('$(')) { 41 return data.CFBundleIdentifier; 42 } 43 } catch (error) { 44 debug('Expected error resolving the bundle identifier from the project Info.plist:', error); 45 } 46 47 return null; 48 } 49} 50