Skip to content

Commit 86f280f

Browse files
author
Dimitar Tachev
authored
Merge pull request #4098 from NativeScript/tachev/merge-release
Merge release into master
2 parents 308a370 + 4edfd25 commit 86f280f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+680
-209
lines changed

CHANGELOG.md

+50
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,56 @@
11
NativeScript CLI Changelog
22
================
33

4+
5.0.0 (2018, November 1)
5+
==
6+
7+
### Breaking
8+
9+
* Existing applications that are using older Android runtime (not 5.0.0 one), but are built with CLI 5.0.0, may experience some changes - until now CLI was always passing parameter to gradle `-PsupportVersion=26.0.0-alpha1`. As CLI no longer passes this version, the default one from build.gradle will be used (for example 27.0.1). Check [this issue](https://github.com/NativeScript/nativescript-cli/pull/3923) for more information. In case you want to use the old version in your application, add the following in your `app.gradle`:
10+
```
11+
project.ext.supportVersion = "26.0.0-alpha1"
12+
```
13+
14+
* CLI will not allow building for iOS with Xcode 8 or below. Check [this issue](https://github.com/NativeScript/nativescript-cli/issues/3887) for more information.
15+
* CLI no longer support macOS Sierra and below. In case you are using such OS, CLI will print error message on each command. It will not stop you, but certain features will not work and we will not investigate them. `tns debug ios --inspector` will not work on macOS Sierra and below.
16+
* You will not be able to build applications for Android without installing Android SDK 28. You can install Android SDK 28 and build tools 28 by executing the following commands:
17+
```
18+
$ANDROID_HOME/tools/bin/sdkmanager "build-tools;28.0.1"
19+
$ANDROID_HOME/tools/bin/sdkmanager "platforms;android-28"
20+
```
21+
* `tns create` command is interactive now. In case you are using it in CI environment where the shell is marked as TTY (Travis for example), the CI will hang as it will wait for selection. You can get back the old behavior by passing `--js`: `tns create <name> --js`. In case the terminal is not interactive, CLI will use the old behavior. More information is available in [this issue](https://github.com/NativeScript/nativescript-cli/issues/3829).
22+
23+
### New
24+
* [Implemented #1945](https://github.com/NativeScript/nativescript-cli/issues/1945): Add `tns plugin create` command.
25+
* [Implemented #3040](https://github.com/NativeScript/nativescript-cli/issues/3040): Ability to have different app identifiers for iOS and Android.
26+
* [Implemented #3813](https://github.com/NativeScript/nativescript-cli/issues/3813): Ability to preview NativeScript apps without any local setup - `tns preview` command.
27+
* [Implemented #3829](https://github.com/NativeScript/nativescript-cli/issues/3829): Interactive `tns create`.
28+
* [Implemented #3843](https://github.com/NativeScript/nativescript-cli/issues/3843): Make new Android livesync reuse socket connection.
29+
* [Implemented #3866](https://github.com/NativeScript/nativescript-cli/issues/3866): Read registry from npm config instead of hard-wiring to registry.npmjs.org.
30+
* [Implemented #3875](https://github.com/NativeScript/nativescript-cli/issues/3875): Add hot module replacement option (`--hmr`) for `tns run [<platform>]` command - it will not to restart the app on js/ts changes.
31+
* [Implemented #3886](https://github.com/NativeScript/nativescript-cli/issues/3886): Drop support for macOS Sierra and below.
32+
* [Implemented #3887](https://github.com/NativeScript/nativescript-cli/issues/3887): CLI should not allow execution of iOS commands with Xcode 8 and below.
33+
* [Implemented #3923](https://github.com/NativeScript/nativescript-cli/pull/3923): Remove requirement for Android Support Repository local installation.
34+
* [Implemented #3991](https://github.com/NativeScript/nativescript-cli/issues/3991): Require Android SDK 28 for compilation.
35+
* [Implemented #4036](https://github.com/NativeScript/nativescript-cli/issues/4036): Ability to run with bundle option on multiple platforms - `tns run --bundle` command.
36+
37+
### Fixed
38+
* [Fixed #3549](https://github.com/NativeScript/nativescript-cli/issues/3549): Podfile generation broken on livesync
39+
* [Fixed #3686](https://github.com/NativeScript/nativescript-cli/issues/3686): Pod install fails with non-error message for fresh installations
40+
* [Fixed #3878](https://github.com/NativeScript/nativescript-cli/pull/3878): Prompter for mail on postinstall is very obligatory
41+
* [Fixed #3910](https://github.com/NativeScript/nativescript-cli/pull/3910): `tns platform add ios` should not be executed on non-macOS
42+
* [Fixed #3912](https://github.com/NativeScript/nativescript-cli/issues/3912): Build fails with Xcode 10 with error could not find included file `../plugins-debug.xcconfig` in search paths
43+
* [Fixed #3920](https://github.com/NativeScript/nativescript-cli/issues/3920): iOS apps will not start with Xcode 10
44+
* [Fixed #3932](https://github.com/NativeScript/nativescript-cli/issues/3932): Plugins' platforms directory should not exist in tns_modules
45+
* [Fixed #3934](https://github.com/NativeScript/nativescript-cli/issues/3934): Unable to create project from scoped package
46+
* [Fixed #3937](https://github.com/NativeScript/nativescript-cli/issues/3937): The app cannot be recovered with livesync after an unhandled exception on iOS
47+
* [Fixed #3957](https://github.com/NativeScript/nativescript-cli/issues/3957): Always have to run plugin tests twice on iOS - Failed to load Info.plist from bundle at path
48+
* [Fixed #3984](https://github.com/NativeScript/nativescript-cli/issues/3984): Files are not deleted from platforms folder on `tns run` command
49+
* [Fixed #3986](https://github.com/NativeScript/nativescript-cli/pull/3986): `tns debug ios` command fails in some cases on iOS Simulator
50+
* [Fixed #4007](https://github.com/NativeScript/nativescript-cli/issues/4007): Application built in release has TypeScript files
51+
* [Fixed #4010](https://github.com/NativeScript/nativescript-cli/issues/4010): `node_modules` are prepared twice on initial run
52+
53+
454
4.2.4 (2018, September 19)
555
==
656

docs/man_pages/project/testing/preview.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Generates a QR code that can be scanned by the NativeScript PlayGround app | `tn
2525

2626
### Options
2727

28-
* `--bundle` - Specifies that the `webpack` bundler will be used to bundle the application.<% if(isConsole) { %> The support for webpack in preview is currently in Beta. Please, do not hesitate to report any problems that you experience with the feature by opening a new issue in the NativeScript CLI repository: https://github.com/NativeScript/nativescript-cli/issues/new/choose.<% } %>
28+
* `--bundle` - (Beta) Specifies that the `webpack` bundler will be used to bundle the application.<% if(isConsole) { %> The support for webpack in preview is currently in Beta. Please, do not hesitate to report any problems that you experience with the feature by opening a new issue in the NativeScript CLI repository: https://github.com/NativeScript/nativescript-cli/issues/new/choose.<% } %>
2929
* `--hmr` - (Beta) Enables the hot module replacement (HMR) feature. HMR depends on `webpack` and adding the `--hmr` flag to the command will automatically enable the `--bundle` option as well.<% if(isConsole) { %> The HMR feature is currently in Beta. For more information about the current development state and any known issues, please check the relevant GitHub issue: https://github.com/NativeScript/NativeScript/issues/6398.<% } %>
3030

3131
<% if(isHtml) { %>

lib/bootstrap.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ $injector.require("usbLiveSyncService", "./services/livesync/livesync-service");
138138
$injector.require("previewAppLiveSyncService", "./services/livesync/playground/preview-app-livesync-service");
139139
$injector.require("previewAppPluginsService", "./services/livesync/playground/preview-app-plugins-service");
140140
$injector.require("previewSdkService", "./services/livesync/playground/preview-sdk-service");
141-
$injector.require("playgroundQrCodeGenerator", "./services/livesync/playground/qr-code-generator");
141+
$injector.requirePublicClass("previewDevicesService", "./services/livesync/playground/devices/preview-devices-service");
142+
$injector.requirePublic("previewQrCodeService", "./services/livesync/playground/preview-qr-code-service");
142143
$injector.requirePublic("sysInfo", "./sys-info");
143144

144145
$injector.require("iOSNotificationService", "./services/ios-notification-service");

lib/commands/preview.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ export class PreviewCommand implements ICommand {
33
private static MIN_SUPPORTED_WEBPACK_VERSION = "0.17.0";
44

55
constructor(private $bundleValidatorHelper: IBundleValidatorHelper,
6+
private $errors: IErrors,
67
private $liveSyncService: ILiveSyncService,
78
private $networkConnectivityValidator: INetworkConnectivityValidator,
89
private $projectData: IProjectData,
910
private $options: IOptions,
10-
private $playgroundQrCodeGenerator: IPlaygroundQrCodeGenerator) { }
11+
private $previewQrCodeService: IPreviewQrCodeService) { }
1112

1213
public async execute(): Promise<void> {
1314
await this.$liveSyncService.liveSync([], {
@@ -23,10 +24,14 @@ export class PreviewCommand implements ICommand {
2324
useHotModuleReload: this.$options.hmr
2425
});
2526

26-
await this.$playgroundQrCodeGenerator.generateQrCode({ useHotModuleReload: this.$options.hmr, link: this.$options.link });
27+
await this.$previewQrCodeService.printLiveSyncQrCode({ useHotModuleReload: this.$options.hmr, link: this.$options.link });
2728
}
2829

2930
public async canExecute(args: string[]): Promise<boolean> {
31+
if (args && args.length) {
32+
this.$errors.fail(`The arguments '${args.join(" ")}' are not valid for the preview command.`);
33+
}
34+
3035
await this.$networkConnectivityValidator.validate();
3136
this.$bundleValidatorHelper.validate(PreviewCommand.MIN_SUPPORTED_WEBPACK_VERSION);
3237
return true;

lib/commands/test-init.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,10 @@ class TestInitCommand implements ICommand {
9393
await this.$pluginsService.add('nativescript-unit-test-runner', this.$projectData);
9494

9595
const testsDir = path.join(this.$projectData.appDirectoryPath, 'tests');
96+
const relativeTestsDir = path.relative(this.$projectData.projectDir, testsDir);
9697
let shouldCreateSampleTests = true;
9798
if (this.$fs.exists(testsDir)) {
98-
this.$logger.info('app/tests/ directory already exists, will not create an example test project.');
99+
this.$logger.info(`${relativeTestsDir} directory already exists, will not create an example test project.`);
99100
shouldCreateSampleTests = false;
100101
}
101102

@@ -104,18 +105,19 @@ class TestInitCommand implements ICommand {
104105
const frameworks = [frameworkToInstall].concat(this.karmaConfigAdditionalFrameworks[frameworkToInstall] || [])
105106
.map(fw => `'${fw}'`)
106107
.join(', ');
108+
const testFiles = `'${relativeTestsDir}/**/*.js'`;
107109
const karmaConfTemplate = this.$resources.readText('test/karma.conf.js');
108-
const karmaConf = _.template(karmaConfTemplate)({ frameworks });
110+
const karmaConf = _.template(karmaConfTemplate)({ frameworks, testFiles });
109111

110112
this.$fs.writeFile(path.join(projectDir, 'karma.conf.js'), karmaConf);
111113

112114
const exampleFilePath = this.$resources.resolvePath(`test/example.${frameworkToInstall}.js`);
113115

114116
if (shouldCreateSampleTests && this.$fs.exists(exampleFilePath)) {
115117
this.$fs.copyFile(exampleFilePath, path.join(testsDir, 'example.js'));
116-
this.$logger.info('\nExample test file created in app/tests/'.yellow);
118+
this.$logger.info(`\nExample test file created in ${relativeTestsDir}`.yellow);
117119
} else {
118-
this.$logger.info('\nPlace your test files under app/tests/'.yellow);
120+
this.$logger.info(`\nPlace your test files under ${relativeTestsDir}`.yellow);
119121
}
120122

121123
this.$logger.info('Run your tests using the "$ tns test <platform>" command.'.yellow);

lib/common/constants.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,5 +155,5 @@ export class AndroidVirtualDevice {
155155
static TIMEOUT_SECONDS = 120;
156156
static GENYMOTION_DEFAULT_STDERR_STRING = "Logging activities to file";
157157

158-
static UNABLE_TO_START_EMULATOR_MESSAGE = "Cannot run your app in the native emulator. Increase the timeout of the operation with the --timeout option or try to restart your adb server with 'adb kill-server' command. Alternatively, run the Android Virtual Device manager and increase the allocated RAM for the virtual device.";
158+
static UNABLE_TO_START_EMULATOR_MESSAGE = "Cannot run the app in the selected native emulator. Try to restart the adb server by running the `adb kill-server` command in the Command Prompt, or increase the allocated RAM of the virtual device through the Android Virtual Device manager. NativeScript CLI users can try to increase the timeout of the operation by adding the `--timeout` flag.";
159159
}

lib/common/declarations.d.ts

+15
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,21 @@ interface IQrCodeGenerator {
969969
generateDataUri(data: string): Promise<string>;
970970
}
971971

972+
interface IQrCodeImageData {
973+
/**
974+
* The original URL used for generating QR code image.
975+
*/
976+
originalUrl: string;
977+
/**
978+
* The shorten URL used for generating QR code image.
979+
*/
980+
shortenUrl: string;
981+
/**
982+
* Base64 encoded data used for generating QR code image.
983+
*/
984+
imageData: string;
985+
}
986+
972987
interface IDynamicHelpProvider {
973988
/**
974989
* Checks if current project's framework is one of the specified as arguments.

lib/common/definitions/mobile.d.ts

+23-5
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,6 @@ declare module Mobile {
143143
--predicate 'eventType == logEvent and subsystem contains "com.example.my_subsystem"'
144144
*/
145145
predicate?: string;
146-
/**
147-
* If set to true, device's log will not be displayed on the console.
148-
*/
149-
muted?: boolean;
150146
}
151147

152148
interface IDeviceAppData extends IPlatform, IConnectTimeoutOption {
@@ -221,12 +217,18 @@ declare module Mobile {
221217
* @param {string} projectName The project name of the currently running application for which we need the logs.
222218
*/
223219
setProjectNameForDevice(deviceIdentifier: string, projectName: string): void;
220+
221+
/**
222+
* Disables logs on the specified device and does not print any logs on the console.
223+
* @param {string} deviceIdentifier The unique identifier of the device.
224+
*/
225+
muteLogsForDevice(deviceIdentifier: string): void;
224226
}
225227

226228
/**
227229
* Describes different options for filtering device logs.
228230
*/
229-
interface IDeviceLogOptions extends IStringDictionary {
231+
interface IDeviceLogOptions extends IDictionary<string | boolean> {
230232
/**
231233
* Process id of the application on the device.
232234
*/
@@ -241,6 +243,11 @@ declare module Mobile {
241243
* The project name.
242244
*/
243245
projectName?: string;
246+
247+
/**
248+
* Specifies if the logs will be printed on the console.
249+
*/
250+
muteLogs?: boolean;
244251
}
245252

246253
/**
@@ -730,6 +737,12 @@ declare module Mobile {
730737
* @returns {Promise<IStartEmulatorOutput>} Starts the emulator and returns the errors if some error occurs.
731738
*/
732739
startEmulator(options: Mobile.IStartEmulatorOptions): Promise<IStartEmulatorOutput>;
740+
741+
/**
742+
* Called when emulator is lost. Its purpose is to clean any resources used by the instance.
743+
* @returns {void}
744+
*/
745+
detach?(deviceInfo: Mobile.IDeviceInfo): void;
733746
}
734747

735748
interface IStartEmulatorOutput {
@@ -772,6 +785,11 @@ declare module Mobile {
772785
* @param imageIdentifier - The imagerIdentifier of the emulator.
773786
*/
774787
startEmulatorArgs(imageIdentifier: string): string[];
788+
/**
789+
* Called when emulator is lost. Its purpose is to clean any resources used by the instance.
790+
* @returns {void}
791+
*/
792+
detach?(deviceInfo: Mobile.IDeviceInfo): void;
775793
}
776794

777795
interface IVirtualBoxService {

lib/common/mobile/android/android-device.ts

+6
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ export class AndroidDevice implements Mobile.IAndroidDevice {
121121
}
122122
}
123123

124+
public detach(): void {
125+
if (this.isEmulator) {
126+
this.$androidEmulatorServices.detach(this.deviceInfo);
127+
}
128+
}
129+
124130
private async getDeviceDetails(shellCommandArgs: string[]): Promise<IAndroidDeviceDetails> {
125131
const parsedDetails: any = {};
126132

lib/common/mobile/android/android-emulator-services.ts

+4
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ export class AndroidEmulatorServices implements Mobile.IEmulatorPlatformService
5959
};
6060
}
6161

62+
public detach(deviceInfo: Mobile.IDeviceInfo) {
63+
this.$androidVirtualDeviceService.detach(deviceInfo);
64+
}
65+
6266
private async startEmulatorCore(options: Mobile.IAndroidStartEmulatorOptions): Promise<{runningEmulator: Mobile.IDeviceInfo, errors: string[], endTimeEpoch: number}> {
6367
const timeout = options.timeout || AndroidVirtualDevice.TIMEOUT_SECONDS;
6468
const endTimeEpoch = getCurrentEpochTime() + this.$utils.getMilliSecondsTimeout(timeout);

lib/common/mobile/android/android-virtual-device-service.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,16 @@ export class AndroidVirtualDeviceService implements Mobile.IAndroidVirtualDevice
142142
});
143143
}
144144

145+
public detach(deviceInfo: Mobile.IDeviceInfo) {
146+
if (this.mapEmulatorIdToImageIdentifier[deviceInfo.identifier]) {
147+
delete this.mapEmulatorIdToImageIdentifier[deviceInfo.identifier];
148+
}
149+
}
150+
145151
private async getEmulatorImagesCore(): Promise<Mobile.IEmulatorImagesOutput> {
146152
let result: ISpawnResult = null;
147153
let devices: Mobile.IDeviceInfo[] = [];
154+
let errors: string[] = [];
148155

149156
if (this.pathToAvdManagerExecutable && this.$fs.exists(this.pathToAvdManagerExecutable)) {
150157
result = await this.$childProcess.trySpawnFromCloseEvent(this.pathToAvdManagerExecutable, ["list", "avds"]);
@@ -154,11 +161,12 @@ export class AndroidVirtualDeviceService implements Mobile.IAndroidVirtualDevice
154161

155162
if (result && result.stdout) {
156163
devices = this.parseListAvdsOutput(result.stdout);
164+
errors = result && result.stderr ? [result.stderr] : [];
157165
} else {
158166
devices = this.listAvdsFromDirectory();
159167
}
160168

161-
return { devices, errors: result && result.stderr ? [result.stderr] : [] };
169+
return { devices, errors };
162170
}
163171

164172
private async getRunningEmulatorData(runningEmulatorId: string, availableEmulators: Mobile.IDeviceInfo[]): Promise<Mobile.IDeviceInfo> {

lib/common/mobile/android/logcat-helper.ts

+14-14
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,6 @@ export class LogcatHelper implements Mobile.ILogcatHelper {
5858
}
5959
}
6060

61-
private async getLogcatStream(deviceIdentifier: string, pid?: string) {
62-
const device = await this.$devicesService.getDevice(deviceIdentifier);
63-
const minAndroidWithLogcatPidSupport = "7.0.0";
64-
const isLogcatPidSupported = semver.gte(semver.coerce(device.deviceInfo.version), minAndroidWithLogcatPidSupport);
65-
const adb: Mobile.IDeviceAndroidDebugBridge = this.$injector.resolve(DeviceAndroidDebugBridge, { identifier: deviceIdentifier });
66-
const logcatCommand = ["logcat"];
67-
68-
if (pid && isLogcatPidSupported) {
69-
logcatCommand.push(`--pid=${pid}`);
70-
}
71-
const logcatStream = await adb.executeCommand(logcatCommand, { returnChildProcess: true });
72-
return logcatStream;
73-
}
74-
7561
public async dump(deviceIdentifier: string): Promise<void> {
7662
const adb: Mobile.IDeviceAndroidDebugBridge = this.$injector.resolve(DeviceAndroidDebugBridge, { identifier: deviceIdentifier });
7763
const logcatDumpStream = await adb.executeCommand(["logcat", "-d"], { returnChildProcess: true });
@@ -101,6 +87,20 @@ export class LogcatHelper implements Mobile.ILogcatHelper {
10187
delete this.mapDevicesLoggingData[deviceIdentifier];
10288
}
10389
}
90+
91+
private async getLogcatStream(deviceIdentifier: string, pid?: string) {
92+
const device = await this.$devicesService.getDevice(deviceIdentifier);
93+
const minAndroidWithLogcatPidSupport = "7.0.0";
94+
const isLogcatPidSupported = !!device.deviceInfo.version && semver.gte(semver.coerce(device.deviceInfo.version), minAndroidWithLogcatPidSupport);
95+
const adb: Mobile.IDeviceAndroidDebugBridge = this.$injector.resolve(DeviceAndroidDebugBridge, { identifier: deviceIdentifier });
96+
const logcatCommand = ["logcat"];
97+
98+
if (pid && isLogcatPidSupported) {
99+
logcatCommand.push(`--pid=${pid}`);
100+
}
101+
const logcatStream = await adb.executeCommand(logcatCommand, { returnChildProcess: true });
102+
return logcatStream;
103+
}
104104
}
105105

106106
$injector.register("logcatHelper", LogcatHelper);

lib/common/mobile/device-log-provider-base.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export abstract class DeviceLogProviderBase extends EventEmitter implements Mobi
2626
this.setLogLevel(logLevel, deviceIdentifier);
2727
}
2828

29+
public muteLogsForDevice(deviceIdentifier: string): void {
30+
this.setDeviceLogOptionsProperty(deviceIdentifier, (deviceLogOptions: Mobile.IDeviceLogOptions) => deviceLogOptions.muteLogs, true);
31+
}
32+
2933
protected getApplicationPidForDevice(deviceIdentifier: string): string {
3034
return this.devicesLogOptions[deviceIdentifier] && this.devicesLogOptions[deviceIdentifier].applicationPid;
3135
}
@@ -39,7 +43,7 @@ export abstract class DeviceLogProviderBase extends EventEmitter implements Mobi
3943
return this.devicesLogOptions[deviceIdentifier];
4044
}
4145

42-
protected setDeviceLogOptionsProperty(deviceIdentifier: string, propNameFunction: Function, propertyValue: string): void {
46+
protected setDeviceLogOptionsProperty(deviceIdentifier: string, propNameFunction: Function, propertyValue: string | boolean): void {
4347
const propertyName = getPropertyName(propNameFunction);
4448

4549
if (propertyName) {

0 commit comments

Comments
 (0)