1*8d307f52SEvan Baconimport { getConfig, getProjectConfigDescriptionWithPaths } from '@expo/config'; 2*8d307f52SEvan Bacon 3*8d307f52SEvan Baconimport { CommandError, UnimplementedError } from '../../utils/errors'; 4*8d307f52SEvan Baconimport { get } from '../../utils/obj'; 5*8d307f52SEvan Bacon 6*8d307f52SEvan Bacon/** Resolves a native app identifier (bundle identifier, package name) from the project files. */ 7*8d307f52SEvan Baconexport class AppIdResolver { 8*8d307f52SEvan Bacon constructor( 9*8d307f52SEvan Bacon protected projectRoot: string, 10*8d307f52SEvan Bacon /** Platform to use. */ 11*8d307f52SEvan Bacon protected platform: string, 12*8d307f52SEvan Bacon /** Nested key in the Expo config like `android.package` or `ios.bundleIdentifier`. */ 13*8d307f52SEvan Bacon protected configProperty: string 14*8d307f52SEvan Bacon ) {} 15*8d307f52SEvan Bacon 16*8d307f52SEvan Bacon /** Resolve the application ID for the project. */ 17*8d307f52SEvan Bacon async getAppIdAsync(): Promise<string> { 18*8d307f52SEvan Bacon if (await this.hasNativeProjectAsync()) { 19*8d307f52SEvan Bacon return this.getAppIdFromNativeAsync(); 20*8d307f52SEvan Bacon } 21*8d307f52SEvan Bacon return this.getAppIdFromConfigAsync(); 22*8d307f52SEvan Bacon } 23*8d307f52SEvan Bacon 24*8d307f52SEvan Bacon /** Returns `true` if the project has native project code. */ 25*8d307f52SEvan Bacon async hasNativeProjectAsync(): Promise<boolean> { 26*8d307f52SEvan Bacon throw new UnimplementedError(); 27*8d307f52SEvan Bacon } 28*8d307f52SEvan Bacon 29*8d307f52SEvan Bacon /** Return the app ID from the Expo config or assert. */ 30*8d307f52SEvan Bacon async getAppIdFromConfigAsync(): Promise<string> { 31*8d307f52SEvan Bacon const config = getConfig(this.projectRoot); 32*8d307f52SEvan Bacon 33*8d307f52SEvan Bacon const appId = get(config.exp, this.configProperty); 34*8d307f52SEvan Bacon if (!appId) { 35*8d307f52SEvan Bacon throw new CommandError( 36*8d307f52SEvan Bacon 'NO_APP_ID', 37*8d307f52SEvan Bacon `Required property '${ 38*8d307f52SEvan Bacon this.configProperty 39*8d307f52SEvan Bacon }' is not found in the project ${getProjectConfigDescriptionWithPaths( 40*8d307f52SEvan Bacon this.projectRoot, 41*8d307f52SEvan Bacon config 42*8d307f52SEvan Bacon )}. This is required to open the app.` 43*8d307f52SEvan Bacon ); 44*8d307f52SEvan Bacon } 45*8d307f52SEvan Bacon return appId; 46*8d307f52SEvan Bacon } 47*8d307f52SEvan Bacon 48*8d307f52SEvan Bacon /** Return the app ID from the native project files or null if the app ID cannot be found. */ 49*8d307f52SEvan Bacon async resolveAppIdFromNativeAsync(): Promise<string | null> { 50*8d307f52SEvan Bacon throw new UnimplementedError(); 51*8d307f52SEvan Bacon } 52*8d307f52SEvan Bacon 53*8d307f52SEvan Bacon /** Return the app ID from the native project files or assert. */ 54*8d307f52SEvan Bacon async getAppIdFromNativeAsync(): Promise<string> { 55*8d307f52SEvan Bacon const appId = await this.resolveAppIdFromNativeAsync(); 56*8d307f52SEvan Bacon if (!appId) { 57*8d307f52SEvan Bacon throw new CommandError( 58*8d307f52SEvan Bacon 'NO_APP_ID', 59*8d307f52SEvan Bacon `Failed to locate the ${this.platform} application identifier in the "${this.platform}/" folder. This is required to open the app.` 60*8d307f52SEvan Bacon ); 61*8d307f52SEvan Bacon } 62*8d307f52SEvan Bacon return appId; 63*8d307f52SEvan Bacon } 64*8d307f52SEvan Bacon} 65