libflitter/controller/ControllerUnit.js

/**
 * @module libflitter/controller/ControllerUnit
 */

const CanonicalUnit = require('../canon/CanonicalUnit')
const Controller = require('./Controller')
const SoftError = require('../errors/SoftError')

/**
 * Unit to load and manage controller class definitions.
 * @extends module:libflitter/canon/CanonicalUnit~CanonicalUnit
 */
class ControllerUnit extends CanonicalUnit {
    /**
     * Get the name of the service provided by this unit: 'controllers'
     * @returns {string} - 'controllers'
     */
    static get name() {
        return 'controllers'
    }

    /**
     * Instantiate the unit.
     * @param {string} [base_directory = './app/controllers'] - the base search directory
     */
    constructor(base_directory = './app/controllers') {
        super(base_directory)

        /**
         * The canonical name of the item.
         * @type {string} = 'item'
         */
        this.canonical_item = 'controller'

        /**
         * The file extension of the canonical item files.
         * @type {string} - '.js'
         */
        this.suffix = '.controller.js'
    }

    /**
     * Prepare a single canonical controller and return the value that should be given by the resolver.
     * @param {object} info
     * @param {module:libflitter/app/FlitterApp} info.app
     * @param {string} info.name - the unqualified canonical name
     * @param {*} info.instance - the static CLASS definition of the controller from the file
     * @returns {Promise<*>}
     */
    async init_canonical_file({app, name, instance}) {
        if ( instance.prototype instanceof Controller ) {
            return new instance(app)
        } else {
            throw (new SoftError(`Cannot create controller for ${name}. Controller classes must extend from libflitter/controller/Controller.`)).unit(this.constructor.name)
        }
    }

    /**
     * Resolve an unqualified canonical name to a registered canonical controller or method.
     * @param {string} name
     * @returns {module:libflitter/controller/Controller~Controller|function}
     */
    get(name) {
        const name_parts = name.split('.')
        const controller_instance = this.canonical_items[name_parts[0]]

        if ( name_parts.length > 1 ) {
            const method_instance = controller_instance[name_parts[1]].bind(controller_instance)

            if ( name_parts > 2 ) {
                let descending_value = method_instance
                name_parts.slice(2).forEach(part => {
                    descending_value = descending_value[part]
                })

                return descending_value
            } else {
                return method_instance
            }
        }
    }

    /**
     * Get the templates provided by the unit.
     * "controller" provided by {@link module:libflitter/templates/controller}.
     * @returns {{controller: {template: ((function(string): string)|*|controller), extension: string, directory: string}}}
     */
    templates(){
        return {
            controller: {
                template: require('../templates/controller'),
                directory: this.directory,
                extension: '.controller.js'
            }
        }
    }
}

module.exports = exports = ControllerUnit