UNPKG

nativescript

Version:

Command-line interface for building NativeScript projects

528 lines • 32.1 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.RunController = void 0; const constants_1 = require("../common/constants"); const constants_2 = require("../constants"); const decorators_1 = require("../common/decorators"); const events_1 = require("events"); const util = require("util"); const _ = require("lodash"); const yok_1 = require("../common/yok"); class RunController extends events_1.EventEmitter { constructor($analyticsService, $buildController, $debugController, $deviceInstallAppService, $devicesService, $errors, $injector, $hmrStatusService, $hooksService, $liveSyncServiceResolver, $liveSyncProcessDataService, $logger, $mobileHelper, $platformsDataService, $pluginsService, $prepareController, $prepareDataService, $prepareNativePlatformService, $projectChangesService, $projectDataService) { super(); this.$analyticsService = $analyticsService; this.$buildController = $buildController; this.$debugController = $debugController; this.$deviceInstallAppService = $deviceInstallAppService; this.$devicesService = $devicesService; this.$errors = $errors; this.$injector = $injector; this.$hmrStatusService = $hmrStatusService; this.$hooksService = $hooksService; this.$liveSyncServiceResolver = $liveSyncServiceResolver; this.$liveSyncProcessDataService = $liveSyncProcessDataService; this.$logger = $logger; this.$mobileHelper = $mobileHelper; this.$platformsDataService = $platformsDataService; this.$pluginsService = $pluginsService; this.$prepareController = $prepareController; this.$prepareDataService = $prepareDataService; this.$prepareNativePlatformService = $prepareNativePlatformService; this.$projectChangesService = $projectChangesService; this.$projectDataService = $projectDataService; this.prepareReadyEventHandler = null; } async run(runData) { const { liveSyncInfo, deviceDescriptors } = runData; const { projectDir } = liveSyncInfo; const projectData = this.$projectDataService.getProjectData(projectDir); await this.initializeSetup(projectData); const deviceDescriptorsForInitialSync = this.getDeviceDescriptorsForInitialSync(projectDir, deviceDescriptors); const newPlatforms = this.$devicesService.getPlatformsFromDeviceDescriptors(deviceDescriptors); const oldPlatforms = this.$liveSyncProcessDataService.getPlatforms(projectDir); const platforms = _.uniq(_.concat(newPlatforms, oldPlatforms)); this.$liveSyncProcessDataService.persistData(projectDir, deviceDescriptors, platforms); const shouldStartWatcher = !liveSyncInfo.skipWatcher && this.$liveSyncProcessDataService.hasDeviceDescriptors(projectDir); if (shouldStartWatcher && liveSyncInfo.useHotModuleReload) { this.$hmrStatusService.attachToHmrStatusEvent(); } if (!this.prepareReadyEventHandler) { const handler = async (data) => { if (data.hasNativeChanges) { const platformData = this.$platformsDataService.getPlatformData(data.platform, projectData); const prepareData = this.$prepareDataService.getPrepareData(liveSyncInfo.projectDir, data.platform, { ...liveSyncInfo, watch: !liveSyncInfo.skipWatcher }); const changesInfo = await this.$projectChangesService.checkForChanges(platformData, projectData, prepareData); if (changesInfo.hasChanges) { await this.syncChangedDataOnDevices(data, projectData, liveSyncInfo); } } else { await this.syncChangedDataOnDevices(data, projectData, liveSyncInfo); } }; this.prepareReadyEventHandler = handler.bind(this); this.$prepareController.on(constants_2.PREPARE_READY_EVENT_NAME, this.prepareReadyEventHandler); } await this.syncInitialDataOnDevices(projectData, liveSyncInfo, deviceDescriptorsForInitialSync); this.attachDeviceLostHandler(); } async stop(data) { const { projectDir, deviceIdentifiers, stopOptions } = data; const liveSyncProcessInfo = this.$liveSyncProcessDataService.getPersistedData(projectDir); 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; const deviceIdentifiersToRemove = deviceIdentifiers && deviceIdentifiers.length ? deviceIdentifiers : _.map(liveSyncProcessInfo.deviceDescriptors, (d) => d.identifier); const removedDeviceIdentifiers = _.remove(liveSyncProcessInfo.deviceDescriptors, (descriptor) => _.includes(deviceIdentifiersToRemove, descriptor.identifier)).map((descriptor) => descriptor.identifier); // Handle the case when no more devices left for any of the persisted platforms for (let i = 0; i < liveSyncProcessInfo.platforms.length; i++) { const platform = liveSyncProcessInfo.platforms[i]; const devices = this.$devicesService.getDevicesForPlatform(platform); if (!devices || !devices.length) { await this.$prepareController.stopWatchers(projectDir, platform); } } // In case deviceIdentifiers are not passed, we should stop the whole LiveSync. if (!deviceIdentifiers || !deviceIdentifiers.length || !liveSyncProcessInfo.deviceDescriptors || !liveSyncProcessInfo.deviceDescriptors.length) { if (liveSyncProcessInfo.timer) { clearTimeout(liveSyncProcessInfo.timer); } for (let k = 0; k < liveSyncProcessInfo.platforms.length; k++) { await this.$prepareController.stopWatchers(projectDir, liveSyncProcessInfo.platforms[k]); } liveSyncProcessInfo.isStopped = true; if (liveSyncProcessInfo.actionsChain && shouldAwaitPendingOperation) { await liveSyncProcessInfo.actionsChain; } liveSyncProcessInfo.deviceDescriptors = []; if (this.prepareReadyEventHandler) { this.$prepareController.removeListener(constants_2.PREPARE_READY_EVENT_NAME, this.prepareReadyEventHandler); this.prepareReadyEventHandler = null; } const projectData = this.$projectDataService.getProjectData(projectDir); await this.$hooksService.executeAfterHooks("watch", { hookArgs: { projectData, }, }); } else if (liveSyncProcessInfo.currentSyncAction && shouldAwaitPendingOperation) { await liveSyncProcessInfo.currentSyncAction; } // Emit RunOnDevice stopped when we've really stopped. _.each(removedDeviceIdentifiers, (deviceIdentifier) => { this.emitCore(constants_2.RunOnDeviceEvents.runOnDeviceStopped, { projectDir, deviceIdentifier, keepProcessAlive: stopOptions === null || stopOptions === void 0 ? void 0 : stopOptions.keepProcessAlive, }); }); if (stopOptions === null || stopOptions === void 0 ? void 0 : stopOptions.keepProcessAlive) { this.removeAllListeners(constants_2.RunOnDeviceEvents.runOnDeviceStopped); } } } getDeviceDescriptors(data) { return this.$liveSyncProcessDataService.getDeviceDescriptors(data.projectDir); } async refreshApplication(projectData, liveSyncResultInfo, filesChangeEventData, deviceDescriptor, fullSyncAction) { const result = deviceDescriptor.debuggingEnabled ? await this.refreshApplicationWithDebug(projectData, liveSyncResultInfo, filesChangeEventData, deviceDescriptor) : await this.refreshApplicationWithoutDebug(projectData, liveSyncResultInfo, filesChangeEventData, deviceDescriptor, undefined, fullSyncAction); const device = liveSyncResultInfo.deviceAppData.device; this.emitCore(constants_2.RunOnDeviceEvents.runOnDeviceExecuted, { projectDir: projectData.projectDir, deviceIdentifier: device.deviceInfo.identifier, applicationIdentifier: projectData.projectIdentifiers[device.deviceInfo.platform.toLowerCase()], syncedFiles: liveSyncResultInfo.modifiedFilesData.map((m) => m.getLocalPath()), isFullSync: liveSyncResultInfo.isFullSync, }); return result; } async refreshApplicationWithDebug(projectData, liveSyncResultInfo, filesChangeEventData, deviceDescriptor) { const debugOptions = deviceDescriptor.debugOptions || {}; liveSyncResultInfo.waitForDebugger = !!debugOptions.debugBrk; liveSyncResultInfo.forceRefreshWithSocket = true; const refreshInfo = await this.refreshApplicationWithoutDebug(projectData, liveSyncResultInfo, filesChangeEventData, deviceDescriptor, { 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 = refreshInfo.didRestart; await this.$debugController.enableDebuggingCoreWithoutWaitingCurrentAction(projectData.projectDir, deviceDescriptor.identifier, debugOptions); return refreshInfo; } async refreshApplicationWithoutDebug(projectData, liveSyncResultInfo, filesChangeEventData, deviceDescriptor, settings, fullSyncAction) { const result = { didRestart: false }; const platform = liveSyncResultInfo.deviceAppData.platform; const applicationIdentifier = projectData.projectIdentifiers[platform.toLowerCase()]; const platformLiveSyncService = this.$liveSyncServiceResolver.resolveLiveSyncService(platform); try { const isFullSync = filesChangeEventData && (filesChangeEventData.hasNativeChanges || !filesChangeEventData.hasOnlyHotUpdateFiles); let shouldRestart = isFullSync; if (!shouldRestart) { shouldRestart = await platformLiveSyncService.shouldRestart(projectData, liveSyncResultInfo); } if (!shouldRestart) { shouldRestart = !(await platformLiveSyncService.tryRefreshApplication(projectData, liveSyncResultInfo)); } if (!isFullSync && shouldRestart && fullSyncAction) { this.$logger.trace(`Syncing all files as the current app state does not support hot updates.`); liveSyncResultInfo.didRecover = true; await fullSyncAction(); } if (shouldRestart) { this.emit(constants_2.DEBUGGER_DETACHED_EVENT_NAME, { deviceIdentifier: liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier, }); await platformLiveSyncService.restartApplication(projectData, liveSyncResultInfo); result.didRestart = true; } } catch (err) { this.$logger.info(`Error while trying to start application ${applicationIdentifier} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}. Error is: ${err.message || err}`); const msg = `Unable to start application ${applicationIdentifier} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}. Try starting it manually.`; this.$logger.warn(msg); const device = liveSyncResultInfo.deviceAppData.device; const deviceIdentifier = device.deviceInfo.identifier; if (!settings || !settings.shouldSkipEmitLiveSyncNotification) { this.emitCore(constants_2.RunOnDeviceEvents.runOnDeviceNotification, { projectDir: projectData.projectDir, deviceIdentifier: device.deviceInfo.identifier, applicationIdentifier: projectData.projectIdentifiers[device.deviceInfo.platform.toLowerCase()], notification: msg, }); } if (settings && settings.shouldCheckDeveloperDiscImage && (err.message || err) === "Could not find developer disk image") { const attachDebuggerOptions = { platform: device.deviceInfo.platform, isEmulator: device.isEmulator, projectDir: projectData.projectDir, deviceIdentifier, debugOptions: deviceDescriptor.debugOptions, outputPath: deviceDescriptor.buildData.outputPath, }; this.emit(constants_2.USER_INTERACTION_NEEDED_EVENT_NAME, attachDebuggerOptions); } } return result; } getDeviceDescriptorsForInitialSync(projectDir, deviceDescriptors) { const currentRunData = this.$liveSyncProcessDataService.getPersistedData(projectDir); const isAlreadyLiveSyncing = currentRunData && !currentRunData.isStopped; // Prevent cases where liveSync is called consecutive times with the same device, for example [ A, B, C ] and then [ A, B, D ] - we want to execute initialSync only for D. const deviceDescriptorsForInitialSync = isAlreadyLiveSyncing ? _.differenceBy(deviceDescriptors, currentRunData.deviceDescriptors, "identifier") : deviceDescriptors; return deviceDescriptorsForInitialSync; } async initializeSetup(projectData) { try { await this.$pluginsService.ensureAllDependenciesAreInstalled(projectData); } catch (err) { this.$logger.trace(err); this.$errors.fail(`Unable to install dependencies. Make sure your package.json is valid and all dependencies are correct. Error is: ${err.message}`); } } attachDeviceLostHandler() { this.$devicesService.on(constants_1.DeviceDiscoveryEventNames.DEVICE_LOST, async (device) => { this.$logger.trace(`Received ${constants_1.DeviceDiscoveryEventNames.DEVICE_LOST} event in LiveSync service for ${device.deviceInfo.identifier}. Will stop LiveSync operation for this device.`); for (const projectDir in this.$liveSyncProcessDataService.getAllPersistedData()) { try { const deviceDescriptors = this.getDeviceDescriptors({ projectDir }); if (_.find(deviceDescriptors, (d) => d.identifier === device.deviceInfo.identifier)) { await this.stop({ projectDir, deviceIdentifiers: [device.deviceInfo.identifier], }); } } catch (err) { this.$logger.warn(`Unable to stop LiveSync operation for ${device.deviceInfo.identifier}.`, err); } } }); } async syncInitialDataOnDevices(projectData, liveSyncInfo, deviceDescriptors) { const rebuiltInformation = {}; const deviceAction = async (device) => { const deviceDescriptor = _.find(deviceDescriptors, (dd) => dd.identifier === device.deviceInfo.identifier); const prepareData = this.$prepareDataService.getPrepareData(liveSyncInfo.projectDir, device.deviceInfo.platform, { ...liveSyncInfo, ...deviceDescriptor.buildData, nativePrepare: { skipNativePrepare: !!deviceDescriptor.skipNativePrepare, }, watch: !liveSyncInfo.skipWatcher, }); const prepareResultData = await this.$prepareController.prepare(prepareData); const buildData = { ...deviceDescriptor.buildData, buildForDevice: !device.isEmulator, }; const platformData = this.$platformsDataService.getPlatformData(device.deviceInfo.platform, projectData); try { let packageFilePath = null; // Case where we have three devices attached, a change that requires build is found, // we'll rebuild the app only for the first device, but we should install new package on all three devices. if (rebuiltInformation[platformData.platformNameLowerCase] && (this.$mobileHelper.isAndroidPlatform(platformData.platformNameLowerCase) || rebuiltInformation[platformData.platformNameLowerCase] .isEmulator === device.isEmulator)) { packageFilePath = rebuiltInformation[platformData.platformNameLowerCase] .packageFilePath; await this.$deviceInstallAppService.installOnDevice(device, buildData, packageFilePath); } else { const shouldBuild = prepareResultData.hasNativeChanges || buildData.nativePrepare.forceRebuildNativeApp || (await this.$buildController.shouldBuild(buildData)); if (shouldBuild) { packageFilePath = await deviceDescriptor.buildAction(); rebuiltInformation[platformData.platformNameLowerCase] = { isEmulator: device.isEmulator, platform: platformData.platformNameLowerCase, packageFilePath, }; } else { await this.$analyticsService.trackEventActionInGoogleAnalytics({ action: "LiveSync" /* TrackActionNames.LiveSync */, device, projectDir: projectData.projectDir, }); } await this.$deviceInstallAppService.installOnDeviceIfNeeded(device, buildData, packageFilePath); } const platformLiveSyncService = this.$liveSyncServiceResolver.resolveLiveSyncService(platformData.platformNameLowerCase); const { force, useHotModuleReload, skipWatcher } = liveSyncInfo; const liveSyncResultInfo = await platformLiveSyncService.fullSync({ force, useHotModuleReload, projectData, device, watch: !skipWatcher, liveSyncDeviceData: deviceDescriptor, }); await this.refreshApplication(projectData, liveSyncResultInfo, null, deviceDescriptor); this.$logger.info(`Successfully synced application ${liveSyncResultInfo.deviceAppData.appIdentifier} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}.`); this.emitCore(constants_2.RunOnDeviceEvents.runOnDeviceStarted, { projectDir: projectData.projectDir, deviceIdentifier: device.deviceInfo.identifier, applicationIdentifier: projectData.projectIdentifiers[device.deviceInfo.platform.toLowerCase()], }); } catch (err) { this.$logger.warn(`Unable to apply changes on device: ${device.deviceInfo.identifier}. Error is: ${err.message}.`); this.$logger.trace(err); this.emitCore(constants_2.RunOnDeviceEvents.runOnDeviceError, { projectDir: projectData.projectDir, deviceIdentifier: device.deviceInfo.identifier, applicationIdentifier: projectData.projectIdentifiers[device.deviceInfo.platform.toLowerCase()], error: err, }); await this.stop({ projectDir: projectData.projectDir, deviceIdentifiers: [device.deviceInfo.identifier], stopOptions: { shouldAwaitAllActions: false }, }); } }; await this.addActionToChain(projectData.projectDir, () => this.$devicesService.execute(deviceAction, (device) => _.some(deviceDescriptors, (deviceDescriptor) => deviceDescriptor.identifier === device.deviceInfo.identifier))); } async syncChangedDataOnDevices(data, projectData, liveSyncInfo) { const successfullySyncedMessageFormat = `Successfully synced application %s on device %s.`; const rebuiltInformation = {}; const deviceAction = async (device) => { var _a, _b; const deviceDescriptors = this.$liveSyncProcessDataService.getDeviceDescriptors(projectData.projectDir); const deviceDescriptor = _.find(deviceDescriptors, (dd) => dd.identifier === device.deviceInfo.identifier); const platformData = this.$platformsDataService.getPlatformData(data.platform, projectData); const prepareData = this.$prepareDataService.getPrepareData(liveSyncInfo.projectDir, device.deviceInfo.platform, { ...liveSyncInfo, ...deviceDescriptor.buildData, nativePrepare: { skipNativePrepare: !!deviceDescriptor.skipNativePrepare, }, watch: !liveSyncInfo.skipWatcher, }); try { const platformLiveSyncService = this.$liveSyncServiceResolver.resolveLiveSyncService(device.deviceInfo.platform); const allAppFiles = ((_b = (_a = data.hmrData) === null || _a === void 0 ? void 0 : _a.fallbackFiles) === null || _b === void 0 ? void 0 : _b.length) ? data.hmrData.fallbackFiles : data.files; const filesToSync = data.hasOnlyHotUpdateFiles ? data.files : allAppFiles; const watchInfo = { liveSyncDeviceData: deviceDescriptor, projectData, // todo: remove stale files once everything is stable // currently, watcher fires multiple times & may clean up unsynced files // filesToRemove: data.staleFiles ?? [], filesToRemove: [], filesToSync, hmrData: data.hmrData, useHotModuleReload: liveSyncInfo.useHotModuleReload, force: liveSyncInfo.force, connectTimeout: 1000, }; const deviceAppData = await platformLiveSyncService.getAppData(_.merge({ device, watch: true }, watchInfo)); if (data.hasNativeChanges) { const rebuiltInfo = rebuiltInformation[platformData.platformNameLowerCase] && (this.$mobileHelper.isAndroidPlatform(platformData.platformNameLowerCase) || rebuiltInformation[platformData.platformNameLowerCase] .isEmulator === device.isEmulator); if (!rebuiltInfo) { await this.$prepareNativePlatformService.prepareNativePlatform(platformData, projectData, prepareData); await deviceDescriptor.buildAction(); rebuiltInformation[platformData.platformNameLowerCase] = { isEmulator: device.isEmulator, platform: platformData.platformNameLowerCase, packageFilePath: null, }; } await this.$deviceInstallAppService.installOnDevice(device, deviceDescriptor.buildData, rebuiltInformation[platformData.platformNameLowerCase] .packageFilePath); await platformLiveSyncService.syncAfterInstall(device, watchInfo); await this.refreshApplication(projectData, { deviceAppData, modifiedFilesData: [], isFullSync: false, useHotModuleReload: liveSyncInfo.useHotModuleReload, }, data, deviceDescriptor); this.$logger.info(util.format(successfullySyncedMessageFormat, deviceAppData.appIdentifier, device.deviceInfo.identifier)); } else { const isInHMRMode = liveSyncInfo.useHotModuleReload && data.hmrData && data.hmrData.hash; if (isInHMRMode) { this.$hmrStatusService.watchHmrStatus(device.deviceInfo.identifier, data.hmrData.hash); } const watchAction = async () => { const liveSyncResultInfo = await platformLiveSyncService.liveSyncWatchAction(device, watchInfo); const fullSyncAction = async () => { watchInfo.filesToSync = allAppFiles; const fullLiveSyncResultInfo = await platformLiveSyncService.liveSyncWatchAction(device, watchInfo); // IMPORTANT: keep the same instance as we rely on side effects _.assign(liveSyncResultInfo, fullLiveSyncResultInfo); }; await this.$hooksService.executeBeforeHooks("watchAction", { hookArgs: { liveSyncResultInfo, filesToSync, allAppFiles, isInHMRMode, filesChangedEvent: data, }, }); await this.refreshApplication(projectData, liveSyncResultInfo, data, deviceDescriptor, fullSyncAction); if (!liveSyncResultInfo.didRecover && isInHMRMode) { const status = await this.$hmrStatusService.getHmrStatus(device.deviceInfo.identifier, data.hmrData.hash); // the timeout is assumed OK as the app could be blocked on a breakpoint if (status === constants_1.HmrConstants.HMR_ERROR_STATUS) { await fullSyncAction(); liveSyncResultInfo.isFullSync = true; await this.refreshApplication(projectData, liveSyncResultInfo, data, deviceDescriptor); } } await this.$hooksService.executeAfterHooks("watchAction", { liveSyncResultInfo, filesToSync, allAppFiles, filesChangedEvent: data, isInHMRMode, }); this.$logger.info(util.format(successfullySyncedMessageFormat, deviceAppData.appIdentifier, device.deviceInfo.identifier)); }; if (liveSyncInfo.useHotModuleReload) { try { this.$logger.trace("Try executing watch action without any preparation of files."); await watchAction(); this.$logger.trace("Successfully executed watch action without any preparation of files."); return; } catch (err) { this.$logger.trace(`Error while trying to execute fast sync. Now we'll check the state of the app and we'll try to resurrect from the error. The error is: ${err}`); } } await this.$deviceInstallAppService.installOnDeviceIfNeeded(device, deviceDescriptor.buildData); watchInfo.connectTimeout = null; await watchAction(); } } catch (err) { this.$logger.warn(`Unable to apply changes for device: ${device.deviceInfo.identifier}. Error is: ${err && err.message}.`); this.emitCore(constants_2.RunOnDeviceEvents.runOnDeviceError, { projectDir: projectData.projectDir, deviceIdentifier: device.deviceInfo.identifier, applicationIdentifier: projectData.projectIdentifiers[device.deviceInfo.platform.toLowerCase()], error: err, }); await this.stop({ projectDir: projectData.projectDir, deviceIdentifiers: [device.deviceInfo.identifier], stopOptions: { shouldAwaitAllActions: false }, }); } }; await this.addActionToChain(projectData.projectDir, () => this.$devicesService.execute(deviceAction, (device) => { const liveSyncProcessInfo = this.$liveSyncProcessDataService.getPersistedData(projectData.projectDir); return (data.platform.toLowerCase() === device.deviceInfo.platform.toLowerCase() && liveSyncProcessInfo && _.some(liveSyncProcessInfo.deviceDescriptors, (deviceDescriptor) => deviceDescriptor.identifier === device.deviceInfo.identifier)); })); } async addActionToChain(projectDir, action) { const liveSyncInfo = this.$liveSyncProcessDataService.getPersistedData(projectDir); if (liveSyncInfo) { liveSyncInfo.actionsChain = liveSyncInfo.actionsChain.then(async () => { if (!liveSyncInfo.isStopped) { liveSyncInfo.currentSyncAction = action(); const res = await liveSyncInfo.currentSyncAction; return res; } }); const result = await liveSyncInfo.actionsChain; return result; } } emitCore(event, data) { this.$logger.trace(`Will emit event ${event} with data`, data); this.emit(event, data); } } exports.RunController = RunController; __decorate([ (0, decorators_1.performanceLog)() ], RunController.prototype, "refreshApplicationWithoutDebug", null); __decorate([ (0, decorators_1.cache)() ], RunController.prototype, "attachDeviceLostHandler", null); yok_1.injector.register("runController", RunController); //# sourceMappingURL=run-controller.js.map