Source: sources/cores/TStore.js

import {
    isFunction,
    isNotArray,
    isNotBoolean,
    isNotObject,
    isNotUndefined,
    isNull,
    isString,
    isUndefined
} from 'itee-validators'

/**
 * @class
 * @classdesc TStore is a simple javascript object whose purpose is to store some ket/value data to future usage. It could be enable/disable.
 *
 * @example {@lang javascript}
 * var cache = new TCache()
 * cache.add( 'foo', 'bar' )
 * TLogger.log( cache.get('foo') ) // 'bar'
 *
 * @author [Tristan Valcke]{@link https://github.com/Itee}
 * @license [BSD-3-Clause]{@link https://opensource.org/licenses/BSD-3-Clause}
 */
class TStore {

    /**
     *
     * @param value
     * @param validators
     * @private
     */
    static _validate ( value, validators ) {

        for ( let validatorIndex = 0, numberOfValidators = validators.length ; validatorIndex < numberOfValidators ; validatorIndex++ ) {

            let validator = validators[ validatorIndex ]

            if ( !validator.validator( value ) ) {

                const error = validator.error
                if ( isString( error ) ) {
                    throw new TypeError( error )
                } else if ( isFunction( error ) ) {
                    throw new TypeError( error( value ) )
                } else {
                    throw new TypeError( `${ value } is invalid.` )
                }

            }

        }

    }
    /**
     * @constructor
     * @param {Object} [parameters={}]
     * @param {Object} [parameters.collection={}]
     * @param {Boolean} [parameters.allowOverride=false]
     * @param {Array.<function>} [parameters.keyValidators=[]]
     * @param {Array.<function>} [parameters.valueValidators=[]]
     */
    constructor ( parameters = {} ) {

        const _parameters = {
            ...{
                collection:      {},
                allowOverride:   false,
                keyValidators:   [],
                valueValidators: []
            }, ...parameters
        }

        this.collection      = _parameters.collection
        this.allowOverride   = _parameters.allowOverride
        this.keyValidators   = _parameters.keyValidators
        this.valueValidators = _parameters.valueValidators

    }
    /**
     *
     * @return {{}}
     */
    get collection () {

        return this._collection

    }
    set collection ( value ) {

        const memberName = 'Collection'
        const expect     = 'Expect an object.'

        if ( isNull( value ) ) { throw new TypeError( `${ memberName } cannot be null ! ${ expect }` ) }
        if ( isUndefined( value ) ) { throw new TypeError( `${ memberName } cannot be undefined ! ${ expect }` ) }
        if ( isNotObject( value ) ) { throw new TypeError( `${ memberName } cannot be an instance of ${ value.constructor.name } ! ${ expect }` ) }

        this._collection = value

    }
    /**
     *
     * @return {*}
     */
    get allowOverride () {

        return this._allowOverride

    }
    set allowOverride ( value ) {

        const memberName = 'Allow override'
        const expect     = 'Expect a boolean.'

        if ( isNull( value ) ) { throw new TypeError( `${ memberName } cannot be null ! ${ expect }` ) }
        if ( isUndefined( value ) ) { throw new TypeError( `${ memberName } cannot be undefined ! ${ expect }` ) }
        if ( isNotBoolean( value ) ) { throw new TypeError( `${ memberName } cannot be an instance of ${ value.constructor.name } ! ${ expect }` ) }

        this._allowOverride = value

    }
    /**
     *
     * @return {*}
     */
    get keyValidators () {

        return this._keyValidators

    }
    set keyValidators ( value ) {

        const memberName = 'Keys validators'
        const expect     = 'Expect an array of TValidator or an empty array.'

        if ( isNull( value ) ) { throw new TypeError( `${ memberName } cannot be null ! ${ expect }` ) }
        if ( isUndefined( value ) ) { throw new TypeError( `${ memberName } cannot be undefined ! ${ expect }` ) }
        if ( isNotArray( value ) ) { throw new TypeError( `${ memberName } cannot be an instance of ${ value.constructor.name } ! ${ expect }` ) }

        this._keyValidators = value

    }
    /**
     *
     * @return {*}
     */
    get valueValidators () {
        return this._valueValidators
    }
    set valueValidators ( value ) {

        const memberName = 'Values validators'
        const expect     = 'Expect an array of TValidator or an empty array.'

        if ( isNull( value ) ) { throw new TypeError( `${ memberName } cannot be null ! ${ expect }` ) }
        if ( isUndefined( value ) ) { throw new TypeError( `${ memberName } cannot be undefined ! ${ expect }` ) }
        if ( isNotArray( value ) ) { throw new TypeError( `${ memberName } cannot be an instance of ${ value.constructor.name } ! ${ expect }` ) }

        this._valueValidators = value

    }
    /**
     *
     * @return {string[]}
     */
    get keys () {

        return Object.keys( this._collection )

    }
    /**
     *
     * @return {unknown[] | any[]}
     */
    get values () {

        return Object.values( this._collection )

    }
    /**
     *
     * @param value
     * @return {TStore} The current instance (this)
     */
    setCollection ( value ) {

        this.collection = value
        return this

    }

    /**
     *
     * @param value
     * @return {TStore} The current instance (this)
     */
    setAllowOverride ( value ) {

        this.allowOverride = value
        return this

    }

    /**
     *
     * @param value
     * @return {TStore} The current instance (this)
     */
    setKeyValidators ( value ) {

        this.keyValidators( value )
        return this

    }

    /**
     *
     * @param value
     * @return {TStore} The current instance (this)
     */
    setValueValidators ( value ) {

        this.valueValidators( value )
        return this

    }

    /**
     * Allow to add new key value pair, the key cannot be null, undefined, or an empty string.
     * In case the key already exist, the value will be overwritten if force params is true or this
     * allow overriding else it throw an TypeError.
     *
     * @param {*} key
     * @param {*} value
     * @param {Boolean} force
     * @return {TStore} The current instance (this)
     */
    add ( key, value, force = false ) {

        if ( this.contain( key ) && ( !this._allowOverride && !force ) ) {
            throw new TypeError( `Item with key (${ key }) already exist in collection !` )
        }

        TStore._validate( key, this._keyValidators )
        TStore._validate( value, this._valueValidators )

        this._collection[ key ] = value

        return this

    }

    /**
     *
     * @param key
     * @return {boolean}
     */
    contain ( key ) {

        return isNotUndefined( this._collection[ key ] )

    }

    /**
     * Return the value associated to the key.
     *
     * @param key
     * @returns {*}
     */
    get ( key ) {

        return this._collection[ key ]

    }

    /**
     * Remove to value from the cache. Does nothing if the key does not exist.
     *
     * @param key
     * @return {TStore} The current instance (this)
     */
    remove ( key ) {

        delete this._collection[ key ]

        return this

    }

    /**
     * Clear the cache and reset collection to an empty object.
     * @return {TStore} The current instance (this)
     */
    clear () {

        this._collection = {}

        return this

    }

}

export { TStore }