UNPKG

mobile-cli-lib

Version:
576 lines (575 loc) 29.1 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var util = require("util"); var Future = require("fibers/future"); var helpers = require("../../helpers"); var assert = require("assert"); var constants = require("../../constants"); var fiberBootstrap = require("../../fiber-bootstrap"); var decorators_1 = require("../../decorators"); var DevicesService = (function () { function DevicesService($logger, $errors, $iOSSimulatorDiscovery, $iOSDeviceDiscovery, $androidDeviceDiscovery, $staticConfig, $messages, $mobileHelper, $deviceLogProvider, $hostInfo, $devicePlatformsConstants, $injector, $options, $androidProcessService, $processService) { this.$logger = $logger; this.$errors = $errors; this.$iOSSimulatorDiscovery = $iOSSimulatorDiscovery; this.$iOSDeviceDiscovery = $iOSDeviceDiscovery; this.$androidDeviceDiscovery = $androidDeviceDiscovery; this.$staticConfig = $staticConfig; this.$messages = $messages; this.$mobileHelper = $mobileHelper; this.$deviceLogProvider = $deviceLogProvider; this.$hostInfo = $hostInfo; this.$devicePlatformsConstants = $devicePlatformsConstants; this.$injector = $injector; this.$options = $options; this.$androidProcessService = $androidProcessService; this.$processService = $processService; this._devices = {}; this.platforms = []; this._isInitialized = false; this.attachToDeviceDiscoveryEvents(); } Object.defineProperty(DevicesService.prototype, "$companionAppsService", { get: function () { return this.$injector.resolve("companionAppsService"); }, enumerable: true, configurable: true }); Object.defineProperty(DevicesService.prototype, "platform", { get: function () { return this._platform; }, enumerable: true, configurable: true }); Object.defineProperty(DevicesService.prototype, "deviceCount", { get: function () { return this._device ? 1 : this.getDeviceInstances().length; }, enumerable: true, configurable: true }); DevicesService.prototype.getDevices = function () { return this.getDeviceInstances().map(function (deviceInstance) { return deviceInstance.deviceInfo; }); }; DevicesService.prototype.getDevicesForPlatform = function (platform) { return _.filter(this.getDeviceInstances(), function (d) { return d.deviceInfo.platform.toLowerCase() === platform.toLowerCase(); }); }; DevicesService.prototype.isAndroidDevice = function (device) { return this.$mobileHelper.isAndroidPlatform(device.deviceInfo.platform); }; DevicesService.prototype.isiOSDevice = function (device) { return this.$mobileHelper.isiOSPlatform(device.deviceInfo.platform) && !device.isEmulator; }; DevicesService.prototype.isiOSSimulator = function (device) { return !!(this.$mobileHelper.isiOSPlatform(device.deviceInfo.platform) && device.isEmulator); }; DevicesService.prototype.setLogLevel = function (logLevel, deviceIdentifier) { this.$deviceLogProvider.setLogLevel(logLevel, deviceIdentifier); }; DevicesService.prototype.isAppInstalledOnDevices = function (deviceIdentifiers, appIdentifier, framework) { var _this = this; this.$logger.trace("Called isInstalledOnDevices for identifiers " + deviceIdentifiers + ". AppIdentifier is " + appIdentifier + ". Framework is: " + framework + "."); return _.map(deviceIdentifiers, function (deviceIdentifier) { return _this.isApplicationInstalledOnDevice(deviceIdentifier, appIdentifier, framework); }); }; DevicesService.prototype.isCompanionAppInstalledOnDevices = function (deviceIdentifiers, framework) { var _this = this; this.$logger.trace("Called isCompanionAppInstalledOnDevices for identifiers " + deviceIdentifiers + ". Framework is " + framework + "."); return _.map(deviceIdentifiers, function (deviceIdentifier) { return _this.isCompanionAppInstalledOnDevice(deviceIdentifier, framework); }); }; DevicesService.prototype.getDeviceInstances = function () { return _.values(this._devices); }; DevicesService.prototype.getAllPlatforms = function () { var _this = this; if (this.platforms.length > 0) { return this.platforms; } this.platforms = _.filter(this.$mobileHelper.platformNames, function (platform) { return _this.$mobileHelper.getPlatformCapabilities(platform).cableDeploy; }); return this.platforms; }; DevicesService.prototype.getPlatform = function (platform) { var allSupportedPlatforms = this.getAllPlatforms(); var normalizedPlatform = this.$mobileHelper.validatePlatformName(platform); if (!_.includes(allSupportedPlatforms, normalizedPlatform)) { this.$errors.failWithoutHelp("Deploying to %s connected devices is not supported. Build the " + "app using the `build` command and deploy the package manually.", normalizedPlatform); } return normalizedPlatform; }; DevicesService.prototype.attachToDeviceDiscoveryEvents = function () { var _this = this; this.$iOSSimulatorDiscovery.on("deviceFound", function (device) { return _this.onDeviceFound(device); }); this.$iOSSimulatorDiscovery.on("deviceLost", function (device) { return _this.onDeviceLost(device); }); this.$iOSDeviceDiscovery.on("deviceFound", function (device) { return _this.onDeviceFound(device); }); this.$iOSDeviceDiscovery.on("deviceLost", function (device) { return _this.onDeviceLost(device); }); this.$androidDeviceDiscovery.on("deviceFound", function (device) { return _this.onDeviceFound(device); }); this.$androidDeviceDiscovery.on("deviceLost", function (device) { return _this.onDeviceLost(device); }); }; DevicesService.prototype.onDeviceFound = function (device) { this.$logger.trace("Found device with identifier '%s'", device.deviceInfo.identifier); this._devices[device.deviceInfo.identifier] = device; }; DevicesService.prototype.onDeviceLost = function (device) { this.$logger.trace("Lost device with identifier '%s'", device.deviceInfo.identifier); delete this._devices[device.deviceInfo.identifier]; }; DevicesService.prototype.detectCurrentlyAttachedDevices = function () { var _this = this; return (function () { try { _this.$iOSDeviceDiscovery.startLookingForDevices().wait(); _this.$androidDeviceDiscovery.startLookingForDevices().wait(); if (_this.$hostInfo.isDarwin) { _this.$iOSSimulatorDiscovery.startLookingForDevices().wait(); } } catch (err) { _this.$logger.trace("Error while detecting devices.", err); } }).future()(); }; DevicesService.prototype.startDeviceDetectionInterval = function () { var _this = this; this.$processService.attachToProcessExitSignals(this, this.clearDeviceDetectionInterval); if (this.deviceDetectionInterval) { this.$logger.trace("Device detection interval is already started. New Interval will not be started."); } else { this.deviceDetectionInterval = setInterval(function () { fiberBootstrap.run(function () { if (_this.deviceDetectionIntervalFuture) { return; } _this.deviceDetectionIntervalFuture = new Future(); try { _this.$iOSDeviceDiscovery.checkForDevices().wait(); } catch (err) { _this.$logger.trace("Error while checking for new iOS devices.", err); } try { _this.$androidDeviceDiscovery.startLookingForDevices().wait(); } catch (err) { _this.$logger.trace("Error while checking for new Android devices.", err); } try { if (_this.$hostInfo.isDarwin) { _this.$iOSSimulatorDiscovery.checkForDevices().wait(); } } catch (err) { _this.$logger.trace("Error while checking for new iOS Simulators.", err); } _.each(_this._devices, function (device) { try { device.applicationManager.checkForApplicationUpdates().wait(); } catch (err) { _this.$logger.trace("Error checking for application updates on device " + device.deviceInfo.identifier + ".", err); } }); _this.deviceDetectionIntervalFuture.return(); _this.deviceDetectionIntervalFuture.wait(); _this.deviceDetectionIntervalFuture = null; }); }, DevicesService.DEVICE_LOOKING_INTERVAL).unref(); } }; DevicesService.prototype.stopDeviceDetectionInterval = function () { var _this = this; return (function () { _this.clearDeviceDetectionInterval(); _this.deviceDetectionInterval = null; _this.getDeviceDetectionIntervalFuture().wait(); }).future()(); }; DevicesService.prototype.getDeviceByIdentifier = function (identifier) { var searchedDevice = _.find(this.getDeviceInstances(), function (device) { return device.deviceInfo.identifier === identifier; }); if (!searchedDevice) { this.$errors.fail(this.$messages.Devices.NotFoundDeviceByIdentifierErrorMessageWithIdentifier, identifier, this.$staticConfig.CLIENT_NAME.toLowerCase()); } return searchedDevice; }; DevicesService.prototype.startLookingForDevices = function () { var _this = this; return (function () { _this.$logger.trace("startLookingForDevices; platform is %s", _this._platform); if (!_this._platform) { _this.detectCurrentlyAttachedDevices().wait(); _this.startDeviceDetectionInterval(); } else if (_this.$mobileHelper.isiOSPlatform(_this._platform)) { _this.$iOSDeviceDiscovery.startLookingForDevices().wait(); if (_this.$hostInfo.isDarwin) { _this.$iOSSimulatorDiscovery.startLookingForDevices().wait(); } } else if (_this.$mobileHelper.isAndroidPlatform(_this._platform)) { _this.$androidDeviceDiscovery.startLookingForDevices().wait(); } }).future()(); }; DevicesService.prototype.getDeviceByIndex = function (index) { this.validateIndex(index - 1); return this.getDeviceInstances()[index - 1]; }; DevicesService.prototype.getDevice = function (deviceOption) { var _this = this; return (function () { _this.detectCurrentlyAttachedDevices().wait(); var device = null; if (_this.hasDevice(deviceOption)) { device = _this.getDeviceByIdentifier(deviceOption); } else if (helpers.isNumber(deviceOption)) { device = _this.getDeviceByIndex(parseInt(deviceOption, 10)); } if (!device) { _this.$errors.fail(_this.$messages.Devices.NotFoundDeviceByIdentifierErrorMessage, _this.$staticConfig.CLIENT_NAME.toLowerCase()); } return device; }).future()(); }; DevicesService.prototype.executeOnDevice = function (action, canExecute) { var _this = this; return (function () { if (!canExecute || canExecute(_this._device)) { action(_this._device).wait(); } }).future()(); }; DevicesService.prototype.executeOnAllConnectedDevices = function (action, canExecute) { var _this = this; return (function () { var devices = _this.filterDevicesByPlatform(); var sortedDevices = _.sortBy(devices, function (device) { return device.deviceInfo.platform; }); var futures = _.map(sortedDevices, function (device) { if (!canExecute || canExecute(device)) { var future = action(device); Future.settle(future); return future; } else { return Future.fromResult(); } }); Future.wait(futures); }).future()(); }; DevicesService.prototype.deployOnDevices = function (deviceIdentifiers, packageFile, packageName, framework) { var _this = this; this.$logger.trace("Called deployOnDevices for identifiers " + deviceIdentifiers + " for packageFile: " + packageFile + ". packageName is " + packageName + "."); return _.map(deviceIdentifiers, function (deviceIdentifier) { return _this.deployOnDevice(deviceIdentifier, packageFile, packageName, framework); }); }; DevicesService.prototype.execute = function (action, canExecute, options) { var _this = this; return (function () { assert.ok(_this._isInitialized, "Devices services not initialized!"); if (_this.hasDevices) { if (_this.$hostInfo.isDarwin && _this._platform && _this.$mobileHelper.isiOSPlatform(_this._platform) && _this.$options.emulator && !_this.isOnlyiOSSimultorRunning()) { _this.startEmulator().wait(); var originalCanExecute_1 = canExecute; canExecute = function (dev) { return _this.isiOSSimulator(dev) && (!originalCanExecute_1 || !!(originalCanExecute_1(dev))); }; } _this.executeCore(action, canExecute).wait(); } else { var message = constants.ERROR_NO_DEVICES; if (options && options.allowNoDevices) { _this.$logger.info(message); } else { if (!_this.$hostInfo.isDarwin && _this._platform && _this.$mobileHelper.isiOSPlatform(_this._platform)) { _this.$errors.failWithoutHelp(message); } else { _this.startEmulator().wait(); _this.executeCore(action, canExecute).wait(); } } } }).future()(); }; DevicesService.prototype.initialize = function (data) { var _this = this; if (this._isInitialized) { return Future.fromResult(); } return (function () { data = data || {}; _this._data = data; var platform = data.platform; var deviceOption = data.deviceId; if (platform && deviceOption) { _this._device = _this.getDevice(deviceOption).wait(); _this._platform = _this._device.deviceInfo.platform; if (_this._platform !== _this.getPlatform(platform)) { _this.$errors.fail("Cannot resolve the specified connected device. The provided platform does not match the provided index or identifier." + "To list currently connected devices and verify that the specified pair of platform and index or identifier exists, run 'device'."); } _this.$logger.warn("Your application will be deployed only on the device specified by the provided index or identifier."); } else if (!platform && deviceOption) { _this._device = _this.getDevice(deviceOption).wait(); _this._platform = _this._device.deviceInfo.platform; } else if (platform && !deviceOption) { _this._platform = _this.getPlatform(platform); _this.startLookingForDevices().wait(); } else { if (data.skipInferPlatform) { _this.startLookingForDevices().wait(); } else { _this.detectCurrentlyAttachedDevices().wait(); var devices = _this.getDeviceInstances(); var platforms = _(devices) .map(function (device) { return device.deviceInfo.platform; }) .filter(function (pl) { try { return _this.getPlatform(pl); } catch (err) { _this.$logger.warn(err.message); return null; } }) .uniq() .value(); if (platforms.length === 1) { _this._platform = platforms[0]; } else if (platforms.length === 0) { _this.$errors.fail({ formatStr: constants.ERROR_NO_DEVICES, suppressCommandHelp: true }); } else { _this.$errors.fail("Multiple device platforms detected (%s). Specify platform or device on command line.", helpers.formatListOfNames(platforms, "and")); } } } if (!_this.$hostInfo.isDarwin && _this._platform && _this.$mobileHelper.isiOSPlatform(_this._platform) && _this.$options.emulator) { _this.$errors.failWithoutHelp("You can use iOS simulator only on OS X."); } _this._isInitialized = true; }).future()(); }; Object.defineProperty(DevicesService.prototype, "hasDevices", { get: function () { if (!this._platform) { return this.getDeviceInstances().length !== 0; } else { return this.filterDevicesByPlatform().length !== 0; } }, enumerable: true, configurable: true }); DevicesService.prototype.isOnlyiOSSimultorRunning = function () { var devices = this.getDeviceInstances(); return this._platform && this.$mobileHelper.isiOSPlatform(this._platform) && _.find(devices, function (d) { return d.isEmulator; }) && !_.find(devices, function (d) { return !d.isEmulator; }); }; DevicesService.prototype.getDeviceByDeviceOption = function () { return this._device; }; DevicesService.prototype.mapAbstractToTcpPort = function (deviceIdentifier, appIdentifier, framework) { return this.$androidProcessService.mapAbstractToTcpPort(deviceIdentifier, appIdentifier, framework); }; DevicesService.prototype.getDebuggableApps = function (deviceIdentifiers) { var _this = this; return _.map(deviceIdentifiers, function (deviceIdentifier) { return _this.getDebuggableAppsCore(deviceIdentifier); }); }; DevicesService.prototype.getDebuggableViews = function (deviceIdentifier, appIdentifier) { var _this = this; return (function () { var device = _this.getDeviceByIdentifier(deviceIdentifier), debuggableViewsPerApp = device.applicationManager.getDebuggableAppViews([appIdentifier]).wait(); return debuggableViewsPerApp && debuggableViewsPerApp[appIdentifier]; }).future()(); }; DevicesService.prototype.clearDeviceDetectionInterval = function () { if (this.deviceDetectionInterval) { clearInterval(this.deviceDetectionInterval); } else { this.$logger.trace("Device detection interval is not started, so it cannot be stopped."); } }; DevicesService.prototype.getDebuggableAppsCore = function (deviceIdentifier) { var _this = this; return (function () { var device = _this.getDeviceByIdentifier(deviceIdentifier); return device.applicationManager.getDebuggableApps().wait(); }).future()(); }; DevicesService.prototype.deployOnDevice = function (deviceIdentifier, packageFile, packageName, framework) { var _this = this; return (function () { _this.stopDeviceDetectionInterval().wait(); var device = _this.getDeviceByIdentifier(deviceIdentifier); device.applicationManager.reinstallApplication(packageName, packageFile).wait(); _this.$logger.info("Successfully deployed on device with identifier '" + device.deviceInfo.identifier + "'."); device.applicationManager.tryStartApplication(packageName, framework).wait(); }).future()(); }; DevicesService.prototype.hasDevice = function (identifier) { return _.some(this.getDeviceInstances(), function (device) { return device.deviceInfo.identifier === identifier; }); }; DevicesService.prototype.filterDevicesByPlatform = function () { var _this = this; return _.filter(this.getDeviceInstances(), function (device) { if (_this.$options.emulator && !device.isEmulator) { return false; } if (_this._platform) { return device.deviceInfo.platform === _this._platform; } return true; }); }; DevicesService.prototype.validateIndex = function (index) { if (index < 0 || index > this.getDeviceInstances().length) { throw new Error(util.format(this.$messages.Devices.NotFoundDeviceByIndexErrorMessage, index, this.$staticConfig.CLIENT_NAME.toLowerCase())); } }; DevicesService.prototype.resolveEmulatorServices = function (platform) { platform = platform || this._platform; if (this.$mobileHelper.isiOSPlatform(platform) && this.$hostInfo.isDarwin) { return this.$injector.resolve("iOSEmulatorServices"); } else if (this.$mobileHelper.isAndroidPlatform(platform)) { return this.$injector.resolve("androidEmulatorServices"); } return null; }; DevicesService.prototype.startEmulator = function (platform) { var _this = this; return (function () { platform = platform || _this._platform; var emulatorServices = _this.resolveEmulatorServices(platform); if (!emulatorServices) { _this.$errors.failWithoutHelp("Unable to detect platform for which to start emulator."); } emulatorServices.startEmulator().wait(); if (_this.$mobileHelper.isAndroidPlatform(platform)) { _this.$androidDeviceDiscovery.startLookingForDevices().wait(); } else if (_this.$mobileHelper.isiOSPlatform(platform) && _this.$hostInfo.isDarwin) { _this.$iOSSimulatorDiscovery.startLookingForDevices().wait(); } }).future()(); }; DevicesService.prototype.executeCore = function (action, canExecute) { if (this._device) { return this.executeOnDevice(action, canExecute); } return this.executeOnAllConnectedDevices(action, canExecute); }; DevicesService.prototype.isApplicationInstalledOnDevice = function (deviceIdentifier, appIdentifier, framework) { var _this = this; return (function () { var isInstalled = false, isLiveSyncSupported = false, device = _this.getDeviceByIdentifier(deviceIdentifier); try { isInstalled = device.applicationManager.isApplicationInstalled(appIdentifier).wait(); device.applicationManager.tryStartApplication(appIdentifier, framework).wait(); isLiveSyncSupported = isInstalled && !!device.applicationManager.isLiveSyncSupported(appIdentifier).wait(); } catch (err) { _this.$logger.trace("Error while checking is application installed. Error is: ", err); } return { appIdentifier: appIdentifier, deviceIdentifier: deviceIdentifier, isInstalled: isInstalled, isLiveSyncSupported: isLiveSyncSupported }; }).future()(); }; DevicesService.prototype.isCompanionAppInstalledOnDevice = function (deviceIdentifier, framework) { var _this = this; return (function () { var isInstalled = false, isLiveSyncSupported = false, device = _this.getDeviceByIdentifier(deviceIdentifier), appIdentifier = _this.$companionAppsService.getCompanionAppIdentifier(framework, device.deviceInfo.platform); try { isLiveSyncSupported = isInstalled = device.applicationManager.isApplicationInstalled(appIdentifier).wait(); } catch (err) { _this.$logger.trace("Error while checking is application installed. Error is: ", err); } return { appIdentifier: appIdentifier, deviceIdentifier: deviceIdentifier, isInstalled: isInstalled, isLiveSyncSupported: isLiveSyncSupported }; }).future()(); }; DevicesService.prototype.getDeviceDetectionIntervalFuture = function () { return this.deviceDetectionIntervalFuture || Future.fromResult(); }; DevicesService.DEVICE_LOOKING_INTERVAL = 2200; __decorate([ decorators_1.exported("devicesService"), __metadata('design:type', Function), __metadata('design:paramtypes', []), __metadata('design:returntype', Array) ], DevicesService.prototype, "getDevices", null); __decorate([ decorators_1.exported("devicesService"), __metadata('design:type', Function), __metadata('design:paramtypes', [String, String]), __metadata('design:returntype', void 0) ], DevicesService.prototype, "setLogLevel", null); __decorate([ decorators_1.exportedPromise("devicesService"), __metadata('design:type', Function), __metadata('design:paramtypes', [Array, String, String]), __metadata('design:returntype', Array) ], DevicesService.prototype, "isAppInstalledOnDevices", null); __decorate([ decorators_1.exportedPromise("devicesService"), __metadata('design:type', Function), __metadata('design:paramtypes', [Array, String]), __metadata('design:returntype', Array) ], DevicesService.prototype, "isCompanionAppInstalledOnDevices", null); __decorate([ decorators_1.exportedPromise("devicesService", function () { this.startDeviceDetectionInterval(); }), __metadata('design:type', Function), __metadata('design:paramtypes', [Array, String, String, String]), __metadata('design:returntype', Array) ], DevicesService.prototype, "deployOnDevices", null); __decorate([ decorators_1.exportedPromise("devicesService"), __metadata('design:type', Function), __metadata('design:paramtypes', [String, String, String]), __metadata('design:returntype', Object) ], DevicesService.prototype, "mapAbstractToTcpPort", null); __decorate([ decorators_1.exportedPromise("devicesService"), __metadata('design:type', Function), __metadata('design:paramtypes', [Array]), __metadata('design:returntype', Array) ], DevicesService.prototype, "getDebuggableApps", null); __decorate([ decorators_1.exportedPromise("devicesService"), __metadata('design:type', Function), __metadata('design:paramtypes', [String, String]), __metadata('design:returntype', Object) ], DevicesService.prototype, "getDebuggableViews", null); return DevicesService; }()); exports.DevicesService = DevicesService; $injector.register("devicesService", DevicesService);