Skip to content

Commit 44eb3c5

Browse files
committed
feat: introduce debugController
1 parent da752d0 commit 44eb3c5

17 files changed

+231
-219
lines changed

lib/bootstrap.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ $injector.require("platformValidationService", "./services/platform/platform-val
4141

4242
$injector.require("buildArtefactsService", "./services/build-artefacts-service");
4343

44-
$injector.require("deviceDebugAppService", "./services/device/device-debug-app-service");
4544
$injector.require("deviceInstallAppService", "./services/device/device-install-app-service");
46-
$injector.require("deviceRefreshAppService", "./services/device/device-refresh-app-service");
4745

4846
$injector.require("runEmitter", "./emitters/run-emitter");
4947
$injector.require("previewAppEmitter", "./emitters/preview-app-emitter");
@@ -53,6 +51,7 @@ $injector.require("prepareController", "./controllers/prepare-controller");
5351
$injector.require("buildController", "./controllers/build-controller");
5452
$injector.require("deployController", "./controllers/deploy-controller");
5553
$injector.require("runController", "./controllers/run-controller");
54+
$injector.require("debugController", "./controllers/debug-controller");
5655
$injector.require("previewAppController", "./controllers/preview-app-controller");
5756

5857
$injector.require("prepareDataService", "./services/prepare-data-service");

lib/commands/debug.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { cache } from "../common/decorators";
22
import { ValidatePlatformCommandBase } from "./command-base";
33
import { LiveSyncCommandHelper } from "../helpers/livesync-command-helper";
4-
import { DeviceDebugAppService } from "../services/device/device-debug-app-service";
54

65
export class DebugPlatformCommand extends ValidatePlatformCommandBase implements ICommand {
76
public allowedParameters: ICommandParameter[] = [];
@@ -17,7 +16,7 @@ export class DebugPlatformCommand extends ValidatePlatformCommandBase implements
1716
protected $logger: ILogger,
1817
protected $errors: IErrors,
1918
private $debugDataService: IDebugDataService,
20-
private $deviceDebugAppService: DeviceDebugAppService,
19+
private $debugController: IDebugController,
2120
private $liveSyncCommandHelper: ILiveSyncCommandHelper,
2221
private $androidBundleValidatorHelper: IAndroidBundleValidatorHelper) {
2322
super($options, $platformsDataService, $platformValidationService, $projectData);
@@ -31,8 +30,6 @@ export class DebugPlatformCommand extends ValidatePlatformCommandBase implements
3130
skipDeviceDetectionInterval: true
3231
});
3332

34-
const debugOptions = <IDebugOptions>_.cloneDeep(this.$options.argv);
35-
3633
const selectedDeviceForDebug = await this.$devicesService.pickSingleDevice({
3734
onlyEmulators: this.$options.emulator,
3835
onlyDevices: this.$options.forDevice,
@@ -42,11 +39,12 @@ export class DebugPlatformCommand extends ValidatePlatformCommandBase implements
4239
const debugData = this.$debugDataService.createDebugData(this.$projectData, { device: selectedDeviceForDebug.deviceInfo.identifier });
4340

4441
if (this.$options.start) {
45-
await this.$deviceDebugAppService.printDebugInformation(await this.$debugService.debug(debugData, debugOptions));
42+
const debugOptions = <IDebugOptions>_.cloneDeep(this.$options.argv);
43+
await this.$debugController.printDebugInformation(await this.$debugService.debug(debugData, debugOptions));
4644
return;
4745
}
4846

49-
await this.$liveSyncCommandHelper.executeLiveSyncOperation([selectedDeviceForDebug], this.platform, {
47+
await this.$liveSyncCommandHelper.executeLiveSyncOperationWithDebug([selectedDeviceForDebug], this.platform, {
5048
deviceDebugMap: {
5149
[selectedDeviceForDebug.deviceInfo.identifier]: true
5250
},

lib/commands/run.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export class RunCommandBase implements ICommand {
1313
private $errors: IErrors,
1414
private $hostInfo: IHostInfo,
1515
private $liveSyncCommandHelper: ILiveSyncCommandHelper,
16-
private $projectData: IProjectData,
16+
private $projectData: IProjectData
1717
) { }
1818

1919
public allowedParameters: ICommandParameter[] = [];

lib/services/device/device-debug-app-service.ts renamed to lib/controllers/debug-controller.ts

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,50 @@
1-
import { performanceLog } from "../../common/decorators";
2-
import { RunEmitter } from "../../emitters/run-emitter";
1+
import { performanceLog } from "../common/decorators";
32
import { EOL } from "os";
3+
import { RunController } from "./run-controller";
4+
5+
export class DebugController extends RunController implements IDebugController {
46

5-
export class DeviceDebugAppService {
67
constructor(
8+
$analyticsService: IAnalyticsService,
9+
$buildDataService: IBuildDataService,
10+
$buildController: IBuildController,
711
private $debugDataService: IDebugDataService,
812
private $debugService: IDebugService,
9-
private $devicesService: Mobile.IDevicesService,
10-
private $errors: IErrors,
11-
private $logger: ILogger,
12-
private $projectDataService: IProjectDataService,
13-
private $runEmitter: RunEmitter
14-
) { }
13+
$deviceInstallAppService: IDeviceInstallAppService,
14+
$devicesService: Mobile.IDevicesService,
15+
$errors: IErrors,
16+
$hmrStatusService: IHmrStatusService,
17+
$hooksService: IHooksService,
18+
$liveSyncServiceResolver: ILiveSyncServiceResolver,
19+
$logger: ILogger,
20+
$platformsDataService: IPlatformsDataService,
21+
$pluginsService: IPluginsService,
22+
$prepareController: IPrepareController,
23+
$prepareDataService: IPrepareDataService,
24+
$prepareNativePlatformService: IPrepareNativePlatformService,
25+
$projectDataService: IProjectDataService,
26+
$runEmitter: IRunEmitter
27+
) {
28+
super(
29+
$analyticsService,
30+
$buildDataService,
31+
$buildController,
32+
$deviceInstallAppService,
33+
$devicesService,
34+
$errors,
35+
$hmrStatusService,
36+
$hooksService,
37+
$liveSyncServiceResolver,
38+
$logger,
39+
$platformsDataService,
40+
$pluginsService,
41+
$prepareController,
42+
$prepareDataService,
43+
$prepareNativePlatformService,
44+
$projectDataService,
45+
$runEmitter
46+
);
47+
}
1548

1649
@performanceLog()
1750
public async enableDebugging(projectData: IProjectData, deviceDescriptor: ILiveSyncDeviceInfo, refreshInfo: IRestartApplicationInfo): Promise<IDebugInformation> {
@@ -64,6 +97,17 @@ export class DeviceDebugAppService {
6497
return debugInformation;
6598
}
6699

100+
// IMPORTANT: This method overrides the refresh logic of runController as enables debugging for provided deviceDescriptor
101+
public async refreshApplication(projectData: IProjectData, liveSyncResultInfo: ILiveSyncResultInfo, deviceDescriptor: ILiveSyncDeviceInfo): Promise<IRestartApplicationInfo> {
102+
liveSyncResultInfo.waitForDebugger = deviceDescriptor.debugOptions && deviceDescriptor.debugOptions.debugBrk;
103+
104+
const refreshInfo = await super.refreshApplication(projectData, liveSyncResultInfo, deviceDescriptor);
105+
106+
await this.enableDebugging(projectData, deviceDescriptor, refreshInfo);
107+
108+
return refreshInfo;
109+
}
110+
67111
@performanceLog()
68112
private async enableDebuggingCoreWithoutWaitingCurrentAction(deviceOption: IEnableDebuggingDeviceOptions, deviceDescriptor: ILiveSyncDeviceInfo, debuggingAdditionalOptions: IDebuggingAdditionalOptions): Promise<IDebugInformation> {
69113
if (!deviceDescriptor) {
@@ -99,4 +143,4 @@ export class DeviceDebugAppService {
99143
return debugInformation;
100144
}
101145
}
102-
$injector.register("deviceDebugAppService", DeviceDebugAppService);
146+
$injector.register("debugController", DebugController);

lib/controllers/run-controller.ts

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,29 @@
1-
import { EventEmitter } from "events";
2-
import { LiveSyncServiceResolver } from "../resolvers/livesync-service-resolver";
31
import { HmrConstants, DeviceDiscoveryEventNames } from "../common/constants";
42
import { PREPARE_READY_EVENT_NAME, TrackActionNames } from "../constants";
5-
import { cache } from "../common/decorators";
3+
import { cache, performanceLog } from "../common/decorators";
64

7-
export class RunController extends EventEmitter {
5+
export class RunController implements IRunController {
86
private processesInfo: IDictionary<IRunOnDeviceProcessInfo> = {};
97

108
constructor(
119
private $analyticsService: IAnalyticsService,
1210
private $buildDataService: IBuildDataService,
1311
private $buildController: IBuildController,
14-
private $deviceDebugAppService: IDeviceDebugAppService,
1512
private $deviceInstallAppService: IDeviceInstallAppService,
16-
private $deviceRefreshAppService: IDeviceRefreshAppService,
17-
private $devicesService: Mobile.IDevicesService,
18-
private $errors: IErrors,
13+
protected $devicesService: Mobile.IDevicesService,
14+
protected $errors: IErrors,
1915
private $hmrStatusService: IHmrStatusService,
2016
public $hooksService: IHooksService,
21-
private $liveSyncServiceResolver: LiveSyncServiceResolver,
22-
private $logger: ILogger,
17+
private $liveSyncServiceResolver: ILiveSyncServiceResolver,
18+
protected $logger: ILogger,
2319
private $platformsDataService: IPlatformsDataService,
2420
private $pluginsService: IPluginsService,
2521
private $prepareController: IPrepareController,
2622
private $prepareDataService: IPrepareDataService,
2723
private $prepareNativePlatformService: IPrepareNativePlatformService,
28-
private $projectDataService: IProjectDataService,
29-
private $runEmitter: IRunEmitter
30-
) { super(); }
24+
protected $projectDataService: IProjectDataService,
25+
protected $runEmitter: IRunEmitter
26+
) { }
3127

3228
public async run(runData: IRunData): Promise<void> {
3329
const { projectDir, liveSyncInfo, deviceDescriptors } = runData;
@@ -115,6 +111,40 @@ export class RunController extends EventEmitter {
115111
return currentDescriptors || [];
116112
}
117113

114+
@performanceLog()
115+
protected async refreshApplication(projectData: IProjectData, liveSyncResultInfo: ILiveSyncResultInfo, deviceDescriptor: ILiveSyncDeviceInfo, settings?: IRefreshApplicationSettings): Promise<IRestartApplicationInfo> {
116+
const result = { didRestart: false };
117+
const platform = liveSyncResultInfo.deviceAppData.platform;
118+
const applicationIdentifier = projectData.projectIdentifiers[platform.toLowerCase()];
119+
const platformLiveSyncService = this.$liveSyncServiceResolver.resolveLiveSyncService(platform);
120+
121+
try {
122+
let shouldRestart = await platformLiveSyncService.shouldRestart(projectData, liveSyncResultInfo);
123+
if (!shouldRestart) {
124+
shouldRestart = !await platformLiveSyncService.tryRefreshApplication(projectData, liveSyncResultInfo);
125+
}
126+
127+
if (shouldRestart) {
128+
this.$runEmitter.emitDebuggerDetachedEvent(liveSyncResultInfo.deviceAppData.device);
129+
await platformLiveSyncService.restartApplication(projectData, liveSyncResultInfo);
130+
result.didRestart = true;
131+
}
132+
} catch (err) {
133+
this.$logger.info(`Error while trying to start application ${applicationIdentifier} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}. Error is: ${err.message || err}`);
134+
const msg = `Unable to start application ${applicationIdentifier} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}. Try starting it manually.`;
135+
this.$logger.warn(msg);
136+
if (!settings || !settings.shouldSkipEmitLiveSyncNotification) {
137+
this.$runEmitter.emitRunNotificationEvent(projectData, liveSyncResultInfo.deviceAppData.device, msg);
138+
}
139+
140+
if (settings && settings.shouldCheckDeveloperDiscImage && (err.message || err) === "Could not find developer disk image") {
141+
this.$runEmitter.emitUserInteractionNeededEvent(projectData, liveSyncResultInfo.deviceAppData.device, deviceDescriptor);
142+
}
143+
}
144+
145+
return result;
146+
}
147+
118148
private getDeviceDescriptorsForInitialSync(projectDir: string, deviceDescriptors: ILiveSyncDeviceInfo[]) {
119149
const currentRunData = this.processesInfo[projectDir];
120150
const isAlreadyLiveSyncing = currentRunData && !currentRunData.isStopped;
@@ -178,17 +208,13 @@ export class RunController extends EventEmitter {
178208
const { force, useHotModuleReload, skipWatcher } = liveSyncInfo;
179209
const liveSyncResultInfo = await platformLiveSyncService.fullSync({ force, useHotModuleReload, projectData, device, watch: !skipWatcher, liveSyncDeviceInfo: deviceDescriptor });
180210

181-
const refreshInfo = await this.$deviceRefreshAppService.refreshApplication(projectData, liveSyncResultInfo, deviceDescriptor);
211+
await this.refreshApplication(projectData, liveSyncResultInfo, deviceDescriptor);
182212

183213
this.$runEmitter.emitRunExecutedEvent(projectData, device, {
184214
syncedFiles: liveSyncResultInfo.modifiedFilesData.map(m => m.getLocalPath()),
185215
isFullSync: liveSyncResultInfo.isFullSync
186216
});
187217

188-
if (liveSyncResultInfo && deviceDescriptor.debuggingEnabled) {
189-
await this.$deviceDebugAppService.enableDebugging(projectData, deviceDescriptor, refreshInfo);
190-
}
191-
192218
this.$logger.info(`Successfully synced application ${liveSyncResultInfo.deviceAppData.appIdentifier} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}.`);
193219

194220
this.$runEmitter.emitRunStartedEvent(projectData, device);
@@ -236,6 +262,11 @@ export class RunController extends EventEmitter {
236262

237263
await this.refreshApplication(projectData, liveSyncResultInfo, deviceDescriptor);
238264

265+
this.$runEmitter.emitRunExecutedEvent(projectData, liveSyncResultInfo.deviceAppData.device, {
266+
syncedFiles: liveSyncResultInfo.modifiedFilesData.map(m => m.getLocalPath()),
267+
isFullSync: liveSyncResultInfo.isFullSync
268+
});
269+
239270
if (!liveSyncResultInfo.didRecover && isInHMRMode) {
240271
const status = await this.$hmrStatusService.getHmrStatus(device.deviceInfo.identifier, data.hmrData.hash);
241272
if (status === HmrConstants.HMR_ERROR_STATUS) {
@@ -244,6 +275,11 @@ export class RunController extends EventEmitter {
244275
// We want to force a restart of the application.
245276
liveSyncResultInfo.isFullSync = true;
246277
await this.refreshApplication(projectData, liveSyncResultInfo, deviceDescriptor);
278+
279+
this.$runEmitter.emitRunExecutedEvent(projectData, liveSyncResultInfo.deviceAppData.device, {
280+
syncedFiles: liveSyncResultInfo.modifiedFilesData.map(m => m.getLocalPath()),
281+
isFullSync: liveSyncResultInfo.isFullSync
282+
});
247283
}
248284
}
249285

@@ -266,19 +302,6 @@ export class RunController extends EventEmitter {
266302
}));
267303
}
268304

269-
private async refreshApplication(projectData: IProjectData, liveSyncResultInfo: ILiveSyncResultInfo, deviceDescriptor: ILiveSyncDeviceInfo) {
270-
const refreshInfo = await this.$deviceRefreshAppService.refreshApplication(projectData, liveSyncResultInfo, deviceDescriptor);
271-
272-
this.$runEmitter.emitRunExecutedEvent(projectData, liveSyncResultInfo.deviceAppData.device, {
273-
syncedFiles: liveSyncResultInfo.modifiedFilesData.map(m => m.getLocalPath()),
274-
isFullSync: liveSyncResultInfo.isFullSync
275-
});
276-
277-
if (liveSyncResultInfo && deviceDescriptor.debuggingEnabled) {
278-
await this.$deviceDebugAppService.enableDebugging(projectData, deviceDescriptor, refreshInfo);
279-
}
280-
}
281-
282305
private async addActionToChain<T>(projectDir: string, action: () => Promise<T>): Promise<T> {
283306
const liveSyncInfo = this.processesInfo[projectDir];
284307
if (liveSyncInfo) {

lib/definitions/debug.d.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ interface IDebugDataService {
107107
* @param {IOptions} options The options based on which debugData will be created
108108
* @returns {IDebugData} Data describing the required information for starting debug process.
109109
*/
110-
createDebugData(projectData: IProjectData, options: IDeviceIdentifier): IDebugData;
110+
createDebugData(projectData: IProjectData, options: IDeviceIdentifier): IDebugData;
111111
}
112112

113113
/**
@@ -154,3 +154,10 @@ interface IDeviceDebugService extends IPlatform, NodeJS.EventEmitter {
154154
interface IDebugResultInfo {
155155
debugUrl: string;
156156
}
157+
158+
interface IDebugController extends IRunController {
159+
// TODO: add disableDebugging method
160+
enableDebugging(projectData: IProjectData, deviceDescriptor: ILiveSyncDeviceInfo, refreshInfo: IRestartApplicationInfo): Promise<IDebugInformation>;
161+
attachDebugger(settings: IAttachDebuggerOptions): Promise<IDebugInformation>;
162+
printDebugInformation(debugInformation: IDebugInformation, fireDebuggerAttachedEvent?: boolean): IDebugInformation;
163+
}

lib/definitions/deploy.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
interface IDeployController {
2+
deploy(data: IRunData): Promise<void>;
3+
}

lib/definitions/livesync.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ declare global {
468468
* @returns {Promise<void>}
469469
*/
470470
executeLiveSyncOperation(devices: Mobile.IDevice[], platform: string, additionalOptions?: ILiveSyncCommandHelperAdditionalOptions): Promise<void>;
471+
executeLiveSyncOperationWithDebug(devices: Mobile.IDevice[], platform: string, additionalOptions?: ILiveSyncCommandHelperAdditionalOptions): Promise<void>;
471472
getPlatformsForOperation(platform: string): string[];
472473

473474
/**
@@ -486,4 +487,7 @@ declare global {
486487
executeCommandLiveSync(platform?: string, additionalOptions?: ILiveSyncCommandHelperAdditionalOptions): Promise<void>;
487488
}
488489

490+
interface ILiveSyncServiceResolver {
491+
resolveLiveSyncService(platform: string): IPlatformLiveSyncService;
492+
}
489493
}

lib/definitions/run.d.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ interface IRunData {
55
}
66

77
interface IRunController {
8-
8+
run(runData: IRunData): Promise<void>;
9+
stop(projectDir: string, deviceIdentifiers?: string[], stopOptions?: { shouldAwaitAllActions: boolean }): Promise<void>;
10+
getDeviceDescriptors(projectDir: string): ILiveSyncDeviceInfo[];
911
}
1012

1113
interface IRunEmitter {
@@ -24,13 +26,3 @@ interface IDeviceInstallAppService {
2426
installOnDeviceIfNeeded(device: Mobile.IDevice, buildData: IBuildData, packageFile?: string): Promise<void>;
2527
shouldInstall(device: Mobile.IDevice, buildData: IBuildData): Promise<boolean>;
2628
}
27-
28-
interface IDeviceRefreshAppService {
29-
refreshApplication(projectData: IProjectData, liveSyncResultInfo: ILiveSyncResultInfo, deviceDescriptor: ILiveSyncDeviceInfo, settings?: IRefreshApplicationSettings): Promise<IRestartApplicationInfo>;
30-
}
31-
32-
interface IDeviceDebugAppService {
33-
enableDebugging(projectData: IProjectData, deviceDescriptor: ILiveSyncDeviceInfo, refreshInfo: IRestartApplicationInfo): Promise<IDebugInformation>;
34-
attachDebugger(settings: IAttachDebuggerOptions): Promise<IDebugInformation>;
35-
printDebugInformation(debugInformation: IDebugInformation, fireDebuggerAttachedEvent: boolean): IDebugInformation;
36-
}

0 commit comments

Comments
 (0)