@@ -37,13 +37,13 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
3737 private $debugDataService : IDebugDataService ,
3838 private $analyticsService : IAnalyticsService ,
3939 private $usbLiveSyncService : DeprecatedUsbLiveSyncService ,
40+ private $previewAppLiveSyncService : IPreviewAppLiveSyncService ,
4041 private $injector : IInjector ) {
4142 super ( ) ;
4243 }
4344
4445 public async liveSync ( deviceDescriptors : ILiveSyncDeviceInfo [ ] , liveSyncData : ILiveSyncInfo ) : Promise < void > {
4546 const projectData = this . $projectDataService . getProjectData ( liveSyncData . projectDir ) ;
46- await this . $pluginsService . ensureAllDependenciesAreInstalled ( projectData ) ;
4747 await this . liveSyncOperation ( deviceDescriptors , liveSyncData , projectData ) ;
4848 }
4949
@@ -318,16 +318,22 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
318318
319319 @hook ( "liveSync" )
320320 private async liveSyncOperation ( deviceDescriptors : ILiveSyncDeviceInfo [ ] , liveSyncData : ILiveSyncInfo , projectData : IProjectData ) : Promise < void > {
321- // In case liveSync is called for a second time for the same projectDir.
322- const isAlreadyLiveSyncing = this . liveSyncProcessesInfo [ projectData . projectDir ] && ! this . liveSyncProcessesInfo [ projectData . projectDir ] . isStopped ;
321+ let deviceDescriptorsForInitialSync : ILiveSyncDeviceInfo [ ] = [ ] ;
323322
324- // 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.
325- const currentlyRunningDeviceDescriptors = this . getLiveSyncDeviceDescriptors ( projectData . projectDir ) ;
326- const deviceDescriptorsForInitialSync = isAlreadyLiveSyncing ? _ . differenceBy ( deviceDescriptors , currentlyRunningDeviceDescriptors , deviceDescriptorPrimaryKey ) : deviceDescriptors ;
323+ if ( ! liveSyncData . syncToPreviewApp ) {
324+ await this . $pluginsService . ensureAllDependenciesAreInstalled ( projectData ) ;
325+ // In case liveSync is called for a second time for the same projectDir.
326+ const isAlreadyLiveSyncing = this . liveSyncProcessesInfo [ projectData . projectDir ] && ! this . liveSyncProcessesInfo [ projectData . projectDir ] . isStopped ;
327+
328+ // 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.
329+ const currentlyRunningDeviceDescriptors = this . getLiveSyncDeviceDescriptors ( projectData . projectDir ) ;
330+ deviceDescriptorsForInitialSync = isAlreadyLiveSyncing ? _ . differenceBy ( deviceDescriptors , currentlyRunningDeviceDescriptors , deviceDescriptorPrimaryKey ) : deviceDescriptors ;
331+ }
327332
328333 this . setLiveSyncProcessInfo ( liveSyncData . projectDir , deviceDescriptors ) ;
329334
330- if ( ! liveSyncData . skipWatcher && this . liveSyncProcessesInfo [ projectData . projectDir ] . deviceDescriptors . length ) {
335+ const shouldStartWatcher = liveSyncData . syncToPreviewApp || ( ! liveSyncData . skipWatcher && this . liveSyncProcessesInfo [ projectData . projectDir ] . deviceDescriptors . length ) ;
336+ if ( shouldStartWatcher ) {
331337 // Should be set after prepare
332338 this . $usbLiveSyncService . isInitialized = true ;
333339 await this . startWatcher ( projectData , liveSyncData , deviceDescriptors ) ;
@@ -448,6 +454,27 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
448454 }
449455
450456 private async initialSync ( projectData : IProjectData , liveSyncData : ILiveSyncInfo , deviceDescriptors : ILiveSyncDeviceInfo [ ] ) : Promise < void > {
457+ if ( liveSyncData . syncToPreviewApp ) {
458+ await this . initialSyncToPreviewApp ( projectData , liveSyncData ) ;
459+ } else {
460+ await this . initialCableSync ( projectData , liveSyncData , deviceDescriptors ) ;
461+ }
462+ }
463+
464+ private async initialSyncToPreviewApp ( projectData : IProjectData , liveSyncData : ILiveSyncInfo ) {
465+ this . addActionToChain ( projectData . projectDir , async ( ) => {
466+ await this . $previewAppLiveSyncService . initialSync ( {
467+ appFilesUpdaterOptions : {
468+ bundle : liveSyncData . bundle ,
469+ release : liveSyncData . release
470+ } ,
471+ env : liveSyncData . env ,
472+ projectData
473+ } ) ;
474+ } ) ;
475+ }
476+
477+ private async initialCableSync ( projectData : IProjectData , liveSyncData : ILiveSyncInfo , deviceDescriptors : ILiveSyncDeviceInfo [ ] ) : Promise < void > {
451478 const preparedPlatforms : string [ ] = [ ] ;
452479 const rebuiltInformation : ILiveSyncBuildInfo [ ] = [ ] ;
453480
@@ -552,82 +579,95 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
552579
553580 const startSyncFilesTimeout = ( ) => {
554581 timeoutTimer = setTimeout ( async ( ) => {
555- // Push actions to the queue, do not start them simultaneously
556- await this . addActionToChain ( projectData . projectDir , async ( ) => {
557- if ( filesToSync . length || filesToRemove . length ) {
558- try {
559- const currentFilesToSync = _ . cloneDeep ( filesToSync ) ;
560- filesToSync . splice ( 0 , filesToSync . length ) ;
561-
562- const currentFilesToRemove = _ . cloneDeep ( filesToRemove ) ;
563- filesToRemove = [ ] ;
564-
565- const allModifiedFiles = [ ] . concat ( currentFilesToSync ) . concat ( currentFilesToRemove ) ;
566-
567- const preparedPlatforms : string [ ] = [ ] ;
568- const rebuiltInformation : ILiveSyncBuildInfo [ ] = [ ] ;
569-
570- const latestAppPackageInstalledSettings = this . getDefaultLatestAppPackageInstalledSettings ( ) ;
571-
572- await this . $devicesService . execute ( async ( device : Mobile . IDevice ) => {
573- const liveSyncProcessInfo = this . liveSyncProcessesInfo [ projectData . projectDir ] ;
574- const deviceBuildInfoDescriptor = _ . find ( liveSyncProcessInfo . deviceDescriptors , dd => dd . identifier === device . deviceInfo . identifier ) ;
575-
576- const appInstalledOnDeviceResult = await this . ensureLatestAppPackageIsInstalledOnDevice ( {
577- device,
578- preparedPlatforms,
579- rebuiltInformation,
580- projectData,
581- deviceBuildInfoDescriptor,
582- liveSyncData,
583- settings : latestAppPackageInstalledSettings ,
584- modifiedFiles : allModifiedFiles ,
585- filesToRemove : currentFilesToRemove ,
586- filesToSync : currentFilesToSync ,
587- bundle : liveSyncData . bundle ,
588- release : liveSyncData . release ,
589- env : liveSyncData . env ,
590- skipModulesNativeCheck : ! liveSyncData . watchAllFiles
591- } , { skipNativePrepare : deviceBuildInfoDescriptor . skipNativePrepare } ) ;
592-
593- const service = this . getLiveSyncService ( device . deviceInfo . platform ) ;
594- const settings : ILiveSyncWatchInfo = {
595- projectData,
596- filesToRemove : currentFilesToRemove ,
597- filesToSync : currentFilesToSync ,
598- isReinstalled : appInstalledOnDeviceResult . appInstalled ,
599- syncAllFiles : liveSyncData . watchAllFiles ,
600- useHotModuleReload : liveSyncData . useHotModuleReload
601- } ;
602-
603- const liveSyncResultInfo = await service . liveSyncWatchAction ( device , settings ) ;
604- await this . refreshApplication ( projectData , liveSyncResultInfo , deviceBuildInfoDescriptor . debugOptions , deviceBuildInfoDescriptor . outputPath ) ;
582+ if ( liveSyncData . syncToPreviewApp ) {
583+ await this . addActionToChain ( projectData . projectDir , async ( ) => {
584+ await this . $previewAppLiveSyncService . syncFiles ( {
585+ appFilesUpdaterOptions : {
586+ bundle : liveSyncData . bundle ,
587+ release : liveSyncData . release
605588 } ,
606- ( device : Mobile . IDevice ) => {
589+ env : liveSyncData . env ,
590+ projectData : projectData
591+ } , filesToSync ) ;
592+ } ) ;
593+ } else {
594+ // Push actions to the queue, do not start them simultaneously
595+ await this . addActionToChain ( projectData . projectDir , async ( ) => {
596+ if ( filesToSync . length || filesToRemove . length ) {
597+ try {
598+ const currentFilesToSync = _ . cloneDeep ( filesToSync ) ;
599+ filesToSync . splice ( 0 , filesToSync . length ) ;
600+
601+ const currentFilesToRemove = _ . cloneDeep ( filesToRemove ) ;
602+ filesToRemove = [ ] ;
603+
604+ const allModifiedFiles = [ ] . concat ( currentFilesToSync ) . concat ( currentFilesToRemove ) ;
605+
606+ const preparedPlatforms : string [ ] = [ ] ;
607+ const rebuiltInformation : ILiveSyncBuildInfo [ ] = [ ] ;
608+
609+ const latestAppPackageInstalledSettings = this . getDefaultLatestAppPackageInstalledSettings ( ) ;
610+
611+ await this . $devicesService . execute ( async ( device : Mobile . IDevice ) => {
607612 const liveSyncProcessInfo = this . liveSyncProcessesInfo [ projectData . projectDir ] ;
608- return liveSyncProcessInfo && _ . some ( liveSyncProcessInfo . deviceDescriptors , deviceDescriptor => deviceDescriptor . identifier === device . deviceInfo . identifier ) ;
609- }
610- ) ;
611- } catch ( err ) {
612- const allErrors = ( < Mobile . IDevicesOperationError > err ) . allErrors ;
613-
614- if ( allErrors && _ . isArray ( allErrors ) ) {
615- for ( const deviceError of allErrors ) {
616- this . $logger . warn ( `Unable to apply changes for device: ${ deviceError . deviceIdentifier } . Error is: ${ deviceError . message } .` ) ;
617-
618- this . emit ( LiveSyncEvents . liveSyncError , {
619- error : deviceError ,
620- deviceIdentifier : deviceError . deviceIdentifier ,
621- projectDir : projectData . projectDir ,
622- applicationIdentifier : projectData . projectId
623- } ) ;
624-
625- await this . stopLiveSync ( projectData . projectDir , [ deviceError . deviceIdentifier ] , { shouldAwaitAllActions : false } ) ;
613+ const deviceBuildInfoDescriptor = _ . find ( liveSyncProcessInfo . deviceDescriptors , dd => dd . identifier === device . deviceInfo . identifier ) ;
614+
615+ const appInstalledOnDeviceResult = await this . ensureLatestAppPackageIsInstalledOnDevice ( {
616+ device,
617+ preparedPlatforms,
618+ rebuiltInformation,
619+ projectData,
620+ deviceBuildInfoDescriptor,
621+ liveSyncData,
622+ settings : latestAppPackageInstalledSettings ,
623+ modifiedFiles : allModifiedFiles ,
624+ filesToRemove : currentFilesToRemove ,
625+ filesToSync : currentFilesToSync ,
626+ bundle : liveSyncData . bundle ,
627+ release : liveSyncData . release ,
628+ env : liveSyncData . env ,
629+ skipModulesNativeCheck : ! liveSyncData . watchAllFiles
630+ } , { skipNativePrepare : deviceBuildInfoDescriptor . skipNativePrepare } ) ;
631+
632+ const service = this . getLiveSyncService ( device . deviceInfo . platform ) ;
633+ const settings : ILiveSyncWatchInfo = {
634+ projectData,
635+ filesToRemove : currentFilesToRemove ,
636+ filesToSync : currentFilesToSync ,
637+ isReinstalled : appInstalledOnDeviceResult . appInstalled ,
638+ syncAllFiles : liveSyncData . watchAllFiles ,
639+ useHotModuleReload : liveSyncData . useHotModuleReload
640+ } ;
641+
642+ const liveSyncResultInfo = await service . liveSyncWatchAction ( device , settings ) ;
643+ await this . refreshApplication ( projectData , liveSyncResultInfo , deviceBuildInfoDescriptor . debugOptions , deviceBuildInfoDescriptor . outputPath ) ;
644+ } ,
645+ ( device : Mobile . IDevice ) => {
646+ const liveSyncProcessInfo = this . liveSyncProcessesInfo [ projectData . projectDir ] ;
647+ return liveSyncProcessInfo && _ . some ( liveSyncProcessInfo . deviceDescriptors , deviceDescriptor => deviceDescriptor . identifier === device . deviceInfo . identifier ) ;
648+ }
649+ ) ;
650+ } catch ( err ) {
651+ const allErrors = ( < Mobile . IDevicesOperationError > err ) . allErrors ;
652+
653+ if ( allErrors && _ . isArray ( allErrors ) ) {
654+ for ( const deviceError of allErrors ) {
655+ this . $logger . warn ( `Unable to apply changes for device: ${ deviceError . deviceIdentifier } . Error is: ${ deviceError . message } .` ) ;
656+
657+ this . emit ( LiveSyncEvents . liveSyncError , {
658+ error : deviceError ,
659+ deviceIdentifier : deviceError . deviceIdentifier ,
660+ projectDir : projectData . projectDir ,
661+ applicationIdentifier : projectData . projectId
662+ } ) ;
663+
664+ await this . stopLiveSync ( projectData . projectDir , [ deviceError . deviceIdentifier ] , { shouldAwaitAllActions : false } ) ;
665+ }
626666 }
627667 }
628668 }
629- }
630- } ) ;
669+ } ) ;
670+ }
631671 } , 250 ) ;
632672
633673 this . liveSyncProcessesInfo [ liveSyncData . projectDir ] . timer = timeoutTimer ;
@@ -683,6 +723,11 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
683723 this . liveSyncProcessesInfo [ liveSyncData . projectDir ] . timer = timeoutTimer ;
684724
685725 this . $processService . attachToProcessExitSignals ( this , ( ) => {
726+ if ( liveSyncData . syncToPreviewApp ) {
727+ // Do not await here, we are in process exit's handler.
728+ this . $previewAppLiveSyncService . stopLiveSync ( ) ;
729+ }
730+
686731 _ . keys ( this . liveSyncProcessesInfo ) . forEach ( projectDir => {
687732 // Do not await here, we are in process exit's handler.
688733 /* tslint:disable:no-floating-promises */
0 commit comments