203 lines
7 KiB
JavaScript
203 lines
7 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.createPrefixedFormatter = exports.createTaggedFormatter = exports.Logger = exports.DEFAULT_LOGGER_HANDLERS = exports.StreamHandler = exports.getLoggerLevelColor = exports.getLoggerLevelName = exports.LOGGER_LEVEL_NAMES = exports.LOGGER_LEVELS = void 0;
|
|
const tslib_1 = require("tslib");
|
|
const utils_terminal_1 = require("@ionic/utils-terminal");
|
|
const stream_1 = require("stream");
|
|
const util = tslib_1.__importStar(require("util"));
|
|
const colors_1 = require("./colors");
|
|
const utils_1 = require("./utils");
|
|
exports.LOGGER_LEVELS = Object.freeze({
|
|
DEBUG: 10,
|
|
INFO: 20,
|
|
WARN: 30,
|
|
ERROR: 40,
|
|
});
|
|
exports.LOGGER_LEVEL_NAMES = new Map([
|
|
[exports.LOGGER_LEVELS.DEBUG, 'DEBUG'],
|
|
[exports.LOGGER_LEVELS.INFO, 'INFO'],
|
|
[exports.LOGGER_LEVELS.WARN, 'WARN'],
|
|
[exports.LOGGER_LEVELS.ERROR, 'ERROR'],
|
|
]);
|
|
function getLoggerLevelName(level) {
|
|
if (level) {
|
|
const levelName = exports.LOGGER_LEVEL_NAMES.get(level);
|
|
if (levelName) {
|
|
return levelName;
|
|
}
|
|
}
|
|
}
|
|
exports.getLoggerLevelName = getLoggerLevelName;
|
|
function getLoggerLevelColor(colors, level) {
|
|
const levelName = getLoggerLevelName(level);
|
|
if (levelName) {
|
|
return colors.log[levelName];
|
|
}
|
|
}
|
|
exports.getLoggerLevelColor = getLoggerLevelColor;
|
|
class StreamHandler {
|
|
constructor({ stream, filter, formatter }) {
|
|
this.stream = stream;
|
|
this.filter = filter;
|
|
this.formatter = formatter;
|
|
}
|
|
clone(opts) {
|
|
const { stream, filter, formatter } = this;
|
|
return new StreamHandler({ stream, filter, formatter, ...opts });
|
|
}
|
|
handle(record) {
|
|
if (this.filter && !this.filter(record)) {
|
|
return;
|
|
}
|
|
const msg = this.formatter && record.format !== false ? this.formatter(record) : record.msg;
|
|
this.stream.write((0, utils_1.enforceLF)(msg));
|
|
}
|
|
}
|
|
exports.StreamHandler = StreamHandler;
|
|
const stdoutLogRecordFilter = (record) => !record.level || record.level === exports.LOGGER_LEVELS.INFO;
|
|
const stderrLogRecordFilter = (record) => !!record.level && record.level !== exports.LOGGER_LEVELS.INFO;
|
|
exports.DEFAULT_LOGGER_HANDLERS = new Set([
|
|
new StreamHandler({ stream: process.stdout, filter: stdoutLogRecordFilter }),
|
|
new StreamHandler({ stream: process.stderr, filter: stderrLogRecordFilter }),
|
|
]);
|
|
class Logger {
|
|
constructor({ level = exports.LOGGER_LEVELS.INFO, handlers } = {}) {
|
|
this.level = level;
|
|
this.handlers = handlers ? handlers : Logger.cloneHandlers(exports.DEFAULT_LOGGER_HANDLERS);
|
|
}
|
|
static cloneHandlers(handlers) {
|
|
return new Set([...handlers].map(handler => handler.clone()));
|
|
}
|
|
/**
|
|
* Clone this logger, optionally overriding logger options.
|
|
*
|
|
* @param opts Logger options to override from this logger.
|
|
*/
|
|
clone(opts = {}) {
|
|
const { level, handlers } = this;
|
|
return new Logger({ level, handlers: Logger.cloneHandlers(handlers), ...opts });
|
|
}
|
|
/**
|
|
* Log a message as-is.
|
|
*
|
|
* @param msg The string to log.
|
|
*/
|
|
msg(msg) {
|
|
this.log(this.createRecord(msg));
|
|
}
|
|
/**
|
|
* Log a message using the `debug` logger level.
|
|
*
|
|
* @param msg The string to log.
|
|
*/
|
|
debug(msg) {
|
|
this.log(this.createRecord(msg, exports.LOGGER_LEVELS.DEBUG));
|
|
}
|
|
/**
|
|
* Log a message using the `info` logger level.
|
|
*
|
|
* @param msg The string to log.
|
|
*/
|
|
info(msg) {
|
|
this.log(this.createRecord(msg, exports.LOGGER_LEVELS.INFO));
|
|
}
|
|
/**
|
|
* Log a message using the `warn` logger level.
|
|
*
|
|
* @param msg The string to log.
|
|
*/
|
|
warn(msg) {
|
|
this.log(this.createRecord(msg, exports.LOGGER_LEVELS.WARN));
|
|
}
|
|
/**
|
|
* Log a message using the `error` logger level.
|
|
*
|
|
* @param msg The string to log.
|
|
*/
|
|
error(msg) {
|
|
this.log(this.createRecord(msg, exports.LOGGER_LEVELS.ERROR));
|
|
}
|
|
createRecord(msg, level, format) {
|
|
return {
|
|
// If the logger is used to quickly print something, let's pretty-print
|
|
// it into a string.
|
|
msg: util.format(msg),
|
|
level,
|
|
logger: this,
|
|
format,
|
|
};
|
|
}
|
|
/**
|
|
* Log newlines using a logger output found via `level`.
|
|
*
|
|
* @param num The number of newlines to log.
|
|
* @param level The logger level. If omitted, the default output is used.
|
|
*/
|
|
nl(num = 1, level) {
|
|
this.log({ ...this.createRecord('\n'.repeat(num), level), format: false });
|
|
}
|
|
/**
|
|
* Log a record using a logger output found via `level`.
|
|
*/
|
|
log(record) {
|
|
if (typeof record.level === 'number' && this.level > record.level) {
|
|
return;
|
|
}
|
|
for (const handler of this.handlers) {
|
|
handler.handle(record);
|
|
}
|
|
}
|
|
createWriteStream(level, format) {
|
|
const self = this;
|
|
return new class extends stream_1.Writable {
|
|
_write(chunk, encoding, callback) {
|
|
self.log(self.createRecord(chunk.toString(), level, format));
|
|
callback();
|
|
}
|
|
}();
|
|
}
|
|
}
|
|
exports.Logger = Logger;
|
|
function createTaggedFormatter({ colors = colors_1.NO_COLORS, prefix = '', tags, titleize, wrap } = {}) {
|
|
const { strong, weak } = colors;
|
|
const getLevelTag = (level) => {
|
|
if (!level) {
|
|
return '';
|
|
}
|
|
if (tags) {
|
|
const tag = tags.get(level);
|
|
return tag ? tag : '';
|
|
}
|
|
const levelName = getLoggerLevelName(level);
|
|
if (!levelName) {
|
|
return '';
|
|
}
|
|
const levelColor = getLoggerLevelColor(colors, level);
|
|
return `${weak('[')}\x1b[40m${strong(levelColor ? levelColor(levelName) : levelName)}\x1b[49m${weak(']')}`;
|
|
};
|
|
return ({ msg, level, format }) => {
|
|
if (format === false) {
|
|
return msg;
|
|
}
|
|
const [firstLine, ...lines] = msg.split('\n');
|
|
const levelColor = getLoggerLevelColor(colors, level);
|
|
const tag = (typeof prefix === 'function' ? prefix() : prefix) + getLevelTag(level);
|
|
const title = titleize && lines.length > 0 ? `${strong(levelColor ? levelColor(firstLine) : firstLine)}\n` : firstLine;
|
|
const indentation = tag ? (0, utils_terminal_1.stringWidth)(tag) + 1 : 0;
|
|
const pulledLines = titleize ? (0, utils_1.dropWhile)(lines, l => l === '') : lines;
|
|
return ((tag ? `${tag} ` : '') +
|
|
(wrap
|
|
? (0, utils_terminal_1.wordWrap)([title, ...pulledLines].join('\n'), { indentation, ...(typeof wrap === 'object' ? wrap : {}) })
|
|
: [title, ...pulledLines.map(l => l ? ' '.repeat(indentation) + l : '')].join('\n')));
|
|
};
|
|
}
|
|
exports.createTaggedFormatter = createTaggedFormatter;
|
|
function createPrefixedFormatter(prefix) {
|
|
return ({ msg, format }) => {
|
|
if (format === false) {
|
|
return msg;
|
|
}
|
|
return `${typeof prefix === 'function' ? prefix() : prefix} ${msg}`;
|
|
};
|
|
}
|
|
exports.createPrefixedFormatter = createPrefixedFormatter;
|