Home Reference Source Test

packages/causality-core/src/store.js

/**
 * class Store is the primitive class for composing higher storage class.
 * This class wrap [levelup](https://www.tensorflow.org/js) 
 * for connect with abstract-leveldown compliant stores.
 * @class Store
 */
export default class Store{
    
    constructor(){
        this.levelup = require('levelup');
        this.logger = console;
    }
    
    async connect(){
        throw Error('implement required');
    }

    /**
     * Get item given the key
     * @param { String } key - key name
     * @param {boolean} [asBuffer=false] - return object or buffer array, default object
     * @returns { Object } item object 
     */
    async getItem(key, asBuffer=false, noError=false){
        if(!this.store){
            throw Error('store is not connect');
        }
        return new Promise((resolve, reject)=>{
            this.store.get(key, {asBuffer}, (err, data)=>{
                if(err){
                    if(noError){
                        resolve({[key]: null});
                    }
                    else{
                        this.logger.debug({key, err});
                        reject('error read');
                    }
                }
                else{
                    resolve({[key]: data});
                }
            });
        });
    }
    /**
     * Set new item with the given key and value
     * @param { String } key - key name of item
     * @param { Object } data - value of item
     * @returns { Promise } - new key promise
     * @memberof MemoryCache
     */
    async setItem(key, data, noError=false){
        if(!this.store){
            throw Error('store is not connect');
        }
        return new Promise((resolve, reject)=>{
            this.store.put(key, data, (err)=>{
                if(err){
                    if(noError){
                        resolve({[key]: null});
                    }
                    else{
                        this.logger.debug({key, err});
                        reject('error write');
                    }
                }
                else{
                    resolve({[key]: data});
                }
            });
        });
    }
    /**
     * Delete item given the item key
     * @param { String } key - key name to delete
     * @returns { Promise } deleted key promise
     * @memberof MemoryCache
     */
    async delItem(key, noError=false){
        if(!this.store){
            throw Error('store is not connect');
        }
        return new Promise((resolve, reject)=>{
            this.store.del(key, (err)=>{
                if(err){
                    if(noError){
                        resolve(null);
                    }
                    else{
                        this.logger.debug(err);
                        reject(`error delete ${key}`);
                    }
                }
                else{
                    resolve(key);
                }
            });
        });
    }
    /**
     * Make name maching function based on prefix path
     * @param { String } pattern - prefix name
     * @returns { Function } name matching function
     * @memberof MemoryCache
     */
    makeCheckItemNameFn(pattern){
        var regex = new RegExp(`${pattern}.*`,'g');
        return (fileName)=>fileName.match(regex) || [];
    }
    
    /**
     * Get the current items under the prefix path
     * @param { String } namePrefix
     * @returns { Array } list of item names
     * @memberof MemoryCache
     */
    async getItemList(namePrefix, noError=false){
        if(!this.store){
            throw Error('store is not connect');
        }
        const NameTester = this.makeCheckItemNameFn(namePrefix);
        return new Promise((resolve, reject)=>{
            let fileList = [];
            this.store.createKeyStream()
                .on('data', (key) =>{
                    key = key.toString('utf8');
                    if(NameTester(key).length===1){
                        fileList.push(key);
                    }
                })
                .on('close', () => resolve(fileList) )
                .on('end',  () => resolve(fileList) )
                .on('error', (err) =>{ 
                    if(noError){
                        resolve(fileList);
                    }
                    else{
                        this.logger.debug( err );
                        reject(`error getItemList ${namePrefix}`);
                    }
                });
        });
    }
}