libflitter/utility/services/Output.service.js

/**
 * @module libflitter/utility/services/Output
 */

const Service = require('../../NamedService')
const color = require('colors/safe')

/**
 * Service for managing output to the console based on logging level.
 * @extends module:flitter-di/src/Service~Service
 */
class Output extends Service {
    /**
     * Get the name of this service: 'output'
     * @returns {string} - 'output'
     */
    static get name() { return 'output' }

    constructor() {
        super()
        /**
         * The logging level.
         * @type {number}
         */
        this.level = 1

        /**
         * If true, includes a timestamp in the output. Default false.
         * @type {boolean}
         */
        this.timestamp = false
    }

    /**
     * Get the trace name of the output method caller.
     * Assumes that the caller is the fourth item in the stack.
     * For example: Output.__get_caller_info < Output.__timestamp < Output.error < Original Caller
     * @returns {string} - the caller's name (e.g. "ClassName.method")
     * @private
     */
    __get_caller_info(level = 4) {
        let inf = (new Error).stack
            .split('at')
            .slice(level)
            .map(x => x.trim()
                .split(' (')[0]
                .split('.')[0]
                .split(':')[0]
            )[0]

        if ( inf.indexOf('node_modules/') >= 0 ) inf = inf.split('node_modules/')[1]
        if ( ['function', 'output'].includes(inf.toLowerCase()) ) return this.__get_caller_info(level + 2)
        return inf
    }

    /**
     * Get a color-formatted timestamp string.
     * @returns {string}
     * @private
     */
    __timestamp() {
        return this.timestamp ? color.cyan(`[${(new Date).toLocaleString()}] [${color.italic(this.__get_caller_info())}]`) : color.cyan(`[${color.italic(this.__get_caller_info())}]`)
    }

    /**
     * Send a [DEBUG] message.
     * The logging level must be greater than or equal to the message level for it to display.
     * @param {string} msg
     * @param {number} [level = 5] - the message level
     */
    debug(msg, level = 5) {
        if ( this.level < level ) return;
        console.log(color.magenta('   [DEBUG]'), this.__timestamp(), msg)
    }

    /**
     * Send an [INFO] message.
     * The logging level must be greater than or equal to the message level for it to display.
     * @param {string} msg
     * @param {number} [level = 4] - the message level
     */
    info(msg, level = 4) {
        if ( this.level < level ) return;
        console.log(color.blue('    [INFO]'), this.__timestamp(), msg)
    }

    /**
     * Send a [MESSAGE] message.
     * The logging level must be greater than or equal to the message level for it to display.
     * @param {string} msg
     * @param {number} [level = 3] - the message level
     */
    message(msg, level = 3) {
        if ( this.level < level ) return;
        console.log(color.cyan(' [MESSAGE]'), this.__timestamp(), msg)
    }

    /**
     * Send a [WARNING] message.
     * The logging level must be greater than or equal to the message level for it to display.
     * @param {string} msg
     * @param {number} [level = 2] - the message level
     */
    warn(msg, level = 2) {
        if ( this.level < level ) return;
        console.log(color.yellow(' [WARNING]'), this.__timestamp(), msg)
    }

    /**
     * Send an [ERROR] message.
     * The logging level must be greater than or equal to the message level for it to display.
     * @param {string} msg
     * @param {number} [level = 1] - the message level
     */
    error(msg, level = 1) {
        if ( this.level < level ) return;
        console.log(color.red('   [ERROR]'), this.__timestamp(), msg)
    }

    /**
     * Send a [SUCCESS] message.
     * The logging level must be greater than or equal to the message level for it to display.
     * @param {string} msg
     * @param {number} [level = 1] - the message level
     */
    success(msg, level = 1) {
        if ( this.level < level ) return;
        console.log(color.green(' [SUCCESS]'), this.__timestamp(), msg)
    }
}

module.exports = exports = Output