/**
 * Modified from bcoin's bdb (https://github.com/bcoin-org/bdb) (MIT LICENSE).
 * Credit to the original author, Christopher Jeffrey (https://github.com/chjj).
 */ import { BigNumber , bufferUtils , getLogger , ONE , ZERO } from '@pigi/core-utils' ; import { AbstractOpenOptions , AbstractLevelDOWN } from 'abstract-leveldown' ; import MemDown from 'memdown' ; import { RangeBucket , DB , K , V , Batch , IteratorOptions , Iterator , Bucket , } from '../types' ; import { BaseIterator } from './iterator' ; import { BaseBucket } from './bucket' ; import { BaseRangeBucket } from './range-bucket' ; const log = getLogger ( 'db' ) ; export const DEFAULT_PREFIX_LENGTH = 3 ; param err return const isNotFound = ( err ) : boolean => { if ( ! err ) { return false ; } return ( err . notFound || err . type === 'NotFoundError' || /not\s*found/i . test ( err . message ) ) ; } ; /**
 * Basic DB implementation that wraps some underlying store.
 */ export class BaseDB implements DB { constructor ( readonly db , readonly prefixLength = DEFAULT_PREFIX_LENGTH ) { } param options public async open ( options ? ) { try { await new Promise < void > ( ( resolve , reject ) => { this . db . open ( options , ( err ) => { if ( err ) { reject ( err ) ; log . error ( `Error opening DB: ${ err . message }, ${ err . stack }` ) ; return ; } resolve ( ) ; } ) ; } ) ; } catch ( err ) { throw err ; } } /**
     * Closes the store.
     */ public async close ( ) { try { await new Promise < void > ( ( resolve , reject ) => { this . db . close ( ( err ) => { if ( err ) { reject ( err ) ; log . error ( `Error closing DB: ${ err . message }, ${ err . stack }` ) ; return ; } resolve ( ) ; } ) ; } ) ; } catch ( err ) { throw err ; } } param key returns public async get ( key ) { return new Promise < V > ( ( resolve , reject ) => { this . db . get ( key , ( err , value ) => { if ( err ) { if ( isNotFound ( err ) ) { log . debug ( `Key ${ key . toString ( 'hex' ) } not found.` ) ; resolve ( null ) ; return ; } reject ( err ) ; log . error ( `Error getting key ${ key . toString ( 'hex' ) }: ${ err . message }, ${ err . stack }` ) ; return ; } resolve ( value ) ; } ) ; } ) ; } param key param value public async put ( key , value ) { return new Promise < void > ( ( resolve , reject ) => { this . db . put ( key , value , ( err ) => { if ( err ) { reject ( err ) ; log . error ( `Error putting key / value ${ key . toString ( 'hex' ) } / ${ value . toString ( 'hex' ) }: ${ err . message }, ${ err . stack }` ) ; return ; } resolve ( ) ; } ) ; } ) ; } param key public async del ( key ) { return new Promise < void > ( ( resolve , reject ) => { this . db . del ( key , ( err ) => { if ( err ) { reject ( err ) ; log . error ( `Error deleting key ${ key . toString ( 'hex' ) }: ${ err . message }, ${ err . stack }` ) ; return ; } resolve ( ) ; } ) ; } ) ; } param key returns public async has ( key ) { try { await this . get ( key ) ; return true ; } catch ( err ) { log . error ( `Error checking key existence: key ${ key . toString ( 'hex' ) }: ${ err . message }, ${ err . stack }` ) ; return false ; } } param operations public async batch ( operations ) { return new Promise < void > ( ( resolve , reject ) => { this . db . batch ( operations , ( err ) => { if ( err ) { reject ( err ) ; log . error ( `Error executing batch operation: ${ err . message }, ${ err . stack }` ) ; return ; } resolve ( ) ; } ) ; } ) ; } param options returns public iterator ( options ? ) { return new BaseIterator ( this , options ) ; } param prefix returns public bucket ( prefix ) { return new BaseBucket ( this , bufferUtils . padLeft ( prefix , this . prefixLength ) ) ; } param prefix returns public rangeBucket ( prefix ) { return new BaseRangeBucket ( this , bufferUtils . padLeft ( prefix , this . prefixLength ) ) ; } } let memId = ZERO ; export const newInMemoryDB = ( prefixLength = 256 , options ? ) : DB => { memId = memId . add ( ONE ) ; return new BaseDB ( new MemDown ( `newInMemoryDB/${ memId . toString ( ) }` ) as any , prefixLength ) ; } ;