diff --git a/lib/commands/debug.ts b/lib/commands/debug.ts index 323cbb605b..728d38b559 100644 --- a/lib/commands/debug.ts +++ b/lib/commands/debug.ts @@ -1,10 +1,6 @@ -import { CONNECTED_STATUS } from "../common/constants"; -import { isInteractive } from "../common/helpers"; import { cache } from "../common/decorators"; -import { DebugCommandErrors } from "../constants"; import { ValidatePlatformCommandBase } from "./command-base"; import { LiveSyncCommandHelper } from "../helpers/livesync-command-helper"; -import { performanceLog } from "../common/decorators"; export class DebugPlatformCommand extends ValidatePlatformCommandBase implements ICommand { public allowedParameters: ICommandParameter[] = []; @@ -21,7 +17,6 @@ export class DebugPlatformCommand extends ValidatePlatformCommandBase implements protected $errors: IErrors, private $debugDataService: IDebugDataService, private $liveSyncService: IDebugLiveSyncService, - private $prompter: IPrompter, private $liveSyncCommandHelper: ILiveSyncCommandHelper, private $androidBundleValidatorHelper: IAndroidBundleValidatorHelper) { super($options, $platformsData, $platformService, $projectData); @@ -37,7 +32,11 @@ export class DebugPlatformCommand extends ValidatePlatformCommandBase implements const debugOptions = _.cloneDeep(this.$options.argv); - const selectedDeviceForDebug = await this.getDeviceForDebug(); + const selectedDeviceForDebug = await this.$devicesService.pickSingleDevice({ + onlyEmulators: this.$options.emulator, + onlyDevices: this.$options.forDevice, + deviceId: this.$options.device + }); const debugData = this.$debugDataService.createDebugData(this.$projectData, { device: selectedDeviceForDebug.deviceInfo.identifier }); @@ -56,61 +55,6 @@ export class DebugPlatformCommand extends ValidatePlatformCommandBase implements }); } - @performanceLog() - public async getDeviceForDebug(): Promise { - if (this.$options.forDevice && this.$options.emulator) { - this.$errors.fail(DebugCommandErrors.UNABLE_TO_USE_FOR_DEVICE_AND_EMULATOR); - } - - if (this.$options.device) { - const device = await this.$devicesService.getDevice(this.$options.device); - return device; - } - - // Now let's take data for each device: - const availableDevicesAndEmulators = this.$devicesService.getDeviceInstances() - .filter(d => d.deviceInfo.status === CONNECTED_STATUS && (!this.platform || d.deviceInfo.platform.toLowerCase() === this.platform.toLowerCase())); - - const selectedDevices = availableDevicesAndEmulators.filter(d => this.$options.emulator ? d.isEmulator : (this.$options.forDevice ? !d.isEmulator : true)); - - if (selectedDevices.length > 1) { - if (isInteractive()) { - const choices = selectedDevices.map(e => `${e.deviceInfo.identifier} - ${e.deviceInfo.displayName}`); - - const selectedDeviceString = await this.$prompter.promptForChoice("Select device for debugging", choices); - - const selectedDevice = _.find(selectedDevices, d => `${d.deviceInfo.identifier} - ${d.deviceInfo.displayName}` === selectedDeviceString); - return selectedDevice; - } else { - const sortedInstances = _.sortBy(selectedDevices, e => e.deviceInfo.version); - const emulators = sortedInstances.filter(e => e.isEmulator); - const devices = sortedInstances.filter(d => !d.isEmulator); - let selectedInstance: Mobile.IDevice; - - if (this.$options.emulator || this.$options.forDevice) { - // When --emulator or --forDevice is passed, the instances are already filtered - // So we are sure we have exactly the type we need and we can safely return the last one (highest OS version). - selectedInstance = _.last(sortedInstances); - } else { - if (emulators.length) { - selectedInstance = _.last(emulators); - } else { - selectedInstance = _.last(devices); - } - } - - this.$logger.warn(`Multiple devices/emulators found. Starting debugger on ${selectedInstance.deviceInfo.identifier}. ` + - "If you want to debug on specific device/emulator, you can specify it with --device option."); - - return selectedInstance; - } - } else if (selectedDevices.length === 1) { - return _.head(selectedDevices); - } - - this.$errors.failWithoutHelp(DebugCommandErrors.NO_DEVICES_EMULATORS_FOUND_FOR_OPTIONS); - } - public async canExecute(args: string[]): Promise { this.$androidBundleValidatorHelper.validateNoAab(); diff --git a/lib/commands/test.ts b/lib/commands/test.ts index 678de186bb..bbce9b5d43 100644 --- a/lib/commands/test.ts +++ b/lib/commands/test.ts @@ -1,24 +1,5 @@ import * as helpers from "../common/helpers"; -function RunTestCommandFactory(platform: string) { - return function RunTestCommand( - $options: IOptions, - $testExecutionService: ITestExecutionService, - $projectData: IProjectData, - $analyticsService: IAnalyticsService, - $platformEnvironmentRequirements: IPlatformEnvironmentRequirements) { - $projectData.initializeProjectData(); - $analyticsService.setShouldDispose($options.justlaunch || !$options.watch); - const projectFilesConfig = helpers.getProjectFilesConfig({ isReleaseBuild: $options.release }); - this.execute = (args: string[]): Promise => $testExecutionService.startTestRunner(platform, $projectData, projectFilesConfig); - this.canExecute = (args: string[]): Promise => canExecute({ $platformEnvironmentRequirements, $projectData, $options, platform }); - this.allowedParameters = []; - }; -} - -$injector.registerCommand("dev-test|android", RunTestCommandFactory('android')); -$injector.registerCommand("dev-test|ios", RunTestCommandFactory('iOS')); - function RunKarmaTestCommandFactory(platform: string) { return function RunKarmaTestCommand($options: IOptions, $testExecutionService: ITestExecutionService, $projectData: IProjectData, $analyticsService: IAnalyticsService, $platformEnvironmentRequirements: IPlatformEnvironmentRequirements) { $projectData.initializeProjectData(); diff --git a/lib/common/definitions/mobile.d.ts b/lib/common/definitions/mobile.d.ts index 8336463808..87d8062121 100644 --- a/lib/common/definitions/mobile.d.ts +++ b/lib/common/definitions/mobile.d.ts @@ -111,12 +111,8 @@ declare module Mobile { } interface IiOSDevice extends IDevice { - getLiveSyncSocket(appId: string): Promise; - destroyLiveSyncSocket(appId: string): void; - - getDebugSocket(appId: string): Promise; + getDebugSocket(appId: string, projectName: string): Promise; destroyDebugSocket(appId: string): void; - openDeviceLogStream(options?: IiOSLogStreamOptions): Promise; destroyAllSockets(): void; } @@ -221,12 +217,6 @@ declare module Mobile { * @param {string} projectName The project name of the currently running application for which we need the logs. */ setProjectNameForDevice(deviceIdentifier: string, projectName: string): void; - - /** - * Disables logs on the specified device and does not print any logs on the console. - * @param {string} deviceIdentifier The unique identifier of the device. - */ - muteLogsForDevice(deviceIdentifier: string): void; } /** @@ -248,10 +238,6 @@ declare module Mobile { */ projectName?: string; - /** - * Specifies if the logs will be printed on the console. - */ - muteLogs?: boolean; } /** @@ -311,19 +297,27 @@ declare module Mobile { justLaunch?: boolean; } + interface IStartApplicationData extends IApplicationData { + waitForDebugger?: boolean; + } + interface IInstallAppData extends IApplicationData { packagePath: string; } + interface IRunningAppInfo { + pid: string; + } + interface IDeviceApplicationManager extends NodeJS.EventEmitter { getInstalledApplications(): Promise; isApplicationInstalled(appIdentifier: string): Promise; installApplication(packageFilePath: string, appIdentifier?: string): Promise; uninstallApplication(appIdentifier: string): Promise; reinstallApplication(appIdentifier: string, packageFilePath: string): Promise; - startApplication(appData: IApplicationData): Promise; + startApplication(appData: IStartApplicationData): Promise; stopApplication(appData: IApplicationData): Promise; - restartApplication(appData: IApplicationData): Promise; + restartApplication(appData: IStartApplicationData): Promise; checkForApplicationUpdates(): Promise; isLiveSyncSupported(appIdentifier: string): Promise; getApplicationInfo(applicationIdentifier: string): Promise; @@ -550,6 +544,27 @@ declare module Mobile { * @returns {Promise} - Returns array of errors. */ startEmulator(options?: IStartEmulatorOptions): Promise; + + /** + * Returns a single device based on the specified options. If more than one devices are matching, + * prompts the user for a manual choice or returns the first one for non interactive terminals. + */ + pickSingleDevice(options: IPickSingleDeviceOptions): Promise + } + + interface IPickSingleDeviceOptions { + /** + * Pick from the connected emulators only + */ + onlyEmulators: boolean; + /** + * Pick from the connected real devices only + */ + onlyDevices: boolean; + /** + * Pick a specific device + */ + deviceId: string; } interface IListEmulatorsOptions { @@ -941,14 +956,6 @@ declare module Mobile { * @returns {net.Socket} Returns instance of net.Socket when connection is successful, otherwise undefined is returned. */ connectToPort(connectToPortData: IConnectToPortData): Promise; - - /** - * Runs an application on emulator - * @param app The path to executable .app - * @param emulatorOptions Emulator options that can be passed - * @returns {Promise} Returns the appId with the process of the running application on the simulator. For example: org.nativescript.myapp 55434 - */ - runApplicationOnEmulator(app: string, emulatorOptions?: IRunApplicationOnEmulatorOptions): Promise; } interface IEmulatorSettingsService { @@ -1251,9 +1258,9 @@ interface IIOSDeviceOperations extends IDisposable, NodeJS.EventEmitter { deleteFiles(deleteArray: IOSDeviceLib.IDeleteFileData[], errorHandler?: DeviceOperationErrorHandler): Promise; - start(startArray: IOSDeviceLib.IDdiApplicationData[], errorHandler?: DeviceOperationErrorHandler): Promise; + start(startArray: IOSDeviceLib.IIOSApplicationData[], errorHandler?: DeviceOperationErrorHandler): Promise; - stop(stopArray: IOSDeviceLib.IDdiApplicationData[], errorHandler?: DeviceOperationErrorHandler): Promise; + stop(stopArray: IOSDeviceLib.IIOSApplicationData[], errorHandler?: DeviceOperationErrorHandler): Promise; postNotification(postNotificationArray: IOSDeviceLib.IPostNotificationData[], errorHandler?: DeviceOperationErrorHandler): Promise; diff --git a/lib/common/mobile/android/android-application-manager.ts b/lib/common/mobile/android/android-application-manager.ts index e559acd6fe..0be7a23aa1 100644 --- a/lib/common/mobile/android/android-application-manager.ts +++ b/lib/common/mobile/android/android-application-manager.ts @@ -47,7 +47,15 @@ export class AndroidApplicationManager extends ApplicationManagerBase { return this.adb.executeShellCommand(["pm", "uninstall", `${appIdentifier}`], { treatErrorsAsWarnings: true }); } - public async startApplication(appData: Mobile.IApplicationData): Promise { + public async startApplication(appData: Mobile.IStartApplicationData): Promise { + if (appData.waitForDebugger) { + await this.adb.executeShellCommand([`cat /dev/null > ${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${appData.appId}-debugbreak`]); + } + + // If the app is debuggable, the Runtime will update the file when its ready for debugging + // and we will be able to take decisions and synchronize the debug experience based on the content + await this.adb.executeShellCommand([`cat /dev/null > ${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${appData.appId}-debugger-started`]); + /* Example "pm dump | grep -A 1 MAIN" output" android.intent.action.MAIN: diff --git a/lib/common/mobile/device-log-provider-base.ts b/lib/common/mobile/device-log-provider-base.ts index 9954d599bb..c96b04b66c 100644 --- a/lib/common/mobile/device-log-provider-base.ts +++ b/lib/common/mobile/device-log-provider-base.ts @@ -26,10 +26,6 @@ export abstract class DeviceLogProviderBase extends EventEmitter implements Mobi this.setLogLevel(logLevel, deviceIdentifier); } - public muteLogsForDevice(deviceIdentifier: string): void { - this.setDeviceLogOptionsProperty(deviceIdentifier, (deviceLogOptions: Mobile.IDeviceLogOptions) => deviceLogOptions.muteLogs, true); - } - protected getApplicationPidForDevice(deviceIdentifier: string): string { return this.devicesLogOptions[deviceIdentifier] && this.devicesLogOptions[deviceIdentifier].applicationPid; } diff --git a/lib/common/mobile/device-log-provider.ts b/lib/common/mobile/device-log-provider.ts index 6a83624eb2..18261a35b8 100644 --- a/lib/common/mobile/device-log-provider.ts +++ b/lib/common/mobile/device-log-provider.ts @@ -11,7 +11,7 @@ export class DeviceLogProvider extends DeviceLogProviderBase { const loggingOptions = this.getDeviceLogOptionsForDevice(deviceIdentifier); const data = this.$logFilter.filterData(platform, lineText, loggingOptions); if (data) { - this.logDataCore(data, loggingOptions); + this.logDataCore(data); this.emit(DEVICE_LOG_EVENT_NAME, lineText, deviceIdentifier, platform); } } @@ -20,10 +20,8 @@ export class DeviceLogProvider extends DeviceLogProviderBase { this.$logFilter.loggingLevel = logLevel.toUpperCase(); } - private logDataCore(data: string, loggingOptions: Mobile.IDeviceLogOptions): void { - if (!loggingOptions || (loggingOptions && !loggingOptions.muteLogs)) { - this.$logger.write(data); - } + private logDataCore(data: string): void { + this.$logger.write(data); } } $injector.register("deviceLogProvider", DeviceLogProvider); diff --git a/lib/common/mobile/ios/device/ios-application-manager.ts b/lib/common/mobile/ios/device/ios-application-manager.ts index bab0b39f1d..024086961a 100644 --- a/lib/common/mobile/ios/device/ios-application-manager.ts +++ b/lib/common/mobile/ios/device/ios-application-manager.ts @@ -74,7 +74,7 @@ export class IOSApplicationManager extends ApplicationManagerBase { this.$logger.trace("Application %s has been uninstalled successfully.", appIdentifier); } - public async startApplication(appData: Mobile.IApplicationData): Promise { + public async startApplication(appData: Mobile.IStartApplicationData): Promise { if (!await this.isApplicationInstalled(appData.appId)) { this.$errors.failWithoutHelp("Invalid application id: %s. All available application ids are: %s%s ", appData.appId, EOL, this.applicationsLiveSyncInfos.join(EOL)); } @@ -89,7 +89,6 @@ export class IOSApplicationManager extends ApplicationManagerBase { const { appId } = appData; this.device.destroyDebugSocket(appId); - this.device.destroyLiveSyncSocket(appId); const action = () => this.$iosDeviceOperations.stop([{ deviceId: this.device.deviceInfo.identifier, ddi: this.$options.ddi, appId }]); @@ -101,7 +100,7 @@ export class IOSApplicationManager extends ApplicationManagerBase { } } - public async restartApplication(appData: Mobile.IApplicationData): Promise { + public async restartApplication(appData: Mobile.IStartApplicationData): Promise { try { await this.setDeviceLogData(appData); await this.stopApplication(appData); @@ -119,8 +118,9 @@ export class IOSApplicationManager extends ApplicationManagerBase { } } - private async runApplicationCore(appData: Mobile.IApplicationData): Promise { - await this.$iosDeviceOperations.start([{ deviceId: this.device.deviceInfo.identifier, appId: appData.appId, ddi: this.$options.ddi }]); + private async runApplicationCore(appData: Mobile.IStartApplicationData): Promise { + const waitForDebugger = appData.waitForDebugger && appData.waitForDebugger.toString(); + await this.$iosDeviceOperations.start([{ deviceId: this.device.deviceInfo.identifier, appId: appData.appId, ddi: this.$options.ddi, waitForDebugger }]); } @cache() diff --git a/lib/common/mobile/ios/device/ios-device.ts b/lib/common/mobile/ios/device/ios-device.ts index b53dec43c2..6abe9618ea 100644 --- a/lib/common/mobile/ios/device/ios-device.ts +++ b/lib/common/mobile/ios/device/ios-device.ts @@ -17,10 +17,10 @@ export class IOSDevice extends IOSDeviceBase { protected $errors: IErrors, private $injector: IInjector, protected $iOSDebuggerPortService: IIOSDebuggerPortService, + protected $deviceLogProvider: Mobile.IDeviceLogProvider, protected $lockService: ILockService, private $iOSSocketRequestExecutor: IiOSSocketRequestExecutor, protected $processService: IProcessService, - private $deviceLogProvider: Mobile.IDeviceLogProvider, private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, private $iOSDeviceProductNameMapper: Mobile.IiOSDeviceProductNameMapper, private $iosDeviceOperations: IIOSDeviceOperations, @@ -60,9 +60,10 @@ export class IOSDevice extends IOSDeviceBase { } } - protected async getSocketCore(appId: string): Promise { + protected async getDebugSocketCore(appId: string, projectName: string): Promise { + await super.attachToDebuggerFoundEvent(projectName); await this.$iOSSocketRequestExecutor.executeAttachRequest(this, constants.AWAIT_NOTIFICATION_TIMEOUT_SECONDS, appId); - const port = await this.getDebuggerPort(appId); + const port = await super.getDebuggerPort(appId); const deviceId = this.deviceInfo.identifier; const socket = await helpers.connectEventuallyUntilTimeout( diff --git a/lib/common/mobile/ios/ios-device-base.ts b/lib/common/mobile/ios/ios-device-base.ts index fd384c8de8..976754f34d 100644 --- a/lib/common/mobile/ios/ios-device-base.ts +++ b/lib/common/mobile/ios/ios-device-base.ts @@ -1,8 +1,10 @@ import * as net from "net"; +import { performanceLog } from "../../decorators"; export abstract class IOSDeviceBase implements Mobile.IiOSDevice { private cachedSockets: IDictionary = {}; protected abstract $errors: IErrors; + protected abstract $deviceLogProvider: Mobile.IDeviceLogProvider; protected abstract $iOSDebuggerPortService: IIOSDebuggerPortService; protected abstract $processService: IProcessService; protected abstract $lockService: ILockService; @@ -10,50 +12,40 @@ export abstract class IOSDeviceBase implements Mobile.IiOSDevice { abstract applicationManager: Mobile.IDeviceApplicationManager; abstract fileSystem: Mobile.IDeviceFileSystem; abstract isEmulator: boolean; - abstract openDeviceLogStream(): Promise; + abstract openDeviceLogStream(options?: Mobile.IiOSLogStreamOptions): Promise; public getApplicationInfo(applicationIdentifier: string): Promise { return this.applicationManager.getApplicationInfo(applicationIdentifier); } - public async getLiveSyncSocket(appId: string): Promise { - return this.getSocket(appId); - } - - public async getDebugSocket(appId: string): Promise { - return this.getSocket(appId); - } - - public async getSocket(appId: string): Promise { + @performanceLog() + public async getDebugSocket(appId: string, projectName: string): Promise { return this.$lockService.executeActionWithLock(async () => { if (this.cachedSockets[appId]) { return this.cachedSockets[appId]; } - this.cachedSockets[appId] = await this.getSocketCore(appId); + this.cachedSockets[appId] = await this.getDebugSocketCore(appId, projectName); if (this.cachedSockets[appId]) { this.cachedSockets[appId].on("close", () => { - this.destroySocket(appId); + this.destroyDebugSocket(appId); }); - this.$processService.attachToProcessExitSignals(this, () => this.destroySocket(appId)); + this.$processService.attachToProcessExitSignals(this, () => this.destroyDebugSocket(appId)); } return this.cachedSockets[appId]; }, "ios-debug-socket.lock"); } - public destroyLiveSyncSocket(appId: string) { - this.destroySocket(appId); - } + protected abstract async getDebugSocketCore(appId: string, projectName: string): Promise; - public destroyDebugSocket(appId: string) { - this.destroySocket(appId); + protected async attachToDebuggerFoundEvent(projectName: string): Promise { + await this.startDeviceLogProcess(projectName); + await this.$iOSDebuggerPortService.attachToDebuggerPortFoundEvent(); } - protected abstract async getSocketCore(appId: string): Promise; - protected async getDebuggerPort(appId: string): Promise { const port = await this.$iOSDebuggerPortService.getPort({ deviceId: this.deviceInfo.identifier, appId }); if (!port) { @@ -71,7 +63,7 @@ export abstract class IOSDeviceBase implements Mobile.IiOSDevice { this.cachedSockets = {}; } - private destroySocket(appId: string) { + public destroyDebugSocket(appId: string) { this.destroySocketSafe(this.cachedSockets[appId]); this.cachedSockets[appId] = null; } @@ -81,4 +73,12 @@ export abstract class IOSDeviceBase implements Mobile.IiOSDevice { socket.destroy(); } } + + private async startDeviceLogProcess(projectName: string): Promise { + if (projectName) { + this.$deviceLogProvider.setProjectNameForDevice(this.deviceInfo.identifier, projectName); + } + + await this.openDeviceLogStream(); + } } diff --git a/lib/common/mobile/ios/simulator/ios-emulator-services.ts b/lib/common/mobile/ios/simulator/ios-emulator-services.ts index 52004fb940..aaa4a4e122 100644 --- a/lib/common/mobile/ios/simulator/ios-emulator-services.ts +++ b/lib/common/mobile/ios/simulator/ios-emulator-services.ts @@ -41,28 +41,6 @@ class IosEmulatorServices implements Mobile.IiOSSimulatorService { return ""; } - public runApplicationOnEmulator(app: string, emulatorOptions?: Mobile.IRunApplicationOnEmulatorOptions): Promise { - emulatorOptions = emulatorOptions || {}; - - if (emulatorOptions.availableDevices) { - return this.$iOSSimResolver.iOSSim.printDeviceTypes(); - } - - const options: any = { - sdkVersion: emulatorOptions.sdk, - device: emulatorOptions.device, - args: emulatorOptions.args, - waitForDebugger: emulatorOptions.waitForDebugger, - skipInstall: emulatorOptions.skipInstall - }; - - if (emulatorOptions.justlaunch) { - options.exit = true; - } - - return this.$iOSSimResolver.iOSSim.launchApplication(app, emulatorOptions.appId, options); - } - public async postDarwinNotification(notification: string, deviceId: string): Promise { return this.$iOSSimResolver.iOSSim.sendNotification(notification, deviceId); } diff --git a/lib/common/mobile/ios/simulator/ios-simulator-application-manager.ts b/lib/common/mobile/ios/simulator/ios-simulator-application-manager.ts index 4269ae0f42..ee7d2eaf3a 100644 --- a/lib/common/mobile/ios/simulator/ios-simulator-application-manager.ts +++ b/lib/common/mobile/ios/simulator/ios-simulator-application-manager.ts @@ -1,20 +1,33 @@ import { ApplicationManagerBase } from "../../application-manager-base"; -import * as path from "path"; -import * as temp from "temp"; +import { ChildProcess } from "child_process"; import { hook, getPidFromiOSSimulatorLogs } from "../../../helpers"; import { cache } from "../../../decorators"; import { IOS_LOG_PREDICATE } from "../../../constants"; +import * as path from "path"; +import * as temp from "temp"; +import * as log4js from "log4js"; export class IOSSimulatorApplicationManager extends ApplicationManagerBase { - constructor(private iosSim: any, + private _lldbProcesses: IDictionary = {}; + + constructor(private $childProcess: IChildProcess, + private iosSim: any, private device: Mobile.IiOSDevice, private $options: IOptions, private $fs: IFileSystem, private $plistParser: IPlistParser, + private $processService: IProcessService, private $deviceLogProvider: Mobile.IDeviceLogProvider, $logger: ILogger, $hooksService: IHooksService) { super($logger, $hooksService); + this.$processService.attachToProcessExitSignals(this, () => { + for (const appId in this._lldbProcesses) { + /* tslint:disable:no-floating-promises */ + this.detachNativeDebugger(appId); + /* tslint:enable:no-floating-promises */ + } + }); } public async getInstalledApplications(): Promise { @@ -37,20 +50,28 @@ export class IOSSimulatorApplicationManager extends ApplicationManagerBase { } public async uninstallApplication(appIdentifier: string): Promise { + await this.detachNativeDebugger(appIdentifier); return this.iosSim.uninstallApplication(this.device.deviceInfo.identifier, appIdentifier); } - public async startApplication(appData: Mobile.IApplicationData): Promise { - const launchResult = await this.iosSim.startApplication(this.device.deviceInfo.identifier, appData.appId); + public async startApplication(appData: Mobile.IStartApplicationData): Promise { + const options = appData.waitForDebugger ? { + waitForDebugger: true, + args: "--nativescript-debug-brk", + } : {}; + const launchResult = await this.iosSim.startApplication(this.device.deviceInfo.identifier, appData.appId, options); const pid = getPidFromiOSSimulatorLogs(appData.appId, launchResult); await this.setDeviceLogData(appData, pid); + if (appData.waitForDebugger) { + this.attachNativeDebugger(appData.appId, pid); + } } public async stopApplication(appData: Mobile.IApplicationData): Promise { const { appId } = appData; this.device.destroyDebugSocket(appId); - this.device.destroyLiveSyncSocket(appId); + await this.detachNativeDebugger(appId); await this.iosSim.stopApplication(this.device.deviceInfo.identifier, appData.appId, appData.projectName); } @@ -88,6 +109,36 @@ export class IOSSimulatorApplicationManager extends ApplicationManagerBase { return Promise.resolve(null); } + // iOS will kill the app if we freeze it in the NativeScript Runtime and wait for debug-brk. + // In order to avoid that, we are attaching lldb and passing it "process continue". + // In this way, iOS will not kill the app because it has a native debugger attached + // and the users will be able to attach a debug session using the debug-brk flag. + private attachNativeDebugger(appId: string, pid: string): void { + this._lldbProcesses[appId] = this.$childProcess.spawn("lldb", ["-p", pid]); + if (log4js.levels.TRACE.isGreaterThanOrEqualTo(this.$logger.getLevel())) { + this._lldbProcesses[appId].stdout.pipe(process.stdout); + } + this._lldbProcesses[appId].stderr.pipe(process.stderr); + this._lldbProcesses[appId].stdin.write("process continue\n"); + } + + private async detachNativeDebugger(appId: string) { + if (this._lldbProcesses[appId]) { + this._lldbProcesses[appId].stdin.write("process detach\n"); + await this.killProcess(this._lldbProcesses[appId]); + this._lldbProcesses[appId] = undefined; + } + } + + private async killProcess(childProcess: ChildProcess): Promise { + if (childProcess) { + return new Promise((resolve, reject) => { + childProcess.on("close", resolve); + childProcess.kill(); + }); + } + } + private async getParsedPlistContent(appIdentifier: string): Promise { if (! await this.isApplicationInstalled(appIdentifier)) { return null; @@ -110,6 +161,6 @@ export class IOSSimulatorApplicationManager extends ApplicationManagerBase { @cache() private startDeviceLog(): Promise { - return this.device.openDeviceLogStream({predicate: IOS_LOG_PREDICATE}); + return this.device.openDeviceLogStream({ predicate: IOS_LOG_PREDICATE }); } } diff --git a/lib/common/mobile/ios/simulator/ios-simulator-device.ts b/lib/common/mobile/ios/simulator/ios-simulator-device.ts index 5a34ba89c0..15f2533c08 100644 --- a/lib/common/mobile/ios/simulator/ios-simulator-device.ts +++ b/lib/common/mobile/ios/simulator/ios-simulator-device.ts @@ -13,6 +13,7 @@ export class IOSSimulator extends IOSDeviceBase implements Mobile.IiOSDevice { constructor(private simulator: Mobile.IiSimDevice, private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, + protected $deviceLogProvider: Mobile.IDeviceLogProvider, protected $errors: IErrors, protected $lockService: ILockService, private $injector: IInjector, @@ -52,11 +53,12 @@ export class IOSSimulator extends IOSDeviceBase implements Mobile.IiOSDevice { return this.$iOSSimulatorLogProvider.startLogProcess(this.simulator.id, options); } - protected async getSocketCore(appId: string): Promise { + protected async getDebugSocketCore(appId: string, projectName: string): Promise { let socket: net.Socket; + await super.attachToDebuggerFoundEvent(projectName); const attachRequestMessage = this.$iOSNotification.getAttachRequest(appId, this.deviceInfo.identifier); await this.$iOSEmulatorServices.postDarwinNotification(attachRequestMessage, this.deviceInfo.identifier); - const port = await this.getDebuggerPort(appId); + const port = await super.getDebuggerPort(appId); try { socket = await helpers.connectEventuallyUntilTimeout( async () => { return this.$iOSEmulatorServices.connectToPort({ port }); }, diff --git a/lib/common/mobile/mobile-core/devices-service.ts b/lib/common/mobile/mobile-core/devices-service.ts index deb58d3f15..6c1b483087 100644 --- a/lib/common/mobile/mobile-core/devices-service.ts +++ b/lib/common/mobile/mobile-core/devices-service.ts @@ -6,6 +6,10 @@ import { exported } from "../../decorators"; import { settlePromises } from "../../helpers"; import { EventEmitter } from "events"; import { EOL } from "os"; +import { CONNECTED_STATUS } from "../../constants"; +import { isInteractive } from "../../helpers"; +import { DebugCommandErrors } from "../../../constants"; +import { performanceLog } from "../../decorators"; export class DevicesService extends EventEmitter implements Mobile.IDevicesService { private static DEVICE_LOOKING_INTERVAL = 200; @@ -42,11 +46,67 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi private $iOSEmulatorServices: Mobile.IiOSSimulatorService, private $androidEmulatorServices: Mobile.IEmulatorPlatformService, private $androidEmulatorDiscovery: Mobile.IDeviceDiscovery, - private $emulatorHelper: Mobile.IEmulatorHelper) { - super(); - this.attachToKnownDeviceDiscoveryEvents(); - this.attachToKnownEmulatorDiscoveryEvents(); - this._allDeviceDiscoveries = [this.$iOSDeviceDiscovery, this.$androidDeviceDiscovery, this.$iOSSimulatorDiscovery]; + private $emulatorHelper: Mobile.IEmulatorHelper, + private $prompter: IPrompter) { + super(); + this.attachToKnownDeviceDiscoveryEvents(); + this.attachToKnownEmulatorDiscoveryEvents(); + this._allDeviceDiscoveries = [this.$iOSDeviceDiscovery, this.$androidDeviceDiscovery, this.$iOSSimulatorDiscovery]; + } + + @performanceLog() + public async pickSingleDevice(options: Mobile.IPickSingleDeviceOptions): Promise { + if (options.onlyDevices && options.onlyEmulators) { + this.$errors.fail(DebugCommandErrors.UNABLE_TO_USE_FOR_DEVICE_AND_EMULATOR); + } + + if (options.deviceId) { + const device = await this.getDevice(options.deviceId); + return device; + } + + // Now let's take data for each device: + const availableDevicesAndEmulators = this.getDeviceInstances() + .filter(d => d.deviceInfo.status === CONNECTED_STATUS && (!this.platform || d.deviceInfo.platform.toLowerCase() === this.platform.toLowerCase())); + + const selectedDevices = availableDevicesAndEmulators.filter(d => options.onlyEmulators ? d.isEmulator : (options.onlyDevices ? !d.isEmulator : true)); + + if (selectedDevices.length > 1) { + if (isInteractive()) { + const choices = selectedDevices.map(e => `${e.deviceInfo.identifier} - ${e.deviceInfo.displayName}`); + + const selectedDeviceString = await this.$prompter.promptForChoice("Select device for debugging", choices); + + const selectedDevice = _.find(selectedDevices, d => `${d.deviceInfo.identifier} - ${d.deviceInfo.displayName}` === selectedDeviceString); + return selectedDevice; + } else { + const sortedInstances = _.sortBy(selectedDevices, e => e.deviceInfo.version); + const emulators = sortedInstances.filter(e => e.isEmulator); + const devices = sortedInstances.filter(d => !d.isEmulator); + let selectedInstance: Mobile.IDevice; + + if (options.onlyEmulators || options.onlyDevices) { + // When --emulator or --forDevice is passed, the instances are already filtered + // So we are sure we have exactly the type we need and we can safely return the last one (highest OS version). + selectedInstance = _.last(sortedInstances); + } else { + if (emulators.length) { + selectedInstance = _.last(emulators); + } else { + selectedInstance = _.last(devices); + } + } + + this.$logger.warn(`Multiple devices/emulators found. Starting debugger on ${selectedInstance.deviceInfo.identifier}. ` + + "If you want to debug on specific device/emulator, you can specify it with --device option."); + + return selectedInstance; + } + } else if (selectedDevices.length === 1) { + return _.head(selectedDevices); + } + + this.$errors.failWithoutHelp(DebugCommandErrors.NO_DEVICES_EMULATORS_FOUND_FOR_OPTIONS); } @exported("devicesService") @@ -70,7 +130,7 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi return ["Missing mandatory image identifier or name option."]; } - const availableEmulatorsOutput = await this.getEmulatorImages({platform: options.platform}); + const availableEmulatorsOutput = await this.getEmulatorImages({ platform: options.platform }); const emulators = this.$emulatorHelper.getEmulatorsFromAvailableEmulatorsOutput(availableEmulatorsOutput); const errors = this.$emulatorHelper.getErrorsFromAvailableEmulatorsOutput(availableEmulatorsOutput); if (errors.length) { diff --git a/lib/common/test/unit-tests/android-application-manager.ts b/lib/common/test/unit-tests/android-application-manager.ts index c677ef5502..61b849a87f 100644 --- a/lib/common/test/unit-tests/android-application-manager.ts +++ b/lib/common/test/unit-tests/android-application-manager.ts @@ -44,7 +44,9 @@ class AndroidDebugBridgeStub { public async executeShellCommand(args: string[]): Promise { if (args && args.length > 0) { - if (args[0] === "pm") { + if (args[0].startsWith("cat")) { + return; + } else if (args[0] === "pm") { const passedIdentifier = args[2]; if (passedIdentifier === invalidIdentifier) { return "invalid output string"; diff --git a/lib/common/test/unit-tests/mobile/application-manager-base.ts b/lib/common/test/unit-tests/mobile/application-manager-base.ts index 3f03f61b95..123d8a6e6f 100644 --- a/lib/common/test/unit-tests/mobile/application-manager-base.ts +++ b/lib/common/test/unit-tests/mobile/application-manager-base.ts @@ -693,6 +693,7 @@ describe("ApplicationManagerBase", () => { } isStartApplicationCalled = true; + return Promise.resolve(); }; await applicationManager.tryStartApplication(applicationData); diff --git a/lib/common/test/unit-tests/mobile/devices-service.ts b/lib/common/test/unit-tests/mobile/devices-service.ts index f1ab3c4ca6..96c4fb7aa4 100644 --- a/lib/common/test/unit-tests/mobile/devices-service.ts +++ b/lib/common/test/unit-tests/mobile/devices-service.ts @@ -1,6 +1,7 @@ import { DevicesService } from "../../../mobile/mobile-core/devices-service"; import { Yok } from "../../../yok"; -import { EmulatorDiscoveryNames, DeviceDiscoveryEventNames } from "../../../constants"; +import { EmulatorDiscoveryNames, DeviceDiscoveryEventNames, CONNECTED_STATUS, UNREACHABLE_STATUS } from "../../../constants"; +import { DebugCommandErrors } from "../../../../constants"; import { EventEmitter } from "events"; import { assert, use } from "chai"; @@ -14,6 +15,8 @@ import { Messages } from "../../../messages/messages"; import * as constants from "../../../constants"; import { DevicePlatformsConstants } from "../../../mobile/device-platforms-constants"; +const helpers = require("../../../helpers"); +const originalIsInteractive = helpers.isInteractive; class AndroidEmulatorDiscoveryStub extends EventEmitter { public startLookingForDevices(): void { // Intentionally left blank. @@ -156,6 +159,7 @@ function createTestInjector(): IInjector { testInjector.register("androidEmulatorServices", AndroidEmulatorServices); testInjector.register("iOSEmulatorServices", IOSEmulatorServices); testInjector.register("messages", Messages); + testInjector.register("prompter", {}); testInjector.register("companionAppsService", {}); testInjector.register("processService", { attachToProcessExitSignals: (context: any, callback: () => Promise) => { /* no implementation required */ } @@ -1701,4 +1705,238 @@ describe("devicesService", () => { assert.deepEqual(actualResult, ["com.telerik.unitTest1", "com.telerik.unitTest2", "com.telerik.unitTest3"]); }); }); + + describe("getDeviceForDebug", () => { + it("throws error when both --for-device and --emulator are passed", async () => { + await assert.isRejected(devicesService.pickSingleDevice({ onlyDevices: true, onlyEmulators: true, deviceId: null }), DebugCommandErrors.UNABLE_TO_USE_FOR_DEVICE_AND_EMULATOR); + }); + + it("returns selected device, when --device is passed", async () => { + const deviceInstance = {}; + const specifiedDeviceOption = "device1"; + devicesService.getDevice = async (deviceOption: string): Promise => { + if (deviceOption === specifiedDeviceOption) { + return deviceInstance; + } + }; + + const selectedDeviceInstance = await devicesService.pickSingleDevice({ onlyDevices: false, onlyEmulators: false, deviceId: specifiedDeviceOption }); + assert.deepEqual(selectedDeviceInstance, deviceInstance); + }); + + const assertErrorIsThrown = async (getDeviceInstancesResult: Mobile.IDevice[], passedOptions?: { forDevice: boolean, emulator: boolean }) => { + devicesService.getDeviceInstances = (): Mobile.IDevice[] => getDeviceInstancesResult; + await devicesService.initialize({ platform: "android" }); + + await assert.isRejected(devicesService.pickSingleDevice({ + onlyDevices: passedOptions ? passedOptions.forDevice : false, + onlyEmulators: passedOptions ? passedOptions.emulator : false, + deviceId: null + }), DebugCommandErrors.NO_DEVICES_EMULATORS_FOUND_FOR_OPTIONS); + }; + + it("throws error when there are no devices/emulators available", () => { + return assertErrorIsThrown([]); + }); + + it("throws error when there are no devices/emulators available for selected platform", () => { + return assertErrorIsThrown([ + { + deviceInfo: { + platform: "ios", + status: CONNECTED_STATUS + } + } + ]); + }); + + it("throws error when there are only not-trusted devices/emulators available for selected platform", () => { + return assertErrorIsThrown([ + { + deviceInfo: { + platform: "android", + status: UNREACHABLE_STATUS + } + } + ]); + }); + + it("throws error when there are only devices and --emulator is passed", () => { + return assertErrorIsThrown([ + { + deviceInfo: { + platform: "android", + status: CONNECTED_STATUS + }, + isEmulator: false + } + ], { + forDevice: false, + emulator: true + }); + }); + + it("throws error when there are only emulators and --forDevice is passed", () => { + return assertErrorIsThrown([ + { + deviceInfo: { + platform: "android", + status: CONNECTED_STATUS + }, + isEmulator: true + } + ], { + forDevice: true, + emulator: false + }); + }); + + it("returns the only available device/emulator when it matches passed -- options", async () => { + const deviceInstance = { + deviceInfo: { + platform: "android", + status: CONNECTED_STATUS + }, + isEmulator: true + }; + + devicesService.getDeviceInstances = (): Mobile.IDevice[] => [deviceInstance]; + + const actualDeviceInstance = + await devicesService.pickSingleDevice({ onlyDevices: false, onlyEmulators: false, deviceId: null }); + + assert.deepEqual(actualDeviceInstance, deviceInstance); + }); + + describe("when multiple devices are detected", () => { + beforeEach(() => { + helpers.isInteractive = originalIsInteractive; + }); + + after(() => { + helpers.isInteractive = originalIsInteractive; + }); + + describe("when terminal is interactive", () => { + + it("prompts the user with information about available devices for specified platform only and returns the selected device instance", async () => { + helpers.isInteractive = () => true; + const deviceInstance1 = { + deviceInfo: { + platform: "android", + status: CONNECTED_STATUS, + identifier: "deviceInstance1", + displayName: "displayName1" + }, + isEmulator: true + }; + + const deviceInstance2 = { + deviceInfo: { + platform: "android", + status: CONNECTED_STATUS, + identifier: "deviceInstance2", + displayName: "displayName2" + }, + isEmulator: true + }; + + const iOSDeviceInstance = { + deviceInfo: { + platform: "ios", + status: CONNECTED_STATUS, + identifier: "iosDevice", + displayName: "iPhone" + }, + isEmulator: true + }; + + await devicesService.initialize({ platform: "android" }); + devicesService.getDeviceInstances = (): Mobile.IDevice[] => [deviceInstance1, deviceInstance2, iOSDeviceInstance]; + + let choicesPassedToPrompter: string[]; + const prompter = testInjector.resolve("prompter"); + prompter.promptForChoice = async (promptMessage: string, choices: any[]): Promise => { + choicesPassedToPrompter = choices; + return choices[1]; + }; + + const actualDeviceInstance = + await devicesService.pickSingleDevice({ onlyDevices: false, onlyEmulators: false, deviceId: null }); + const expectedChoicesPassedToPrompter = [deviceInstance1, deviceInstance2].map(d => `${d.deviceInfo.identifier} - ${d.deviceInfo.displayName}`); + assert.deepEqual(choicesPassedToPrompter, expectedChoicesPassedToPrompter); + assert.deepEqual(actualDeviceInstance, deviceInstance2); + }); + }); + + describe("when terminal is not interactive", () => { + beforeEach(() => { + helpers.isInteractive = () => false; + }); + + const assertCorrectInstanceIsUsed = async (opts: { forDevice: boolean, emulator: boolean, isEmulatorTest: boolean, excludeLastDevice?: boolean }) => { + const deviceInstance1 = { + deviceInfo: { + platform: "android", + status: CONNECTED_STATUS, + identifier: "deviceInstance1", + displayName: "displayName1", + version: "5.1" + }, + isEmulator: opts.isEmulatorTest + }; + + const deviceInstance2 = { + deviceInfo: { + platform: "android", + status: CONNECTED_STATUS, + identifier: "deviceInstance2", + displayName: "displayName2", + version: "6.0" + }, + isEmulator: opts.isEmulatorTest + }; + + const deviceInstance3 = { + deviceInfo: { + platform: "android", + status: CONNECTED_STATUS, + identifier: "deviceInstance3", + displayName: "displayName3", + version: "7.1" + }, + isEmulator: !opts.isEmulatorTest + }; + + const deviceInstances = [deviceInstance1, deviceInstance2]; + if (!opts.excludeLastDevice) { + deviceInstances.push(deviceInstance3); + } + + devicesService.getDeviceInstances = (): Mobile.IDevice[] => deviceInstances; + + const actualDeviceInstance = + await devicesService.pickSingleDevice({ onlyDevices: opts.forDevice, onlyEmulators: opts.emulator, deviceId: null }); + + assert.deepEqual(actualDeviceInstance, deviceInstance2); + }; + + it("returns the emulator with highest API level when --emulator is passed", () => { + return assertCorrectInstanceIsUsed({ forDevice: false, emulator: true, isEmulatorTest: true }); + }); + + it("returns the device with highest API level when --forDevice is passed", () => { + return assertCorrectInstanceIsUsed({ forDevice: true, emulator: false, isEmulatorTest: false }); + }); + + it("returns the emulator with highest API level when neither --emulator and --forDevice are passed", () => { + return assertCorrectInstanceIsUsed({ forDevice: false, emulator: false, isEmulatorTest: true }); + }); + + it("returns the device with highest API level when neither --emulator and --forDevice are passed and emulators are not available", async () => { + return assertCorrectInstanceIsUsed({ forDevice: false, emulator: false, isEmulatorTest: false, excludeLastDevice: true }); + }); + }); + }); + }); }); diff --git a/lib/common/test/unit-tests/mobile/ios-simulator-discovery.ts b/lib/common/test/unit-tests/mobile/ios-simulator-discovery.ts index f6c4cb0d31..e962305cfe 100644 --- a/lib/common/test/unit-tests/mobile/ios-simulator-discovery.ts +++ b/lib/common/test/unit-tests/mobile/ios-simulator-discovery.ts @@ -5,7 +5,7 @@ import { assert } from "chai"; import { DeviceDiscoveryEventNames, CONNECTED_STATUS } from "../../../constants"; import { DevicePlatformsConstants } from "../../../mobile/device-platforms-constants"; import { ErrorsStub, CommonLoggerStub, HooksServiceStub, LockServiceStub } from "../stubs"; -import { FileSystemStub } from "../../../../../test/stubs"; +import { FileSystemStub, ChildProcessStub, ProcessServiceStub } from "../../../../../test/stubs"; let currentlyRunningSimulators: Mobile.IiSimDevice[]; @@ -13,6 +13,7 @@ function createTestInjector(): IInjector { const injector = new Yok(); injector.register("fs", FileSystemStub); injector.register("plistParser", {}); + injector.register("childProcess", ChildProcessStub); injector.register("injector", injector); injector.register("errors", ErrorsStub); injector.register("iOSDebuggerPortService", {}); @@ -40,7 +41,7 @@ function createTestInjector(): IInjector { injector.register("deviceLogProvider", {}); injector.register("iOSEmulatorServices", {}); injector.register("iOSNotification", {}); - injector.register("processService", {}); + injector.register("processService", ProcessServiceStub); injector.register("options", {}); injector.register("hooksService", HooksServiceStub); injector.register("logger", CommonLoggerStub); diff --git a/lib/common/test/unit-tests/stubs.ts b/lib/common/test/unit-tests/stubs.ts index b7dfee7f17..75d10257a1 100644 --- a/lib/common/test/unit-tests/stubs.ts +++ b/lib/common/test/unit-tests/stubs.ts @@ -178,6 +178,4 @@ export class DeviceLogProviderStub extends EventEmitter implements Mobile.IDevic setProjectNameForDevice(deviceIdentifier: string, projectName: string): void { this.currentDeviceProjectNames[deviceIdentifier] = projectName; } - - muteLogsForDevice(deviceIdentifier: string): void { } } diff --git a/lib/declarations.d.ts b/lib/declarations.d.ts index 631462421e..4c643c3b1e 100644 --- a/lib/declarations.d.ts +++ b/lib/declarations.d.ts @@ -482,14 +482,10 @@ interface IGenerateOptions { collection?: string; } -interface IDebugInformation extends IPort, Mobile.IDeviceIdentifier, IHasHasReconnected { +interface IDebugInformation extends IPort, Mobile.IDeviceIdentifier { url: string; } -interface IHasHasReconnected { - hasReconnected: boolean; -} - interface IPort { port: Number; } @@ -747,9 +743,9 @@ interface IAndroidToolsInfoValidateInput extends IAndroidToolsInfoOptions { interface IAppDebugSocketProxyFactory extends NodeJS.EventEmitter { getTCPSocketProxy(deviceIdentifier: string, appId: string): any; - addTCPSocketProxy(device: Mobile.IiOSDevice, appId: string): Promise; + addTCPSocketProxy(device: Mobile.IiOSDevice, appId: string, projectName: string): Promise; - ensureWebSocketProxy(device: Mobile.IiOSDevice, appId: string): Promise; + ensureWebSocketProxy(device: Mobile.IiOSDevice, appId: string, projectName: string): Promise; removeAllProxies(): void; } diff --git a/lib/definitions/debug.d.ts b/lib/definitions/debug.d.ts index c2586789b4..f05682ac38 100644 --- a/lib/definitions/debug.d.ts +++ b/lib/definitions/debug.d.ts @@ -141,14 +141,6 @@ interface IDebugService extends IDebugServiceBase { * Describes actions required for debugging on specific platform (Android or iOS). */ interface IDeviceDebugService extends IPlatform, NodeJS.EventEmitter { - /** - * Starts debug operation. - * @param {IAppDebugData} debugData Describes information for application that will be debugged. - * @param {IDebugOptions} debugOptions Describe possible options to modify the behaivor of the debug operation, for example stop on the first line. - * @returns {Promise} - */ - debugStart(debugData: IAppDebugData, debugOptions: IDebugOptions): Promise; - /** * Stops debug operation. * @returns {Promise} @@ -164,6 +156,6 @@ interface IDeviceDebugService extends IPlatform, NodeJS.EventEmitter { debug(debugData: IAppDebugData, debugOptions: IDebugOptions): Promise; } -interface IDebugResultInfo extends IHasHasReconnected { +interface IDebugResultInfo { debugUrl: string; } diff --git a/lib/definitions/ios-debugger-port-service.d.ts b/lib/definitions/ios-debugger-port-service.d.ts index 02d1872551..340b0c9e84 100644 --- a/lib/definitions/ios-debugger-port-service.d.ts +++ b/lib/definitions/ios-debugger-port-service.d.ts @@ -19,15 +19,10 @@ interface IIOSDebuggerPortService { * Gets iOS debugger port for specified deviceId and appId * @param {IIOSDebuggerPortInputData} data - Describes deviceId and appId */ - getPort(data: IIOSDebuggerPortInputData, debugOptions?: IDebugOptions): Promise; + getPort(data: IIOSDebuggerPortInputData): Promise; /** - * Attaches on DEBUGGER_PORT_FOUND event and STARTING_IOS_APPLICATION events - * In case when DEBUGGER_PORT_FOUND event is emitted, stores the port and clears the timeout if such. - * In case when STARTING_IOS_APPLICATION event is emitted, sets the port to null and add timeout for 10000 miliseconds which checks if port is null and prints a warning. - * @param {Mobile.IDevice} device - Describes the device which logs should be parsed. - * @param {IProjectDir} data - Object that has a projectDir property. - * @param {IDebugOptions} debugOptions + * Attaches on DEBUGGER_PORT_FOUND event and stores the port * @returns {Promise} */ - attachToDebuggerPortFoundEvent(device: Mobile.IDevice, data: IProjectDir, debugOptions: IDebugOptions): Promise; + attachToDebuggerPortFoundEvent(): Promise; } \ No newline at end of file diff --git a/lib/definitions/livesync.d.ts b/lib/definitions/livesync.d.ts index 212474a508..9fb762a293 100644 --- a/lib/definitions/livesync.d.ts +++ b/lib/definitions/livesync.d.ts @@ -368,6 +368,7 @@ interface ILiveSyncWatchInfo extends IProjectDataComposition, IHasUseHotModuleRe interface ILiveSyncResultInfo extends IHasUseHotModuleReloadOption { modifiedFilesData: Mobile.ILocalToDevicePathData[]; isFullSync: boolean; + waitForDebugger?: boolean; deviceAppData: Mobile.IDeviceAppData; didRecover?: boolean } @@ -396,7 +397,6 @@ interface IPlatformLiveSyncService { fullSync(syncInfo: IFullSyncInfo): Promise; liveSyncWatchAction(device: Mobile.IDevice, liveSyncInfo: ILiveSyncWatchInfo): Promise; refreshApplication(projectData: IProjectData, liveSyncInfo: ILiveSyncResultInfo): Promise; - prepareForLiveSync(device: Mobile.IDevice, data: IProjectDir, liveSyncInfo: ILiveSyncInfo, debugOptions: IDebugOptions): Promise; getDeviceLiveSyncService(device: Mobile.IDevice, projectData: IProjectData): INativeScriptDeviceLiveSyncService; } diff --git a/lib/definitions/platform.d.ts b/lib/definitions/platform.d.ts index 2fe9bdd2f9..cebe288593 100644 --- a/lib/definitions/platform.d.ts +++ b/lib/definitions/platform.d.ts @@ -133,7 +133,7 @@ interface IPlatformService extends IBuildPlatformAction, NodeJS.EventEmitter { * @param {IProjectData} projectData DTO with information about the project. * @returns {void} */ - startApplication(platform: string, runOptions: IRunPlatformOptions, appData: Mobile.IApplicationData): Promise; + startApplication(platform: string, runOptions: IRunPlatformOptions, appData: Mobile.IStartApplicationData): Promise; cleanDestinationApp(platformInfo: IPreparePlatformInfo): Promise; validatePlatformInstalled(platform: string, projectData: IProjectData): void; @@ -278,7 +278,7 @@ interface IValidBuildOutputData { regexes?: RegExp[]; } -interface IBuildOutputOptions extends Partial, IRelease, IHasAndroidBundle {} +interface IBuildOutputOptions extends Partial, IRelease, IHasAndroidBundle { } interface IPlatformsData { availablePlatforms: any; diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index b9f7aa950f..2684a8f3c0 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -54,7 +54,7 @@ interface ICreateProjectData extends IProjectDir, IProjectName { } interface IProjectService { - validateProjectName(opts: { projectName: string, force: boolean, pathToProject: string }) : Promise + validateProjectName(opts: { projectName: string, force: boolean, pathToProject: string }): Promise /** * Creates new NativeScript application. * @param {any} projectSettings Options describing new project - its name, appId, path and template from which to be created. @@ -463,7 +463,6 @@ interface IValidatePlatformOutput { } interface ITestExecutionService { - startTestRunner(platform: string, projectData: IProjectData, projectFilesConfig: IProjectFilesConfig): Promise; startKarmaServer(platform: string, projectData: IProjectData, projectFilesConfig: IProjectFilesConfig): Promise; } diff --git a/lib/device-sockets/ios/app-debug-socket-proxy-factory.ts b/lib/device-sockets/ios/app-debug-socket-proxy-factory.ts index 5f015aca8d..8967bd2ee5 100644 --- a/lib/device-sockets/ios/app-debug-socket-proxy-factory.ts +++ b/lib/device-sockets/ios/app-debug-socket-proxy-factory.ts @@ -20,7 +20,7 @@ export class AppDebugSocketProxyFactory extends EventEmitter implements IAppDebu return this.deviceTcpServers[`${deviceIdentifier}-${appId}`]; } - public async addTCPSocketProxy(device: Mobile.IiOSDevice, appId: string): Promise { + public async addTCPSocketProxy(device: Mobile.IiOSDevice, appId: string, projectName: string): Promise { const cacheKey = `${device.deviceInfo.identifier}-${appId}`; const existingServer = this.deviceTcpServers[cacheKey]; if (existingServer) { @@ -44,7 +44,7 @@ export class AppDebugSocketProxyFactory extends EventEmitter implements IAppDebu } }); - const appDebugSocket = await device.getDebugSocket(appId); + const appDebugSocket = await device.getDebugSocket(appId, projectName); this.$logger.info("Backend socket created."); appDebugSocket.on("end", () => { @@ -80,9 +80,9 @@ export class AppDebugSocketProxyFactory extends EventEmitter implements IAppDebu return server; } - public async ensureWebSocketProxy(device: Mobile.IiOSDevice, appId: string): Promise { + public async ensureWebSocketProxy(device: Mobile.IiOSDevice, appId: string, projectName: string): Promise { const existingWebProxy = this.deviceWebServers[`${device.deviceInfo.identifier}-${appId}`]; - const result = existingWebProxy || await this.addWebSocketProxy(device, appId); + const result = existingWebProxy || await this.addWebSocketProxy(device, appId, projectName); // TODO: do not remove till VSCode waits for this message in order to reattach this.$logger.info("Opened localhost " + result.options.port); @@ -90,7 +90,7 @@ export class AppDebugSocketProxyFactory extends EventEmitter implements IAppDebu return result; } - private async addWebSocketProxy(device: Mobile.IiOSDevice, appId: string): Promise { + private async addWebSocketProxy(device: Mobile.IiOSDevice, appId: string, projectName: string): Promise { const cacheKey = `${device.deviceInfo.identifier}-${appId}`; const existingServer = this.deviceWebServers[cacheKey]; if (existingServer) { @@ -115,7 +115,7 @@ export class AppDebugSocketProxyFactory extends EventEmitter implements IAppDebu this.$logger.info("Frontend client connected."); let appDebugSocket; try { - appDebugSocket = await device.getDebugSocket(appId); + appDebugSocket = await device.getDebugSocket(appId, projectName); this.$logger.info("Backend socket created."); info.req["__deviceSocket"] = appDebugSocket; } catch (err) { diff --git a/lib/device-sockets/ios/notification.ts b/lib/device-sockets/ios/notification.ts index a9e72eb23e..ce85a19fe1 100644 --- a/lib/device-sockets/ios/notification.ts +++ b/lib/device-sockets/ios/notification.ts @@ -16,8 +16,8 @@ export class IOSNotification extends EventEmitter implements IiOSNotification { return this.formatNotification(IOSNotification.READY_FOR_ATTACH_NOTIFICATION_NAME, projectId); } - private formatNotification(notification: string, projectId: string) { - return `${projectId}:NativeScript.Debug.${notification}`; + private formatNotification(notification: string, appId: string) { + return `${appId}:NativeScript.Debug.${notification}`; } } $injector.register("iOSNotification", IOSNotification); diff --git a/lib/services/android-device-debug-service.ts b/lib/services/android-device-debug-service.ts index febdceebac..b764e5bd11 100644 --- a/lib/services/android-device-debug-service.ts +++ b/lib/services/android-device-debug-service.ts @@ -15,10 +15,8 @@ export class AndroidDeviceDebugService extends DebugServiceBase implements IDevi protected $devicesService: Mobile.IDevicesService, private $errors: IErrors, private $logger: ILogger, - private $androidDeviceDiscovery: Mobile.IDeviceDiscovery, private $androidProcessService: Mobile.IAndroidProcessService, private $net: INet, - private $projectDataService: IProjectDataService, private $deviceLogProvider: Mobile.IDeviceLogProvider) { super(device, $devicesService); @@ -28,11 +26,10 @@ export class AndroidDeviceDebugService extends DebugServiceBase implements IDevi @performanceLog() public async debug(debugData: IDebugData, debugOptions: IDebugOptions): Promise { this._packageName = debugData.applicationIdentifier; - const result = this.device.isEmulator - ? await this.debugOnEmulator(debugData, debugOptions) - : await this.debugOnDevice(debugData, debugOptions); + const result = await this.debugCore(debugData.applicationIdentifier, debugOptions); - if (!debugOptions.justlaunch) { + // TODO: extract this logic outside the debug service + if (debugOptions.start && !debugOptions.justlaunch) { const pid = await this.$androidProcessService.getAppProcessId(this.deviceIdentifier, debugData.applicationIdentifier); if (pid) { this.$deviceLogProvider.setApplicationPidForDevice(this.deviceIdentifier, pid); @@ -44,31 +41,10 @@ export class AndroidDeviceDebugService extends DebugServiceBase implements IDevi return result; } - public async debugStart(debugData: IDebugData, debugOptions: IDebugOptions): Promise { - await this.$devicesService.initialize({ platform: this.platform, deviceId: this.deviceIdentifier }); - const projectData = this.$projectDataService.getProjectData(debugData.projectDir); - const appData: Mobile.IApplicationData = { - appId: debugData.applicationIdentifier, - projectName: projectData.projectName - }; - - const action = (device: Mobile.IAndroidDevice): Promise => this.debugStartCore(appData, debugOptions); - - await this.$devicesService.execute(action, this.getCanExecuteAction(this.deviceIdentifier)); - } - public debugStop(): Promise { return this.removePortForwarding(); } - private async debugOnEmulator(debugData: IDebugData, debugOptions: IDebugOptions): Promise { - // Assure we've detected the emulator as device - // For example in case deployOnEmulator had stated new emulator instance - // we need some time to detect it. Let's force detection. - await this.$androidDeviceDiscovery.startLookingForDevices(); - return this.debugOnDevice(debugData, debugOptions); - } - private async removePortForwarding(packageName?: string): Promise { const port = await this.getForwardedDebugPort(this.device.deviceInfo.identifier, packageName || this._packageName); return this.device.adb.executeCommand(["forward", "--remove", `tcp:${port}`]); @@ -100,44 +76,20 @@ export class AndroidDeviceDebugService extends DebugServiceBase implements IDevi } @performanceLog() - private async debugOnDevice(debugData: IDebugData, debugOptions: IDebugOptions): Promise { - let packageFile = ""; - - if (!debugOptions.start && !this.device.isEmulator) { - packageFile = debugData.pathToAppPackage; - this.$logger.out("Using ", packageFile); - } - - await this.$devicesService.initialize({ platform: this.platform, deviceId: this.deviceIdentifier }); - - const projectName = this.$projectDataService.getProjectData(debugData.projectDir).projectName; - const appData: Mobile.IApplicationData = { - appId: debugData.applicationIdentifier, - projectName - }; - - const action = (device: Mobile.IAndroidDevice): Promise => this.debugCore(device, packageFile, appData, debugOptions); - - const deviceActionResult = await this.$devicesService.execute(action, this.getCanExecuteAction(this.deviceIdentifier)); - return deviceActionResult[0].result; - } - - @performanceLog() - private async debugCore(device: Mobile.IAndroidDevice, packageFile: string, appData: Mobile.IApplicationData, debugOptions: IDebugOptions): Promise { - const result: IDebugResultInfo = { hasReconnected: false, debugUrl: null }; + private async debugCore(appId: string, debugOptions: IDebugOptions): Promise { + const result: IDebugResultInfo = { debugUrl: null }; if (debugOptions.stop) { await this.removePortForwarding(); return result; } - if (!debugOptions.start) { - await this.debugStartCore(appData, debugOptions); - result.hasReconnected = true; + await this.validateRunningApp(this.deviceIdentifier, appId); + if (debugOptions.debugBrk) { + await this.waitForDebugServer(appId); } - await this.validateRunningApp(device.deviceInfo.identifier, appData.appId); - const debugPort = await this.getForwardedDebugPort(device.deviceInfo.identifier, appData.appId); - await this.printDebugPort(device.deviceInfo.identifier, debugPort); + const debugPort = await this.getForwardedDebugPort(this.deviceIdentifier, appId); + await this.printDebugPort(this.deviceIdentifier, debugPort); result.debugUrl = this.getChromeDebugUrl(debugOptions, debugPort); @@ -148,28 +100,15 @@ export class AndroidDeviceDebugService extends DebugServiceBase implements IDevi this.$logger.info("device: " + deviceId + " debug port: " + port + "\n"); } + // TODO: extract this logic outside the debug service private async validateRunningApp(deviceId: string, packageName: string): Promise { if (!(await this.isAppRunning(packageName, deviceId))) { this.$errors.failWithoutHelp(`The application ${packageName} does not appear to be running on ${deviceId} or is not built with debugging enabled. Try starting the application manually.`); } } - private async debugStartCore(appData: Mobile.IApplicationData, debugOptions: IDebugOptions): Promise { - await this.device.applicationManager.stopApplication(appData); - - if (debugOptions.debugBrk) { - await this.device.adb.executeShellCommand([`cat /dev/null > ${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${appData.appId}-debugbreak`]); - } - - await this.device.adb.executeShellCommand([`cat /dev/null > ${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${appData.appId}-debugger-started`]); - - await this.device.applicationManager.startApplication(appData); - - await this.waitForDebugger(appData.appId); - } - - private async waitForDebugger(packageName: String): Promise { - const debuggerStartedFilePath = `${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${packageName}-debugger-started`; + private async waitForDebugServer(appId: String): Promise { + const debuggerStartedFilePath = `${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${appId}-debugger-started`; const waitText: string = `0 ${debuggerStartedFilePath}`; let maxWait = 12; let debuggerStarted: boolean = false; diff --git a/lib/services/debug-service-base.ts b/lib/services/debug-service-base.ts index 230fbb3d78..4b6a9ea097 100644 --- a/lib/services/debug-service-base.ts +++ b/lib/services/debug-service-base.ts @@ -12,8 +12,6 @@ export abstract class DebugServiceBase extends EventEmitter implements IDeviceDe public abstract async debug(debugData: IDebugData, debugOptions: IDebugOptions): Promise; - public abstract async debugStart(debugData: IDebugData, debugOptions: IDebugOptions): Promise; - public abstract async debugStop(): Promise; protected getCanExecuteAction(deviceIdentifier: string): (device: Mobile.IDevice) => boolean { diff --git a/lib/services/debug-service.ts b/lib/services/debug-service.ts index 0d2ca0afa1..0771c77376 100644 --- a/lib/services/debug-service.ts +++ b/lib/services/debug-service.ts @@ -100,8 +100,7 @@ export class DebugService extends EventEmitter implements IDebugService { const debugInfo: IDebugInformation = { url: debugResultInfo.debugUrl, port: 0, - deviceIdentifier, - hasReconnected: debugResultInfo.hasReconnected + deviceIdentifier }; if (debugResultInfo.debugUrl) { diff --git a/lib/services/ios-debugger-port-service.ts b/lib/services/ios-debugger-port-service.ts index 4af4adcb69..8dd0463617 100644 --- a/lib/services/ios-debugger-port-service.ts +++ b/lib/services/ios-debugger-port-service.ts @@ -11,11 +11,10 @@ export class IOSDebuggerPortService implements IIOSDebuggerPortService { private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, private $logger: ILogger) { } - public getPort(data: IIOSDebuggerPortInputData, debugOptions?: IDebugOptions): Promise { + public getPort(data: IIOSDebuggerPortInputData): Promise { return new Promise((resolve, reject) => { const key = `${data.deviceId}${data.appId}`; - const timeout = this.getTimeout(debugOptions); - let retryCount = Math.max(timeout * 1000 / 500, 10); + let retryCount = Math.max(IOSDebuggerPortService.DEFAULT_TIMEOUT_IN_SECONDS * 1000 / 500, 10); const interval = setInterval(() => { let port = this.getPortByKey(key); @@ -30,9 +29,9 @@ export class IOSDebuggerPortService implements IIOSDebuggerPortService { }); } - public async attachToDebuggerPortFoundEvent(device: Mobile.IDevice, data: IProjectDir, debugOptions: IDebugOptions): Promise { + public async attachToDebuggerPortFoundEvent(): Promise { this.attachToDebuggerPortFoundEventCore(); - this.attachToAttachRequestEvent(device, debugOptions); + this.attachToAttachRequestEvent(); } @cache() @@ -53,14 +52,12 @@ export class IOSDebuggerPortService implements IIOSDebuggerPortService { }; this.$logger.trace(DEBUGGER_PORT_FOUND_EVENT_NAME, data); - this.setData(data, { port: data.port }); this.clearTimeout(data); + this.setData(data, { port: data.port }); } @cache() - private attachToAttachRequestEvent(device: Mobile.IDevice, debugOptions: IDebugOptions): void { - const timeout = this.getTimeout(debugOptions); - + private attachToAttachRequestEvent(): void { this.$iOSNotification.on(ATTACH_REQUEST_EVENT_NAME, (data: IIOSDebuggerPortData) => { this.$logger.trace(ATTACH_REQUEST_EVENT_NAME, data); const timer = setTimeout(() => { @@ -68,7 +65,7 @@ export class IOSDebuggerPortService implements IIOSDebuggerPortService { if (!this.getPortByKey(`${data.deviceId}${data.appId}`)) { this.$logger.warn(`NativeScript debugger was not able to get inspector socket port on device ${data.deviceId} for application ${data.appId}.`); } - }, timeout * 1000); + }, IOSDebuggerPortService.DEFAULT_TIMEOUT_IN_SECONDS * 1000); this.setData(data, { port: null, timer }); }); @@ -99,17 +96,5 @@ export class IOSDebuggerPortService implements IIOSDebuggerPortService { clearTimeout(storedData.timer); } } - - private getTimeout(debugOptions: IDebugOptions): number { - let timeout = parseInt(debugOptions && debugOptions.timeout, 10); - if (timeout === 0) { - timeout = Number.MAX_SAFE_INTEGER; - } - if (!timeout) { - timeout = IOSDebuggerPortService.DEFAULT_TIMEOUT_IN_SECONDS; - } - - return timeout; - } } $injector.register("iOSDebuggerPortService", IOSDebuggerPortService); diff --git a/lib/services/ios-device-debug-service.ts b/lib/services/ios-device-debug-service.ts index 641657f0ec..0479006dba 100644 --- a/lib/services/ios-device-debug-service.ts +++ b/lib/services/ios-device-debug-service.ts @@ -1,33 +1,25 @@ import * as path from "path"; -import * as log4js from "log4js"; import { ChildProcess } from "child_process"; import { DebugServiceBase } from "./debug-service-base"; -import { IOS_LOG_PREDICATE } from "../common/constants"; import { CONNECTION_ERROR_EVENT_NAME } from "../constants"; -import { getPidFromiOSSimulatorLogs } from "../common/helpers"; const inspectorAppName = "NativeScript Inspector.app"; const inspectorNpmPackageName = "tns-ios-inspector"; const inspectorUiDir = "WebInspectorUI/"; import { performanceLog } from "../common/decorators"; export class IOSDeviceDebugService extends DebugServiceBase implements IDeviceDebugService { - private _lldbProcess: ChildProcess; private deviceIdentifier: string; constructor(protected device: Mobile.IiOSDevice, protected $devicesService: Mobile.IDevicesService, - private $platformService: IPlatformService, - private $iOSEmulatorServices: Mobile.IiOSSimulatorService, private $childProcess: IChildProcess, private $hostInfo: IHostInfo, private $logger: ILogger, private $errors: IErrors, private $packageInstallationManager: IPackageInstallationManager, - private $iOSDebuggerPortService: IIOSDebuggerPortService, private $processService: IProcessService, private $appDebugSocketProxyFactory: IAppDebugSocketProxyFactory, - private $projectDataService: IProjectDataService, - private $deviceLogProvider: Mobile.IDeviceLogProvider) { + private $projectDataService: IProjectDataService) { super(device, $devicesService); this.$processService.attachToProcessExitSignals(this, this.debugStop); @@ -41,38 +33,16 @@ export class IOSDeviceDebugService extends DebugServiceBase implements IDeviceDe @performanceLog() public async debug(debugData: IDebugData, debugOptions: IDebugOptions): Promise { - const result: IDebugResultInfo = { hasReconnected: false, debugUrl: null }; + const result: IDebugResultInfo = { debugUrl: null }; this.validateOptions(debugOptions); - await this.startDeviceLogProcess(debugData, debugOptions); - await this.$iOSDebuggerPortService.attachToDebuggerPortFoundEvent(this.device, debugData, debugOptions); - - if (!debugOptions.start) { - await this.startApp(debugData, debugOptions); - result.hasReconnected = true; - } - result.debugUrl = await this.wireDebuggerClient(debugData, debugOptions); return result; } - public async debugStart(debugData: IDebugData, debugOptions: IDebugOptions): Promise { - await this.startApp(debugData, debugOptions); - await this.wireDebuggerClient(debugData, debugOptions); - } - public async debugStop(): Promise { this.$appDebugSocketProxyFactory.removeAllProxies(); - await this.stopAppDebuggerOnSimulator(); - } - - private async startApp(debugData: IDebugData, debugOptions: IDebugOptions) { - if (this.device.isEmulator) { - await this.startAppOnSimulator(debugData, debugOptions); - } else { - await this.startAppOnDevice(debugData, debugOptions); - } } private validateOptions(debugOptions: IDebugOptions) { @@ -81,71 +51,14 @@ export class IOSDeviceDebugService extends DebugServiceBase implements IDeviceDe } } - @performanceLog() - private async startDeviceLogProcess(debugData: IDebugData, debugOptions: IDebugOptions): Promise { - if (debugOptions.justlaunch) { - // No logs should be printed on console when `--justlaunch` option is passed. - // On the other side we need to start log process in order to get debugger port from logs. - this.$deviceLogProvider.muteLogsForDevice(this.deviceIdentifier); - } - + private getProjectName(debugData: IDebugData): string { let projectName = debugData.projectName; if (!projectName && debugData.projectDir) { const projectData = this.$projectDataService.getProjectData(debugData.projectDir); projectName = projectData.projectName; } - if (projectName) { - this.$deviceLogProvider.setProjectNameForDevice(this.deviceIdentifier, projectName); - } - - await this.device.openDeviceLogStream({ predicate: IOS_LOG_PREDICATE }); - } - - @performanceLog() - private async startAppOnSimulator(debugData: IDebugData, debugOptions: IDebugOptions): Promise { - const args = debugOptions.debugBrk ? "--nativescript-debug-brk" : "--nativescript-debug-start"; - const launchResult = await this.$iOSEmulatorServices.runApplicationOnEmulator(debugData.pathToAppPackage, { - waitForDebugger: true, - captureStdin: true, - args: args, - appId: debugData.applicationIdentifier, - skipInstall: true, - device: this.deviceIdentifier, - justlaunch: debugOptions.justlaunch, - timeout: debugOptions.timeout, - sdk: debugOptions.sdk - }); - const pid = getPidFromiOSSimulatorLogs(debugData.applicationIdentifier, launchResult); - this.startAppDebuggerOnSimulator(pid); - } - - @performanceLog() - private async startAppOnDevice(debugData: IDebugData, debugOptions: IDebugOptions): Promise { - const runOptions: IRunPlatformOptions = { - device: this.deviceIdentifier, - emulator: this.device.isEmulator, - justlaunch: debugOptions.justlaunch - }; - const projectData = this.$projectDataService.getProjectData(debugData.projectDir); - await this.$platformService.startApplication(this.platform, runOptions, { appId: debugData.applicationIdentifier, projectName: projectData.projectName }); - } - - private startAppDebuggerOnSimulator(pid: string) { - this._lldbProcess = this.$childProcess.spawn("lldb", ["-p", pid]); - if (log4js.levels.TRACE.isGreaterThanOrEqualTo(this.$logger.getLevel())) { - this._lldbProcess.stdout.pipe(process.stdout); - } - this._lldbProcess.stderr.pipe(process.stderr); - this._lldbProcess.stdin.write("process continue\n"); - } - - private async stopAppDebuggerOnSimulator() { - if (this._lldbProcess) { - this._lldbProcess.stdin.write("process detach\n"); - await this.killProcess(this._lldbProcess); - this._lldbProcess = undefined; - } + return projectName; } private async killProcess(childProcess: ChildProcess): Promise { @@ -170,14 +83,16 @@ export class IOSDeviceDebugService extends DebugServiceBase implements IDeviceDe if (debugOptions.chrome) { this.$logger.info("'--chrome' is the default behavior. Use --inspector to debug iOS applications using the Safari Web Inspector."); } - const webSocketProxy = await this.$appDebugSocketProxyFactory.ensureWebSocketProxy(this.device, debugData.applicationIdentifier); + const projectName = this.getProjectName(debugData); + const webSocketProxy = await this.$appDebugSocketProxyFactory.ensureWebSocketProxy(this.device, debugData.applicationIdentifier, projectName); return this.getChromeDebugUrl(debugOptions, webSocketProxy.options.port); } private async setupTcpAppDebugProxy(debugData: IDebugData, debugOptions: IDebugOptions): Promise { + const projectName = this.getProjectName(debugData); const existingTcpProxy = this.$appDebugSocketProxyFactory.getTCPSocketProxy(this.deviceIdentifier, debugData.applicationIdentifier); - const tcpSocketProxy = existingTcpProxy || await this.$appDebugSocketProxyFactory.addTCPSocketProxy(this.device, debugData.applicationIdentifier); + const tcpSocketProxy = existingTcpProxy || await this.$appDebugSocketProxyFactory.addTCPSocketProxy(this.device, debugData.applicationIdentifier, projectName); if (!existingTcpProxy) { const inspectorProcess = await this.openAppInspector(tcpSocketProxy.address(), debugData, debugOptions); if (inspectorProcess) { diff --git a/lib/services/livesync/android-device-livesync-service.ts b/lib/services/livesync/android-device-livesync-service.ts index 7452030e18..3740cf0922 100644 --- a/lib/services/livesync/android-device-livesync-service.ts +++ b/lib/services/livesync/android-device-livesync-service.ts @@ -49,8 +49,8 @@ export class AndroidDeviceLiveSyncService extends AndroidDeviceLiveSyncServiceBa const canExecuteFastSync = reloadedSuccessfully && !liveSyncInfo.isFullSync && !_.some(localToDevicePaths, (localToDevicePath: Mobile.ILocalToDevicePathData) => !this.canExecuteFastSync(liveSyncInfo, localToDevicePath.getLocalPath(), projectData, this.device.deviceInfo.platform)); - if (!canExecuteFastSync) { - await this.restartApplication(deviceAppData, projectData.projectName); + if (!canExecuteFastSync || liveSyncInfo.waitForDebugger) { + await this.restartApplication(deviceAppData, projectData.projectName, liveSyncInfo.waitForDebugger); result.didRestart = true; } @@ -68,12 +68,12 @@ export class AndroidDeviceLiveSyncService extends AndroidDeviceLiveSyncServiceBa this.$mobileHelper.buildDevicePath(deviceRootPath, LiveSyncPaths.REMOVEDSYNC_DIR_NAME)]); } - private async restartApplication(deviceAppData: Mobile.IDeviceAppData, projectName: string): Promise { + private async restartApplication(deviceAppData: Mobile.IDeviceAppData, projectName: string, waitForDebugger: boolean): Promise { const devicePathRoot = `/data/data/${deviceAppData.appIdentifier}/files`; const devicePath = this.$mobileHelper.buildDevicePath(devicePathRoot, "code_cache", "secondary_dexes", "proxyThumb"); await this.device.adb.executeShellCommand(["rm", "-rf", devicePath]); - await this.device.applicationManager.restartApplication({ appId: deviceAppData.appIdentifier, projectName }); + await this.device.applicationManager.restartApplication({ appId: deviceAppData.appIdentifier, projectName, waitForDebugger }); } @performanceLog() diff --git a/lib/services/livesync/android-device-livesync-sockets-service.ts b/lib/services/livesync/android-device-livesync-sockets-service.ts index 4480bf080b..db78c48ea6 100644 --- a/lib/services/livesync/android-device-livesync-sockets-service.ts +++ b/lib/services/livesync/android-device-livesync-sockets-service.ts @@ -33,7 +33,7 @@ export class AndroidDeviceSocketsLiveSyncService extends AndroidDeviceLiveSyncSe const pathToLiveSyncFile = temp.path({ prefix: "livesync" }); this.$fs.writeFile(pathToLiveSyncFile, ""); await this.device.fileSystem.putFile(pathToLiveSyncFile, this.getPathToLiveSyncFileOnDevice(deviceAppData.appIdentifier), deviceAppData.appIdentifier); - await this.device.applicationManager.startApplication({ appId: deviceAppData.appIdentifier, projectName: this.data.projectName, justLaunch: true }); + await this.device.applicationManager.startApplication({ appId: deviceAppData.appIdentifier, projectName: this.data.projectName, justLaunch: true, waitForDebugger: false }); await this.connectLivesyncTool(this.data.projectIdentifiers.android, deviceAppData.connectTimeout); } catch (err) { await this.device.fileSystem.deleteFile(this.getPathToLiveSyncFileOnDevice(deviceAppData.appIdentifier), deviceAppData.appIdentifier); @@ -95,9 +95,9 @@ export class AndroidDeviceSocketsLiveSyncService extends AndroidDeviceLiveSyncSe public async refreshApplication(projectData: IProjectData, liveSyncInfo: IAndroidLiveSyncResultInfo): Promise { const result: IRefreshApplicationInfo = { didRestart: false }; const canExecuteFastSync = !liveSyncInfo.isFullSync && this.canExecuteFastSyncForPaths(liveSyncInfo, liveSyncInfo.modifiedFilesData, projectData, this.device.deviceInfo.platform); - if (!canExecuteFastSync || !liveSyncInfo.didRefresh) { - await this.device.applicationManager.restartApplication({ appId: liveSyncInfo.deviceAppData.appIdentifier, projectName: projectData.projectName }); - if (!this.$options.justlaunch && this.livesyncTool.protocolVersion && semver.gte(this.livesyncTool.protocolVersion, AndroidDeviceSocketsLiveSyncService.MINIMAL_VERSION_LONG_LIVING_CONNECTION)) { + if (!canExecuteFastSync || !liveSyncInfo.didRefresh || liveSyncInfo.waitForDebugger) { + await this.device.applicationManager.restartApplication({ appId: liveSyncInfo.deviceAppData.appIdentifier, projectName: projectData.projectName, waitForDebugger: liveSyncInfo.waitForDebugger }); + if (!this.$options.justlaunch && !liveSyncInfo.waitForDebugger && this.livesyncTool.protocolVersion && semver.gte(this.livesyncTool.protocolVersion, AndroidDeviceSocketsLiveSyncService.MINIMAL_VERSION_LONG_LIVING_CONNECTION)) { try { await this.connectLivesyncTool(liveSyncInfo.deviceAppData.appIdentifier); } catch (e) { diff --git a/lib/services/livesync/android-livesync-service.ts b/lib/services/livesync/android-livesync-service.ts index 5a94d73cce..70f765ae3e 100644 --- a/lib/services/livesync/android-livesync-service.ts +++ b/lib/services/livesync/android-livesync-service.ts @@ -13,7 +13,7 @@ export class AndroidLiveSyncService extends PlatformLiveSyncServiceBase implemen $fs: IFileSystem, $logger: ILogger, $projectFilesProvider: IProjectFilesProvider) { - super($fs, $logger, $platformsData, $projectFilesManager, $devicePathProvider, $projectFilesProvider); + super($fs, $logger, $platformsData, $projectFilesManager, $devicePathProvider, $projectFilesProvider); } protected _getDeviceLiveSyncService(device: Mobile.IDevice, data: IProjectDir, frameworkVersion: string): INativeScriptDeviceLiveSyncService { @@ -54,8 +54,6 @@ export class AndroidLiveSyncService extends PlatformLiveSyncServiceBase implemen return result; } - public async prepareForLiveSync(device: Mobile.IDevice, data: IProjectDir): Promise { /* */ } - private async finalizeSync(device: Mobile.IDevice, projectData: IProjectData, liveSyncResult: ILiveSyncResultInfo): Promise { const liveSyncService = this.getDeviceLiveSyncService(device, projectData); const finalizeResult = await liveSyncService.finalizeSync(liveSyncResult, projectData); diff --git a/lib/services/livesync/ios-device-livesync-service.ts b/lib/services/livesync/ios-device-livesync-service.ts index 45641da0ac..9c2124d927 100644 --- a/lib/services/livesync/ios-device-livesync-service.ts +++ b/lib/services/livesync/ios-device-livesync-service.ts @@ -24,7 +24,7 @@ export class IOSDeviceLiveSyncService extends DeviceLiveSyncServiceBase implemen } const appId = projectData.projectIdentifiers.ios; - this.socket = await this.device.getLiveSyncSocket(appId); + this.socket = await this.device.getDebugSocket(appId, projectData.projectName); if (!this.socket) { return false; } @@ -43,8 +43,8 @@ export class IOSDeviceLiveSyncService extends DeviceLiveSyncServiceBase implemen const result: IRefreshApplicationInfo = { didRestart: false }; const deviceAppData = liveSyncInfo.deviceAppData; const localToDevicePaths = liveSyncInfo.modifiedFilesData; - if (liveSyncInfo.isFullSync) { - await this.restartApplication(deviceAppData, projectData.projectName); + if (liveSyncInfo.isFullSync || liveSyncInfo.waitForDebugger) { + await this.restartApplication(deviceAppData, projectData.projectName, liveSyncInfo.waitForDebugger); result.didRestart = true; return result; } @@ -57,7 +57,7 @@ export class IOSDeviceLiveSyncService extends DeviceLiveSyncServiceBase implemen const canExecuteFastSync = this.canExecuteFastSyncForPaths(liveSyncInfo, localToDevicePaths, projectData, deviceAppData.platform); if (!canExecuteFastSync) { - await this.restartApplication(deviceAppData, projectData.projectName); + await this.restartApplication(deviceAppData, projectData.projectName, liveSyncInfo.waitForDebugger); result.didRestart = true; return result; } @@ -65,15 +65,15 @@ export class IOSDeviceLiveSyncService extends DeviceLiveSyncServiceBase implemen if (await this.setupSocketIfNeeded(projectData)) { await this.reloadPage(otherFiles); } else { - await this.restartApplication(deviceAppData, projectData.projectName); + await this.restartApplication(deviceAppData, projectData.projectName, liveSyncInfo.waitForDebugger); result.didRestart = true; } return result; } - private async restartApplication(deviceAppData: Mobile.IDeviceAppData, projectName: string): Promise { - return this.device.applicationManager.restartApplication({ appId: deviceAppData.appIdentifier, projectName }); + private async restartApplication(deviceAppData: Mobile.IDeviceAppData, projectName: string, waitForDebugger: boolean): Promise { + await this.device.applicationManager.restartApplication({ appId: deviceAppData.appIdentifier, projectName, waitForDebugger }); } private async reloadPage(localToDevicePaths: Mobile.ILocalToDevicePathData[]): Promise { diff --git a/lib/services/livesync/ios-livesync-service.ts b/lib/services/livesync/ios-livesync-service.ts index b783c6208a..16566740b2 100644 --- a/lib/services/livesync/ios-livesync-service.ts +++ b/lib/services/livesync/ios-livesync-service.ts @@ -13,8 +13,7 @@ export class IOSLiveSyncService extends PlatformLiveSyncServiceBase implements I private $injector: IInjector, $devicePathProvider: IDevicePathProvider, $logger: ILogger, - $projectFilesProvider: IProjectFilesProvider, - private $iOSDebuggerPortService: IIOSDebuggerPortService) { + $projectFilesProvider: IProjectFilesProvider) { super($fs, $logger, $platformsData, $projectFilesManager, $devicePathProvider, $projectFilesProvider); } @@ -75,12 +74,6 @@ export class IOSLiveSyncService extends PlatformLiveSyncServiceBase implements I } } - public async prepareForLiveSync(device: Mobile.IDevice, data: IProjectDir, liveSyncInfo: ILiveSyncInfo, debugOptions: IDebugOptions): Promise { - if (!liveSyncInfo.skipWatcher) { - return this.$iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device, data, debugOptions); - } - } - protected _getDeviceLiveSyncService(device: Mobile.IDevice, data: IProjectDir): INativeScriptDeviceLiveSyncService { const service = this.$injector.resolve(IOSDeviceLiveSyncService, { device, data }); return service; diff --git a/lib/services/livesync/livesync-service.ts b/lib/services/livesync/livesync-service.ts index 849c64f7d6..1b030d70a1 100644 --- a/lib/services/livesync/livesync-service.ts +++ b/lib/services/livesync/livesync-service.ts @@ -75,8 +75,7 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi public async stopLiveSync(projectDir: string, deviceIdentifiers?: string[], stopOptions?: { shouldAwaitAllActions: boolean }): Promise { const liveSyncProcessInfo = this.liveSyncProcessesInfo[projectDir]; - - if (liveSyncProcessInfo) { + if (liveSyncProcessInfo && !liveSyncProcessInfo.isStopped) { // In case we are coming from error during livesync, the current action is the one that erred (but we are still executing it), // so we cannot await it as this will cause infinite loop. const shouldAwaitPendingOperation = !stopOptions || stopOptions.shouldAwaitAllActions; @@ -174,6 +173,7 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi const platformLiveSyncService = this.getLiveSyncService(platform); const applicationIdentifier = projectData.projectIdentifiers[platform.toLowerCase()]; try { + // TODO: this.emit(DEBUGGER_DETACHED_EVENT_NAME, { deviceIdentifier }); when we have control on the restart application flow result = await platformLiveSyncService.refreshApplication(projectData, liveSyncResultInfo); } catch (err) { this.$logger.info(`Error while trying to start application ${applicationIdentifier} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}. Error is: ${err.message || err}`); @@ -206,30 +206,18 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi @performanceLog() private async refreshApplicationWithDebug(projectData: IProjectData, liveSyncResultInfo: ILiveSyncResultInfo, debugOptions: IDebugOptions, outputPath?: string): Promise { - let didRestart = false; - const deviceAppData = liveSyncResultInfo.deviceAppData; debugOptions = debugOptions || {}; - const deviceIdentifier = liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier; if (debugOptions.debugBrk) { - await this.$debugService.debugStop(deviceIdentifier); - this.emit(DEBUGGER_DETACHED_EVENT_NAME, { deviceIdentifier }); - const applicationId = deviceAppData.appIdentifier; - try { - await deviceAppData.device.applicationManager.stopApplication({ appId: applicationId, projectName: projectData.projectName }); - } catch (err) { - this.$logger.trace("Could not stop application during debug livesync. Will try to restart app instead.", err); - this.handleDeveloperDiskImageError(err, liveSyncResultInfo, projectData, debugOptions, outputPath); - } - } else { - const refreshInfo = await this.refreshApplicationWithoutDebug(projectData, liveSyncResultInfo, debugOptions, outputPath, { shouldSkipEmitLiveSyncNotification: true, shouldCheckDeveloperDiscImage: true }); - didRestart = refreshInfo.didRestart; + liveSyncResultInfo.waitForDebugger = true; } + const refreshInfo = await this.refreshApplicationWithoutDebug(projectData, liveSyncResultInfo, debugOptions, outputPath, { shouldSkipEmitLiveSyncNotification: true, shouldCheckDeveloperDiscImage: true }); + // we do not stop the application when debugBrk is false, so we need to attach, instead of launch // if we try to send the launch request, the debugger port will not be printed and the command will timeout debugOptions.start = !debugOptions.debugBrk; - debugOptions.forceDebuggerAttachedEvent = didRestart; + debugOptions.forceDebuggerAttachedEvent = refreshInfo.didRestart; const deviceOption = { deviceIdentifier: liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier, debugOptions: debugOptions, @@ -279,10 +267,8 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi projectDir: settings.projectDir }; debugData.pathToAppPackage = this.$platformService.lastOutputPath(settings.platform, buildConfig, projectData, settings.outputPath); - const debugInfo = await this.$debugService.debug(debugData, settings.debugOptions); - const fireDebuggerAttachedEvent = settings.debugOptions.forceDebuggerAttachedEvent || debugInfo.hasReconnected; - const result = this.printDebugInformation(debugInfo, fireDebuggerAttachedEvent); + const result = this.printDebugInformation(debugInfo, settings.debugOptions.forceDebuggerAttachedEvent); return result; } @@ -546,8 +532,6 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi env: liveSyncData.env }, { skipNativePrepare: deviceBuildInfoDescriptor.skipNativePrepare }); - await platformLiveSyncService.prepareForLiveSync(device, projectData, liveSyncData, deviceBuildInfoDescriptor.debugOptions); - const liveSyncResultInfo = await platformLiveSyncService.fullSync({ projectData, device, diff --git a/lib/services/platform-service.ts b/lib/services/platform-service.ts index 06fbe1f24c..4a188cdfed 100644 --- a/lib/services/platform-service.ts +++ b/lib/services/platform-service.ts @@ -594,7 +594,7 @@ export class PlatformService extends EventEmitter implements IPlatformService { await this.$devicesService.execute(action, this.getCanExecuteAction(deployInfo.platform, deployInfo.deployOptions)); } - public async startApplication(platform: string, runOptions: IRunPlatformOptions, appData: Mobile.IApplicationData): Promise { + public async startApplication(platform: string, runOptions: IRunPlatformOptions, appData: Mobile.IStartApplicationData): Promise { this.$logger.out("Starting..."); const action = async (device: Mobile.IDevice) => { diff --git a/lib/services/test-execution-service.ts b/lib/services/test-execution-service.ts index c081d1d1bd..24647fa12e 100644 --- a/lib/services/test-execution-service.ts +++ b/lib/services/test-execution-service.ts @@ -8,15 +8,11 @@ interface IKarmaConfigOptions { } class TestExecutionService implements ITestExecutionService { - private static MAIN_APP_NAME = `./tns_modules/${constants.TEST_RUNNER_NAME}/app.js`; private static CONFIG_FILE_NAME = `node_modules/${constants.TEST_RUNNER_NAME}/config.js`; private static SOCKETIO_JS_FILE_NAME = `node_modules/${constants.TEST_RUNNER_NAME}/socket.io.js`; - constructor(private $injector: IInjector, - private $platformService: IPlatformService, - private $platformsData: IPlatformsData, + constructor(private $platformService: IPlatformService, private $liveSyncService: ILiveSyncService, - private $debugDataService: IDebugDataService, private $httpClient: Server.IHttpClient, private $config: IConfiguration, private $logger: ILogger, @@ -24,142 +20,16 @@ class TestExecutionService implements ITestExecutionService { private $options: IOptions, private $pluginsService: IPluginsService, private $errors: IErrors, - private $debugService: IDebugService, private $devicesService: Mobile.IDevicesService, private $childProcess: IChildProcess) { } public platform: string; - public async startTestRunner(platform: string, projectData: IProjectData, projectFilesConfig: IProjectFilesConfig): Promise { - this.platform = platform; - this.$options.justlaunch = true; - await new Promise((resolve, reject) => { - process.on('message', async (launcherConfig: any) => { - try { - const platformData = this.$platformsData.getPlatformData(platform.toLowerCase(), projectData); - const projectDir = projectData.projectDir; - await this.$devicesService.initialize({ - platform: platform, - deviceId: this.$options.device, - emulator: this.$options.emulator - }); - const projectFilesPath = path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME); - - const configOptions: IKarmaConfigOptions = JSON.parse(launcherConfig); - this.$options.debugBrk = configOptions.debugBrk; - this.$options.debugTransport = configOptions.debugTransport; - const configJs = this.generateConfig(this.$options.port.toString(), configOptions); - this.$fs.writeFile(path.join(projectDir, TestExecutionService.CONFIG_FILE_NAME), configJs); - - const socketIoJsUrl = `http://localhost:${this.$options.port}/socket.io/socket.io.js`; - const socketIoJs = (await this.$httpClient.httpRequest(socketIoJsUrl)).body; - this.$fs.writeFile(path.join(projectDir, TestExecutionService.SOCKETIO_JS_FILE_NAME), socketIoJs); - const appFilesUpdaterOptions: IAppFilesUpdaterOptions = { - bundle: !!this.$options.bundle, - release: this.$options.release, - useHotModuleReload: this.$options.hmr - }; - const preparePlatformInfo: IPreparePlatformInfo = { - platform, - appFilesUpdaterOptions, - platformTemplate: this.$options.platformTemplate, - projectData, - config: this.$options, - env: this.$options.env - }; - - if (!await this.$platformService.preparePlatform(preparePlatformInfo)) { - this.$errors.failWithoutHelp("Verify that listed files are well-formed and try again the operation."); - } - - this.detourEntryPoint(projectFilesPath); - - const deployOptions: IDeployPlatformOptions = { - clean: this.$options.clean, - device: this.$options.device, - emulator: this.$options.emulator, - projectDir: this.$options.path, - platformTemplate: this.$options.platformTemplate, - release: this.$options.release, - provision: this.$options.provision, - teamId: this.$options.teamId - }; - - if (this.$options.bundle) { - this.$options.watch = false; - } - - const devices = this.$devicesService.getDeviceInstances(); - // Now let's take data for each device: - const platformLowerCase = this.platform && this.platform.toLowerCase(); - const deviceDescriptors: ILiveSyncDeviceInfo[] = devices.filter(d => !platformLowerCase || d.deviceInfo.platform.toLowerCase() === platformLowerCase) - .map(d => { - const info: ILiveSyncDeviceInfo = { - identifier: d.deviceInfo.identifier, - buildAction: async (): Promise => { - const buildConfig: IBuildConfig = { - buildForDevice: !d.isEmulator, // this.$options.forDevice, - projectDir: this.$options.path, - clean: this.$options.clean, - teamId: this.$options.teamId, - device: this.$options.device, - provision: this.$options.provision, - release: this.$options.release, - keyStoreAlias: this.$options.keyStoreAlias, - keyStorePath: this.$options.keyStorePath, - keyStoreAliasPassword: this.$options.keyStoreAliasPassword, - keyStorePassword: this.$options.keyStorePassword - }; - - await this.$platformService.buildPlatform(d.deviceInfo.platform, buildConfig, projectData); - const pathToBuildResult = await this.$platformService.lastOutputPath(d.deviceInfo.platform, buildConfig, projectData); - return pathToBuildResult; - }, - debugOptions: this.$options - }; - - return info; - }); - - const liveSyncInfo: ILiveSyncInfo = { - projectDir: projectData.projectDir, - skipWatcher: !this.$options.watch || this.$options.justlaunch, - watchAllFiles: this.$options.syncAllFiles, - bundle: !!this.$options.bundle, - release: this.$options.release, - env: this.$options.env, - timeout: this.$options.timeout, - useHotModuleReload: this.$options.hmr - }; - - await this.$liveSyncService.liveSync(deviceDescriptors, liveSyncInfo); - - if (this.$options.debugBrk) { - this.$logger.info('Starting debugger...'); - const debugService: IDeviceDebugService = this.$injector.resolve(`${platform}DebugService`); - const debugData = this.getDebugData(platform, projectData, deployOptions); - await debugService.debugStart(debugData, this.$options); - } - resolve(); - } catch (err) { - reject(err); - } - }); - - // Tell the parent that we are ready to receive the data. - process.send("ready"); - }); - } - public async startKarmaServer(platform: string, projectData: IProjectData, projectFilesConfig: IProjectFilesConfig): Promise { platform = platform.toLowerCase(); this.platform = platform; - if (this.$options.debugBrk && this.$options.watch) { - this.$errors.failWithoutHelp("You cannot use --watch and --debug-brk simultaneously. Remove one of the flags and try again."); - } - // We need the dependencies installed here, so we can start the Karma server. await this.$pluginsService.ensureAllDependenciesAreInstalled(projectData); @@ -209,66 +79,64 @@ class TestExecutionService implements ITestExecutionService { this.$errors.failWithoutHelp("Verify that listed files are well-formed and try again the operation."); } - const deployOptions: IDeployPlatformOptions = { - clean: this.$options.clean, - device: this.$options.device, - emulator: this.$options.emulator, - projectDir: this.$options.path, - platformTemplate: this.$options.platformTemplate, - release: this.$options.release, - provision: this.$options.provision, - teamId: this.$options.teamId - }; - + let devices = []; if (this.$options.debugBrk) { - const debugData = this.getDebugData(platform, projectData, deployOptions); - await this.$debugService.debug(debugData, this.$options); + const selectedDeviceForDebug = await this.$devicesService.pickSingleDevice({ + onlyEmulators: this.$options.emulator, + onlyDevices: this.$options.forDevice, + deviceId: this.$options.device + }); + devices = [selectedDeviceForDebug]; + // const debugData = this.getDebugData(platform, projectData, deployOptions, { device: selectedDeviceForDebug.deviceInfo.identifier }); + // await this.$debugService.debug(debugData, this.$options); } else { - const devices = this.$devicesService.getDeviceInstances(); - // Now let's take data for each device: - const platformLowerCase = this.platform && this.platform.toLowerCase(); - const deviceDescriptors: ILiveSyncDeviceInfo[] = devices.filter(d => !platformLowerCase || d.deviceInfo.platform.toLowerCase() === platformLowerCase) - .map(d => { - const info: ILiveSyncDeviceInfo = { - identifier: d.deviceInfo.identifier, - buildAction: async (): Promise => { - const buildConfig: IBuildConfig = { - buildForDevice: !d.isEmulator, - projectDir: this.$options.path, - clean: this.$options.clean, - teamId: this.$options.teamId, - device: this.$options.device, - provision: this.$options.provision, - release: this.$options.release, - keyStoreAlias: this.$options.keyStoreAlias, - keyStorePath: this.$options.keyStorePath, - keyStoreAliasPassword: this.$options.keyStoreAliasPassword, - keyStorePassword: this.$options.keyStorePassword - }; - - await this.$platformService.buildPlatform(d.deviceInfo.platform, buildConfig, projectData); - const pathToBuildResult = await this.$platformService.lastOutputPath(d.deviceInfo.platform, buildConfig, projectData); - return pathToBuildResult; - }, - debugOptions: this.$options - }; + devices = this.$devicesService.getDeviceInstances(); + } - return info; - }); + // Now let's take data for each device: + const platformLowerCase = this.platform && this.platform.toLowerCase(); + const deviceDescriptors: ILiveSyncDeviceInfo[] = devices.filter(d => !platformLowerCase || d.deviceInfo.platform.toLowerCase() === platformLowerCase) + .map(d => { + const info: ILiveSyncDeviceInfo = { + identifier: d.deviceInfo.identifier, + buildAction: async (): Promise => { + const buildConfig: IBuildConfig = { + buildForDevice: !d.isEmulator, + projectDir: this.$options.path, + clean: this.$options.clean, + teamId: this.$options.teamId, + device: this.$options.device, + provision: this.$options.provision, + release: this.$options.release, + keyStoreAlias: this.$options.keyStoreAlias, + keyStorePath: this.$options.keyStorePath, + keyStoreAliasPassword: this.$options.keyStoreAliasPassword, + keyStorePassword: this.$options.keyStorePassword + }; + + await this.$platformService.buildPlatform(d.deviceInfo.platform, buildConfig, projectData); + const pathToBuildResult = await this.$platformService.lastOutputPath(d.deviceInfo.platform, buildConfig, projectData); + return pathToBuildResult; + }, + debugOptions: this.$options, + debugggingEnabled: this.$options.debugBrk + }; + + return info; + }); - const liveSyncInfo: ILiveSyncInfo = { - projectDir: projectData.projectDir, - skipWatcher: !this.$options.watch || this.$options.justlaunch, - watchAllFiles: this.$options.syncAllFiles, - bundle: !!this.$options.bundle, - release: this.$options.release, - env: this.$options.env, - timeout: this.$options.timeout, - useHotModuleReload: this.$options.hmr - }; + const liveSyncInfo: ILiveSyncInfo = { + projectDir: projectData.projectDir, + skipWatcher: !this.$options.watch || this.$options.justlaunch, + watchAllFiles: this.$options.syncAllFiles, + bundle: !!this.$options.bundle, + release: this.$options.release, + env: this.$options.env, + timeout: this.$options.timeout, + useHotModuleReload: this.$options.hmr + }; - await this.$liveSyncService.liveSync(deviceDescriptors, liveSyncInfo); - } + await this.$liveSyncService.liveSync(deviceDescriptors, liveSyncInfo); }; karmaRunner.on("message", (karmaData: any) => { @@ -297,13 +165,6 @@ class TestExecutionService implements ITestExecutionService { allowedParameters: ICommandParameter[] = []; - private detourEntryPoint(projectFilesPath: string): void { - const packageJsonPath = path.join(projectFilesPath, 'package.json'); - const packageJson = this.$fs.readJson(packageJsonPath); - packageJson.main = TestExecutionService.MAIN_APP_NAME; - this.$fs.writeJson(packageJsonPath, packageJson); - } - private generateConfig(port: string, options: any): string { const nics = os.networkInterfaces(); const ips = Object.keys(nics) @@ -355,13 +216,5 @@ class TestExecutionService implements ITestExecutionService { return karmaConfig; } - - private getDebugData(platform: string, projectData: IProjectData, deployOptions: IDeployPlatformOptions): IDebugData { - const buildConfig: IBuildConfig = _.merge({ buildForDevice: this.$options.forDevice }, deployOptions); - const debugData = this.$debugDataService.createDebugData(projectData, this.$options); - debugData.pathToAppPackage = this.$platformService.lastOutputPath(platform, buildConfig, projectData); - - return debugData; - } } $injector.register('testExecutionService', TestExecutionService); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index eb4afe527f..d282aa7e69 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -9,22 +9,33 @@ "resolved": "https://registry.npmjs.org/@nativescript/schematics-executor/-/schematics-executor-0.0.2.tgz", "integrity": "sha512-3pA0cXbkwu55+He71QO1oRE18wQyquk5t6vpM4laAFatI5w8n2dyHYSzM7pM6bN57zpcP2sk5u1q3YtYv0d2MQ==" }, + "@sinonjs/commons": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.3.0.tgz", + "integrity": "sha512-j4ZwhaHmwsCb4DlDOIWnI5YyKDNMoNThsmwEpfHx6a1EpsGZ9qYLxP++LMlmBRjtGptGHFsGItJ768snllFWpA==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, "@sinonjs/formatio": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.0.0.tgz", - "integrity": "sha512-vdjoYLDptCgvtJs57ULshak3iJe4NW3sJ3g36xVDGff5AE8P30S6A093EIEPjdi2noGhfuNOEkbxt3J3awFW1w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.1.0.tgz", + "integrity": "sha512-ZAR2bPHOl4Xg6eklUGpsdiIJ4+J1SNag1DHHrG/73Uz/nVwXqjgUtRPLoS+aVyieN9cSbc0E4LsU984tWcDyNg==", "dev": true, "requires": { - "@sinonjs/samsam": "2.1.0" + "@sinonjs/samsam": "^2 || ^3" } }, "@sinonjs/samsam": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-2.1.0.tgz", - "integrity": "sha512-5x2kFgJYupaF1ns/RmharQ90lQkd2ELS8A9X0ymkAAdemYHGtI2KiUHG8nX2WU0T1qgnOU5YMqnBM2V7NUanNw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.0.2.tgz", + "integrity": "sha512-m08g4CS3J6lwRQk1pj1EO+KEVWbrbXsmi9Pw0ySmrIbcVxVaedoFgLvFsV8wHLwh01EpROVz3KvVcD1Jmks9FQ==", "dev": true, "requires": { - "array-from": "^2.1.1" + "@sinonjs/commons": "^1.0.2", + "array-from": "^2.1.1", + "lodash.get": "^4.4.2" } }, "@types/axios": { @@ -85,7 +96,7 @@ }, "@types/events": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", "dev": true }, @@ -128,7 +139,7 @@ }, "@types/ora": { "version": "1.3.3", - "resolved": "http://registry.npmjs.org/@types/ora/-/ora-1.3.3.tgz", + "resolved": "https://registry.npmjs.org/@types/ora/-/ora-1.3.3.tgz", "integrity": "sha512-XaSVRyCfnGq1xGlb6iuoxnomMXPIlZnvIIkKiGNMTCeVOg7G1Si+FA9N1lPrykPEfiRHwbuZXuTCSoYcHyjcdg==", "dev": true, "requires": { @@ -161,7 +172,7 @@ }, "@types/rx": { "version": "4.1.1", - "resolved": "http://registry.npmjs.org/@types/rx/-/rx-4.1.1.tgz", + "resolved": "https://registry.npmjs.org/@types/rx/-/rx-4.1.1.tgz", "integrity": "sha1-WY/JSla67ZdfGUV04PVy/Y5iekg=", "dev": true, "requires": { @@ -334,7 +345,7 @@ }, "@types/ws": { "version": "4.0.1", - "resolved": "http://registry.npmjs.org/@types/ws/-/ws-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-4.0.1.tgz", "integrity": "sha512-J56Wn8j7ovzmlrkUSPXnVRH+YXUCGoVokiB49QIjz+yq0234guOrBvF/HHrqrJjnY4p5oq+q6xAxT/7An6SeWQ==", "dev": true, "requires": { @@ -355,8 +366,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "acorn": { "version": "5.7.3", @@ -366,7 +376,7 @@ }, "acorn-jsx": { "version": "3.0.1", - "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { @@ -375,7 +385,7 @@ "dependencies": { "acorn": { "version": "3.3.0", - "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true } @@ -423,7 +433,7 @@ }, "ansi-escapes": { "version": "3.1.0", - "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" }, "ansi-regex": { @@ -455,6 +465,16 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -527,7 +547,7 @@ }, "async": { "version": "1.2.1", - "resolved": "http://registry.npmjs.org/async/-/async-1.2.1.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-1.2.1.tgz", "integrity": "sha1-pIFqF81f9RbfosdpikUzabl5DeA=" }, "async-each": { @@ -562,7 +582,7 @@ }, "axios": { "version": "0.18.0", - "resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", "requires": { "follow-redirects": "^1.3.0", @@ -581,7 +601,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -662,13 +682,13 @@ } }, "big-integer": { - "version": "1.6.36", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.36.tgz", - "integrity": "sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==" + "version": "1.6.40", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.40.tgz", + "integrity": "sha512-CjhtJp0BViLzP1ZkEnoywjgtFQXS2pomKjAJtIISTCnuHILkLcAXLdFLG/nxsHc4s9kJfc+82Xpg8WNyhfACzQ==" }, "bignumber.js": { "version": "2.4.0", - "resolved": "http://registry.npmjs.org/bignumber.js/-/bignumber.js-2.4.0.tgz", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.4.0.tgz", "integrity": "sha1-g4qZLan51zfg9LLbC+YrsJ3Qxeg=" }, "binary-extensions": { @@ -693,7 +713,7 @@ }, "body-parser": { "version": "1.14.2", - "resolved": "http://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", "dev": true, "requires": { @@ -717,7 +737,7 @@ }, "debug": { "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { @@ -726,7 +746,7 @@ }, "http-errors": { "version": "1.3.1", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", "dev": true, "requires": { @@ -736,13 +756,13 @@ }, "iconv-lite": { "version": "0.4.13", - "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", "dev": true }, "ms": { "version": "0.7.1", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, @@ -884,32 +904,32 @@ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "cacache": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.1.tgz", - "integrity": "sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", "y18n": "^4.0.0" }, "dependencies": { - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "requires": { - "glob": "^7.0.5" + "yallist": "^3.0.2" } }, "y18n": { @@ -946,7 +966,7 @@ }, "callsites": { "version": "0.2.0", - "resolved": "http://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "dev": true }, @@ -957,7 +977,7 @@ }, "camelcase-keys": { "version": "2.1.0", - "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { @@ -1013,7 +1033,7 @@ }, "chalk": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.0.tgz", "integrity": "sha1-CbRTzsSXp1Ug5KYK5IIUqHAOCSE=", "requires": { "ansi-styles": "^2.1.0", @@ -1110,12 +1130,12 @@ "dependencies": { "colors": { "version": "1.0.3", - "resolved": "http://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" }, "lodash": { "version": "3.6.0", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz", "integrity": "sha1-Umao9J3Zib5Pn2gbbyoMVShdDZo=" } } @@ -1133,26 +1153,6 @@ "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } } }, "clone": { @@ -1218,7 +1218,7 @@ }, "colors": { "version": "1.1.2", - "resolved": "http://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" }, "combined-stream": { @@ -1255,6 +1255,11 @@ "typedarray": "^0.0.6" } }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", @@ -1277,16 +1282,6 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.0" - }, - "dependencies": { - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "requires": { - "glob": "^7.0.5" - } - } } }, "copy-descriptor": { @@ -1353,7 +1348,7 @@ }, "d": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { @@ -1369,13 +1364,23 @@ } }, "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.0.tgz", + "integrity": "sha512-YbKCNLPPP4inc0E5If4OaalBc7gpaM2MRv77Pv2VThVComLKfbGYtJcdDCViDyp1Wd4SebhHLz94vp91zbK6bw==", + "requires": { + "@types/node": "^8.0.7" + }, + "dependencies": { + "@types/node": { + "version": "8.10.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.39.tgz", + "integrity": "sha512-rE7fktr02J8ybFf6eysife+WF+L4sAHWzw09DgdCebEu+qDwMvv4zl6Bc+825ttGZP73kCKxa3dhJOoGJ8+5mA==" + } + } }, "date-format": { "version": "0.0.0", - "resolved": "http://registry.npmjs.org/date-format/-/date-format-0.0.0.tgz", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-0.0.0.tgz", "integrity": "sha1-CSBoY6sHDrRZrOpVQsvYVrEZZrM=" }, "dateformat": { @@ -1423,6 +1428,12 @@ } } }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "optional": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -1495,6 +1506,12 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "optional": true + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -1509,6 +1526,12 @@ "repeating": "^2.0.0" } }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "optional": true + }, "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", @@ -1616,9 +1639,9 @@ } }, "es5-ext": { - "version": "0.10.46", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", + "version": "0.10.47", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.47.tgz", + "integrity": "sha512-/1TItLfj+TTfWoeRcDn/0FbGV6SNo4R+On2GGVucPU/j3BWnXE2Co8h8CTo4Tu34gFJtnmwS9xiScKs4EjZhdw==", "dev": true, "requires": { "es6-iterator": "~2.0.3", @@ -1653,12 +1676,12 @@ }, "es6-promise": { "version": "3.3.1", - "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" }, "es6-promisify": { "version": "5.0.0", - "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "requires": { "es6-promise": "^4.0.3" @@ -1793,13 +1816,13 @@ "dependencies": { "ansi-escapes": { "version": "1.4.0", - "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", "dev": true }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -1831,7 +1854,7 @@ }, "inquirer": { "version": "0.12.0", - "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", "dev": true, "requires": { @@ -1850,18 +1873,9 @@ "through": "^2.3.6" } }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, "onetime": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", "dev": true }, @@ -1884,17 +1898,6 @@ "once": "^1.3.0" } }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -1905,7 +1908,7 @@ }, "espree": { "version": "3.5.4", - "resolved": "http://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { @@ -1958,7 +1961,7 @@ }, "eventemitter2": { "version": "0.4.14", - "resolved": "http://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", "dev": true }, @@ -2172,7 +2175,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, "fast-json-stable-stringify": { @@ -2233,7 +2236,7 @@ }, "file-type": { "version": "3.9.0", - "resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" }, "file-uri-to-path": { @@ -2311,17 +2314,6 @@ "graceful-fs": "^4.1.2", "rimraf": "~2.6.2", "write": "^0.2.1" - }, - "dependencies": { - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "^7.0.5" - } - } } }, "flush-write-stream": { @@ -2334,9 +2326,9 @@ } }, "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", + "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", "requires": { "debug": "=3.1.0" }, @@ -2444,465 +2436,13 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "optional": true, - "requires": { - "safer-buffer": "^2.1.0" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.0", - "bundled": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "optional": true, - "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "optional": true, - "requires": { - "glob": "^7.0.5" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "optional": true, - "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "optional": true, - "requires": { - "string-width": "^1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true - } + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.6.tgz", + "integrity": "sha512-BalK54tfK0pMC0jQFb2oHn1nz7JNQD/2ex5pBnCHgBi2xG7VV0cAOGy2RS2VbCqUXx5/6obMrMcQTJ8yjcGzbg==", + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" } }, "ftp": { @@ -2921,7 +2461,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "requires": { "core-util-is": "~1.0.0", @@ -2937,6 +2477,22 @@ } } }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, "gaze": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.0.tgz", @@ -2987,20 +2543,45 @@ }, "get-stream": { "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "get-uri": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", - "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.3.tgz", + "integrity": "sha512-x5j6Ks7FOgLD/GlvjKwgu7wdmMR55iuRHhn8hj/+gA+eSbxQvZ+AEomq+3MgVEZj1vpi738QahGbCCSIDtXtkw==", "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "3", + "data-uri-to-buffer": "2", + "debug": "4", + "extend": "~3.0.2", "file-uri-to-path": "1", "ftp": "~0.3.10", - "readable-stream": "2" + "readable-stream": "3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "readable-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", + "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "get-value": { @@ -3182,7 +2763,7 @@ }, "grunt-cli": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", "dev": true, "requires": { @@ -3211,17 +2792,32 @@ "esprima": "^2.6.0" } }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true } } }, "grunt-contrib-clean": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-1.0.0.tgz", "integrity": "sha1-ay7ZQRfix//jLuBFeMlv5GJam20=", "dev": true, "requires": { @@ -3231,18 +2827,9 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "^7.0.5" - } } } }, @@ -3258,7 +2845,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -3285,13 +2872,13 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, "lodash": { "version": "3.10.1", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", "dev": true } @@ -3327,7 +2914,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -3340,7 +2927,7 @@ }, "lodash": { "version": "4.3.0", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=", "dev": true } @@ -3363,13 +2950,13 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, "lodash": { "version": "4.3.0", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=", "dev": true }, @@ -3475,7 +3062,7 @@ }, "es6-promise": { "version": "0.1.2", - "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-0.1.2.tgz", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-0.1.2.tgz", "integrity": "sha1-8RLCn+paCZhTn8tqL9IUQ9KPBfc=", "dev": true }, @@ -3553,7 +3140,7 @@ }, "rimraf": { "version": "2.2.6", - "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz", "integrity": "sha1-xZWXVpsU2VatKcrMQr3d9fDqT0w=", "dev": true } @@ -3615,6 +3202,12 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "optional": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -3657,7 +3250,7 @@ }, "hoek": { "version": "4.2.1", - "resolved": "http://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" }, "hooker": { @@ -3678,7 +3271,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "requires": { "depd": "~1.1.2", @@ -3756,7 +3349,7 @@ }, "iconv-lite": { "version": "0.4.11", - "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=" }, "iferr": { @@ -3816,6 +3409,12 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "optional": true + }, "inquirer": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", @@ -3850,20 +3449,34 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -3883,9 +3496,9 @@ } }, "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==" }, "invert-kv": { "version": "1.0.0", @@ -3893,9 +3506,9 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ios-device-lib": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/ios-device-lib/-/ios-device-lib-0.5.0.tgz", - "integrity": "sha512-EKSXHYvOhjB+R/8EaWX9Iha7AIk1U26rxvxq7Hpg/19zOXqsnjuakyJ3fDKh5BXnU7CzBpkz1V2lwi8JPvD5fw==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/ios-device-lib/-/ios-device-lib-0.5.1.tgz", + "integrity": "sha512-HW96QpgGCCtg5E8rz+758FrieUbwqHFC7c2g6Al2kTIF2iaKBeVXZhONE8PoQPtpm+PrFBBkA9i4ZlyntS2FoA==", "requires": { "bufferpack": "0.0.6", "node-uuid": "1.4.7" @@ -3920,7 +3533,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -3930,14 +3543,6 @@ "supports-color": "^2.0.0" } }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, "plist": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/plist/-/plist-2.1.0.tgz", @@ -3948,19 +3553,9 @@ "xmldom": "0.1.x" } }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, "yargs": { "version": "6.6.0", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", "requires": { "camelcase": "^3.0.0", @@ -3999,14 +3594,6 @@ "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, "lodash": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", @@ -4027,16 +3614,6 @@ "rechoir": "^0.6.2" } }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, "yargs": { "version": "4.7.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.7.1.tgz", @@ -4116,7 +3693,7 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "requires": { "builtin-modules": "^1.0.0" @@ -4197,9 +3774,12 @@ } }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-function": { "version": "1.0.1", @@ -4397,6 +3977,15 @@ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", @@ -4405,7 +3994,7 @@ }, "source-map": { "version": "0.2.0", - "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", "dev": true, "optional": true, @@ -4468,9 +4057,9 @@ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" }, "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -4555,9 +4144,9 @@ } }, "just-extend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-3.0.0.tgz", - "integrity": "sha512-Fu3T6pKBuxjWT/p4DkqGHFRsysc8OauWr4ZRTY9dIx07Y9O0RkoR5jcv28aeD1vuAwhm3nLkDurwLXoALp4DpQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", "dev": true }, "kind-of": { @@ -4610,7 +4199,7 @@ }, "load-json-file": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "requires": { "graceful-fs": "^4.1.2", @@ -4741,9 +4330,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -4762,7 +4351,7 @@ }, "log4js": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/log4js/-/log4js-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-1.0.1.tgz", "integrity": "sha1-+vZMEFa2NSpfu/CpO2Gpl5qEIsw=", "requires": { "debug": "^2.2.0", @@ -4787,12 +4376,19 @@ } }, "lru-cache": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.4.tgz", - "integrity": "sha512-EPstzZ23znHUVLKj+lcXO1KvZkrlw+ZirdwvOmnAnA/1PB4ggyXJ77LRkCqkff+ShQ+cqoxCxLQOh4cKITO5iA==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "requires": { "pseudomap": "^1.0.2", - "yallist": "^3.0.2" + "yallist": "^2.1.2" + }, + "dependencies": { + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } } }, "make-fetch-happen": { @@ -4883,28 +4479,15 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, - "cli-table": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", - "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", - "requires": { - "colors": "1.0.3" - } - }, - "colors": { - "version": "1.0.3", - "resolved": "http://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -4916,20 +4499,20 @@ } }, "math-random": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", - "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", "dev": true }, "media-typer": { "version": "0.3.0", - "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, "meow": { "version": "3.7.0", - "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { @@ -4947,7 +4530,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -5019,7 +4602,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "minipass": { @@ -5032,9 +4615,9 @@ } }, "minizlib": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.1.tgz", - "integrity": "sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", + "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "requires": { "minipass": "^2.2.1" } @@ -5077,7 +4660,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -5085,7 +4668,7 @@ }, "mocha": { "version": "3.1.2", - "resolved": "http://registry.npmjs.org/mocha/-/mocha-3.1.2.tgz", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.1.2.tgz", "integrity": "sha1-Ufk7Qyv34bF1/8Iog8zQvjLbprU=", "dev": true, "requires": { @@ -5104,7 +4687,7 @@ "dependencies": { "commander": { "version": "2.9.0", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true, "requires": { @@ -5113,7 +4696,7 @@ }, "debug": { "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { @@ -5148,7 +4731,7 @@ }, "ms": { "version": "0.7.1", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, @@ -5174,16 +4757,6 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "requires": { - "glob": "^7.0.5" - } - } } }, "ms": { @@ -5197,9 +4770,9 @@ "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=" }, "nan": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", - "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", + "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", "optional": true }, "nanoid": { @@ -5272,10 +4845,21 @@ }, "ncp": { "version": "0.5.1", - "resolved": "http://registry.npmjs.org/ncp/-/ncp-0.5.1.tgz", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.5.1.tgz", "integrity": "sha1-dDmFMW49tFkoG1hxaehFc1oFQ58=", "dev": true }, + "needle": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz", + "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, "netmask": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", @@ -5283,18 +4867,18 @@ }, "next-tick": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, "nise": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.6.tgz", - "integrity": "sha512-1GedetLKzmqmgwabuMSqPsT7oumdR77SBpDfNNJhADRIeA3LN/2RVqR4fFqwvzhAqcTef6PPCzQwITE/YQ8S8A==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.8.tgz", + "integrity": "sha512-kGASVhuL4tlAV0tvA34yJYZIVihrUt/5bDwpp4tTluigxUr2bBlJeDXmivb6NuEdFkqvdv/Ybb9dm16PSKUhtw==", "dev": true, "requires": { - "@sinonjs/formatio": "3.0.0", - "just-extend": "^3.0.0", + "@sinonjs/formatio": "^3.1.0", + "just-extend": "^4.0.2", "lolex": "^2.3.2", "path-to-regexp": "^1.7.0", "text-encoding": "^0.6.4" @@ -5318,18 +4902,49 @@ "safe-buffer": "^5.1.1" } }, + "node-pre-gyp": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz", + "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==", + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, "node-uuid": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.3.3.tgz", "integrity": "sha1-09tNe1aBDZ5AMjQnZigq8HORcps=" }, "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "optional": true, "requires": { - "abbrev": "1" + "abbrev": "1", + "osenv": "^0.1.4" + }, + "dependencies": { + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + } } }, "normalize-package-data": { @@ -5379,9 +4994,9 @@ } }, "npm-packlist": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.12.tgz", - "integrity": "sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.2.0.tgz", + "integrity": "sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ==", "requires": { "ignore-walk": "^3.0.1", "npm-bundled": "^1.0.1" @@ -5406,6 +5021,18 @@ "path-key": "^1.0.0" } }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -5538,7 +5165,7 @@ }, "ora": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/ora/-/ora-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/ora/-/ora-2.0.0.tgz", "integrity": "sha512-g+IR0nMUXq1k4nE3gkENbN4wkF0XsVZFyxznTF6CdmwQ9qeTGONGpSR9LM5//1l0TVvJoJF3MkMtJp6slUsWFg==", "requires": { "chalk": "^2.3.1", @@ -5563,9 +5190,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -5592,12 +5219,12 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-locale": { "version": "1.4.0", - "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "requires": { "lcid": "^1.0.0" @@ -5605,7 +5232,7 @@ }, "os-tmpdir": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "osenv": { @@ -5707,14 +5334,6 @@ "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "requires": { - "glob": "^7.0.5" - } } } }, @@ -5824,7 +5443,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { @@ -5884,7 +5503,7 @@ }, "pegjs": { "version": "0.6.2", - "resolved": "http://registry.npmjs.org/pegjs/-/pegjs-0.6.2.tgz", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.6.2.tgz", "integrity": "sha1-dGUfioAORE22iOTuro7bZWN6F6U=" }, "pend": { @@ -5904,7 +5523,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "pinkie": { @@ -5962,7 +5581,7 @@ }, "xmlbuilder": { "version": "2.2.1", - "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.2.1.tgz", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.2.1.tgz", "integrity": "sha1-kyZDDxMNh0NdTECGZDqikm4QWjI=", "requires": { "lodash-node": "~2.4.1" @@ -5981,7 +5600,7 @@ "dependencies": { "lodash": { "version": "4.17.4", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" }, "plist": { @@ -6035,7 +5654,7 @@ }, "progress": { "version": "1.1.8", - "resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", "dev": true }, @@ -6063,7 +5682,7 @@ }, "proxy-agent": { "version": "2.3.1", - "resolved": "http://registry.npmjs.org/proxy-agent/-/proxy-agent-2.3.1.tgz", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.3.1.tgz", "integrity": "sha512-CNKuhC1jVtm8KJYFTS2ZRO71VCBx3QSA92So/e6NrY6GoJonkx3Irnk4047EsCcswczwqAekRj3s8qLRGahSKg==", "requires": { "agent-base": "^4.2.0", @@ -6221,6 +5840,26 @@ } } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "optional": true + } + } + }, "read-chunk": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-1.0.1.tgz", @@ -6247,7 +5886,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -6278,17 +5917,6 @@ "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "mute-stream": "0.0.5" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - } } }, "rechoir": { @@ -6368,7 +5996,7 @@ }, "request": { "version": "2.85.0", - "resolved": "http://registry.npmjs.org/request/-/request-2.85.0.tgz", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", "requires": { "aws-sign2": "~0.7.0", @@ -6414,7 +6042,7 @@ }, "require-uncached": { "version": "1.0.3", - "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { @@ -6423,11 +6051,11 @@ } }, "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", + "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", "requires": { - "path-parse": "^1.0.5" + "path-parse": "^1.0.6" } }, "resolve-from": { @@ -6461,9 +6089,12 @@ "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" }, "rimraf": { - "version": "2.2.8", - "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "requires": { + "glob": "^7.1.3" + } }, "run-async": { "version": "2.3.0", @@ -6502,7 +6133,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "requires": { "ret": "~0.1.10" @@ -6562,7 +6193,7 @@ }, "shelljs": { "version": "0.7.6", - "resolved": "http://registry.npmjs.org/shelljs/-/shelljs-0.7.6.tgz", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.6.tgz", "integrity": "sha1-N5zM+1a5HIYB5HkzVutTgpJN6a0=", "requires": { "glob": "^7.0.0", @@ -6591,7 +6222,7 @@ }, "should-equal": { "version": "0.5.0", - "resolved": "http://registry.npmjs.org/should-equal/-/should-equal-0.5.0.tgz", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-0.5.0.tgz", "integrity": "sha1-x5fxNfMGf+tp6+zbMGscP+IbPm8=", "dev": true, "requires": { @@ -6695,7 +6326,7 @@ }, "slice-ansi": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", "dev": true }, @@ -6829,7 +6460,7 @@ }, "source-map": { "version": "0.5.6", - "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=" }, "source-map-resolve": { @@ -6867,9 +6498,9 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, "spdx-correct": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", - "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -6890,9 +6521,9 @@ } }, "spdx-license-ids": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", - "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==" }, "split-string": { "version": "3.1.0", @@ -6909,9 +6540,9 @@ "dev": true }, "sshpk": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", - "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz", + "integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==", "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -7000,7 +6631,7 @@ "dependencies": { "debug": { "version": "0.7.4", - "resolved": "http://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=" }, "isarray": { @@ -7010,7 +6641,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "requires": { "core-util-is": "~1.0.0", @@ -7027,27 +6658,13 @@ } }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -7070,7 +6687,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" @@ -7096,8 +6713,7 @@ "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "superagent": { "version": "3.8.3", @@ -7133,7 +6749,7 @@ }, "superagent-proxy": { "version": "1.0.3", - "resolved": "http://registry.npmjs.org/superagent-proxy/-/superagent-proxy-1.0.3.tgz", + "resolved": "https://registry.npmjs.org/superagent-proxy/-/superagent-proxy-1.0.3.tgz", "integrity": "sha512-79Ujg1lRL2ICfuHUdX+H2MjIw73kB7bXsIkxLwHURz3j0XUmEEEoJ+u/wq+mKwna21Uejsm2cGR3OESA00TIjA==", "requires": { "debug": "^3.1.0", @@ -7167,7 +6783,7 @@ }, "table": { "version": "3.8.3", - "resolved": "http://registry.npmjs.org/table/-/table-3.8.3.tgz", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", "dev": true, "requires": { @@ -7189,9 +6805,15 @@ "json-stable-stringify": "^1.0.1" } }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -7201,6 +6823,33 @@ "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } } } }, @@ -7229,11 +6878,18 @@ "requires": { "os-tmpdir": "^1.0.0", "rimraf": "~2.2.6" + }, + "dependencies": { + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + } } }, "text-encoding": { "version": "0.6.4", - "resolved": "http://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", "dev": true }, @@ -7250,7 +6906,7 @@ }, "through": { "version": "2.3.8", - "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { @@ -7283,7 +6939,7 @@ "dependencies": { "debug": { "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { @@ -7292,7 +6948,7 @@ }, "ms": { "version": "0.7.1", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, @@ -7516,7 +7172,7 @@ }, "underscore.string": { "version": "3.2.3", - "resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz", "integrity": "sha1-gGmSYzZl1eX8tNsfs6hi62jp5to=", "dev": true }, @@ -7659,7 +7315,7 @@ }, "uuid": { "version": "3.0.1", - "resolved": "http://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=" }, "validate-npm-package-license": { @@ -7726,6 +7382,15 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, "window-size": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", @@ -7743,31 +7408,11 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } } }, "wrappy": { @@ -7786,7 +7431,7 @@ }, "ws": { "version": "5.1.0", - "resolved": "http://registry.npmjs.org/ws/-/ws-5.1.0.tgz", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.1.0.tgz", "integrity": "sha512-7KU/qkUXtJW9aa5WRKlo0puE1ejEoAgDb0D/Pt+lWpTkKF7Kp+MqFOtwNFwnuiYeeDpFjp0qyMniE84OjKIEqQ==", "requires": { "async-limiter": "~1.0.0" @@ -7827,14 +7472,14 @@ "dependencies": { "xmlbuilder": { "version": "9.0.7", - "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" } } }, "xmlbuilder": { "version": "8.2.2", - "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=" }, "xmldom": { @@ -7858,13 +7503,13 @@ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, "yallist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" }, "yargs": { "version": "6.0.0", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-6.0.0.tgz", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.0.0.tgz", "integrity": "sha1-kAR5306L9qsOhyFvXtKydguWg0U=", "requires": { "cliui": "^3.2.0", @@ -7880,31 +7525,11 @@ "window-size": "^0.2.0", "y18n": "^3.2.1", "yargs-parser": "^4.0.2" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } } }, "yargs-parser": { "version": "4.2.1", - "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", "requires": { "camelcase": "^3.0.0" diff --git a/package.json b/package.json index 4925ea1c68..4a30fb3a82 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "gaze": "1.1.0", "iconv-lite": "0.4.11", "inquirer": "6.2.0", - "ios-device-lib": "0.5.0", + "ios-device-lib": "0.5.1", "ios-mobileprovision-finder": "1.0.10", "ios-sim-portable": "4.0.8", "istextorbinary": "2.2.1", diff --git a/test/debug.ts b/test/debug.ts index ae180e5c6c..fa3588e15f 100644 --- a/test/debug.ts +++ b/test/debug.ts @@ -1,6 +1,6 @@ import * as stubs from "./stubs"; import * as yok from "../lib/common/yok"; -import { DebugAndroidCommand, DebugPlatformCommand } from "../lib/commands/debug"; +import { DebugAndroidCommand } from "../lib/commands/debug"; import { assert } from "chai"; import { BundleValidatorHelper } from "../lib/helpers/bundle-validator-helper"; import { Configuration, StaticConfig } from "../lib/config"; @@ -10,13 +10,8 @@ import { FileSystem } from "../lib/common/file-system"; import { AndroidProjectService } from "../lib/services/android-project-service"; import { AndroidDebugBridge } from "../lib/common/mobile/android/android-debug-bridge"; import { AndroidDebugBridgeResultHandler } from "../lib/common/mobile/android/android-debug-bridge-result-handler"; -import { DebugCommandErrors } from "../lib/constants"; -import { CONNECTED_STATUS, UNREACHABLE_STATUS } from "../lib/common/constants"; import { SettingsService } from "../lib/common/test/unit-tests/stubs"; -const helpers = require("../lib/common/helpers"); -const originalIsInteracive = helpers.isInteractive; - function createTestInjector(): IInjector { const testInjector: IInjector = new yok.Yok(); @@ -87,262 +82,6 @@ function createTestInjector(): IInjector { } describe("debug command tests", () => { - describe("getDeviceForDebug", () => { - it("throws error when both --for-device and --emulator are passed", async () => { - const testInjector = createTestInjector(); - const options = testInjector.resolve("options"); - options.forDevice = options.emulator = true; - const debugCommand = testInjector.resolve(DebugPlatformCommand, { debugService: {}, platform: "android" }); - await assert.isRejected(debugCommand.getDeviceForDebug(), DebugCommandErrors.UNABLE_TO_USE_FOR_DEVICE_AND_EMULATOR); - }); - - it("returns selected device, when --device is passed", async () => { - const testInjector = createTestInjector(); - const devicesService = testInjector.resolve("devicesService"); - const deviceInstance = {}; - const specifiedDeviceOption = "device1"; - devicesService.getDevice = async (deviceOption: string): Promise => { - if (deviceOption === specifiedDeviceOption) { - return deviceInstance; - } - }; - - const options = testInjector.resolve("options"); - options.device = specifiedDeviceOption; - const debugCommand = testInjector.resolve(DebugPlatformCommand, { debugService: {}, platform: "android" }); - const selectedDeviceInstance = await debugCommand.getDeviceForDebug(); - assert.deepEqual(selectedDeviceInstance, deviceInstance); - }); - - const assertErrorIsThrown = async (getDeviceInstancesResult: Mobile.IDevice[], passedOptions?: { forDevice: boolean, emulator: boolean }) => { - const testInjector = createTestInjector(); - if (passedOptions) { - const options = testInjector.resolve("options"); - options.forDevice = passedOptions.forDevice; - options.emulator = passedOptions.emulator; - } - - const devicesService = testInjector.resolve("devicesService"); - devicesService.getDeviceInstances = (): Mobile.IDevice[] => getDeviceInstancesResult; - - const debugCommand = testInjector.resolve(DebugPlatformCommand, { debugService: {}, platform: "android" }); - await assert.isRejected(debugCommand.getDeviceForDebug(), DebugCommandErrors.NO_DEVICES_EMULATORS_FOUND_FOR_OPTIONS); - }; - - it("throws error when there are no devices/emulators available", () => { - return assertErrorIsThrown([]); - }); - - it("throws error when there are no devices/emulators available for selected platform", () => { - return assertErrorIsThrown([ - { - deviceInfo: { - platform: "ios", - status: CONNECTED_STATUS - } - } - ]); - }); - - it("throws error when there are only not-trusted devices/emulators available for selected platform", () => { - return assertErrorIsThrown([ - { - deviceInfo: { - platform: "android", - status: UNREACHABLE_STATUS - } - } - ]); - }); - - it("throws error when there are only devices and --emulator is passed", () => { - return assertErrorIsThrown([ - { - deviceInfo: { - platform: "android", - status: CONNECTED_STATUS - }, - isEmulator: false - } - ], { - forDevice: false, - emulator: true - }); - }); - - it("throws error when there are only emulators and --forDevice is passed", () => { - return assertErrorIsThrown([ - { - deviceInfo: { - platform: "android", - status: CONNECTED_STATUS - }, - isEmulator: true - } - ], { - forDevice: true, - emulator: false - }); - }); - - it("returns the only available device/emulator when it matches passed -- options", async () => { - const testInjector = createTestInjector(); - const deviceInstance = { - deviceInfo: { - platform: "android", - status: CONNECTED_STATUS - }, - isEmulator: true - }; - - const devicesService = testInjector.resolve("devicesService"); - devicesService.getDeviceInstances = (): Mobile.IDevice[] => [deviceInstance]; - - const debugCommand = testInjector.resolve(DebugPlatformCommand, { debugService: {}, platform: "android" }); - const actualDeviceInstance = await debugCommand.getDeviceForDebug(); - assert.deepEqual(actualDeviceInstance, deviceInstance); - }); - - describe("when multiple devices are detected", () => { - beforeEach(() => { - helpers.isInteractive = originalIsInteracive; - }); - - after(() => { - helpers.isInteractive = originalIsInteracive; - }); - - describe("when terminal is interactive", () => { - - it("prompts the user with information about available devices for specified platform only and returns the selected device instance", async () => { - helpers.isInteractive = () => true; - const testInjector = createTestInjector(); - const deviceInstance1 = { - deviceInfo: { - platform: "android", - status: CONNECTED_STATUS, - identifier: "deviceInstance1", - displayName: "displayName1" - }, - isEmulator: true - }; - - const deviceInstance2 = { - deviceInfo: { - platform: "android", - status: CONNECTED_STATUS, - identifier: "deviceInstance2", - displayName: "displayName2" - }, - isEmulator: true - }; - - const iOSDeviceInstance = { - deviceInfo: { - platform: "ios", - status: CONNECTED_STATUS, - identifier: "iosDevice", - displayName: "iPhone" - }, - isEmulator: true - }; - - const devicesService = testInjector.resolve("devicesService"); - devicesService.getDeviceInstances = (): Mobile.IDevice[] => [deviceInstance1, deviceInstance2, iOSDeviceInstance]; - - let choicesPassedToPrompter: string[]; - const prompter = testInjector.resolve("prompter"); - prompter.promptForChoice = async (promptMessage: string, choices: any[]): Promise => { - choicesPassedToPrompter = choices; - return choices[1]; - }; - - const debugCommand = testInjector.resolve(DebugPlatformCommand, { debugService: {}, platform: "android" }); - const actualDeviceInstance = await debugCommand.getDeviceForDebug(); - const expectedChoicesPassedToPrompter = [deviceInstance1, deviceInstance2].map(d => `${d.deviceInfo.identifier} - ${d.deviceInfo.displayName}`); - assert.deepEqual(choicesPassedToPrompter, expectedChoicesPassedToPrompter); - - assert.deepEqual(actualDeviceInstance, deviceInstance2); - }); - }); - - describe("when terminal is not interactive", () => { - beforeEach(() => { - helpers.isInteractive = () => false; - }); - - const assertCorrectInstanceIsUsed = async (opts: { forDevice: boolean, emulator: boolean, isEmulatorTest: boolean, excludeLastDevice?: boolean }) => { - const testInjector = createTestInjector(); - const deviceInstance1 = { - deviceInfo: { - platform: "android", - status: CONNECTED_STATUS, - identifier: "deviceInstance1", - displayName: "displayName1", - version: "5.1" - }, - isEmulator: opts.isEmulatorTest - }; - - const deviceInstance2 = { - deviceInfo: { - platform: "android", - status: CONNECTED_STATUS, - identifier: "deviceInstance2", - displayName: "displayName2", - version: "6.0" - }, - isEmulator: opts.isEmulatorTest - }; - - const deviceInstance3 = { - deviceInfo: { - platform: "android", - status: CONNECTED_STATUS, - identifier: "deviceInstance3", - displayName: "displayName3", - version: "7.1" - }, - isEmulator: !opts.isEmulatorTest - }; - - const options = testInjector.resolve("options"); - options.forDevice = opts.forDevice; - options.emulator = opts.emulator; - - const devicesService = testInjector.resolve("devicesService"); - const deviceInstances = [deviceInstance1, deviceInstance2]; - if (!opts.excludeLastDevice) { - deviceInstances.push(deviceInstance3); - } - - devicesService.getDeviceInstances = (): Mobile.IDevice[] => deviceInstances; - - const debugCommand = testInjector.resolve(DebugPlatformCommand, { debugService: {}, platform: "android" }); - const actualDeviceInstance = await debugCommand.getDeviceForDebug(); - - assert.deepEqual(actualDeviceInstance, deviceInstance2); - }; - - it("returns the emulator with highest API level when --emulator is passed", () => { - return assertCorrectInstanceIsUsed({ forDevice: false, emulator: true, isEmulatorTest: true }); - }); - - it("returns the device with highest API level when --forDevice is passed", () => { - return assertCorrectInstanceIsUsed({ forDevice: true, emulator: false, isEmulatorTest: false }); - }); - - it("returns the emulator with highest API level when neither --emulator and --forDevice are passed", () => { - return assertCorrectInstanceIsUsed({ forDevice: false, emulator: false, isEmulatorTest: true }); - }); - - it("returns the device with highest API level when neither --emulator and --forDevice are passed and emulators are not available", async () => { - return assertCorrectInstanceIsUsed({ forDevice: false, emulator: false, isEmulatorTest: false, excludeLastDevice: true }); - }); - }); - }); - }); - describe("Debugger tests", () => { let testInjector: IInjector; diff --git a/test/services/android-device-debug-service.ts b/test/services/android-device-debug-service.ts index 3edf69f536..0b3076062a 100644 --- a/test/services/android-device-debug-service.ts +++ b/test/services/android-device-debug-service.ts @@ -9,12 +9,10 @@ class AndroidDeviceDebugServiceInheritor extends AndroidDeviceDebugService { constructor(protected $devicesService: Mobile.IDevicesService, $errors: IErrors, $logger: ILogger, - $androidDeviceDiscovery: Mobile.IDeviceDiscovery, $androidProcessService: Mobile.IAndroidProcessService, $net: INet, - $projectDataService: IProjectDataService, $deviceLogProvider: Mobile.IDeviceLogProvider) { - super({ deviceInfo: { identifier: "123" } }, $devicesService, $errors, $logger, $androidDeviceDiscovery, $androidProcessService, $net, $projectDataService, $deviceLogProvider); + super({ deviceInfo: { identifier: "123" } }, $devicesService, $errors, $logger, $androidProcessService, $net, $deviceLogProvider); } public getChromeDebugUrl(debugOptions: IDebugOptions, port: number): string { diff --git a/test/services/debug-service.ts b/test/services/debug-service.ts index 5991165dcd..dd40a7b836 100644 --- a/test/services/debug-service.ts +++ b/test/services/debug-service.ts @@ -12,7 +12,7 @@ const defaultDeviceIdentifier = "Nexus5"; class PlatformDebugService extends EventEmitter /* implements IPlatformDebugService */ { public async debug(debugData: IDebugData, debugOptions: IDebugOptions): Promise { - return { debugUrl: fakeChromeDebugUrl, hasReconnected: false }; + return { debugUrl: fakeChromeDebugUrl }; } } @@ -226,8 +226,7 @@ describe("debugService", () => { assert.deepEqual(debugInfo, { url: fakeChromeDebugUrl, port: fakeChromeDebugPort, - deviceIdentifier: debugData.deviceIdentifier, - hasReconnected: false + deviceIdentifier: debugData.deviceIdentifier }); }); }); diff --git a/test/services/ios-debugger-port-service.ts b/test/services/ios-debugger-port-service.ts index 2f12ac2cdc..abbbf43602 100644 --- a/test/services/ios-debugger-port-service.ts +++ b/test/services/ios-debugger-port-service.ts @@ -145,13 +145,9 @@ describe("iOSDebuggerPortService", () => { } ]; - const mockProjectDirObj = { - projectDir: "/Users/username/projectdir" - }; - _.each(testCases, testCase => { it(testCase.name, async () => { - await iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device, mockProjectDirObj, {}); + await iOSDebuggerPortService.attachToDebuggerPortFoundEvent(); if (testCase.emitStartingIOSApplicationEvent) { emitStartingIOSApplicationEvent(); } @@ -165,7 +161,7 @@ describe("iOSDebuggerPortService", () => { assert.deepEqual(port, testCase.emittedPort); }); it(`${testCase.name} for multiline debugger port message.`, async () => { - await iOSDebuggerPortService.attachToDebuggerPortFoundEvent(device, mockProjectDirObj, {}); + await iOSDebuggerPortService.attachToDebuggerPortFoundEvent(); if (testCase.emitStartingIOSApplicationEvent) { emitStartingIOSApplicationEvent(); } diff --git a/test/services/ios-device-debug-service.ts b/test/services/ios-device-debug-service.ts index 86423e0756..bfdffe1153 100644 --- a/test/services/ios-device-debug-service.ts +++ b/test/services/ios-device-debug-service.ts @@ -7,21 +7,16 @@ const expectedDevToolsCommitSha = "02e6bde1bbe34e43b309d4ef774b1168d25fd024"; class IOSDeviceDebugServiceInheritor extends IOSDeviceDebugService { constructor(protected $devicesService: Mobile.IDevicesService, - $platformService: IPlatformService, - $iOSEmulatorServices: Mobile.IiOSSimulatorService, $childProcess: IChildProcess, $hostInfo: IHostInfo, $logger: ILogger, $errors: IErrors, $packageInstallationManager: IPackageInstallationManager, - $iOSDebuggerPortService: IIOSDebuggerPortService, $processService: IProcessService, $appDebugSocketProxyFactory: IAppDebugSocketProxyFactory, - $projectDataService: IProjectDataService, - $deviceLogProvider: Mobile.IDeviceLogProvider) { - super({ deviceInfo: { identifier: "123" } }, $devicesService, $platformService, $iOSEmulatorServices, $childProcess, $hostInfo, $logger, $errors, - $packageInstallationManager, $iOSDebuggerPortService, - $processService, $appDebugSocketProxyFactory, $projectDataService, $deviceLogProvider); + $projectDataService: IProjectDataService) { + super({ deviceInfo: { identifier: "123" } }, $devicesService, $childProcess, $hostInfo, $logger, $errors, + $packageInstallationManager, $processService, $appDebugSocketProxyFactory, $projectDataService); } public getChromeDebugUrl(debugOptions: IDebugOptions, port: number): string { diff --git a/test/stubs.ts b/test/stubs.ts index bbf28e6eeb..a8182dfb6c 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -643,10 +643,6 @@ export class DebugServiceStub extends EventEmitter implements IDeviceDebugServic return; } - public async debugStart(): Promise { - return; - } - public async debugStop(): Promise { return; }