Skip to content

Commit f278202

Browse files
committed
Add "Sync to Playground" option in prompts when env is not properly configured
1 parent 94f9acc commit f278202

7 files changed

+74
-33
lines changed

lib/definitions/preview-app-livesync.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FilePayload, DeviceConnectedMessage } from "nativescript-preview-sdk";
1+
import { FilePayload, Device } from "nativescript-preview-sdk";
22

33
declare global {
44
interface IPreviewAppLiveSyncService {
@@ -7,11 +7,11 @@ declare global {
77
stopLiveSync(): Promise<void>;
88
}
99

10-
interface IPreviewAppLiveSyncData extends IProjectDataComposition, IAppFilesUpdaterOptionsComposition, IEnvOptions { }
10+
interface IPreviewAppLiveSyncData extends IProjectDir, IAppFilesUpdaterOptionsComposition, IEnvOptions { }
1111

1212
interface IPreviewSdkService extends NodeJS.EventEmitter {
1313
qrCodeUrl: string;
14-
connectedDevices: DeviceConnectedMessage[];
14+
connectedDevices: Device[];
1515
initialize(): void;
1616
applyChanges(files: FilePayload[]): Promise<void>;
1717
stop(): void;

lib/services/livesync/livesync-service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
469469
release: liveSyncData.release
470470
},
471471
env: liveSyncData.env,
472-
projectData
472+
projectDir: projectData.projectDir
473473
});
474474
});
475475
}
@@ -587,7 +587,7 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
587587
release: liveSyncData.release
588588
},
589589
env: liveSyncData.env,
590-
projectData: projectData
590+
projectDir: projectData.projectDir
591591
}, filesToSync);
592592
});
593593
} else {

lib/services/livesync/playground/preview-app-livesync-service.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as path from "path";
2-
import { FilePayload, DeviceConnectedMessage } from "nativescript-preview-sdk";
2+
import { FilePayload, Device } from "nativescript-preview-sdk";
33
import { PreviewSdkEventNames } from "./preview-app-constants";
44
import { APP_FOLDER_NAME, APP_RESOURCES_FOLDER_NAME, TNS_MODULES_FOLDER_NAME } from "../../../constants";
55

@@ -8,13 +8,15 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
88
private $logger: ILogger,
99
private $platformService: IPlatformService,
1010
private $platformsData: IPlatformsData,
11+
private $projectDataService: IProjectDataService,
1112
private $previewSdkService: IPreviewSdkService,
1213
private $projectFilesManager: IProjectFilesManager,
1314
private $qrCodeTerminalService: IQrCodeTerminalService) { }
1415

1516
public async initialSync(data: IPreviewAppLiveSyncData): Promise<void> {
1617
this.$previewSdkService.initialize();
17-
this.$previewSdkService.on(PreviewSdkEventNames.DEVICE_CONNECTED, async (device: DeviceConnectedMessage) => {
18+
this.$previewSdkService.on(PreviewSdkEventNames.DEVICE_CONNECTED, async (device: Device) => {
19+
this.$logger.trace("Found connected device", device);
1820
await this.trySyncFilesOnDevice(data, device);
1921
});
2022
await this.generateQRCode();
@@ -35,22 +37,23 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
3537
this.$qrCodeTerminalService.generate(this.$previewSdkService.qrCodeUrl);
3638
}
3739

38-
private async trySyncFilesOnDevice(data: IPreviewAppLiveSyncData, device: DeviceConnectedMessage, files?: string[]): Promise<void> {
39-
this.$logger.info(`Start syncing changes on device ${device.deviceId}.`);
40+
private async trySyncFilesOnDevice(data: IPreviewAppLiveSyncData, device: Device, files?: string[]): Promise<void> {
41+
this.$logger.info(`Start syncing changes on device ${device.id}.`);
4042

4143
try {
4244
await this.syncFilesOnDevice(data, device, files);
43-
this.$logger.info(`Successfully synced changes on device ${device.deviceId}.`);
45+
this.$logger.info(`Successfully synced changes on device ${device.id}.`);
4446
} catch (err) {
45-
this.$logger.warn(`Unable to apply changes on device ${device.deviceId}. Error is ${err.message}.`);
47+
this.$logger.warn(`Unable to apply changes on device ${device.id}. Error is: ${JSON.stringify(err, null, 2)}.`);
4648
}
4749
}
4850

49-
private async syncFilesOnDevice(data: IPreviewAppLiveSyncData, device: DeviceConnectedMessage, files?: string[]): Promise<void> {
50-
const { appFilesUpdaterOptions, env, projectData } = data;
51+
private async syncFilesOnDevice(data: IPreviewAppLiveSyncData, device: Device, files?: string[]): Promise<void> {
52+
const { appFilesUpdaterOptions, env, projectDir } = data;
5153
const platform = device.platform;
54+
const projectData = this.$projectDataService.getProjectData(projectDir);
5255
const platformData = this.$platformsData.getPlatformData(platform, projectData);
53-
56+
5457
await this.preparePlatform(platform, appFilesUpdaterOptions, env, projectData);
5558

5659
const payloads = this.getFilePayloads(platformData, projectData, files);
@@ -64,12 +67,19 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
6467
if (files) {
6568
files = files.map(file => path.join(platformsAppFolderPath, path.relative(appFolderPath, file)));
6669
} else {
67-
files = this.$projectFilesManager.getProjectFiles(platformsAppFolderPath);
70+
const excludedProjectDirsAndFiles = [TNS_MODULES_FOLDER_NAME, APP_RESOURCES_FOLDER_NAME, "*.ts", "*.sass", "*.scss", ".less"];
71+
files = this.$projectFilesManager.getProjectFiles(platformsAppFolderPath, excludedProjectDirsAndFiles);
6872
}
6973

70-
const result = files
74+
const filesToTransfer = files
7175
.filter(file => file.indexOf(TNS_MODULES_FOLDER_NAME) === -1)
7276
.filter(file => file.indexOf(APP_RESOURCES_FOLDER_NAME) === -1)
77+
.filter(file => path.basename(file) !== "main.aot.js")
78+
.filter(file => path.basename(file) !== ".DS_Store");
79+
80+
this.$logger.trace(`Transferring ${filesToTransfer.join("\n")}.`);
81+
82+
const payloads = filesToTransfer
7383
.map(file => {
7484
return {
7585
event: PreviewSdkEventNames.CHANGE_EVENT_NAME,
@@ -79,7 +89,8 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
7989
};
8090
});
8191

82-
return result;
92+
93+
return payloads;
8394
}
8495

8596
private async preparePlatform(platform: string, appFilesUpdaterOptions: IAppFilesUpdaterOptions, env: Object, projectData: IProjectData): Promise<void> {

lib/services/livesync/playground/preview-sdk-service.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { PreviewSdkEventNames, PubnubKeys } from "./preview-app-constants";
55
export class PreviewSdkService extends EventEmitter implements IPreviewSdkService {
66
private messagingService: MessagingService = null;
77
private instanceId: string = null;
8-
public connectedDevices: DeviceConnectedMessage[] = [];
8+
public connectedDevices: Device[] = [];
99

1010
constructor(private $errors: IErrors,
1111
private $logger: ILogger) {
@@ -54,25 +54,20 @@ export class PreviewSdkService extends EventEmitter implements IPreviewSdkServic
5454
},
5555
onConnectedDevicesChange: (connectedDevices: ConnectedDevices) => ({ }),
5656
onLogMessage: (log: string, deviceName: string) => {
57-
this.$logger.trace(`device name: ${deviceName} log: ${log}`);
57+
this.$logger.info(`LOG from device ${deviceName}: ${log}`);
5858
},
5959
onRestartMessage: () => {
6060
console.log("ON RESTART MESSAGE!!!");
6161
},
6262
onUncaughtErrorMessage: () => {
6363
this.$errors.failWithoutHelp("UncaughtErrorMessage while preview app!!");
6464
},
65-
onDeviceConnected: (deviceConnectedMessage: DeviceConnectedMessage) => {
66-
this.emit(PreviewSdkEventNames.DEVICE_CONNECTED, deviceConnectedMessage);
67-
this.connectedDevices.push(deviceConnectedMessage);
65+
onDeviceConnectedMessage: (deviceConnectedMessage: DeviceConnectedMessage) => ({ }),
66+
onDeviceConnected: (device: Device) => {
67+
this.emit(PreviewSdkEventNames.DEVICE_CONNECTED, device);
68+
this.connectedDevices.push(device);
6869
},
6970
onDevicesPresence: (devices: Device[]) => {
70-
this.connectedDevices.forEach(connectedDevice => {
71-
const device = _.find(devices, d => d.id === connectedDevice.deviceId);
72-
if (!device) {
73-
_.remove(this.connectedDevices, d => d.deviceId === connectedDevice.deviceId);
74-
}
75-
});
7671
},
7772
onSendingChange: (sending: boolean) => ({ })
7873
};

lib/services/platform-environment-requirements.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { NATIVESCRIPT_CLOUD_EXTENSION_NAME, TrackActionNames } from "../constants";
22
import { isInteractive } from "../common/helpers";
33
import { EOL } from "os";
4+
import { cache } from "../common/decorators";
45

56
export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequirements {
67
constructor(private $commandsService: ICommandsService,
@@ -10,11 +11,18 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
1011
private $nativeScriptCloudExtensionService: INativeScriptCloudExtensionService,
1112
private $prompter: IPrompter,
1213
private $staticConfig: IStaticConfig,
13-
private $analyticsService: IAnalyticsService) { }
14+
private $analyticsService: IAnalyticsService,
15+
private $injector: IInjector) { }
16+
17+
@cache()
18+
private get $previewAppLiveSyncService(): IPreviewAppLiveSyncService {
19+
return this.$injector.resolve("previewAppLiveSyncService");
20+
}
1421

1522
public static CLOUD_SETUP_OPTION_NAME = "Configure for Cloud Builds";
1623
public static LOCAL_SETUP_OPTION_NAME = "Configure for Local Builds";
1724
public static TRY_CLOUD_OPERATION_OPTION_NAME = "Try Cloud Operation";
25+
public static SYNC_TO_PREVIEW_APP_OPTION_NAME = "Sync to Playground";
1826
public static MANUALLY_SETUP_OPTION_NAME = "Skip Step and Configure Manually";
1927
private static BOTH_CLOUD_SETUP_AND_LOCAL_SETUP_OPTION_NAME = "Configure for Both Local and Cloud Builds";
2028
private static CHOOSE_OPTIONS_MESSAGE = "To continue, choose one of the following options: ";
@@ -23,6 +31,8 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
2331
private static MISSING_LOCAL_AND_CLOUD_SETUP_MESSAGE = `You are missing the ${NATIVESCRIPT_CLOUD_EXTENSION_NAME} extension and you will not be able to execute cloud builds. ${PlatformEnvironmentRequirements.MISSING_LOCAL_SETUP_MESSAGE} ${PlatformEnvironmentRequirements.CHOOSE_OPTIONS_MESSAGE} `;
2432
private static MISSING_LOCAL_BUT_CLOUD_SETUP_MESSAGE = `You have ${NATIVESCRIPT_CLOUD_EXTENSION_NAME} extension installed, so you can execute cloud builds, but ${_.lowerFirst(PlatformEnvironmentRequirements.MISSING_LOCAL_SETUP_MESSAGE)}`;
2533
private static RUN_TNS_SETUP_MESSAGE = 'Run $ tns setup command to run the setup script to try to automatically configure your environment for local builds.';
34+
private static SYNC_TO_PREVIEW_APP_MESSAGE = `Select "Sync to Playground" to enjoy NativeScript without any local setup. All you need is a couple of companion apps installed on you devices.`;
35+
private static RUN_PREVIEW_COMMAND_MESSAGE = `Run $ tns preview command to enjoy NativeScript without any local setup.`;
2636

2737
private cliCommandToCloudCommandName: IStringDictionary = {
2838
"build": "tns cloud build",
@@ -53,10 +63,12 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
5363
this.$logger.info(infoMessage);
5464

5565
const choices = this.$nativeScriptCloudExtensionService.isInstalled() ? [
66+
PlatformEnvironmentRequirements.SYNC_TO_PREVIEW_APP_OPTION_NAME,
5667
PlatformEnvironmentRequirements.TRY_CLOUD_OPERATION_OPTION_NAME,
5768
PlatformEnvironmentRequirements.LOCAL_SETUP_OPTION_NAME,
5869
PlatformEnvironmentRequirements.MANUALLY_SETUP_OPTION_NAME,
5970
] : [
71+
PlatformEnvironmentRequirements.SYNC_TO_PREVIEW_APP_OPTION_NAME,
6072
PlatformEnvironmentRequirements.CLOUD_SETUP_OPTION_NAME,
6173
PlatformEnvironmentRequirements.LOCAL_SETUP_OPTION_NAME,
6274
PlatformEnvironmentRequirements.BOTH_CLOUD_SETUP_AND_LOCAL_SETUP_OPTION_NAME,
@@ -67,6 +79,7 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
6779

6880
await this.processCloudBuildsIfNeeded(selectedOption, platform);
6981
this.processManuallySetupIfNeeded(selectedOption, platform);
82+
await this.processSyncToPreviewAppIfNeeded(selectedOption, projectDir);
7083

7184
if (selectedOption === PlatformEnvironmentRequirements.LOCAL_SETUP_OPTION_NAME) {
7285
await this.$doctorService.runSetupScript();
@@ -155,6 +168,23 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
155168
}
156169
}
157170

171+
private async processSyncToPreviewAppIfNeeded(selectedOption: string, projectDir: string) {
172+
if (selectedOption === PlatformEnvironmentRequirements.SYNC_TO_PREVIEW_APP_OPTION_NAME) {
173+
if (!projectDir) {
174+
this.$errors.failWithoutHelp(`No project found. In order to sync to playground you need to go to project directory or specify --path option.`);
175+
}
176+
177+
await this.$previewAppLiveSyncService.initialSync({
178+
projectDir,
179+
appFilesUpdaterOptions: {
180+
bundle: false,
181+
release: false
182+
},
183+
env: null
184+
});
185+
}
186+
}
187+
158188
private processManuallySetup(platform?: string): void {
159189
this.fail(`To be able to ${platform ? `build for ${platform}` : 'build'}, verify that your environment is configured according to the system requirements described at ${this.$staticConfig.SYS_REQUIREMENTS_LINK}. In case you have any questions, you can check our forum: 'http://forum.nativescript.org' and our public Slack channel: 'https://nativescriptcommunity.slack.com/'.`);
160190
}
@@ -177,12 +207,14 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
177207
return this.$nativeScriptCloudExtensionService.isInstalled() ?
178208
this.buildMultilineMessage([
179209
`${PlatformEnvironmentRequirements.MISSING_LOCAL_SETUP_MESSAGE} ${PlatformEnvironmentRequirements.CHOOSE_OPTIONS_MESSAGE}`,
210+
PlatformEnvironmentRequirements.RUN_PREVIEW_COMMAND_MESSAGE,
180211
PlatformEnvironmentRequirements.RUN_TNS_SETUP_MESSAGE,
181212
this.getCloudBuildsMessage(platform),
182213
this.getEnvVerificationMessage()
183214
]) :
184215
this.buildMultilineMessage([
185216
PlatformEnvironmentRequirements.MISSING_LOCAL_AND_CLOUD_SETUP_MESSAGE,
217+
PlatformEnvironmentRequirements.RUN_PREVIEW_COMMAND_MESSAGE,
186218
PlatformEnvironmentRequirements.RUN_TNS_SETUP_MESSAGE,
187219
`Run $ tns cloud setup command to install the ${NATIVESCRIPT_CLOUD_EXTENSION_NAME} extension to configure your environment for cloud builds.`,
188220
this.getEnvVerificationMessage()
@@ -193,11 +225,13 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
193225
return this.$nativeScriptCloudExtensionService.isInstalled() ?
194226
this.buildMultilineMessage([
195227
`${PlatformEnvironmentRequirements.MISSING_LOCAL_BUT_CLOUD_SETUP_MESSAGE} ${PlatformEnvironmentRequirements.CHOOSE_OPTIONS_MESSAGE}`,
228+
PlatformEnvironmentRequirements.SYNC_TO_PREVIEW_APP_MESSAGE,
196229
`Select "Configure for Local Builds" to run the setup script and automatically configure your environment for local builds.`,
197230
`Select "Skip Step and Configure Manually" to disregard this option and install any required components manually.`
198231
]) :
199232
this.buildMultilineMessage([
200233
PlatformEnvironmentRequirements.MISSING_LOCAL_AND_CLOUD_SETUP_MESSAGE,
234+
PlatformEnvironmentRequirements.SYNC_TO_PREVIEW_APP_MESSAGE,
201235
`Select "Configure for Cloud Builds" to install the ${NATIVESCRIPT_CLOUD_EXTENSION_NAME} extension and automatically configure your environment for cloud builds.`,
202236
`Select "Configure for Local Builds" to run the setup script and automatically configure your environment for local builds.`,
203237
`Select "Configure for Both Local and Cloud Builds" to automatically configure your environment for both options.`,

test/services/livesync-service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const createTestInjector = (): IInjector => {
3636
iOS: "iOS"
3737
}
3838
});
39+
testInjector.register("previewAppLiveSyncService", {});
3940

4041
return testInjector;
4142
};

test/services/platform-environment-requirements.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import { EOL } from "os";
77
const platform = "android";
88
const cloudBuildsErrorMessage = `In order to test your application use the $ tns login command to log in with your account and then $ tns cloud build command to build your app in the cloud.`;
99
const manuallySetupErrorMessage = `To be able to build for ${platform}, verify that your environment is configured according to the system requirements described at `;
10-
const nonInteractiveConsoleMessageWhenExtensionIsNotInstalled = `You are missing the nativescript-cloud extension and you will not be able to execute cloud builds. Your environment is not configured properly and you will not be able to execute local builds. To continue, choose one of the following options: ${EOL}Run $ tns setup command to run the setup script to try to automatically configure your environment for local builds.${EOL}Run $ tns cloud setup command to install the nativescript-cloud extension to configure your environment for cloud builds.${EOL}Verify that your environment is configured according to the system requirements described at `;
11-
const nonInteractiveConsoleMessageWhenExtensionIsInstalled = `Your environment is not configured properly and you will not be able to execute local builds. To continue, choose one of the following options: ${EOL}Run $ tns setup command to run the setup script to try to automatically configure your environment for local builds.${EOL}In order to test your application use the $ tns login command to log in with your account and then $ tns cloud build command to build your app in the cloud.${EOL}Verify that your environment is configured according to the system requirements described at .`;
10+
const nonInteractiveConsoleMessageWhenExtensionIsNotInstalled = `You are missing the nativescript-cloud extension and you will not be able to execute cloud builds. Your environment is not configured properly and you will not be able to execute local builds. To continue, choose one of the following options: ${EOL}Run $ tns preview command to enjoy NativeScript without any local setup.${EOL}Run $ tns setup command to run the setup script to try to automatically configure your environment for local builds.${EOL}Run $ tns cloud setup command to install the nativescript-cloud extension to configure your environment for cloud builds.${EOL}Verify that your environment is configured according to the system requirements described at `;
11+
const nonInteractiveConsoleMessageWhenExtensionIsInstalled = `Your environment is not configured properly and you will not be able to execute local builds. To continue, choose one of the following options: ${EOL}Run $ tns preview command to enjoy NativeScript without any local setup.${EOL}Run $ tns setup command to run the setup script to try to automatically configure your environment for local builds.${EOL}In order to test your application use the $ tns login command to log in with your account and then $ tns cloud build command to build your app in the cloud.${EOL}Verify that your environment is configured according to the system requirements described at .`;
1212

1313
function createTestInjector() {
1414
const testInjector = new Yok();
@@ -96,7 +96,7 @@ describe("platformEnvironmentRequirements ", () => {
9696
assert.isTrue(promptForChoiceData.length === 1);
9797
assert.isTrue(isExtensionInstallCalled);
9898
assert.deepEqual("To continue, choose one of the following options: ", promptForChoiceData[0].message);
99-
assert.deepEqual(['Configure for Cloud Builds', 'Configure for Local Builds', 'Configure for Both Local and Cloud Builds', 'Skip Step and Configure Manually'], promptForChoiceData[0].choices);
99+
assert.deepEqual(['Sync to Playground', 'Configure for Cloud Builds', 'Configure for Local Builds', 'Configure for Both Local and Cloud Builds', 'Skip Step and Configure Manually'], promptForChoiceData[0].choices);
100100
});
101101
it("should show prompt when environment is not configured and nativescript-cloud extension is installed", async () => {
102102
mockDoctorService({ canExecuteLocalBuild: false });
@@ -106,7 +106,7 @@ describe("platformEnvironmentRequirements ", () => {
106106
await assert.isRejected(platformEnvironmentRequirements.checkEnvironmentRequirements(platform));
107107
assert.isTrue(promptForChoiceData.length === 1);
108108
assert.deepEqual("To continue, choose one of the following options: ", promptForChoiceData[0].message);
109-
assert.deepEqual(['Try Cloud Operation', 'Configure for Local Builds', 'Skip Step and Configure Manually'], promptForChoiceData[0].choices);
109+
assert.deepEqual(['Sync to Playground', 'Try Cloud Operation', 'Configure for Local Builds', 'Skip Step and Configure Manually'], promptForChoiceData[0].choices);
110110
});
111111
it("should skip env chech when NS_SKIP_ENV_CHECK environment variable is passed", async() => {
112112
process.env.NS_SKIP_ENV_CHECK = true;

0 commit comments

Comments
 (0)