@visulima/pail 4.0.0-alpha.1 → 4.0.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +204 -0
- package/LICENSE.md +434 -52
- package/README.md +323 -0
- package/dist/error.d.ts +104 -0
- package/dist/error.js +76 -0
- package/dist/index.browser.d.ts +3 -1
- package/dist/index.browser.js +1490 -3
- package/dist/index.server.d.ts +3 -5
- package/dist/index.server.js +2380 -110
- package/dist/middleware/elysia.d.ts +71 -0
- package/dist/middleware/elysia.js +70 -0
- package/dist/middleware/express.d.ts +86 -0
- package/dist/middleware/express.js +29 -0
- package/dist/middleware/fastify.d.ts +81 -0
- package/dist/middleware/fastify.js +46 -0
- package/dist/middleware/hono.d.ts +85 -0
- package/dist/middleware/hono.js +33 -0
- package/dist/middleware/next/handler.d.ts +36 -0
- package/dist/middleware/next/handler.js +53 -0
- package/dist/middleware/next/middleware.d.ts +59 -0
- package/dist/middleware/next/storage.d.ts +14 -0
- package/dist/middleware/shared/create-middleware-logger.d.ts +82 -0
- package/dist/middleware/shared/headers.d.ts +14 -0
- package/dist/middleware/shared/routes.d.ts +30 -0
- package/dist/middleware/shared/storage.d.ts +29 -0
- package/dist/middleware/sveltekit.d.ts +123 -0
- package/dist/middleware/sveltekit.js +43 -0
- package/dist/object-tree.d.ts +2 -2
- package/dist/object-tree.js +7 -7
- package/dist/packem_shared/{AbstractJsonReporter-BaZ33PlE.js → AbstractJsonReporter-BO8Calb4.js} +112 -32
- package/dist/packem_shared/AbstractJsonReporter-nOj0Ft1F.js +284 -0
- package/dist/packem_shared/{JsonReporter-BRw4skd5.js → JsonReporter-CCmj7oYL.js} +2 -2
- package/dist/packem_shared/{JsonReporter-VzgyLEYz.js → JsonReporter-Ck2PIAEw.js} +2 -2
- package/dist/packem_shared/PrettyReporter-BCvyNzXO.js +2720 -0
- package/dist/packem_shared/{PrettyReporter-DySIXBjQ.js → PrettyReporter-BtTr13Ha.js} +55 -11
- package/dist/packem_shared/abstract-pretty-reporter-CXAKYCb8.js +2635 -0
- package/dist/packem_shared/constants-B1RjD_ps.js +99 -0
- package/dist/packem_shared/createPailError-B_sgL0nF.js +76 -0
- package/dist/packem_shared/headers-BxHWM6KI.js +127 -0
- package/dist/packem_shared/{index-BomQ3E6J.js → index-Bx3-C0j9.js} +29 -21
- package/dist/packem_shared/pailMiddleware-Ci88geIF.js +24 -0
- package/dist/packem_shared/storage-D0vqz8OX.js +36 -0
- package/dist/packem_shared/{InteractiveStreamHook-DiSubbJ1.js → useLogger-D0rU3lcX.js} +13 -1
- package/dist/packem_shared/{write-console-log-based-on-level-DBmRYXpj.js → write-console-log-based-on-level-ree2lDPw.js} +5 -4
- package/dist/packem_shared/{write-stream-BG8fhcs3.js → write-stream-MDqyXmc_.js} +1 -1
- package/dist/pail.browser.d.ts +1 -1
- package/dist/pail.server.d.ts +1 -76
- package/dist/processor/caller/caller-processor.js +1 -1
- package/dist/processor/environment-processor.d.ts +124 -0
- package/dist/processor/environment-processor.js +89 -0
- package/dist/processor/message-formatter-processor.d.ts +2 -3
- package/dist/processor/message-formatter-processor.js +654 -5
- package/dist/processor/opentelemetry-processor.js +4 -4
- package/dist/processor/redact-processor.d.ts +1 -1
- package/dist/processor/redact-processor.js +2 -1
- package/dist/processor/sampling-processor.d.ts +111 -0
- package/dist/processor/sampling-processor.js +59 -0
- package/dist/reporter/file/json-file-reporter.js +1 -1
- package/dist/reporter/http/abstract-http-reporter.js +23 -26
- package/dist/reporter/http/http-reporter.edge-light.js +134 -57
- package/dist/reporter/json/abstract-json-reporter.d.ts +1 -1
- package/dist/reporter/json/index.browser.js +2 -2
- package/dist/reporter/json/index.js +2 -2
- package/dist/reporter/pretty/index.browser.js +1 -1
- package/dist/reporter/pretty/index.js +1 -1
- package/dist/reporter/pretty/pretty-reporter.server.d.ts +1 -1
- package/dist/reporter/raw/raw-reporter.server.d.ts +1 -1
- package/dist/reporter/simple/simple-reporter.server.d.ts +1 -1
- package/dist/reporter/simple/simple-reporter.server.js +8 -12
- package/dist/types.d.ts +4 -4
- package/dist/utils/write-console-log-based-on-level.d.ts +1 -1
- package/dist/wide-event.d.ts +300 -0
- package/dist/wide-event.js +284 -0
- package/package.json +73 -20
- package/dist/interactive/index.d.ts +0 -2
- package/dist/interactive/index.js +0 -2
- package/dist/interactive/interactive-manager.d.ts +0 -108
- package/dist/interactive/interactive-stream-hook.d.ts +0 -68
- package/dist/packem_shared/InteractiveManager-CZ85hGNW.js +0 -172
- package/dist/packem_shared/PrettyReporter-DgZB2eBG.js +0 -222
- package/dist/packem_shared/abstract-pretty-reporter-Di_sdm2r.js +0 -50
- package/dist/packem_shared/format-label-De49vNPd.js +0 -1193
- package/dist/packem_shared/get-longest-label-C9PWeyKq.js +0 -9
- package/dist/packem_shared/index-DqKWykfa.js +0 -1146
- package/dist/packem_shared/interactive-stream-hook-DG4BtN12.js +0 -141
- package/dist/packem_shared/pail.browser-u2CSR_af.js +0 -1427
- package/dist/progress-bar.d.ts +0 -136
- package/dist/progress-bar.js +0 -404
- package/dist/spinner.d.ts +0 -220
- package/dist/spinner.js +0 -2150
- package/dist/utils/ansi-escapes.d.ts +0 -4
package/dist/index.server.js
CHANGED
|
@@ -9,18 +9,1464 @@ const {
|
|
|
9
9
|
stderr,
|
|
10
10
|
env
|
|
11
11
|
} = __cjs_getProcess;
|
|
12
|
-
import InteractiveManager from '
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
import { InteractiveManager, InteractiveStreamHook } from '@visulima/interactive-manager';
|
|
13
|
+
import { g as getLongestLabel, E as EXTENDED_RFC_5424_LOG_LEVELS, a as EMPTY_SYMBOL, L as LOG_TYPES, i as inspect, w as writeStream, A as AbstractPrettyReporter, d as defaultInspectorConfig, t as terminalSize, b as getLongestBadge, c as getStringWidth, f as formatLabel, e as wordWrap, r as renderError, W as WrapMode } from './packem_shared/abstract-pretty-reporter-CXAKYCb8.js';
|
|
14
|
+
import colorize, { red, greenBright, cyan, green, grey, bgGrey, underline, white } from '@visulima/colorize';
|
|
15
|
+
export { PailError, createPailError } from './packem_shared/createPailError-B_sgL0nF.js';
|
|
16
|
+
|
|
17
|
+
const ESC = "\x1B";
|
|
18
|
+
const CSI = `${ESC}[`;
|
|
19
|
+
|
|
20
|
+
const isBrowser = typeof globalThis !== "undefined" && typeof globalThis.window === "object" && globalThis.window.document !== void 0;
|
|
21
|
+
const OSTYPE_REGEX = /^(?:msys|cygwin)$/;
|
|
22
|
+
const isWindows = !isBrowser && (process.platform === "win32" || OSTYPE_REGEX.test(process.env.OSTYPE));
|
|
23
|
+
|
|
24
|
+
var EraseDisplayMode = /* @__PURE__ */ ((EraseDisplayMode2) => {
|
|
25
|
+
EraseDisplayMode2[EraseDisplayMode2["ToEnd"] = 0] = "ToEnd";
|
|
26
|
+
EraseDisplayMode2[EraseDisplayMode2["ToBeginning"] = 1] = "ToBeginning";
|
|
27
|
+
EraseDisplayMode2[EraseDisplayMode2["EntireScreen"] = 2] = "EntireScreen";
|
|
28
|
+
EraseDisplayMode2[EraseDisplayMode2["EntireScreenAndScrollback"] = 3] = "EntireScreenAndScrollback";
|
|
29
|
+
return EraseDisplayMode2;
|
|
30
|
+
})(EraseDisplayMode || {});
|
|
31
|
+
const eraseDisplay = (mode) => {
|
|
32
|
+
const validMode = mode >= 0 && mode <= 3 ? mode : 0;
|
|
33
|
+
return `${CSI}${validMode === 0 ? "" : String(validMode)}J`;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const resetTerminal = isWindows ? `${eraseDisplay(EraseDisplayMode.EntireScreen)}${CSI}0f` : `${eraseDisplay(EraseDisplayMode.EntireScreen)}${eraseDisplay(EraseDisplayMode.EntireScreenAndScrollback)}${CSI}H${ESC}c`;
|
|
37
|
+
|
|
38
|
+
function getDefaultExportFromCjs(x) {
|
|
39
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
var safeStableStringify = {exports: {}};
|
|
43
|
+
|
|
44
|
+
var hasRequiredSafeStableStringify;
|
|
45
|
+
|
|
46
|
+
function requireSafeStableStringify () {
|
|
47
|
+
if (hasRequiredSafeStableStringify) return safeStableStringify.exports;
|
|
48
|
+
hasRequiredSafeStableStringify = 1;
|
|
49
|
+
(function (module, exports$1) {
|
|
50
|
+
const { hasOwnProperty } = Object.prototype;
|
|
51
|
+
const stringify = configure();
|
|
52
|
+
stringify.configure = configure;
|
|
53
|
+
stringify.stringify = stringify;
|
|
54
|
+
stringify.default = stringify;
|
|
55
|
+
exports$1.stringify = stringify;
|
|
56
|
+
exports$1.configure = configure;
|
|
57
|
+
module.exports = stringify;
|
|
58
|
+
const strEscapeSequencesRegExp = /[\u0000-\u001f\u0022\u005c\ud800-\udfff]/;
|
|
59
|
+
function strEscape(str) {
|
|
60
|
+
if (str.length < 5e3 && !strEscapeSequencesRegExp.test(str)) {
|
|
61
|
+
return `"${str}"`;
|
|
62
|
+
}
|
|
63
|
+
return JSON.stringify(str);
|
|
64
|
+
}
|
|
65
|
+
function sort(array, comparator) {
|
|
66
|
+
if (array.length > 200 || comparator) {
|
|
67
|
+
return array.sort(comparator);
|
|
68
|
+
}
|
|
69
|
+
for (let i = 1; i < array.length; i++) {
|
|
70
|
+
const currentValue = array[i];
|
|
71
|
+
let position = i;
|
|
72
|
+
while (position !== 0 && array[position - 1] > currentValue) {
|
|
73
|
+
array[position] = array[position - 1];
|
|
74
|
+
position--;
|
|
75
|
+
}
|
|
76
|
+
array[position] = currentValue;
|
|
77
|
+
}
|
|
78
|
+
return array;
|
|
79
|
+
}
|
|
80
|
+
const typedArrayPrototypeGetSymbolToStringTag = Object.getOwnPropertyDescriptor(
|
|
81
|
+
Object.getPrototypeOf(
|
|
82
|
+
Object.getPrototypeOf(
|
|
83
|
+
new Int8Array()
|
|
84
|
+
)
|
|
85
|
+
),
|
|
86
|
+
Symbol.toStringTag
|
|
87
|
+
).get;
|
|
88
|
+
function isTypedArrayWithEntries(value) {
|
|
89
|
+
return typedArrayPrototypeGetSymbolToStringTag.call(value) !== void 0 && value.length !== 0;
|
|
90
|
+
}
|
|
91
|
+
function stringifyTypedArray(array, separator, maximumBreadth) {
|
|
92
|
+
if (array.length < maximumBreadth) {
|
|
93
|
+
maximumBreadth = array.length;
|
|
94
|
+
}
|
|
95
|
+
const whitespace = separator === "," ? "" : " ";
|
|
96
|
+
let res = `"0":${whitespace}${array[0]}`;
|
|
97
|
+
for (let i = 1; i < maximumBreadth; i++) {
|
|
98
|
+
res += `${separator}"${i}":${whitespace}${array[i]}`;
|
|
99
|
+
}
|
|
100
|
+
return res;
|
|
101
|
+
}
|
|
102
|
+
function getCircularValueOption(options) {
|
|
103
|
+
if (hasOwnProperty.call(options, "circularValue")) {
|
|
104
|
+
const circularValue = options.circularValue;
|
|
105
|
+
if (typeof circularValue === "string") {
|
|
106
|
+
return `"${circularValue}"`;
|
|
107
|
+
}
|
|
108
|
+
if (circularValue == null) {
|
|
109
|
+
return circularValue;
|
|
110
|
+
}
|
|
111
|
+
if (circularValue === Error || circularValue === TypeError) {
|
|
112
|
+
return {
|
|
113
|
+
toString() {
|
|
114
|
+
throw new TypeError("Converting circular structure to JSON");
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
throw new TypeError('The "circularValue" argument must be of type string or the value null or undefined');
|
|
119
|
+
}
|
|
120
|
+
return '"[Circular]"';
|
|
121
|
+
}
|
|
122
|
+
function getDeterministicOption(options) {
|
|
123
|
+
let value;
|
|
124
|
+
if (hasOwnProperty.call(options, "deterministic")) {
|
|
125
|
+
value = options.deterministic;
|
|
126
|
+
if (typeof value !== "boolean" && typeof value !== "function") {
|
|
127
|
+
throw new TypeError('The "deterministic" argument must be of type boolean or comparator function');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return value === void 0 ? true : value;
|
|
131
|
+
}
|
|
132
|
+
function getBooleanOption(options, key) {
|
|
133
|
+
let value;
|
|
134
|
+
if (hasOwnProperty.call(options, key)) {
|
|
135
|
+
value = options[key];
|
|
136
|
+
if (typeof value !== "boolean") {
|
|
137
|
+
throw new TypeError(`The "${key}" argument must be of type boolean`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return value === void 0 ? true : value;
|
|
141
|
+
}
|
|
142
|
+
function getPositiveIntegerOption(options, key) {
|
|
143
|
+
let value;
|
|
144
|
+
if (hasOwnProperty.call(options, key)) {
|
|
145
|
+
value = options[key];
|
|
146
|
+
if (typeof value !== "number") {
|
|
147
|
+
throw new TypeError(`The "${key}" argument must be of type number`);
|
|
148
|
+
}
|
|
149
|
+
if (!Number.isInteger(value)) {
|
|
150
|
+
throw new TypeError(`The "${key}" argument must be an integer`);
|
|
151
|
+
}
|
|
152
|
+
if (value < 1) {
|
|
153
|
+
throw new RangeError(`The "${key}" argument must be >= 1`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return value === void 0 ? Infinity : value;
|
|
157
|
+
}
|
|
158
|
+
function getItemCount(number) {
|
|
159
|
+
if (number === 1) {
|
|
160
|
+
return "1 item";
|
|
161
|
+
}
|
|
162
|
+
return `${number} items`;
|
|
163
|
+
}
|
|
164
|
+
function getUniqueReplacerSet(replacerArray) {
|
|
165
|
+
const replacerSet = /* @__PURE__ */ new Set();
|
|
166
|
+
for (const value of replacerArray) {
|
|
167
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
168
|
+
replacerSet.add(String(value));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return replacerSet;
|
|
172
|
+
}
|
|
173
|
+
function getStrictOption(options) {
|
|
174
|
+
if (hasOwnProperty.call(options, "strict")) {
|
|
175
|
+
const value = options.strict;
|
|
176
|
+
if (typeof value !== "boolean") {
|
|
177
|
+
throw new TypeError('The "strict" argument must be of type boolean');
|
|
178
|
+
}
|
|
179
|
+
if (value) {
|
|
180
|
+
return (value2) => {
|
|
181
|
+
let message = `Object can not safely be stringified. Received type ${typeof value2}`;
|
|
182
|
+
if (typeof value2 !== "function") message += ` (${value2.toString()})`;
|
|
183
|
+
throw new Error(message);
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function configure(options) {
|
|
189
|
+
options = { ...options };
|
|
190
|
+
const fail = getStrictOption(options);
|
|
191
|
+
if (fail) {
|
|
192
|
+
if (options.bigint === void 0) {
|
|
193
|
+
options.bigint = false;
|
|
194
|
+
}
|
|
195
|
+
if (!("circularValue" in options)) {
|
|
196
|
+
options.circularValue = Error;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const circularValue = getCircularValueOption(options);
|
|
200
|
+
const bigint = getBooleanOption(options, "bigint");
|
|
201
|
+
const deterministic = getDeterministicOption(options);
|
|
202
|
+
const comparator = typeof deterministic === "function" ? deterministic : void 0;
|
|
203
|
+
const maximumDepth = getPositiveIntegerOption(options, "maximumDepth");
|
|
204
|
+
const maximumBreadth = getPositiveIntegerOption(options, "maximumBreadth");
|
|
205
|
+
function stringifyFnReplacer(key, parent, stack, replacer, spacer, indentation) {
|
|
206
|
+
let value = parent[key];
|
|
207
|
+
if (typeof value === "object" && value !== null && typeof value.toJSON === "function") {
|
|
208
|
+
value = value.toJSON(key);
|
|
209
|
+
}
|
|
210
|
+
value = replacer.call(parent, key, value);
|
|
211
|
+
switch (typeof value) {
|
|
212
|
+
case "string":
|
|
213
|
+
return strEscape(value);
|
|
214
|
+
case "object": {
|
|
215
|
+
if (value === null) {
|
|
216
|
+
return "null";
|
|
217
|
+
}
|
|
218
|
+
if (stack.indexOf(value) !== -1) {
|
|
219
|
+
return circularValue;
|
|
220
|
+
}
|
|
221
|
+
let res = "";
|
|
222
|
+
let join = ",";
|
|
223
|
+
const originalIndentation = indentation;
|
|
224
|
+
if (Array.isArray(value)) {
|
|
225
|
+
if (value.length === 0) {
|
|
226
|
+
return "[]";
|
|
227
|
+
}
|
|
228
|
+
if (maximumDepth < stack.length + 1) {
|
|
229
|
+
return '"[Array]"';
|
|
230
|
+
}
|
|
231
|
+
stack.push(value);
|
|
232
|
+
if (spacer !== "") {
|
|
233
|
+
indentation += spacer;
|
|
234
|
+
res += `
|
|
235
|
+
${indentation}`;
|
|
236
|
+
join = `,
|
|
237
|
+
${indentation}`;
|
|
238
|
+
}
|
|
239
|
+
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
240
|
+
let i = 0;
|
|
241
|
+
for (; i < maximumValuesToStringify - 1; i++) {
|
|
242
|
+
const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
243
|
+
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
244
|
+
res += join;
|
|
245
|
+
}
|
|
246
|
+
const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
247
|
+
res += tmp !== void 0 ? tmp : "null";
|
|
248
|
+
if (value.length - 1 > maximumBreadth) {
|
|
249
|
+
const removedKeys = value.length - maximumBreadth - 1;
|
|
250
|
+
res += `${join}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
251
|
+
}
|
|
252
|
+
if (spacer !== "") {
|
|
253
|
+
res += `
|
|
254
|
+
${originalIndentation}`;
|
|
255
|
+
}
|
|
256
|
+
stack.pop();
|
|
257
|
+
return `[${res}]`;
|
|
258
|
+
}
|
|
259
|
+
let keys = Object.keys(value);
|
|
260
|
+
const keyLength = keys.length;
|
|
261
|
+
if (keyLength === 0) {
|
|
262
|
+
return "{}";
|
|
263
|
+
}
|
|
264
|
+
if (maximumDepth < stack.length + 1) {
|
|
265
|
+
return '"[Object]"';
|
|
266
|
+
}
|
|
267
|
+
let whitespace = "";
|
|
268
|
+
let separator = "";
|
|
269
|
+
if (spacer !== "") {
|
|
270
|
+
indentation += spacer;
|
|
271
|
+
join = `,
|
|
272
|
+
${indentation}`;
|
|
273
|
+
whitespace = " ";
|
|
274
|
+
}
|
|
275
|
+
const maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
276
|
+
if (deterministic && !isTypedArrayWithEntries(value)) {
|
|
277
|
+
keys = sort(keys, comparator);
|
|
278
|
+
}
|
|
279
|
+
stack.push(value);
|
|
280
|
+
for (let i = 0; i < maximumPropertiesToStringify; i++) {
|
|
281
|
+
const key2 = keys[i];
|
|
282
|
+
const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
|
|
283
|
+
if (tmp !== void 0) {
|
|
284
|
+
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
285
|
+
separator = join;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (keyLength > maximumBreadth) {
|
|
289
|
+
const removedKeys = keyLength - maximumBreadth;
|
|
290
|
+
res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
|
|
291
|
+
separator = join;
|
|
292
|
+
}
|
|
293
|
+
if (spacer !== "" && separator.length > 1) {
|
|
294
|
+
res = `
|
|
295
|
+
${indentation}${res}
|
|
296
|
+
${originalIndentation}`;
|
|
297
|
+
}
|
|
298
|
+
stack.pop();
|
|
299
|
+
return `{${res}}`;
|
|
300
|
+
}
|
|
301
|
+
case "number":
|
|
302
|
+
return isFinite(value) ? String(value) : fail ? fail(value) : "null";
|
|
303
|
+
case "boolean":
|
|
304
|
+
return value === true ? "true" : "false";
|
|
305
|
+
case "undefined":
|
|
306
|
+
return void 0;
|
|
307
|
+
case "bigint":
|
|
308
|
+
if (bigint) {
|
|
309
|
+
return String(value);
|
|
310
|
+
}
|
|
311
|
+
// fallthrough
|
|
312
|
+
default:
|
|
313
|
+
return fail ? fail(value) : void 0;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function stringifyArrayReplacer(key, value, stack, replacer, spacer, indentation) {
|
|
317
|
+
if (typeof value === "object" && value !== null && typeof value.toJSON === "function") {
|
|
318
|
+
value = value.toJSON(key);
|
|
319
|
+
}
|
|
320
|
+
switch (typeof value) {
|
|
321
|
+
case "string":
|
|
322
|
+
return strEscape(value);
|
|
323
|
+
case "object": {
|
|
324
|
+
if (value === null) {
|
|
325
|
+
return "null";
|
|
326
|
+
}
|
|
327
|
+
if (stack.indexOf(value) !== -1) {
|
|
328
|
+
return circularValue;
|
|
329
|
+
}
|
|
330
|
+
const originalIndentation = indentation;
|
|
331
|
+
let res = "";
|
|
332
|
+
let join = ",";
|
|
333
|
+
if (Array.isArray(value)) {
|
|
334
|
+
if (value.length === 0) {
|
|
335
|
+
return "[]";
|
|
336
|
+
}
|
|
337
|
+
if (maximumDepth < stack.length + 1) {
|
|
338
|
+
return '"[Array]"';
|
|
339
|
+
}
|
|
340
|
+
stack.push(value);
|
|
341
|
+
if (spacer !== "") {
|
|
342
|
+
indentation += spacer;
|
|
343
|
+
res += `
|
|
344
|
+
${indentation}`;
|
|
345
|
+
join = `,
|
|
346
|
+
${indentation}`;
|
|
347
|
+
}
|
|
348
|
+
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
349
|
+
let i = 0;
|
|
350
|
+
for (; i < maximumValuesToStringify - 1; i++) {
|
|
351
|
+
const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
352
|
+
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
353
|
+
res += join;
|
|
354
|
+
}
|
|
355
|
+
const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
356
|
+
res += tmp !== void 0 ? tmp : "null";
|
|
357
|
+
if (value.length - 1 > maximumBreadth) {
|
|
358
|
+
const removedKeys = value.length - maximumBreadth - 1;
|
|
359
|
+
res += `${join}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
360
|
+
}
|
|
361
|
+
if (spacer !== "") {
|
|
362
|
+
res += `
|
|
363
|
+
${originalIndentation}`;
|
|
364
|
+
}
|
|
365
|
+
stack.pop();
|
|
366
|
+
return `[${res}]`;
|
|
367
|
+
}
|
|
368
|
+
stack.push(value);
|
|
369
|
+
let whitespace = "";
|
|
370
|
+
if (spacer !== "") {
|
|
371
|
+
indentation += spacer;
|
|
372
|
+
join = `,
|
|
373
|
+
${indentation}`;
|
|
374
|
+
whitespace = " ";
|
|
375
|
+
}
|
|
376
|
+
let separator = "";
|
|
377
|
+
for (const key2 of replacer) {
|
|
378
|
+
const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
|
|
379
|
+
if (tmp !== void 0) {
|
|
380
|
+
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
381
|
+
separator = join;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (spacer !== "" && separator.length > 1) {
|
|
385
|
+
res = `
|
|
386
|
+
${indentation}${res}
|
|
387
|
+
${originalIndentation}`;
|
|
388
|
+
}
|
|
389
|
+
stack.pop();
|
|
390
|
+
return `{${res}}`;
|
|
391
|
+
}
|
|
392
|
+
case "number":
|
|
393
|
+
return isFinite(value) ? String(value) : fail ? fail(value) : "null";
|
|
394
|
+
case "boolean":
|
|
395
|
+
return value === true ? "true" : "false";
|
|
396
|
+
case "undefined":
|
|
397
|
+
return void 0;
|
|
398
|
+
case "bigint":
|
|
399
|
+
if (bigint) {
|
|
400
|
+
return String(value);
|
|
401
|
+
}
|
|
402
|
+
// fallthrough
|
|
403
|
+
default:
|
|
404
|
+
return fail ? fail(value) : void 0;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function stringifyIndent(key, value, stack, spacer, indentation) {
|
|
408
|
+
switch (typeof value) {
|
|
409
|
+
case "string":
|
|
410
|
+
return strEscape(value);
|
|
411
|
+
case "object": {
|
|
412
|
+
if (value === null) {
|
|
413
|
+
return "null";
|
|
414
|
+
}
|
|
415
|
+
if (typeof value.toJSON === "function") {
|
|
416
|
+
value = value.toJSON(key);
|
|
417
|
+
if (typeof value !== "object") {
|
|
418
|
+
return stringifyIndent(key, value, stack, spacer, indentation);
|
|
419
|
+
}
|
|
420
|
+
if (value === null) {
|
|
421
|
+
return "null";
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (stack.indexOf(value) !== -1) {
|
|
425
|
+
return circularValue;
|
|
426
|
+
}
|
|
427
|
+
const originalIndentation = indentation;
|
|
428
|
+
if (Array.isArray(value)) {
|
|
429
|
+
if (value.length === 0) {
|
|
430
|
+
return "[]";
|
|
431
|
+
}
|
|
432
|
+
if (maximumDepth < stack.length + 1) {
|
|
433
|
+
return '"[Array]"';
|
|
434
|
+
}
|
|
435
|
+
stack.push(value);
|
|
436
|
+
indentation += spacer;
|
|
437
|
+
let res2 = `
|
|
438
|
+
${indentation}`;
|
|
439
|
+
const join2 = `,
|
|
440
|
+
${indentation}`;
|
|
441
|
+
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
442
|
+
let i = 0;
|
|
443
|
+
for (; i < maximumValuesToStringify - 1; i++) {
|
|
444
|
+
const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
445
|
+
res2 += tmp2 !== void 0 ? tmp2 : "null";
|
|
446
|
+
res2 += join2;
|
|
447
|
+
}
|
|
448
|
+
const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
449
|
+
res2 += tmp !== void 0 ? tmp : "null";
|
|
450
|
+
if (value.length - 1 > maximumBreadth) {
|
|
451
|
+
const removedKeys = value.length - maximumBreadth - 1;
|
|
452
|
+
res2 += `${join2}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
453
|
+
}
|
|
454
|
+
res2 += `
|
|
455
|
+
${originalIndentation}`;
|
|
456
|
+
stack.pop();
|
|
457
|
+
return `[${res2}]`;
|
|
458
|
+
}
|
|
459
|
+
let keys = Object.keys(value);
|
|
460
|
+
const keyLength = keys.length;
|
|
461
|
+
if (keyLength === 0) {
|
|
462
|
+
return "{}";
|
|
463
|
+
}
|
|
464
|
+
if (maximumDepth < stack.length + 1) {
|
|
465
|
+
return '"[Object]"';
|
|
466
|
+
}
|
|
467
|
+
indentation += spacer;
|
|
468
|
+
const join = `,
|
|
469
|
+
${indentation}`;
|
|
470
|
+
let res = "";
|
|
471
|
+
let separator = "";
|
|
472
|
+
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
473
|
+
if (isTypedArrayWithEntries(value)) {
|
|
474
|
+
res += stringifyTypedArray(value, join, maximumBreadth);
|
|
475
|
+
keys = keys.slice(value.length);
|
|
476
|
+
maximumPropertiesToStringify -= value.length;
|
|
477
|
+
separator = join;
|
|
478
|
+
}
|
|
479
|
+
if (deterministic) {
|
|
480
|
+
keys = sort(keys, comparator);
|
|
481
|
+
}
|
|
482
|
+
stack.push(value);
|
|
483
|
+
for (let i = 0; i < maximumPropertiesToStringify; i++) {
|
|
484
|
+
const key2 = keys[i];
|
|
485
|
+
const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
|
|
486
|
+
if (tmp !== void 0) {
|
|
487
|
+
res += `${separator}${strEscape(key2)}: ${tmp}`;
|
|
488
|
+
separator = join;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (keyLength > maximumBreadth) {
|
|
492
|
+
const removedKeys = keyLength - maximumBreadth;
|
|
493
|
+
res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
|
|
494
|
+
separator = join;
|
|
495
|
+
}
|
|
496
|
+
if (separator !== "") {
|
|
497
|
+
res = `
|
|
498
|
+
${indentation}${res}
|
|
499
|
+
${originalIndentation}`;
|
|
500
|
+
}
|
|
501
|
+
stack.pop();
|
|
502
|
+
return `{${res}}`;
|
|
503
|
+
}
|
|
504
|
+
case "number":
|
|
505
|
+
return isFinite(value) ? String(value) : fail ? fail(value) : "null";
|
|
506
|
+
case "boolean":
|
|
507
|
+
return value === true ? "true" : "false";
|
|
508
|
+
case "undefined":
|
|
509
|
+
return void 0;
|
|
510
|
+
case "bigint":
|
|
511
|
+
if (bigint) {
|
|
512
|
+
return String(value);
|
|
513
|
+
}
|
|
514
|
+
// fallthrough
|
|
515
|
+
default:
|
|
516
|
+
return fail ? fail(value) : void 0;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
function stringifySimple(key, value, stack) {
|
|
520
|
+
switch (typeof value) {
|
|
521
|
+
case "string":
|
|
522
|
+
return strEscape(value);
|
|
523
|
+
case "object": {
|
|
524
|
+
if (value === null) {
|
|
525
|
+
return "null";
|
|
526
|
+
}
|
|
527
|
+
if (typeof value.toJSON === "function") {
|
|
528
|
+
value = value.toJSON(key);
|
|
529
|
+
if (typeof value !== "object") {
|
|
530
|
+
return stringifySimple(key, value, stack);
|
|
531
|
+
}
|
|
532
|
+
if (value === null) {
|
|
533
|
+
return "null";
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
if (stack.indexOf(value) !== -1) {
|
|
537
|
+
return circularValue;
|
|
538
|
+
}
|
|
539
|
+
let res = "";
|
|
540
|
+
const hasLength = value.length !== void 0;
|
|
541
|
+
if (hasLength && Array.isArray(value)) {
|
|
542
|
+
if (value.length === 0) {
|
|
543
|
+
return "[]";
|
|
544
|
+
}
|
|
545
|
+
if (maximumDepth < stack.length + 1) {
|
|
546
|
+
return '"[Array]"';
|
|
547
|
+
}
|
|
548
|
+
stack.push(value);
|
|
549
|
+
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
550
|
+
let i = 0;
|
|
551
|
+
for (; i < maximumValuesToStringify - 1; i++) {
|
|
552
|
+
const tmp2 = stringifySimple(String(i), value[i], stack);
|
|
553
|
+
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
554
|
+
res += ",";
|
|
555
|
+
}
|
|
556
|
+
const tmp = stringifySimple(String(i), value[i], stack);
|
|
557
|
+
res += tmp !== void 0 ? tmp : "null";
|
|
558
|
+
if (value.length - 1 > maximumBreadth) {
|
|
559
|
+
const removedKeys = value.length - maximumBreadth - 1;
|
|
560
|
+
res += `,"... ${getItemCount(removedKeys)} not stringified"`;
|
|
561
|
+
}
|
|
562
|
+
stack.pop();
|
|
563
|
+
return `[${res}]`;
|
|
564
|
+
}
|
|
565
|
+
let keys = Object.keys(value);
|
|
566
|
+
const keyLength = keys.length;
|
|
567
|
+
if (keyLength === 0) {
|
|
568
|
+
return "{}";
|
|
569
|
+
}
|
|
570
|
+
if (maximumDepth < stack.length + 1) {
|
|
571
|
+
return '"[Object]"';
|
|
572
|
+
}
|
|
573
|
+
let separator = "";
|
|
574
|
+
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
575
|
+
if (hasLength && isTypedArrayWithEntries(value)) {
|
|
576
|
+
res += stringifyTypedArray(value, ",", maximumBreadth);
|
|
577
|
+
keys = keys.slice(value.length);
|
|
578
|
+
maximumPropertiesToStringify -= value.length;
|
|
579
|
+
separator = ",";
|
|
580
|
+
}
|
|
581
|
+
if (deterministic) {
|
|
582
|
+
keys = sort(keys, comparator);
|
|
583
|
+
}
|
|
584
|
+
stack.push(value);
|
|
585
|
+
for (let i = 0; i < maximumPropertiesToStringify; i++) {
|
|
586
|
+
const key2 = keys[i];
|
|
587
|
+
const tmp = stringifySimple(key2, value[key2], stack);
|
|
588
|
+
if (tmp !== void 0) {
|
|
589
|
+
res += `${separator}${strEscape(key2)}:${tmp}`;
|
|
590
|
+
separator = ",";
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
if (keyLength > maximumBreadth) {
|
|
594
|
+
const removedKeys = keyLength - maximumBreadth;
|
|
595
|
+
res += `${separator}"...":"${getItemCount(removedKeys)} not stringified"`;
|
|
596
|
+
}
|
|
597
|
+
stack.pop();
|
|
598
|
+
return `{${res}}`;
|
|
599
|
+
}
|
|
600
|
+
case "number":
|
|
601
|
+
return isFinite(value) ? String(value) : fail ? fail(value) : "null";
|
|
602
|
+
case "boolean":
|
|
603
|
+
return value === true ? "true" : "false";
|
|
604
|
+
case "undefined":
|
|
605
|
+
return void 0;
|
|
606
|
+
case "bigint":
|
|
607
|
+
if (bigint) {
|
|
608
|
+
return String(value);
|
|
609
|
+
}
|
|
610
|
+
// fallthrough
|
|
611
|
+
default:
|
|
612
|
+
return fail ? fail(value) : void 0;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
function stringify2(value, replacer, space) {
|
|
616
|
+
if (arguments.length > 1) {
|
|
617
|
+
let spacer = "";
|
|
618
|
+
if (typeof space === "number") {
|
|
619
|
+
spacer = " ".repeat(Math.min(space, 10));
|
|
620
|
+
} else if (typeof space === "string") {
|
|
621
|
+
spacer = space.slice(0, 10);
|
|
622
|
+
}
|
|
623
|
+
if (replacer != null) {
|
|
624
|
+
if (typeof replacer === "function") {
|
|
625
|
+
return stringifyFnReplacer("", { "": value }, [], replacer, spacer, "");
|
|
626
|
+
}
|
|
627
|
+
if (Array.isArray(replacer)) {
|
|
628
|
+
return stringifyArrayReplacer("", value, [], getUniqueReplacerSet(replacer), spacer, "");
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
if (spacer.length !== 0) {
|
|
632
|
+
return stringifyIndent("", value, [], spacer, "");
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
return stringifySimple("", value, []);
|
|
636
|
+
}
|
|
637
|
+
return stringify2;
|
|
638
|
+
}
|
|
639
|
+
} (safeStableStringify, safeStableStringify.exports));
|
|
640
|
+
return safeStableStringify.exports;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
var safeStableStringifyExports = requireSafeStableStringify();
|
|
644
|
+
const cjsModule = /*@__PURE__*/getDefaultExportFromCjs(safeStableStringifyExports);
|
|
645
|
+
|
|
646
|
+
const configure = cjsModule.configure;
|
|
647
|
+
|
|
648
|
+
const writeConsoleLogBasedOnLevel = (level) => {
|
|
649
|
+
const c = console;
|
|
650
|
+
if (level === "error") {
|
|
651
|
+
return c.__error ?? console.error;
|
|
652
|
+
}
|
|
653
|
+
if (level === "warn") {
|
|
654
|
+
return c.__warn ?? console.warn;
|
|
655
|
+
}
|
|
656
|
+
if (level === "trace") {
|
|
657
|
+
return c.__trace ?? console.trace;
|
|
658
|
+
}
|
|
659
|
+
return c.__log ?? console.log;
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
let RawReporter$1 = class RawReporter {
|
|
663
|
+
// eslint-disable-next-line class-methods-use-this
|
|
664
|
+
log(meta) {
|
|
665
|
+
const { context = [], message, type } = meta;
|
|
666
|
+
const consoleLogFunction = writeConsoleLogBasedOnLevel(type.level);
|
|
667
|
+
consoleLogFunction(message, ...context);
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
const arrayify = (x) => {
|
|
672
|
+
if (x === void 0) {
|
|
673
|
+
return [];
|
|
674
|
+
}
|
|
675
|
+
return Array.isArray(x) ? x : [x];
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
const mergeTypes = (standard, custom) => {
|
|
679
|
+
const types = { ...standard };
|
|
680
|
+
Object.keys(custom).forEach((type) => {
|
|
681
|
+
types[type] = { ...types[type], ...custom[type] };
|
|
682
|
+
});
|
|
683
|
+
return types;
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
const preventLoop = (function_) => {
|
|
687
|
+
let doing = false;
|
|
688
|
+
return function(...args) {
|
|
689
|
+
if (doing) {
|
|
690
|
+
return void 0;
|
|
691
|
+
}
|
|
692
|
+
doing = true;
|
|
693
|
+
try {
|
|
694
|
+
const result = function_.apply(this, args);
|
|
695
|
+
doing = false;
|
|
696
|
+
return result;
|
|
697
|
+
} catch (error) {
|
|
698
|
+
doing = false;
|
|
699
|
+
throw error;
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
};
|
|
703
|
+
class PailBrowserImpl {
|
|
704
|
+
timersMap;
|
|
705
|
+
countMap;
|
|
706
|
+
seqTimers;
|
|
707
|
+
lastLog;
|
|
708
|
+
logLevels;
|
|
709
|
+
disabled;
|
|
710
|
+
paused;
|
|
711
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
712
|
+
messageQueue;
|
|
713
|
+
scopeName;
|
|
714
|
+
types;
|
|
715
|
+
longestLabel;
|
|
716
|
+
processors;
|
|
717
|
+
generalLogLevel;
|
|
718
|
+
reporters;
|
|
719
|
+
throttle;
|
|
720
|
+
throttleMin;
|
|
721
|
+
stringify;
|
|
722
|
+
groups;
|
|
723
|
+
startTimerMessage;
|
|
724
|
+
endTimerMessage;
|
|
725
|
+
rawReporter;
|
|
726
|
+
force = {};
|
|
727
|
+
/**
|
|
728
|
+
* Creates a new Pail browser logger instance.
|
|
729
|
+
*
|
|
730
|
+
* Initializes the logger with the provided configuration options,
|
|
731
|
+
* setting up reporters, processors, log levels, and other internal state.
|
|
732
|
+
* @param options Configuration options for the logger
|
|
733
|
+
*/
|
|
734
|
+
constructor(options) {
|
|
735
|
+
this.throttle = options.throttle ?? 1e3;
|
|
736
|
+
this.throttleMin = options.throttleMin ?? 5;
|
|
737
|
+
const parentLongestLabel = options.parentLongestLabel;
|
|
738
|
+
const parentTypes = options.parentTypes;
|
|
739
|
+
const parentStringify = options.parentStringify;
|
|
740
|
+
const parentLogLevels = options.parentLogLevels;
|
|
741
|
+
this.stringify = parentStringify ?? configure({
|
|
742
|
+
strict: true
|
|
743
|
+
});
|
|
744
|
+
this.startTimerMessage = options.messages?.timerStart ?? "Initialized timer...";
|
|
745
|
+
this.endTimerMessage = options.messages?.timerEnd ?? "Timer run for:";
|
|
746
|
+
if (parentTypes && parentLongestLabel) {
|
|
747
|
+
this.types = parentTypes;
|
|
748
|
+
this.longestLabel = parentLongestLabel;
|
|
749
|
+
} else {
|
|
750
|
+
this.types = mergeTypes(LOG_TYPES, options.types ?? {});
|
|
751
|
+
this.longestLabel = getLongestLabel(this.types);
|
|
752
|
+
}
|
|
753
|
+
this.logLevels = parentLogLevels && !options.logLevels ? parentLogLevels : { ...EXTENDED_RFC_5424_LOG_LEVELS, ...options.logLevels };
|
|
754
|
+
this.generalLogLevel = this.#normalizeLogLevel(options.logLevel);
|
|
755
|
+
this.reporters = /* @__PURE__ */ new Set();
|
|
756
|
+
this.processors = /* @__PURE__ */ new Set();
|
|
757
|
+
this.disabled = options.disabled ?? false;
|
|
758
|
+
this.paused = false;
|
|
759
|
+
this.messageQueue = [];
|
|
760
|
+
this.scopeName = arrayify(options.scope).filter(Boolean);
|
|
761
|
+
this.timersMap = /* @__PURE__ */ new Map();
|
|
762
|
+
this.countMap = /* @__PURE__ */ new Map();
|
|
763
|
+
this.groups = [];
|
|
764
|
+
this.seqTimers = /* @__PURE__ */ new Set();
|
|
765
|
+
this.lastLog = {};
|
|
766
|
+
this.logger = preventLoop(this.logger.bind(this));
|
|
767
|
+
this.#initializeBoundMethods();
|
|
768
|
+
if (Array.isArray(options.reporters)) {
|
|
769
|
+
this.registerReporters(options.reporters);
|
|
770
|
+
}
|
|
771
|
+
this.rawReporter = this.extendReporter(options.rawReporter ?? new RawReporter$1());
|
|
772
|
+
if (Array.isArray(options.processors)) {
|
|
773
|
+
this.registerProcessors(options.processors);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Initializes bound methods for all logger types.
|
|
778
|
+
*
|
|
779
|
+
* Creates bound methods for both regular and force logging methods.
|
|
780
|
+
* This is separated to allow reuse when types haven't changed.
|
|
781
|
+
*/
|
|
782
|
+
#initializeBoundMethods() {
|
|
783
|
+
for (const type in this.types) {
|
|
784
|
+
this[type] = this.logger.bind(this, type, false, false);
|
|
785
|
+
}
|
|
786
|
+
for (const type in this.types) {
|
|
787
|
+
this.force[type] = this.logger.bind(this, type, false, true);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* Wraps the global console methods to redirect them through the logger.
|
|
792
|
+
*
|
|
793
|
+
* This method replaces console methods (log, info, warn, error, etc.) with
|
|
794
|
+
* calls to the corresponding logger methods. The original console methods
|
|
795
|
+
* are backed up and can be restored using restoreConsole().
|
|
796
|
+
* @example
|
|
797
|
+
* ```typescript
|
|
798
|
+
* const logger = createPail();
|
|
799
|
+
* logger.wrapConsole();
|
|
800
|
+
*
|
|
801
|
+
* console.log("This will go through the logger");
|
|
802
|
+
* console.error("This too!");
|
|
803
|
+
*
|
|
804
|
+
* logger.restoreConsole(); // Restore original console methods
|
|
805
|
+
* ```
|
|
806
|
+
*/
|
|
807
|
+
wrapConsole() {
|
|
808
|
+
for (const type in this.types) {
|
|
809
|
+
if (!console[`__${type}`]) {
|
|
810
|
+
console[`__${type}`] = console[type];
|
|
811
|
+
}
|
|
812
|
+
console[type] = this[type];
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
816
|
+
* Restores the original global console methods.
|
|
817
|
+
*
|
|
818
|
+
* This method restores the console methods that were backed up by wrapConsole().
|
|
819
|
+
* After calling this, console methods will work as they did before wrapping.
|
|
820
|
+
* @example
|
|
821
|
+
* ```typescript
|
|
822
|
+
* const logger = createPail();
|
|
823
|
+
* logger.wrapConsole();
|
|
824
|
+
*
|
|
825
|
+
* // Console methods are now wrapped
|
|
826
|
+
* logger.restoreConsole();
|
|
827
|
+
* // Console methods are restored to original behavior
|
|
828
|
+
* ```
|
|
829
|
+
*/
|
|
830
|
+
restoreConsole() {
|
|
831
|
+
for (const type in this.types) {
|
|
832
|
+
if (console[`__${type}`]) {
|
|
833
|
+
console[type] = console[`__${type}`];
|
|
834
|
+
delete console[`__${type}`];
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* Wraps uncaught exception and unhandled rejection handlers.
|
|
840
|
+
*
|
|
841
|
+
* This method sets up global error handlers that will log uncaught exceptions
|
|
842
|
+
* and unhandled promise rejections through the logger. This is useful for
|
|
843
|
+
* capturing and logging application crashes.
|
|
844
|
+
* @example
|
|
845
|
+
* ```typescript
|
|
846
|
+
* const logger = createPail();
|
|
847
|
+
* logger.wrapException();
|
|
848
|
+
*
|
|
849
|
+
* // Now uncaught errors will be logged
|
|
850
|
+
* throw new Error("This will be logged");
|
|
851
|
+
* ```
|
|
852
|
+
*/
|
|
853
|
+
wrapException() {
|
|
854
|
+
{
|
|
855
|
+
process.on("uncaughtException", (error) => {
|
|
856
|
+
this.error(error);
|
|
857
|
+
});
|
|
858
|
+
process.on("unhandledRejection", (error) => {
|
|
859
|
+
this.error(error);
|
|
860
|
+
});
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
/**
|
|
864
|
+
* Disables all logging output.
|
|
865
|
+
*
|
|
866
|
+
* When disabled, all log calls will be silently ignored and no output
|
|
867
|
+
* will be produced by any reporters. This can be useful for temporarily
|
|
868
|
+
* suppressing log output in production or during testing.
|
|
869
|
+
* @example
|
|
870
|
+
* ```typescript
|
|
871
|
+
* const logger = createPail();
|
|
872
|
+
* logger.disable();
|
|
873
|
+
* logger.info("This won't be logged"); // Silent
|
|
874
|
+
* logger.enable();
|
|
875
|
+
* logger.info("This will be logged"); // Output produced
|
|
876
|
+
* ```
|
|
877
|
+
*/
|
|
878
|
+
disable() {
|
|
879
|
+
this.disabled = true;
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Enables logging output.
|
|
883
|
+
*
|
|
884
|
+
* Re-enables logging after it has been disabled. All subsequent log calls
|
|
885
|
+
* will produce output according to the configured reporters.
|
|
886
|
+
* @example
|
|
887
|
+
* ```typescript
|
|
888
|
+
* const logger = createPail();
|
|
889
|
+
* logger.disable();
|
|
890
|
+
* logger.info("This won't be logged");
|
|
891
|
+
* logger.enable(); // Re-enable logging
|
|
892
|
+
* logger.info("This will be logged");
|
|
893
|
+
* ```
|
|
894
|
+
*/
|
|
895
|
+
enable() {
|
|
896
|
+
this.disabled = false;
|
|
897
|
+
}
|
|
898
|
+
/**
|
|
899
|
+
* Checks if logging is currently enabled.
|
|
900
|
+
*
|
|
901
|
+
* Returns true if logging is enabled and false if it has been disabled.
|
|
902
|
+
* @returns True if logging is enabled, false if disabled
|
|
903
|
+
* @example
|
|
904
|
+
* ```typescript
|
|
905
|
+
* const logger = createPail();
|
|
906
|
+
* console.log(logger.isEnabled()); // true
|
|
907
|
+
* logger.disable();
|
|
908
|
+
* console.log(logger.isEnabled()); // false
|
|
909
|
+
* ```
|
|
910
|
+
*/
|
|
911
|
+
isEnabled() {
|
|
912
|
+
return !this.disabled;
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* Pauses logging and starts queuing messages.
|
|
916
|
+
*
|
|
917
|
+
* When paused, all log calls will be queued instead of being output immediately.
|
|
918
|
+
* The queued messages will be processed when resume() is called. This is useful
|
|
919
|
+
* for temporarily buffering log output during critical operations.
|
|
920
|
+
* @example
|
|
921
|
+
* ```typescript
|
|
922
|
+
* const logger = createPail();
|
|
923
|
+
* logger.pause();
|
|
924
|
+
* logger.info("This will be queued"); // Queued, not output yet
|
|
925
|
+
* logger.warn("This too"); // Also queued
|
|
926
|
+
* logger.resume(); // Now both messages are output
|
|
927
|
+
* ```
|
|
928
|
+
*/
|
|
929
|
+
pause() {
|
|
930
|
+
this.paused = true;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Resumes logging and flushes all queued messages.
|
|
934
|
+
*
|
|
935
|
+
* Processes all messages that were queued during the pause period and
|
|
936
|
+
* resumes normal logging behavior. Messages are output in the order
|
|
937
|
+
* they were originally called.
|
|
938
|
+
* @example
|
|
939
|
+
* ```typescript
|
|
940
|
+
* const logger = createPail();
|
|
941
|
+
* logger.pause();
|
|
942
|
+
* logger.info("Message 1"); // Queued
|
|
943
|
+
* logger.info("Message 2"); // Queued
|
|
944
|
+
* logger.resume(); // Both messages are now output in order
|
|
945
|
+
* logger.info("Message 3"); // Output immediately
|
|
946
|
+
* ```
|
|
947
|
+
*/
|
|
948
|
+
resume() {
|
|
949
|
+
this.paused = false;
|
|
950
|
+
const queue = this.messageQueue.splice(0);
|
|
951
|
+
for (let i = 0; i < queue.length; i += 1) {
|
|
952
|
+
const { messageObject, raw, type } = queue[i];
|
|
953
|
+
this.logger(type, raw, false, ...messageObject);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* Creates a scoped logger instance.
|
|
958
|
+
*
|
|
959
|
+
* Returns a new logger instance that inherits all configuration but adds
|
|
960
|
+
* the specified scope names to all log messages. This is useful for
|
|
961
|
+
* categorizing logs by component, module, or feature.
|
|
962
|
+
* @template N - The new custom logger type names
|
|
963
|
+
* @param name Scope names to apply to all log messages
|
|
964
|
+
* @returns A new scoped logger instance
|
|
965
|
+
* @throws {Error} If no scope name is provided
|
|
966
|
+
* @example
|
|
967
|
+
* ```typescript
|
|
968
|
+
* const logger = createPail();
|
|
969
|
+
* const scopedLogger = logger.scope("auth", "login");
|
|
970
|
+
* scopedLogger.info("User logged in"); // Will include scope: ["auth", "login"]
|
|
971
|
+
* ```
|
|
972
|
+
*/
|
|
973
|
+
scope(...name) {
|
|
974
|
+
if (name.length === 0) {
|
|
975
|
+
throw new Error("No scope name was defined.");
|
|
976
|
+
}
|
|
977
|
+
this.scopeName = name.flat();
|
|
978
|
+
return this;
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* Removes the current scope from the logger.
|
|
982
|
+
*
|
|
983
|
+
* Clears all scope names that were set by previous scope() calls.
|
|
984
|
+
* After calling this, log messages will no longer include scope information.
|
|
985
|
+
* @example
|
|
986
|
+
* ```typescript
|
|
987
|
+
* const logger = createPail();
|
|
988
|
+
* const scopedLogger = logger.scope("auth");
|
|
989
|
+
* scopedLogger.info("Scoped message"); // Has scope
|
|
990
|
+
* scopedLogger.unscope();
|
|
991
|
+
* scopedLogger.info("Unscoped message"); // No scope
|
|
992
|
+
* ```
|
|
993
|
+
*/
|
|
994
|
+
unscope() {
|
|
995
|
+
this.scopeName = [];
|
|
996
|
+
}
|
|
997
|
+
/**
|
|
998
|
+
* Creates a child logger that inherits settings from the parent.
|
|
999
|
+
*
|
|
1000
|
+
* Returns a new logger instance that inherits all configuration from the parent
|
|
1001
|
+
* (reporters, processors, types, log levels, throttle settings, etc.) while allowing
|
|
1002
|
+
* you to override only what you need. Child loggers are independent instances with
|
|
1003
|
+
* their own state (timers, counters, etc.).
|
|
1004
|
+
* @template N - The new custom logger type names
|
|
1005
|
+
* @template LC - The new log level types
|
|
1006
|
+
* @param options Configuration options to override or extend parent settings
|
|
1007
|
+
* @returns A new child logger instance
|
|
1008
|
+
* @example
|
|
1009
|
+
* ```typescript
|
|
1010
|
+
* const parent = createPail({
|
|
1011
|
+
* logLevel: "info",
|
|
1012
|
+
* types: { http: { label: "HTTP", logLevel: "info" } },
|
|
1013
|
+
* reporters: [new PrettyReporter()],
|
|
1014
|
+
* });
|
|
1015
|
+
*
|
|
1016
|
+
* // Child inherits parent settings but overrides log level
|
|
1017
|
+
* const child = parent.child({ logLevel: "debug" });
|
|
1018
|
+
* child.info("This will be logged"); // Uses debug level from child
|
|
1019
|
+
* child.http("GET /api 200"); // Inherits http type from parent
|
|
1020
|
+
*
|
|
1021
|
+
* // Child can add new types
|
|
1022
|
+
* const childWithNewType = parent.child({
|
|
1023
|
+
* types: { db: { label: "DB", logLevel: "info" } },
|
|
1024
|
+
* });
|
|
1025
|
+
* childWithNewType.db("Query executed"); // New type available
|
|
1026
|
+
* ```
|
|
1027
|
+
*/
|
|
1028
|
+
child(options) {
|
|
1029
|
+
const typesChanged = options?.types !== void 0;
|
|
1030
|
+
const mergedTypes = typesChanged ? mergeTypes(this.types, options.types) : this.types;
|
|
1031
|
+
const childReporters = options?.reporters ?? [];
|
|
1032
|
+
const allReporters = childReporters.length > 0 ? [...this.reporters, ...childReporters] : [...this.reporters];
|
|
1033
|
+
const childProcessors = options?.processors ?? [];
|
|
1034
|
+
const allProcessors = childProcessors.length > 0 ? [...this.processors, ...childProcessors] : [...this.processors];
|
|
1035
|
+
const mergedLogLevels = options?.logLevels ? { ...this.logLevels, ...options.logLevels } : this.logLevels;
|
|
1036
|
+
let mergedScope;
|
|
1037
|
+
if (options?.scope) {
|
|
1038
|
+
const childScope = arrayify(options.scope).filter(Boolean);
|
|
1039
|
+
mergedScope = this.scopeName.length > 0 ? [...this.scopeName, ...childScope] : childScope;
|
|
1040
|
+
} else {
|
|
1041
|
+
mergedScope = this.scopeName.length > 0 ? this.scopeName : [];
|
|
1042
|
+
}
|
|
1043
|
+
const mergedMessages = options?.messages ? {
|
|
1044
|
+
timerEnd: this.endTimerMessage,
|
|
1045
|
+
timerStart: this.startTimerMessage,
|
|
1046
|
+
...options.messages
|
|
1047
|
+
} : {
|
|
1048
|
+
timerEnd: this.endTimerMessage,
|
|
1049
|
+
timerStart: this.startTimerMessage
|
|
1050
|
+
};
|
|
1051
|
+
const childOptions = {
|
|
1052
|
+
disabled: options?.disabled ?? this.disabled,
|
|
1053
|
+
logLevel: options?.logLevel ?? this.generalLogLevel,
|
|
1054
|
+
logLevels: mergedLogLevels,
|
|
1055
|
+
messages: mergedMessages,
|
|
1056
|
+
processors: allProcessors,
|
|
1057
|
+
rawReporter: options?.rawReporter ?? this.rawReporter,
|
|
1058
|
+
reporters: allReporters,
|
|
1059
|
+
scope: mergedScope,
|
|
1060
|
+
throttle: options?.throttle ?? this.throttle,
|
|
1061
|
+
throttleMin: options?.throttleMin ?? this.throttleMin
|
|
1062
|
+
};
|
|
1063
|
+
if (typesChanged) {
|
|
1064
|
+
childOptions.parentTypes = mergedTypes;
|
|
1065
|
+
childOptions.parentLongestLabel = getLongestLabel(mergedTypes);
|
|
1066
|
+
} else {
|
|
1067
|
+
childOptions.parentTypes = this.types;
|
|
1068
|
+
childOptions.parentLongestLabel = this.longestLabel;
|
|
1069
|
+
}
|
|
1070
|
+
if (!options?.logLevels) {
|
|
1071
|
+
childOptions.parentLogLevels = this.logLevels;
|
|
1072
|
+
}
|
|
1073
|
+
if (!options?.messages) {
|
|
1074
|
+
childOptions.parentMessages = {
|
|
1075
|
+
timerEnd: this.endTimerMessage,
|
|
1076
|
+
timerStart: this.startTimerMessage
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
childOptions.parentStringify = this.stringify;
|
|
1080
|
+
return new PailBrowserImpl(childOptions);
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* Starts a timer with the specified label.
|
|
1084
|
+
*
|
|
1085
|
+
* Records the current timestamp and associates it with the given label.
|
|
1086
|
+
* Multiple timers can be active simultaneously with different labels.
|
|
1087
|
+
* @param label The timer label (defaults to "default")
|
|
1088
|
+
* @example
|
|
1089
|
+
* ```typescript
|
|
1090
|
+
* const logger = createPail();
|
|
1091
|
+
* logger.time("operation");
|
|
1092
|
+
* // ... some operation ...
|
|
1093
|
+
* logger.timeEnd("operation"); // Logs: "Timer run for: X ms"
|
|
1094
|
+
* ```
|
|
1095
|
+
*/
|
|
1096
|
+
time(label = "default") {
|
|
1097
|
+
if (this.seqTimers.has(label)) {
|
|
1098
|
+
this.logger("warn", false, false, {
|
|
1099
|
+
message: `Timer '${label}' already exists`,
|
|
1100
|
+
prefix: label
|
|
1101
|
+
});
|
|
1102
|
+
} else {
|
|
1103
|
+
this.seqTimers.add(label);
|
|
1104
|
+
this.timersMap.set(label, Date.now());
|
|
1105
|
+
this.logger("start", false, false, {
|
|
1106
|
+
message: this.startTimerMessage,
|
|
1107
|
+
prefix: label
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Logs the current elapsed time for a timer without stopping it.
|
|
1113
|
+
*
|
|
1114
|
+
* Calculates and logs the time elapsed since the timer was started,
|
|
1115
|
+
* but keeps the timer running. If no label is provided, uses the
|
|
1116
|
+
* most recently started timer.
|
|
1117
|
+
* @param label The timer label (uses last timer if not specified)
|
|
1118
|
+
* @param data Additional data to include in the log message
|
|
1119
|
+
* @example
|
|
1120
|
+
* ```typescript
|
|
1121
|
+
* const logger = createPail();
|
|
1122
|
+
* logger.time("task");
|
|
1123
|
+
* // ... some work ...
|
|
1124
|
+
* logger.timeLog("task"); // Logs current elapsed time
|
|
1125
|
+
* // ... more work ...
|
|
1126
|
+
* logger.timeEnd("task"); // Logs final time and stops timer
|
|
1127
|
+
* ```
|
|
1128
|
+
*/
|
|
1129
|
+
timeLog(label, ...data) {
|
|
1130
|
+
if (!label && this.seqTimers.size > 0) {
|
|
1131
|
+
label = [...this.seqTimers].pop();
|
|
1132
|
+
}
|
|
1133
|
+
if (label && this.timersMap.has(label)) {
|
|
1134
|
+
const span = Date.now() - this.timersMap.get(label);
|
|
1135
|
+
this.logger("info", false, false, {
|
|
1136
|
+
context: data,
|
|
1137
|
+
message: span < 1e3 ? `${String(span)} ms` : `${(span / 1e3).toFixed(2)} s`,
|
|
1138
|
+
prefix: label
|
|
1139
|
+
});
|
|
1140
|
+
} else {
|
|
1141
|
+
this.logger("warn", false, false, {
|
|
1142
|
+
context: data,
|
|
1143
|
+
message: "Timer not found",
|
|
1144
|
+
prefix: label
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
/**
|
|
1149
|
+
* Stops a timer and logs the final elapsed time.
|
|
1150
|
+
*
|
|
1151
|
+
* Calculates the total time elapsed since the timer was started,
|
|
1152
|
+
* logs the result, and removes the timer. If no label is provided,
|
|
1153
|
+
* uses the most recently started timer.
|
|
1154
|
+
* @param label The timer label (uses last timer if not specified)
|
|
1155
|
+
* @example
|
|
1156
|
+
* ```typescript
|
|
1157
|
+
* const logger = createPail();
|
|
1158
|
+
* logger.time("operation");
|
|
1159
|
+
* // ... perform operation ...
|
|
1160
|
+
* logger.timeEnd("operation"); // Logs: "Timer run for: X ms"
|
|
1161
|
+
* ```
|
|
1162
|
+
*/
|
|
1163
|
+
timeEnd(label) {
|
|
1164
|
+
if (!label && this.seqTimers.size > 0) {
|
|
1165
|
+
label = [...this.seqTimers].pop();
|
|
1166
|
+
}
|
|
1167
|
+
if (label && this.timersMap.has(label)) {
|
|
1168
|
+
const span = Date.now() - this.timersMap.get(label);
|
|
1169
|
+
this.timersMap.delete(label);
|
|
1170
|
+
this.logger("stop", false, false, {
|
|
1171
|
+
message: `${this.endTimerMessage} ${span < 1e3 ? `${String(span)} ms` : `${(span / 1e3).toFixed(2)} s`}`,
|
|
1172
|
+
prefix: label
|
|
1173
|
+
});
|
|
1174
|
+
} else {
|
|
1175
|
+
this.logger("warn", false, false, {
|
|
1176
|
+
message: "Timer not found",
|
|
1177
|
+
prefix: label
|
|
1178
|
+
});
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
/**
|
|
1182
|
+
* Starts a log group with the specified label.
|
|
1183
|
+
*
|
|
1184
|
+
* Groups related log messages together. In browser environments,
|
|
1185
|
+
* this uses the native console.group() functionality. In other
|
|
1186
|
+
* environments, it tracks group nesting internally.
|
|
1187
|
+
* @param label The group label (defaults to "console.group")
|
|
1188
|
+
* @example
|
|
1189
|
+
* ```typescript
|
|
1190
|
+
* const logger = createPail();
|
|
1191
|
+
* logger.group("Database Operations");
|
|
1192
|
+
* logger.info("Connecting to database");
|
|
1193
|
+
* logger.info("Running migration");
|
|
1194
|
+
* logger.groupEnd(); // End the group
|
|
1195
|
+
* ```
|
|
1196
|
+
*/
|
|
1197
|
+
group(label = "console.group") {
|
|
1198
|
+
if (globalThis.window === void 0) {
|
|
1199
|
+
this.groups.push(label);
|
|
1200
|
+
} else {
|
|
1201
|
+
console.group(label);
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Ends the current log group.
|
|
1206
|
+
*
|
|
1207
|
+
* Closes the most recently opened log group. In browser environments,
|
|
1208
|
+
* this uses the native console.groupEnd() functionality.
|
|
1209
|
+
* @example
|
|
1210
|
+
* ```typescript
|
|
1211
|
+
* const logger = createPail();
|
|
1212
|
+
* logger.group("Processing");
|
|
1213
|
+
* logger.info("Step 1");
|
|
1214
|
+
* logger.info("Step 2");
|
|
1215
|
+
* logger.groupEnd(); // Closes the "Processing" group
|
|
1216
|
+
* ```
|
|
1217
|
+
*/
|
|
1218
|
+
groupEnd() {
|
|
1219
|
+
if (globalThis.window === void 0) {
|
|
1220
|
+
this.groups.pop();
|
|
1221
|
+
} else {
|
|
1222
|
+
console.groupEnd();
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
/**
|
|
1226
|
+
* Increments and logs a counter with the specified label.
|
|
1227
|
+
*
|
|
1228
|
+
* Maintains an internal counter for each label and logs the current count
|
|
1229
|
+
* each time it's called. Useful for tracking how many times certain
|
|
1230
|
+
* code paths are executed.
|
|
1231
|
+
* @param label The counter label (defaults to "default")
|
|
1232
|
+
* @example
|
|
1233
|
+
* ```typescript
|
|
1234
|
+
* const logger = createPail();
|
|
1235
|
+
* logger.count("requests"); // Logs: "requests: 1"
|
|
1236
|
+
* logger.count("requests"); // Logs: "requests: 2"
|
|
1237
|
+
* logger.count("errors"); // Logs: "errors: 1"
|
|
1238
|
+
* ```
|
|
1239
|
+
*/
|
|
1240
|
+
count(label = "default") {
|
|
1241
|
+
const current = this.countMap.get(label) ?? 0;
|
|
1242
|
+
this.countMap.set(label, current + 1);
|
|
1243
|
+
this.logger("log", false, false, {
|
|
1244
|
+
message: `${label}: ${String(current + 1)}`,
|
|
1245
|
+
prefix: label
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* Resets a counter to zero.
|
|
1250
|
+
*
|
|
1251
|
+
* Removes the counter with the specified label, effectively resetting
|
|
1252
|
+
* it to zero. If the counter doesn't exist, logs a warning.
|
|
1253
|
+
* @param label The counter label to reset (defaults to "default")
|
|
1254
|
+
* @example
|
|
1255
|
+
* ```typescript
|
|
1256
|
+
* const logger = createPail();
|
|
1257
|
+
* logger.count("requests"); // Logs: "requests: 1"
|
|
1258
|
+
* logger.countReset("requests"); // Resets counter
|
|
1259
|
+
* logger.count("requests"); // Logs: "requests: 1" (starts over)
|
|
1260
|
+
* ```
|
|
1261
|
+
*/
|
|
1262
|
+
countReset(label = "default") {
|
|
1263
|
+
if (this.countMap.has(label)) {
|
|
1264
|
+
this.countMap.delete(label);
|
|
1265
|
+
} else {
|
|
1266
|
+
this.logger("warn", false, false, {
|
|
1267
|
+
message: `Count for ${label} does not exist`,
|
|
1268
|
+
prefix: label
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
/**
|
|
1273
|
+
* Clears the console output.
|
|
1274
|
+
*
|
|
1275
|
+
* Calls the native console.clear() method to clear all output from
|
|
1276
|
+
* the console. This is a convenience method that wraps the native
|
|
1277
|
+
* console.clear() functionality.
|
|
1278
|
+
* @example
|
|
1279
|
+
* ```typescript
|
|
1280
|
+
* const logger = createPail();
|
|
1281
|
+
* logger.info("Some message");
|
|
1282
|
+
* logger.clear(); // Clears the console
|
|
1283
|
+
* ```
|
|
1284
|
+
*/
|
|
1285
|
+
// eslint-disable-next-line class-methods-use-this
|
|
1286
|
+
clear() {
|
|
1287
|
+
console.clear();
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Logs a raw message bypassing normal processing.
|
|
1291
|
+
*
|
|
1292
|
+
* Sends a message directly to the raw reporter without going through
|
|
1293
|
+
* the normal logging pipeline (processors, throttling, etc.). This is
|
|
1294
|
+
* useful for logging that needs to bypass all formatting and processing.
|
|
1295
|
+
* @param message The raw message to log
|
|
1296
|
+
* @param arguments_ Additional arguments to include
|
|
1297
|
+
* @example
|
|
1298
|
+
* ```typescript
|
|
1299
|
+
* const logger = createPail();
|
|
1300
|
+
* logger.raw("Direct message", { data: "value" });
|
|
1301
|
+
* ```
|
|
1302
|
+
*/
|
|
1303
|
+
raw(message, ...arguments_) {
|
|
1304
|
+
if (this.disabled) {
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1307
|
+
this.logger("log", true, false, {
|
|
1308
|
+
context: arguments_,
|
|
1309
|
+
message
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
extendReporter(reporter) {
|
|
1313
|
+
if (typeof reporter.setLoggerTypes === "function") {
|
|
1314
|
+
reporter.setLoggerTypes(this.types);
|
|
1315
|
+
}
|
|
1316
|
+
if (typeof reporter.setStringify === "function") {
|
|
1317
|
+
reporter.setStringify(this.stringify);
|
|
1318
|
+
}
|
|
1319
|
+
return reporter;
|
|
1320
|
+
}
|
|
1321
|
+
registerReporters(reporters) {
|
|
1322
|
+
for (let i = 0; i < reporters.length; i += 1) {
|
|
1323
|
+
this.reporters.add(this.extendReporter(reporters[i]));
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
registerProcessors(processors) {
|
|
1327
|
+
for (let i = 0; i < processors.length; i += 1) {
|
|
1328
|
+
const processor = processors[i];
|
|
1329
|
+
if (typeof processor.setStringify === "function") {
|
|
1330
|
+
processor.setStringify(this.stringify);
|
|
1331
|
+
}
|
|
1332
|
+
this.processors.add(processor);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
#report(meta, raw) {
|
|
1336
|
+
if (raw) {
|
|
1337
|
+
this.rawReporter.log(Object.freeze(meta));
|
|
1338
|
+
} else {
|
|
1339
|
+
for (const reporter of this.reporters) {
|
|
1340
|
+
reporter.log(Object.freeze(meta));
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
#normalizeLogLevel(level) {
|
|
1345
|
+
return level && this.logLevels[level] ? level : "debug";
|
|
1346
|
+
}
|
|
1347
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
1348
|
+
#buildMeta(typeName, type, ...arguments_) {
|
|
1349
|
+
const meta = {
|
|
1350
|
+
badge: void 0,
|
|
1351
|
+
context: void 0,
|
|
1352
|
+
error: void 0,
|
|
1353
|
+
label: void 0,
|
|
1354
|
+
message: EMPTY_SYMBOL,
|
|
1355
|
+
prefix: void 0,
|
|
1356
|
+
repeated: void 0,
|
|
1357
|
+
scope: void 0,
|
|
1358
|
+
suffix: void 0
|
|
1359
|
+
};
|
|
1360
|
+
meta.type = {
|
|
1361
|
+
level: type.logLevel,
|
|
1362
|
+
name: typeName
|
|
1363
|
+
};
|
|
1364
|
+
meta.groups = this.groups;
|
|
1365
|
+
meta.scope = this.scopeName;
|
|
1366
|
+
meta.date = /* @__PURE__ */ new Date();
|
|
1367
|
+
if (arguments_.length > 0 && arguments_[0] instanceof Error) {
|
|
1368
|
+
meta.error = arguments_[0];
|
|
1369
|
+
if (arguments_.length > 1) {
|
|
1370
|
+
meta.context = arguments_.slice(1);
|
|
1371
|
+
}
|
|
1372
|
+
} else if (arguments_.length > 0 && typeof arguments_[0] === "object" && arguments_[0] !== null && "message" in arguments_[0]) {
|
|
1373
|
+
const { context, message, prefix, suffix } = arguments_[0];
|
|
1374
|
+
if (context) {
|
|
1375
|
+
meta.context = context;
|
|
1376
|
+
}
|
|
1377
|
+
if (prefix) {
|
|
1378
|
+
meta.prefix = prefix;
|
|
1379
|
+
}
|
|
1380
|
+
if (suffix) {
|
|
1381
|
+
meta.suffix = suffix;
|
|
1382
|
+
}
|
|
1383
|
+
meta.message = message;
|
|
1384
|
+
if (arguments_.length > 1) {
|
|
1385
|
+
const additionalContext = arguments_.slice(1);
|
|
1386
|
+
if (meta.context) {
|
|
1387
|
+
meta.context = Array.isArray(meta.context) ? [...meta.context, ...additionalContext] : [meta.context, ...additionalContext];
|
|
1388
|
+
} else {
|
|
1389
|
+
meta.context = additionalContext;
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
} else if (arguments_.length > 1) {
|
|
1393
|
+
meta.message = arguments_[0];
|
|
1394
|
+
meta.context = arguments_.slice(1);
|
|
1395
|
+
} else if (arguments_.length === 1) {
|
|
1396
|
+
meta.message = arguments_[0];
|
|
1397
|
+
} else {
|
|
1398
|
+
meta.message = void 0;
|
|
1399
|
+
}
|
|
1400
|
+
if (type.logLevel === "trace") {
|
|
1401
|
+
meta.traceError = new Error("Trace");
|
|
1402
|
+
}
|
|
1403
|
+
if (type.badge) {
|
|
1404
|
+
meta.badge = type.badge;
|
|
1405
|
+
}
|
|
1406
|
+
if (type.label) {
|
|
1407
|
+
meta.label = type.label;
|
|
1408
|
+
}
|
|
1409
|
+
return meta;
|
|
1410
|
+
}
|
|
1411
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
1412
|
+
logger(type, raw, force, ...messageObject) {
|
|
1413
|
+
if (this.disabled) {
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
if (this.paused) {
|
|
1417
|
+
this.messageQueue.push({ messageObject, raw, type });
|
|
1418
|
+
return;
|
|
1419
|
+
}
|
|
1420
|
+
const typeConfig = this.types[type];
|
|
1421
|
+
const logLevel = this.#normalizeLogLevel(typeConfig.logLevel);
|
|
1422
|
+
if (force || this.logLevels[logLevel] >= this.logLevels[this.generalLogLevel]) {
|
|
1423
|
+
let meta = this.#buildMeta(type, typeConfig, ...messageObject);
|
|
1424
|
+
const resolveLog = (newLog = false) => {
|
|
1425
|
+
const repeated = (this.lastLog.count ?? 0) - this.throttleMin;
|
|
1426
|
+
if (this.lastLog.object && repeated > 0) {
|
|
1427
|
+
const lastMeta = { ...this.lastLog.object };
|
|
1428
|
+
if (repeated > 1) {
|
|
1429
|
+
lastMeta.repeated = repeated;
|
|
1430
|
+
}
|
|
1431
|
+
this.#report(lastMeta, raw);
|
|
1432
|
+
this.lastLog.count = 1;
|
|
1433
|
+
}
|
|
1434
|
+
if (newLog) {
|
|
1435
|
+
for (const processor of this.processors) {
|
|
1436
|
+
meta = { ...processor.process(meta) };
|
|
1437
|
+
}
|
|
1438
|
+
this.lastLog.object = meta;
|
|
1439
|
+
this.#report(meta, raw);
|
|
1440
|
+
}
|
|
1441
|
+
};
|
|
1442
|
+
clearTimeout(this.lastLog.timeout);
|
|
1443
|
+
const diffTime = this.lastLog.time && meta.date ? new Date(meta.date).getTime() - this.lastLog.time.getTime() : 0;
|
|
1444
|
+
this.lastLog.time = new Date(meta.date);
|
|
1445
|
+
if (diffTime < this.throttle) {
|
|
1446
|
+
try {
|
|
1447
|
+
const isSameLog = this.lastLog.object && JSON.stringify([meta.label, meta.scope, meta.type, meta.message, meta.prefix, meta.suffix, meta.context]) === JSON.stringify([
|
|
1448
|
+
this.lastLog.object.label,
|
|
1449
|
+
this.lastLog.object.scope,
|
|
1450
|
+
this.lastLog.object.type,
|
|
1451
|
+
this.lastLog.object.message,
|
|
1452
|
+
this.lastLog.object.prefix,
|
|
1453
|
+
this.lastLog.object.suffix,
|
|
1454
|
+
this.lastLog.object.context
|
|
1455
|
+
]);
|
|
1456
|
+
if (isSameLog) {
|
|
1457
|
+
this.lastLog.count = (this.lastLog.count ?? 0) + 1;
|
|
1458
|
+
if (this.lastLog.count > this.throttleMin) {
|
|
1459
|
+
this.lastLog.timeout = setTimeout(resolveLog, this.throttle);
|
|
1460
|
+
return;
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
} catch {
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
resolveLog(true);
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
24
1470
|
|
|
25
1471
|
class RawReporter {
|
|
26
1472
|
#stdout;
|
|
@@ -58,7 +1504,7 @@ class RawReporter {
|
|
|
58
1504
|
if (typeof value === "object") {
|
|
59
1505
|
return ` ${inspect(value, this.#inspectOptions)}`;
|
|
60
1506
|
}
|
|
61
|
-
return ` ${value}`;
|
|
1507
|
+
return ` ${String(value)}`;
|
|
62
1508
|
})
|
|
63
1509
|
);
|
|
64
1510
|
}
|
|
@@ -134,6 +1580,7 @@ class PailServerImpl extends PailBrowserImpl {
|
|
|
134
1580
|
this.registerProcessors(processors);
|
|
135
1581
|
}
|
|
136
1582
|
}
|
|
1583
|
+
options;
|
|
137
1584
|
stdout;
|
|
138
1585
|
stderr;
|
|
139
1586
|
interactiveManager;
|
|
@@ -179,7 +1626,7 @@ class PailServerImpl extends PailBrowserImpl {
|
|
|
179
1626
|
*/
|
|
180
1627
|
// @ts-expect-error - override signature differs due to server-specific options
|
|
181
1628
|
child(options) {
|
|
182
|
-
const typesChanged = options?.types !== void 0
|
|
1629
|
+
const typesChanged = options?.types !== void 0;
|
|
183
1630
|
const mergedTypes = typesChanged ? mergeTypes(this.types, options.types) : this.types;
|
|
184
1631
|
const childReporters = options?.reporters ?? [];
|
|
185
1632
|
const allReporters = childReporters.length > 0 ? [...this.reporters, ...childReporters] : [...this.reporters];
|
|
@@ -350,99 +1797,6 @@ class PailServerImpl extends PailBrowserImpl {
|
|
|
350
1797
|
this.restoreConsole();
|
|
351
1798
|
this.restoreStd();
|
|
352
1799
|
}
|
|
353
|
-
/**
|
|
354
|
-
* Creates a single progress bar.
|
|
355
|
-
* @param options Configuration options for the progress bar
|
|
356
|
-
* @returns A new ProgressBar instance
|
|
357
|
-
* @example
|
|
358
|
-
* ```typescript
|
|
359
|
-
* const logger = createPail({ interactive: true });
|
|
360
|
-
* const bar = logger.createProgressBar({
|
|
361
|
-
* total: 100,
|
|
362
|
-
* format: 'Downloading [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}'
|
|
363
|
-
* });
|
|
364
|
-
*
|
|
365
|
-
* bar.start();
|
|
366
|
-
* // ... do work and update progress
|
|
367
|
-
* bar.update(50);
|
|
368
|
-
* bar.stop();
|
|
369
|
-
* ```
|
|
370
|
-
*/
|
|
371
|
-
createProgressBar(options) {
|
|
372
|
-
if (!this.interactiveManager) {
|
|
373
|
-
throw new Error("Interactive mode is not enabled. Create Pail with { interactive: true } to use progress bars.");
|
|
374
|
-
}
|
|
375
|
-
const styledOptions = applyStyleToOptions(options);
|
|
376
|
-
return new ProgressBar(styledOptions, this.interactiveManager);
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* Creates a multi-bar progress manager for displaying multiple progress bars.
|
|
380
|
-
* @param options Configuration options for the multi-bar manager
|
|
381
|
-
* @returns A new MultiProgressBar instance
|
|
382
|
-
* @example
|
|
383
|
-
* ```typescript
|
|
384
|
-
* const logger = createPail({ interactive: true });
|
|
385
|
-
* const multiBar = logger.createMultiProgressBar();
|
|
386
|
-
*
|
|
387
|
-
* const bar1 = multiBar.create(100);
|
|
388
|
-
* const bar2 = multiBar.create(200);
|
|
389
|
-
*
|
|
390
|
-
* bar1.start();
|
|
391
|
-
* bar2.start();
|
|
392
|
-
* // ... update bars as needed
|
|
393
|
-
* multiBar.stop();
|
|
394
|
-
* ```
|
|
395
|
-
*/
|
|
396
|
-
createMultiProgressBar(options = {}) {
|
|
397
|
-
if (!this.interactiveManager) {
|
|
398
|
-
throw new Error("Interactive mode is not enabled. Create Pail with { interactive: true } to use progress bars.");
|
|
399
|
-
}
|
|
400
|
-
const styledOptions = applyStyleToOptions(options);
|
|
401
|
-
return new MultiProgressBar(styledOptions, this.interactiveManager);
|
|
402
|
-
}
|
|
403
|
-
/**
|
|
404
|
-
* Creates a single spinner.
|
|
405
|
-
* @param options Configuration options for the spinner
|
|
406
|
-
* @returns A new Spinner instance
|
|
407
|
-
* @example
|
|
408
|
-
* ```typescript
|
|
409
|
-
* const logger = createPail({ interactive: true });
|
|
410
|
-
* const spinner = logger.createSpinner({ name: 'dots' });
|
|
411
|
-
* spinner.start('Loading...');
|
|
412
|
-
* // ... do work
|
|
413
|
-
* spinner.succeed('Done');
|
|
414
|
-
* ```
|
|
415
|
-
*/
|
|
416
|
-
createSpinner(options = {}) {
|
|
417
|
-
if (!this.interactiveManager) {
|
|
418
|
-
throw new Error("Interactive mode is not enabled. Create Pail with { interactive: true } to use spinners.");
|
|
419
|
-
}
|
|
420
|
-
return new Spinner(options, this.interactiveManager);
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Creates a multi-spinner manager for displaying multiple spinners.
|
|
424
|
-
* @param options Configuration options for the multi-spinner manager
|
|
425
|
-
* @returns A new MultiSpinner instance
|
|
426
|
-
* @example
|
|
427
|
-
* ```typescript
|
|
428
|
-
* const logger = createPail({ interactive: true });
|
|
429
|
-
* const multiSpinner = logger.createMultiSpinner();
|
|
430
|
-
*
|
|
431
|
-
* const spinner1 = multiSpinner.create('Loading 1');
|
|
432
|
-
* const spinner2 = multiSpinner.create('Loading 2');
|
|
433
|
-
*
|
|
434
|
-
* spinner1.start();
|
|
435
|
-
* spinner2.start();
|
|
436
|
-
* // ... update spinners as needed
|
|
437
|
-
* multiSpinner.stop();
|
|
438
|
-
* ```
|
|
439
|
-
*/
|
|
440
|
-
createMultiSpinner(options = {}) {
|
|
441
|
-
if (!this.interactiveManager) {
|
|
442
|
-
throw new Error("Interactive mode is not enabled. Create Pail with { interactive: true } to use spinners.");
|
|
443
|
-
}
|
|
444
|
-
return new MultiSpinner(options, this.interactiveManager);
|
|
445
|
-
}
|
|
446
1800
|
/**
|
|
447
1801
|
* Clears the terminal screen.
|
|
448
1802
|
*
|
|
@@ -457,8 +1811,8 @@ class PailServerImpl extends PailBrowserImpl {
|
|
|
457
1811
|
* ```
|
|
458
1812
|
*/
|
|
459
1813
|
clear() {
|
|
460
|
-
this.stdout.write(
|
|
461
|
-
this.stderr.write(
|
|
1814
|
+
this.stdout.write(resetTerminal);
|
|
1815
|
+
this.stderr.write(resetTerminal);
|
|
462
1816
|
}
|
|
463
1817
|
extendReporter(reporter) {
|
|
464
1818
|
if (typeof reporter.setStdout === "function") {
|
|
@@ -505,6 +1859,922 @@ class PailServerImpl extends PailBrowserImpl {
|
|
|
505
1859
|
}
|
|
506
1860
|
const PailServer = PailServerImpl;
|
|
507
1861
|
|
|
1862
|
+
const colorKeywords = /* @__PURE__ */ new Map([
|
|
1863
|
+
["aliceblue", "#f0f8ff"],
|
|
1864
|
+
["antiquewhite", "#faebd7"],
|
|
1865
|
+
["aqua", "#00ffff"],
|
|
1866
|
+
["aquamarine", "#7fffd4"],
|
|
1867
|
+
["azure", "#f0ffff"],
|
|
1868
|
+
["beige", "#f5f5dc"],
|
|
1869
|
+
["bisque", "#ffe4c4"],
|
|
1870
|
+
["black", "#000000"],
|
|
1871
|
+
["blanchedalmond", "#ffebcd"],
|
|
1872
|
+
["blue", "#0000ff"],
|
|
1873
|
+
["blueviolet", "#8a2be2"],
|
|
1874
|
+
["brown", "#a52a2a"],
|
|
1875
|
+
["burlywood", "#deb887"],
|
|
1876
|
+
["cadetblue", "#5f9ea0"],
|
|
1877
|
+
["chartreuse", "#7fff00"],
|
|
1878
|
+
["chocolate", "#d2691e"],
|
|
1879
|
+
["coral", "#ff7f50"],
|
|
1880
|
+
["cornflowerblue", "#6495ed"],
|
|
1881
|
+
["cornsilk", "#fff8dc"],
|
|
1882
|
+
["crimson", "#dc143c"],
|
|
1883
|
+
["cyan", "#00ffff"],
|
|
1884
|
+
["darkblue", "#00008b"],
|
|
1885
|
+
["darkcyan", "#008b8b"],
|
|
1886
|
+
["darkgoldenrod", "#b8860b"],
|
|
1887
|
+
["darkgray", "#a9a9a9"],
|
|
1888
|
+
["darkgreen", "#006400"],
|
|
1889
|
+
["darkgrey", "#a9a9a9"],
|
|
1890
|
+
["darkkhaki", "#bdb76b"],
|
|
1891
|
+
["darkmagenta", "#8b008b"],
|
|
1892
|
+
["darkolivegreen", "#556b2f"],
|
|
1893
|
+
["darkorange", "#ff8c00"],
|
|
1894
|
+
["darkorchid", "#9932cc"],
|
|
1895
|
+
["darkred", "#8b0000"],
|
|
1896
|
+
["darksalmon", "#e9967a"],
|
|
1897
|
+
["darkseagreen", "#8fbc8f"],
|
|
1898
|
+
["darkslateblue", "#483d8b"],
|
|
1899
|
+
["darkslategray", "#2f4f4f"],
|
|
1900
|
+
["darkslategrey", "#2f4f4f"],
|
|
1901
|
+
["darkturquoise", "#00ced1"],
|
|
1902
|
+
["darkviolet", "#9400d3"],
|
|
1903
|
+
["deeppink", "#ff1493"],
|
|
1904
|
+
["deepskyblue", "#00bfff"],
|
|
1905
|
+
["dimgray", "#696969"],
|
|
1906
|
+
["dimgrey", "#696969"],
|
|
1907
|
+
["dodgerblue", "#1e90ff"],
|
|
1908
|
+
["firebrick", "#b22222"],
|
|
1909
|
+
["floralwhite", "#fffaf0"],
|
|
1910
|
+
["forestgreen", "#228b22"],
|
|
1911
|
+
["fuchsia", "#ff00ff"],
|
|
1912
|
+
["gainsboro", "#dcdcdc"],
|
|
1913
|
+
["ghostwhite", "#f8f8ff"],
|
|
1914
|
+
["gold", "#ffd700"],
|
|
1915
|
+
["goldenrod", "#daa520"],
|
|
1916
|
+
["gray", "#808080"],
|
|
1917
|
+
["green", "#008000"],
|
|
1918
|
+
["greenyellow", "#adff2f"],
|
|
1919
|
+
["grey", "#808080"],
|
|
1920
|
+
["honeydew", "#f0fff0"],
|
|
1921
|
+
["hotpink", "#ff69b4"],
|
|
1922
|
+
["indianred", "#cd5c5c"],
|
|
1923
|
+
["indigo", "#4b0082"],
|
|
1924
|
+
["ivory", "#fffff0"],
|
|
1925
|
+
["khaki", "#f0e68c"],
|
|
1926
|
+
["lavender", "#e6e6fa"],
|
|
1927
|
+
["lavenderblush", "#fff0f5"],
|
|
1928
|
+
["lawngreen", "#7cfc00"],
|
|
1929
|
+
["lemonchiffon", "#fffacd"],
|
|
1930
|
+
["lightblue", "#add8e6"],
|
|
1931
|
+
["lightcoral", "#f08080"],
|
|
1932
|
+
["lightcyan", "#e0ffff"],
|
|
1933
|
+
["lightgoldenrodyellow", "#fafad2"],
|
|
1934
|
+
["lightgray", "#d3d3d3"],
|
|
1935
|
+
["lightgreen", "#90ee90"],
|
|
1936
|
+
["lightgrey", "#d3d3d3"],
|
|
1937
|
+
["lightpink", "#ffb6c1"],
|
|
1938
|
+
["lightsalmon", "#ffa07a"],
|
|
1939
|
+
["lightseagreen", "#20b2aa"],
|
|
1940
|
+
["lightskyblue", "#87cefa"],
|
|
1941
|
+
["lightslategray", "#778899"],
|
|
1942
|
+
["lightslategrey", "#778899"],
|
|
1943
|
+
["lightsteelblue", "#b0c4de"],
|
|
1944
|
+
["lightyellow", "#ffffe0"],
|
|
1945
|
+
["lime", "#00ff00"],
|
|
1946
|
+
["limegreen", "#32cd32"],
|
|
1947
|
+
["linen", "#faf0e6"],
|
|
1948
|
+
["magenta", "#ff00ff"],
|
|
1949
|
+
["maroon", "#800000"],
|
|
1950
|
+
["mediumaquamarine", "#66cdaa"],
|
|
1951
|
+
["mediumblue", "#0000cd"],
|
|
1952
|
+
["mediumorchid", "#ba55d3"],
|
|
1953
|
+
["mediumpurple", "#9370db"],
|
|
1954
|
+
["mediumseagreen", "#3cb371"],
|
|
1955
|
+
["mediumslateblue", "#7b68ee"],
|
|
1956
|
+
["mediumspringgreen", "#00fa9a"],
|
|
1957
|
+
["mediumturquoise", "#48d1cc"],
|
|
1958
|
+
["mediumvioletred", "#c71585"],
|
|
1959
|
+
["midnightblue", "#191970"],
|
|
1960
|
+
["mintcream", "#f5fffa"],
|
|
1961
|
+
["mistyrose", "#ffe4e1"],
|
|
1962
|
+
["moccasin", "#ffe4b5"],
|
|
1963
|
+
["navajowhite", "#ffdead"],
|
|
1964
|
+
["navy", "#000080"],
|
|
1965
|
+
["oldlace", "#fdf5e6"],
|
|
1966
|
+
["olive", "#808000"],
|
|
1967
|
+
["olivedrab", "#6b8e23"],
|
|
1968
|
+
["orange", "#ffa500"],
|
|
1969
|
+
["orangered", "#ff4500"],
|
|
1970
|
+
["orchid", "#da70d6"],
|
|
1971
|
+
["palegoldenrod", "#eee8aa"],
|
|
1972
|
+
["palegreen", "#98fb98"],
|
|
1973
|
+
["paleturquoise", "#afeeee"],
|
|
1974
|
+
["palevioletred", "#db7093"],
|
|
1975
|
+
["papayawhip", "#ffefd5"],
|
|
1976
|
+
["peachpuff", "#ffdab9"],
|
|
1977
|
+
["peru", "#cd853f"],
|
|
1978
|
+
["pink", "#ffc0cb"],
|
|
1979
|
+
["plum", "#dda0dd"],
|
|
1980
|
+
["powderblue", "#b0e0e6"],
|
|
1981
|
+
["purple", "#800080"],
|
|
1982
|
+
["rebeccapurple", "#663399"],
|
|
1983
|
+
["red", "#ff0000"],
|
|
1984
|
+
["rosybrown", "#bc8f8f"],
|
|
1985
|
+
["royalblue", "#4169e1"],
|
|
1986
|
+
["saddlebrown", "#8b4513"],
|
|
1987
|
+
["salmon", "#fa8072"],
|
|
1988
|
+
["sandybrown", "#f4a460"],
|
|
1989
|
+
["seagreen", "#2e8b57"],
|
|
1990
|
+
["seashell", "#fff5ee"],
|
|
1991
|
+
["sienna", "#a0522d"],
|
|
1992
|
+
["silver", "#c0c0c0"],
|
|
1993
|
+
["skyblue", "#87ceeb"],
|
|
1994
|
+
["slateblue", "#6a5acd"],
|
|
1995
|
+
["slategray", "#708090"],
|
|
1996
|
+
["slategrey", "#708090"],
|
|
1997
|
+
["snow", "#fffafa"],
|
|
1998
|
+
["springgreen", "#00ff7f"],
|
|
1999
|
+
["steelblue", "#4682b4"],
|
|
2000
|
+
["tan", "#d2b48c"],
|
|
2001
|
+
["teal", "#008080"],
|
|
2002
|
+
["thistle", "#d8bfd8"],
|
|
2003
|
+
["tomato", "#ff6347"],
|
|
2004
|
+
["turquoise", "#40e0d0"],
|
|
2005
|
+
["violet", "#ee82ee"],
|
|
2006
|
+
["wheat", "#f5deb3"],
|
|
2007
|
+
["white", "#ffffff"],
|
|
2008
|
+
["whitesmoke", "#f5f5f5"],
|
|
2009
|
+
["yellow", "#ffff00"],
|
|
2010
|
+
["yellowgreen", "#9acd32"]
|
|
2011
|
+
]);
|
|
2012
|
+
const HASH_PATTERN = /^#([\dA-F]{2})([\dA-F]{2})([\dA-F]{2})([\dA-F]{2})?$/i;
|
|
2013
|
+
const SMALL_HASH_PATTERN = /^#([\dA-F])([\dA-F])([\dA-F])([\dA-F])?$/i;
|
|
2014
|
+
const RGB_PATTERN = /^rgba?\(\s*([+-]?(?:\d+(?:\.\d+)?|\.\d+))\s*,\s*([+-]?(?:\d+(?:\.\d+)?|\.\d+))\s*,\s*([+-]?(?:\d+(?:\.\d+)?|\.\d+))\s*(,\s*([+-]?(?:\d+(?:\.\d+)?|\.\d+))\s*)?\)$/;
|
|
2015
|
+
const HSL_PATTERN = /^hsla?\(\s*([+-]?(?:\d+(?:\.\d+)?|\.\d+))\s*,\s*([+-]?(?:\d+(?:\.\d+)?|\.\d+))%\s*,\s*([+-]?(?:\d+(?:\.\d+)?|\.\d+))%\s*(,\s*([+-]?(?:\d+(?:\.\d+)?|\.\d+))\s*)?\)$/;
|
|
2016
|
+
const getDefaultCss = () => {
|
|
2017
|
+
return {
|
|
2018
|
+
__proto__: null,
|
|
2019
|
+
backgroundColor: null,
|
|
2020
|
+
color: null,
|
|
2021
|
+
fontStyle: null,
|
|
2022
|
+
fontWeight: null,
|
|
2023
|
+
textDecorationColor: null,
|
|
2024
|
+
textDecorationLine: []
|
|
2025
|
+
};
|
|
2026
|
+
};
|
|
2027
|
+
const SPACE_PATTERN = /\s+/;
|
|
2028
|
+
const parseCssColor = (colorString) => {
|
|
2029
|
+
if (colorKeywords.has(colorString)) {
|
|
2030
|
+
colorString = colorKeywords.get(colorString);
|
|
2031
|
+
}
|
|
2032
|
+
const hashMatch = HASH_PATTERN.exec(colorString);
|
|
2033
|
+
if (hashMatch) {
|
|
2034
|
+
return [Number.parseInt(hashMatch[1], 16), Number.parseInt(hashMatch[2], 16), Number.parseInt(hashMatch[3], 16)];
|
|
2035
|
+
}
|
|
2036
|
+
const smallHashMatch = SMALL_HASH_PATTERN.exec(colorString);
|
|
2037
|
+
if (smallHashMatch) {
|
|
2038
|
+
return [
|
|
2039
|
+
Number.parseInt(`${smallHashMatch[1]}${smallHashMatch[1]}`, 16),
|
|
2040
|
+
Number.parseInt(`${smallHashMatch[2]}${smallHashMatch[2]}`, 16),
|
|
2041
|
+
Number.parseInt(`${smallHashMatch[3]}${smallHashMatch[3]}`, 16)
|
|
2042
|
+
];
|
|
2043
|
+
}
|
|
2044
|
+
const rgbMatch = RGB_PATTERN.exec(colorString);
|
|
2045
|
+
if (rgbMatch) {
|
|
2046
|
+
return [
|
|
2047
|
+
Math.round(Math.max(0, Math.min(255, Number(rgbMatch[1])))),
|
|
2048
|
+
Math.round(Math.max(0, Math.min(255, Number(rgbMatch[2])))),
|
|
2049
|
+
Math.round(Math.max(0, Math.min(255, Number(rgbMatch[3]))))
|
|
2050
|
+
];
|
|
2051
|
+
}
|
|
2052
|
+
const hslMatch = HSL_PATTERN.exec(colorString);
|
|
2053
|
+
if (hslMatch) {
|
|
2054
|
+
let h = Number(hslMatch[1]) % 360;
|
|
2055
|
+
if (h < 0) {
|
|
2056
|
+
h += 360;
|
|
2057
|
+
}
|
|
2058
|
+
const s = Math.max(0, Math.min(100, Number(hslMatch[2]))) / 100;
|
|
2059
|
+
const l = Math.max(0, Math.min(100, Number(hslMatch[3]))) / 100;
|
|
2060
|
+
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
2061
|
+
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
2062
|
+
const m = l - c / 2;
|
|
2063
|
+
let r_;
|
|
2064
|
+
let g_;
|
|
2065
|
+
let b_;
|
|
2066
|
+
if (h < 60) {
|
|
2067
|
+
({ 0: r_, 1: g_, 2: b_ } = [c, x, 0]);
|
|
2068
|
+
} else if (h < 120) {
|
|
2069
|
+
({ 0: r_, 1: g_, 2: b_ } = [x, c, 0]);
|
|
2070
|
+
} else if (h < 180) {
|
|
2071
|
+
({ 0: r_, 1: g_, 2: b_ } = [0, c, x]);
|
|
2072
|
+
} else if (h < 240) {
|
|
2073
|
+
({ 0: r_, 1: g_, 2: b_ } = [0, x, c]);
|
|
2074
|
+
} else if (h < 300) {
|
|
2075
|
+
({ 0: r_, 1: g_, 2: b_ } = [x, 0, c]);
|
|
2076
|
+
} else {
|
|
2077
|
+
({ 0: r_, 1: g_, 2: b_ } = [c, 0, x]);
|
|
2078
|
+
}
|
|
2079
|
+
return [Math.round((r_ + m) * 255), Math.round((g_ + m) * 255), Math.round((b_ + m) * 255)];
|
|
2080
|
+
}
|
|
2081
|
+
return null;
|
|
2082
|
+
};
|
|
2083
|
+
const colorEquals = (color1, color2) => color1?.[0] === color2?.[0] && color1?.[1] === color2?.[1] && color1?.[2] === color2?.[2];
|
|
2084
|
+
const parseCss = (cssString) => {
|
|
2085
|
+
const css = getDefaultCss();
|
|
2086
|
+
const rawEntries = [];
|
|
2087
|
+
let inValue = false;
|
|
2088
|
+
let currentKey = null;
|
|
2089
|
+
let parenthesesDepth = 0;
|
|
2090
|
+
let currentPart = "";
|
|
2091
|
+
for (const c of cssString) {
|
|
2092
|
+
if (c === "(") {
|
|
2093
|
+
parenthesesDepth += 1;
|
|
2094
|
+
} else if (parenthesesDepth > 0) {
|
|
2095
|
+
if (c === ")") {
|
|
2096
|
+
parenthesesDepth -= 1;
|
|
2097
|
+
}
|
|
2098
|
+
} else if (inValue) {
|
|
2099
|
+
if (c === ";") {
|
|
2100
|
+
const value = currentPart.trim();
|
|
2101
|
+
if (value !== "") {
|
|
2102
|
+
rawEntries.push([currentKey, value]);
|
|
2103
|
+
}
|
|
2104
|
+
currentKey = null;
|
|
2105
|
+
currentPart = "";
|
|
2106
|
+
inValue = false;
|
|
2107
|
+
continue;
|
|
2108
|
+
}
|
|
2109
|
+
} else if (c === ":") {
|
|
2110
|
+
currentKey = currentPart.trim();
|
|
2111
|
+
currentPart = "";
|
|
2112
|
+
inValue = true;
|
|
2113
|
+
continue;
|
|
2114
|
+
}
|
|
2115
|
+
currentPart += c;
|
|
2116
|
+
}
|
|
2117
|
+
if (inValue && parenthesesDepth === 0) {
|
|
2118
|
+
const value = currentPart.trim();
|
|
2119
|
+
if (value !== "") {
|
|
2120
|
+
rawEntries.push([currentKey, value]);
|
|
2121
|
+
}
|
|
2122
|
+
currentKey = null;
|
|
2123
|
+
currentPart = "";
|
|
2124
|
+
}
|
|
2125
|
+
for (const { 0: key, 1: value } of rawEntries) {
|
|
2126
|
+
switch (key) {
|
|
2127
|
+
case "background-color": {
|
|
2128
|
+
if (value != void 0) {
|
|
2129
|
+
css.backgroundColor = value;
|
|
2130
|
+
}
|
|
2131
|
+
break;
|
|
2132
|
+
}
|
|
2133
|
+
case "color": {
|
|
2134
|
+
if (value != void 0) {
|
|
2135
|
+
css.color = value;
|
|
2136
|
+
}
|
|
2137
|
+
break;
|
|
2138
|
+
}
|
|
2139
|
+
case "font-style": {
|
|
2140
|
+
if (["italic", "oblique", "oblique 14deg"].includes(value)) {
|
|
2141
|
+
css.fontStyle = "italic";
|
|
2142
|
+
}
|
|
2143
|
+
break;
|
|
2144
|
+
}
|
|
2145
|
+
case "font-weight": {
|
|
2146
|
+
if (value === "bold") {
|
|
2147
|
+
css.fontWeight = value;
|
|
2148
|
+
}
|
|
2149
|
+
break;
|
|
2150
|
+
}
|
|
2151
|
+
case "text-decoration": {
|
|
2152
|
+
css.textDecorationColor = null;
|
|
2153
|
+
css.textDecorationLine = [];
|
|
2154
|
+
const arguments_ = value.split(SPACE_PATTERN);
|
|
2155
|
+
for (const argument of arguments_) {
|
|
2156
|
+
const maybeColor = parseCssColor(argument);
|
|
2157
|
+
if (maybeColor != void 0) {
|
|
2158
|
+
css.textDecorationColor = maybeColor;
|
|
2159
|
+
} else if (["line-through", "overline", "underline"].includes(argument)) {
|
|
2160
|
+
css.textDecorationLine.push(argument);
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
break;
|
|
2164
|
+
}
|
|
2165
|
+
case "text-decoration-color": {
|
|
2166
|
+
const color = parseCssColor(value);
|
|
2167
|
+
if (color != void 0) {
|
|
2168
|
+
css.textDecorationColor = color;
|
|
2169
|
+
}
|
|
2170
|
+
break;
|
|
2171
|
+
}
|
|
2172
|
+
case "text-decoration-line": {
|
|
2173
|
+
css.textDecorationLine = [];
|
|
2174
|
+
const lineTypes = value.split(SPACE_PATTERN);
|
|
2175
|
+
for (const lineType of lineTypes) {
|
|
2176
|
+
if (["line-through", "overline", "underline"].includes(lineType)) {
|
|
2177
|
+
css.textDecorationLine.push(lineType);
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
break;
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
return css;
|
|
2185
|
+
};
|
|
2186
|
+
const cssToAnsi = (css, previousCss = null) => {
|
|
2187
|
+
previousCss = previousCss ?? getDefaultCss();
|
|
2188
|
+
let ansi = "";
|
|
2189
|
+
if (!colorEquals(css.backgroundColor, previousCss.backgroundColor)) {
|
|
2190
|
+
if (css.backgroundColor == void 0) {
|
|
2191
|
+
ansi += "\x1B[49m";
|
|
2192
|
+
} else {
|
|
2193
|
+
switch (css.backgroundColor) {
|
|
2194
|
+
case "black": {
|
|
2195
|
+
ansi += "\x1B[40m";
|
|
2196
|
+
break;
|
|
2197
|
+
}
|
|
2198
|
+
case "blue": {
|
|
2199
|
+
ansi += "\x1B[44m";
|
|
2200
|
+
break;
|
|
2201
|
+
}
|
|
2202
|
+
case "cyan": {
|
|
2203
|
+
ansi += "\x1B[46m";
|
|
2204
|
+
break;
|
|
2205
|
+
}
|
|
2206
|
+
case "green": {
|
|
2207
|
+
ansi += "\x1B[42m";
|
|
2208
|
+
break;
|
|
2209
|
+
}
|
|
2210
|
+
case "magenta": {
|
|
2211
|
+
ansi += "\x1B[45m";
|
|
2212
|
+
break;
|
|
2213
|
+
}
|
|
2214
|
+
case "red": {
|
|
2215
|
+
ansi += "\x1B[41m";
|
|
2216
|
+
break;
|
|
2217
|
+
}
|
|
2218
|
+
case "white": {
|
|
2219
|
+
ansi += "\x1B[47m";
|
|
2220
|
+
break;
|
|
2221
|
+
}
|
|
2222
|
+
case "yellow": {
|
|
2223
|
+
ansi += "\x1B[43m";
|
|
2224
|
+
break;
|
|
2225
|
+
}
|
|
2226
|
+
default: {
|
|
2227
|
+
if (Array.isArray(css.backgroundColor)) {
|
|
2228
|
+
const { 0: r, 1: g, 2: b } = css.backgroundColor;
|
|
2229
|
+
ansi += `\x1B[48;2;${String(r)};${String(g)};${String(b)}m`;
|
|
2230
|
+
} else {
|
|
2231
|
+
const parsed = parseCssColor(css.backgroundColor);
|
|
2232
|
+
if (parsed === null) {
|
|
2233
|
+
ansi += "\x1B[49m";
|
|
2234
|
+
} else {
|
|
2235
|
+
const { 0: r, 1: g, 2: b } = parsed;
|
|
2236
|
+
ansi += `\x1B[48;2;${String(r)};${String(g)};${String(b)}m`;
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
if (!colorEquals(css.color, previousCss.color)) {
|
|
2244
|
+
if (css.color == void 0) {
|
|
2245
|
+
ansi += "\x1B[39m";
|
|
2246
|
+
} else {
|
|
2247
|
+
switch (css.color) {
|
|
2248
|
+
case "black": {
|
|
2249
|
+
ansi += "\x1B[30m";
|
|
2250
|
+
break;
|
|
2251
|
+
}
|
|
2252
|
+
case "blue": {
|
|
2253
|
+
ansi += "\x1B[34m";
|
|
2254
|
+
break;
|
|
2255
|
+
}
|
|
2256
|
+
case "cyan": {
|
|
2257
|
+
ansi += "\x1B[36m";
|
|
2258
|
+
break;
|
|
2259
|
+
}
|
|
2260
|
+
case "green": {
|
|
2261
|
+
ansi += "\x1B[32m";
|
|
2262
|
+
break;
|
|
2263
|
+
}
|
|
2264
|
+
case "magenta": {
|
|
2265
|
+
ansi += "\x1B[35m";
|
|
2266
|
+
break;
|
|
2267
|
+
}
|
|
2268
|
+
case "red": {
|
|
2269
|
+
ansi += "\x1B[31m";
|
|
2270
|
+
break;
|
|
2271
|
+
}
|
|
2272
|
+
case "white": {
|
|
2273
|
+
ansi += "\x1B[37m";
|
|
2274
|
+
break;
|
|
2275
|
+
}
|
|
2276
|
+
case "yellow": {
|
|
2277
|
+
ansi += "\x1B[33m";
|
|
2278
|
+
break;
|
|
2279
|
+
}
|
|
2280
|
+
default: {
|
|
2281
|
+
if (Array.isArray(css.color)) {
|
|
2282
|
+
const { 0: r, 1: g, 2: b } = css.color;
|
|
2283
|
+
ansi += `\x1B[38;2;${String(r)};${String(g)};${String(b)}m`;
|
|
2284
|
+
} else {
|
|
2285
|
+
const parsed = parseCssColor(css.color);
|
|
2286
|
+
if (parsed === null) {
|
|
2287
|
+
ansi += "\x1B[39m";
|
|
2288
|
+
} else {
|
|
2289
|
+
const { 0: r, 1: g, 2: b } = parsed;
|
|
2290
|
+
ansi += `\x1B[38;2;${String(r)};${String(g)};${String(b)}m`;
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
if (css.fontWeight !== previousCss.fontWeight) {
|
|
2298
|
+
ansi += css.fontWeight === "bold" ? "\x1B[1m" : "\x1B[22m";
|
|
2299
|
+
}
|
|
2300
|
+
if (css.fontStyle !== previousCss.fontStyle) {
|
|
2301
|
+
ansi += css.fontStyle === "italic" ? "\x1B[3m" : "\x1B[23m";
|
|
2302
|
+
}
|
|
2303
|
+
if (!colorEquals(css.textDecorationColor, previousCss.textDecorationColor)) {
|
|
2304
|
+
if (css.textDecorationColor == void 0) {
|
|
2305
|
+
ansi += "\x1B[59m";
|
|
2306
|
+
} else {
|
|
2307
|
+
const { 0: r, 1: g, 2: b } = css.textDecorationColor;
|
|
2308
|
+
ansi += `\x1B[58;2;${String(r)};${String(g)};${String(b)}m`;
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
if (css.textDecorationLine.includes("line-through") !== previousCss.textDecorationLine.includes("line-through")) {
|
|
2312
|
+
ansi += css.textDecorationLine.includes("line-through") ? "\x1B[9m" : "\x1B[29m";
|
|
2313
|
+
}
|
|
2314
|
+
if (css.textDecorationLine.includes("overline") !== previousCss.textDecorationLine.includes("overline")) {
|
|
2315
|
+
ansi += css.textDecorationLine.includes("overline") ? "\x1B[53m" : "\x1B[55m";
|
|
2316
|
+
}
|
|
2317
|
+
if (css.textDecorationLine.includes("underline") !== previousCss.textDecorationLine.includes("underline")) {
|
|
2318
|
+
ansi += css.textDecorationLine.includes("underline") ? "\x1B[4m" : "\x1B[24m";
|
|
2319
|
+
}
|
|
2320
|
+
return ansi;
|
|
2321
|
+
};
|
|
2322
|
+
const tryStringify = (o) => {
|
|
2323
|
+
try {
|
|
2324
|
+
return JSON.stringify(o);
|
|
2325
|
+
} catch {
|
|
2326
|
+
return '"[Circular]"';
|
|
2327
|
+
}
|
|
2328
|
+
};
|
|
2329
|
+
const CHAR_PERCENT = "%".codePointAt(0);
|
|
2330
|
+
const CHAR_s = "s".codePointAt(0);
|
|
2331
|
+
const CHAR_d = "d".codePointAt(0);
|
|
2332
|
+
const CHAR_f = "f".codePointAt(0);
|
|
2333
|
+
const CHAR_i = "i".codePointAt(0);
|
|
2334
|
+
const CHAR_O = "O".codePointAt(0);
|
|
2335
|
+
const CHAR_o = "o".codePointAt(0);
|
|
2336
|
+
const CHAR_j = "j".codePointAt(0);
|
|
2337
|
+
const CHAR_c = "c".codePointAt(0);
|
|
2338
|
+
const format = (fmt, arguments_ = [], options = {}) => {
|
|
2339
|
+
if (typeof fmt !== "string" && typeof fmt !== "object" || fmt === null) {
|
|
2340
|
+
throw new TypeError(`fmt must be a string or object, got ${fmt === null ? "null" : typeof fmt}`);
|
|
2341
|
+
}
|
|
2342
|
+
const stringify = options.stringify ?? tryStringify;
|
|
2343
|
+
const offset = 1;
|
|
2344
|
+
if (typeof fmt === "object") {
|
|
2345
|
+
const argumentsLength = arguments_.length + offset;
|
|
2346
|
+
if (argumentsLength === 1) {
|
|
2347
|
+
return "{}";
|
|
2348
|
+
}
|
|
2349
|
+
const objects = Array.from({ length: argumentsLength });
|
|
2350
|
+
objects[0] = stringify(fmt);
|
|
2351
|
+
for (let index = 1; index < argumentsLength; index += 1) {
|
|
2352
|
+
objects[index] = stringify(arguments_[index - offset]);
|
|
2353
|
+
}
|
|
2354
|
+
return objects.join(" ");
|
|
2355
|
+
}
|
|
2356
|
+
if (arguments_.length === 0) {
|
|
2357
|
+
return fmt;
|
|
2358
|
+
}
|
|
2359
|
+
let result = "";
|
|
2360
|
+
let a = 1 - offset;
|
|
2361
|
+
let lastPosition = -1;
|
|
2362
|
+
let usedStyle = false;
|
|
2363
|
+
let previousCss = null;
|
|
2364
|
+
for (let index = 0; index < fmt.length; ) {
|
|
2365
|
+
if (fmt.codePointAt(index) === CHAR_PERCENT && index + 1 < fmt.length) {
|
|
2366
|
+
lastPosition = lastPosition > -1 ? lastPosition : 0;
|
|
2367
|
+
const c = fmt.codePointAt(index + 1);
|
|
2368
|
+
if (c === void 0) {
|
|
2369
|
+
a += 1;
|
|
2370
|
+
break;
|
|
2371
|
+
}
|
|
2372
|
+
switch (c) {
|
|
2373
|
+
case CHAR_c: {
|
|
2374
|
+
if (globalThis.window === void 0) {
|
|
2375
|
+
const css = parseCss(arguments_[a]);
|
|
2376
|
+
if (lastPosition < index) {
|
|
2377
|
+
result += fmt.slice(lastPosition, index);
|
|
2378
|
+
}
|
|
2379
|
+
result += cssToAnsi(css, previousCss);
|
|
2380
|
+
if (result !== "") {
|
|
2381
|
+
usedStyle = true;
|
|
2382
|
+
previousCss = css;
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
lastPosition = index + 2;
|
|
2386
|
+
index += 1;
|
|
2387
|
+
break;
|
|
2388
|
+
}
|
|
2389
|
+
case CHAR_d:
|
|
2390
|
+
case CHAR_f: {
|
|
2391
|
+
if (a >= arguments_.length || arguments_[a] == void 0) {
|
|
2392
|
+
break;
|
|
2393
|
+
}
|
|
2394
|
+
if (lastPosition < index) {
|
|
2395
|
+
result += fmt.slice(lastPosition, index);
|
|
2396
|
+
}
|
|
2397
|
+
result += Number(arguments_[a]).toString();
|
|
2398
|
+
lastPosition = index + 2;
|
|
2399
|
+
index += 1;
|
|
2400
|
+
break;
|
|
2401
|
+
}
|
|
2402
|
+
case CHAR_i: {
|
|
2403
|
+
if (a >= arguments_.length || arguments_[a] == void 0) {
|
|
2404
|
+
break;
|
|
2405
|
+
}
|
|
2406
|
+
if (lastPosition < index) {
|
|
2407
|
+
result += fmt.slice(lastPosition, index);
|
|
2408
|
+
}
|
|
2409
|
+
result += Math.floor(Number(arguments_[a])).toString();
|
|
2410
|
+
lastPosition = index + 2;
|
|
2411
|
+
index += 1;
|
|
2412
|
+
break;
|
|
2413
|
+
}
|
|
2414
|
+
case CHAR_j:
|
|
2415
|
+
case CHAR_O:
|
|
2416
|
+
case CHAR_o: {
|
|
2417
|
+
if (a >= arguments_.length || arguments_[a] === void 0) {
|
|
2418
|
+
break;
|
|
2419
|
+
}
|
|
2420
|
+
if (lastPosition < index) {
|
|
2421
|
+
result += fmt.slice(lastPosition, index);
|
|
2422
|
+
}
|
|
2423
|
+
const temporaryArgument = arguments_[a];
|
|
2424
|
+
const type = typeof temporaryArgument;
|
|
2425
|
+
if (type === "string") {
|
|
2426
|
+
result += `'${temporaryArgument}'`;
|
|
2427
|
+
lastPosition = index + 2;
|
|
2428
|
+
break;
|
|
2429
|
+
}
|
|
2430
|
+
if (type === "function") {
|
|
2431
|
+
result += temporaryArgument.name ? `[Function: ${temporaryArgument.name}]` : "[Function: <anonymous>]";
|
|
2432
|
+
lastPosition = index + 2;
|
|
2433
|
+
break;
|
|
2434
|
+
}
|
|
2435
|
+
result += stringify(temporaryArgument);
|
|
2436
|
+
lastPosition = index + 2;
|
|
2437
|
+
index += 1;
|
|
2438
|
+
break;
|
|
2439
|
+
}
|
|
2440
|
+
case CHAR_PERCENT: {
|
|
2441
|
+
if (lastPosition < index) {
|
|
2442
|
+
result += fmt.slice(lastPosition, index);
|
|
2443
|
+
}
|
|
2444
|
+
result += "%";
|
|
2445
|
+
lastPosition = index + 2;
|
|
2446
|
+
index += 1;
|
|
2447
|
+
a -= 1;
|
|
2448
|
+
break;
|
|
2449
|
+
}
|
|
2450
|
+
case CHAR_s: {
|
|
2451
|
+
if (a >= arguments_.length) {
|
|
2452
|
+
break;
|
|
2453
|
+
}
|
|
2454
|
+
if (lastPosition < index) {
|
|
2455
|
+
result += fmt.slice(lastPosition, index);
|
|
2456
|
+
}
|
|
2457
|
+
result += typeof arguments_[a] === "object" ? stringify(arguments_[a]) : String(arguments_[a]);
|
|
2458
|
+
lastPosition = index + 2;
|
|
2459
|
+
index += 1;
|
|
2460
|
+
break;
|
|
2461
|
+
}
|
|
2462
|
+
default: {
|
|
2463
|
+
if (typeof options.formatters?.[c] === "function") {
|
|
2464
|
+
if (lastPosition < index) {
|
|
2465
|
+
result += fmt.slice(lastPosition, index);
|
|
2466
|
+
}
|
|
2467
|
+
result += options.formatters[c](arguments_[a]);
|
|
2468
|
+
lastPosition = index + 2;
|
|
2469
|
+
index += 1;
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
a += 1;
|
|
2474
|
+
}
|
|
2475
|
+
index += 1;
|
|
2476
|
+
}
|
|
2477
|
+
if (lastPosition === -1) {
|
|
2478
|
+
return fmt;
|
|
2479
|
+
}
|
|
2480
|
+
if (lastPosition < fmt.length) {
|
|
2481
|
+
result += fmt.slice(lastPosition);
|
|
2482
|
+
}
|
|
2483
|
+
if (usedStyle) {
|
|
2484
|
+
result += "\x1B[0m";
|
|
2485
|
+
}
|
|
2486
|
+
return result;
|
|
2487
|
+
};
|
|
2488
|
+
const build = (options = {}) => {
|
|
2489
|
+
const formatters = {};
|
|
2490
|
+
if (typeof options.formatters === "object") {
|
|
2491
|
+
Object.entries(options.formatters).forEach(([key, formatterFunction]) => {
|
|
2492
|
+
if (key.length === 0) {
|
|
2493
|
+
throw new Error(`Formatter %${key} has no characters`);
|
|
2494
|
+
}
|
|
2495
|
+
if (key.length > 1) {
|
|
2496
|
+
throw new Error(`Formatter %${key} has more than one character`);
|
|
2497
|
+
}
|
|
2498
|
+
if (typeof formatterFunction !== "function") {
|
|
2499
|
+
throw new TypeError(`Formatter for %${key} is not a function`);
|
|
2500
|
+
}
|
|
2501
|
+
const c = key.codePointAt(0);
|
|
2502
|
+
if (c === void 0) {
|
|
2503
|
+
throw new Error(`${key}.codePointAt(0) failed to return a value, please report this issue`);
|
|
2504
|
+
}
|
|
2505
|
+
formatters[c] = formatterFunction;
|
|
2506
|
+
});
|
|
2507
|
+
}
|
|
2508
|
+
return (f, arguments_ = [], formatOptions = {}) => format(f, arguments_, { ...formatOptions, formatters });
|
|
2509
|
+
};
|
|
2510
|
+
|
|
2511
|
+
class MessageFormatterProcessor {
|
|
2512
|
+
/** Custom stringify function for object serialization */
|
|
2513
|
+
#stringify;
|
|
2514
|
+
/** Custom formatters for message interpolation */
|
|
2515
|
+
#formatters;
|
|
2516
|
+
/**
|
|
2517
|
+
* Creates a new MessageFormatterProcessor instance.
|
|
2518
|
+
* @param options Configuration options
|
|
2519
|
+
* @param options.formatters Custom formatters for message interpolation
|
|
2520
|
+
*/
|
|
2521
|
+
constructor(options = {}) {
|
|
2522
|
+
this.#formatters = options.formatters;
|
|
2523
|
+
}
|
|
2524
|
+
/**
|
|
2525
|
+
* Sets the stringify function for object serialization.
|
|
2526
|
+
* @param function_ The stringify function to use for serializing objects
|
|
2527
|
+
*/
|
|
2528
|
+
setStringify(function_) {
|
|
2529
|
+
this.#stringify = function_;
|
|
2530
|
+
}
|
|
2531
|
+
/**
|
|
2532
|
+
* Processes log metadata to format messages.
|
|
2533
|
+
*
|
|
2534
|
+
* Applies string interpolation and custom formatters to the message
|
|
2535
|
+
* and contextual data in the log metadata.
|
|
2536
|
+
* @param meta The log metadata to process
|
|
2537
|
+
* @returns The processed metadata with formatted messages
|
|
2538
|
+
*/
|
|
2539
|
+
process(meta) {
|
|
2540
|
+
const formatter = build({
|
|
2541
|
+
formatters: this.#formatters});
|
|
2542
|
+
if (meta.message !== void 0) {
|
|
2543
|
+
meta.message = this.#format(formatter, meta.message, meta.context ?? []);
|
|
2544
|
+
}
|
|
2545
|
+
return meta;
|
|
2546
|
+
}
|
|
2547
|
+
/**
|
|
2548
|
+
* Recursively formats data using the formatter.
|
|
2549
|
+
*
|
|
2550
|
+
* Applies string interpolation and formatting to strings, arrays, and objects.
|
|
2551
|
+
* @param formatter The formatter function to use
|
|
2552
|
+
* @param data The data to format (string, array, or object)
|
|
2553
|
+
* @param arguments_ Additional arguments for formatting
|
|
2554
|
+
* @returns The formatted data
|
|
2555
|
+
* @private
|
|
2556
|
+
*/
|
|
2557
|
+
#format(formatter, data, arguments_ = []) {
|
|
2558
|
+
if (typeof data === "string") {
|
|
2559
|
+
return formatter(data, arguments_);
|
|
2560
|
+
}
|
|
2561
|
+
if (typeof data === "object" && data !== null) {
|
|
2562
|
+
const record = data;
|
|
2563
|
+
const keys = Object.keys(record);
|
|
2564
|
+
for (let i = 0; i < keys.length; i += 1) {
|
|
2565
|
+
const index = keys[i];
|
|
2566
|
+
const value = record[index];
|
|
2567
|
+
if (typeof value === "string" || Array.isArray(value) || typeof value === "object") {
|
|
2568
|
+
record[index] = this.#format(formatter, value, arguments_);
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
return data;
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
|
|
2576
|
+
const PAIL_DIST_REGEX = /[\\/]pail[\\/]dist/;
|
|
2577
|
+
const pailFileFilter = (line) => !PAIL_DIST_REGEX.test(line);
|
|
2578
|
+
class PrettyReporter extends AbstractPrettyReporter {
|
|
2579
|
+
#stdout;
|
|
2580
|
+
#stderr;
|
|
2581
|
+
#interactiveManager;
|
|
2582
|
+
#interactive = false;
|
|
2583
|
+
#inspectOptions;
|
|
2584
|
+
#errorOptions;
|
|
2585
|
+
/**
|
|
2586
|
+
* Creates a new Server Pretty Reporter instance.
|
|
2587
|
+
* @param options Configuration options for styling, error rendering, and object inspection
|
|
2588
|
+
*/
|
|
2589
|
+
constructor(options = {}) {
|
|
2590
|
+
const { error: errorOptions, inspect: inspectOptions, ...rest } = options;
|
|
2591
|
+
super({
|
|
2592
|
+
uppercase: {
|
|
2593
|
+
label: true,
|
|
2594
|
+
...rest.uppercase
|
|
2595
|
+
},
|
|
2596
|
+
...rest
|
|
2597
|
+
});
|
|
2598
|
+
this.#inspectOptions = { ...defaultInspectorConfig, ...inspectOptions };
|
|
2599
|
+
this.#errorOptions = {
|
|
2600
|
+
...errorOptions,
|
|
2601
|
+
color: {
|
|
2602
|
+
fileLine: green,
|
|
2603
|
+
hint: cyan,
|
|
2604
|
+
marker: red,
|
|
2605
|
+
message: red,
|
|
2606
|
+
method: greenBright,
|
|
2607
|
+
title: red
|
|
2608
|
+
}
|
|
2609
|
+
};
|
|
2610
|
+
this.#stdout = stdout;
|
|
2611
|
+
this.#stderr = stderr;
|
|
2612
|
+
}
|
|
2613
|
+
/**
|
|
2614
|
+
* Sets the stdout stream for the reporter.
|
|
2615
|
+
* @param stdout_ The writable stream to use for standard output
|
|
2616
|
+
*/
|
|
2617
|
+
setStdout(stdout_) {
|
|
2618
|
+
this.#stdout = stdout_;
|
|
2619
|
+
}
|
|
2620
|
+
/**
|
|
2621
|
+
* Sets the stderr stream for the reporter.
|
|
2622
|
+
* @param stderr_ The writable stream to use for error output
|
|
2623
|
+
*/
|
|
2624
|
+
setStderr(stderr_) {
|
|
2625
|
+
this.#stderr = stderr_;
|
|
2626
|
+
}
|
|
2627
|
+
/**
|
|
2628
|
+
* Sets the interactive manager for handling interactive output.
|
|
2629
|
+
* @param manager The interactive manager instance, or undefined to disable
|
|
2630
|
+
*/
|
|
2631
|
+
setInteractiveManager(manager) {
|
|
2632
|
+
this.#interactiveManager = manager;
|
|
2633
|
+
}
|
|
2634
|
+
/**
|
|
2635
|
+
* Enables or disables interactive mode.
|
|
2636
|
+
* @param interactive Whether to enable interactive terminal features
|
|
2637
|
+
*/
|
|
2638
|
+
setIsInteractive(interactive) {
|
|
2639
|
+
this.#interactive = interactive;
|
|
2640
|
+
}
|
|
2641
|
+
log(meta) {
|
|
2642
|
+
this._log(this._formatMessage(meta), meta.type.level);
|
|
2643
|
+
}
|
|
2644
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity, no-underscore-dangle
|
|
2645
|
+
_formatMessage(data) {
|
|
2646
|
+
const { columns } = terminalSize();
|
|
2647
|
+
let size = columns;
|
|
2648
|
+
if (typeof this.styles.messageLength === "number") {
|
|
2649
|
+
size = this.styles.messageLength;
|
|
2650
|
+
}
|
|
2651
|
+
const { badge, context, date, error, file, groups, label, message, prefix, repeated, scope, suffix, traceError, type } = data;
|
|
2652
|
+
const { color } = this.loggerTypes[type.name];
|
|
2653
|
+
const colorized = color ? colorize[color] : white;
|
|
2654
|
+
const groupSpaces = groups.map(() => " ").join("");
|
|
2655
|
+
const items = [];
|
|
2656
|
+
if (groups.length > 0) {
|
|
2657
|
+
items.push(`${groupSpaces + grey(`[${groups.at(-1) ?? ""}]`)} `);
|
|
2658
|
+
}
|
|
2659
|
+
if (date) {
|
|
2660
|
+
items.push(`${grey(this.styles.dateFormatter(typeof date === "string" ? new Date(date) : date))} `);
|
|
2661
|
+
}
|
|
2662
|
+
if (badge) {
|
|
2663
|
+
items.push(colorized(badge));
|
|
2664
|
+
} else {
|
|
2665
|
+
const longestBadge = getLongestBadge(this.loggerTypes);
|
|
2666
|
+
if (longestBadge.length > 0) {
|
|
2667
|
+
items.push(`${grey(".".repeat(longestBadge.length))} `);
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
const longestLabel = getLongestLabel(this.loggerTypes);
|
|
2671
|
+
if (label) {
|
|
2672
|
+
const longestLabelWidth = getStringWidth(longestLabel);
|
|
2673
|
+
const labelWidth = getStringWidth(label);
|
|
2674
|
+
items.push(`${colorized(formatLabel(label, this.styles))} `, grey(".".repeat(Math.max(0, longestLabelWidth - labelWidth))));
|
|
2675
|
+
} else {
|
|
2676
|
+
items.push(grey(".".repeat(longestLabel.length + 2)));
|
|
2677
|
+
}
|
|
2678
|
+
if (repeated) {
|
|
2679
|
+
items.push(`${bgGrey.white(`[${String(repeated)}x]`)} `);
|
|
2680
|
+
}
|
|
2681
|
+
if (Array.isArray(scope) && scope.length > 0) {
|
|
2682
|
+
items.push(` ${grey(`[${scope.join(" > ")}]`)} `);
|
|
2683
|
+
}
|
|
2684
|
+
if (prefix) {
|
|
2685
|
+
items.push(`${grey(`${Array.isArray(scope) && scope.length > 0 ? ". " : " "}[${this.styles.underline.prefix ? underline(prefix) : prefix}]`)} `);
|
|
2686
|
+
}
|
|
2687
|
+
const titleSize = getStringWidth(items.join(" "));
|
|
2688
|
+
if (file) {
|
|
2689
|
+
const fileMessage = (file.name ?? "") + (file.line ? `:${String(file.line)}` : "");
|
|
2690
|
+
const fileMessageSize = getStringWidth(fileMessage);
|
|
2691
|
+
if (fileMessageSize + titleSize + 2 > size) {
|
|
2692
|
+
items.push(grey(` ${fileMessage}`));
|
|
2693
|
+
} else {
|
|
2694
|
+
const dots = Math.max(0, size - titleSize - fileMessageSize - 2);
|
|
2695
|
+
items.push(grey(`${".".repeat(dots)} ${fileMessage}`));
|
|
2696
|
+
}
|
|
2697
|
+
} else {
|
|
2698
|
+
items.push(grey(".".repeat(Math.max(0, size - titleSize - 1))));
|
|
2699
|
+
}
|
|
2700
|
+
if (items.length > 0) {
|
|
2701
|
+
items.push("\n\n");
|
|
2702
|
+
}
|
|
2703
|
+
if (message !== EMPTY_SYMBOL) {
|
|
2704
|
+
const formattedMessage = typeof message === "string" ? message : inspect(message, this.#inspectOptions);
|
|
2705
|
+
items.push(
|
|
2706
|
+
groupSpaces + wordWrap(formattedMessage, {
|
|
2707
|
+
trim: false,
|
|
2708
|
+
width: size - 3,
|
|
2709
|
+
wrapMode: WrapMode.STRICT_WIDTH
|
|
2710
|
+
})
|
|
2711
|
+
);
|
|
2712
|
+
}
|
|
2713
|
+
if (context) {
|
|
2714
|
+
let hasError = false;
|
|
2715
|
+
items.push(
|
|
2716
|
+
...context.map((value) => {
|
|
2717
|
+
if (value instanceof Error) {
|
|
2718
|
+
hasError = true;
|
|
2719
|
+
return `
|
|
2720
|
+
|
|
2721
|
+
${renderError(value, {
|
|
2722
|
+
...this.#errorOptions,
|
|
2723
|
+
filterStacktrace: pailFileFilter,
|
|
2724
|
+
prefix: groupSpaces
|
|
2725
|
+
})}`;
|
|
2726
|
+
}
|
|
2727
|
+
if (typeof value === "object") {
|
|
2728
|
+
return ` ${inspect(value, this.#inspectOptions)}`;
|
|
2729
|
+
}
|
|
2730
|
+
const newValue = (hasError ? "\n\n" : " ") + String(value);
|
|
2731
|
+
hasError = false;
|
|
2732
|
+
return newValue;
|
|
2733
|
+
})
|
|
2734
|
+
);
|
|
2735
|
+
}
|
|
2736
|
+
if (error) {
|
|
2737
|
+
items.push(
|
|
2738
|
+
renderError(error, {
|
|
2739
|
+
...this.#errorOptions,
|
|
2740
|
+
filterStacktrace: pailFileFilter,
|
|
2741
|
+
prefix: groupSpaces
|
|
2742
|
+
})
|
|
2743
|
+
);
|
|
2744
|
+
}
|
|
2745
|
+
if (traceError) {
|
|
2746
|
+
items.push(
|
|
2747
|
+
`
|
|
2748
|
+
|
|
2749
|
+
${renderError(traceError, {
|
|
2750
|
+
...this.#errorOptions,
|
|
2751
|
+
filterStacktrace: pailFileFilter,
|
|
2752
|
+
hideErrorCauseCodeView: true,
|
|
2753
|
+
hideErrorCodeView: true,
|
|
2754
|
+
hideErrorErrorsCodeView: true,
|
|
2755
|
+
hideMessage: true,
|
|
2756
|
+
prefix: groupSpaces
|
|
2757
|
+
})}`
|
|
2758
|
+
);
|
|
2759
|
+
}
|
|
2760
|
+
if (suffix) {
|
|
2761
|
+
items.push("\n", groupSpaces + grey(this.styles.underline.suffix ? underline(suffix) : suffix));
|
|
2762
|
+
}
|
|
2763
|
+
return items.join("");
|
|
2764
|
+
}
|
|
2765
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
2766
|
+
_log(message, logLevel) {
|
|
2767
|
+
const streamType = ["error", "trace", "warn"].includes(logLevel) ? "stderr" : "stdout";
|
|
2768
|
+
const stream = streamType === "stderr" ? this.#stderr : this.#stdout;
|
|
2769
|
+
if (this.#interactive && this.#interactiveManager !== void 0 && stream.isTTY) {
|
|
2770
|
+
this.#interactiveManager.update(streamType, message.split("\n"), 0);
|
|
2771
|
+
} else {
|
|
2772
|
+
writeStream(`${message}
|
|
2773
|
+
`, stream);
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
|
|
508
2778
|
const getDefaultLogLevel = () => {
|
|
509
2779
|
if (env.NODE_ENV === "debug" || env.DEBUG !== void 0) {
|
|
510
2780
|
return "debug";
|
|
@@ -530,4 +2800,4 @@ const createPail = (options) => {
|
|
|
530
2800
|
};
|
|
531
2801
|
const pail = createPail();
|
|
532
2802
|
|
|
533
|
-
export {
|
|
2803
|
+
export { createPail, pail };
|