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 /** @return `true` if the app has valid `*.pbxproj` file */ 16 async hasNativeProjectAsync(): Promise<boolean> { 17 try { 18 // Never returns nullish values. 19 return !!IOSConfig.Paths.getAllPBXProjectPaths(this.projectRoot).length; 20 } catch (error: any) { 21 debug('Expected error checking for native project:', error); 22 return false; 23 } 24 } 25 26 async resolveAppIdFromNativeAsync(): Promise<string | null> { 27 // Check xcode project 28 try { 29 const bundleId = IOSConfig.BundleIdentifier.getBundleIdentifierFromPbxproj(this.projectRoot); 30 if (bundleId) { 31 return bundleId; 32 } 33 } catch (error: any) { 34 debug('Expected error resolving the bundle identifier from the pbxproj:', error); 35 } 36 37 // Check Info.plist 38 try { 39 const infoPlistPath = IOSConfig.Paths.getInfoPlistPath(this.projectRoot); 40 const data = await plist.parse(fs.readFileSync(infoPlistPath, 'utf8')); 41 if (data.CFBundleIdentifier && !data.CFBundleIdentifier.startsWith('$(')) { 42 return data.CFBundleIdentifier; 43 } 44 } catch (error) { 45 debug('Expected error resolving the bundle identifier from the project Info.plist:', error); 46 } 47 48 return null; 49 } 50} 51