forms/FormsUnit.js

/**
 * @module flitter-forms/FormsUnit
 */

const CanonicalUnit = require('libflitter/canon/CanonicalUnit')
const Validator = require('./Validator')

/**
 * Unit that loads form validator definitions and makes available
 * flitter-forms' service helpers.
 * @extends module:libflitter/canon/CanonicalUnit~CanonicalUnit
 */
class FormsUnit extends CanonicalUnit {
    /**
     * Get the name of the service provided by this unit: 'forms'
     * @returns {string} - 'forms'
     */
    static get name() {
        return 'forms'
    }

    /**
     * Defines the services required by this unit.
     * @returns {Array<string>}
     */
    static get services() {
        return [...super.services, 'output']
    }

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

        /**
         * Name of the canonical item provided by this unit: 'form'
         * @type {string} - 'form'
         */
        this.canonical_item = 'form'

        /**
         * File extension of the canonical item provided by this unit: '.form.js'
         * @type {string} - '.form.js'
         */
        this.suffix = '.form.js'
    }

    /**
     * Initializes the unit. Loads the form validator definitions from the configured directory.
     * @param {module:libflitter/app/FlitterApp~FlitterApp} app - the Flitter app
     * @returns {Promise<void>}
     */
    async go(app) {
        app.make(Validator)
        return super.go(app)
    }

    /**
     * Init a single instance of the validator from the canonical info.
     * @param {object} info
     * @param {module:libflitter/app/FlitterApp~FlitterApp} info.app - the Flitter app
     * @param {string} info.name - the unqualified canonical name of the file
     * @param {object} instance - validator schema definition
     * @returns {Promise<module:flitter-forms/Validator~Validator>}
     */
    async init_canonical_file({app, name, instance}) {
        const validator_instance = new Validator(name, instance)
        return validator_instance
    }

    /**
     * Initialize a form for the specified validator into the request's session.
     * @param {module:flitter-forms/Validator~Validator} validator
     * @param {express/request} request
     */
    init(validator, request) {
        if ( !Object.keys(request.session).includes('forms') ) {
            request.session.forms = {}
        }

        if ( !Object.keys(request.session.forms).includes(validator.name) ) {
            request.session.forms[validator.name] = {
                data: {},
                errors: {},
            }
        } else {
            if ( !Object.keys(request.session.forms[validator.name]).includes('data') ) {
                request.session.forms[validator.name].data = {}
            }

            if ( !Object.keys(request.session.forms[validator.name]).includes('errors') ) {
                request.session.forms[validator.name].errors = {}
            }
        }
    }

    /**
     * Deploy the sample files provided by this unit. Creates the "app/validators" directory and an example validator
     * schema.
     * @returns {Promise<void>}
     */
    async deploy(){

        /*
         * Root directory of the flitter-forms package.
         */
        const package_dir = __dirname

        /*
         * Root directory of the Flitter app.
         */

        this.output.info("Forms deploy from: "+package_dir)
        this.output.info("To: "+this.directory)

        function do_copy(from, to){
            return new Promise(
                (resolve, reject) => {
                    ncp(from, to, (error) => {
                        if ( error ) reject(error)

                        resolve()
                    })
                }
            )
        }

        /*
         * Copy the template validators form over to the validators/ directory.
         */
        await do_copy(path.resolve(package_dir+"/deploy/validators"), this.directory)
    }

    /**
     * Get the templates provided by this unit.
     * @returns {Object}
     */
    templates(){
        return {
            form: {
                template: require('./templates/form'),
                directory: this.directory,
                extension: '.form.js'
            }
        }
    }
}

module.exports = exports = FormsUnit