libflitter/express/ExpressUnit.js

/**
 * @module libflitter/express/ExpressUnit
 */

const uuid = require('uuid/v4')
const Unit = require('../Unit')
const session = require('express-session')
const MongoDBStore = require('connect-mongodb-session')(session)
const path = require('path')

/**
 * The Express unit is responsible for injecting the 3rd-party tools
 * that Flitter makes available into the underlying Express framework
 * so they can be used in lower contexts. Currently, that includes the
 * body parser and session store.
 *
 * @extends module:libflitter/Unit~Unit
 */
class ExpressUnit extends Unit {

    /**
     * Loads the unit. Registers the 'busboy-body-parser' and 'express-session' packages with the underlying Express app.
     * @param {module:libflitter/app/FlitterApp~FlitterApp} app - the Flitter app
     * @returns {Promise<void>}
     */
    async go(app, context){

        /*
         * Load the body parser into the underlying Express app.
         * This is done here do that the body is parsed before any
         * of the middleware/controllers/routing/etc.
         */
        const body_parser = require('busboy-body-parser')
        app.express.use(body_parser())

        let store
        if ( app.d.database ) {

            /*
             * Set up the session store.
             */
            store = new MongoDBStore({
                uri: app.d.database.string,
                collection: 'flitter_sessions'
            })

        }

        app.express.use(session({
            genid: () => {
                return uuid() // use UUIDs for session IDs
            },
            secret: app.d.config.get('server.session.secret'),
            resave: true,
            saveUninitialized: true,
            store: (store ? store : null),
        }))

        context.bind('session_store', store)
    }

    /**
     * Get the name of the unit.
     * @returns {string} "express"
     */
    name(){
        return "express"
    }

    /**
     * Closes the session store's DB connection.
     * @param {module:libflitter/app/FlitterApp~FlitterApp} app
     * @returns {Promise<void>}
     */
    async cleanup(app){
        if ( app.d.express && app.d.express.session_store ) {
            await app.d.express.session_store.client.close()
        }
    }

    /**
     * Get the fully-qualified path to the migrations provided by this unit.
     * @returns {string}
     */
    migrations(){
        return path.resolve(__dirname, 'migrations')
    }

}

module.exports = exports = ExpressUnit