Skip to content

Commit f7a4594

Browse files
Merge pull request #3588 from NativeScript/vladimirov/deprecate-macos-sierra
feat: Deprecate support for all macOS versions below High Sierra
2 parents 04ef22f + 64bab09 commit f7a4594

9 files changed

+218
-4
lines changed

PublicAPI.md

+46
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ const tns = require("nativescript");
5050
* [generateSplashScreens](#generatesplashscreens)
5151
* [androidProcessService](#androidprocessservice)
5252
* [getAppProcessId](#getappprocessid)
53+
* [sysInfo](#sysinfo)
54+
* [getSupportedNodeVersionRange](#getsupportednodeversionrange)
55+
* [getSystemWarnings](#getsystemwarnings)
5356

5457
## Module projectService
5558

@@ -1017,6 +1020,7 @@ tns.liveSyncService.on("debuggerDetached", debugInfo => {
10171020
console.log(`Detached debugger for device with id ${debugInfo.deviceIdentifier}`);
10181021
});
10191022
```
1023+
10201024
## analyticsSettingsService
10211025
Provides methods for accessing the analytics settings file data.
10221026
@@ -1078,6 +1082,7 @@ tns.analyticsSettingsService.getPlaygroundInfo("/my/project/path")
10781082
console.log(playgroundInfo.usedTutorial);
10791083
});
10801084
```
1085+
10811086
## constants
10821087
Contains various constants related to NativeScript.
10831088
@@ -1151,6 +1156,47 @@ tns.androidProcessService.getAppProcessId("4df18f307d8a8f1b", "org.nativescript.
11511156
.catch(err => console.error(`Error while checking for PID: ${err}`));
11521157
```
11531158
1159+
## sysInfo
1160+
The `sysInfo` module exposes methods to get the current environment setup and warnings for it.
1161+
1162+
### getSupportedNodeVersionRange
1163+
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`.
1164+
1165+
* Definition
1166+
```TypeScript
1167+
/**
1168+
* Returns the value of engines.node key from CLI's package.json file.
1169+
* @return {string} The range of supported Node.js versions.
1170+
*/
1171+
getSupportedNodeVersionRange(): string;
1172+
```
1173+
1174+
* Usage
1175+
```JavaScript
1176+
const nodeJsRange = tns.sysInfo.getSupportedNodeVersionRange();
1177+
console.log(nodeJsRange);
1178+
```
1179+
1180+
### getSystemWarnings
1181+
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.
1182+
1183+
* Definition
1184+
```TypeScript
1185+
/**
1186+
* Gets all global warnings for the current environment, for example Node.js version compatibility, OS compatibility, etc.
1187+
* @return {Promise<string[]>} All warnings. Empty array is returned in case the system is setup correctly.
1188+
*/
1189+
getSystemWarnings(): Promise<string[]>;
1190+
```
1191+
1192+
* Usage
1193+
```JavaScript
1194+
tns.sysInfo.getSystemWarnings()
1195+
.then(warnings => {
1196+
warnings.forEach(warn => console.log(warn));
1197+
})
1198+
.catch(err => console.error(`Error while trying to get system warnings: ${err}`));
1199+
```
11541200
11551201
## How to add a new method to Public API
11561202
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.

bin/tns

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ var path = require("path"),
66
pathToLib = path.join(__dirname, "..", "lib"),
77
pathToCommon = path.join(pathToLib, "common");
88

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

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

lib/bootstrap.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ $injector.requirePublicClass("liveSyncService", "./services/livesync/livesync-se
125125
$injector.require("androidLiveSyncService", "./services/livesync/android-livesync-service");
126126
$injector.require("iOSLiveSyncService", "./services/livesync/ios-livesync-service");
127127
$injector.require("usbLiveSyncService", "./services/livesync/livesync-service"); // The name is used in https://github.com/NativeScript/nativescript-dev-typescript
128-
$injector.require("sysInfo", "./sys-info");
128+
$injector.requirePublic("sysInfo", "./sys-info");
129129

130130
$injector.require("iOSNotificationService", "./services/ios-notification-service");
131131
$injector.require("socketProxyFactory", "./device-sockets/ios/socket-proxy-factory");

lib/constants.ts

+8
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,11 @@ export class AssetConstants {
170170
public static defaultScale = 1;
171171
public static defaultOverlayImageScale = 0.8;
172172
}
173+
174+
// https://en.wikipedia.org/wiki/Darwin_(operating_system)#Release_history
175+
export class MacOSVersions {
176+
public static Sierra = "10.12";
177+
public static HighSierra = "10.13";
178+
}
179+
180+
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.";

lib/nativescript-cli.ts

+8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require("./bootstrap");
2+
import { EOL } from "os";
23
import * as shelljs from "shelljs";
34
shelljs.config.silent = true;
45
shelljs.config.fatal = true;
@@ -21,6 +22,13 @@ import { settlePromises } from "./common/helpers";
2122
logger.trace("Unable to load extensions. Error is: ", err);
2223
}
2324

25+
const $sysInfo = $injector.resolve<ISysInfo>("sysInfo");
26+
const macOSWarning = await $sysInfo.getMacOSWarningMessage();
27+
if (macOSWarning) {
28+
const message = EOL + macOSWarning + EOL ;
29+
logger.warn(message);
30+
}
31+
2432
const commandDispatcher: ICommandDispatcher = $injector.resolve("commandDispatcher");
2533

2634
const messages: IMessagesService = $injector.resolve("$messagesService");

lib/sys-info.ts

+40-1
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
import * as path from "path";
2+
import { format } from "util";
23
import { sysInfo } from "nativescript-doctor";
4+
import { MacOSVersions, MacOSDeprecationStringFormat } from "./constants";
5+
import { getNodeWarning } from "./common/verify-node-version";
6+
import { exported } from "./common/decorators";
37

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

11+
constructor(private $fs: IFileSystem,
12+
private $hostInfo: IHostInfo) { }
13+
714
public async getSysInfo(config?: NativeScriptDoctor.ISysInfoConfig): Promise<NativeScriptDoctor.ISysInfoData> {
815
if (!this.sysInfo) {
916
const pathToNativeScriptCliPackageJson = (config && config.pathToNativeScriptCliPackageJson) || path.join(__dirname, "..", "package.json");
1017
const androidToolsInfo = config && config.androidToolsInfo;
1118

12-
this.sysInfo = await sysInfo.getSysInfo({pathToNativeScriptCliPackageJson, androidToolsInfo});
19+
this.sysInfo = await sysInfo.getSysInfo({ pathToNativeScriptCliPackageJson, androidToolsInfo });
1320
}
1421

1522
return this.sysInfo;
@@ -26,5 +33,37 @@ export class SysInfo implements ISysInfo {
2633
public getJavaCompilerVersion(): Promise<string> {
2734
return sysInfo.getJavaCompilerVersion();
2835
}
36+
37+
@exported("sysInfo")
38+
public async getSystemWarnings(): Promise<string[]> {
39+
const warnings: string[] = [];
40+
const macOSWarningMessage = await this.getMacOSWarningMessage();
41+
if (macOSWarningMessage) {
42+
warnings.push(macOSWarningMessage);
43+
}
44+
45+
const nodeWarning = getNodeWarning();
46+
if (nodeWarning) {
47+
warnings.push(nodeWarning);
48+
}
49+
50+
return warnings;
51+
}
52+
53+
@exported("sysInfo")
54+
public getSupportedNodeVersionRange(): string {
55+
const pathToCLIPackageJson = path.join(__dirname, "..", "package.json");
56+
const jsonContent = this.$fs.readJson(pathToCLIPackageJson);
57+
return jsonContent && jsonContent.engines && jsonContent.engines.node;
58+
}
59+
60+
public async getMacOSWarningMessage(): Promise<string> {
61+
const macOSVersion = await this.$hostInfo.getMacOSVersion();
62+
if (macOSVersion && macOSVersion < MacOSVersions.HighSierra) {
63+
return format(MacOSDeprecationStringFormat, macOSVersion);
64+
}
65+
66+
return null;
67+
}
2968
}
3069
$injector.register("sysInfo", SysInfo);

test/nativescript-cli-lib.ts

+4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ describe("nativescript-cli-lib", () => {
5151
],
5252
androidProcessService: [
5353
"getAppProcessId"
54+
],
55+
sysInfo: [
56+
"getSupportedNodeVersionRange",
57+
"getSystemWarnings"
5458
]
5559
};
5660

test/sys-info.ts

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { SysInfo } from "../lib/sys-info";
2+
import { Yok } from "../lib/common/yok";
3+
import { assert } from "chai";
4+
import { format } from "util";
5+
import * as sinon from "sinon";
6+
import { MacOSVersions, MacOSDeprecationStringFormat } from "../lib/constants";
7+
const verifyNodeVersion = require("../lib/common/verify-node-version");
8+
9+
describe("sysInfo", () => {
10+
let sandbox: sinon.SinonSandbox = null;
11+
beforeEach(() => {
12+
sandbox = sinon.sandbox.create();
13+
});
14+
15+
afterEach(() => {
16+
sandbox.restore();
17+
});
18+
19+
const createTestInjector = (): IInjector => {
20+
const testInjector = new Yok();
21+
testInjector.register("hostInfo", {
22+
getMacOSVersion: async (): Promise<string> => null
23+
});
24+
25+
testInjector.register("fs", {
26+
readJson: (filename: string, encoding?: string): any => null
27+
});
28+
29+
testInjector.register("sysInfo", SysInfo);
30+
31+
return testInjector;
32+
};
33+
34+
describe("getSystemWarnings", () => {
35+
const getSystemWarnings = async (opts?: { nodeJsWarning?: string, macOSDeprecatedVersion?: string }): Promise<string[]> => {
36+
sandbox.stub(verifyNodeVersion, "getNodeWarning").returns(opts && opts.nodeJsWarning);
37+
38+
const testInjector = createTestInjector();
39+
const $hostInfo = testInjector.resolve<IHostInfo>("hostInfo");
40+
$hostInfo.getMacOSVersion = async (): Promise<string> => opts && opts.macOSDeprecatedVersion;
41+
const sysInfo = testInjector.resolve<ISysInfo>("sysInfo");
42+
const warnings = await sysInfo.getSystemWarnings();
43+
return warnings;
44+
};
45+
46+
it("returns empty array when there are no warnings", async () => {
47+
const warnings = await getSystemWarnings();
48+
assert.deepEqual(warnings, []);
49+
});
50+
51+
it("returns correct single warning when macOS version is deprecated", async () => {
52+
const macOSDeprecatedVersion = MacOSVersions.Sierra;
53+
const macOSWarning = format(MacOSDeprecationStringFormat, macOSDeprecatedVersion);
54+
const warnings = await getSystemWarnings({ macOSDeprecatedVersion });
55+
assert.deepEqual(warnings, [macOSWarning]);
56+
});
57+
58+
it("returns correct single warning when Node.js version is deprecated", async () => {
59+
const nodeJsWarning = "Node.js Warning";
60+
const warnings = await getSystemWarnings({ nodeJsWarning });
61+
assert.deepEqual(warnings, [nodeJsWarning]);
62+
});
63+
64+
it("returns correct warnings when both Node.js and macOS versions are deprecated", async () => {
65+
const macOSDeprecatedVersion = MacOSVersions.Sierra;
66+
const macOSWarning = format(MacOSDeprecationStringFormat, macOSDeprecatedVersion);
67+
const nodeJsWarning = "Node.js Warning";
68+
const warnings = await getSystemWarnings({ macOSDeprecatedVersion, nodeJsWarning });
69+
assert.deepEqual(warnings, [macOSWarning, nodeJsWarning]);
70+
});
71+
});
72+
73+
describe("getMacOSWarningMessage", () => {
74+
const getMacOSWarning = async (macOSDeprecatedVersion?: string): Promise<string> => {
75+
sandbox.stub(verifyNodeVersion, "getNodeWarning").returns(null);
76+
77+
const testInjector = createTestInjector();
78+
const $hostInfo = testInjector.resolve<IHostInfo>("hostInfo");
79+
$hostInfo.getMacOSVersion = async (): Promise<string> => macOSDeprecatedVersion;
80+
const sysInfo = testInjector.resolve<ISysInfo>("sysInfo");
81+
const warning = await sysInfo.getMacOSWarningMessage();
82+
return warning;
83+
};
84+
85+
it("returns null when macOS version is supported", async () => {
86+
const warning = await getMacOSWarning();
87+
assert.deepEqual(warning, null);
88+
});
89+
90+
it("returns correct single warning when macOS version is deprecated", async () => {
91+
const macOSDeprecatedVersion = MacOSVersions.Sierra;
92+
const macOSWarning = format(MacOSDeprecationStringFormat, macOSDeprecatedVersion);
93+
const warning = await getMacOSWarning(macOSDeprecatedVersion);
94+
assert.deepEqual(warning, macOSWarning);
95+
});
96+
});
97+
98+
describe("getSupportedNodeVersionRange", () => {
99+
it("returns range from CLI's package.json", () => {
100+
const testInjector = createTestInjector();
101+
const expectedRange = require("../package.json").engines.node;
102+
const fs = testInjector.resolve<IFileSystem>("fs");
103+
fs.readJson = () => require("../package.json");
104+
const sysInfo = testInjector.resolve<ISysInfo>("sysInfo");
105+
const actualRange = sysInfo.getSupportedNodeVersionRange();
106+
assert.equal(actualRange, expectedRange);
107+
});
108+
});
109+
});

0 commit comments

Comments
 (0)