import { IStorageProvider } from "./IStorageProvider" ; import { IFilterInfo } from "../IFilter" ; import * as lowdb from "lowdb" ; import * as FileSync from "lowdb/adapters/FileSync" ; import { IAppserviceStorageProvider } from "./IAppserviceStorageProvider" ; import * as sha512 from "hash.js/lib/hash/sha/512" ; import * as mkdirp from "mkdirp" ; import * as path from "path" ; category export class SimpleFsStorageProvider implements IStorageProvider , IAppserviceStorageProvider { private db : any ; private completedTransactions = [ ] ; param { string } filename param { boolean } trackTransactionsInMemory param { int } maxInMemoryTransactions constructor ( filename , private trackTransactionsInMemory = true , private maxInMemoryTransactions = 20 ) { mkdirp . sync ( path . dirname ( filename ) ) ; const adapter = new FileSync ( filename ) ; this . db = lowdb ( adapter ) ; this . db . defaults ( { syncToken : null , filter : null , appserviceUsers : { } , appserviceTransactions : { } , kvStore : { } , } ) . write ( ) ; } setSyncToken ( token ) { this . db . set ( 'syncToken' , token ) . write ( ) ; } getSyncToken ( ) { return this . db . get ( 'syncToken' ) . value ( ) ; } setFilter ( filter ) { this . db . set ( 'filter' , filter ) . write ( ) ; } getFilter ( ) { return this . db . get ( 'filter' ) . value ( ) ; } addRegisteredUser ( userId ) { const key = sha512 ( ) . update ( userId ) . digest ( 'hex' ) ; this . db . set ( `appserviceUsers.${ key }.userId` , userId ) . set ( `appserviceUsers.${ key }.registered` , true ) . write ( ) ; } isUserRegistered ( userId ) { const key = sha512 ( ) . update ( userId ) . digest ( 'hex' ) ; return this . db . get ( `appserviceUsers.${ key }.registered` ) . value ( ) ; } isTransactionCompleted ( transactionId ) { if ( this . trackTransactionsInMemory ) { return this . completedTransactions . indexOf ( transactionId ) !== - 1 ; } const key = sha512 ( ) . update ( transactionId ) . digest ( 'hex' ) ; return this . db . get ( `appserviceTransactions.${ key }.completed` ) . value ( ) ; } setTransactionCompleted ( transactionId ) { if ( this . trackTransactionsInMemory ) { if ( this . completedTransactions . indexOf ( transactionId ) === - 1 ) { this . completedTransactions . push ( transactionId ) ; } if ( this . completedTransactions . length > this . maxInMemoryTransactions ) { this . completedTransactions = this . completedTransactions . reverse ( ) . slice ( 0 , this . maxInMemoryTransactions ) . reverse ( ) ; } return ; } const key = sha512 ( ) . update ( transactionId ) . digest ( 'hex' ) ; this . db . set ( `appserviceTransactions.${ key }.txnId` , transactionId ) . set ( `appserviceTransactions.${ key }.completed` , true ) . write ( ) ; } readValue ( key ) { return this . db . get ( "kvStore" ) . value ( ) [ key ] ; } storeValue ( key , value ) { const kvStore = this . db . get ( "kvStore" ) . value ( ) ; kvStore [ key ] = value ; this . db . set ( "kvStore" , kvStore ) . write ( ) ; } storageForUser ( userId ) { return new NamespacedFsProvider ( userId , this ) ; } } category class NamespacedFsProvider implements IStorageProvider { constructor ( private prefix , private parent ) { } setFilter ( filter ) { return this . parent . storeValue ( `${ this . prefix }_int_filter` , JSON . stringify ( filter ) ) ; } getFilter ( ) { return Promise . resolve ( this . parent . readValue ( `${ this . prefix }_int_filter` ) ) . then ( r => r ? JSON . parse ( r ) : r ) ; } setSyncToken ( token ) { return this . parent . storeValue ( `${ this . prefix }_int_syncToken` , token ) ; } getSyncToken ( ) { return Promise . resolve ( this . parent . readValue ( `${ this . prefix }_int_syncToken` ) ) . then ( r => r ?? null ) ; } readValue ( key ) { return this . parent . readValue ( `${ this . prefix }_kv_${ key }` ) ; } storeValue ( key , value ) { return this . parent . storeValue ( `${ this . prefix }_kv_${ key }` , value ) ; } }