import { IOSConfig } from '@expo/config-plugins'; import plist from '@expo/plist'; import fs from 'fs'; import { AppIdResolver } from '../AppIdResolver'; const debug = require('debug')('expo:start:platforms:ios:AppleAppIdResolver') as typeof console.log; /** Resolves the iOS bundle identifier from the Expo config or native files. */ export class AppleAppIdResolver extends AppIdResolver { constructor(projectRoot: string) { super(projectRoot, 'ios', 'ios.bundleIdentifier'); } /** @return `true` if the app has valid `*.pbxproj` file */ async hasNativeProjectAsync(): Promise { try { // Never returns nullish values. return !!IOSConfig.Paths.getAllPBXProjectPaths(this.projectRoot).length; } catch (error: any) { debug('Expected error checking for native project:', error); return false; } } async resolveAppIdFromNativeAsync(): Promise { // Check xcode project try { const bundleId = IOSConfig.BundleIdentifier.getBundleIdentifierFromPbxproj(this.projectRoot); if (bundleId) { return bundleId; } } catch (error: any) { debug('Expected error resolving the bundle identifier from the pbxproj:', error); } // Check Info.plist try { const infoPlistPath = IOSConfig.Paths.getInfoPlistPath(this.projectRoot); const data = await plist.parse(fs.readFileSync(infoPlistPath, 'utf8')); if (data.CFBundleIdentifier && !data.CFBundleIdentifier.startsWith('$(')) { return data.CFBundleIdentifier; } } catch (error) { debug('Expected error resolving the bundle identifier from the project Info.plist:', error); } return null; } }