xref: /expo/packages/@expo/cli/src/run/ios/launchApp.ts (revision 8a424beb)
1c4ef02aeSEvan Baconimport chalk from 'chalk';
2c4ef02aeSEvan Baconimport path from 'path';
3c4ef02aeSEvan Bacon
4*8a424bebSJames Ideimport * as XcodeBuild from './XcodeBuild';
5*8a424bebSJames Ideimport { BuildProps } from './XcodeBuild.types';
6*8a424bebSJames Ideimport { getAppDeltaDirectory, installOnDeviceAsync } from './appleDevice/installOnDeviceAsync';
7c4ef02aeSEvan Baconimport { AppleDeviceManager } from '../../start/platforms/ios/AppleDeviceManager';
8c4ef02aeSEvan Baconimport { SimulatorLogStreamer } from '../../start/platforms/ios/simctlLogging';
9c4ef02aeSEvan Baconimport { DevServerManager } from '../../start/server/DevServerManager';
10c4ef02aeSEvan Baconimport { parsePlistAsync } from '../../utils/plist';
11c4ef02aeSEvan Baconimport { profile } from '../../utils/profile';
12c4ef02aeSEvan Bacon
13c4ef02aeSEvan Bacon/** Install and launch the app binary on a device. */
14c4ef02aeSEvan Baconexport async function launchAppAsync(
15c4ef02aeSEvan Bacon  binaryPath: string,
16c4ef02aeSEvan Bacon  manager: DevServerManager,
17c4ef02aeSEvan Bacon  props: Pick<BuildProps, 'isSimulator' | 'device' | 'shouldStartBundler'>
18c4ef02aeSEvan Bacon) {
19c4ef02aeSEvan Bacon  const appId = await profile(getBundleIdentifierForBinaryAsync)(binaryPath);
20c4ef02aeSEvan Bacon
21c4ef02aeSEvan Bacon  if (!props.isSimulator) {
22c4ef02aeSEvan Bacon    await profile(installOnDeviceAsync)({
23c4ef02aeSEvan Bacon      bundleIdentifier: appId,
24c4ef02aeSEvan Bacon      bundle: binaryPath,
25c4ef02aeSEvan Bacon      appDeltaDirectory: getAppDeltaDirectory(appId),
26c4ef02aeSEvan Bacon      udid: props.device.udid,
27c4ef02aeSEvan Bacon      deviceName: props.device.name,
28c4ef02aeSEvan Bacon    });
29c4ef02aeSEvan Bacon    return;
30c4ef02aeSEvan Bacon  }
31c4ef02aeSEvan Bacon
32c4ef02aeSEvan Bacon  XcodeBuild.logPrettyItem(chalk`{bold Installing} on ${props.device.name}`);
33c4ef02aeSEvan Bacon
34c4ef02aeSEvan Bacon  const device = await AppleDeviceManager.resolveAsync({ device: props.device });
35c4ef02aeSEvan Bacon  await device.installAppAsync(binaryPath);
36c4ef02aeSEvan Bacon
37c4ef02aeSEvan Bacon  XcodeBuild.logPrettyItem(chalk`{bold Opening} on ${device.name} {dim (${appId})}`);
38c4ef02aeSEvan Bacon
39c4ef02aeSEvan Bacon  if (props.shouldStartBundler) {
40c4ef02aeSEvan Bacon    await SimulatorLogStreamer.getStreamer(device.device, {
41c4ef02aeSEvan Bacon      appId,
42c4ef02aeSEvan Bacon    }).attachAsync();
43c4ef02aeSEvan Bacon  }
44c4ef02aeSEvan Bacon
45c4ef02aeSEvan Bacon  await manager.getDefaultDevServer().openCustomRuntimeAsync(
46c4ef02aeSEvan Bacon    'simulator',
47c4ef02aeSEvan Bacon    {
48c4ef02aeSEvan Bacon      applicationId: appId,
49c4ef02aeSEvan Bacon    },
50c4ef02aeSEvan Bacon    { device }
51c4ef02aeSEvan Bacon  );
52c4ef02aeSEvan Bacon}
53c4ef02aeSEvan Bacon
54c4ef02aeSEvan Baconasync function getBundleIdentifierForBinaryAsync(binaryPath: string): Promise<string> {
55c4ef02aeSEvan Bacon  const builtInfoPlistPath = path.join(binaryPath, 'Info.plist');
56c4ef02aeSEvan Bacon  const { CFBundleIdentifier } = await parsePlistAsync(builtInfoPlistPath);
57c4ef02aeSEvan Bacon  return CFBundleIdentifier;
58c4ef02aeSEvan Bacon}
59