libflitter/static/StaticUnit.js

/**
 * @module libflitter/static/StaticUnit
 */

const express = require('express')
const path = require('path')
const Unit = require('../Unit')
const fs = require('fs')

/**
 * The static unit initializes the favicon and the static assets folder.
 * This allows static assets to be served from Flitter from a path prefix
 * and assumes a favicon.ico file exists.
 * 
 * @extends module:libflitter/Unit~Unit
 */
class StaticUnit extends Unit {
    /**
     * Get the name of the service provided by this unit: 'static'
     * @returns {string} - 'static'
     */
    static get name() {
        return 'static'
    }

    static get services() {
        return [...super.services, 'output']
    }

    /**
     * Instantiate the class. Resolves the path to the static assets.
     * @param {string} [static_asset_dir = './app/assets'] - the path to the static assets
     */
    constructor(static_asset_dir = './app/assets'){
        super()

        /**
         * The fully-qualified path to the static asset directory.
         * @type {string}
         * @name StaticUnit#static_asset_directory
         */
        this.static_asset_directory = path.resolve(static_asset_dir)
    }

    /**
     * Loads the unit. Configures the underlying Express app to serve files in 
     * {@link module:libflitter/static/StaticUnit~StaticUnit#static_asset_directory} on the '/assets' route.
     * Also, configures the express-favicon package to serve the favicon.ico file in that directory.
     * @param {module:libflitter/app/FlitterApp~FlitterApp} app - the Flitter app
     * @returns {Promise<void>}
     */
    async go(app){

        /*
         * Serve the static asset directory as static files
         * at the '/assets' prefix.
         */
        app.express.use('/assets', express.static(this.static_asset_directory))

        /*
         * Serve the favicon.ico file if it exists.
         * This should normally be in ./app/assets/favicon.ico
         */
        const favicon = require('express-favicon')
        const favicon_location = path.resolve(this.static_asset_directory+'/favicon.ico')
        fs.access(favicon_location, fs.F_OK, e => {
            if ( !e ) app.express.use(favicon(favicon_location))
            else this.output.warn(`Unable to find favicon file in ${this.static_asset_directory+'/favicon.ico'}. It will not be served.`)
        })
    }

    /**
     * Get the directories provided by this unit.
     * {@link module:libflitter/static/StaticUnit~StaticUnit#static_asset_directory} as "assets".
     * @returns {{assets: string}}
     */
    directories() {
        return {
            assets: this.static_asset_directory
        }
    }
}

module.exports = exports = StaticUnit