@expo/cli 0.2.8 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/bin/cli CHANGED
@@ -121,7 +121,7 @@ const args = (0, _arg).default({
121
121
  });
122
122
  if (args["--version"]) {
123
123
  // Version is added in the build script.
124
- console.log("0.2.8");
124
+ console.log("0.2.9");
125
125
  process.exit(0);
126
126
  }
127
127
  if (args["--non-interactive"]) {
@@ -248,7 +248,7 @@ commands[command]().then((exec)=>{
248
248
  logEventAsync("action", {
249
249
  action: `expo ${command}`,
250
250
  source: "expo/cli",
251
- source_version: "0.2.8"
251
+ source_version: "0.2.9"
252
252
  });
253
253
  });
254
254
 
@@ -6,8 +6,11 @@ exports.ensureSimulatorOpenAsync = ensureSimulatorOpenAsync;
6
6
  var osascript = _interopRequireWildcard(require("@expo/osascript"));
7
7
  var _assert = _interopRequireDefault(require("assert"));
8
8
  var _chalk = _interopRequireDefault(require("chalk"));
9
+ var _fs = _interopRequireDefault(require("fs"));
10
+ var _path = _interopRequireDefault(require("path"));
9
11
  var _delay = require("../../../utils/delay");
10
12
  var _errors = require("../../../utils/errors");
13
+ var _plist = require("../../../utils/plist");
11
14
  var _url = require("../../../utils/url");
12
15
  var _deviceManager = require("../DeviceManager");
13
16
  var _expoGoInstaller = require("../ExpoGoInstaller");
@@ -42,6 +45,7 @@ function _interopRequireWildcard(obj) {
42
45
  return newObj;
43
46
  }
44
47
  }
48
+ const debug = require("debug")("expo:start:platforms:ios:AppleDeviceManager");
45
49
  const EXPO_GO_BUNDLE_IDENTIFIER = "host.exp.Exponent";
46
50
  async function ensureSimulatorOpenAsync({ udid , osType } = {}, tryAgain = true) {
47
51
  // Use a default simulator if none was specified
@@ -146,7 +150,14 @@ class AppleDeviceManager extends _deviceManager.DeviceManager {
146
150
  await this.waitForAppInstalledAsync(await this.getApplicationIdFromBundle(filePath));
147
151
  }
148
152
  async getApplicationIdFromBundle(filePath) {
149
- // TODO: Implement...
153
+ debug("getApplicationIdFromBundle:", filePath);
154
+ const builtInfoPlistPath = _path.default.join(filePath, "Info.plist");
155
+ if (_fs.default.existsSync(builtInfoPlistPath)) {
156
+ const { CFBundleIdentifier } = await (0, _plist).parsePlistAsync(builtInfoPlistPath);
157
+ debug("getApplicationIdFromBundle: using built Info.plist", CFBundleIdentifier);
158
+ return CFBundleIdentifier;
159
+ }
160
+ debug("getApplicationIdFromBundle: no Info.plist found");
150
161
  return EXPO_GO_BUNDLE_IDENTIFIER;
151
162
  }
152
163
  async waitForAppInstalledAsync(applicationId) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/start/platforms/ios/AppleDeviceManager.ts"],"sourcesContent":["import * as osascript from '@expo/osascript';\nimport assert from 'assert';\nimport chalk from 'chalk';\n\nimport { delayAsync, waitForActionAsync } from '../../../utils/delay';\nimport { CommandError } from '../../../utils/errors';\nimport { validateUrl } from '../../../utils/url';\nimport { DeviceManager } from '../DeviceManager';\nimport { ExpoGoInstaller } from '../ExpoGoInstaller';\nimport { BaseResolveDeviceProps } from '../PlatformManager';\nimport { assertSystemRequirementsAsync } from './assertSystemRequirements';\nimport { ensureSimulatorAppRunningAsync } from './ensureSimulatorAppRunning';\nimport {\n getBestBootedSimulatorAsync,\n getBestUnbootedSimulatorAsync,\n getSelectableSimulatorsAsync,\n} from './getBestSimulator';\nimport { promptAppleDeviceAsync } from './promptAppleDevice';\nimport * as SimControl from './simctl';\n\nconst EXPO_GO_BUNDLE_IDENTIFIER = 'host.exp.Exponent';\n\n/**\n * Ensure a simulator is booted and the Simulator app is opened.\n * This is where any timeout related error handling should live.\n */\nexport async function ensureSimulatorOpenAsync(\n { udid, osType }: Partial<Pick<SimControl.Device, 'udid' | 'osType'>> = {},\n tryAgain: boolean = true\n): Promise<SimControl.Device> {\n // Use a default simulator if none was specified\n if (!udid) {\n // If a simulator is open, side step the entire booting sequence.\n const simulatorOpenedByApp = await getBestBootedSimulatorAsync({ osType });\n if (simulatorOpenedByApp) {\n return simulatorOpenedByApp;\n }\n\n // Otherwise, find the best possible simulator from user defaults and continue\n const bestUdid = await getBestUnbootedSimulatorAsync({ osType });\n if (!bestUdid) {\n throw new CommandError('No simulators found.');\n }\n udid = bestUdid;\n }\n\n const bootedDevice = await waitForActionAsync({\n action: () => {\n // Just for the type check.\n assert(udid);\n return SimControl.bootAsync({ udid });\n },\n });\n\n if (!bootedDevice) {\n // Give it a second chance, this might not be needed but it could potentially lead to a better UX on slower devices.\n if (tryAgain) {\n return await ensureSimulatorOpenAsync({ udid, osType }, false);\n }\n // TODO: We should eliminate all needs for a timeout error, it's bad UX to get an error about the simulator not starting while the user can clearly see it starting on their slow computer.\n throw new CommandError(\n 'SIMULATOR_TIMEOUT',\n `Simulator didn't boot fast enough. Try opening Simulator first, then running your app.`\n );\n }\n return bootedDevice;\n}\nexport class AppleDeviceManager extends DeviceManager<SimControl.Device> {\n static assertSystemRequirementsAsync = assertSystemRequirementsAsync;\n\n static async resolveAsync({\n device,\n shouldPrompt,\n }: BaseResolveDeviceProps<\n Partial<Pick<SimControl.Device, 'udid' | 'osType'>>\n > = {}): Promise<AppleDeviceManager> {\n if (shouldPrompt) {\n const devices = await getSelectableSimulatorsAsync(device);\n device = await promptAppleDeviceAsync(devices, device?.osType);\n }\n\n const booted = await ensureSimulatorOpenAsync(device);\n return new AppleDeviceManager(booted);\n }\n\n get name() {\n return this.device.name;\n }\n\n get identifier(): string {\n return this.device.udid;\n }\n\n async getAppVersionAsync(appId: string): Promise<string | null> {\n return await SimControl.getInfoPlistValueAsync(this.device, {\n appId,\n key: 'CFBundleShortVersionString',\n });\n }\n\n async startAsync(): Promise<SimControl.Device> {\n return ensureSimulatorOpenAsync({ osType: this.device.osType, udid: this.device.udid });\n }\n\n async launchApplicationIdAsync(appId: string) {\n try {\n const result = await SimControl.openAppIdAsync(this.device, {\n appId,\n });\n if (result.status === 0) {\n await this.activateWindowAsync();\n } else {\n throw new CommandError(result.stderr);\n }\n } catch (error: any) {\n let errorMessage = `Couldn't open iOS app with ID \"${appId}\" on device \"${this.name}\".`;\n if (error instanceof CommandError && error.code === 'APP_NOT_INSTALLED') {\n if (appId === EXPO_GO_BUNDLE_IDENTIFIER) {\n errorMessage = `Couldn't open Expo Go app on device \"${this.name}\". Please install.`;\n } else {\n errorMessage += `\\nThe app might not be installed, try installing it with: ${chalk.bold(\n `expo run:ios -d ${this.device.udid}`\n )}`;\n }\n }\n if (error.stderr) {\n errorMessage += chalk.gray(`\\n${error.stderr}`);\n } else if (error.message) {\n errorMessage += chalk.gray(`\\n${error.message}`);\n }\n throw new CommandError(errorMessage);\n }\n }\n\n async installAppAsync(filePath: string) {\n await SimControl.installAsync(this.device, {\n filePath,\n });\n\n await this.waitForAppInstalledAsync(await this.getApplicationIdFromBundle(filePath));\n }\n\n private async getApplicationIdFromBundle(filePath: string): Promise<string> {\n // TODO: Implement...\n return EXPO_GO_BUNDLE_IDENTIFIER;\n }\n\n private async waitForAppInstalledAsync(applicationId: string): Promise<boolean> {\n while (true) {\n if (await this.isAppInstalledAsync(applicationId)) {\n return true;\n }\n await delayAsync(100);\n }\n }\n\n async uninstallAppAsync(appId: string) {\n await SimControl.uninstallAsync(this.device, {\n appId,\n });\n }\n\n async isAppInstalledAsync(appId: string) {\n return !!(await SimControl.getContainerPathAsync(this.device, {\n appId,\n }));\n }\n\n async openUrlAsync(url: string) {\n // Non-compliant URLs will be treated as application identifiers.\n if (!validateUrl(url, { requireProtocol: true })) {\n return await this.launchApplicationIdAsync(url);\n }\n\n try {\n await SimControl.openUrlAsync(this.device, { url });\n } catch (error: any) {\n // 194 means the device does not conform to a given URL, in this case we'll assume that the desired app is not installed.\n if (error.status === 194) {\n // An error was encountered processing the command (domain=NSOSStatusErrorDomain, code=-10814):\n // The operation couldn’t be completed. (OSStatus error -10814.)\n //\n // This can be thrown when no app conforms to the URI scheme that we attempted to open.\n throw new CommandError(\n 'APP_NOT_INSTALLED',\n `Device ${this.device.name} (${this.device.udid}) has no app to handle the URI: ${url}`\n );\n }\n throw error;\n }\n }\n\n async activateWindowAsync() {\n await ensureSimulatorAppRunningAsync(this.device);\n // TODO: Focus the individual window\n await osascript.execAsync(`tell application \"Simulator\" to activate`);\n }\n\n async ensureExpoGoAsync(sdkVersion?: string): Promise<boolean> {\n const installer = new ExpoGoInstaller('ios', EXPO_GO_BUNDLE_IDENTIFIER, sdkVersion);\n return installer.ensureAsync(this);\n }\n}\n"],"names":["ensureSimulatorOpenAsync","osascript","SimControl","EXPO_GO_BUNDLE_IDENTIFIER","udid","osType","tryAgain","simulatorOpenedByApp","getBestBootedSimulatorAsync","bestUdid","getBestUnbootedSimulatorAsync","CommandError","bootedDevice","waitForActionAsync","action","assert","bootAsync","AppleDeviceManager","DeviceManager","assertSystemRequirementsAsync","resolveAsync","device","shouldPrompt","devices","getSelectableSimulatorsAsync","promptAppleDeviceAsync","booted","name","identifier","getAppVersionAsync","appId","getInfoPlistValueAsync","key","startAsync","launchApplicationIdAsync","result","openAppIdAsync","status","activateWindowAsync","stderr","error","errorMessage","code","chalk","bold","gray","message","installAppAsync","filePath","installAsync","waitForAppInstalledAsync","getApplicationIdFromBundle","applicationId","isAppInstalledAsync","delayAsync","uninstallAppAsync","uninstallAsync","getContainerPathAsync","openUrlAsync","url","validateUrl","requireProtocol","ensureSimulatorAppRunningAsync","execAsync","ensureExpoGoAsync","sdkVersion","installer","ExpoGoInstaller","ensureAsync"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/start/platforms/ios/AppleDeviceManager.ts"],"sourcesContent":["import * as osascript from '@expo/osascript';\nimport assert from 'assert';\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\n\nimport { delayAsync, waitForActionAsync } from '../../../utils/delay';\nimport { CommandError } from '../../../utils/errors';\nimport { parsePlistAsync } from '../../../utils/plist';\nimport { validateUrl } from '../../../utils/url';\nimport { DeviceManager } from '../DeviceManager';\nimport { ExpoGoInstaller } from '../ExpoGoInstaller';\nimport { BaseResolveDeviceProps } from '../PlatformManager';\nimport { assertSystemRequirementsAsync } from './assertSystemRequirements';\nimport { ensureSimulatorAppRunningAsync } from './ensureSimulatorAppRunning';\nimport {\n getBestBootedSimulatorAsync,\n getBestUnbootedSimulatorAsync,\n getSelectableSimulatorsAsync,\n} from './getBestSimulator';\nimport { promptAppleDeviceAsync } from './promptAppleDevice';\nimport * as SimControl from './simctl';\n\nconst debug = require('debug')('expo:start:platforms:ios:AppleDeviceManager') as typeof console.log;\n\nconst EXPO_GO_BUNDLE_IDENTIFIER = 'host.exp.Exponent';\n\n/**\n * Ensure a simulator is booted and the Simulator app is opened.\n * This is where any timeout related error handling should live.\n */\nexport async function ensureSimulatorOpenAsync(\n { udid, osType }: Partial<Pick<SimControl.Device, 'udid' | 'osType'>> = {},\n tryAgain: boolean = true\n): Promise<SimControl.Device> {\n // Use a default simulator if none was specified\n if (!udid) {\n // If a simulator is open, side step the entire booting sequence.\n const simulatorOpenedByApp = await getBestBootedSimulatorAsync({ osType });\n if (simulatorOpenedByApp) {\n return simulatorOpenedByApp;\n }\n\n // Otherwise, find the best possible simulator from user defaults and continue\n const bestUdid = await getBestUnbootedSimulatorAsync({ osType });\n if (!bestUdid) {\n throw new CommandError('No simulators found.');\n }\n udid = bestUdid;\n }\n\n const bootedDevice = await waitForActionAsync({\n action: () => {\n // Just for the type check.\n assert(udid);\n return SimControl.bootAsync({ udid });\n },\n });\n\n if (!bootedDevice) {\n // Give it a second chance, this might not be needed but it could potentially lead to a better UX on slower devices.\n if (tryAgain) {\n return await ensureSimulatorOpenAsync({ udid, osType }, false);\n }\n // TODO: We should eliminate all needs for a timeout error, it's bad UX to get an error about the simulator not starting while the user can clearly see it starting on their slow computer.\n throw new CommandError(\n 'SIMULATOR_TIMEOUT',\n `Simulator didn't boot fast enough. Try opening Simulator first, then running your app.`\n );\n }\n return bootedDevice;\n}\nexport class AppleDeviceManager extends DeviceManager<SimControl.Device> {\n static assertSystemRequirementsAsync = assertSystemRequirementsAsync;\n\n static async resolveAsync({\n device,\n shouldPrompt,\n }: BaseResolveDeviceProps<\n Partial<Pick<SimControl.Device, 'udid' | 'osType'>>\n > = {}): Promise<AppleDeviceManager> {\n if (shouldPrompt) {\n const devices = await getSelectableSimulatorsAsync(device);\n device = await promptAppleDeviceAsync(devices, device?.osType);\n }\n\n const booted = await ensureSimulatorOpenAsync(device);\n return new AppleDeviceManager(booted);\n }\n\n get name() {\n return this.device.name;\n }\n\n get identifier(): string {\n return this.device.udid;\n }\n\n async getAppVersionAsync(appId: string): Promise<string | null> {\n return await SimControl.getInfoPlistValueAsync(this.device, {\n appId,\n key: 'CFBundleShortVersionString',\n });\n }\n\n async startAsync(): Promise<SimControl.Device> {\n return ensureSimulatorOpenAsync({ osType: this.device.osType, udid: this.device.udid });\n }\n\n async launchApplicationIdAsync(appId: string) {\n try {\n const result = await SimControl.openAppIdAsync(this.device, {\n appId,\n });\n if (result.status === 0) {\n await this.activateWindowAsync();\n } else {\n throw new CommandError(result.stderr);\n }\n } catch (error: any) {\n let errorMessage = `Couldn't open iOS app with ID \"${appId}\" on device \"${this.name}\".`;\n if (error instanceof CommandError && error.code === 'APP_NOT_INSTALLED') {\n if (appId === EXPO_GO_BUNDLE_IDENTIFIER) {\n errorMessage = `Couldn't open Expo Go app on device \"${this.name}\". Please install.`;\n } else {\n errorMessage += `\\nThe app might not be installed, try installing it with: ${chalk.bold(\n `expo run:ios -d ${this.device.udid}`\n )}`;\n }\n }\n if (error.stderr) {\n errorMessage += chalk.gray(`\\n${error.stderr}`);\n } else if (error.message) {\n errorMessage += chalk.gray(`\\n${error.message}`);\n }\n throw new CommandError(errorMessage);\n }\n }\n\n async installAppAsync(filePath: string) {\n await SimControl.installAsync(this.device, {\n filePath,\n });\n\n await this.waitForAppInstalledAsync(await this.getApplicationIdFromBundle(filePath));\n }\n\n private async getApplicationIdFromBundle(filePath: string): Promise<string> {\n debug('getApplicationIdFromBundle:', filePath);\n const builtInfoPlistPath = path.join(filePath, 'Info.plist');\n if (fs.existsSync(builtInfoPlistPath)) {\n const { CFBundleIdentifier } = await parsePlistAsync(builtInfoPlistPath);\n debug('getApplicationIdFromBundle: using built Info.plist', CFBundleIdentifier);\n return CFBundleIdentifier;\n }\n debug('getApplicationIdFromBundle: no Info.plist found');\n return EXPO_GO_BUNDLE_IDENTIFIER;\n }\n\n private async waitForAppInstalledAsync(applicationId: string): Promise<boolean> {\n while (true) {\n if (await this.isAppInstalledAsync(applicationId)) {\n return true;\n }\n await delayAsync(100);\n }\n }\n\n async uninstallAppAsync(appId: string) {\n await SimControl.uninstallAsync(this.device, {\n appId,\n });\n }\n\n async isAppInstalledAsync(appId: string) {\n return !!(await SimControl.getContainerPathAsync(this.device, {\n appId,\n }));\n }\n\n async openUrlAsync(url: string) {\n // Non-compliant URLs will be treated as application identifiers.\n if (!validateUrl(url, { requireProtocol: true })) {\n return await this.launchApplicationIdAsync(url);\n }\n\n try {\n await SimControl.openUrlAsync(this.device, { url });\n } catch (error: any) {\n // 194 means the device does not conform to a given URL, in this case we'll assume that the desired app is not installed.\n if (error.status === 194) {\n // An error was encountered processing the command (domain=NSOSStatusErrorDomain, code=-10814):\n // The operation couldn’t be completed. (OSStatus error -10814.)\n //\n // This can be thrown when no app conforms to the URI scheme that we attempted to open.\n throw new CommandError(\n 'APP_NOT_INSTALLED',\n `Device ${this.device.name} (${this.device.udid}) has no app to handle the URI: ${url}`\n );\n }\n throw error;\n }\n }\n\n async activateWindowAsync() {\n await ensureSimulatorAppRunningAsync(this.device);\n // TODO: Focus the individual window\n await osascript.execAsync(`tell application \"Simulator\" to activate`);\n }\n\n async ensureExpoGoAsync(sdkVersion?: string): Promise<boolean> {\n const installer = new ExpoGoInstaller('ios', EXPO_GO_BUNDLE_IDENTIFIER, sdkVersion);\n return installer.ensureAsync(this);\n }\n}\n"],"names":["ensureSimulatorOpenAsync","osascript","SimControl","debug","require","EXPO_GO_BUNDLE_IDENTIFIER","udid","osType","tryAgain","simulatorOpenedByApp","getBestBootedSimulatorAsync","bestUdid","getBestUnbootedSimulatorAsync","CommandError","bootedDevice","waitForActionAsync","action","assert","bootAsync","AppleDeviceManager","DeviceManager","assertSystemRequirementsAsync","resolveAsync","device","shouldPrompt","devices","getSelectableSimulatorsAsync","promptAppleDeviceAsync","booted","name","identifier","getAppVersionAsync","appId","getInfoPlistValueAsync","key","startAsync","launchApplicationIdAsync","result","openAppIdAsync","status","activateWindowAsync","stderr","error","errorMessage","code","chalk","bold","gray","message","installAppAsync","filePath","installAsync","waitForAppInstalledAsync","getApplicationIdFromBundle","builtInfoPlistPath","path","join","fs","existsSync","CFBundleIdentifier","parsePlistAsync","applicationId","isAppInstalledAsync","delayAsync","uninstallAppAsync","uninstallAsync","getContainerPathAsync","openUrlAsync","url","validateUrl","requireProtocol","ensureSimulatorAppRunningAsync","execAsync","ensureExpoGoAsync","sdkVersion","installer","ExpoGoInstaller","ensureAsync"],"mappings":"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"}
@@ -128,7 +128,7 @@ async function createHostInfoAsync() {
128
128
  host: await _userSettings.default.getAnonymousIdentifierAsync(),
129
129
  server: "expo",
130
130
  // Defined in the build step
131
- serverVersion: "0.2.8",
131
+ serverVersion: "0.2.9",
132
132
  serverDriver: _manifestMiddleware.DEVELOPER_TOOL,
133
133
  serverOS: _os.default.platform(),
134
134
  serverOSVersion: _os.default.release()
@@ -94,7 +94,7 @@ async function logEventAsync(event, properties = {}) {
94
94
  }
95
95
  const { userId , deviceId } = identifyData;
96
96
  const commonEventProperties = {
97
- source_version: "0.2.8",
97
+ source_version: "0.2.9",
98
98
  source: "expo"
99
99
  };
100
100
  const identity = {
@@ -135,7 +135,7 @@ function getContext() {
135
135
  },
136
136
  app: {
137
137
  name: "expo",
138
- version: "0.2.8"
138
+ version: "0.2.9"
139
139
  },
140
140
  ci: ciInfo.isCI ? {
141
141
  name: ciInfo.name,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/cli",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "The Expo CLI",
5
5
  "main": "build/bin/cli",
6
6
  "bin": {
@@ -137,5 +137,5 @@
137
137
  "structured-headers": "^0.4.1",
138
138
  "taskr": "1.1.0"
139
139
  },
140
- "gitHead": "485f74643b21338a15fd9ff7fcd6c82ea4fbb6f1"
140
+ "gitHead": "f0f9fbc21b313d6c9ea79e56c74f58a21f48c66f"
141
141
  }