Skip to content

Commit c91958d

Browse files
committed
Fix "Cannot find connected devices" error when the env is not properly configured and "Sync to Playground" option is selected
1 parent e7edf2d commit c91958d

File tree

11 files changed

+74
-21
lines changed

11 files changed

+74
-21
lines changed

lib/bootstrap.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ $injector.require("androidLiveSyncService", "./services/livesync/android-livesyn
130130
$injector.require("iOSLiveSyncService", "./services/livesync/ios-livesync-service");
131131
$injector.require("usbLiveSyncService", "./services/livesync/livesync-service"); // The name is used in https://github.com/NativeScript/nativescript-dev-typescript
132132
$injector.require("previewAppLiveSyncService", "./services/livesync/playground/preview-app-livesync-service");
133+
$injector.require("previewAppPluginsService", "./services/livesync/playground/preview-app-plugins-service");
133134
$injector.require("previewSdkService", "./services/livesync/playground/preview-sdk-service");
134135
$injector.requirePublic("sysInfo", "./sys-info");
135136

lib/commands/run.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ANDROID_RELEASE_BUILD_ERROR_MESSAGE } from "../constants";
33
import { cache } from "../common/decorators";
44

55
export class RunCommandBase implements ICommand {
6+
private liveSyncCommandHelperAdditionalOptions: ILiveSyncCommandHelperAdditionalOptions = <ILiveSyncCommandHelperAdditionalOptions>{};
67

78
public platform: string;
89
constructor(private $projectData: IProjectData,
@@ -13,7 +14,7 @@ export class RunCommandBase implements ICommand {
1314

1415
public allowedParameters: ICommandParameter[] = [];
1516
public async execute(args: string[]): Promise<void> {
16-
return this.$liveSyncCommandHelper.executeCommandLiveSync(this.platform);
17+
return this.$liveSyncCommandHelper.executeCommandLiveSync(this.platform, this.liveSyncCommandHelperAdditionalOptions);
1718
}
1819

1920
public async canExecute(args: string[]): Promise<boolean> {
@@ -28,7 +29,11 @@ export class RunCommandBase implements ICommand {
2829
this.platform = this.$devicePlatformsConstants.Android;
2930
}
3031

31-
await this.$liveSyncCommandHelper.validatePlatform(this.platform);
32+
const validatePlatformOutput = await this.$liveSyncCommandHelper.validatePlatform(this.platform);
33+
if (validatePlatformOutput && validatePlatformOutput[this.platform.toLowerCase()]) {
34+
const checkEnvironmentRequirementsOutput = validatePlatformOutput[this.platform.toLowerCase()].checkEnvironmentRequirementsOutput;
35+
this.liveSyncCommandHelperAdditionalOptions.syncToPreviewApp = checkEnvironmentRequirementsOutput && checkEnvironmentRequirementsOutput.selectedOption === "Sync to Playground";
36+
}
3237

3338
return true;
3439
}
@@ -68,7 +73,8 @@ export class RunIosCommand implements ICommand {
6873
}
6974

7075
public async canExecute(args: string[]): Promise<boolean> {
71-
return await this.runCommand.canExecute(args) && await this.$platformService.validateOptions(this.$options.provision, this.$options.teamId, this.$projectData, this.$platformsData.availablePlatforms.iOS);
76+
const result = await this.runCommand.canExecute(args) && await this.$platformService.validateOptions(this.$options.provision, this.$options.teamId, this.$projectData, this.$platformsData.availablePlatforms.iOS);
77+
return result;
7278
}
7379
}
7480

@@ -110,6 +116,7 @@ export class RunAndroidCommand implements ICommand {
110116
if (this.$options.release && (!this.$options.keyStorePath || !this.$options.keyStorePassword || !this.$options.keyStoreAlias || !this.$options.keyStoreAliasPassword)) {
111117
this.$errors.fail(ANDROID_RELEASE_BUILD_ERROR_MESSAGE);
112118
}
119+
113120
return this.$platformService.validateOptions(this.$options.provision, this.$options.teamId, this.$projectData, this.$platformsData.availablePlatforms.Android);
114121
}
115122
}

lib/definitions/livesync.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ interface ILiveSyncCommandHelperAdditionalOptions extends IBuildPlatformAction,
524524
* @returns {string} The build output directory.
525525
*/
526526
getOutputDirectory?(options: IOutputDirectoryOptions): string;
527+
syncToPreviewApp?: boolean;
527528
}
528529

529530
interface ILiveSyncCommandHelper {
@@ -542,7 +543,7 @@ interface ILiveSyncCommandHelper {
542543
* @param {string} platform The platform to be validated.
543544
* @return {Promise<void>}
544545
*/
545-
validatePlatform(platform: string): Promise<void>;
546+
validatePlatform(platform: string): Promise<IDictionary<IValidateOutput>>;
546547

547548
/**
548549
* Executes livesync operation. Meant to be called from within a command.

lib/definitions/platform.d.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,5 +391,10 @@ interface IUpdateAppOptions extends IOptionalFilesToSync, IOptionalFilesToRemove
391391
}
392392

393393
interface IPlatformEnvironmentRequirements {
394-
checkEnvironmentRequirements(platform?: string, projectDir?: string, runtimeVersion?: string): Promise<boolean>;
394+
checkEnvironmentRequirements(platform?: string, projectDir?: string, runtimeVersion?: string): Promise<ICheckEnvironmentRequirementsOutput>;
395+
}
396+
397+
interface ICheckEnvironmentRequirementsOutput {
398+
canExecute: boolean;
399+
selectedOption: string;
395400
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,8 @@ declare global {
1616
applyChanges(files: FilePayload[]): Promise<void>;
1717
stop(): void;
1818
}
19+
20+
interface IPreviewAppPluginsService {
21+
comparePluginsOnDevice(device: Device): Promise<void>;
22+
}
1923
}

lib/definitions/project.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ interface ICleanNativeAppData extends IProjectDir, IPlatform { }
319319

320320
interface IPlatformProjectService extends NodeJS.EventEmitter, IPlatformProjectServiceBase {
321321
getPlatformData(projectData: IProjectData): IPlatformData;
322-
validate(projectData: IProjectData): Promise<void>;
322+
validate(projectData: IProjectData): Promise<IValidateOutput>;
323323
createProject(frameworkDir: string, frameworkVersion: string, projectData: IProjectData, config: ICreateProjectOptions): Promise<void>;
324324
interpolateData(projectData: IProjectData, platformSpecificData: IPlatformSpecificData): Promise<void>;
325325
interpolateConfigurationFile(projectData: IProjectData, platformSpecificData: IPlatformSpecificData): void;
@@ -438,6 +438,10 @@ interface IPlatformProjectService extends NodeJS.EventEmitter, IPlatformProjectS
438438
checkIfPluginsNeedBuild(projectData: IProjectData): Promise<Array<any>>;
439439
}
440440

441+
interface IValidateOutput {
442+
checkEnvironmentRequirementsOutput: ICheckEnvironmentRequirementsOutput;
443+
}
444+
441445
interface ITestExecutionService {
442446
startTestRunner(platform: string, projectData: IProjectData, projectFilesConfig: IProjectFilesConfig): Promise<void>;
443447
startKarmaServer(platform: string, projectData: IProjectData, projectFilesConfig: IProjectFilesConfig): Promise<void>;

lib/helpers/livesync-command-helper.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export class LiveSyncCommandHelper implements ILiveSyncCommandHelper {
2626
this.$logger.info("Skipping node_modules folder! Use the syncAllFiles option to sync files from this folder.");
2727
}
2828

29+
if (additionalOptions && additionalOptions.syncToPreviewApp) {
30+
return;
31+
}
32+
2933
const emulator = this.$options.emulator;
3034
await this.$devicesService.initialize({
3135
deviceId: this.$options.device,
@@ -123,15 +127,20 @@ export class LiveSyncCommandHelper implements ILiveSyncCommandHelper {
123127
await this.$liveSyncService.liveSync(deviceDescriptors, liveSyncInfo);
124128
}
125129

126-
public async validatePlatform(platform: string) {
130+
public async validatePlatform(platform: string): Promise<IDictionary<IValidateOutput>> {
131+
const result: IDictionary<IValidateOutput> = {};
132+
127133
const availablePlatforms = this.getPlatformsForOperation(platform);
128134
for (const availablePlatform of availablePlatforms) {
129135
const platformData = this.$platformsData.getPlatformData(availablePlatform, this.$projectData);
130136
const platformProjectService = platformData.platformProjectService;
131-
await platformProjectService.validate(this.$projectData);
137+
const validateOutput = await platformProjectService.validate(this.$projectData);
138+
result[availablePlatform.toLowerCase()] = validateOutput;
132139
}
133140

134141
this.$bundleValidatorHelper.validate();
142+
143+
return result;
135144
}
136145

137146
private async runInReleaseMode(platform: string, additionalOptions?: ILiveSyncCommandHelperAdditionalOptions): Promise<void> {

lib/services/android-project-service.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,16 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
118118
}
119119
}
120120

121-
public async validate(projectData: IProjectData): Promise<void> {
121+
public async validate(projectData: IProjectData): Promise<IValidateOutput> {
122122
this.validatePackageName(projectData.projectId);
123123
this.validateProjectName(projectData.projectName);
124124

125-
await this.$platformEnvironmentRequirements.checkEnvironmentRequirements(this.getPlatformData(projectData).normalizedPlatformName, projectData.projectDir);
125+
const checkEnvironmentRequirementsOutput = await this.$platformEnvironmentRequirements.checkEnvironmentRequirements(this.getPlatformData(projectData).normalizedPlatformName, projectData.projectDir);
126126
this.$androidToolsInfo.validateTargetSdk({ showWarningsAsErrors: true });
127+
128+
return {
129+
checkEnvironmentRequirementsOutput
130+
};
127131
}
128132

129133
public async validatePlugins(): Promise<void> { /* */ }

lib/services/ios-project-service.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,17 +133,21 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
133133
return path.join(this.getPlatformData(projectData).projectRoot, projectData.projectName, "Resources");
134134
}
135135

136-
public async validate(projectData: IProjectData): Promise<void> {
136+
public async validate(projectData: IProjectData): Promise<IValidateOutput> {
137137
if (!this.$hostInfo.isDarwin) {
138138
return;
139139
}
140140

141-
await this.$platformEnvironmentRequirements.checkEnvironmentRequirements(this.getPlatformData(projectData).normalizedPlatformName, projectData.projectDir);
141+
const checkEnvironmentRequirementsOutput = await this.$platformEnvironmentRequirements.checkEnvironmentRequirements(this.getPlatformData(projectData).normalizedPlatformName, projectData.projectDir);
142142

143143
const xcodeBuildVersion = await this.getXcodeVersion();
144144
if (helpers.versionCompare(xcodeBuildVersion, IOSProjectService.XCODEBUILD_MIN_VERSION) < 0) {
145145
this.$errors.fail("NativeScript can only run in Xcode version %s or greater", IOSProjectService.XCODEBUILD_MIN_VERSION);
146146
}
147+
148+
return {
149+
checkEnvironmentRequirementsOutput
150+
};
147151
}
148152

149153
// TODO: Remove Promise, reason: readDirectory - unable until androidProjectService has async operations.

lib/services/platform-environment-requirements.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
3131
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} `;
3232
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)}`;
3333
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.`;
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 your devices.`;
3535
private static RUN_PREVIEW_COMMAND_MESSAGE = `Run $ tns preview command to enjoy NativeScript without any local setup.`;
3636

3737
private cliCommandToCloudCommandName: IStringDictionary = {
@@ -40,13 +40,18 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
4040
"deploy": "tns cloud deploy"
4141
};
4242

43-
public async checkEnvironmentRequirements(platform?: string, projectDir?: string, runtimeVersion?: string): Promise<boolean> {
43+
public async checkEnvironmentRequirements(platform?: string, projectDir?: string, runtimeVersion?: string): Promise<ICheckEnvironmentRequirementsOutput> {
44+
let selectedOption = null;
45+
4446
if (process.env.NS_SKIP_ENV_CHECK) {
4547
await this.$analyticsService.trackEventActionInGoogleAnalytics({
4648
action: TrackActionNames.CheckEnvironmentRequirements,
4749
additionalData: "Skipped: NS_SKIP_ENV_CHECK is set"
4850
});
49-
return true;
51+
return {
52+
canExecute: true,
53+
selectedOption
54+
};
5055
}
5156

5257
const canExecute = await this.$doctorService.canExecuteLocalBuild(platform, projectDir, runtimeVersion);
@@ -75,7 +80,7 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
7580
PlatformEnvironmentRequirements.MANUALLY_SETUP_OPTION_NAME,
7681
];
7782

78-
const selectedOption = await this.promptForChoice({ infoMessage, choices });
83+
selectedOption = await this.promptForChoice({ infoMessage, choices });
7984

8085
await this.processCloudBuildsIfNeeded(selectedOption, platform);
8186
this.processManuallySetupIfNeeded(selectedOption, platform);
@@ -85,7 +90,10 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
8590
await this.$doctorService.runSetupScript();
8691

8792
if (await this.$doctorService.canExecuteLocalBuild(platform, projectDir, runtimeVersion)) {
88-
return true;
93+
return {
94+
canExecute: true,
95+
selectedOption
96+
};
8997
}
9098

9199
if (this.$nativeScriptCloudExtensionService.isInstalled()) {
@@ -116,7 +124,10 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
116124
if (selectedOption === PlatformEnvironmentRequirements.BOTH_CLOUD_SETUP_AND_LOCAL_SETUP_OPTION_NAME) {
117125
await this.processBothCloudBuildsAndSetupScript();
118126
if (await this.$doctorService.canExecuteLocalBuild(platform, projectDir, runtimeVersion)) {
119-
return true;
127+
return {
128+
canExecute: true,
129+
selectedOption
130+
};
120131
}
121132

122133
this.processManuallySetup(platform);
@@ -125,7 +136,10 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
125136
this.processTryCloudSetupIfNeeded(selectedOption, platform);
126137
}
127138

128-
return true;
139+
return {
140+
canExecute,
141+
selectedOption
142+
};
129143
}
130144

131145
private async processCloudBuildsIfNeeded(selectedOption: string, platform?: string): Promise<void> {

0 commit comments

Comments
 (0)