mobile-cli-lib
Version:
common lib used by different CLI
576 lines (575 loc) • 29.1 kB
JavaScript
"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);