import csv from 'csvtojson' ; import path from 'path' ; import fs from 'fs' ; import CaseInformation from '../CaseInformation' ; import FacilityInformation from '../FacilityInformation' ; import { filterLatestFacilityData } from '../utils/helper' ; class CSVDatabase { isConverting ! : boolean ; csvClass : CaseInformation | FacilityInformation | unknown ; CSVDatabaseArray ! : ( CaseInformation | FacilityInformation ) [ ] ; csvFilePath ! : string ; converter : any ; async init ( CsvClass ) { this . isConverting = false ; this . csvClass = CsvClass ; this . CSVDatabaseArray = [ ] ; let tmpPath = '../../tmp' ; if ( process . env . NODE_ENV === 'production' ) tmpPath = '../tmp' ; if ( this . csvClass instanceof CaseInformation ) { this . csvFilePath = path . join ( __dirname , `${ tmpPath }/${ CaseInformation . getFilename ( ) }` ) ; } else if ( this . csvClass instanceof FacilityInformation ) { this . csvFilePath = path . join ( __dirname , `${ tmpPath }/${ FacilityInformation . getFilename ( ) }` ) ; } else { throw Error ( 'CSVDatabase type not found' ) ; } await this . convertCsvToJson ( ) ; return this ; } return { Promise < Converter > } assureCSIsLoaded ( ) { return this . converter ; } return { Promise < Converter > } async convertCsvToJson ( ) { if ( ! this . isConverting ) { this . isConverting = true ; const pathToCSV = this . csvFilePath ; let dateThreshold = new Date ( ) ; dateThreshold = dateThreshold . setDate ( dateThreshold . getDate ( ) - ( parseInt ( process . env . FACILITIES_THRESHOLD as string , 10 ) || 360 ) ) ; let msg = process . env . FACILITIES_THRESHOLD || 'facilities threshold not found in .env, setting to 360' ; msg += '\nIf this causes Out of memory error lower the value to 7 or 30' ; console . log ( 'Facilities Threshold: ' , msg ) ; const isFacilityInfo = ( this . csvClass instanceof FacilityInformation ) ; const isCaseInfo = ( this . csvClass instanceof CaseInformation ) ; const updatedDateIndex = 3 ; if ( fs . existsSync ( pathToCSV ) ) { this . converter = csv ( { trim : true , } ) . fromFile ( pathToCSV ) . preFileLine ( async ( fileLineString ) => { if ( isFacilityInfo ) { const newFileLineString = ( fileLineString ) . split ( ',' ) ; const upDate = new Date ( newFileLineString [ updatedDateIndex ] ) ; if ( upDate < ( dateThreshold ) ) return ( '' ) ; return ( newFileLineString . join ( ',' ) ) ; } if ( isCaseInfo ) { return ( fileLineString ) ; } throw Error ( 'Cannot determine csv data type while parsing csv file.' ) ; } ) . then ( ( json ) => { json . forEach ( ( row ) => { let c ; if ( this . csvClass instanceof FacilityInformation ) { c = new FacilityInformation ( ) ; if ( row . updateddate !== '' ) { Object . assign ( c , row ) ; this . CSVDatabaseArray . push ( c ) ; } } else if ( this . csvClass instanceof CaseInformation ) { c = new CaseInformation ( ) ; Object . assign ( c , row ) ; this . CSVDatabaseArray . push ( c ) ; } else { throw Error ( 'Cannot determine csv type for updateddate' ) ; } } ) ; } ) . then ( ( ) => { if ( this . CSVDatabaseArray [ 0 ] instanceof CaseInformation ) { console . log ( 'CaseInformation CSV loaded' ) ; return true ; } if ( this . CSVDatabaseArray [ 0 ] instanceof FacilityInformation ) { console . log ( 'FacilityInformation CSV loaded' ) ; console . log ( 'Grouping results by latest updateddate...' ) ; this . CSVDatabaseArray = filterLatestFacilityData ( this . CSVDatabaseArray ) ; console . log ( 'Grouping done!' ) ; return true ; } throw Error ( '[CSVDatabase.js]Cannot determine csv data type.' ) ; } , ( err ) => console . log ( err ) ) ; return this . converter ; } this . isConverting = false ; console . error ( `Cannot find ${ this . csvFilePath }, Did you visit "/api/updateDatabase"?` ) ; } return null ; } param { String } field param { String } value async filter ( field , value ) { await this . assureCSIsLoaded ( ) ; return this . CSVDatabaseArray . filter ( ( ci ) => ci [ field ] == value ) ; } param { int } size return { Promise < [ CaseInformation ] | [ FacilityInformation ] > } async get ( size = this . getSize ( ) ) { await this . assureCSIsLoaded ( ) ; return this . CSVDatabaseArray . slice ( 0 , await size ) ; } return { int } async getSize ( ) { await this . assureCSIsLoaded ( ) ; return this . CSVDatabaseArray . length ; } param { String } field return { Promise < [ CaseInformation ] > } async sort ( field ) { const cs = await this . get ( ) ; return cs . sort ( this . getSortOrder ( field ) ) ; } param { String } property return { Function } getSortOrder = ( property ) => ( a , b ) => { if ( a [ property ] > b [ property ] ) { return 1 ; } if ( a [ property ] < b [ property ] ) { return - 1 ; } return 0 ; } ; param { [ CaseInformation ] } csArr param { String } caseCode return { int } findIndex = ( csArr , caseCode ) => csArr . findIndex ( ( cs ) => cs . CaseCode == caseCode ) ; } export default CSVDatabase ;