Skip to content

fix (getting started): Improve behaviour when nativescript-cloud is installed #3495

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ $injector.require("terminalSpinnerService", "./services/terminal-spinner-service

$injector.require('playgroundService', './services/playground-service');
$injector.require("platformEnvironmentRequirements", "./services/platform-environment-requirements");
$injector.require("nativescriptCloudExtensionService", "./services/nativescript-cloud-extension-service");
$injector.require("nativeScriptCloudExtensionService", "./services/nativescript-cloud-extension-service");

$injector.requireCommand("resources|generate|icons", "./commands/generate-assets");
$injector.requireCommand("resources|generate|splashes", "./commands/generate-assets");
Expand Down
4 changes: 2 additions & 2 deletions lib/commands/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ $injector.registerCommand("setup|*", SetupCommand);
export class CloudSetupCommand implements ICommand {
public allowedParameters: ICommandParameter[] = [];

constructor(private $nativescriptCloudExtensionService: INativescriptCloudExtensionService) { }
constructor(private $nativeScriptCloudExtensionService: INativeScriptCloudExtensionService) { }

public execute(args: string[]): Promise<any> {
return this.$nativescriptCloudExtensionService.install();
return this.$nativeScriptCloudExtensionService.install();
}
}
$injector.registerCommand(["setup|cloud", "cloud|setup"], CloudSetupCommand);
7 changes: 6 additions & 1 deletion lib/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -788,12 +788,17 @@ interface IBundleValidatorHelper {
validate(): void;
}

interface INativescriptCloudExtensionService {
interface INativeScriptCloudExtensionService {
/**
* Installs nativescript-cloud extension
* @return {Promise<IExtensionData>} returns the extension data
*/
install(): Promise<IExtensionData>;
/**
* Checks if nativescript-cloud extension is installed
* @return {boolean} returns true in case when nativescript-cloud extension is installed, false otherwise
*/
isInstalled(): boolean
}

/**
Expand Down
30 changes: 24 additions & 6 deletions lib/services/nativescript-cloud-extension-service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
import * as constants from "../constants";
import * as semver from "semver";

export class NativescriptCloudExtensionService implements INativescriptCloudExtensionService {

export class NativeScriptCloudExtensionService implements INativeScriptCloudExtensionService {
constructor(private $extensibilityService: IExtensibilityService,
private $logger: ILogger) { }
private $logger: ILogger,
private $npmInstallationManager: INpmInstallationManager) { }

public install(): Promise<IExtensionData> {
const installedExtensions = this.$extensibilityService.getInstalledExtensions() || {};
if (!installedExtensions[constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME]) {
if (!this.isInstalled()) {
return this.$extensibilityService.installExtension(constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME);
}

this.$logger.out(`Extension ${constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME} is already installed.`);
}

public isInstalled(): boolean {
return !!this.getExtensionData();
}

public async isLatestVersionInstalled(): Promise<boolean> {
const extensionData = this.getExtensionData();
if (extensionData) {
const latestVersion = await this.$npmInstallationManager.getLatestVersion(constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME);
return semver.eq(latestVersion, extensionData.version);
}

return false;
}

private getExtensionData(): IExtensionData {
return _.find(this.$extensibilityService.getInstalledExtensionsData(), extensionData => extensionData.extensionName === constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME);
}
}
$injector.register("nativescriptCloudExtensionService", NativescriptCloudExtensionService);
$injector.register("nativeScriptCloudExtensionService", NativeScriptCloudExtensionService);
119 changes: 85 additions & 34 deletions lib/services/platform-environment-requirements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
constructor(private $commandsService: ICommandsService,
private $doctorService: IDoctorService,
private $errors: IErrors,
private $nativescriptCloudExtensionService: INativescriptCloudExtensionService,
private $logger: ILogger,
private $nativeScriptCloudExtensionService: INativeScriptCloudExtensionService,
private $prompter: IPrompter,
private $staticConfig: IStaticConfig) { }

public static CLOUD_BUILDS_OPTION_NAME = "Configure for Cloud Builds";
public static SETUP_SCRIPT_OPTION_NAME = "Configure for Local Builds";
public static CLOUD_SETUP_OPTION_NAME = "Configure for Cloud Builds";
public static LOCAL_SETUP_OPTION_NAME = "Configure for Local Builds";
public static MANUALLY_SETUP_OPTION_NAME = "Skip Step and Configure Manually";
private static BOTH_CLOUD_BUILDS_AND_SETUP_SCRIPT_OPTION_NAME = "Configure for Both Local and Cloud Builds";
private static NOT_CONFIGURED_ENV_MESSAGE = "To continue, choose one of the following options: ";
private static NOT_CONFIGURED_ENV_AFTER_SETUP_SCRIPT_MESSAGE = "The setup script was not able to configure your environment for local builds. To execute local builds, you have to set up your environment manually. To continue, choose one of the following options:";
private static BOTH_CLOUD_SETUP_AND_LOCAL_SETUP_OPTION_NAME = "Configure for Both Local and Cloud Builds";
private static CHOOSE_OPTIONS_MESSAGE = "To continue, choose one of the following options: ";
private static NOT_CONFIGURED_ENV_AFTER_SETUP_SCRIPT_MESSAGE = `The setup script was not able to configure your environment for local builds. To execute local builds, you have to set up your environment manually. In case you have any questions, you can check our forum: 'http://forum.nativescript.org' and our public Slack channel: 'https://nativescriptcommunity.slack.com/'. ${PlatformEnvironmentRequirements.CHOOSE_OPTIONS_MESSAGE}`;
private static MISSING_LOCAL_SETUP_MESSAGE = "Your environment is not configured properly and you will not be able to execute local builds.";
private static MISSING_LOCAL_AND_CLOUD_SETUP_MESSAGE = `You are missing the ${constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME} extension and you will not be able to execute cloud builds. ${PlatformEnvironmentRequirements.MISSING_LOCAL_SETUP_MESSAGE} ${PlatformEnvironmentRequirements.CHOOSE_OPTIONS_MESSAGE} `;
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.';

private cliCommandToCloudCommandName: IStringDictionary = {
"build": "tns cloud build",
Expand All @@ -32,47 +35,38 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
const canExecute = await this.$doctorService.canExecuteLocalBuild(platform);
if (!canExecute) {
if (!isInteractive()) {
this.fail(`You are missing the ${constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME} 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 ${constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME} extension to configure your environment for cloud builds.` + EOL
+ `Verify that your environment is configured according to the system requirements described at ${this.$staticConfig.SYS_REQUIREMENTS_LINK}`);
this.fail(this.getNonInteractiveConsoleMessage(platform));
}

this.$logger.info(`You are missing the ${constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME} 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. ` + EOL
+ `Select "Configure for Cloud Builds" to install the ${constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME} extension and automatically configure your environment for cloud builds.` + EOL
+ `Select "Configure for Local Builds" to run the setup script and automatically configure your environment for local builds.`
+ `Select "Configure for Both Local and Cloud Builds" to automatically configure your environment for both options.`
+ `Select "Skip Step and Configure Manually" to disregard these options and install any required components manually.`);

const selectedOption = await this.$prompter.promptForChoice(PlatformEnvironmentRequirements.NOT_CONFIGURED_ENV_MESSAGE, [
PlatformEnvironmentRequirements.CLOUD_BUILDS_OPTION_NAME,
PlatformEnvironmentRequirements.SETUP_SCRIPT_OPTION_NAME,
PlatformEnvironmentRequirements.BOTH_CLOUD_BUILDS_AND_SETUP_SCRIPT_OPTION_NAME,
PlatformEnvironmentRequirements.MANUALLY_SETUP_OPTION_NAME,
]);
this.$logger.info(this.getInteractiveConsoleMessage(platform));

await this.processCloudBuildsIfNeeded(platform, selectedOption);
const selectedOption = await this.promptForChoice();

await this.processCloudBuildsIfNeeded(platform, selectedOption);
this.processManuallySetupIfNeeded(platform, selectedOption);

if (selectedOption === PlatformEnvironmentRequirements.SETUP_SCRIPT_OPTION_NAME) {
if (selectedOption === PlatformEnvironmentRequirements.LOCAL_SETUP_OPTION_NAME) {
await this.$doctorService.runSetupScript();

if (await this.$doctorService.canExecuteLocalBuild(platform)) {
return true;
}

const option = await this.$prompter.promptForChoice(PlatformEnvironmentRequirements.NOT_CONFIGURED_ENV_AFTER_SETUP_SCRIPT_MESSAGE, [
PlatformEnvironmentRequirements.CLOUD_BUILDS_OPTION_NAME,
PlatformEnvironmentRequirements.MANUALLY_SETUP_OPTION_NAME
]);
if (this.$nativeScriptCloudExtensionService.isInstalled()) {
this.processManuallySetup(platform);
} else {
const option = await this.$prompter.promptForChoice(PlatformEnvironmentRequirements.NOT_CONFIGURED_ENV_AFTER_SETUP_SCRIPT_MESSAGE, [
PlatformEnvironmentRequirements.CLOUD_SETUP_OPTION_NAME,
PlatformEnvironmentRequirements.MANUALLY_SETUP_OPTION_NAME
]);

await this.processCloudBuildsIfNeeded(platform, option);
await this.processCloudBuildsIfNeeded(platform, option);

this.processManuallySetupIfNeeded(platform, option);
this.processManuallySetupIfNeeded(platform, option);
}
}

if (selectedOption === PlatformEnvironmentRequirements.BOTH_CLOUD_BUILDS_AND_SETUP_SCRIPT_OPTION_NAME) {
if (selectedOption === PlatformEnvironmentRequirements.BOTH_CLOUD_SETUP_AND_LOCAL_SETUP_OPTION_NAME) {
await this.processBothCloudBuildsAndSetupScript(platform);
if (await this.$doctorService.canExecuteLocalBuild(platform)) {
return true;
Expand All @@ -86,7 +80,7 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
}

private async processCloudBuildsIfNeeded(platform: string, selectedOption: string): Promise<void> {
if (selectedOption === PlatformEnvironmentRequirements.CLOUD_BUILDS_OPTION_NAME) {
if (selectedOption === PlatformEnvironmentRequirements.CLOUD_SETUP_OPTION_NAME) {
await this.processCloudBuilds(platform);
}
}
Expand All @@ -97,10 +91,10 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
}

private processCloudBuildsCore(platform: string): Promise<IExtensionData> {
return this.$nativescriptCloudExtensionService.install();
return this.$nativeScriptCloudExtensionService.install();
}

private getCloudBuildsMessage(platform: string): string {
private getCloudBuildsMessage(platform: string): string {
const cloudCommandName = this.cliCommandToCloudCommandName[this.$commandsService.currentCommandData.commandName];
if (!cloudCommandName) {
return `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.`;
Expand Down Expand Up @@ -136,5 +130,62 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
private fail(message: string): void {
this.$errors.fail({ formatStr: message, suppressCommandHelp: true, printOnStdout: true });
}

private getNonInteractiveConsoleMessage(platform: string) {
return this.$nativeScriptCloudExtensionService.isInstalled() ?
this.buildMultilineMessage([
`${PlatformEnvironmentRequirements.MISSING_LOCAL_SETUP_MESSAGE} ${PlatformEnvironmentRequirements.CHOOSE_OPTIONS_MESSAGE}`,
PlatformEnvironmentRequirements.RUN_TNS_SETUP_MESSAGE,
this.getCloudBuildsMessage(platform),
this.getEnvVerificationMessage()
]) :
this.buildMultilineMessage([
PlatformEnvironmentRequirements.MISSING_LOCAL_AND_CLOUD_SETUP_MESSAGE,
PlatformEnvironmentRequirements.RUN_TNS_SETUP_MESSAGE,
`Run $ tns cloud setup command to install the ${constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME} extension to configure your environment for cloud builds.`,
this.getEnvVerificationMessage()
]);
}

private getInteractiveConsoleMessage(platform: string) {
const message = `The ${constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME} extension is installed and you can ${_.lowerFirst(this.getCloudBuildsMessage(platform))}`;

return this.$nativeScriptCloudExtensionService.isInstalled() ?
this.buildMultilineMessage([
`${message.bold}`,
`${PlatformEnvironmentRequirements.MISSING_LOCAL_SETUP_MESSAGE} ${PlatformEnvironmentRequirements.CHOOSE_OPTIONS_MESSAGE}`,
`Select "Configure for Local Builds" to run the setup script and automatically configure your environment for local builds.`,
`Select "Skip Step and Configure Manually" to disregard this option and install any required components manually.`
]) :
this.buildMultilineMessage([
PlatformEnvironmentRequirements.MISSING_LOCAL_AND_CLOUD_SETUP_MESSAGE,
`Select "Configure for Cloud Builds" to install the ${constants.NATIVESCRIPT_CLOUD_EXTENSION_NAME} extension and automatically configure your environment for cloud builds.`,
`Select "Configure for Local Builds" to run the setup script and automatically configure your environment for local builds.`,
`Select "Configure for Both Local and Cloud Builds" to automatically configure your environment for both options.`,
`Select "Configure for Both Local and Cloud Builds" to automatically configure your environment for both options.`
]);
}

private promptForChoice(): Promise<string> {
const choices = this.$nativeScriptCloudExtensionService.isInstalled() ? [
PlatformEnvironmentRequirements.LOCAL_SETUP_OPTION_NAME,
PlatformEnvironmentRequirements.MANUALLY_SETUP_OPTION_NAME,
] : [
PlatformEnvironmentRequirements.CLOUD_SETUP_OPTION_NAME,
PlatformEnvironmentRequirements.LOCAL_SETUP_OPTION_NAME,
PlatformEnvironmentRequirements.BOTH_CLOUD_SETUP_AND_LOCAL_SETUP_OPTION_NAME,
PlatformEnvironmentRequirements.MANUALLY_SETUP_OPTION_NAME,
];

return this.$prompter.promptForChoice(PlatformEnvironmentRequirements.CHOOSE_OPTIONS_MESSAGE, choices);
}

private getEnvVerificationMessage() {
return `Verify that your environment is configured according to the system requirements described at ${this.$staticConfig.SYS_REQUIREMENTS_LINK}.`;
}

private buildMultilineMessage(parts: string[]): string {
return parts.join(EOL);
}
}
$injector.register("platformEnvironmentRequirements", PlatformEnvironmentRequirements);
Loading