UNPKG

nativescript-doctor

Version:

Library that helps identifying if the environment can be used for development of {N} apps.

514 lines (513 loc) 24.3 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const os_1 = require("os"); const path = require("path"); const osenv = require("osenv"); const temp = require("temp"); const semver = require("semver"); const constants_1 = require("./constants"); class SysInfo { constructor(childProcess, fileSystem, helpers, hostInfo, winReg, androidToolsInfo) { this.childProcess = childProcess; this.fileSystem = fileSystem; this.helpers = helpers; this.hostInfo = hostInfo; this.winReg = winReg; this.androidToolsInfo = androidToolsInfo; this.monoVerRegExp = /version (\d+[.]\d+[.]\d+) /gm; this.shouldCache = true; } getJavaCompilerVersion() { return this.getValueForProperty(() => this.javaCompilerVerCache, () => __awaiter(this, void 0, void 0, function* () { const javacVersion = process.env["JAVA_HOME"] ? (yield this.getVersionOfJavaExecutableFromJavaHome(constants_1.Constants.JAVAC_EXECUTABLE_NAME, SysInfo.JAVA_COMPILER_VERSION_REGEXP)) : (yield this.getVersionOfJavaExecutableFromPath(constants_1.Constants.JAVAC_EXECUTABLE_NAME, SysInfo.JAVA_COMPILER_VERSION_REGEXP)); return javacVersion; })); } getJavaVersion() { return this.getValueForProperty(() => this.javaVerCache, () => __awaiter(this, void 0, void 0, function* () { const javaVersion = (yield this.getJavaVersionFromJavaHome()) || (yield this.getJavaVersionFromPath()); return javaVersion; })); } getJavaPath() { return this.getValueForProperty(() => this.javaPathCache, () => __awaiter(this, void 0, void 0, function* () { const javaPath = (yield this.getJavaExecutablePathFromJavaHome(constants_1.Constants.JAVA_EXECUTABLE_NAME)) || (yield this.getJavaExecutablePathFromPath(constants_1.Constants.JAVA_EXECUTABLE_NAME)); return javaPath; })); } getJavaVersionFromPath() { return this.getValueForProperty(() => this.javaVerPathCache, () => { return this.getVersionOfJavaExecutableFromPath(constants_1.Constants.JAVA_EXECUTABLE_NAME, SysInfo.JAVA_VERSION_REGEXP); }); } getJavaVersionFromJavaHome() { return this.getValueForProperty(() => this.javaVerJavaHomeCache, () => { return this.getVersionOfJavaExecutableFromJavaHome(constants_1.Constants.JAVA_EXECUTABLE_NAME, SysInfo.JAVA_VERSION_REGEXP); }); } getXcodeVersion() { return this.getValueForProperty(() => this.xCodeVerCache, () => __awaiter(this, void 0, void 0, function* () { if (this.hostInfo.isDarwin) { const output = yield this.execCommand("xcodebuild -version"); const xcodeVersionMatch = output && output.match(SysInfo.XCODE_VERSION_REGEXP); if (xcodeVersionMatch) { return this.getVersionFromString(output); } } })); } getNodeVersion() { return __awaiter(this, void 0, void 0, function* () { return this.getValueForProperty(() => this.nodeVerCache, () => __awaiter(this, void 0, void 0, function* () { const output = yield this.execCommand("node -v"); if (output) { const version = this.getVersionFromString(output); return version || output; } return null; })); }); } getNpmVersion() { return this.getValueForProperty(() => this.npmVerCache, () => __awaiter(this, void 0, void 0, function* () { const output = yield this.execCommand("npm -v"); return output ? output.split("\n")[0] : null; })); } getNodeGypVersion() { return this.getValueForProperty(() => this.nodeGypVerCache, () => __awaiter(this, void 0, void 0, function* () { const output = yield this.execCommand("node-gyp -v"); return output ? this.getVersionFromString(output) : null; })); } getXcodeprojLocation() { return this.getValueForProperty(() => this.xCodeprojLocationCache, () => __awaiter(this, void 0, void 0, function* () { const output = yield this.execCommand("which xcodeproj"); return output ? output.trim() : null; })); } isITunesInstalled() { return this.getValueForProperty(() => this.iTunesInstalledCache, () => __awaiter(this, void 0, void 0, function* () { if (this.hostInfo.isLinux) { return false; } let coreFoundationDir; let mobileDeviceDir; if (this.hostInfo.isWindows) { const commonProgramFiles = this.hostInfo.isWindows64 ? process.env["CommonProgramFiles(x86)"] : process.env["CommonProgramFiles"]; coreFoundationDir = path.join(commonProgramFiles, "Apple", "Apple Application Support"); mobileDeviceDir = path.join(commonProgramFiles, "Apple", "Mobile Device Support"); } else if (this.hostInfo.isDarwin) { coreFoundationDir = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation"; mobileDeviceDir = "/System/Library/PrivateFrameworks/MobileDevice.framework/MobileDevice"; } return (yield this.fileSystem.exists(coreFoundationDir)) && (yield this.fileSystem.exists(mobileDeviceDir)); })); } getCocoaPodsVersion() { return this.getValueForProperty(() => this.cocoaPodsVerCache, () => __awaiter(this, void 0, void 0, function* () { if (this.hostInfo.isDarwin) { if (this.hostInfo.isDarwin) { const output = yield this.execCommand("pod --version"); const cocoaPodsVersionMatch = output && output.match(SysInfo.VERSION_REGEXP); if (cocoaPodsVersionMatch && cocoaPodsVersionMatch[0]) { return cocoaPodsVersionMatch[0].trim(); } } } })); } getOs() { return this.getValueForProperty(() => this.osCache, () => __awaiter(this, void 0, void 0, function* () { return yield (this.hostInfo.isWindows ? this.winVer() : this.unixVer()); })); } getAdbVersion(pathToAdb) { return this.getValueForProperty(() => this.adbVerCache, () => __awaiter(this, void 0, void 0, function* () { let output = null; pathToAdb = pathToAdb || (yield this.androidToolsInfo.getPathToAdbFromAndroidHome()); if (pathToAdb) { output = yield this.childProcess.spawnFromEvent(pathToAdb, ["version"], "close", { ignoreError: true }); } return output && output.stdout ? this.getVersionFromString(output.stdout) : null; })); } isAndroidInstalled() { return this.getValueForProperty(() => this.androidInstalledCache, () => __awaiter(this, void 0, void 0, function* () { try { const errors = this.androidToolsInfo.validateAndroidHomeEnvVariable(); return errors.length === 0; } catch (err) { return false; } })); } isAndroidSdkConfiguredCorrectly() { return __awaiter(this, void 0, void 0, function* () { return this.getValueForProperty(() => this.isAndroidSdkConfiguredCorrectlyCache, () => __awaiter(this, void 0, void 0, function* () { const output = yield this.childProcess.spawnFromEvent(this.androidToolsInfo.getPathToEmulatorExecutable(), ["-help"], "close", { ignoreError: true }); return output && output.stdout.indexOf("usage: emulator") >= 0; })); }); } getMonoVersion() { return this.getValueForProperty(() => this.monoVerCache, () => __awaiter(this, void 0, void 0, function* () { const output = yield this.execCommand("mono --version"); const match = this.monoVerRegExp.exec(output); return match ? match[1] : null; })); } getGitVersion() { return this.getValueForProperty(() => this.gitVerCache, () => __awaiter(this, void 0, void 0, function* () { const gitPath = yield this.getGitPath(); if (!gitPath) { return null; } const output = yield this.execCommand(`${this.helpers.quoteString(gitPath)} --version`); const matches = SysInfo.GIT_VERSION_REGEXP.exec(output); return matches && matches[1]; })); } getGradleVersion() { return this.getValueForProperty(() => this.gradleVerCache, () => __awaiter(this, void 0, void 0, function* () { const output = yield this.execCommand("gradle -v"); const matches = SysInfo.GRADLE_VERSION_REGEXP.exec(output); return matches && matches[1]; })); } getSysInfo(config) { return __awaiter(this, void 0, void 0, function* () { if (config && config.platform && config.platform.toLowerCase() === constants_1.Constants.ANDROID_PLATFORM_NAME.toLowerCase()) { return Object.assign(yield this.getCommonSysInfo(), yield this.getAndroidSysInfo(config)); } if (config && config.platform && config.platform.toLowerCase() === constants_1.Constants.IOS_PLATFORM_NAME.toLowerCase()) { return Object.assign(yield this.getCommonSysInfo(), yield this.getiOSSysInfo()); } return Object.assign(yield this.getCommonSysInfo(), yield this.getAndroidSysInfo(), yield this.getiOSSysInfo()); }); } isCocoaPodsWorkingCorrectly() { return this.getValueForProperty(() => this.isCocoaPodsWorkingCorrectlyCache, () => __awaiter(this, void 0, void 0, function* () { if (this.hostInfo.isDarwin) { if (!this.fileSystem.exists(path.join(osenv.home(), ".cocoapods"))) { return true; } temp.track(); const tempDirectory = temp.mkdirSync("nativescript-check-cocoapods"); const pathToXCodeProjectZip = path.join(__dirname, "..", "resources", "cocoapods-verification", "cocoapods.zip"); yield this.fileSystem.extractZip(pathToXCodeProjectZip, tempDirectory); const xcodeProjectDir = path.join(tempDirectory, "cocoapods"); try { const spawnResult = yield this.childProcess.spawnFromEvent("pod", ["install"], "exit", { spawnOptions: { cwd: xcodeProjectDir } }); if (spawnResult.exitCode) { this.fileSystem.deleteEntry(tempDirectory); return false; } else { const exists = this.fileSystem.exists(path.join(xcodeProjectDir, "cocoapods.xcworkspace")); this.fileSystem.deleteEntry(tempDirectory); return exists; } } catch (err) { this.fileSystem.deleteEntry(tempDirectory); return null; } } else { return false; } })); } getNativeScriptCliVersion() { return this.getValueForProperty(() => this.nativeScriptCliVersionCache, () => __awaiter(this, void 0, void 0, function* () { const output = yield this.execCommand("tns --version"); return output ? this.getVersionFromCLIOutput(output.trim()) : output; })); } getXcprojInfo() { return this.getValueForProperty(() => this.xcprojInfoCache, () => __awaiter(this, void 0, void 0, function* () { const cocoaPodsVersion = yield this.getCocoaPodsVersion(); let xcodeVersion = yield this.getXcodeVersion(); if (xcodeVersion) { xcodeVersion = this.helpers.appendZeroesToVersion(xcodeVersion, 3); } const shouldUseXcproj = cocoaPodsVersion && !!(semver.lt(cocoaPodsVersion, "1.0.0") && semver.gte(xcodeVersion, "7.3.0")); let xcprojAvailable; if (shouldUseXcproj) { xcprojAvailable = !!(yield this.exec("xcproj --version")); } return { shouldUseXcproj, xcprojAvailable }; })); } getPythonInfo() { return this.getValueForProperty(() => this.pythonInfoCache, () => __awaiter(this, void 0, void 0, function* () { if (this.hostInfo.isDarwin) { try { yield this.childProcess.exec(`python -c "import six"`); } catch (error) { if (error.code === 1) { return { isInstalled: true, isSixPackageInstalled: false }; } return { isInstalled: false, isSixPackageInstalled: false, installationErrorMessage: error.message }; } return { isInstalled: true, isSixPackageInstalled: true }; } return null; })); } isCocoaPodsUpdateRequired() { return this.getValueForProperty(() => this.isCocoaPodsUpdateRequiredCache, () => __awaiter(this, void 0, void 0, function* () { const xcprojInfo = yield this.getXcprojInfo(); if (xcprojInfo.shouldUseXcproj && !xcprojInfo.xcprojAvailable) { return true; } else { return false; } })); } setShouldCacheSysInfo(shouldCache) { this.shouldCache = shouldCache; } getGitPath() { return this.hostInfo.isWindows ? this.findGitWin32() : this.findGitUnix(); } findGitWin32() { return __awaiter(this, void 0, void 0, function* () { let result; const win32Paths = [process.env["ProgramFiles"], process.env["ProgramFiles(x86)"]]; for (const win32Path of win32Paths) { result = this.findSystemGitWin32(win32Path); if (result) { return result; } } result = this.findGitHubGitWin32(); return result ? result : yield this.findGitCore("where"); }); } findSystemGitWin32(base) { if (!base) { return null; } return this.findSpecificGit(path.join(base, "Git", "cmd", "git.exe")); } findGitHubGitWin32() { const github = path.join(process.env["LOCALAPPDATA"], "GitHub"); if (!this.fileSystem.exists(github)) { return null; } const children = this.fileSystem.readDirectory(github); const git = children.filter(child => /^PortableGit/.test(child))[0]; if (!this.fileSystem.exists(git)) { return null; } return this.findSpecificGit(path.join(github, git, "cmd", "git.exe")); } findSpecificGit(gitPath) { return this.fileSystem.exists(gitPath) ? gitPath : null; } findGitUnix() { return __awaiter(this, void 0, void 0, function* () { return yield this.findGitCore("which"); }); } findGitCore(command, options) { return __awaiter(this, void 0, void 0, function* () { const result = yield this.execCommand(`${command} git`); return result && result.split("\n")[0].trim(); }); } getValueForProperty(property, getValueMethod) { return __awaiter(this, void 0, void 0, function* () { if (this.shouldCache) { const propertyName = this.helpers.getPropertyName(property); const cachedValue = this[propertyName]; if (cachedValue === undefined) { const result = yield getValueMethod(); this[propertyName] = result; return result; } else { return cachedValue; } } else { return yield getValueMethod(); } }); } exec(cmd, execOptions) { return __awaiter(this, void 0, void 0, function* () { if (cmd) { try { return yield this.childProcess.exec(cmd, execOptions); } catch (err) { return null; } } return null; }); } execCommand(cmd, execOptions) { return __awaiter(this, void 0, void 0, function* () { const output = yield this.exec(cmd, execOptions); return output && output.stdout; }); } getVersionFromString(versionString) { const matches = versionString.match(SysInfo.VERSION_REGEXP); if (matches) { return `${matches[1]}.${matches[2]}.${matches[3] || 0}`; } return null; } getVersionFromCLIOutput(commandOutput) { const matches = commandOutput.match(SysInfo.CLI_OUTPUT_VERSION_REGEXP); return matches && matches[0]; } winVer() { return __awaiter(this, void 0, void 0, function* () { let productName; let currentVersion; let currentBuild; const hive = this.winReg.registryKeys.HKLM; const key = "\\Software\\Microsoft\\Windows NT\\CurrentVersion"; productName = yield this.winReg.getRegistryValue("ProductName", hive, key); currentVersion = yield this.winReg.getRegistryValue("CurrentVersion", hive, key); currentBuild = yield this.winReg.getRegistryValue("CurrentBuild", hive, key); return `${productName} ${currentVersion}.${currentBuild}`; }); } unixVer() { return this.execCommand("uname -a"); } getCommonSysInfo() { return this.getValueForProperty(() => this.commonSysInfoCache, () => __awaiter(this, void 0, void 0, function* () { const result = Object.create(null); result.platform = os_1.platform(); result.shell = osenv.shell(); result.os = yield this.getOs(); result.procArch = process.arch; result.nodeVer = yield this.getNodeVersion(); result.npmVer = yield this.getNpmVersion(); result.nodeGypVer = yield this.getNodeGypVersion(); result.nativeScriptCliVersion = yield this.getNativeScriptCliVersion(); result.gitVer = yield this.getGitVersion(); return result; })); } getiOSSysInfo() { return __awaiter(this, void 0, void 0, function* () { return this.getValueForProperty(() => this.iOSSysInfoCache, () => __awaiter(this, void 0, void 0, function* () { const result = Object.create(null); result.xcodeVer = yield this.getXcodeVersion(); result.xcodeprojLocation = yield this.getXcodeprojLocation(); result.itunesInstalled = yield this.isITunesInstalled(); result.cocoaPodsVer = yield this.getCocoaPodsVersion(); result.isCocoaPodsWorkingCorrectly = yield this.isCocoaPodsWorkingCorrectly(); result.isCocoaPodsUpdateRequired = yield this.isCocoaPodsUpdateRequired(); result.pythonInfo = yield this.getPythonInfo(); return result; })); }); } getAndroidSysInfo(config) { return __awaiter(this, void 0, void 0, function* () { return this.getValueForProperty(() => this.androidSysInfoCache, () => __awaiter(this, void 0, void 0, function* () { const result = Object.create(null); result.dotNetVer = yield this.hostInfo.dotNetVersion(); result.javacVersion = yield this.getJavaCompilerVersion(); result.javaVersion = yield this.getJavaVersion(); result.javaPath = yield this.getJavaPath(); result.adbVer = yield this.getAdbVersion(config && config.androidToolsInfo && config.androidToolsInfo.pathToAdb); result.androidInstalled = yield this.isAndroidInstalled(); result.monoVer = yield this.getMonoVersion(); result.gradleVer = yield this.getGradleVersion(); result.isAndroidSdkConfiguredCorrectly = yield this.isAndroidSdkConfiguredCorrectly(); return result; })); }); } getVersionOfJavaExecutableFromJavaHome(javaExecutableName, regExp) { return __awaiter(this, void 0, void 0, function* () { let javaExecutableVersion = null; const javaExecutablePath = this.getJavaExecutablePathFromJavaHome(javaExecutableName); if (javaExecutablePath) { javaExecutableVersion = yield this.getVersionOfJavaExecutable(javaExecutablePath, regExp); } return javaExecutableVersion; }); } getJavaExecutablePathFromJavaHome(javaExecutableName) { let javaExecutablePath = null; try { const javaHome = process.env["JAVA_HOME"]; const javaExecutableFile = this.hostInfo.isWindows ? `${javaExecutableName}.exe` : javaExecutableName; if (javaHome) { const pathToJavaExecutable = path.join(javaHome, "bin", javaExecutableFile); if (this.fileSystem.exists(pathToJavaExecutable)) { javaExecutablePath = pathToJavaExecutable; } } } catch (err) { } return javaExecutablePath; } getVersionOfJavaExecutableFromPath(javaExecutableName, regExp) { return __awaiter(this, void 0, void 0, function* () { let javaExecutableVersion = null; const javaExecutablePath = yield this.getJavaExecutablePathFromPath(javaExecutableName); if (javaExecutablePath) { javaExecutableVersion = yield this.getVersionOfJavaExecutable(javaExecutablePath, regExp); } return javaExecutableVersion; }); } getJavaExecutablePathFromPath(javaExecutableName) { return __awaiter(this, void 0, void 0, function* () { let javaExecutablePath = null; try { const detectionCommand = this.hostInfo.isWindows ? "where" : "which"; yield this.childProcess.exec(`${detectionCommand} ${javaExecutableName}`); javaExecutablePath = javaExecutableName; } catch (err) { } return javaExecutablePath; }); } getVersionOfJavaExecutable(executable, regExp) { return __awaiter(this, void 0, void 0, function* () { try { const output = yield this.childProcess.exec(`"${executable}" -version`); return regExp.exec(`${output.stderr}${os_1.EOL}${output.stdout}`)[1]; } catch (err) { return null; } }); } } exports.SysInfo = SysInfo; SysInfo.JAVA_COMPILER_VERSION_REGEXP = /^javac (.*)/im; SysInfo.JAVA_VERSION_REGEXP = /^(?:(?:java)|(?:openjdk)).*?\"(.*)\"/im; SysInfo.XCODE_VERSION_REGEXP = /Xcode (.*)/; SysInfo.VERSION_REGEXP = /(\d{1,})\.(\d{1,})\.*([\w-]{0,})/m; SysInfo.CLI_OUTPUT_VERSION_REGEXP = /^(?:\d+\.){2}\d+.*?$/m; SysInfo.GIT_VERSION_REGEXP = /^git version (.*)/; SysInfo.GRADLE_VERSION_REGEXP = /Gradle (.*)/i;