@tdb/web
Version:
Common condiguration for serving a web-site and testing web-based UI components.
395 lines (315 loc) • 9.11 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.consola = factory());
}(this, (function () { 'use strict';
var Types = {
// Level 0
fatal: {
level: 0
},
error: {
level: 0
},
// Level 1
warn: {
level: 1
},
// Level 2
log: {
level: 2
},
// Level 3
info: {
level: 3
},
success: {
level: 3
},
// Level 4
debug: {
level: 4
},
// Level 5
trace: {
level: 5
},
// Silent
silent: {
level: Infinity
},
// Legacy
ready: {
level: 3
},
start: {
level: 3
}
};
function isPlainObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
}
function isLogObj(arg) {
// Should be plain object
// Also contains either message or args field
return isPlainObject(arg) && Boolean(arg.message || arg.args);
}
let paused = false;
const queue = [];
class Consola {
constructor(options = {}) {
this._reporters = options.reporters || [];
this._types = options.types || Types;
this._level = options.level != null ? options.level : 3;
this._defaults = options.defaults || {};
this._async = typeof options.async !== 'undefined' ? options.async : null;
this._stdout = options.stdout;
this._stderr = options.stdout;
this._mockFn = options.mockFn; // Create logger functions for current instance
for (const type in this._types) {
this[type] = this._wrapLogFn(Object.assign({
type
}, this._types[type], this._defaults));
} // Use _mockFn if is set
if (this._mockFn) {
this.mockTypes();
}
}
get level() {
return this._level;
}
set level(newLevel) {
// Ensure that newLevel does not exceeds type level boundaries
let min = 0;
let max = 0;
for (const typeName in this._types) {
const type = this._types[typeName];
if (type.level > max) {
max = type.level;
} else if (type.level < min) {
min = type.level;
}
} // Set level
this._level = Math.min(max, Math.max(min, newLevel));
}
get stdout() {
return this._stdout || console._stdout; // eslint-disable-line no-console
}
get stderr() {
return this._stderr || console._stderr; // eslint-disable-line no-console
}
create(options) {
return new Consola(Object.assign({
reporters: this._reporters,
level: this._level,
types: this._types,
defaults: this._defaults,
stdout: this._stdout,
stderr: this._stderr,
mockFn: this._mockFn
}, options));
}
addReporter(reporter) {
this._reporters.push(reporter);
return this;
}
removeReporter(reporter) {
if (reporter) {
const i = this._reporters.indexOf(reporter);
if (i >= 0) {
return this._reporters.splice(i, 1);
}
} else {
this._reporters.splice(0);
}
return this;
}
setReporters(reporters) {
this._reporters = Array.isArray(reporters) ? reporters : [reporters];
}
withDefaults(defaults) {
return this.create({
defaults: Object.assign({}, this._defaults, defaults)
});
}
withTag(tag) {
return this.withDefaults({
tag: this._defaults.tag ? this._defaults.tag + ':' + tag : tag
});
}
wrapAll() {
this.wrapConsole();
this.wrapStd();
}
restoreAll() {
this.restoreConsole();
this.restoreStd();
}
wrapConsole() {
for (const type in this._types) {
// Backup original value
if (!console['__' + type]) {
// eslint-disable-line no-console
console['__' + type] = console[type]; // eslint-disable-line no-console
} // Override
console[type] = this[type]; // eslint-disable-line no-console
}
}
restoreConsole() {
for (const type in this._types) {
// Restore if backup is available
if (console['__' + type]) {
// eslint-disable-line no-console
console[type] = console['__' + type]; // eslint-disable-line no-console
delete console['__' + type]; // eslint-disable-line no-console
}
}
}
wrapStd() {
this._wrapStream(this.stdout, 'log');
this._wrapStream(this.stderr, 'log');
}
_wrapStream(stream, type) {
if (!stream) {
return;
} // Backup original value
if (!stream.__write) {
stream.__write = stream.write;
} // Override
stream.write = data => {
this[type](String(data).trim());
};
}
restoreStd() {
this._restoreStream(this.stdout);
this._restoreStream(this.stderr);
}
_restoreStream(stream) {
if (!stream) {
return;
}
if (stream.__write) {
stream.write = stream.__write;
delete stream.__write;
}
}
pauseLogs() {
paused = true;
}
resumeLogs() {
paused = false; // Process queue
const _queue = queue.splice(0);
for (const item of _queue) {
item[0]._logFn(item[1], item[2]);
}
}
mockTypes(mockFn) {
this._mockFn = mockFn || this._mockFn;
if (typeof this._mockFn !== 'function') {
return;
}
for (const type in this._types) {
this[type] = this._mockFn(type, this._types[type]) || this[type];
}
}
_wrapLogFn(defaults) {
function logFn() {
if (paused) {
queue.push([this, defaults, arguments]);
return;
}
return this._logFn(defaults, arguments);
}
return logFn.bind(this);
}
_logFn(defaults, args) {
if (defaults.level > this._level) {
return this._async ? Promise.resolve(false) : false;
} // Construct a new log object
const logObj = Object.assign({
date: new Date(),
args: []
}, defaults); // Consume arguments
if (args.length === 1 && isLogObj(args[0])) {
Object.assign(logObj, args[0]);
} else {
logObj.args = Array.from(args);
} // Aliases
if (logObj.message) {
logObj.args.unshift(logObj.message);
delete logObj.message;
}
if (logObj.additional) {
if (!Array.isArray(logObj.additional)) {
logObj.additional = logObj.additional.split('\n');
}
logObj.args.push('\n' + logObj.additional.join('\n'));
delete logObj.additional;
} // Log
if (this._async) {
return this._logAsync(logObj);
} else {
this._log(logObj);
}
}
_log(logObj) {
for (const reporter of this._reporters) {
reporter.log(logObj, {
async: false,
stdout: this.stdout,
stderr: this.stderr
});
}
}
_logAsync(logObj) {
return Promise.all(this._reporters.map(reporter => reporter.log(logObj, {
async: true,
stdout: this.stdout,
stderr: this.stderr
})));
}
} // Legacy support
Consola.prototype.add = Consola.prototype.addReporter;
Consola.prototype.remove = Consola.prototype.removeReporter;
Consola.prototype.clear = Consola.prototype.removeReporter;
Consola.prototype.withScope = Consola.prototype.withTag;
Consola.prototype.mock = Consola.prototype.mockTypes;
Consola.prototype.pause = Consola.prototype.pauseLogs;
Consola.prototype.resume = Consola.prototype.resumeLogs;
const TYPE_COLOR_MAP = {
'info': 'cyan'
};
const LEVEL_COLOR_MAP = {
0: 'red',
1: 'yellow',
2: 'white',
3: 'green'
};
class BrowserReporter {
constructor(options) {
this.options = Object.assign({}, options);
}
log(logObj) {
// consoleLogFn
let consoleLogFn = console[logObj.type]; // eslint-disable-line no-console
if (!consoleLogFn) {
consoleLogFn = console[logObj.level < 2 ? 'error' : 'log']; // eslint-disable-line no-console
} // Type
const type = logObj.type.toUpperCase(); // Styles
const color = TYPE_COLOR_MAP[logObj.type] || LEVEL_COLOR_MAP[logObj.level];
const styleColor = `color: ${color}; background-color: inherit;`;
const styleInherit = `color: inherit; background-color: inherit;`;
const styleAdditional = `color: ${logObj.additionalColor || 'grey'}; background-color: inherit;`; // Date
const date = new Date(logObj.date).toLocaleTimeString(); // Log to the console
consoleLogFn(`%c[${type}]%c[${date}]%c`, styleColor, styleAdditional, styleInherit, ...logObj.args);
}
}
if (!window.consola) {
// Create new consola instance
window.consola = new Consola({
reporters: [new BrowserReporter()]
});
}
var browser = window.consola;
return browser;
})));