Skip to content

Commit e295df8

Browse files
committed
feat: introduce initialSync workflow
1 parent fb47b68 commit e295df8

16 files changed

+587
-106
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"program": "${workspaceRoot}/lib/nativescript-cli.js",
1616

1717
// example commands
18-
"args": [ "build", "ios", "--path", "${workspaceRoot}/scratch/webpackApp", "--bundle"]
18+
"args": [ "run", "ios", "--path", "${workspaceRoot}/scratch/webpackApp", "--bundle"]
1919
// "args": [ "test", "android", "--justlaunch"]
2020
// "args": [ "platform", "add", "android@1.3.0", "--path", "cliapp"]
2121
// "args": [ "platform", "remove", "android", "--path", "cliapp"]

lib/bootstrap.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,12 @@ $injector.require("platformAddService", "./services/platform/platform-add-servic
4040
$injector.require("platformBuildService", "./services/platform/platform-build-service");
4141
$injector.require("platformValidationService", "./services/platform/platform-validation-service");
4242
$injector.require("platformCommandsService", "./services/platform/platform-commands-service");
43+
$injector.require("platformWatcherService", "./services/platform/platform-watcher-service");
4344

4445
$injector.require("platformWorkflowService", "./services/workflow/platform-workflow-service");
46+
$injector.require("deviceWorkflowService", "./services/workflow/device-workflow-service");
47+
$injector.require("runWorkflowService", "./services/workflow/run-workflow-service");
48+
$injector.require("bundleWorkflowService", "./services/bundle-workflow-service");
4549

4650
$injector.require("platformWorkflowDataFactory", "./factory/platform-workflow-data-factory");
4751

lib/declarations.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1028,7 +1028,7 @@ interface INetworkConnectivityValidator {
10281028
}
10291029

10301030
interface IBundleWorkflowService {
1031-
1031+
start(projectDir: string, deviceDescriptors: ILiveSyncDeviceInfo[], liveSyncInfo: ILiveSyncInfo): Promise<void>;
10321032
}
10331033

10341034
interface IPlatformValidationService {
@@ -1058,6 +1058,7 @@ interface IPlatformValidationService {
10581058

10591059
interface IBuildArtefactsService {
10601060
getLastBuiltPackagePath(platformData: IPlatformData, buildConfig: IBuildConfig, outputPath?: string): Promise<string>;
1061+
getAllBuiltApplicationPackages(buildOutputPath: string, validBuildOutputData: IValidBuildOutputData): IApplicationPackage[];
10611062
}
10621063

10631064
interface IPlatformAddService {
@@ -1083,4 +1084,5 @@ interface IAddPlatformData {
10831084
interface IPlatformBuildService {
10841085
buildPlatform(platformData: IPlatformData, projectData: IProjectData, buildConfig: IBuildConfig): Promise<string>;
10851086
saveBuildInfoFile(platformData: IPlatformData, projectData: IProjectData, buildInfoFileDirname: string): void;
1087+
getBuildInfoFromFile(platformData: IPlatformData, buildConfig: IBuildConfig, buildOutputPath?: string): IBuildInfo;
10861088
}

lib/definitions/livesync.d.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,10 @@ declare global {
264264
getLiveSyncDeviceDescriptors(projectDir: string): ILiveSyncDeviceInfo[];
265265
}
266266

267+
interface ILiveSyncService2 {
268+
fullSync(device: Mobile.IDevice, deviceBuildInfoDescriptor: ILiveSyncDeviceInfo, projectData: IProjectData, liveSyncInfo: ILiveSyncInfo): Promise<ILiveSyncResultInfo>;
269+
}
270+
267271
/**
268272
* Describes LiveSync operations while debuggging.
269273
*/
@@ -374,7 +378,6 @@ declare global {
374378
interface IFullSyncInfo extends IProjectDataComposition, IHasUseHotModuleReloadOption, IConnectTimeoutOption {
375379
device: Mobile.IDevice;
376380
watch: boolean;
377-
syncAllFiles: boolean;
378381
liveSyncDeviceInfo: ILiveSyncDeviceInfo;
379382
force?: boolean;
380383
}

lib/helpers/livesync-command-helper.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import { LiveSyncEvents } from "../constants";
1+
// import { LiveSyncEvents } from "../constants";
22

33
export class LiveSyncCommandHelper implements ILiveSyncCommandHelper {
44
public static MIN_SUPPORTED_WEBPACK_VERSION_WITH_HMR = "0.17.0";
55

66
constructor(private $platformService: IPlatformService,
77
private $projectData: IProjectData,
88
private $options: IOptions,
9-
private $liveSyncService: ILiveSyncService,
9+
private $bundleWorkflowService: IBundleWorkflowService,
10+
// private $liveSyncService: ILiveSyncService,
1011
private $iosDeviceOperations: IIOSDeviceOperations,
1112
private $mobileHelper: Mobile.IMobileHelper,
1213
private $devicesService: Mobile.IDevicesService,
@@ -127,16 +128,18 @@ export class LiveSyncCommandHelper implements ILiveSyncCommandHelper {
127128
force: this.$options.force
128129
};
129130

130-
const remainingDevicesToSync = devices.map(d => d.deviceInfo.identifier);
131-
this.$liveSyncService.on(LiveSyncEvents.liveSyncStopped, (data: { projectDir: string, deviceIdentifier: string }) => {
132-
_.remove(remainingDevicesToSync, d => d === data.deviceIdentifier);
131+
await this.$bundleWorkflowService.start(this.$projectData.projectDir, deviceDescriptors, liveSyncInfo);
133132

134-
if (remainingDevicesToSync.length === 0) {
135-
process.exit(ErrorCodes.ALL_DEVICES_DISCONNECTED);
136-
}
137-
});
133+
// const remainingDevicesToSync = devices.map(d => d.deviceInfo.identifier);
134+
// this.$liveSyncService.on(LiveSyncEvents.liveSyncStopped, (data: { projectDir: string, deviceIdentifier: string }) => {
135+
// _.remove(remainingDevicesToSync, d => d === data.deviceIdentifier);
136+
137+
// if (remainingDevicesToSync.length === 0) {
138+
// process.exit(ErrorCodes.ALL_DEVICES_DISCONNECTED);
139+
// }
140+
// });
138141

139-
await this.$liveSyncService.liveSync(deviceDescriptors, liveSyncInfo);
142+
// await this.$liveSyncService.liveSync(deviceDescriptors, liveSyncInfo);
140143
}
141144

142145
public async validatePlatform(platform: string): Promise<IDictionary<IValidatePlatformOutput>> {

lib/services/build-artefacts-service.ts

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,27 @@ export class BuildArtefactsService implements IBuildArtefactsService {
1919
return packageFile;
2020
}
2121

22+
public getAllBuiltApplicationPackages(buildOutputPath: string, validBuildOutputData: IValidBuildOutputData): IApplicationPackage[] {
23+
const rootFiles = this.$fs.readDirectory(buildOutputPath).map(filename => path.join(buildOutputPath, filename));
24+
let result = this.getApplicationPackagesCore(rootFiles, validBuildOutputData.packageNames);
25+
if (result) {
26+
return result;
27+
}
28+
29+
const candidates = this.$fs.enumerateFilesInDirectorySync(buildOutputPath);
30+
result = this.getApplicationPackagesCore(candidates, validBuildOutputData.packageNames);
31+
if (result) {
32+
return result;
33+
}
34+
35+
if (validBuildOutputData.regexes && validBuildOutputData.regexes.length) {
36+
const packages = candidates.filter(filepath => _.some(validBuildOutputData.regexes, regex => regex.test(path.basename(filepath))));
37+
return this.createApplicationPackages(packages);
38+
}
39+
40+
return [];
41+
}
42+
2243
private getLatestApplicationPackageForDevice(platformData: IPlatformData, buildConfig: IBuildConfig, outputPath?: string): IApplicationPackage {
2344
outputPath = outputPath || platformData.getBuildOutputPath(buildConfig);
2445
const buildOutputOptions = { buildForDevice: true, release: buildConfig.release, androidBundle: buildConfig.androidBundle };
@@ -32,7 +53,7 @@ export class BuildArtefactsService implements IBuildArtefactsService {
3253
}
3354

3455
private getLatestApplicationPackage(buildOutputPath: string, validBuildOutputData: IValidBuildOutputData): IApplicationPackage {
35-
let packages = this.getApplicationPackages(buildOutputPath, validBuildOutputData);
56+
let packages = this.getAllBuiltApplicationPackages(buildOutputPath, validBuildOutputData);
3657
const packageExtName = path.extname(validBuildOutputData.packageNames[0]);
3758
if (packages.length === 0) {
3859
this.$errors.fail(`No ${packageExtName} found in ${buildOutputPath} directory.`);
@@ -47,26 +68,6 @@ export class BuildArtefactsService implements IBuildArtefactsService {
4768
return packages[0];
4869
}
4970

50-
private getApplicationPackages(buildOutputPath: string, validBuildOutputData: IValidBuildOutputData): IApplicationPackage[] {
51-
// Get latest package` that is produced from build
52-
let result = this.getApplicationPackagesCore(this.$fs.readDirectory(buildOutputPath).map(filename => path.join(buildOutputPath, filename)), validBuildOutputData.packageNames);
53-
if (result) {
54-
return result;
55-
}
56-
57-
const candidates = this.$fs.enumerateFilesInDirectorySync(buildOutputPath);
58-
result = this.getApplicationPackagesCore(candidates, validBuildOutputData.packageNames);
59-
if (result) {
60-
return result;
61-
}
62-
63-
if (validBuildOutputData.regexes && validBuildOutputData.regexes.length) {
64-
return this.createApplicationPackages(candidates.filter(filepath => _.some(validBuildOutputData.regexes, regex => regex.test(path.basename(filepath)))));
65-
}
66-
67-
return [];
68-
}
69-
7071
private getApplicationPackagesCore(candidates: string[], validPackageNames: string[]): IApplicationPackage[] {
7172
const packages = candidates.filter(filePath => _.includes(validPackageNames, path.basename(filePath)));
7273
if (packages.length > 0) {
@@ -77,14 +78,12 @@ export class BuildArtefactsService implements IBuildArtefactsService {
7778
}
7879

7980
private createApplicationPackages(packages: string[]): IApplicationPackage[] {
80-
return packages.map(filepath => this.createApplicationPackage(filepath));
81-
}
82-
83-
private createApplicationPackage(packageName: string): IApplicationPackage {
84-
return {
85-
packageName,
86-
time: this.$fs.getFsStats(packageName).mtime
87-
};
81+
return packages.map(packageName => {
82+
return {
83+
packageName,
84+
time: this.$fs.getFsStats(packageName).mtime
85+
};
86+
});
8887
}
8988
}
9089
$injector.register("buildArtefactsService", BuildArtefactsService);
Lines changed: 118 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,137 @@
1-
import * as path from "path";
2-
import * as constants from "../constants";
1+
// import * as path from "path";
2+
// import * as constants from "../constants";
33

4+
const deviceDescriptorPrimaryKey = "identifier";
5+
6+
// TODO: Rename this class to RunWorkflowService
47
export class BundleWorkflowService implements IBundleWorkflowService {
8+
private liveSyncProcessesInfo: IDictionary<any> = {};
9+
510
constructor(
611
private $devicesService: Mobile.IDevicesService,
12+
private $deviceWorkflowService: IDeviceWorkflowService,
713
private $errors: IErrors,
8-
private $fs: IFileSystem,
14+
private $liveSyncService: ILiveSyncService2,
15+
// private $fs: IFileSystem,
916
private $logger: ILogger,
10-
private $platformAddService: IPlatformAddService,
17+
// private $platformAddService: IPlatformAddService,
1118
private $platformsData: IPlatformsData,
1219
private $platformWatcherService: IPlatformWatcherService,
20+
private $platformWorkflowService: IPlatformWorkflowService,
1321
private $pluginsService: IPluginsService,
14-
private $projectChangesService: IProjectChangesService
22+
private $projectDataService: IProjectDataService,
23+
// private $projectChangesService: IProjectChangesService
1524
) { }
1625

1726
// processInfo[projectDir] = {
1827
// deviceDescriptors, nativeFilesWatcher, jsFilesWatcher
1928
// }
2029

21-
public async start(projectData: IProjectData, deviceDescriptors: ILiveSyncDeviceInfo[], liveSyncInfo: ILiveSyncInfo): Promise<void> {
30+
public async start(projectDir: string, deviceDescriptors: ILiveSyncDeviceInfo[], liveSyncInfo: ILiveSyncInfo): Promise<void> {
31+
const projectData = this.$projectDataService.getProjectData(projectDir);
2232
await this.initializeSetup(projectData);
2333

2434
const platforms = _(deviceDescriptors)
2535
.map(device => this.$devicesService.getDeviceByIdentifier(device.identifier))
2636
.map(device => device.deviceInfo.platform)
2737
.uniq()
2838
.value();
29-
for (const platform in platforms) {
30-
const platformData = this.$platformsData.getPlatformData(platform, projectData);
3139

32-
const shouldAddPlatform = this.shouldAddPlatform(platformData, projectData, liveSyncInfo.nativePrepare);
33-
if (shouldAddPlatform) {
34-
await this.$platformAddService.addPlatform({
35-
platformParam: (<any>liveSyncInfo).platformParam,
36-
frameworkPath: (<any>liveSyncInfo).frameworkPath,
37-
nativePrepare: liveSyncInfo.nativePrepare
38-
}, projectData);
40+
const workflowData: IPlatformWorkflowData = {
41+
platformParam: null,
42+
nativePrepare: liveSyncInfo.nativePrepare,
43+
release: liveSyncInfo.release,
44+
useHotModuleReload: liveSyncInfo.useHotModuleReload,
45+
signingOptions: {
46+
teamId: (<any>liveSyncInfo).teamId,
47+
provision: (<any>liveSyncInfo).provision
3948
}
49+
};
4050

41-
this.$platformWatcherService.on("onInitialSync", async () => {
42-
console.log("================= RECEIVED INITIAL SYNC ============= ");
43-
// check if we should build, install, transfer files
44-
// AddActionToChain
45-
});
46-
this.$platformWatcherService.on("onFilesChange", () => {
47-
console.log("=================== RECEIVED FILES CHANGE ================ ");
48-
// Emitted when webpack compilatation is done and native prepare is done
49-
// console.log("--------- ========= ---------- ", data);
50-
// AddActionToChain
51-
});
51+
// Ensure platform is added before starting JS(webpack) and native prepare
52+
for (const platform of platforms) {
53+
const platformNameLowerCase = platform.toLowerCase();
54+
const platformData = this.$platformsData.getPlatformData(platformNameLowerCase, projectData);
55+
workflowData.platformParam = platformNameLowerCase;
56+
await this.$platformWorkflowService.addPlatformIfNeeded(platformData, projectData, workflowData);
57+
}
58+
59+
this.setLiveSyncProcessInfo(projectDir, liveSyncInfo, deviceDescriptors);
60+
61+
const initalSyncDeviceAction = async (device: Mobile.IDevice): Promise<void> => {
62+
console.log("================== INITIAL SYNC DEVICE ACTION ================");
63+
const deviceBuildInfoDescriptor = _.find(deviceDescriptors, dd => dd.identifier === device.deviceInfo.identifier);
64+
const platform = device.deviceInfo.platform;
65+
const platformData = this.$platformsData.getPlatformData(platform, projectData);
66+
const buildConfig = {
67+
buildForDevice: !device.isEmulator,
68+
device: device.deviceInfo.identifier,
69+
release: liveSyncInfo.release,
70+
clean: liveSyncInfo.clean,
71+
iCloudContainerEnvironment: "",
72+
projectDir: projectData.projectDir,
73+
teamId: <any>null,
74+
provision: <any>null,
75+
};
76+
const outputPath = deviceBuildInfoDescriptor.outputPath || platformData.getBuildOutputPath(buildConfig);
77+
const packageFilePath = await this.$platformWorkflowService.buildPlatformIfNeeded(platformData, projectData, workflowData, buildConfig, outputPath);
78+
79+
await this.$deviceWorkflowService.installOnDeviceIfNeeded(device, platformData, projectData, buildConfig, packageFilePath, outputPath);
80+
81+
await this.$liveSyncService.fullSync(device, deviceBuildInfoDescriptor, projectData, liveSyncInfo);
82+
};
83+
84+
// const filesChangeDeviceAction = async (device: Mobile.IDevice): Promise<void> {
85+
// // test
86+
// };
87+
88+
this.$platformWatcherService.on("onInitialSync", async () => { // TODO: emit correct initialSyncData -> platform + hasNativeChange
89+
await this.addActionToChain(projectData.projectDir, () => this.$devicesService.execute(initalSyncDeviceAction, (device: Mobile.IDevice) => _.some(deviceDescriptors, deviceDescriptor => deviceDescriptor.identifier === device.deviceInfo.identifier)));
90+
});
91+
this.$platformWatcherService.on("fileChangeData", () => {
92+
console.log("=================== RECEIVED FILES CHANGE ================ ");
93+
// Emitted when webpack compilatation is done and native prepare is done
94+
// console.log("--------- ========= ---------- ", data);
95+
// AddActionToChain
96+
});
5297

53-
await this.$platformWatcherService.startWatcher(platformData, projectData, {
54-
webpackCompilerConfig: liveSyncInfo.webpackCompilerConfig,
55-
preparePlatformData: {
56-
release: liveSyncInfo.release,
57-
useHotModuleReload: liveSyncInfo.useHotModuleReload,
58-
nativePrepare: liveSyncInfo.nativePrepare,
59-
signingOptions: {
60-
teamId: (<any>liveSyncInfo).teamId,
61-
provision: (<any>liveSyncInfo).provision
98+
const shouldStartWatcher = !liveSyncInfo.skipWatcher && (liveSyncInfo.syncToPreviewApp || this.liveSyncProcessesInfo[projectData.projectDir].deviceDescriptors.length);
99+
100+
if (shouldStartWatcher) {
101+
// TODO: Extract the preparePlatformData to separate variable
102+
for (const platform of platforms) {
103+
const platformData = this.$platformsData.getPlatformData(platform.toLocaleLowerCase(), projectData);
104+
await this.$platformWatcherService.startWatcher(platformData, projectData, {
105+
webpackCompilerConfig: liveSyncInfo.webpackCompilerConfig,
106+
preparePlatformData: {
107+
release: liveSyncInfo.release,
108+
useHotModuleReload: liveSyncInfo.useHotModuleReload,
109+
nativePrepare: liveSyncInfo.nativePrepare,
110+
signingOptions: {
111+
teamId: (<any>liveSyncInfo).teamId,
112+
provision: (<any>liveSyncInfo).provision
113+
}
62114
}
63-
}
64-
});
115+
});
116+
}
65117
}
118+
}
66119

67-
for (const deviceDescriptor in deviceDescriptors) {
68-
console.log("============ DEVICE DESCRIPTOR ============== ", deviceDescriptor);
69-
}
120+
public getLiveSyncDeviceDescriptors(projectDir: string): ILiveSyncDeviceInfo[] {
121+
const liveSyncProcessesInfo = this.liveSyncProcessesInfo[projectDir] || <ILiveSyncProcessInfo>{};
122+
const currentDescriptors = liveSyncProcessesInfo.deviceDescriptors;
123+
return currentDescriptors || [];
124+
}
125+
126+
private setLiveSyncProcessInfo(projectDir: string, liveSyncInfo: ILiveSyncInfo, deviceDescriptors: ILiveSyncDeviceInfo[]): void {
127+
this.liveSyncProcessesInfo[projectDir] = this.liveSyncProcessesInfo[projectDir] || Object.create(null);
128+
this.liveSyncProcessesInfo[projectDir].actionsChain = this.liveSyncProcessesInfo[projectDir].actionsChain || Promise.resolve();
129+
this.liveSyncProcessesInfo[projectDir].currentSyncAction = this.liveSyncProcessesInfo[projectDir].actionsChain;
130+
this.liveSyncProcessesInfo[projectDir].isStopped = false;
131+
this.liveSyncProcessesInfo[projectDir].syncToPreviewApp = liveSyncInfo.syncToPreviewApp;
132+
133+
const currentDeviceDescriptors = this.getLiveSyncDeviceDescriptors(projectDir);
134+
this.liveSyncProcessesInfo[projectDir].deviceDescriptors = _.uniqBy(currentDeviceDescriptors.concat(deviceDescriptors), deviceDescriptorPrimaryKey);
70135
}
71136

72137
private async initializeSetup(projectData: IProjectData): Promise<void> {
@@ -78,15 +143,20 @@ export class BundleWorkflowService implements IBundleWorkflowService {
78143
}
79144
}
80145

81-
private shouldAddPlatform(platformData: IPlatformData, projectData: IProjectData, nativePrepare: INativePrepare): boolean {
82-
const platformName = platformData.normalizedPlatformName.toLowerCase();
83-
const prepareInfo = this.$projectChangesService.getPrepareInfo(platformName, projectData);
84-
const hasPlatformDirectory = this.$fs.exists(path.join(projectData.platformsDir, platformName));
85-
const shouldAddNativePlatform = !nativePrepare || !nativePrepare.skipNativePrepare;
86-
const requiresNativePlatformAdd = prepareInfo && prepareInfo.nativePlatformStatus === constants.NativePlatformStatus.requiresPlatformAdd;
87-
const result = !hasPlatformDirectory || (shouldAddNativePlatform && requiresNativePlatformAdd);
146+
private async addActionToChain<T>(projectDir: string, action: () => Promise<T>): Promise<T> {
147+
const liveSyncInfo = this.liveSyncProcessesInfo[projectDir];
148+
if (liveSyncInfo) {
149+
liveSyncInfo.actionsChain = liveSyncInfo.actionsChain.then(async () => {
150+
if (!liveSyncInfo.isStopped) {
151+
liveSyncInfo.currentSyncAction = action();
152+
const res = await liveSyncInfo.currentSyncAction;
153+
return res;
154+
}
155+
});
88156

89-
return result;
157+
const result = await liveSyncInfo.actionsChain;
158+
return result;
159+
}
90160
}
91161
}
92162
$injector.register("bundleWorkflowService", BundleWorkflowService);

lib/services/device/device-installation-service.ts

Whitespace-only changes.

0 commit comments

Comments
 (0)