11import * as path from "path" ;
2- import { FilePayload , Device , FilesPayload } from "nativescript-preview-sdk" ;
3- import { PreviewSdkEventNames } from "./preview-app-constants" ;
4- import { APP_FOLDER_NAME , APP_RESOURCES_FOLDER_NAME , TNS_MODULES_FOLDER_NAME } from "../../../constants" ;
2+ import { Device , FilesPayload } from "nativescript-preview-sdk" ;
3+ import { APP_RESOURCES_FOLDER_NAME , APP_FOLDER_NAME } from "../../../constants" ;
54import { HmrConstants } from "../../../common/constants" ;
6- const isTextOrBinary = require ( 'istextorbinary' ) ;
7-
8- interface ISyncFilesOptions {
9- filesToSync ?: string [ ] ;
10- filesToRemove ?: string [ ] ;
11- isInitialSync ?: boolean ;
12- skipPrepare ?: boolean ;
13- useHotModuleReload ?: boolean ;
14- deviceId ?: string ;
15- }
5+ import { stringify } from "../../../common/helpers" ;
166
177export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
18- private excludedFileExtensions = [ ".ts" , ".sass" , ".scss" , ".less" ] ;
19- private excludedFiles = [ ".DS_Store" ] ;
8+
209 private deviceInitializationPromise : IDictionary < Promise < FilesPayload > > = { } ;
2110
22- constructor ( private $fs : IFileSystem ,
11+ constructor (
2312 private $errors : IErrors ,
2413 private $hooksService : IHooksService ,
2514 private $logger : ILogger ,
26- private $platformService : IPlatformService ,
2715 private $platformsData : IPlatformsData ,
2816 private $projectDataService : IProjectDataService ,
2917 private $previewSdkService : IPreviewSdkService ,
18+ private $previewAppFilesService : IPreviewAppFilesService ,
3019 private $previewAppPluginsService : IPreviewAppPluginsService ,
3120 private $previewDevicesService : IPreviewDevicesService ,
32- private $projectFilesManager : IProjectFilesManager ,
3321 private $hmrStatusService : IHmrStatusService ,
34- private $projectFilesProvider : IProjectFilesProvider ) { }
22+ ) { }
3523
3624 public async initialize ( data : IPreviewAppLiveSyncData ) : Promise < void > {
3725 await this . $previewSdkService . initialize ( async ( device : Device ) => {
@@ -43,7 +31,7 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
4331 return this . deviceInitializationPromise [ device . id ] ;
4432 }
4533
46- this . deviceInitializationPromise [ device . id ] = this . initializePreviewForDevice ( data , device ) ;
34+ this . deviceInitializationPromise [ device . id ] = this . getInitialFilesForDevice ( data , device ) ;
4735 try {
4836 const payloads = await this . deviceInitializationPromise [ device . id ] ;
4937 return payloads ;
@@ -65,27 +53,28 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
6553 . map ( device => device . platform )
6654 . uniq ( )
6755 . value ( ) ;
56+
6857 for ( const platform of platforms ) {
69- await this . syncFilesForPlatformSafe ( data , platform , { filesToSync, filesToRemove, useHotModuleReload : data . useHotModuleReload } ) ;
58+ await this . syncFilesForPlatformSafe ( data , { filesToSync, filesToRemove } , platform ) ;
7059 }
7160 }
7261
7362 public async stopLiveSync ( ) : Promise < void > {
7463 this . $previewSdkService . stop ( ) ;
7564 }
7665
77- private async initializePreviewForDevice ( data : IPreviewAppLiveSyncData , device : Device ) : Promise < FilesPayload > {
66+ private async getInitialFilesForDevice ( data : IPreviewAppLiveSyncData , device : Device ) : Promise < FilesPayload > {
7867 const hookArgs = this . getHookArgs ( data , device ) ;
7968 await this . $hooksService . executeBeforeHooks ( "preview-sync" , { hookArgs } ) ;
8069 await this . $previewAppPluginsService . comparePluginsOnDevice ( data , device ) ;
81- const payloads = await this . syncFilesForPlatformSafe ( data , device . platform , { isInitialSync : true , useHotModuleReload : data . useHotModuleReload } ) ;
70+ const payloads = await this . getInitialFilesForPlatformSafe ( data , device . platform ) ;
8271 return payloads ;
8372 }
8473
8574 private getHookArgs ( data : IPreviewAppLiveSyncData , device : Device ) {
8675 const filesToSyncMap : IDictionary < string [ ] > = { } ;
8776 const hmrData : IDictionary < IPlatformHmrData > = { } ;
88- const promise = Promise . resolve < FilesPayload > ( null ) ;
77+ const promise = Promise . resolve ( ) ;
8978 const result = {
9079 projectData : this . $projectDataService . getProjectData ( data . projectDir ) ,
9180 hmrData,
@@ -106,14 +95,44 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
10695 return result ;
10796 }
10897
109- private async onWebpackCompilationComplete ( data : IPreviewAppLiveSyncData , hmrData : IDictionary < IPlatformHmrData > , filesToSyncMap : IDictionary < string [ ] > , promise : Promise < FilesPayload > , platform : string ) {
98+ private async getInitialFilesForPlatformSafe ( data : IPreviewAppLiveSyncData , platform : string ) : Promise < FilesPayload > {
99+ this . $logger . info ( `Start sending initial files for platform ${ platform } .` ) ;
100+
101+ try {
102+ const payloads = this . $previewAppFilesService . getInitialFilesPayload ( data , platform ) ;
103+ this . $logger . info ( `Successfully sent initial files for platform ${ platform } .` ) ;
104+ return payloads ;
105+ } catch ( err ) {
106+ this . $logger . warn ( `Unable to apply changes for platform ${ platform } . Error is: ${ err } , ${ stringify ( err ) } ` ) ;
107+ }
108+ }
109+
110+ private async syncFilesForPlatformSafe ( data : IPreviewAppLiveSyncData , filesData : IPreviewAppFilesData , platform : string , deviceId ?: string ) : Promise < void > {
111+ this . $logger . info ( `Start syncing changes for platform ${ platform } .` ) ;
112+
113+ try {
114+ const payloads = this . $previewAppFilesService . getFilesPayload ( data , filesData , platform ) ;
115+ await this . $previewSdkService . applyChanges ( payloads ) ;
116+ this . $logger . info ( `Successfully synced ${ payloads . files . map ( filePayload => filePayload . file . yellow ) } for platform ${ platform } .` ) ;
117+ } catch ( err ) {
118+ this . $logger . warn ( `Unable to apply changes for platform ${ platform } . Error is: ${ err } , ${ stringify ( err ) } .` ) ;
119+ }
120+ }
121+
122+ private async onWebpackCompilationComplete ( data : IPreviewAppLiveSyncData , hmrData : IDictionary < IPlatformHmrData > , filesToSyncMap : IDictionary < string [ ] > , promise : Promise < void > , platform : string ) {
110123 await promise
111124 . then ( async ( ) => {
112125 const currentHmrData = _ . cloneDeep ( hmrData ) ;
113126 const platformHmrData = currentHmrData [ platform ] || < any > { } ;
114- const filesToSync = _ . cloneDeep ( filesToSyncMap [ platform ] ) ;
115- // We don't need to prepare when webpack emits changed files. We just need to send a message to pubnub.
116- promise = this . syncFilesForPlatformSafe ( data , platform , { filesToSync, skipPrepare : true , useHotModuleReload : data . useHotModuleReload } ) ;
127+ const projectData = this . $projectDataService . getProjectData ( data . projectDir ) ;
128+ const platformData = this . $platformsData . getPlatformData ( platform , projectData ) ;
129+ const clonedFiles = _ . cloneDeep ( filesToSyncMap [ platform ] ) ;
130+ const filesToSync = _ . map ( clonedFiles , fileToSync => {
131+ const result = path . join ( platformData . appDestinationDirectoryPath , APP_FOLDER_NAME , path . relative ( projectData . getAppDirectoryPath ( ) , fileToSync ) ) ;
132+ return result ;
133+ } ) ;
134+
135+ promise = this . syncFilesForPlatformSafe ( data , { filesToSync } , platform ) ;
117136 await promise ;
118137
119138 if ( data . useHotModuleReload && platformHmrData . hash ) {
@@ -122,123 +141,20 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
122141 await Promise . all ( _ . map ( devices , async ( previewDevice : Device ) => {
123142 const status = await this . $hmrStatusService . getHmrStatus ( previewDevice . id , platformHmrData . hash ) ;
124143 if ( status === HmrConstants . HMR_ERROR_STATUS ) {
125- await this . syncFilesForPlatformSafe ( data , platform , { filesToSync : platformHmrData . fallbackFiles , useHotModuleReload : false , deviceId : previewDevice . id } ) ;
144+ const originalUseHotModuleReload = data . useHotModuleReload ;
145+ data . useHotModuleReload = false ;
146+ await this . syncFilesForPlatformSafe ( data , { filesToSync : platformHmrData . fallbackFiles } , platform , previewDevice . id ) ;
147+ data . useHotModuleReload = originalUseHotModuleReload ;
126148 }
127149 } ) ) ;
128150 }
129151 } ) ;
130152 filesToSyncMap [ platform ] = [ ] ;
131153 }
132154
133- private async syncFilesForPlatformSafe ( data : IPreviewAppLiveSyncData , platform : string , opts ?: ISyncFilesOptions ) : Promise < FilesPayload > {
134- this . $logger . info ( `Start syncing changes for platform ${ platform } .` ) ;
135-
136- opts = opts || { } ;
137- let payloads = null ;
138-
139- try {
140- const { env, projectDir } = data ;
141- const projectData = this . $projectDataService . getProjectData ( projectDir ) ;
142- const platformData = this . $platformsData . getPlatformData ( platform , projectData ) ;
143-
144- if ( ! opts . skipPrepare ) {
145- await this . preparePlatform ( platform , data , env , projectData ) ;
146- }
147-
148- if ( opts . isInitialSync ) {
149- const platformsAppFolderPath = path . join ( platformData . appDestinationDirectoryPath , APP_FOLDER_NAME ) ;
150- opts . filesToSync = this . $projectFilesManager . getProjectFiles ( platformsAppFolderPath ) ;
151- payloads = this . getFilesPayload ( platformData , projectData , opts ) ;
152- this . $logger . info ( `Successfully synced changes for platform ${ platform } .` ) ;
153- } else {
154- opts . filesToSync = _ . map ( opts . filesToSync , file => this . $projectFilesProvider . mapFilePath ( file , platformData . normalizedPlatformName , projectData ) ) ;
155- payloads = this . getFilesPayload ( platformData , projectData , opts ) ;
156- await this . $previewSdkService . applyChanges ( payloads ) ;
157- this . $logger . info ( `Successfully synced ${ payloads . files . map ( filePayload => filePayload . file . yellow ) } for platform ${ platform } .` ) ;
158- }
159-
160- return payloads ;
161- } catch ( err ) {
162- this . $logger . warn ( `Unable to apply changes for platform ${ platform } . Error is: ${ err } , ${ JSON . stringify ( err , null , 2 ) } .` ) ;
163- }
164- }
165-
166- private getFilesPayload ( platformData : IPlatformData , projectData : IProjectData , opts ?: ISyncFilesOptions ) : FilesPayload {
167- const { filesToSync, filesToRemove, deviceId } = opts ;
168-
169- const filesToTransfer = filesToSync
170- . filter ( file => file . indexOf ( TNS_MODULES_FOLDER_NAME ) === - 1 )
171- . filter ( file => file . indexOf ( APP_RESOURCES_FOLDER_NAME ) === - 1 )
172- . filter ( file => ! _ . includes ( this . excludedFiles , path . basename ( file ) ) )
173- . filter ( file => ! _ . includes ( this . excludedFileExtensions , path . extname ( file ) ) ) ;
174-
175- this . $logger . trace ( `Transferring ${ filesToTransfer . join ( "\n" ) } .` ) ;
176-
177- const payloadsToSync = filesToTransfer . map ( file => this . createFilePayload ( file , platformData , projectData , PreviewSdkEventNames . CHANGE_EVENT_NAME ) ) ;
178- const payloadsToRemove = _ . map ( filesToRemove , file => this . createFilePayload ( file , platformData , projectData , PreviewSdkEventNames . UNLINK_EVENT_NAME ) ) ;
179- const payloads = payloadsToSync . concat ( payloadsToRemove ) ;
180-
181- const hmrMode = opts . useHotModuleReload ? 1 : 0 ;
182- return { files : payloads , platform : platformData . normalizedPlatformName . toLowerCase ( ) , hmrMode, deviceId } ;
183- }
184-
185- private async preparePlatform ( platform : string , data : IPreviewAppLiveSyncData , env : Object , projectData : IProjectData ) : Promise < void > {
186- const appFilesUpdaterOptions = {
187- bundle : data . bundle ,
188- useHotModuleReload : data . useHotModuleReload ,
189- release : false
190- } ;
191- const nativePrepare = { skipNativePrepare : true } ;
192- const config = < IPlatformOptions > { } ;
193- const platformTemplate = < string > null ;
194- const prepareInfo = {
195- platform,
196- appFilesUpdaterOptions,
197- env,
198- projectData,
199- nativePrepare,
200- config,
201- platformTemplate,
202- skipCopyTnsModules : true ,
203- skipCopyAppResourcesFiles : true
204- } ;
205- await this . $platformService . preparePlatform ( prepareInfo ) ;
206- }
207-
208155 private showWarningsForNativeFiles ( files : string [ ] ) : void {
209156 _ . filter ( files , file => file . indexOf ( APP_RESOURCES_FOLDER_NAME ) > - 1 )
210157 . forEach ( file => this . $logger . warn ( `Unable to apply changes from ${ APP_RESOURCES_FOLDER_NAME } folder. You need to build your application in order to make changes in ${ APP_RESOURCES_FOLDER_NAME } folder.` ) ) ;
211158 }
212-
213- private createFilePayload ( file : string , platformData : IPlatformData , projectData : IProjectData , event : string ) : FilePayload {
214- const projectFileInfo = this . $projectFilesProvider . getProjectFileInfo ( file , platformData . normalizedPlatformName , null ) ;
215- const binary = isTextOrBinary . isBinarySync ( file ) ;
216- let fileContents = "" ;
217- let filePath = "" ;
218-
219- if ( event === PreviewSdkEventNames . CHANGE_EVENT_NAME ) {
220- const relativePath = path . relative ( path . join ( platformData . appDestinationDirectoryPath , APP_FOLDER_NAME ) , file ) ;
221- filePath = path . join ( path . dirname ( relativePath ) , projectFileInfo . onDeviceFileName ) ;
222-
223- if ( binary ) {
224- const bitmap = < string > this . $fs . readFile ( file ) ;
225- const base64 = Buffer . from ( bitmap ) . toString ( 'base64' ) ;
226- fileContents = base64 ;
227- } else {
228- fileContents = this . $fs . readText ( path . join ( path . dirname ( projectFileInfo . filePath ) , projectFileInfo . onDeviceFileName ) ) ;
229- }
230- } else if ( event === PreviewSdkEventNames . UNLINK_EVENT_NAME ) {
231- filePath = path . relative ( path . join ( projectData . projectDir , APP_FOLDER_NAME ) , file ) ;
232- }
233-
234- const filePayload = {
235- event,
236- file : filePath ,
237- binary,
238- fileContents
239- } ;
240-
241- return filePayload ;
242- }
243159}
244160$injector . register ( "previewAppLiveSyncService" , PreviewAppLiveSyncService ) ;
0 commit comments