@@ -103,7 +103,7 @@ export abstract class EntityCollection <A extends EntityBaseAttribute, T extends
103103 if ( result == 0 ) {
104104 return ContainsType . yesSameVersion ;
105105 } else if ( result == 1 ) return ContainsType . yesVersionSmaller ;
106- return ContainsType . yesMoreVersion ;
106+ return ContainsType . yesNewerVersion ;
107107 }
108108
109109 public SelectByEndDeviceArchitecture ( endDeviceArchitecture ?:string ) :Array < T >
@@ -123,7 +123,7 @@ export abstract class EntityCollection <A extends EntityBaseAttribute, T extends
123123 return this . _items . get ( idEntity ) ;
124124 }
125125
126- protected async LoadFromFolder ( pathFolder :string , type :EntityType ) :Promise < IotResult >
126+ protected async LoadEntitiesFromFolder ( pathFolder :string , type :EntityType ) :Promise < IotResult >
127127 {
128128 let result :IotResult ;
129129 try {
@@ -144,7 +144,7 @@ export abstract class EntityCollection <A extends EntityBaseAttribute, T extends
144144 let dir :string ;
145145 for ( let i = 0 ; i < listFolders . length ; i ++ ) {
146146 dir = listFolders [ i ] ;
147- await this . ImportEntity ( dir , type ) ;
147+ await this . LoadOneEntityFromFolder ( dir , type ) ;
148148 }
149149 //result
150150 if ( ( this . Count - entitysCountBegin ) > 0 ) {
@@ -160,14 +160,45 @@ export abstract class EntityCollection <A extends EntityBaseAttribute, T extends
160160 return Promise . resolve ( result ) ;
161161 }
162162
163- protected async ImportEntity ( dir :string , type :EntityType ) :Promise < IotResult >
163+ protected async ImportEntityFromZip ( fileZipPath :string , type :EntityType ) :Promise < IotResult >
164+ {
165+ let result :IotResult ;
166+ //unpack to current dir
167+ let unpackDir = path . join ( path . dirname ( fileZipPath ) , path . parse ( fileZipPath ) . name ) ;
168+ try {
169+ result = IoTHelper . UnpackFromZip ( fileZipPath , unpackDir ) ;
170+ if ( result . Status != StatusResult . Ok ) return Promise . resolve ( result ) ;
171+ //test
172+ result = await this . LoadOneEntityFromFolder ( unpackDir , type , true ) ;
173+ if ( result . Status != StatusResult . Ok ) return Promise . resolve ( result ) ;
174+ //move
175+ let entity :T ;
176+ entity = < T > result . returnObject ;
177+ result = entity . Move ( this . GetDirEntitiesCallback ( type ) ) ;
178+ if ( result . Status != StatusResult . Ok ) return Promise . resolve ( result ) ;
179+ //add
180+ unpackDir = < string > result . returnObject ;
181+ result = await this . LoadOneEntityFromFolder ( unpackDir , type ) ;
182+ } catch ( err : any ) {
183+ result = new IotResult ( StatusResult . Error , `${ this . _entityLabel } import error. File: ${ fileZipPath } , type ${ type } .` , err ) ;
184+ //clear
185+ if ( fs . existsSync ( unpackDir ) ) {
186+ fs . emptyDirSync ( unpackDir ) ;
187+ fs . removeSync ( unpackDir ) ;
188+ }
189+ }
190+ //result
191+ return Promise . resolve ( result ) ;
192+ }
193+
194+ protected async LoadOneEntityFromFolder ( dir :string , type :EntityType , isTest :boolean = false ) :Promise < IotResult >
164195 {
165196 let result :IotResult ;
166197 try {
167198 const filePath = `${ dir } \\${ this . _entityLabel . toLowerCase ( ) } .fastiot.yaml` ;
168199 let entity = new this . TCreator ( this . Config . schemasFolderPath ) ;
169200 entity . Init ( type , filePath , this . Config . recoverySourcePath ) ;
170- if ( ! entity . IsValid && type == EntityType . system ) {
201+ if ( ! isTest && ! entity . IsValid && type == EntityType . system ) {
171202 //Recovery
172203 this . CreateEvent ( `${ this . _entityLabel } recovery: ${ path . dirname ( filePath ) } ` , LogLevel . Debug ) ;
173204 result = entity . Recovery ( ) ;
@@ -179,20 +210,26 @@ export abstract class EntityCollection <A extends EntityBaseAttribute, T extends
179210 }
180211 //main
181212 if ( entity . IsValid ) {
182- this . CreateEvent ( `${ this . _entityLabel } is valid: [${ entity . Attributes . Id } ]` , LogLevel . Debug ) ;
213+ if ( ! isTest ) this . CreateEvent ( `${ this . _entityLabel } is valid: [${ entity . Attributes . Id } ]` , LogLevel . Debug ) ;
183214 if ( this . IsCompatibleByVersionExtAndPlatform ( entity ) ) {
184215 const isContains = this . Contains ( entity ) ;
185216 switch ( isContains ) {
186217 case ContainsType . no : {
187- this . Add ( entity ) ;
188- this . CreateEvent ( `${ this . _entityLabel } added: [${ entity . Attributes . Id } ] ${ entity . RootDir } ` , LogLevel . Debug ) ;
218+ if ( ! isTest ) {
219+ this . Add ( entity ) ;
220+ this . CreateEvent ( `${ this . _entityLabel } added: [${ entity . Attributes . Id } ] ${ entity . RootDir } ` , LogLevel . Debug ) ;
221+ }
189222 result = new IotResult ( StatusResult . Ok , `${ this . _entityLabel } added: [${ entity . Attributes . Id } ] ${ entity . RootDir } ` ) ;
223+ result . returnObject = entity ;
190224 break ;
191225 }
192226 case ContainsType . yesVersionSmaller : {
193- this . Update ( entity ) ;
194- this . CreateEvent ( `${ this . _entityLabel } updated: [${ entity . Attributes . Id } ] ${ entity . RootDir } ` , LogLevel . Debug ) ;
227+ if ( ! isTest ) {
228+ this . Update ( entity ) ;
229+ this . CreateEvent ( `${ this . _entityLabel } updated: [${ entity . Attributes . Id } ] ${ entity . RootDir } ` , LogLevel . Debug ) ;
230+ }
195231 result = new IotResult ( StatusResult . Ok , `${ this . _entityLabel } updated: [${ entity . Attributes . Id } ] ${ entity . RootDir } ` ) ;
232+ result . returnObject = entity ;
196233 break ;
197234 }
198235 default : {
@@ -211,19 +248,20 @@ export abstract class EntityCollection <A extends EntityBaseAttribute, T extends
211248 this . CreateEvent ( result ) ;
212249 this . CreateEvent ( entity . ValidationErrorsToString , LogLevel . Debug ) ;
213250 //delete system entity
214- if ( type == EntityType . system ) {
251+ if ( ! isTest && type == EntityType . system ) {
215252 result = entity . Remove ( ) ;
216253 this . CreateEvent ( result , LogLevel . Debug ) ;
217254 }
218255 }
219256 } catch ( err : any ) {
220- result = new IotResult ( StatusResult . Error , `Error import ${ type } ${ this . _entitiesLabel } dir ${ dir } ` , err ) ;
257+ result = new IotResult ( StatusResult . Error , `Error load ${ type } ${ this . _entitiesLabel } dir ${ dir } ` , err ) ;
221258 }
222259 return Promise . resolve ( result ) ;
223260 }
224261
225262 protected async UpdateEntitiesFromUrl ( url :string , type :EntityType ) :Promise < IotResult >
226263 {
264+ //download list
227265 const destPath = this . GetDirEntitiesCallback ( type ) ;
228266 let downloader = new EntityDownloader ( ) ;
229267 let result :IotResult ;
@@ -239,72 +277,47 @@ export abstract class EntityCollection <A extends EntityBaseAttribute, T extends
239277 result = new IotResult ( StatusResult . Ok , `Url: ${ url } . No ${ this . _entitiesLabel } to download` ) ;
240278 return Promise . resolve ( result ) ;
241279 }
242- //next
280+ //filter
243281 let index :number = 0 ;
244282 do {
245283 let item = listDownload [ index ] ;
246284 if ( item ) {
247- //parse
248- if ( this . IsCompatibleByVersionExtAndPlatform2 ( item . ForVersionExt , item . platform ) ) {
249- const isContains = this . Contains2 ( item . Id , EntityType . system , item . Version ) ;
250- switch ( isContains ) {
251- case ContainsType . no : {
252- result = await downloader . DownloadEntity ( item , this . Config . tempFolderPath ) ;
253- if ( result . Status == StatusResult . Ok ) {
254- const unpackPath = < string > result . returnObject ;
255- const filePath = path . join ( unpackPath , `${ this . _entityLabel . toLowerCase ( ) } .fastiot.yaml` ) ;
256- let entity = new this . TCreator ( this . Config . schemasFolderPath ) ;
257- entity . Init ( EntityType . system , filePath ) ;
258- if ( entity . IsValid ) {
259- result = entity . Move ( path . join ( destPath , entity . Attributes . Id ) ) ;
260- if ( result . Status == StatusResult . Error ) {
261- this . CreateEvent ( result , LogLevel . Debug ) ;
262- break ;
263- }
264- this . Add ( entity ) ;
265- this . CreateEvent ( `${ this . _entityLabel } added/updated: [${ entity . Attributes . Id } ] ${ entity . RootDir } ` , LogLevel . Debug ) ;
266- } else {
267- result = new IotResult ( StatusResult . Error , `The ${ this . _entityLabel } ${ entity . YAMLFilePath } has not been validated` )
268- this . CreateEvent ( result , LogLevel . Debug ) ;
269- this . CreateEvent ( entity . ValidationErrorsToString , LogLevel . Debug ) ;
270- }
271- }
272- break ;
273- }
274- case ContainsType . yesVersionSmaller : {
275- result = await downloader . DownloadEntity ( item , this . Config . tempFolderPath ) ;
276- if ( result . Status == StatusResult . Ok ) {
277- const unpackPath = < string > result . returnObject ;
278- const filePath = path . join ( unpackPath , ` ${ this . _entityLabel . toLowerCase ( ) } .fastiot.yaml` ) ;
279- let entity = new this . TCreator ( this . Config . schemasFolderPath ) ;
280- entity . Init ( EntityType . system , filePath ) ;
281- if ( entity . IsValid ) {
282- result = entity . Move ( path . join ( destPath , entity . Attributes . Id ) ) ;
283- if ( result . Status == StatusResult . Error ) {
284- this . CreateEvent ( result , LogLevel . Debug ) ;
285- break ;
286- }
287- this . Update ( entity ) ;
288- this . CreateEvent ( `${ this . _entityLabel } added/updated: [${ entity . Attributes . Id } ] ${ entity . RootDir } ` , LogLevel . Debug ) ;
289- } else {
290- result = new IotResult ( StatusResult . Error , `The ${ this . _entityLabel } ${ entity . YAMLFilePath } has not been validated` )
291- this . CreateEvent ( result , LogLevel . Debug ) ;
292- this . CreateEvent ( entity . ValidationErrorsToString , LogLevel . Debug ) ;
293- }
294- }
295- }
296- default : {
297- //statements;
298- break ;
299- }
300- }
301- } else {
302- result = new IotResult ( StatusResult . Error , `Error. The ${ this . _entityLabel } ${ item . Url } is for a newer version of the extension. ` +
303- `Update the extension.` ) ;
285+ //check
286+ if ( this . IsCompatibleByVersionExtAndPlatform2 ( item . ForVersionExt , item . platform ) ) {
287+ const isContains = this . Contains2 ( item . Id , EntityType . system , item . Version ) ;
288+ if ( isContains == ContainsType . yesSameVersion || isContains == ContainsType . yesNewerVersion ) {
289+ //remove
290+ listDownload . splice ( index , 1 ) ;
291+ index -- ;
292+ }
293+ } else {
294+ //remove
295+ listDownload . splice ( index , 1 ) ;
296+ index -- ;
297+ }
298+ } else break ;
299+ index ++ ;
300+ } while ( true )
301+ //add entities
302+ index = 0 ;
303+ do {
304+ let item = listDownload [ index ] ;
305+ if ( ! item ) break ; // exit do
306+ //download entity
307+ result = await downloader . DownloadEntity ( item , this . Config . tempFolderPath ) ;
308+ this . CreateEvent ( result , LogLevel . Debug ) ;
309+ //add entity
310+ if ( result . Status == StatusResult . Ok ) {
311+ const fileZipPath = < string > result . returnObject ;
312+ result = await this . ImportEntityFromZip ( fileZipPath , type ) ;
313+ if ( result . Status == StatusResult . Ok ) {
314+ //delete zip
315+ fs . removeSync ( fileZipPath ) ;
316+ } else {
304317 this . CreateEvent ( result , LogLevel . Debug ) ;
305318 }
306- //
307- } else break ;
319+ }
320+ //next index
308321 index ++ ;
309322 } while ( true )
310323 //result
@@ -337,11 +350,11 @@ export abstract class EntityCollection <A extends EntityBaseAttribute, T extends
337350 return Promise . resolve ( result ) ;
338351 }
339352
340- protected async LoadEntities ( type :EntityType ) :Promise < void >
353+ protected async LoadEntitiesByType ( type :EntityType ) :Promise < void >
341354 {
342355 this . CreateEvent ( `☑️ Loading ${ type } ${ this . _entitiesLabel } ` , LogLevel . Debug ) ;
343356 const path = this . GetDirEntitiesCallback ( type ) ;
344- const result = await this . LoadFromFolder ( path , type ) ;
357+ const result = await this . LoadEntitiesFromFolder ( path , type ) ;
345358 this . CreateEvent ( result , LogLevel . Debug ) ;
346359 }
347360
@@ -357,7 +370,7 @@ export abstract class EntityCollection <A extends EntityBaseAttribute, T extends
357370 LogLevel . Information ) ;
358371 //Loading system entities
359372 this . CreateEvent ( `Loading system ${ this . _entitiesLabel } ` , undefined , 15 ) ; //15
360- await this . LoadEntities ( EntityType . system ) ;
373+ await this . LoadEntitiesByType ( EntityType . system ) ;
361374 //Updating system entities
362375 this . CreateEvent ( `Updating system ${ this . _entitiesLabel } ` , undefined , 15 ) ; //30
363376 //To get the number of hours since Unix epoch, i.e. Unix timestamp:
@@ -379,7 +392,7 @@ export abstract class EntityCollection <A extends EntityBaseAttribute, T extends
379392 }
380393 //Loading community entities
381394 this . CreateEvent ( `Loading community ${ this . _entitiesLabel } ` , undefined , 15 ) ; //45
382- await this . LoadEntities ( EntityType . community ) ;
395+ await this . LoadEntitiesByType ( EntityType . community ) ;
383396 //Updating community entities
384397 this . CreateEvent ( `Updating community ${ this . _entitiesLabel } ` , undefined , 15 ) ; //60
385398 if ( force || isNeedUpdate ( ) ) {
@@ -395,7 +408,7 @@ export abstract class EntityCollection <A extends EntityBaseAttribute, T extends
395408 }
396409 //Loading custom entities
397410 this . CreateEvent ( `Loading custom ${ this . _entitiesLabel } templates loaded ` , undefined , 15 ) ; //75
398- await this . LoadEntities ( EntityType . user ) ;
411+ await this . LoadEntitiesByType ( EntityType . user ) ;
399412 //result
400413 this . CreateEvent ( new IotResult ( StatusResult . Ok , `${ this . _entitiesLabel } loaded` ) ) ;
401414 const endMsg = `📚 ${ this . Count } ${ this . _entityLabel } (s) available.` ;
0 commit comments