Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
9b83cda
WIP
nadyaA May 10, 2017
33d79ab
Move OS compatibility check to commands
nadyaA May 16, 2017
8ccf75f
New LiveSync
rosen-vladimirov May 31, 2017
a0f037e
WIP
rosen-vladimirov Jun 4, 2017
33371a4
WIP next
rosen-vladimirov Jun 5, 2017
19b7fca
Add useLiveEdit option
rosen-vladimirov Jun 5, 2017
1765397
Update Public API interfaces
rosen-vladimirov Jun 5, 2017
823f1c5
Add events for LiveSync
rosen-vladimirov Jun 5, 2017
f45f1e3
Add correct events for LiveSync
rosen-vladimirov Jun 5, 2017
cd7f808
Add docs and improve liveSync operations when called multiple times f…
rosen-vladimirov Jun 6, 2017
e293ef9
Fix liveSync - add correct check for deviceDescriptors
rosen-vladimirov Jun 6, 2017
2c4d0c9
Delete AndroidAppIdentifier
Jun 5, 2017
b3b7df8
Remove device-path-provider
Jun 6, 2017
4aafecc
Fix multiple rebuilds for the same platform
rosen-vladimirov Jun 6, 2017
6b3662d
Fix unit tests
rosen-vladimirov Jun 6, 2017
0f9c0aa
Extract all common logic of livesync services to platform-livesync-se…
rosen-vladimirov Jun 6, 2017
4dfc040
Remove livesync-provider
rosen-vladimirov Jun 6, 2017
3a38e78
Add notify event during LiveSync
rosen-vladimirov Jun 6, 2017
869c95a
Rename error event to liveSyncError
rosen-vladimirov Jun 6, 2017
96af540
Do not kill ios-device-lib in `tns run`
rosen-vladimirov Jun 7, 2017
4d6b990
WIP
TsvetanMilanov Jun 7, 2017
f11d405
Expose saveBuildInfoFile
Jun 8, 2017
4eb8d7f
Fix always reinstalling apps during livesync
rosen-vladimirov Jun 9, 2017
4bb0330
Minor bugfixes
Jun 9, 2017
e6c2821
Move notification service to common
Jun 9, 2017
4e4197e
Fix Success livesync and run fail messages
Jun 9, 2017
e377340
Implement tracking
Jun 9, 2017
75578ea
Fix lint errors
Jun 9, 2017
03f0537
Fix message for tests
Jun 12, 2017
e2205c6
Fix comments vol. I
Jun 12, 2017
82ba18f
Cache sockets per app per device
rosen-vladimirov Jun 12, 2017
013c5fa
Fix run
Jun 12, 2017
714275c
Fix run not starting emulator
Jun 13, 2017
64080f7
Pass emulator flag and fix process.platform messages
Jun 13, 2017
c6127ea
Fix chrome debug message
Jun 13, 2017
f32f243
Do not determine dynamic dependencies on Windows
nadyaA Jun 14, 2017
5b1141c
Restart app upon debugging
Jun 15, 2017
0acb22d
Update common to latest master
Jun 15, 2017
baab31b
Remove obsolete vendor directory
Jun 15, 2017
7b2f1ab
Fix run with --release and --clean
Jun 14, 2017
f3dc66e
Fix unit tests
rosen-vladimirov Jun 14, 2017
b4b4232
Fix debug-service unit tests
rosen-vladimirov Jun 15, 2017
b74d44d
Update ios-device-lib to 0.4.4
rosen-vladimirov Jun 15, 2017
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
203 changes: 203 additions & 0 deletions PublicAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,32 @@ This document describes all methods that can be invoked when NativeScript CLI is
const tns = require("nativescript");
```

# Contents
* [projectService](#projectservice)
* [createProject](#createproject)
* [isValidNativeScriptProject](#isvalidnativescriptproject)
* [extensibilityService](#extensibilityservice)
* [installExtension](#installextension)
* [uninstallExtension](#uninstallextension)
* [getInstalledExtensions](#getinstalledextensions)
* [loadExtensions](#loadextensions)
* [settingsService](#settingsservice)
* [setSettings](#setsettings)
* [npm](#npm)
* [install](#install)
* [uninstall](#uninstall)
* [search](#search)
* [view](#view)
* [analyticsService](#analyticsservice)
* [startEqatecMonitor](#starteqatecmonitor)
* [debugService](#debugservice)
* [debug](#debug)
* [liveSyncService](#livesyncservice)
* [liveSync](#livesync)
* [stopLiveSync](#stopLiveSync)
* [events](#events)


## Module projectService

`projectService` modules allow you to create new NativeScript application.
Expand Down Expand Up @@ -498,6 +524,183 @@ tns.debugService.debug(debugData, debugOptions)
.catch(err => console.log(`Unable to start debug operation, reason: ${err.message}.`));
```

## liveSyncService
Used to LiveSync changes on devices. The operation can be started for multiple devices and stopped for each of them. During LiveSync operation, the service will emit different events based on the action that's executing.

### liveSync
Starts a LiveSync operation for specified devices. During the operation, application may have to be rebuilt (for example in case a change in App_Resources is detected).
By default the LiveSync operation will start file system watcher for `<project dir>/app` directory and any change in it will trigger a LiveSync operation.
After calling the method once, you can add new devices to the same LiveSync operation by calling the method again with the new device identifiers.

> NOTE: Consecutive calls to `liveSync` method for the same project will execute the initial sync (deploy and fullSync) only for new device identifiers. So in case the first call is for devices with ids [ 'A' , 'B' ] and the second one is for devices with ids [ 'B', 'C' ], the initial sync will be executed only for device with identifier 'C'.

> NOTE: In case a consecutive call to `liveSync` method requires change in the pattern for watching files (i.e. `liveSyncData.syncAllFiles` option has changed), current watch operation will be stopped and a new one will be started.

* Definition
```TypeScript
/**
* Starts LiveSync operation by rebuilding the application if necessary and starting watcher.
* @param {ILiveSyncDeviceInfo[]} deviceDescriptors Describes each device for which we would like to sync the application - identifier, outputPath and action to rebuild the app.
* @param {ILiveSyncInfo} liveSyncData Describes the LiveSync operation - for which project directory is the operation and other settings.
* @returns {Promise<void>}
*/
liveSync(deviceDescriptors: ILiveSyncDeviceInfo[], liveSyncData: ILiveSyncInfo): Promise<void>;
```

* Usage:
```JavaScript
const projectDir = "myProjectDir";
const androidDeviceDescriptor = {
identifier: "4df18f307d8a8f1b",
buildAction: () => {
return tns.localBuildService.build("Android", { projectDir, bundle: false, release: false, buildForDevice: true });
},
outputPath: null
};

const iOSDeviceDescriptor = {
identifier: "12318af23ebc0e25",
buildAction: () => {
return tns.localBuildService.build("iOS", { projectDir, bundle: false, release: false, buildForDevice: true });
},
outputPath: null
};

const liveSyncData = {
projectDir,
skipWatcher: false,
watchAllFiles: false,
useLiveEdit: false
};

tns.liveSyncService.liveSync([ androidDeviceDescriptor, iOSDeviceDescriptor ], liveSyncData)
.then(() => {
console.log("LiveSync operation started.");
}, err => {
console.log("An error occurred during LiveSync", err);
});
```

### stopLiveSync
Stops LiveSync operation. In case deviceIdentifires are passed, the operation will be stopped only for these devices.

* Definition
```TypeScript
/**
* Stops LiveSync operation for specified directory.
* @param {string} projectDir The directory for which to stop the operation.
* @param {string[]} @optional deviceIdentifiers Device ids for which to stop the application. In case nothing is passed, LiveSync operation will be stopped for all devices.
* @returns {Promise<void>}
*/
stopLiveSync(projectDir: string, deviceIdentifiers?: string[]): Promise<void>;
```

* Usage
```JavaScript
const projectDir = "myProjectDir";
const deviceIdentifiers = [ "4df18f307d8a8f1b", "12318af23ebc0e25" ];
tns.liveSyncService.stopLiveSync(projectDir, deviceIdentifiers)
.then(() => {
console.log("LiveSync operation stopped.");
}, err => {
console.log("An error occurred during stopage.", err);
});
```

### Events
`liveSyncService` raises several events in order to provide information for current state of the operation.
* liveSyncStarted - raised whenever CLI starts a LiveSync operation for specific device. When `liveSync` method is called, the initial LiveSync operation will emit `liveSyncStarted` for each specified device. After that the event will be emitted only in case when liveSync method is called again with different device instances. The event is raised with the following data:
```TypeScript
{
projectDir: string;
deviceIdentifier: string;
applicationIdentifier: string;
}
```

Example:
```JavaScript
tns.liveSyncService.on("liveSyncStarted", data => {
console.log(`Started LiveSync on ${data.deviceIdentifier} for ${data.applicationIdentifier}.`);
});
```

* liveSyncExecuted - raised whenever CLI finishes a LiveSync operation for specific device. When `liveSync` method is called, the initial LiveSync operation will emit `liveSyncExecuted` for each specified device once it finishes the operation. After that the event will be emitted whenever a change is detected (in case file system watcher is started) and the LiveSync operation is executed for each device. The event is raised with the following data:
```TypeScript
{
projectDir: string;
deviceIdentifier: string;
applicationIdentifier: string;
/**
* Full paths to files synced during the operation. In case the `syncedFiles.length` is 0, the operation is "fullSync" (i.e. all project files are synced).
*/
syncedFiles: string[];
}
```

Example:
```JavaScript
tns.liveSyncService.on("liveSyncExecuted", data => {
console.log(`Executed LiveSync on ${data.deviceIdentifier} for ${data.applicationIdentifier}. Uploaded files are: ${data.syncedFiles.join(" ")}.`);
});
```

* liveSyncStopped - raised when LiveSync operation is stopped. The event will be raised when the operation is stopped for each device and will be raised when the whole operation is stopped. The event is raised with the following data:
```TypeScript
{
projectDir: string;
/**
* Passed only when the LiveSync operation is stopped for a specific device. In case it is not passed, the whole LiveSync operation is stopped.
*/
deviceIdentifier?: string;
}
```

Example:
```JavaScript
tns.liveSyncService.on("liveSyncStopped", data => {
if (data.deviceIdentifier) {
console.log(`Stopped LiveSync on ${data.deviceIdentifier} for ${data.projectDir}.`);
} else {
console.log(`Stopped LiveSync for ${data.projectDir}.`);
}
});
```

* liveSyncError - raised whenever an error is detected during LiveSync operation. The event is raised for specific device. Once an error is detected, the event will be raised and the LiveSync operation will be stopped for this device, i.e. `liveSyncStopped` event will be raised for it. The event is raised with the following data:
```TypeScript
{
projectDir: string;
deviceIdentifier: string;
applicationIdentifier: string;
error: Error;
}
```

Example:
```JavaScript
tns.liveSyncService.on("liveSyncError", data => {
console.log(`Error detected during LiveSync on ${data.deviceIdentifier} for ${data.projectDir}. Error: ${data.error.message}.`);
});
```

* notify - raised when LiveSync operation has some data that is important for the user. The event is raised for specific device. The event is raised with the following data:
```TypeScript
{
projectDir: string;
deviceIdentifier: string;
applicationIdentifier: string;
notification: string;
}
```

Example:
```JavaScript
tns.liveSyncService.on("notify", data => {
console.log(`Notification: ${data.notification} for LiveSync operation on ${data.deviceIdentifier} for ${data.projectDir}. `);
});
```

## 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.
For example the `$options` injected module contains information about all `--` options passed on the terminal. When the CLI is used as a library, the options are not populated. Before adding method to public API, make sure its implementation does not rely on `$options`.
Expand Down
12 changes: 7 additions & 5 deletions lib/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ $injector.require("platformsData", "./platforms-data");
$injector.require("platformService", "./services/platform-service");

$injector.require("debugDataService", "./services/debug-data-service");
$injector.requirePublicClass("debugService", "./services/debug-service");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the whole class is public ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it is an EventEmitter

$injector.require("iOSDebugService", "./services/ios-debug-service");
$injector.require("androidDebugService", "./services/android-debug-service");

Expand All @@ -39,6 +40,7 @@ $injector.requireCommand("platform|*list", "./commands/list-platforms");
$injector.requireCommand("platform|add", "./commands/add-platform");
$injector.requireCommand("platform|remove", "./commands/remove-platform");
$injector.requireCommand("platform|update", "./commands/update-platform");
$injector.requireCommand("run|*all", "./commands/run");
$injector.requireCommand("run|ios", "./commands/run");
$injector.requireCommand("run|android", "./commands/run");

Expand Down Expand Up @@ -74,7 +76,6 @@ $injector.require("commandsServiceProvider", "./providers/commands-service-provi
$injector.require("deviceAppDataProvider", "./providers/device-app-data-provider");

$injector.require("deviceLogProvider", "./common/mobile/device-log-provider");
$injector.require("liveSyncProvider", "./providers/livesync-provider");
$injector.require("projectFilesProvider", "./providers/project-files-provider");

$injector.require("nodeModulesBuilder", "./tools/node-modules/node-modules-builder");
Expand All @@ -99,14 +100,15 @@ $injector.require("infoService", "./services/info-service");
$injector.requireCommand("info", "./commands/info");

$injector.require("androidToolsInfo", "./android-tools-info");
$injector.require("devicePathProvider", "./device-path-provider");

$injector.requireCommand("platform|clean", "./commands/platform-clean");

$injector.requirePublicClass("liveSyncService", "./services/livesync/livesync-service");
$injector.require("debugLiveSyncService", "./services/livesync/debug-livesync-service");
$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("iosLiveSyncServiceLocator", "./services/livesync/ios-device-livesync-service");
$injector.require("androidLiveSyncServiceLocator", "./services/livesync/android-device-livesync-service");
$injector.require("platformLiveSyncService", "./services/livesync/platform-livesync-service");

$injector.require("sysInfo", "./sys-info");

$injector.require("iOSNotificationService", "./services/ios-notification-service");
Expand Down
12 changes: 11 additions & 1 deletion lib/commands/appstore-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@ export class ListiOSApps implements ICommand {
constructor(private $injector: IInjector,
private $itmsTransporterService: IITMSTransporterService,
private $logger: ILogger,
private $prompter: IPrompter) { }
private $projectData: IProjectData,
private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants,
private $platformService: IPlatformService,
private $errors: IErrors,
private $prompter: IPrompter) {
this.$projectData.initializeProjectData();
}

public async execute(args: string[]): Promise<void> {
if (!this.$platformService.isPlatformSupportedForOS(this.$devicePlatformsConstants.iOS, this.$projectData)) {
this.$errors.fail(`Applications for platform ${this.$devicePlatformsConstants.iOS} can not be built on this OS`);
}

let username = args[0],
password = args[1];

Expand Down
5 changes: 2 additions & 3 deletions lib/commands/appstore-upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export class PublishIOS implements ICommand {
new StringCommandParameter(this.$injector), new StringCommandParameter(this.$injector)];

constructor(private $errors: IErrors,
private $hostInfo: IHostInfo,
private $injector: IInjector,
private $itmsTransporterService: IITMSTransporterService,
private $logger: ILogger,
Expand Down Expand Up @@ -100,8 +99,8 @@ export class PublishIOS implements ICommand {
}

public async canExecute(args: string[]): Promise<boolean> {
if (!this.$hostInfo.isDarwin) {
this.$errors.failWithoutHelp("This command is only available on Mac OS X.");
if (!this.$platformService.isPlatformSupportedForOS(this.$devicePlatformsConstants.iOS, this.$projectData)) {
this.$errors.fail(`Applications for platform ${this.$devicePlatformsConstants.iOS} can not be built on this OS`);
}

return true;
Expand Down
19 changes: 16 additions & 3 deletions lib/commands/build.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
export class BuildCommandBase {
constructor(protected $options: IOptions,
protected $errors: IErrors,
protected $projectData: IProjectData,
protected $platformsData: IPlatformsData,
protected $devicePlatformsConstants: Mobile.IDevicePlatformsConstants,
protected $platformService: IPlatformService) {
this.$projectData.initializeProjectData();
}
Expand Down Expand Up @@ -29,23 +31,32 @@ export class BuildCommandBase {
this.$platformService.copyLastOutput(platform, this.$options.copyTo, buildConfig, this.$projectData);
}
}

protected validatePlatform(platform: string): void {
if (!this.$platformService.isPlatformSupportedForOS(platform, this.$projectData)) {
this.$errors.fail(`Applications for platform ${platform} can not be built on this OS`);
}
}
}

export class BuildIosCommand extends BuildCommandBase implements ICommand {
public allowedParameters: ICommandParameter[] = [];

constructor(protected $options: IOptions,
$errors: IErrors,
$projectData: IProjectData,
$platformsData: IPlatformsData,
$devicePlatformsConstants: Mobile.IDevicePlatformsConstants,
$platformService: IPlatformService) {
super($options, $projectData, $platformsData, $platformService);
super($options, $errors, $projectData, $platformsData, $devicePlatformsConstants, $platformService);
}

public async execute(args: string[]): Promise<void> {
return this.executeCore([this.$platformsData.availablePlatforms.iOS]);
}

public canExecute(args: string[]): Promise<boolean> {
super.validatePlatform(this.$devicePlatformsConstants.iOS);
return args.length === 0 && this.$platformService.validateOptions(this.$options.provision, this.$projectData, this.$platformsData.availablePlatforms.iOS);
}
}
Expand All @@ -56,18 +67,20 @@ export class BuildAndroidCommand extends BuildCommandBase implements ICommand {
public allowedParameters: ICommandParameter[] = [];

constructor(protected $options: IOptions,
protected $errors: IErrors,
$projectData: IProjectData,
$platformsData: IPlatformsData,
private $errors: IErrors,
$devicePlatformsConstants: Mobile.IDevicePlatformsConstants,
$platformService: IPlatformService) {
super($options, $projectData, $platformsData, $platformService);
super($options, $errors, $projectData, $platformsData, $devicePlatformsConstants, $platformService);
}

public async execute(args: string[]): Promise<void> {
return this.executeCore([this.$platformsData.availablePlatforms.Android]);
}

public async canExecute(args: string[]): Promise<boolean> {
super.validatePlatform(this.$devicePlatformsConstants.Android);
if (this.$options.release && (!this.$options.keyStorePath || !this.$options.keyStorePassword || !this.$options.keyStoreAlias || !this.$options.keyStoreAliasPassword)) {
this.$errors.fail("When producing a release build, you need to specify all --key-store-* options.");
}
Expand Down
Loading