1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | 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;
|
4 | const stream_1 = require("stream");
|
5 | const util = require("util");
|
6 | const colors_1 = require("./colors");
|
7 | const format_1 = require("./format");
|
8 | const utils_1 = require("./utils");
|
9 | exports.LOGGER_LEVELS = Object.freeze({
|
10 | DEBUG: 10,
|
11 | INFO: 20,
|
12 | WARN: 30,
|
13 | ERROR: 40,
|
14 | });
|
15 | exports.LOGGER_LEVEL_NAMES = new Map([
|
16 | [exports.LOGGER_LEVELS.DEBUG, 'DEBUG'],
|
17 | [exports.LOGGER_LEVELS.INFO, 'INFO'],
|
18 | [exports.LOGGER_LEVELS.WARN, 'WARN'],
|
19 | [exports.LOGGER_LEVELS.ERROR, 'ERROR'],
|
20 | ]);
|
21 | function getLoggerLevelName(level) {
|
22 | if (level) {
|
23 | const levelName = exports.LOGGER_LEVEL_NAMES.get(level);
|
24 | if (levelName) {
|
25 | return levelName;
|
26 | }
|
27 | }
|
28 | }
|
29 | exports.getLoggerLevelName = getLoggerLevelName;
|
30 | function getLoggerLevelColor(colors, level) {
|
31 | const levelName = getLoggerLevelName(level);
|
32 | if (levelName) {
|
33 | return colors.log[levelName];
|
34 | }
|
35 | }
|
36 | exports.getLoggerLevelColor = getLoggerLevelColor;
|
37 | class StreamHandler {
|
38 | constructor({ stream, filter, formatter }) {
|
39 | this.stream = stream;
|
40 | this.filter = filter;
|
41 | this.formatter = formatter;
|
42 | }
|
43 | clone(opts) {
|
44 | const { stream, filter, formatter } = this;
|
45 | return new StreamHandler({ stream, filter, formatter, ...opts });
|
46 | }
|
47 | handle(record) {
|
48 | if (this.filter && !this.filter(record)) {
|
49 | return;
|
50 | }
|
51 | const msg = this.formatter && record.format !== false ? this.formatter(record) : record.msg;
|
52 | this.stream.write(utils_1.enforceLF(msg));
|
53 | }
|
54 | }
|
55 | exports.StreamHandler = StreamHandler;
|
56 | const stdoutLogRecordFilter = (record) => !record.level || record.level === exports.LOGGER_LEVELS.INFO;
|
57 | const stderrLogRecordFilter = (record) => !!record.level && record.level !== exports.LOGGER_LEVELS.INFO;
|
58 | exports.DEFAULT_LOGGER_HANDLERS = new Set([
|
59 | new StreamHandler({ stream: process.stdout, filter: stdoutLogRecordFilter }),
|
60 | new StreamHandler({ stream: process.stderr, filter: stderrLogRecordFilter }),
|
61 | ]);
|
62 | class Logger {
|
63 | constructor({ level = exports.LOGGER_LEVELS.INFO, handlers } = {}) {
|
64 | this.level = level;
|
65 | this.handlers = handlers ? handlers : Logger.cloneHandlers(exports.DEFAULT_LOGGER_HANDLERS);
|
66 | }
|
67 | static cloneHandlers(handlers) {
|
68 | return new Set([...handlers].map(handler => handler.clone()));
|
69 | }
|
70 | |
71 |
|
72 |
|
73 |
|
74 |
|
75 | clone(opts = {}) {
|
76 | const { level, handlers } = this;
|
77 | return new Logger({ level, handlers: Logger.cloneHandlers(handlers), ...opts });
|
78 | }
|
79 | |
80 |
|
81 |
|
82 |
|
83 |
|
84 | msg(msg) {
|
85 | this.log(this.createRecord(msg));
|
86 | }
|
87 | |
88 |
|
89 |
|
90 |
|
91 |
|
92 | debug(msg) {
|
93 | this.log(this.createRecord(msg, exports.LOGGER_LEVELS.DEBUG));
|
94 | }
|
95 | |
96 |
|
97 |
|
98 |
|
99 |
|
100 | info(msg) {
|
101 | this.log(this.createRecord(msg, exports.LOGGER_LEVELS.INFO));
|
102 | }
|
103 | |
104 |
|
105 |
|
106 |
|
107 |
|
108 | warn(msg) {
|
109 | this.log(this.createRecord(msg, exports.LOGGER_LEVELS.WARN));
|
110 | }
|
111 | |
112 |
|
113 |
|
114 |
|
115 |
|
116 | error(msg) {
|
117 | this.log(this.createRecord(msg, exports.LOGGER_LEVELS.ERROR));
|
118 | }
|
119 | createRecord(msg, level, format) {
|
120 | return {
|
121 |
|
122 |
|
123 | msg: util.format(msg),
|
124 | level,
|
125 | logger: this,
|
126 | format,
|
127 | };
|
128 | }
|
129 | |
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 | nl(num = 1, level) {
|
136 | this.log({ ...this.createRecord('\n'.repeat(num), level), format: false });
|
137 | }
|
138 | |
139 |
|
140 |
|
141 | log(record) {
|
142 | if (typeof record.level === 'number' && this.level > record.level) {
|
143 | return;
|
144 | }
|
145 | for (const handler of this.handlers) {
|
146 | handler.handle(record);
|
147 | }
|
148 | }
|
149 | createWriteStream(level, format) {
|
150 | const self = this;
|
151 | return new class extends stream_1.Writable {
|
152 | _write(chunk, encoding, callback) {
|
153 | self.log(self.createRecord(chunk.toString(), level, format));
|
154 | callback();
|
155 | }
|
156 | }();
|
157 | }
|
158 | }
|
159 | exports.Logger = Logger;
|
160 | function createTaggedFormatter({ colors = colors_1.NO_COLORS, prefix = '', tags, titleize, wrap } = {}) {
|
161 | const { strong, weak } = colors;
|
162 | const getLevelTag = (level) => {
|
163 | if (!level) {
|
164 | return '';
|
165 | }
|
166 | if (tags) {
|
167 | const tag = tags.get(level);
|
168 | return tag ? tag : '';
|
169 | }
|
170 | const levelName = getLoggerLevelName(level);
|
171 | if (!levelName) {
|
172 | return '';
|
173 | }
|
174 | const levelColor = getLoggerLevelColor(colors, level);
|
175 | return `${weak('[')}\x1b[40m${strong(levelColor ? levelColor(levelName) : levelName)}\x1b[49m${weak(']')}`;
|
176 | };
|
177 | return ({ msg, level, format }) => {
|
178 | if (format === false) {
|
179 | return msg;
|
180 | }
|
181 | const [firstLine, ...lines] = msg.split('\n');
|
182 | const levelColor = getLoggerLevelColor(colors, level);
|
183 | const tag = (typeof prefix === 'function' ? prefix() : prefix) + getLevelTag(level);
|
184 | const title = titleize && lines.length > 0 ? `${strong(levelColor ? levelColor(firstLine) : firstLine)}\n` : firstLine;
|
185 | const indentation = tag ? format_1.stringWidth(tag) + 1 : 0;
|
186 | const pulledLines = titleize ? utils_1.dropWhile(lines, l => l === '') : lines;
|
187 | return ((tag ? `${tag} ` : '') +
|
188 | (wrap
|
189 | ? format_1.wordWrap([title, ...pulledLines].join('\n'), { indentation, ...(typeof wrap === 'object' ? wrap : {}) })
|
190 | : [title, ...pulledLines.map(l => l ? ' '.repeat(indentation) + l : '')].join('\n')));
|
191 | };
|
192 | }
|
193 | exports.createTaggedFormatter = createTaggedFormatter;
|
194 | function createPrefixedFormatter(prefix) {
|
195 | return ({ msg, format }) => {
|
196 | if (format === false) {
|
197 | return msg;
|
198 | }
|
199 | return `${typeof prefix === 'function' ? prefix() : prefix} ${msg}`;
|
200 | };
|
201 | }
|
202 | exports.createPrefixedFormatter = createPrefixedFormatter;
|