416 lines
9.7 KiB
Plaintext
416 lines
9.7 KiB
Plaintext
'use strict';
|
|
|
|
const LogLevels = {
|
|
silent: Number.NEGATIVE_INFINITY,
|
|
fatal: 0,
|
|
error: 0,
|
|
warn: 1,
|
|
log: 2,
|
|
info: 3,
|
|
success: 3,
|
|
fail: 3,
|
|
ready: 3,
|
|
start: 3,
|
|
box: 3,
|
|
debug: 4,
|
|
trace: 5,
|
|
verbose: Number.POSITIVE_INFINITY
|
|
};
|
|
const LogTypes = {
|
|
// Silent
|
|
silent: {
|
|
level: -1
|
|
},
|
|
// Level 0
|
|
fatal: {
|
|
level: LogLevels.fatal
|
|
},
|
|
error: {
|
|
level: LogLevels.error
|
|
},
|
|
// Level 1
|
|
warn: {
|
|
level: LogLevels.warn
|
|
},
|
|
// Level 2
|
|
log: {
|
|
level: LogLevels.log
|
|
},
|
|
// Level 3
|
|
info: {
|
|
level: LogLevels.info
|
|
},
|
|
success: {
|
|
level: LogLevels.success
|
|
},
|
|
fail: {
|
|
level: LogLevels.fail
|
|
},
|
|
ready: {
|
|
level: LogLevels.info
|
|
},
|
|
start: {
|
|
level: LogLevels.info
|
|
},
|
|
box: {
|
|
level: LogLevels.info
|
|
},
|
|
// Level 4
|
|
debug: {
|
|
level: LogLevels.debug
|
|
},
|
|
// Level 5
|
|
trace: {
|
|
level: LogLevels.trace
|
|
},
|
|
// Verbose
|
|
verbose: {
|
|
level: LogLevels.verbose
|
|
}
|
|
};
|
|
|
|
function isObject(value) {
|
|
return value !== null && typeof value === "object";
|
|
}
|
|
function _defu(baseObject, defaults, namespace = ".", merger) {
|
|
if (!isObject(defaults)) {
|
|
return _defu(baseObject, {}, namespace, merger);
|
|
}
|
|
const object = Object.assign({}, defaults);
|
|
for (const key in baseObject) {
|
|
if (key === "__proto__" || key === "constructor") {
|
|
continue;
|
|
}
|
|
const value = baseObject[key];
|
|
if (value === null || value === void 0) {
|
|
continue;
|
|
}
|
|
if (merger && merger(object, key, value, namespace)) {
|
|
continue;
|
|
}
|
|
if (Array.isArray(value) && Array.isArray(object[key])) {
|
|
object[key] = [...value, ...object[key]];
|
|
} else if (isObject(value) && isObject(object[key])) {
|
|
object[key] = _defu(
|
|
value,
|
|
object[key],
|
|
(namespace ? `${namespace}.` : "") + key.toString(),
|
|
merger
|
|
);
|
|
} else {
|
|
object[key] = value;
|
|
}
|
|
}
|
|
return object;
|
|
}
|
|
function createDefu(merger) {
|
|
return (...arguments_) => (
|
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
arguments_.reduce((p, c) => _defu(p, c, "", merger), {})
|
|
);
|
|
}
|
|
const defu = createDefu();
|
|
|
|
function isPlainObject(obj) {
|
|
return Object.prototype.toString.call(obj) === "[object Object]";
|
|
}
|
|
function isLogObj(arg) {
|
|
if (!isPlainObject(arg)) {
|
|
return false;
|
|
}
|
|
if (!arg.message && !arg.args) {
|
|
return false;
|
|
}
|
|
if (arg.stack) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
let paused = false;
|
|
const queue = [];
|
|
class Consola {
|
|
constructor(options = {}) {
|
|
const types = options.types || LogTypes;
|
|
this.options = defu(
|
|
{
|
|
...options,
|
|
defaults: { ...options.defaults },
|
|
level: _normalizeLogLevel(options.level, types),
|
|
reporters: [...options.reporters || []]
|
|
},
|
|
{
|
|
types: LogTypes,
|
|
throttle: 1e3,
|
|
throttleMin: 5,
|
|
formatOptions: {
|
|
date: true,
|
|
colors: false,
|
|
compact: true
|
|
}
|
|
}
|
|
);
|
|
for (const type in types) {
|
|
const defaults = {
|
|
type,
|
|
...this.options.defaults,
|
|
...types[type]
|
|
};
|
|
this[type] = this._wrapLogFn(defaults);
|
|
this[type].raw = this._wrapLogFn(
|
|
defaults,
|
|
true
|
|
);
|
|
}
|
|
if (this.options.mockFn) {
|
|
this.mockTypes();
|
|
}
|
|
this._lastLog = {};
|
|
}
|
|
get level() {
|
|
return this.options.level;
|
|
}
|
|
set level(level) {
|
|
this.options.level = _normalizeLogLevel(
|
|
level,
|
|
this.options.types,
|
|
this.options.level
|
|
);
|
|
}
|
|
prompt(message, opts) {
|
|
if (!this.options.prompt) {
|
|
throw new Error("prompt is not supported!");
|
|
}
|
|
return this.options.prompt(message, opts);
|
|
}
|
|
create(options) {
|
|
const instance = new Consola({
|
|
...this.options,
|
|
...options
|
|
});
|
|
if (this._mockFn) {
|
|
instance.mockTypes(this._mockFn);
|
|
}
|
|
return instance;
|
|
}
|
|
withDefaults(defaults) {
|
|
return this.create({
|
|
...this.options,
|
|
defaults: {
|
|
...this.options.defaults,
|
|
...defaults
|
|
}
|
|
});
|
|
}
|
|
withTag(tag) {
|
|
return this.withDefaults({
|
|
tag: this.options.defaults.tag ? this.options.defaults.tag + ":" + tag : tag
|
|
});
|
|
}
|
|
addReporter(reporter) {
|
|
this.options.reporters.push(reporter);
|
|
return this;
|
|
}
|
|
removeReporter(reporter) {
|
|
if (reporter) {
|
|
const i = this.options.reporters.indexOf(reporter);
|
|
if (i >= 0) {
|
|
return this.options.reporters.splice(i, 1);
|
|
}
|
|
} else {
|
|
this.options.reporters.splice(0);
|
|
}
|
|
return this;
|
|
}
|
|
setReporters(reporters) {
|
|
this.options.reporters = Array.isArray(reporters) ? reporters : [reporters];
|
|
return this;
|
|
}
|
|
wrapAll() {
|
|
this.wrapConsole();
|
|
this.wrapStd();
|
|
}
|
|
restoreAll() {
|
|
this.restoreConsole();
|
|
this.restoreStd();
|
|
}
|
|
wrapConsole() {
|
|
for (const type in this.options.types) {
|
|
if (!console["__" + type]) {
|
|
console["__" + type] = console[type];
|
|
}
|
|
console[type] = this[type].raw;
|
|
}
|
|
}
|
|
restoreConsole() {
|
|
for (const type in this.options.types) {
|
|
if (console["__" + type]) {
|
|
console[type] = console["__" + type];
|
|
delete console["__" + type];
|
|
}
|
|
}
|
|
}
|
|
wrapStd() {
|
|
this._wrapStream(this.options.stdout, "log");
|
|
this._wrapStream(this.options.stderr, "log");
|
|
}
|
|
_wrapStream(stream, type) {
|
|
if (!stream) {
|
|
return;
|
|
}
|
|
if (!stream.__write) {
|
|
stream.__write = stream.write;
|
|
}
|
|
stream.write = (data) => {
|
|
this[type].raw(String(data).trim());
|
|
};
|
|
}
|
|
restoreStd() {
|
|
this._restoreStream(this.options.stdout);
|
|
this._restoreStream(this.options.stderr);
|
|
}
|
|
_restoreStream(stream) {
|
|
if (!stream) {
|
|
return;
|
|
}
|
|
if (stream.__write) {
|
|
stream.write = stream.__write;
|
|
delete stream.__write;
|
|
}
|
|
}
|
|
pauseLogs() {
|
|
paused = true;
|
|
}
|
|
resumeLogs() {
|
|
paused = false;
|
|
const _queue = queue.splice(0);
|
|
for (const item of _queue) {
|
|
item[0]._logFn(item[1], item[2]);
|
|
}
|
|
}
|
|
mockTypes(mockFn) {
|
|
const _mockFn = mockFn || this.options.mockFn;
|
|
this._mockFn = _mockFn;
|
|
if (typeof _mockFn !== "function") {
|
|
return;
|
|
}
|
|
for (const type in this.options.types) {
|
|
this[type] = _mockFn(type, this.options.types[type]) || this[type];
|
|
this[type].raw = this[type];
|
|
}
|
|
}
|
|
_wrapLogFn(defaults, isRaw) {
|
|
return (...args) => {
|
|
if (paused) {
|
|
queue.push([this, defaults, args, isRaw]);
|
|
return;
|
|
}
|
|
return this._logFn(defaults, args, isRaw);
|
|
};
|
|
}
|
|
_logFn(defaults, args, isRaw) {
|
|
if ((defaults.level || 0) > this.level) {
|
|
return false;
|
|
}
|
|
const logObj = {
|
|
date: /* @__PURE__ */ new Date(),
|
|
args: [],
|
|
...defaults,
|
|
level: _normalizeLogLevel(defaults.level, this.options.types)
|
|
};
|
|
if (!isRaw && args.length === 1 && isLogObj(args[0])) {
|
|
Object.assign(logObj, args[0]);
|
|
} else {
|
|
logObj.args = [...args];
|
|
}
|
|
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;
|
|
}
|
|
logObj.type = typeof logObj.type === "string" ? logObj.type.toLowerCase() : "log";
|
|
logObj.tag = typeof logObj.tag === "string" ? logObj.tag : "";
|
|
const resolveLog = (newLog = false) => {
|
|
const repeated = (this._lastLog.count || 0) - this.options.throttleMin;
|
|
if (this._lastLog.object && repeated > 0) {
|
|
const args2 = [...this._lastLog.object.args];
|
|
if (repeated > 1) {
|
|
args2.push(`(repeated ${repeated} times)`);
|
|
}
|
|
this._log({ ...this._lastLog.object, args: args2 });
|
|
this._lastLog.count = 1;
|
|
}
|
|
if (newLog) {
|
|
this._lastLog.object = logObj;
|
|
this._log(logObj);
|
|
}
|
|
};
|
|
clearTimeout(this._lastLog.timeout);
|
|
const diffTime = this._lastLog.time && logObj.date ? logObj.date.getTime() - this._lastLog.time.getTime() : 0;
|
|
this._lastLog.time = logObj.date;
|
|
if (diffTime < this.options.throttle) {
|
|
try {
|
|
const serializedLog = JSON.stringify([
|
|
logObj.type,
|
|
logObj.tag,
|
|
logObj.args
|
|
]);
|
|
const isSameLog = this._lastLog.serialized === serializedLog;
|
|
this._lastLog.serialized = serializedLog;
|
|
if (isSameLog) {
|
|
this._lastLog.count = (this._lastLog.count || 0) + 1;
|
|
if (this._lastLog.count > this.options.throttleMin) {
|
|
this._lastLog.timeout = setTimeout(
|
|
resolveLog,
|
|
this.options.throttle
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
} catch {
|
|
}
|
|
}
|
|
resolveLog(true);
|
|
}
|
|
_log(logObj) {
|
|
for (const reporter of this.options.reporters) {
|
|
reporter.log(logObj, {
|
|
options: this.options
|
|
});
|
|
}
|
|
}
|
|
}
|
|
function _normalizeLogLevel(input, types = {}, defaultLevel = 3) {
|
|
if (input === void 0) {
|
|
return defaultLevel;
|
|
}
|
|
if (typeof input === "number") {
|
|
return input;
|
|
}
|
|
if (types[input] && types[input].level !== void 0) {
|
|
return types[input].level;
|
|
}
|
|
return defaultLevel;
|
|
}
|
|
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;
|
|
function createConsola(options = {}) {
|
|
return new Consola(options);
|
|
}
|
|
|
|
exports.Consola = Consola;
|
|
exports.LogLevels = LogLevels;
|
|
exports.LogTypes = LogTypes;
|
|
exports.createConsola = createConsola;
|