const g = global as any ; export interface LevelDBIteratorI { seekToFirst ( ) : LevelDBIteratorI ; seekLast ( ) : LevelDBIteratorI ; seek ( target ) : LevelDBIteratorI ; valid ( ) : boolean ; next ( ) : void ; prev ( ) : void ; close ( ) : void ; keyStr ( ) : string ; keyBuf ( ) : ArrayBuffer ; valueStr ( ) : string ; valueBuf ( ) : ArrayBuffer ; } export interface LevelDBI { close ( ) : void ; closed ( ) : boolean ; put ( k , v ) : void ; delete ( k ) : void ; getStr ( k ) : null | string ; getBuf ( k ) : null | ArrayBuffer ; newIterator ( ) : LevelDBIteratorI ; } export class LevelDBIterator implements LevelDBIteratorI { private ref : number ; constructor ( dbRef ) { this . ref = g . leveldbNewIterator ( dbRef ) ; } seekToFirst ( ) { g . leveldbIteratorSeekToFirst ( this . ref ) ; return this ; } seekLast ( ) { g . leveldbIteratorSeekToLast ( this . ref ) ; return this ; } seek ( target ) { g . leveldbIteratorSeek ( this . ref , target ) ; return this ; } valid ( ) { return g . leveldbIteratorValid ( this . ref ) ; } next ( ) { g . leveldbIteratorNext ( this . ref ) ; } prev ( ) { g . leveldbIteratorPrev ( this . ref ) ; } close ( ) { g . leveldbIteratorDelete ( this . ref ) ; this . ref = - 1 ; } keyStr ( ) { return g . leveldbIteratorKeyStr ( this . ref ) ; } keyBuf ( ) { return g . leveldbIteratorKeyBuf ( this . ref ) ; } valueStr ( ) { return g . leveldbIteratorValueStr ( this . ref ) ; } valueBuf ( ) { return g . leveldbIteratorValueBuf ( this . ref ) ; } } export class LevelDB implements LevelDBI { private static openPathRefs : { [ name ] : undefined | number ; } = { } ; private ref : undefined | number ; public static async waitNativeModuleInitialized ( ) { for ( let i = 0 ; i < 2000 ; ++ i ) { if ( g . leveldbOpen ) { return true ; } await new Promise ( resolve => setTimeout ( resolve , 20 ) ) ; } return false ; } constructor ( name , createIfMissing , errorIfExists ) { if ( LevelDB . openPathRefs [ name ] !== undefined ) { this . ref = LevelDB . openPathRefs [ name ] ; } else { LevelDB . openPathRefs [ name ] = this . ref = g . leveldbOpen ( name , createIfMissing , errorIfExists ) ; } } close ( ) { g . leveldbClose ( this . ref ) ; for ( const name in LevelDB . openPathRefs ) { if ( LevelDB . openPathRefs [ name ] === this . ref ) { delete LevelDB . openPathRefs [ name ] ; } } this . ref = undefined ; } closed ( ) { return this . ref === undefined || ! Object . values ( LevelDB . openPathRefs ) . includes ( this . ref ) ; } put ( k , v ) { g . leveldbPut ( this . ref , k , v ) ; } delete ( k ) { g . leveldbDelete ( this . ref , k ) ; } getStr ( k ) { return g . leveldbGetStr ( this . ref , k ) ; } getBuf ( k ) { return g . leveldbGetBuf ( this . ref , k ) ; } newIterator ( ) { if ( this . ref === undefined ) { throw new Error ( 'LevelDB.newIterator: could not create iterator, the DB was closed!' ) ; } return new LevelDBIterator ( this . ref ) ; } merge ( src , batchMerge ) { if ( this . ref === undefined ) { throw new Error ( 'LevelDB.merge: could not merge, the dest DB (this) was closed!' ) ; } if ( src . ref === undefined ) { throw new Error ( 'LevelDB.merge: could not merge, the source DB was closed!' ) ; } g . leveldbMerge ( this . ref , src . ref , batchMerge ) ; } static destroyDB ( name , force ? ) { if ( LevelDB . openPathRefs [ name ] !== undefined ) { if ( force ) { g . leveldbClose ( LevelDB . openPathRefs [ name ] ) ; delete LevelDB . openPathRefs [ name ] ; } else { throw new Error ( 'DB is open! Cannot destroy' ) ; } } g . leveldbDestroy ( name ) ; } static readFileToBuf = g . leveldbReadFileBuf as ( path : string , pos : number , len : number ) => ArrayBuffer ; }