import Logger from '../../tools/env.logger' ; import * as Tools from '../../tools/index' ; import * as fs from 'fs' ; import { IService } from '../../interfaces/interface.service' ; type TFilename = string ; type TContent = string ; type TDestroyResolver = ( ) => void ; class description class ServiceFileWriter implements IService { private _logger : Logger = new Logger ( 'ServiceFileWriter' ) ; private _pending : Map < TFilename , TContent [ ] > = new Map ( ) ; private _destroy : TDestroyResolver | undefined ; private _writting : Map < TFilename , Promise < void > > = new Map ( ) ; returns public init ( ) { return new Promise ( ( resolve , reject ) => { resolve ( ) ; } ) ; } public destroy ( ) { return new Promise ( ( resolve ) => { this . _destroy = resolve ; this . _tryToDestroy ( ) ; } ) ; } public getName ( ) { return 'ServiceFileWriter' ; } public write ( filename , content ) { if ( this . _destroy !== undefined ) { return new Error ( this . _logger . warn ( `Data wouldn't be written into "${ filename }" because write service would be destroyed.` ) ) ; } if ( typeof filename !== 'string' || filename . trim ( ) === '' ) { return new Error ( this . _logger . warn ( `Not valid file name` ) ) ; } let pending = this . _pending . get ( filename ) ; const next = pending === undefined ; if ( pending === undefined ) { pending = [ ] ; } pending . push ( content ) ; this . _pending . set ( filename , pending ) ; if ( next ) { this . _next ( ) ; } } private _next ( ) { this . _pending . forEach ( ( _ , filename ) => { if ( this . _writting . has ( filename ) ) { return ; } const current = _ [ 0 ] ; this . _writting . set ( filename , this . _write ( filename , current ) . catch ( ( err ) => { this . _logger . error ( `Fail write data into "${ filename }" due error: ${ err . message }` ) ; } ) . finally ( ( ) => { this . _writting . delete ( filename ) ; const pendings = this . _pending . get ( filename ) ; if ( pendings === undefined ) { return ; } pendings . splice ( 0 , 1 ) ; if ( pendings . length === 0 ) { this . _pending . delete ( filename ) ; this . _tryToDestroy ( ) ; } else { this . _pending . set ( filename , pendings ) ; this . _next ( ) ; } } ) ) ; } ) ; } private _write ( filename , content ) { return new Promise ( ( resolve , reject ) => { fs . writeFile ( filename , content , ( error ) => { if ( error ) { reject ( error ) ; } else { resolve ( ) ; } } ) ; } ) ; } private _tryToDestroy ( ) { if ( this . _destroy === undefined ) { return ; } if ( this . _pending . size !== 0 ) { return ; } this . _destroy ( ) ; } } export default ( new ServiceFileWriter ( ) ) ;