Skip to content

Commit

Permalink
Expose enable/disable debugging
Browse files Browse the repository at this point in the history
Expose enable/disable debugging when CLI is required as a library.
Includes:
* Unify `debug-livesync-service` and `livesync-service` into one class. Enable said class to attach a debugger at runtime during LiveSync
* Remove redundant `debugLivesync` property from `$config` and its every usage
* Remove redundant `debugStop` code in `android-debug-service`
* Raise events in the event of inability to start/stop the app on iOS
  • Loading branch information
Dimitar Kerezov committed Aug 23, 2017
1 parent e6eda41 commit 7922411
Show file tree
Hide file tree
Showing 30 changed files with 532 additions and 400 deletions.
98 changes: 98 additions & 0 deletions PublicAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,8 @@ After calling the method once, you can add new devices to the same LiveSync oper
> 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.
> NOTE: In case `debugggingEnabled` is set to `true` in a deviceDescriptor, debugging will initially be enabled for that device and a debugger will be attached after a successful livesync operation.
* Definition
```TypeScript
/**
Expand Down Expand Up @@ -623,6 +625,92 @@ tns.liveSyncService.stopLiveSync(projectDir, deviceIdentifiers)
});
```
### enableDebugging
Enables debugging during a LiveSync operation. This method will try to attach a debugger to the application. Note that `userInteractionNeeded` event may be raised. Additional details about the arguments can be seen [here](https://github.com/NativeScript/nativescript-cli/blob/master/lib/definitions/livesync.d.ts).
* Definition
```TypeScript
/**
* Enables debugging for the specified devices
* @param {IEnableDebuggingDeviceOptions[]} deviceOpts Settings used for enabling debugging for each device.
* @param {IDebuggingAdditionalOptions} enableDebuggingOptions Settings used for enabling debugging.
* @returns {Promise<void>[]} Array of promises for each device.
*/
enableDebugging(deviceOpts: IEnableDebuggingDeviceOptions[], enableDebuggingOptions: IDebuggingAdditionalOptions): Promise<void>[];
```
* Usage
```JavaScript
const projectDir = "/tmp/myProject";
const liveSyncData = { projectDir };
const devices = [androidDeviceDescriptor, iOSDeviceDescriptor];
tns.liveSyncService.liveSync(devices, liveSyncData)
.then(() => {
console.log("LiveSync operation started.");
devices.forEach(device => {
tns.liveSyncService.enableDebugging([{
deviceIdentifier: device.identifier
}], { projectDir });
});
});
```
### attachDebugger
Attaches a debugger to the specified device. Additional details about the argument can be seen [here](https://github.com/NativeScript/nativescript-cli/blob/master/lib/definitions/livesync.d.ts).
* Definition
```TypeScript
/**
* Attaches a debugger to the specified device.
* @param {IAttachDebuggerOptions} settings Settings used for controling the attaching process.
* @returns {Promise<void>}
*/
attachDebugger(settings: IAttachDebuggerOptions): Promise<void>;
```
* Usage
```JavaScript
tns.liveSyncService.on("userInteractionNeeded", data => {
console.log("Please restart the app manually");
return tns.liveSyncService.attachDebugger(data);
});
```
### disableDebugging
Disables debugging during a LiveSync operation. This method will try to detach a debugger from the application. Additional details about the arguments can be seen [here](https://github.com/NativeScript/nativescript-cli/blob/master/lib/definitions/livesync.d.ts).
* Definition
```TypeScript
/**
* Disables debugging for the specified devices
* @param {IDisableDebuggingDeviceOptions[]} deviceOptions Settings used for disabling debugging for each device.
* @param {IDebuggingAdditionalOptions} debuggingAdditionalOptions Settings used for disabling debugging.
* @returns {Promise<void>[]} Array of promises for each device.
*/
disableDebugging(deviceOptions: IDisableDebuggingDeviceOptions[], debuggingAdditionalOptions: IDebuggingAdditionalOptions): Promise<void>[];
```
* Usage
```JavaScript
const projectDir = "/tmp/myProject";
const liveSyncData = { projectDir };
const devices = [androidDeviceDescriptor, iOSDeviceDescriptor];
tns.liveSyncService.liveSync(devices, liveSyncData)
.then(() => {
console.log("LiveSync operation started.");
devices.forEach(device => {
tns.liveSyncService.enableDebugging([{
deviceIdentifier: device.identifier
}], { projectDir });
setTimeout(() => {
tns.liveSyncService.disableDebugging([{
deviceIdentifier: device.identifier
}], { projectDir });
}, 1000 * 30);
});
});
```
### getLiveSyncDeviceDescriptors
Gives information for currently running LiveSync operation and parameters used to start it on each device.
Expand Down Expand Up @@ -741,6 +829,16 @@ tns.liveSyncService.on("notify", data => {
});
```
* userInteractionNeeded - raised whenever CLI needs to restart an application but cannot so the user has to restart it manually. The event is raised with an object, which can later be passed to `attachDebugger` method of `liveSyncService`:
Example:
```JavaScript
tns.liveSyncService.on("userInteractionNeeded", data => {
console.log("Please restart the app manually");
return tns.liveSyncService.attachDebugger(data);
});
```
## 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
1 change: 0 additions & 1 deletion lib/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ $injector.requireCommand("platform|clean", "./commands/platform-clean");

$injector.requirePublicClass("liveSyncService", "./services/livesync/livesync-service");
$injector.require("liveSyncCommandHelper", "./services/livesync/livesync-command-helper");
$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
Expand Down
30 changes: 15 additions & 15 deletions lib/commands/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { DebugCommandErrors } from "../constants";
export class DebugPlatformCommand implements ICommand {
public allowedParameters: ICommandParameter[] = [];

constructor(private debugService: IPlatformDebugService,
private platform: string,
constructor(private platform: string,
private $debugService: IDebugService,
protected $devicesService: Mobile.IDevicesService,
protected $platformService: IPlatformService,
protected $projectData: IProjectData,
Expand All @@ -16,31 +16,29 @@ export class DebugPlatformCommand implements ICommand {
protected $logger: ILogger,
protected $errors: IErrors,
private $debugDataService: IDebugDataService,
private $debugLiveSyncService: IDebugLiveSyncService,
private $config: IConfiguration,
private $liveSyncService: IDebugLiveSyncService,
private $prompter: IPrompter,
private $liveSyncCommandHelper: ILiveSyncCommandHelper) {
}

public async execute(args: string[]): Promise<void> {
const debugOptions = this.$options;
const debugOptions = <IDebugOptions>_.cloneDeep(this.$options.argv);

let debugData = this.$debugDataService.createDebugData(this.$projectData, this.$options);

await this.$platformService.trackProjectType(this.$projectData);

const selectedDeviceForDebug = await this.getDeviceForDebug();
debugData.deviceIdentifier = selectedDeviceForDebug.deviceInfo.identifier;

if (this.$options.start) {
return this.$debugLiveSyncService.printDebugInformation(await this.debugService.debug(debugData, debugOptions));
return this.$liveSyncService.printDebugInformation(await this.$debugService.debug(debugData, debugOptions));
}

this.$config.debugLivesync = true;

await this.$devicesService.detectCurrentlyAttachedDevices({ shouldReturnImmediateResult: false, platform: this.platform });

await this.$liveSyncCommandHelper.executeLiveSyncOperation([selectedDeviceForDebug], this.$debugLiveSyncService, this.platform);
await this.$liveSyncCommandHelper.executeLiveSyncOperation([selectedDeviceForDebug], this.platform, {
[selectedDeviceForDebug.deviceInfo.identifier]: true
});
}

public async getDeviceForDebug(): Promise<Mobile.IDevice> {
Expand Down Expand Up @@ -104,6 +102,10 @@ export class DebugPlatformCommand implements ICommand {
this.$errors.fail(`Applications for platform ${this.platform} can not be built on this OS`);
}

if (this.$options.release) {
this.$errors.fail("--release flag is not applicable to this command");
}

const platformData = this.$platformsData.getPlatformData(this.platform, this.$projectData);
const platformProjectService = platformData.platformProjectService;
await platformProjectService.validate(this.$projectData);
Expand All @@ -123,7 +125,7 @@ export class DebugIOSCommand implements ICommand {

@cache()
private get debugPlatformCommand(): DebugPlatformCommand {
return this.$injector.resolve<DebugPlatformCommand>(DebugPlatformCommand, { debugService: this.$iOSDebugService, platform: this.platform });
return this.$injector.resolve<DebugPlatformCommand>(DebugPlatformCommand, { platform: this.platform });
}

public allowedParameters: ICommandParameter[] = [];
Expand All @@ -135,7 +137,6 @@ export class DebugIOSCommand implements ICommand {
private $injector: IInjector,
private $projectData: IProjectData,
private $platformsData: IPlatformsData,
private $iOSDebugService: IDebugService,
$iosDeviceOperations: IIOSDeviceOperations) {
this.$projectData.initializeProjectData();
// Do not dispose ios-device-lib, so the process will remain alive and the debug application (NativeScript Inspector or Chrome DevTools) will be able to connect to the socket.
Expand Down Expand Up @@ -166,7 +167,7 @@ export class DebugAndroidCommand implements ICommand {

@cache()
private get debugPlatformCommand(): DebugPlatformCommand {
return this.$injector.resolve<DebugPlatformCommand>(DebugPlatformCommand, { debugService: this.$androidDebugService, platform: this.platform });
return this.$injector.resolve<DebugPlatformCommand>(DebugPlatformCommand, { platform: this.platform });
}

public allowedParameters: ICommandParameter[] = [];
Expand All @@ -177,8 +178,7 @@ export class DebugAndroidCommand implements ICommand {
private $options: IOptions,
private $injector: IInjector,
private $projectData: IProjectData,
private $platformsData: IPlatformsData,
private $androidDebugService: IDebugService) {
private $platformsData: IPlatformsData) {
this.$projectData.initializeProjectData();
}

Expand Down
2 changes: 1 addition & 1 deletion lib/commands/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class RunCommandBase implements ICommand {
await this.$devicesService.detectCurrentlyAttachedDevices({ shouldReturnImmediateResult: false, platform: this.platform });
let devices = this.$devicesService.getDeviceInstances();
devices = devices.filter(d => !this.platform || d.deviceInfo.platform.toLowerCase() === this.platform.toLowerCase());
await this.$liveSyncCommandHelper.executeLiveSyncOperation(devices, this.$liveSyncService, this.platform);
await this.$liveSyncCommandHelper.executeLiveSyncOperation(devices, this.platform);
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/common
1 change: 0 additions & 1 deletion lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export class Configuration extends ConfigBase implements IConfiguration { // Use
TYPESCRIPT_COMPILER_OPTIONS = {};
ANDROID_DEBUG_UI: string = null;
USE_POD_SANDBOX: boolean = false;
debugLivesync: boolean = false;

/*don't require logger and everything that has logger as dependency in config.js due to cyclic dependency*/
constructor(protected $fs: IFileSystem) {
Expand Down
3 changes: 3 additions & 0 deletions lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,16 @@ export const ANGULAR_NAME = "angular";
export const TYPESCRIPT_NAME = "typescript";
export const BUILD_OUTPUT_EVENT_NAME = "buildOutput";
export const CONNECTION_ERROR_EVENT_NAME = "connectionError";
export const USER_INTERACTION_NEEDED_EVENT_NAME = "userInteractionNeeded";
export const DEBUGGER_ATTACHED_EVENT_NAME = "debuggerAttached";
export const VERSION_STRING = "version";
export const INSPECTOR_CACHE_DIRNAME = "ios-inspector";
export const POST_INSTALL_COMMAND_NAME = "post-install-cli";

export class DebugCommandErrors {
public static UNABLE_TO_USE_FOR_DEVICE_AND_EMULATOR = "The options --for-device and --emulator cannot be used simultaneously. Please use only one of them.";
public static NO_DEVICES_EMULATORS_FOUND_FOR_OPTIONS = "Unable to find device or emulator for specified options.";
public static UNSUPPORTED_DEVICE_OS_FOR_DEBUGGING = "Unsupported device OS for debugging";
}

export const enum NativePlatformStatus {
Expand Down
4 changes: 1 addition & 3 deletions lib/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@ interface IStaticConfig extends Config.IStaticConfig { }
interface IConfiguration extends Config.IConfig {
ANDROID_DEBUG_UI: string;
USE_POD_SANDBOX: boolean;
debugLivesync: boolean;
}

interface IApplicationPackage {
Expand Down Expand Up @@ -405,8 +404,7 @@ interface IDeviceEmulator extends IEmulator, IDeviceIdentifier { }

interface IRunPlatformOptions extends IJustLaunch, IDeviceEmulator { }

interface IDeployPlatformOptions extends IAndroidReleaseOptions, IPlatformTemplate, IRelease, IClean, IDeviceEmulator, IProvision, ITeamIdentifier {
projectDir: string;
interface IDeployPlatformOptions extends IAndroidReleaseOptions, IPlatformTemplate, IRelease, IClean, IDeviceEmulator, IProvision, ITeamIdentifier, IProjectDir {
forceInstall?: boolean;
}

Expand Down
25 changes: 10 additions & 15 deletions lib/definitions/debug.d.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
/**
* Describes information for starting debug process.
*/
interface IDebugData {
/**
* Id of the device on which the debug process will be started.
*/
deviceIdentifier: string;

interface IDebugData extends Mobile.IDeviceIdentifier {
/**
* Application identifier of the app that it will be debugged.
*/
Expand Down Expand Up @@ -115,14 +110,19 @@ interface IDebugServiceBase extends NodeJS.EventEmitter {
debug(debugData: IDebugData, debugOptions: IDebugOptions): Promise<string>;
}

interface IDebugService {
getDebugService(device: Mobile.IDevice): IPlatformDebugService;
interface IDebugService extends IDebugServiceBase {
/**
* Stops debug operation for a specific device.
* @param {string} deviceIdentifier Identifier of the device fo which debugging will be stopped.
* @returns {Promise<void>}
*/
debugStop(deviceIdentifier: string): Promise<void>;
}

/**
* Describes actions required for debugging on specific platform (Android or iOS).
*/
interface IPlatformDebugService extends IDebugServiceBase {
interface IPlatformDebugService extends IDebugServiceBase, IPlatform {
/**
* Starts debug operation.
* @param {IDebugData} debugData Describes information for device and application that will be debugged.
Expand All @@ -135,10 +135,5 @@ interface IPlatformDebugService extends IDebugServiceBase {
* Stops debug operation.
* @returns {Promise<void>}
*/
debugStop(): Promise<void>

/**
* Mobile platform of the device - Android or iOS.
*/
platform: string;
debugStop(): Promise<void>;
}
3 changes: 1 addition & 2 deletions lib/definitions/emulator-platform-service.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
interface IEmulatorInfo {
interface IEmulatorInfo extends IPlatform {
name: string;
version: string;
platform: string;
id: string;
type: string;
isRunning?: boolean;
Expand Down
Loading

0 comments on commit 7922411

Please sign in to comment.