mobile-cli-lib
Version:
common lib used by different CLI
287 lines (286 loc) • 17.5 kB
JavaScript
"use strict";
var fiberBootstrap = require("../fiber-bootstrap");
var syncBatchLib = require("./livesync/sync-batch");
var shell = require("shelljs");
var path = require("path");
var temp = require("temp");
var minimatch = require("minimatch");
var constants = require("../constants");
var util = require("util");
var gaze = require("gaze");
var LiveSyncServiceBase = (function () {
function LiveSyncServiceBase($devicesService, $mobileHelper, $logger, $options, $deviceAppDataFactory, $fs, $injector, $hooksService, $projectFilesManager, $projectFilesProvider, $liveSyncProvider, $devicePlatformsConstants, $hostInfo, $dispatcher) {
this.$devicesService = $devicesService;
this.$mobileHelper = $mobileHelper;
this.$logger = $logger;
this.$options = $options;
this.$deviceAppDataFactory = $deviceAppDataFactory;
this.$fs = $fs;
this.$injector = $injector;
this.$hooksService = $hooksService;
this.$projectFilesManager = $projectFilesManager;
this.$projectFilesProvider = $projectFilesProvider;
this.$liveSyncProvider = $liveSyncProvider;
this.$devicePlatformsConstants = $devicePlatformsConstants;
this.$hostInfo = $hostInfo;
this.$dispatcher = $dispatcher;
this.showFullLiveSyncInformation = false;
this.batch = Object.create(null);
this.livesyncData = Object.create(null);
this.fileHashes = Object.create(null);
}
LiveSyncServiceBase.prototype.sync = function (data, filePaths) {
var _this = this;
return (function () {
_this.syncCore(data, filePaths).wait();
if (_this.$options.watch) {
_this.$hooksService.executeBeforeHooks('watch').wait();
_this.partialSync(data, data[0].syncWorkingDirectory);
}
}).future()();
};
LiveSyncServiceBase.prototype.isFileExcluded = function (filePath, excludedPatterns) {
var isFileExcluded = false;
_.each(excludedPatterns, function (pattern) {
if (minimatch(filePath, pattern, { nocase: true })) {
isFileExcluded = true;
return false;
}
});
return isFileExcluded;
};
LiveSyncServiceBase.prototype.partialSync = function (data, syncWorkingDirectory) {
var that = this;
this.showFullLiveSyncInformation = true;
gaze("**/*", { cwd: syncWorkingDirectory }, function (err, watcher) {
this.on('all', function (event, filePath) {
fiberBootstrap.run(function () {
that.$dispatcher.dispatch(function () { return (function () {
try {
if (filePath.indexOf(constants.APP_RESOURCES_FOLDER_NAME) !== -1) {
that.$logger.warn(("Skipping livesync for changed file " + filePath + ". This change requires a full build to update your application. ").yellow.bold);
return;
}
var fileHash = that.$fs.exists(filePath).wait() && that.$fs.getFsStats(filePath).wait().isFile() ? that.$fs.getFileShasum(filePath).wait() : "";
if (fileHash === that.fileHashes[filePath]) {
that.$logger.trace("Skipping livesync for " + filePath + " file with " + fileHash + " hash.");
return;
}
that.$logger.trace("Adding " + filePath + " file with " + fileHash + " hash.");
that.fileHashes[filePath] = fileHash;
for (var _i = 0, data_1 = data; _i < data_1.length; _i++) {
var dataItem = data_1[_i];
if (that.isFileExcluded(filePath, dataItem.excludedProjectDirsAndFiles)) {
that.$logger.trace("Skipping livesync for changed file " + filePath + " as it is excluded in the patterns: " + dataItem.excludedProjectDirsAndFiles.join(", "));
continue;
}
var mappedFilePath = that.$projectFilesProvider.mapFilePath(filePath, dataItem.platform);
that.$logger.trace("Syncing filePath " + filePath + ", mappedFilePath is " + mappedFilePath);
if (!mappedFilePath) {
that.$logger.warn("Unable to sync " + filePath + ".");
continue;
}
if (event === "added" || event === "changed" || event === "renamed") {
that.batchSync(dataItem, mappedFilePath);
}
else if (event === "deleted") {
that.fileHashes = (_.omit(that.fileHashes, filePath));
that.syncRemovedFile(dataItem, mappedFilePath).wait();
}
}
}
catch (err) {
that.$logger.info(("Unable to sync file " + filePath + ". Error is:" + err.message).red.bold);
that.$logger.info("Try saving it again or restart the livesync operation.");
}
}).future()(); });
});
});
});
this.$dispatcher.run();
};
LiveSyncServiceBase.prototype.batchSync = function (data, filePath) {
var _this = this;
var platformBatch = this.batch[data.platform];
if (!platformBatch || !platformBatch.syncPending) {
var done = function () {
return (function () {
setTimeout(function () {
fiberBootstrap.run(function () {
_this.$dispatcher.dispatch(function () { return (function () {
try {
var _loop_1 = function(platformName) {
var batch = _this.batch[platformName];
var livesyncData = _this.livesyncData[platformName];
batch.syncFiles((function (filesToSync) {
_this.$liveSyncProvider.preparePlatformForSync(platformName).wait();
_this.syncCore([livesyncData], filesToSync);
}).future()).wait();
};
for (var platformName in _this.batch) {
_loop_1(platformName);
}
}
catch (err) {
_this.$logger.warn("Unable to sync files. Error is:", err.message);
}
}).future()(); });
});
}, syncBatchLib.SYNC_WAIT_THRESHOLD);
}).future()();
};
this.batch[data.platform] = this.$injector.resolve(syncBatchLib.SyncBatch, { done: done });
this.livesyncData[data.platform] = data;
}
this.batch[data.platform].addFile(filePath);
};
LiveSyncServiceBase.prototype.syncRemovedFile = function (data, filePath) {
var _this = this;
return (function () {
var filePathArray = [filePath], deviceFilesAction = _this.getSyncRemovedFilesAction(data);
_this.syncCore([data], filePathArray, deviceFilesAction).wait();
}).future()();
};
LiveSyncServiceBase.prototype.getSyncRemovedFilesAction = function (data) {
var _this = this;
return function (deviceAppData, device, localToDevicePaths) {
var platformLiveSyncService = _this.resolveDeviceLiveSyncService(data.platform, device);
return platformLiveSyncService.removeFiles(deviceAppData.appIdentifier, localToDevicePaths);
};
};
LiveSyncServiceBase.prototype.getSyncAction = function (data, filesToSync, deviceFilesAction, liveSyncOptions) {
var _this = this;
var appIdentifier = data.appIdentifier;
var platform = data.platform;
var projectFilesPath = data.projectFilesPath;
var packageFilePath = null;
var action = function (device) {
return (function () {
var shouldRefreshApplication = true;
var deviceAppData = _this.$deviceAppDataFactory.create(appIdentifier, _this.$mobileHelper.normalizePlatformName(platform), device, liveSyncOptions);
if (deviceAppData.isLiveSyncSupported().wait()) {
var platformLiveSyncService = _this.resolveDeviceLiveSyncService(platform, device);
if (platformLiveSyncService.beforeLiveSyncAction) {
platformLiveSyncService.beforeLiveSyncAction(deviceAppData).wait();
}
device.applicationManager.checkForApplicationUpdates().wait();
var wasInstalled = true;
if (!device.applicationManager.isApplicationInstalled(appIdentifier).wait() && !_this.$options.companion) {
_this.$logger.warn("The application with id \"" + appIdentifier + "\" is not installed on device with identifier " + device.deviceInfo.identifier + ".");
if (!packageFilePath) {
packageFilePath = _this.$liveSyncProvider.buildForDevice(device).wait();
}
device.applicationManager.installApplication(packageFilePath).wait();
if (platformLiveSyncService.afterInstallApplicationAction) {
var localToDevicePaths = _this.$projectFilesManager.createLocalToDevicePaths(deviceAppData, projectFilesPath, filesToSync, data.excludedProjectDirsAndFiles, liveSyncOptions);
shouldRefreshApplication = platformLiveSyncService.afterInstallApplicationAction(deviceAppData, localToDevicePaths).wait();
}
else {
shouldRefreshApplication = false;
}
if (device.applicationManager.canStartApplication() && !shouldRefreshApplication) {
device.applicationManager.startApplication(appIdentifier).wait();
}
wasInstalled = false;
}
if (shouldRefreshApplication) {
var localToDevicePaths = _this.$projectFilesManager.createLocalToDevicePaths(deviceAppData, projectFilesPath, filesToSync, data.excludedProjectDirsAndFiles, liveSyncOptions);
if (deviceFilesAction) {
deviceFilesAction(deviceAppData, device, localToDevicePaths).wait();
}
else {
_this.transferFiles(deviceAppData, localToDevicePaths, projectFilesPath, !filesToSync).wait();
}
_this.$logger.info("Applying changes...");
platformLiveSyncService.refreshApplication(deviceAppData, localToDevicePaths, data.forceExecuteFullSync || !wasInstalled).wait();
_this.$logger.info("Successfully synced application " + data.appIdentifier + " on device " + device.deviceInfo.identifier + ".");
}
}
else {
_this.$logger.warn("LiveSync is not supported for application: " + deviceAppData.appIdentifier + " on device with identifier " + device.deviceInfo.identifier + ".");
}
}).future()();
};
return action;
};
LiveSyncServiceBase.prototype.syncCore = function (data, filesToSync, deviceFilesAction) {
var _this = this;
return (function () {
for (var _i = 0, data_2 = data; _i < data_2.length; _i++) {
var dataItem = data_2[_i];
var appIdentifier = dataItem.appIdentifier;
var platform = dataItem.platform;
var canExecute = _this.getCanExecuteAction(platform, appIdentifier, dataItem.canExecute);
var action = _this.getSyncAction(dataItem, filesToSync, deviceFilesAction, { isForCompanionApp: _this.$options.companion, additionalConfigurations: dataItem.additionalConfigurations, configuration: dataItem.configuration, isForDeletedFiles: false });
_this.$devicesService.execute(action, canExecute).wait();
}
}).future()();
};
LiveSyncServiceBase.prototype.transferFiles = function (deviceAppData, localToDevicePaths, projectFilesPath, isFullSync) {
var _this = this;
return (function () {
_this.$logger.info("Transferring project files...");
_this.logFilesSyncInformation(localToDevicePaths, "Transferring %s.", _this.$logger.trace);
var canTransferDirectory = isFullSync && (_this.$devicesService.isAndroidDevice(deviceAppData.device) || _this.$devicesService.isiOSSimulator(deviceAppData.device));
if (canTransferDirectory) {
var tempDir_1 = temp.mkdirSync("tempDir");
_.each(localToDevicePaths, function (localToDevicePath) {
var fileDirname = path.join(tempDir_1, path.dirname(localToDevicePath.getRelativeToProjectBasePath()));
shell.mkdir("-p", fileDirname);
if (!_this.$fs.getFsStats(localToDevicePath.getLocalPath()).wait().isDirectory()) {
shell.cp("-f", localToDevicePath.getLocalPath(), path.join(fileDirname, path.basename(localToDevicePath.getDevicePath())));
}
});
deviceAppData.device.fileSystem.transferDirectory(deviceAppData, localToDevicePaths, tempDir_1).wait();
}
else {
_this.$liveSyncProvider.transferFiles(deviceAppData, localToDevicePaths, projectFilesPath, isFullSync).wait();
}
_this.logFilesSyncInformation(localToDevicePaths, "Successfully transferred %s.", _this.$logger.info);
}).future()();
};
LiveSyncServiceBase.prototype.logFilesSyncInformation = function (localToDevicePaths, message, action) {
var _this = this;
if (this.showFullLiveSyncInformation) {
_.each(localToDevicePaths, function (file) {
action.call(_this.$logger, util.format(message, path.basename(file.getLocalPath()).yellow));
});
}
else {
action.call(this.$logger, util.format(message, "all files"));
}
};
LiveSyncServiceBase.prototype.resolveDeviceLiveSyncService = function (platform, device) {
return this.$injector.resolve(this.$liveSyncProvider.deviceSpecificLiveSyncServices[platform.toLowerCase()], { _device: device });
};
LiveSyncServiceBase.prototype.getCanExecuteAction = function (platform, appIdentifier, canExecute) {
var _this = this;
canExecute = canExecute || (function (dev) { return dev.deviceInfo.platform.toLowerCase() === platform.toLowerCase(); });
var finalCanExecute = canExecute;
if (this.$options.device) {
return function (device) { return canExecute(device) && device.deviceInfo.identifier === _this.$devicesService.getDeviceByDeviceOption().deviceInfo.identifier; };
}
if (this.$mobileHelper.isiOSPlatform(platform)) {
if (this.$options.emulator) {
finalCanExecute = function (device) { return canExecute(device) && _this.$devicesService.isiOSSimulator(device); };
}
else {
var devices = this.$devicesService.getDevicesForPlatform(platform);
var simulator_1 = _.find(devices, function (d) { return _this.$devicesService.isiOSSimulator(d); });
if (simulator_1) {
var iOSDevices = _.filter(devices, function (d) { return d.deviceInfo.identifier !== simulator_1.deviceInfo.identifier; });
if (iOSDevices && iOSDevices.length) {
var isApplicationInstalledOnSimulator = simulator_1.applicationManager.isApplicationInstalled(appIdentifier).wait();
var isApplicationInstalledOnAllDevices = _.intersection.apply(null, iOSDevices.map(function (device) { return device.applicationManager.isApplicationInstalled(appIdentifier).wait(); }));
if (!isApplicationInstalledOnSimulator && !isApplicationInstalledOnAllDevices) {
finalCanExecute = function (device) { return canExecute(device) && _this.$devicesService.isiOSDevice(device); };
}
}
}
}
}
return finalCanExecute;
};
return LiveSyncServiceBase;
}());
$injector.register('liveSyncServiceBase', LiveSyncServiceBase);