Skip to content

feat: Deprecate support for all macOS versions below High Sierra #3588

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 1 commit into from
May 17, 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
46 changes: 46 additions & 0 deletions PublicAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ const tns = require("nativescript");
* [generateSplashScreens](#generatesplashscreens)
* [androidProcessService](#androidprocessservice)
* [getAppProcessId](#getappprocessid)
* [sysInfo](#sysinfo)
* [getSupportedNodeVersionRange](#getsupportednodeversionrange)
* [getSystemWarnings](#getsystemwarnings)

## Module projectService

Expand Down Expand Up @@ -1017,6 +1020,7 @@ tns.liveSyncService.on("debuggerDetached", debugInfo => {
console.log(`Detached debugger for device with id ${debugInfo.deviceIdentifier}`);
});
```

## analyticsSettingsService
Provides methods for accessing the analytics settings file data.

Expand Down Expand Up @@ -1078,6 +1082,7 @@ tns.analyticsSettingsService.getPlaygroundInfo("/my/project/path")
console.log(playgroundInfo.usedTutorial);
});
```

## constants
Contains various constants related to NativeScript.

Expand Down Expand Up @@ -1151,6 +1156,47 @@ tns.androidProcessService.getAppProcessId("4df18f307d8a8f1b", "org.nativescript.
.catch(err => console.error(`Error while checking for PID: ${err}`));
```

## sysInfo
The `sysInfo` module exposes methods to get the current environment setup and warnings for it.

### getSupportedNodeVersionRange
The `getSupportedNodeVersionRange` method gives information about the supported Node.js versions for the current CLI. The result is a valid semver range, for example `>=6.0.0`.

* Definition
```TypeScript
/**
* Returns the value of engines.node key from CLI's package.json file.
* @return {string} The range of supported Node.js versions.
*/
getSupportedNodeVersionRange(): string;
```

* Usage
```JavaScript
const nodeJsRange = tns.sysInfo.getSupportedNodeVersionRange();
console.log(nodeJsRange);
```

### getSystemWarnings
The `getSystemWarnings` methods returns all deprecation warnings for current environment. For example, in case the support for the current OS is deprecated by CLI, the method will return array with one message describing the deprecation.

* Definition
```TypeScript
/**
* Gets all global warnings for the current environment, for example Node.js version compatibility, OS compatibility, etc.
* @return {Promise<string[]>} All warnings. Empty array is returned in case the system is setup correctly.
*/
getSystemWarnings(): Promise<string[]>;
```

* Usage
```JavaScript
tns.sysInfo.getSystemWarnings()
.then(warnings => {
warnings.forEach(warn => console.log(warn));
})
.catch(err => console.error(`Error while trying to get system warnings: ${err}`));
```

## How to add a new method to Public API
CLI is designed as command line tool and when it is used as a library, it does not give you access to all of the methods. This is mainly implementation detail. Most of the CLI's code is created to work in command line, not as a library, so before adding method to public API, most probably it will require some modification.
Expand Down
2 changes: 1 addition & 1 deletion bin/tns
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ var path = require("path"),
pathToLib = path.join(__dirname, "..", "lib"),
pathToCommon = path.join(pathToLib, "common");

require(path.join(pathToCommon, "verify-node-version")).verifyNodeVersion(node, "NativeScript", [ "^6.0.0" ]);
require(path.join(pathToCommon, "verify-node-version")).verifyNodeVersion();

var pathToCliExecutable = path.join(pathToLib, "nativescript-cli.js");

Expand Down
2 changes: 1 addition & 1 deletion lib/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ $injector.requirePublicClass("liveSyncService", "./services/livesync/livesync-se
$injector.require("androidLiveSyncService", "./services/livesync/android-livesync-service");
$injector.require("iOSLiveSyncService", "./services/livesync/ios-livesync-service");
$injector.require("usbLiveSyncService", "./services/livesync/livesync-service"); // The name is used in https://github.com/NativeScript/nativescript-dev-typescript
$injector.require("sysInfo", "./sys-info");
$injector.requirePublic("sysInfo", "./sys-info");

$injector.require("iOSNotificationService", "./services/ios-notification-service");
$injector.require("socketProxyFactory", "./device-sockets/ios/socket-proxy-factory");
Expand Down
8 changes: 8 additions & 0 deletions lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,11 @@ export class AssetConstants {
public static defaultScale = 1;
public static defaultOverlayImageScale = 0.8;
}

// https://en.wikipedia.org/wiki/Darwin_(operating_system)#Release_history
export class MacOSVersions {
public static Sierra = "10.12";
public static HighSierra = "10.13";
}

export const MacOSDeprecationStringFormat = "Support for macOS %s is deprecated and will be removed in one of the next releases of NativeScript. Please, upgrade to the latest macOS version.";
8 changes: 8 additions & 0 deletions lib/nativescript-cli.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require("./bootstrap");
import { EOL } from "os";
import * as shelljs from "shelljs";
shelljs.config.silent = true;
shelljs.config.fatal = true;
Expand All @@ -21,6 +22,13 @@ import { settlePromises } from "./common/helpers";
logger.trace("Unable to load extensions. Error is: ", err);
}

const $sysInfo = $injector.resolve<ISysInfo>("sysInfo");
const macOSWarning = await $sysInfo.getMacOSWarningMessage();
if (macOSWarning) {
const message = EOL + macOSWarning + EOL ;
logger.warn(message);
}

const commandDispatcher: ICommandDispatcher = $injector.resolve("commandDispatcher");

const messages: IMessagesService = $injector.resolve("$messagesService");
Expand Down
41 changes: 40 additions & 1 deletion lib/sys-info.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import * as path from "path";
import { format } from "util";
import { sysInfo } from "nativescript-doctor";
import { MacOSVersions, MacOSDeprecationStringFormat } from "./constants";
import { getNodeWarning } from "./common/verify-node-version";
import { exported } from "./common/decorators";

export class SysInfo implements ISysInfo {
private sysInfo: ISysInfoData = null;

constructor(private $fs: IFileSystem,
private $hostInfo: IHostInfo) { }

public async getSysInfo(config?: NativeScriptDoctor.ISysInfoConfig): Promise<NativeScriptDoctor.ISysInfoData> {
if (!this.sysInfo) {
const pathToNativeScriptCliPackageJson = (config && config.pathToNativeScriptCliPackageJson) || path.join(__dirname, "..", "package.json");
const androidToolsInfo = config && config.androidToolsInfo;

this.sysInfo = await sysInfo.getSysInfo({pathToNativeScriptCliPackageJson, androidToolsInfo});
this.sysInfo = await sysInfo.getSysInfo({ pathToNativeScriptCliPackageJson, androidToolsInfo });
}

return this.sysInfo;
Expand All @@ -26,5 +33,37 @@ export class SysInfo implements ISysInfo {
public getJavaCompilerVersion(): Promise<string> {
return sysInfo.getJavaCompilerVersion();
}

@exported("sysInfo")
public async getSystemWarnings(): Promise<string[]> {
const warnings: string[] = [];
const macOSWarningMessage = await this.getMacOSWarningMessage();
if (macOSWarningMessage) {
warnings.push(macOSWarningMessage);
}

const nodeWarning = getNodeWarning();
if (nodeWarning) {
warnings.push(nodeWarning);
}

return warnings;
}

@exported("sysInfo")
public getSupportedNodeVersionRange(): string {
const pathToCLIPackageJson = path.join(__dirname, "..", "package.json");
const jsonContent = this.$fs.readJson(pathToCLIPackageJson);
return jsonContent && jsonContent.engines && jsonContent.engines.node;
}

public async getMacOSWarningMessage(): Promise<string> {
const macOSVersion = await this.$hostInfo.getMacOSVersion();
if (macOSVersion && macOSVersion < MacOSVersions.HighSierra) {
return format(MacOSDeprecationStringFormat, macOSVersion);
}

return null;
}
}
$injector.register("sysInfo", SysInfo);
4 changes: 4 additions & 0 deletions test/nativescript-cli-lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ describe("nativescript-cli-lib", () => {
],
androidProcessService: [
"getAppProcessId"
],
sysInfo: [
"getSupportedNodeVersionRange",
"getSystemWarnings"
]
};

Expand Down
109 changes: 109 additions & 0 deletions test/sys-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { SysInfo } from "../lib/sys-info";
import { Yok } from "../lib/common/yok";
import { assert } from "chai";
import { format } from "util";
import * as sinon from "sinon";
import { MacOSVersions, MacOSDeprecationStringFormat } from "../lib/constants";
const verifyNodeVersion = require("../lib/common/verify-node-version");

describe("sysInfo", () => {
let sandbox: sinon.SinonSandbox = null;
beforeEach(() => {
sandbox = sinon.sandbox.create();
});

afterEach(() => {
sandbox.restore();
});

const createTestInjector = (): IInjector => {
const testInjector = new Yok();
testInjector.register("hostInfo", {
getMacOSVersion: async (): Promise<string> => null
});

testInjector.register("fs", {
readJson: (filename: string, encoding?: string): any => null
});

testInjector.register("sysInfo", SysInfo);

return testInjector;
};

describe("getSystemWarnings", () => {
const getSystemWarnings = async (opts?: { nodeJsWarning?: string, macOSDeprecatedVersion?: string }): Promise<string[]> => {
sandbox.stub(verifyNodeVersion, "getNodeWarning").returns(opts && opts.nodeJsWarning);

const testInjector = createTestInjector();
const $hostInfo = testInjector.resolve<IHostInfo>("hostInfo");
$hostInfo.getMacOSVersion = async (): Promise<string> => opts && opts.macOSDeprecatedVersion;
const sysInfo = testInjector.resolve<ISysInfo>("sysInfo");
const warnings = await sysInfo.getSystemWarnings();
return warnings;
};

it("returns empty array when there are no warnings", async () => {
const warnings = await getSystemWarnings();
assert.deepEqual(warnings, []);
});

it("returns correct single warning when macOS version is deprecated", async () => {
const macOSDeprecatedVersion = MacOSVersions.Sierra;
const macOSWarning = format(MacOSDeprecationStringFormat, macOSDeprecatedVersion);
const warnings = await getSystemWarnings({ macOSDeprecatedVersion });
assert.deepEqual(warnings, [macOSWarning]);
});

it("returns correct single warning when Node.js version is deprecated", async () => {
const nodeJsWarning = "Node.js Warning";
const warnings = await getSystemWarnings({ nodeJsWarning });
assert.deepEqual(warnings, [nodeJsWarning]);
});

it("returns correct warnings when both Node.js and macOS versions are deprecated", async () => {
const macOSDeprecatedVersion = MacOSVersions.Sierra;
const macOSWarning = format(MacOSDeprecationStringFormat, macOSDeprecatedVersion);
const nodeJsWarning = "Node.js Warning";
const warnings = await getSystemWarnings({ macOSDeprecatedVersion, nodeJsWarning });
assert.deepEqual(warnings, [macOSWarning, nodeJsWarning]);
});
});

describe("getMacOSWarningMessage", () => {
const getMacOSWarning = async (macOSDeprecatedVersion?: string): Promise<string> => {
sandbox.stub(verifyNodeVersion, "getNodeWarning").returns(null);

const testInjector = createTestInjector();
const $hostInfo = testInjector.resolve<IHostInfo>("hostInfo");
$hostInfo.getMacOSVersion = async (): Promise<string> => macOSDeprecatedVersion;
const sysInfo = testInjector.resolve<ISysInfo>("sysInfo");
const warning = await sysInfo.getMacOSWarningMessage();
return warning;
};

it("returns null when macOS version is supported", async () => {
const warning = await getMacOSWarning();
assert.deepEqual(warning, null);
});

it("returns correct single warning when macOS version is deprecated", async () => {
const macOSDeprecatedVersion = MacOSVersions.Sierra;
const macOSWarning = format(MacOSDeprecationStringFormat, macOSDeprecatedVersion);
const warning = await getMacOSWarning(macOSDeprecatedVersion);
assert.deepEqual(warning, macOSWarning);
});
});

describe("getSupportedNodeVersionRange", () => {
it("returns range from CLI's package.json", () => {
const testInjector = createTestInjector();
const expectedRange = require("../package.json").engines.node;
const fs = testInjector.resolve<IFileSystem>("fs");
fs.readJson = () => require("../package.json");
const sysInfo = testInjector.resolve<ISysInfo>("sysInfo");
const actualRange = sysInfo.getSupportedNodeVersionRange();
assert.equal(actualRange, expectedRange);
});
});
});