import { AbstractModule, Hook } from 'adapt-authoring-core'
import chalk from 'chalk'
/**
* Module for logging message to the console
* @memberof logger
* @extends {AbstractModule}
*/
class LoggerModule extends AbstractModule {
/**
* Colours an input string
* @param {String} str
* @param {String} colour
* @return {String}
*/
static colourise (str, colour) {
const chalkFunc = chalk[colour]
return chalkFunc ? chalkFunc(str) : str
}
/**
* Returns a formatted date stamp
* @param {Object} config
* @return {String}
*/
static getDateStamp (config) {
if (!config.timestamp) {
return ''
}
let str
if (config.dateFormat === 'iso') {
str = new Date().toISOString()
} else if (config.dateFormat === 'short') {
const d = new Date()
const m = d.getMonth() + 1
const s = d.getSeconds()
const date = `${d.getDate()}/${m < 10 ? `0${m}` : m}/${d.getFullYear().toString().slice(2)}`
const time = `${d.getHours()}:${d.getMinutes()}:${s < 10 ? `0${s}` : s}`
str = `${date}-${time}`
}
return LoggerModule.colourise(`${str} `, 'grey')
}
/** @override */
async init () {
await this.app.waitForModule('config')
/**
* Defines what messages are logged
* @type {Array}
*/
this.levelsConfig = this.getConfig('levels')
/**
* Hook invoked on each message logged
* @type {Hook}
*/
this.logHook = new Hook()
/**
* Module configuration options
* @type {Object}
*/
this.config = {
levels: {
error: {
enable: this.isLevelEnabled('error'),
moduleOverrides: this.getModuleOverrides('error'),
colour: 'red'
},
warn: {
enable: this.isLevelEnabled('warn'),
moduleOverrides: this.getModuleOverrides('warn'),
colour: 'yellow'
},
success: {
enable: this.isLevelEnabled('success'),
moduleOverrides: this.getModuleOverrides('success'),
colour: 'green'
},
info: {
enable: this.isLevelEnabled('info'),
moduleOverrides: this.getModuleOverrides('info'),
colour: 'cyan'
},
debug: {
enable: this.isLevelEnabled('debug'),
moduleOverrides: this.getModuleOverrides('debug'),
colour: 'grey'
}
},
timestamp: this.getConfig('showTimestamp'),
dateFormat: this.getConfig('dateFormat'),
mute: this.getConfig('mute').toString() === 'true'
}
// store instance on main App instance
this.app.logger = this
}
/**
* Determines whether a specific log level is enabled
* @param {String} level
* @return {Boolean}
*/
isLevelEnabled (level) { // note explicit disable takes preference
return !this.levelsConfig.includes(`!${level}`) && this.levelsConfig.includes(level)
}
/**
* Returns a list of log levels with overrides, either inclusive or exclusive
* @param {String} level
* @return {Array}
*/
getModuleOverrides (level) {
const levels = []
this.levelsConfig.forEach(l => {
const s = `${level}.`; const notS = `!${level}.`
if (l.indexOf(s) === 0 || l.indexOf(notS) === 0) levels.push(l)
})
return levels
}
/**
* Returns whether a message should be logged (i.e. not disabled in the config)
* @param {string} level Logging level
* @param {string} id Id of log caller
* @returns {boolean}
*/
isLoggingEnabled (level, id) {
const { enable, moduleOverrides = [] } = this?.config?.levels[level] || {}
const isEnabled = enable || moduleOverrides.includes(`${level}.${id}`)
const disableOverride = moduleOverrides.includes(`!${level}.${id}`)
return isEnabled && !disableOverride
}
/**
* Logs a message to the console
* @param {String} level Severity of the message
* @param {String} id Identifier for the message. Helps to differentiate between other messages.
* @param {...*} args Arguments to be logged
*/
log (level, id, ...args) {
if (this?.config?.mute?.toString() === 'true') {
return
}
if (id === AbstractModule.MODULE_READY) { // @hack for https://github.com/adaptlearning/adapt-authoring/issues/134 (better than overriding setReady)
id = this.name.split('-').pop()
args = [AbstractModule.MODULE_READY, ...args]
}
if (!this.isLoggingEnabled(level, id)) {
return
}
const colour = this?.config?.levels[level]?.colour
const logFunc = console[level] ?? console.log
logFunc(`${LoggerModule.getDateStamp(this.config)}${LoggerModule.colourise(level, colour)} ${LoggerModule.colourise(id, 'magenta')}`, ...args)
this.logHook.invoke(new Date(), level, id, ...args)
}
}
export default LoggerModule