@logtape/file 0.9.0-dev.1
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/LICENSE +20 -0
- package/README.md +43 -0
- package/esm/_dnt.shims.js +57 -0
- package/esm/file/filesink.base.js +78 -0
- package/esm/file/filesink.node.js +47 -0
- package/esm/file/mod.js +1 -0
- package/esm/logtape/config.js +287 -0
- package/esm/logtape/context.js +23 -0
- package/esm/logtape/filter.js +42 -0
- package/esm/logtape/formatter.js +261 -0
- package/esm/logtape/level.js +59 -0
- package/esm/logtape/logger.js +480 -0
- package/esm/logtape/mod.js +8 -0
- package/esm/logtape/nodeUtil.js +2 -0
- package/esm/logtape/record.js +1 -0
- package/esm/logtape/sink.js +96 -0
- package/esm/package.json +3 -0
- package/package.json +55 -0
- package/script/_dnt.shims.js +60 -0
- package/script/file/filesink.base.js +82 -0
- package/script/file/filesink.node.js +55 -0
- package/script/file/mod.js +6 -0
- package/script/logtape/config.js +321 -0
- package/script/logtape/context.js +26 -0
- package/script/logtape/filter.js +46 -0
- package/script/logtape/formatter.js +270 -0
- package/script/logtape/level.js +64 -0
- package/script/logtape/logger.js +511 -0
- package/script/logtape/mod.js +34 -0
- package/script/logtape/nodeUtil.js +7 -0
- package/script/logtape/record.js +2 -0
- package/script/logtape/sink.js +101 -0
- package/script/package.json +3 -0
- package/types/_dnt.shims.d.ts +2 -0
- package/types/_dnt.shims.d.ts.map +1 -0
- package/types/_dnt.test_shims.d.ts.map +1 -0
- package/types/deps/jsr.io/@david/which-runtime/0.2.1/mod.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/assert/0.222.1/_constants.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/assert/0.222.1/_diff.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/assert/0.222.1/_format.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/assert/0.222.1/assert_equals.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/assert/0.222.1/assertion_error.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/assert/0.222.1/equal.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/fmt/0.222.1/colors.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/path/1.0.8/_common/assert_path.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/path/1.0.8/_common/constants.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/path/1.0.8/_common/normalize.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/path/1.0.8/_common/normalize_string.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/path/1.0.8/_os.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/path/1.0.8/join.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/path/1.0.8/posix/_util.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/path/1.0.8/posix/join.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/path/1.0.8/posix/normalize.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/path/1.0.8/windows/_util.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/path/1.0.8/windows/join.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/path/1.0.8/windows/normalize.d.ts.map +1 -0
- package/types/file/filesink.base.d.ts +89 -0
- package/types/file/filesink.base.d.ts.map +1 -0
- package/types/file/filesink.node.d.ts +34 -0
- package/types/file/filesink.node.d.ts.map +1 -0
- package/types/file/filesink.test.d.ts.map +1 -0
- package/types/file/mod.d.ts +3 -0
- package/types/file/mod.d.ts.map +1 -0
- package/types/logtape/config.d.ts +183 -0
- package/types/logtape/config.d.ts.map +1 -0
- package/types/logtape/context.d.ts +35 -0
- package/types/logtape/context.d.ts.map +1 -0
- package/types/logtape/filter.d.ts +31 -0
- package/types/logtape/filter.d.ts.map +1 -0
- package/types/logtape/fixtures.d.ts.map +1 -0
- package/types/logtape/formatter.d.ts +260 -0
- package/types/logtape/formatter.d.ts.map +1 -0
- package/types/logtape/level.d.ts +32 -0
- package/types/logtape/level.d.ts.map +1 -0
- package/types/logtape/logger.d.ts +423 -0
- package/types/logtape/logger.d.ts.map +1 -0
- package/types/logtape/mod.d.ts +9 -0
- package/types/logtape/mod.d.ts.map +1 -0
- package/types/logtape/nodeUtil.d.ts +3 -0
- package/types/logtape/nodeUtil.d.ts.map +1 -0
- package/types/logtape/record.d.ts +44 -0
- package/types/logtape/record.d.ts.map +1 -0
- package/types/logtape/sink.d.ts +108 -0
- package/types/logtape/sink.d.ts.map +1 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import util from "./nodeUtil.js";
|
|
2
|
+
/**
|
|
3
|
+
* The severity level abbreviations.
|
|
4
|
+
*/
|
|
5
|
+
const levelAbbreviations = {
|
|
6
|
+
"debug": "DBG",
|
|
7
|
+
"info": "INF",
|
|
8
|
+
"warning": "WRN",
|
|
9
|
+
"error": "ERR",
|
|
10
|
+
"fatal": "FTL",
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* A platform-specific inspect function. In Deno, this is {@link Deno.inspect},
|
|
14
|
+
* and in Node.js/Bun it is `util.inspect()`. If neither is available, it
|
|
15
|
+
* falls back to {@link JSON.stringify}.
|
|
16
|
+
*
|
|
17
|
+
* @param value The value to inspect.
|
|
18
|
+
* @param options The options for inspecting the value.
|
|
19
|
+
* If `colors` is `true`, the output will be ANSI-colored.
|
|
20
|
+
* @returns The string representation of the value.
|
|
21
|
+
*/
|
|
22
|
+
const inspect =
|
|
23
|
+
// @ts-ignore: Deno global
|
|
24
|
+
// dnt-shim-ignore
|
|
25
|
+
"Deno" in globalThis && "inspect" in globalThis.Deno &&
|
|
26
|
+
// @ts-ignore: Deno global
|
|
27
|
+
// dnt-shim-ignore
|
|
28
|
+
typeof globalThis.Deno.inspect === "function"
|
|
29
|
+
? (v, opts) =>
|
|
30
|
+
// @ts-ignore: Deno global
|
|
31
|
+
// dnt-shim-ignore
|
|
32
|
+
globalThis.Deno.inspect(v, {
|
|
33
|
+
strAbbreviateSize: Infinity,
|
|
34
|
+
iterableLimit: Infinity,
|
|
35
|
+
...opts,
|
|
36
|
+
})
|
|
37
|
+
// @ts-ignore: Node.js global
|
|
38
|
+
// dnt-shim-ignore
|
|
39
|
+
: util != null && "inspect" in util && typeof util.inspect === "function"
|
|
40
|
+
? (v, opts) =>
|
|
41
|
+
// @ts-ignore: Node.js global
|
|
42
|
+
// dnt-shim-ignore
|
|
43
|
+
util.inspect(v, {
|
|
44
|
+
maxArrayLength: Infinity,
|
|
45
|
+
maxStringLength: Infinity,
|
|
46
|
+
...opts,
|
|
47
|
+
})
|
|
48
|
+
: (v) => JSON.stringify(v);
|
|
49
|
+
/**
|
|
50
|
+
* Get a text formatter with the specified options. Although it's flexible
|
|
51
|
+
* enough to create a custom formatter, if you want more control, you can
|
|
52
|
+
* create a custom formatter that satisfies the {@link TextFormatter} type
|
|
53
|
+
* instead.
|
|
54
|
+
*
|
|
55
|
+
* For more information on the options, see {@link TextFormatterOptions}.
|
|
56
|
+
*
|
|
57
|
+
* By default, the formatter formats log records as follows:
|
|
58
|
+
*
|
|
59
|
+
* ```
|
|
60
|
+
* 2023-11-14 22:13:20.000 +00:00 [INF] category·subcategory: Hello, world!
|
|
61
|
+
* ```
|
|
62
|
+
* @param options The options for the text formatter.
|
|
63
|
+
* @returns The text formatter.
|
|
64
|
+
* @since 0.6.0
|
|
65
|
+
*/
|
|
66
|
+
export function getTextFormatter(options = {}) {
|
|
67
|
+
const timestampRenderer = options.timestamp == null || options.timestamp === "date-time-timezone"
|
|
68
|
+
? (ts) => new Date(ts).toISOString().replace("T", " ").replace("Z", " +00:00")
|
|
69
|
+
: options.timestamp === "date-time-tz"
|
|
70
|
+
? (ts) => new Date(ts).toISOString().replace("T", " ").replace("Z", " +00")
|
|
71
|
+
: options.timestamp === "date-time"
|
|
72
|
+
? (ts) => new Date(ts).toISOString().replace("T", " ").replace("Z", "")
|
|
73
|
+
: options.timestamp === "time-timezone"
|
|
74
|
+
? (ts) => new Date(ts).toISOString().replace(/.*T/, "").replace("Z", " +00:00")
|
|
75
|
+
: options.timestamp === "time-tz"
|
|
76
|
+
? (ts) => new Date(ts).toISOString().replace(/.*T/, "").replace("Z", " +00")
|
|
77
|
+
: options.timestamp === "time"
|
|
78
|
+
? (ts) => new Date(ts).toISOString().replace(/.*T/, "").replace("Z", "")
|
|
79
|
+
: options.timestamp === "date"
|
|
80
|
+
? (ts) => new Date(ts).toISOString().replace(/T.*/, "")
|
|
81
|
+
: options.timestamp === "rfc3339"
|
|
82
|
+
? (ts) => new Date(ts).toISOString()
|
|
83
|
+
: options.timestamp;
|
|
84
|
+
const categorySeparator = options.category ?? "·";
|
|
85
|
+
const valueRenderer = options.value ?? inspect;
|
|
86
|
+
const levelRenderer = options.level == null || options.level === "ABBR"
|
|
87
|
+
? (level) => levelAbbreviations[level]
|
|
88
|
+
: options.level === "abbr"
|
|
89
|
+
? (level) => levelAbbreviations[level].toLowerCase()
|
|
90
|
+
: options.level === "FULL"
|
|
91
|
+
? (level) => level.toUpperCase()
|
|
92
|
+
: options.level === "full"
|
|
93
|
+
? (level) => level
|
|
94
|
+
: options.level === "L"
|
|
95
|
+
? (level) => level.charAt(0).toUpperCase()
|
|
96
|
+
: options.level === "l"
|
|
97
|
+
? (level) => level.charAt(0)
|
|
98
|
+
: options.level;
|
|
99
|
+
const formatter = options.format ??
|
|
100
|
+
(({ timestamp, level, category, message }) => `${timestamp} [${level}] ${category}: ${message}`);
|
|
101
|
+
return (record) => {
|
|
102
|
+
let message = "";
|
|
103
|
+
for (let i = 0; i < record.message.length; i++) {
|
|
104
|
+
if (i % 2 === 0)
|
|
105
|
+
message += record.message[i];
|
|
106
|
+
else
|
|
107
|
+
message += valueRenderer(record.message[i]);
|
|
108
|
+
}
|
|
109
|
+
const timestamp = timestampRenderer(record.timestamp);
|
|
110
|
+
const level = levelRenderer(record.level);
|
|
111
|
+
const category = typeof categorySeparator === "function"
|
|
112
|
+
? categorySeparator(record.category)
|
|
113
|
+
: record.category.join(categorySeparator);
|
|
114
|
+
const values = {
|
|
115
|
+
timestamp,
|
|
116
|
+
level,
|
|
117
|
+
category,
|
|
118
|
+
message,
|
|
119
|
+
record,
|
|
120
|
+
};
|
|
121
|
+
return `${formatter(values)}\n`;
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The default text formatter. This formatter formats log records as follows:
|
|
126
|
+
*
|
|
127
|
+
* ```
|
|
128
|
+
* 2023-11-14 22:13:20.000 +00:00 [INF] category·subcategory: Hello, world!
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* @param record The log record to format.
|
|
132
|
+
* @returns The formatted log record.
|
|
133
|
+
*/
|
|
134
|
+
export const defaultTextFormatter = getTextFormatter();
|
|
135
|
+
const RESET = "\x1b[0m";
|
|
136
|
+
const ansiColors = {
|
|
137
|
+
black: "\x1b[30m",
|
|
138
|
+
red: "\x1b[31m",
|
|
139
|
+
green: "\x1b[32m",
|
|
140
|
+
yellow: "\x1b[33m",
|
|
141
|
+
blue: "\x1b[34m",
|
|
142
|
+
magenta: "\x1b[35m",
|
|
143
|
+
cyan: "\x1b[36m",
|
|
144
|
+
white: "\x1b[37m",
|
|
145
|
+
};
|
|
146
|
+
const ansiStyles = {
|
|
147
|
+
bold: "\x1b[1m",
|
|
148
|
+
dim: "\x1b[2m",
|
|
149
|
+
italic: "\x1b[3m",
|
|
150
|
+
underline: "\x1b[4m",
|
|
151
|
+
strikethrough: "\x1b[9m",
|
|
152
|
+
};
|
|
153
|
+
const defaultLevelColors = {
|
|
154
|
+
debug: "blue",
|
|
155
|
+
info: "green",
|
|
156
|
+
warning: "yellow",
|
|
157
|
+
error: "red",
|
|
158
|
+
fatal: "magenta",
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Get an ANSI color formatter with the specified options.
|
|
162
|
+
*
|
|
163
|
+
* 
|
|
164
|
+
* @param option The options for the ANSI color formatter.
|
|
165
|
+
* @returns The ANSI color formatter.
|
|
166
|
+
* @since 0.6.0
|
|
167
|
+
*/
|
|
168
|
+
export function getAnsiColorFormatter(options = {}) {
|
|
169
|
+
const format = options.format;
|
|
170
|
+
const timestampStyle = typeof options.timestampStyle === "undefined"
|
|
171
|
+
? "dim"
|
|
172
|
+
: options.timestampStyle;
|
|
173
|
+
const timestampColor = options.timestampColor ?? null;
|
|
174
|
+
const timestampPrefix = `${timestampStyle == null ? "" : ansiStyles[timestampStyle]}${timestampColor == null ? "" : ansiColors[timestampColor]}`;
|
|
175
|
+
const timestampSuffix = timestampStyle == null && timestampColor == null
|
|
176
|
+
? ""
|
|
177
|
+
: RESET;
|
|
178
|
+
const levelStyle = typeof options.levelStyle === "undefined"
|
|
179
|
+
? "bold"
|
|
180
|
+
: options.levelStyle;
|
|
181
|
+
const levelColors = options.levelColors ?? defaultLevelColors;
|
|
182
|
+
const categoryStyle = typeof options.categoryStyle === "undefined"
|
|
183
|
+
? "dim"
|
|
184
|
+
: options.categoryStyle;
|
|
185
|
+
const categoryColor = options.categoryColor ?? null;
|
|
186
|
+
const categoryPrefix = `${categoryStyle == null ? "" : ansiStyles[categoryStyle]}${categoryColor == null ? "" : ansiColors[categoryColor]}`;
|
|
187
|
+
const categorySuffix = categoryStyle == null && categoryColor == null
|
|
188
|
+
? ""
|
|
189
|
+
: RESET;
|
|
190
|
+
return getTextFormatter({
|
|
191
|
+
timestamp: "date-time-tz",
|
|
192
|
+
value(value) {
|
|
193
|
+
return inspect(value, { colors: true });
|
|
194
|
+
},
|
|
195
|
+
...options,
|
|
196
|
+
format({ timestamp, level, category, message, record }) {
|
|
197
|
+
const levelColor = levelColors[record.level];
|
|
198
|
+
timestamp = `${timestampPrefix}${timestamp}${timestampSuffix}`;
|
|
199
|
+
level = `${levelStyle == null ? "" : ansiStyles[levelStyle]}${levelColor == null ? "" : ansiColors[levelColor]}${level}${levelStyle == null && levelColor == null ? "" : RESET}`;
|
|
200
|
+
return format == null
|
|
201
|
+
? `${timestamp} ${level} ${categoryPrefix}${category}:${categorySuffix} ${message}`
|
|
202
|
+
: format({
|
|
203
|
+
timestamp,
|
|
204
|
+
level,
|
|
205
|
+
category: `${categoryPrefix}${category}${categorySuffix}`,
|
|
206
|
+
message,
|
|
207
|
+
record,
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* A text formatter that uses ANSI colors to format log records.
|
|
214
|
+
*
|
|
215
|
+
* 
|
|
216
|
+
*
|
|
217
|
+
* @param record The log record to format.
|
|
218
|
+
* @returns The formatted log record.
|
|
219
|
+
* @since 0.5.0
|
|
220
|
+
*/
|
|
221
|
+
export const ansiColorFormatter = getAnsiColorFormatter();
|
|
222
|
+
/**
|
|
223
|
+
* The styles for the log level in the console.
|
|
224
|
+
*/
|
|
225
|
+
const logLevelStyles = {
|
|
226
|
+
"debug": "background-color: gray; color: white;",
|
|
227
|
+
"info": "background-color: white; color: black;",
|
|
228
|
+
"warning": "background-color: orange; color: black;",
|
|
229
|
+
"error": "background-color: red; color: white;",
|
|
230
|
+
"fatal": "background-color: maroon; color: white;",
|
|
231
|
+
};
|
|
232
|
+
/**
|
|
233
|
+
* The default console formatter.
|
|
234
|
+
*
|
|
235
|
+
* @param record The log record to format.
|
|
236
|
+
* @returns The formatted log record, as an array of arguments for
|
|
237
|
+
* {@link console.log}.
|
|
238
|
+
*/
|
|
239
|
+
export function defaultConsoleFormatter(record) {
|
|
240
|
+
let msg = "";
|
|
241
|
+
const values = [];
|
|
242
|
+
for (let i = 0; i < record.message.length; i++) {
|
|
243
|
+
if (i % 2 === 0)
|
|
244
|
+
msg += record.message[i];
|
|
245
|
+
else {
|
|
246
|
+
msg += "%o";
|
|
247
|
+
values.push(record.message[i]);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
const date = new Date(record.timestamp);
|
|
251
|
+
const time = `${date.getUTCHours().toString().padStart(2, "0")}:${date.getUTCMinutes().toString().padStart(2, "0")}:${date.getUTCSeconds().toString().padStart(2, "0")}.${date.getUTCMilliseconds().toString().padStart(3, "0")}`;
|
|
252
|
+
return [
|
|
253
|
+
`%c${time} %c${levelAbbreviations[record.level]}%c %c${record.category.join("\xb7")} %c${msg}`,
|
|
254
|
+
"color: gray;",
|
|
255
|
+
logLevelStyles[record.level],
|
|
256
|
+
"background-color: default;",
|
|
257
|
+
"color: gray;",
|
|
258
|
+
"color: default;",
|
|
259
|
+
...values,
|
|
260
|
+
];
|
|
261
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const logLevels = ["debug", "info", "warning", "error", "fatal"];
|
|
2
|
+
/**
|
|
3
|
+
* Parses a log level from a string.
|
|
4
|
+
*
|
|
5
|
+
* @param level The log level as a string. This is case-insensitive.
|
|
6
|
+
* @returns The log level.
|
|
7
|
+
* @throws {TypeError} If the log level is invalid.
|
|
8
|
+
*/
|
|
9
|
+
export function parseLogLevel(level) {
|
|
10
|
+
level = level.toLowerCase();
|
|
11
|
+
switch (level) {
|
|
12
|
+
case "debug":
|
|
13
|
+
case "info":
|
|
14
|
+
case "warning":
|
|
15
|
+
case "error":
|
|
16
|
+
case "fatal":
|
|
17
|
+
return level;
|
|
18
|
+
default:
|
|
19
|
+
throw new TypeError(`Invalid log level: ${level}.`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Checks if a string is a valid log level. This function can be used as
|
|
24
|
+
* as a type guard to narrow the type of a string to a {@link LogLevel}.
|
|
25
|
+
*
|
|
26
|
+
* @param level The log level as a string. This is case-sensitive.
|
|
27
|
+
* @returns `true` if the string is a valid log level.
|
|
28
|
+
*/
|
|
29
|
+
export function isLogLevel(level) {
|
|
30
|
+
switch (level) {
|
|
31
|
+
case "debug":
|
|
32
|
+
case "info":
|
|
33
|
+
case "warning":
|
|
34
|
+
case "error":
|
|
35
|
+
case "fatal":
|
|
36
|
+
return true;
|
|
37
|
+
default:
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Compares two log levels.
|
|
43
|
+
* @param a The first log level.
|
|
44
|
+
* @param b The second log level.
|
|
45
|
+
* @returns A negative number if `a` is less than `b`, a positive number if `a`
|
|
46
|
+
* is greater than `b`, or zero if they are equal.
|
|
47
|
+
* @since 0.8.0
|
|
48
|
+
*/
|
|
49
|
+
export function compareLogLevel(a, b) {
|
|
50
|
+
const aIndex = logLevels.indexOf(a);
|
|
51
|
+
if (aIndex < 0) {
|
|
52
|
+
throw new TypeError(`Invalid log level: ${JSON.stringify(a)}.`);
|
|
53
|
+
}
|
|
54
|
+
const bIndex = logLevels.indexOf(b);
|
|
55
|
+
if (bIndex < 0) {
|
|
56
|
+
throw new TypeError(`Invalid log level: ${JSON.stringify(b)}.`);
|
|
57
|
+
}
|
|
58
|
+
return aIndex - bIndex;
|
|
59
|
+
}
|