Skip to content

Commit a7d71a0

Browse files
committed
fix: runtime version validation and getMaxSupportedCompileVersion
1 parent 20641e7 commit a7d71a0

File tree

3 files changed

+74
-44
lines changed

3 files changed

+74
-44
lines changed

lib/android-tools-info.ts

Lines changed: 71 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
7272
const errors: NativeScriptDoctor.IWarning[] = [];
7373
const toolsInfoData = this.getToolsInfo(config);
7474
const isAndroidHomeValid = this.isAndroidHomeValid();
75-
const runtimeVersion = this.getRuntimeVersion(config);
76-
const supportsOnlyMinRequiredCompileTarget = this.getMaxSupportedCompileVersion(runtimeVersion) === AndroidToolsInfo.MIN_REQUIRED_COMPILE_TARGET;
75+
const supportsOnlyMinRequiredCompileTarget = this.getMaxSupportedCompileVersion(config) === AndroidToolsInfo.MIN_REQUIRED_COMPILE_TARGET;
76+
7777
if (!toolsInfoData.compileSdkVersion) {
7878
errors.push({
7979
warning: `Cannot find a compatible Android SDK for compilation. To be able to build for Android, install Android SDK ${AndroidToolsInfo.MIN_REQUIRED_COMPILE_TARGET}${supportsOnlyMinRequiredCompileTarget ? "" : " or later"}.`,
@@ -367,68 +367,97 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
367367
return !errors && !errors.length;
368368
}
369369

370-
private getAndroidRuntimeVersionFromProjectDir(projectDir: string): string {
371-
let runtimePackage: string = null;
372-
let runtimeVersion: string = null;
373-
if (projectDir && this.fs.exists(projectDir)) {
374-
const pathToPackageJson = path.join(projectDir, Constants.PACKAGE_JSON);
375-
376-
if (this.fs.exists(pathToPackageJson)) {
377-
const content = this.fs.readJson<INativeScriptProjectPackageJson>(pathToPackageJson);
378-
const scopedRuntime = "@nativescript/android";
379-
const oldRuntime = "tns-android";
380-
if (content) {
381-
if (content.devDependencies && content.devDependencies[scopedRuntime]) {
382-
runtimePackage = scopedRuntime;
383-
runtimeVersion = content.devDependencies[scopedRuntime];
384-
} else if (content.nativescript && content.nativescript[oldRuntime] && content.nativescript[oldRuntime].version) {
385-
runtimePackage = oldRuntime;
386-
runtimeVersion = content && content.nativescript && content.nativescript[oldRuntime] && content.nativescript[oldRuntime].version;
387-
}
388-
}
389-
390-
}
391-
}
392-
393-
if (runtimeVersion && runtimeVersion.includes('tgz')) {
394-
try {
395-
runtimeVersion = require(`${runtimePackage}/package.json`).version;
396-
} catch (err) {
397-
runtimeVersion = null;
398-
}
399-
}
400-
401-
return runtimeVersion;
370+
private getAndroidRuntimePackageFromProjectDir(projectDir: string): { name: string, version: string } {
371+
if (!projectDir || !this.fs.exists(projectDir)) {
372+
return null
373+
}
374+
const pathToPackageJson = path.join(projectDir, Constants.PACKAGE_JSON);
375+
376+
if(!this.fs.exists(pathToPackageJson)) {
377+
return null
378+
}
379+
380+
const content = this.fs.readJson<INativeScriptProjectPackageJson>(pathToPackageJson);
381+
382+
if(!content) {
383+
return null
384+
}
385+
386+
// in case we have a nativescript key and a runtime with a version
387+
// we are dealing with a legacy project and should respect the values
388+
// in the nativescript key
389+
if(content && content.nativescript && content.nativescript['tns-android'] && content.nativescript['tns-android'].version) {
390+
return {
391+
name: Constants.ANDROID_OLD_RUNTIME,
392+
version: content.nativescript && content.nativescript['tns-android'] && content.nativescript['tns-android'].version
393+
};
394+
}
395+
396+
if(content && content.devDependencies) {
397+
const foundRuntime = Object.keys(content.devDependencies).find(depName => {
398+
return depName === Constants.ANDROID_SCOPED_RUNTIME || depName === Constants.ANDROID_OLD_RUNTIME
399+
})
400+
401+
if(foundRuntime) {
402+
let version = content.devDependencies[foundRuntime]
403+
404+
if(version.includes('tgz')) {
405+
try {
406+
const packagePath = require.resolve(`${foundRuntime}/package.json`, {
407+
paths: [projectDir]
408+
})
409+
version = require(packagePath).version;
410+
} catch (err) {
411+
version = '*';
412+
}
413+
}
414+
415+
return {
416+
name: foundRuntime,
417+
version
418+
}
419+
}
420+
}
421+
422+
return null
402423
}
403424

404425
private getRuntimeVersion({ runtimeVersion, projectDir } : { runtimeVersion?: string, projectDir?: string}): string {
405-
runtimeVersion = runtimeVersion || this.getAndroidRuntimeVersionFromProjectDir(projectDir);
426+
let runtimePackage = {
427+
name: Constants.ANDROID_SCOPED_RUNTIME,
428+
version: runtimeVersion
429+
}
430+
if(!runtimeVersion) {
431+
runtimePackage = this.getAndroidRuntimePackageFromProjectDir(projectDir)
432+
runtimeVersion = runtimePackage?.version;
433+
}
434+
406435
if (runtimeVersion) {
407436
// Check if the version is not "next" or "rc", i.e. tag from npm
408-
if (!semver.valid(runtimeVersion)) {
437+
if (!semver.validRange(runtimeVersion)) {
409438
try {
410-
const npmViewOutput = this.childProcess.execSync(`npm view ${Constants.ANDROID_RUNTIME} dist-tags --json`);
439+
const npmViewOutput = this.childProcess.execSync(`npm view ${runtimePackage.name} dist-tags --json`);
411440
const jsonNpmViewOutput = JSON.parse(npmViewOutput);
441+
412442
runtimeVersion = jsonNpmViewOutput[runtimeVersion] || runtimeVersion;
413443
} catch (err) {
414444
// Maybe there's no npm here
415445
}
416446
}
417447
}
418448

419-
if (runtimeVersion && !semver.valid(runtimeVersion)) {
449+
if (runtimeVersion && !semver.validRange(runtimeVersion)) {
420450
// If we got here, something terribly wrong happened.
421451
throw new Error(`The determined Android runtime version ${runtimeVersion} is not valid. Unable to verify if the current system is setup for Android development.`);
422452
}
423453

424454
return runtimeVersion;
425455
}
426456

427-
private getMaxSupportedCompileVersion(runtimeVersion: string): number {
428-
if (runtimeVersion && semver.lt(semver.coerce(runtimeVersion), "6.1.0")) {
457+
private getMaxSupportedCompileVersion(config: Partial<NativeScriptDoctor.IProjectDir> & { runtimeVersion?: string}): number {
458+
if (config.runtimeVersion && semver.lt(semver.coerce(config.runtimeVersion), "6.1.0")) {
429459
return 28;
430460
}
431-
432-
return this.parseAndroidSdkString(_.last(this.getSupportedTargets(runtimeVersion).sort()));
461+
return this.parseAndroidSdkString(_.last(this.getSupportedTargets(config.projectDir).sort()));
433462
}
434463
}

lib/constants.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ export class Constants {
1212

1313
public static PACKAGE_JSON = "package.json";
1414
public static NATIVESCRIPT_KEY = "nativescript";
15-
public static ANDROID_RUNTIME = "tns-android";
15+
public static ANDROID_OLD_RUNTIME = "tns-android";
16+
public static ANDROID_SCOPED_RUNTIME = "@nativescript/android";
1617
public static VERSION_PROPERTY_NAME = "version";
1718
public static XCODE_MIN_REQUIRED_VERSION = 10;
1819
public static JAVAC_EXECUTABLE_NAME = "javac";

lib/declarations.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,5 @@ interface INativeScriptNode {
7979
interface INativeScriptProjectPackageJson {
8080
nativescript: INativeScriptNode;
8181
dependencies?: any;
82-
devDependencies?: any;
82+
devDependencies?: { [name: string]: string };
8383
}

0 commit comments

Comments
 (0)