-
-
Notifications
You must be signed in to change notification settings - Fork 197
/
Copy pathplatform-livesync-service-base.ts
148 lines (123 loc) · 7.3 KB
/
platform-livesync-service-base.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import * as path from "path";
import * as util from "util";
import { APP_FOLDER_NAME } from "../../constants";
import { getHash } from "../../common/helpers";
export abstract class PlatformLiveSyncServiceBase {
private _deviceLiveSyncServicesCache: IDictionary<INativeScriptDeviceLiveSyncService> = {};
constructor(protected $fs: IFileSystem,
protected $logger: ILogger,
protected $platformsData: IPlatformsData,
protected $projectFilesManager: IProjectFilesManager,
private $devicePathProvider: IDevicePathProvider,
private $projectFilesProvider: IProjectFilesProvider) { }
public getDeviceLiveSyncService(device: Mobile.IDevice, projectData: IProjectData): INativeScriptDeviceLiveSyncService {
const platformData = this.$platformsData.getPlatformData(device.deviceInfo.platform, projectData);
const frameworkVersion = platformData.platformProjectService.getFrameworkVersion(projectData);
const key = getHash(`${device.deviceInfo.identifier}${projectData.projectId}${projectData.projectDir}${frameworkVersion}`);
if (!this._deviceLiveSyncServicesCache[key]) {
this._deviceLiveSyncServicesCache[key] = this._getDeviceLiveSyncService(device, projectData, frameworkVersion);
}
return this._deviceLiveSyncServicesCache[key];
}
protected abstract _getDeviceLiveSyncService(device: Mobile.IDevice, data: IProjectData, frameworkVersion: string): INativeScriptDeviceLiveSyncService;
public async refreshApplication(projectData: IProjectData, liveSyncInfo: ILiveSyncResultInfo): Promise<void> {
if (liveSyncInfo.isFullSync || liveSyncInfo.modifiedFilesData.length) {
const deviceLiveSyncService = this.getDeviceLiveSyncService(liveSyncInfo.deviceAppData.device, projectData);
this.$logger.info("Refreshing application...");
await deviceLiveSyncService.refreshApplication(projectData, liveSyncInfo);
}
}
public async fullSync(syncInfo: IFullSyncInfo): Promise<ILiveSyncResultInfo> {
const projectData = syncInfo.projectData;
const device = syncInfo.device;
const deviceLiveSyncService = this.getDeviceLiveSyncService(device, syncInfo.projectData);
const platformData = this.$platformsData.getPlatformData(device.deviceInfo.platform, projectData);
const deviceAppData = await this.getAppData(syncInfo);
if (deviceLiveSyncService.beforeLiveSyncAction) {
await deviceLiveSyncService.beforeLiveSyncAction(deviceAppData);
}
const projectFilesPath = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME);
const localToDevicePaths = await this.$projectFilesManager.createLocalToDevicePaths(deviceAppData, projectFilesPath, null, []);
const modifiedFilesData = await this.transferFiles(deviceAppData, localToDevicePaths, projectFilesPath, true, projectData);
return {
modifiedFilesData,
isFullSync: true,
deviceAppData,
useHotModuleReload: syncInfo.useHotModuleReload
};
}
public async liveSyncWatchAction(device: Mobile.IDevice, liveSyncInfo: ILiveSyncWatchInfo): Promise<ILiveSyncResultInfo> {
const projectData = liveSyncInfo.projectData;
const deviceLiveSyncService = this.getDeviceLiveSyncService(device, projectData);
const syncInfo = _.merge<IFullSyncInfo>({ device, watch: true }, liveSyncInfo);
const deviceAppData = await this.getAppData(syncInfo);
if (deviceLiveSyncService.beforeLiveSyncAction) {
await deviceLiveSyncService.beforeLiveSyncAction(deviceAppData);
}
let modifiedLocalToDevicePaths: Mobile.ILocalToDevicePathData[] = [];
if (liveSyncInfo.filesToSync.length) {
const filesToSync = liveSyncInfo.filesToSync;
const mappedFiles = _.map(filesToSync, filePath => this.$projectFilesProvider.mapFilePath(filePath, device.deviceInfo.platform, projectData));
// Some plugins modify platforms dir on afterPrepare (check nativescript-dev-sass) - we want to sync only existing file.
const existingFiles = mappedFiles.filter(m => m && this.$fs.exists(m));
this.$logger.trace("Will execute livesync for files: ", existingFiles);
const skippedFiles = _.difference(mappedFiles, existingFiles);
if (skippedFiles.length) {
this.$logger.trace("The following files will not be synced as they do not exist:", skippedFiles);
}
if (existingFiles.length) {
const platformData = this.$platformsData.getPlatformData(device.deviceInfo.platform, projectData);
const projectFilesPath = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME);
const localToDevicePaths = await this.$projectFilesManager.createLocalToDevicePaths(deviceAppData,
projectFilesPath, existingFiles, []);
modifiedLocalToDevicePaths.push(...localToDevicePaths);
modifiedLocalToDevicePaths = await this.transferFiles(deviceAppData, localToDevicePaths, projectFilesPath, false, projectData);
}
}
if (liveSyncInfo.filesToRemove.length) {
const filePaths = liveSyncInfo.filesToRemove;
const platformData = this.$platformsData.getPlatformData(device.deviceInfo.platform, projectData);
const mappedFiles = _(filePaths)
.map(filePath => this.$projectFilesProvider.mapFilePath(filePath, device.deviceInfo.platform, projectData))
.filter(filePath => !!filePath)
.value();
const projectFilesPath = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME);
const localToDevicePaths = await this.$projectFilesManager.createLocalToDevicePaths(deviceAppData, projectFilesPath, mappedFiles, []);
modifiedLocalToDevicePaths.push(...localToDevicePaths);
await deviceLiveSyncService.removeFiles(deviceAppData, localToDevicePaths, projectFilesPath);
}
return {
modifiedFilesData: modifiedLocalToDevicePaths,
isFullSync: liveSyncInfo.isReinstalled,
deviceAppData,
useHotModuleReload: liveSyncInfo.useHotModuleReload
};
}
protected async transferFiles(deviceAppData: Mobile.IDeviceAppData, localToDevicePaths: Mobile.ILocalToDevicePathData[], projectFilesPath: string, isFullSync: boolean, projectData: IProjectData): Promise<Mobile.ILocalToDevicePathData[]> {
let transferredFiles: Mobile.ILocalToDevicePathData[] = [];
const deviceLiveSyncService = this.getDeviceLiveSyncService(deviceAppData.device, projectData);
transferredFiles = await deviceLiveSyncService.transferFiles(deviceAppData, localToDevicePaths, projectFilesPath, isFullSync);
this.logFilesSyncInformation(transferredFiles, "Successfully transferred %s.", this.$logger.info);
return transferredFiles;
}
protected async getAppData(syncInfo: IFullSyncInfo): Promise<Mobile.IDeviceAppData> {
const deviceProjectRootOptions: IDeviceProjectRootOptions = _.assign({ appIdentifier: syncInfo.projectData.projectId }, syncInfo);
return {
appIdentifier: syncInfo.projectData.projectId,
device: syncInfo.device,
platform: syncInfo.device.deviceInfo.platform,
getDeviceProjectRootPath: () => this.$devicePathProvider.getDeviceProjectRootPath(syncInfo.device, deviceProjectRootOptions),
deviceSyncZipPath: this.$devicePathProvider.getDeviceSyncZipPath(syncInfo.device),
isLiveSyncSupported: async () => true
};
}
private logFilesSyncInformation(localToDevicePaths: Mobile.ILocalToDevicePathData[], message: string, action: Function): void {
if (localToDevicePaths && localToDevicePaths.length < 10) {
_.each(localToDevicePaths, (file: Mobile.ILocalToDevicePathData) => {
action.call(this.$logger, util.format(message, path.basename(file.getLocalPath()).yellow));
});
} else {
action.call(this.$logger, util.format(message, "all files"));
}
}
}