diff --git a/lib/bootstrap.ts b/lib/bootstrap.ts index 0c5124ec0c..afb64b1f7f 100644 --- a/lib/bootstrap.ts +++ b/lib/bootstrap.ts @@ -181,3 +181,5 @@ $injector.require("iOSDebuggerPortService", "./services/ios-debugger-port-servic $injector.require("pacoteService", "./services/pacote-service"); $injector.require("qrCodeTerminalService", "./services/qr-code-terminal-service"); + +$injector.require("networkConnectivityValidator", "./helpers/network-connectivity-validator"); diff --git a/lib/commands/preview.ts b/lib/commands/preview.ts index 4163c3e435..e78433b737 100644 --- a/lib/commands/preview.ts +++ b/lib/commands/preview.ts @@ -3,6 +3,7 @@ export class PreviewCommand implements ICommand { constructor(private $bundleValidatorHelper: IBundleValidatorHelper, private $liveSyncService: ILiveSyncService, + private $networkConnectivityValidator: INetworkConnectivityValidator, private $projectData: IProjectData, private $options: IOptions, private $playgroundQrCodeGenerator: IPlaygroundQrCodeGenerator, @@ -27,6 +28,7 @@ export class PreviewCommand implements ICommand { } public async canExecute(args: string[]): Promise { + await this.$networkConnectivityValidator.validate(); this.$bundleValidatorHelper.validate(); return true; } diff --git a/lib/declarations.d.ts b/lib/declarations.d.ts index 7019f4a098..7b93382430 100644 --- a/lib/declarations.d.ts +++ b/lib/declarations.d.ts @@ -865,4 +865,8 @@ interface IAssetsGenerationService { interface IRuntimeGradleVersions { gradleVersion?: string; gradleAndroidPluginVersion?: string; +} + +interface INetworkConnectivityValidator { + validate(): Promise; } \ No newline at end of file diff --git a/lib/helpers/network-connectivity-validator.ts b/lib/helpers/network-connectivity-validator.ts new file mode 100644 index 0000000000..3e82721cb2 --- /dev/null +++ b/lib/helpers/network-connectivity-validator.ts @@ -0,0 +1,31 @@ +import * as dns from "dns"; + +export class NetworkConnectivityValidator implements INetworkConnectivityValidator { + private static DNS_LOOKUP_URL = "play.nativescript.org"; + private static NO_INTERNET_ERROR_CODE = "ENOTFOUND"; + private static NO_INTERNET_ERROR_MESSAGE = "No internet connection. Check your internet settings and try again."; + + constructor(private $errors: IErrors, + private $logger: ILogger) { } + + public async validate(): Promise { + const isConnected = await this.isConnected(); + if (!isConnected) { + this.$errors.failWithoutHelp(NetworkConnectivityValidator.NO_INTERNET_ERROR_MESSAGE); + } + } + + private isConnected(): Promise { + return new Promise((resolve, reject) => { + dns.lookup(NetworkConnectivityValidator.DNS_LOOKUP_URL, err => { + this.$logger.trace(`Error from dns.lookup is ${err}.`); + if (err && err.code === NetworkConnectivityValidator.NO_INTERNET_ERROR_CODE) { + resolve(false); + } else { + resolve(true); + } + }); + }); + } +} +$injector.register("networkConnectivityValidator", NetworkConnectivityValidator);