Source: sources/controllers/TAbstractDataController.js

/**
 * @author [Tristan Valcke]{@link https://github.com/Itee}
 * @license [BSD-3-Clause]{@link https://opensource.org/licenses/BSD-3-Clause}
 *
 * @class TDatabaseController
 * @classdesc The TDatabaseController is the base class to perform CRUD operations on the database
 */

import {
    isArray,
    isBlankString,
    isDefined,
    isEmptyArray,
    isEmptyObject,
    isEmptyString,
    isNotArray,
    isNotBoolean,
    isNotDefined,
    isNotObject,
    isNotString,
    isNull,
    isObject,
    isUndefined
}                                   from 'itee-validators'
import { TAbstractResponder }       from '../databases/TAbstractResponder'
import { UnprocessableEntityError } from '../messages/http/UnprocessableEntityError'

/**
 * @class
 * @classdesc The TDatabaseController is the base class to perform CRUD operations on the database
 * @augments module:Databases/TAbstractResponder~TAbstractResponder
 */
class TAbstractDataController extends TAbstractResponder {

    /**
     * @constructor
     * @param {Object} [parameters={}] - An object containing all parameters to pass through the inheritance chain to initialize this instance
     * @param {external:Others~DatabaseDriver} parameters.driver Any official database driver that will be used internally by inherited class
     * @param {boolean} [parameters.useNext=false] A boolean flag to indicate that this instance should use "next()" function instead of return response to client.
     */
    constructor ( parameters ) {

        const _parameters = {
            ...{
                driver:  null,
                useNext: false
            },
            ...parameters
        }

        super( _parameters )

        /**
         * The database drive to use internally
         * @throws {TypeError} Will throw an error if the argument is null.
         * @throws {TypeError} Will throw an error if the argument is undefined.
         */
        this.driver = _parameters.driver
        this.useNext = _parameters.useNext

    }
    get useNext () {
        return this._useNext
    }
    set useNext ( value ) {
        if ( isNull( value ) ) { throw new TypeError( 'Driver cannot be null ! Expect a database driver.' ) }
        if ( isUndefined( value ) ) { throw new TypeError( 'Driver cannot be undefined ! Expect a database driver.' ) }
        if ( isNotBoolean( value ) ) { throw new TypeError( 'Driver cannot be undefined ! Expect a database driver.' ) }

        this._useNext = value
    }
    get driver () {
        return this._driver
    }
    set driver ( value ) {
        if ( isNull( value ) ) { throw new TypeError( 'Driver cannot be null ! Expect a database driver.' ) }
        if ( isUndefined( value ) ) { throw new TypeError( 'Driver cannot be undefined ! Expect a database driver.' ) }

        this._driver = value
    }

    //////////////////
    // CRUD Methods //
    //////////////////
    create ( request, response, next ) {

        const data = request.body

        if ( isNotDefined( data ) ) {

            TAbstractDataController.returnError(
                new UnprocessableEntityError( 'Le corps de la requete ne peut pas être null ou indefini.' ),
                ( this.useNext ) ? next : response
            )

        } else if ( isArray( data ) ) {

            if ( isEmptyArray( data ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `Le tableau d'objet de la requete ne peut pas être vide.` ),
                    ( this.useNext ) ? next : response
                )

            } else {

                this._createMany( data, response, next )

            }

        } else if ( isObject( data ) ) {

            if ( isEmptyObject( data ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `L'objet de la requete ne peut pas être vide.` ),
                    ( this.useNext ) ? next : response
                )

            } else {

                this._createOne( data, response, next )

            }

        } else {

            TAbstractDataController.returnError(
                new UnprocessableEntityError( `Le type de donnée de la requete est invalide. Les paramètres valides sont objet ou un tableau d'objet.` ),
                ( this.useNext ) ? next : response
            )

        }

    }

    _createOne ( /*data, response, next*/ ) {}

    _createMany ( /*datas, response, next*/ ) {}

    read ( request, response, next ) {

        const id          = request.params[ 'id' ]
        const requestBody = request.body
        const haveBody    = ( isDefined( requestBody ) )
        const ids         = ( haveBody ) ? requestBody.ids : null
        const query       = ( haveBody ) ? requestBody.query : null
        const projection  = ( haveBody ) ? requestBody.projection : null

        if ( isDefined( id ) ) {

            if ( isNotString( id ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `L'identifiant devrait être une chaine de caractères.` ),
                    ( this.useNext ) ? next : response
                )

            } else if ( isEmptyString( id ) || isBlankString( id ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `L'identifiant ne peut pas être une chaine de caractères vide.` ),
                    ( this.useNext ) ? next : response
                )

            } else {

                this._readOne( id, projection, response, next )

            }

        } else if ( isDefined( ids ) ) {

            if ( isNotArray( ids ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `Le tableau d'identifiants devrait être un tableau de chaine de caractères.` ),
                    ( this.useNext ) ? next : response
                )

            } else if ( isEmptyArray( ids ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `Le tableau d'identifiants ne peut pas être vide.` ),
                    ( this.useNext ) ? next : response
                )

            } else {

                this._readMany( ids, projection, response, next )

            }

        } else if ( isDefined( query ) ) {

            if ( isNotObject( query ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `La requete devrait être un objet javascript.` ),
                    ( this.useNext ) ? next : response
                )

            } else if ( isEmptyObject( query ) ) {

                this._readAll( projection, response, next )

            } else {

                this._readWhere( query, projection, response, next )

            }

        } else {

            TAbstractDataController.returnError(
                new UnprocessableEntityError( `La requete ne peut pas être null.` ),
                ( this.useNext ) ? next : response
            )

        }

    }

    _readOne ( /*id, projection, response, next*/ ) {}

    _readMany ( /*ids, projection, response, next*/ ) {}

    _readWhere ( /*query, projection, response, next*/ ) {}

    _readAll ( /*projection, response, next*/ ) {}

    update ( request, response, next ) {

        const id          = request.params[ 'id' ]
        const requestBody = request.body
        const haveBody    = ( isDefined( requestBody ) )
        const ids         = ( haveBody ) ? requestBody.ids : null
        const query       = ( haveBody ) ? requestBody.query : null
        const update      = ( haveBody ) ? requestBody.update : null

        if ( isNotDefined( update ) ) {

            TAbstractDataController.returnError(
                new UnprocessableEntityError( `La mise à jour a appliquer ne peut pas être null ou indefini.` ),
                ( this.useNext ) ? next : response
            )

        } else if ( isDefined( id ) ) {

            if ( isNotString( id ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `L'identifiant devrait être une chaine de caractères.` ),
                    ( this.useNext ) ? next : response
                )

            } else if ( isEmptyString( id ) || isBlankString( id ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `L'identifiant ne peut pas être une chaine de caractères vide.` ),
                    ( this.useNext ) ? next : response
                )

            } else {

                this._updateOne( id, update, response, next )

            }

        } else if ( isDefined( ids ) ) {

            if ( isNotArray( ids ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `Le tableau d'identifiants devrait être un tableau de chaine de caractères.` ),
                    ( this.useNext ) ? next : response
                )

            } else if ( isEmptyArray( ids ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `Le tableau d'identifiants ne peut pas être vide.` ),
                    ( this.useNext ) ? next : response
                )

            } else {

                this._updateMany( ids, update, response, next )

            }

        } else if ( isDefined( query ) ) {

            if ( isNotObject( query ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `La requete devrait être un objet javascript.` ),
                    ( this.useNext ) ? next : response
                )

            } else if ( isEmptyObject( query ) ) {

                this._updateAll( update, response, next )

            } else {

                this._updateWhere( query, update, response, next )

            }

        } else {

            TAbstractDataController.returnError(
                new UnprocessableEntityError( `La requete ne peut pas être vide.` ),
                ( this.useNext ) ? next : response
            )

        }

    }

    _updateOne ( /*id, update, response, next*/ ) {}

    _updateMany ( /*ids, updates, response, next*/ ) {}

    _updateWhere ( /*query, update, response, next*/ ) {}

    _updateAll ( /*update, response, next*/ ) {}

    delete ( request, response, next ) {

        const id          = request.params[ 'id' ]
        const requestBody = request.body
        const haveBody    = ( isDefined( requestBody ) )
        const ids         = ( haveBody ) ? requestBody.ids : null
        const query       = ( haveBody ) ? requestBody.query : null

        if ( isDefined( id ) ) {

            if ( isNotString( id ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `L'identifiant devrait être une chaine de caractères.` ),
                    ( this.useNext ) ? next : response
                )

            } else if ( isEmptyString( id ) || isBlankString( id ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `L'identifiant ne peut pas être une chaine de caractères vide.` ),
                    ( this.useNext ) ? next : response
                )

            } else {

                this._deleteOne( id, response, next )

            }

        } else if ( isDefined( ids ) ) {

            if ( isNotArray( ids ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `Le tableau d'identifiants devrait être un tableau de chaine de caractères.` ),
                    ( this.useNext ) ? next : response
                )

            } else if ( isEmptyArray( ids ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `Le tableau d'identifiants ne peut pas être vide.` ),
                    ( this.useNext ) ? next : response
                )

            } else {

                this._deleteMany( ids, response, next )

            }

        } else if ( isDefined( query ) ) {

            if ( isNotObject( query ) ) {

                TAbstractDataController.returnError(
                    new UnprocessableEntityError( `La requete devrait être un objet javascript.` ),
                    ( this.useNext ) ? next : response
                )

            } else if ( isEmptyObject( query ) ) {

                this._deleteAll( response, next )

            } else {

                this._deleteWhere( query, response, next )

            }

        } else {

            TAbstractDataController.returnError(
                new UnprocessableEntityError( `La requete ne peut pas être vide.` ),
                ( this.useNext ) ? next : response
            )

        }

    }

    _deleteOne ( /*id, response, next*/ ) {}

    _deleteMany ( /*ids, response, next*/ ) {}

    _deleteWhere ( /*query, response, next*/ ) {}

    _deleteAll ( /*response, next*/ ) {}

}

export { TAbstractDataController }