@holz/console-backend 0.7.0 → 0.8.0-rc.2
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/dist/holz-console-backend.cjs +1 -1
- package/dist/holz-console-backend.d.ts +5 -2
- package/dist/holz-console-backend.js +31 -12
- package/package.json +6 -5
- package/src/__tests__/__snapshots__/console-backend.test.ts.snap +28 -0
- package/src/__tests__/console-backend.test.ts +3 -0
- package/src/console-backend.ts +23 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r={fatal:60,error:50,warn:40,info:30,debug:20,trace:10},c=1e3,i=60*c,u=60*i,f=24*u,g=(a,s=a)=>{const t=a.getTime()-s.getTime(),e=Math.abs(t),n=t<0?"":"+";return e>=f?`${n}${Math.round(t/f)}d`:e>=u?`${n}${Math.round(t/u)}h`:e>=i?`${n}${Math.round(t/i)}m`:e>=c?`${n}${Math.round(t/c)}s`:`${n}${t}ms`},$=(a={})=>{const s=a.console??console;let t;return e=>{const n=new Date(e.timestamp),l=[{include:!0,format:"%s",values:[e.message]},{include:Object.keys(e.context).length>0,format:"%o",values:[e.context]},{include:!0,format:"%c%s",values:["color: gray",g(n,t)]},{include:e.origin.length>0,format:"%c%s",values:["color: rgba(128, 128, 128, 0.6); font-style: italic",e.origin.join(":")]}].filter(o=>o.include),m=l.map(o=>o.format).join(" "),d=l.flatMap(o=>o.values);s[h[e.level]](m,...d),t=n}},h={[r.trace]:"trace",[r.debug]:"debug",[r.info]:"info",[r.warn]:"warn",[r.error]:"error",[r.fatal]:"error"};exports.createConsoleBackend=$;
|
|
@@ -4,13 +4,16 @@ import { LogProcessor } from '@holz/core';
|
|
|
4
4
|
* A backend that pretty-prints logs to a browser console, or any
|
|
5
5
|
* remote-attached console.
|
|
6
6
|
*/
|
|
7
|
-
export declare
|
|
7
|
+
export declare const createConsoleBackend: (options?: Options) => LogProcessor;
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* A subset of the Console interface. Must support printf-style interpolation.
|
|
11
11
|
* @see https://console.spec.whatwg.org/#formatting-specifiers
|
|
12
|
+
*
|
|
13
|
+
* Note that `fatal` has no corresponding equivalent. It will be downgraded to
|
|
14
|
+
* `error` when printed.
|
|
12
15
|
*/
|
|
13
|
-
declare type MinimalConsole = Pick<Console, 'debug' | 'info' | 'warn' | 'error'>;
|
|
16
|
+
declare type MinimalConsole = Pick<Console, 'trace' | 'debug' | 'info' | 'warn' | 'error'>;
|
|
14
17
|
|
|
15
18
|
declare interface Options {
|
|
16
19
|
console?: MinimalConsole;
|
|
@@ -1,12 +1,24 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
const r = {
|
|
2
|
+
/** A critical failure happened and the program must exit. */
|
|
3
|
+
fatal: 60,
|
|
4
|
+
/** Something failed, but we can keep going. */
|
|
5
|
+
error: 50,
|
|
6
|
+
/** Cause for concern, but we can keep going. */
|
|
7
|
+
warn: 40,
|
|
8
|
+
/** High-level progress updates. */
|
|
9
|
+
info: 30,
|
|
10
|
+
/** Verbose update about events or control flow (usually hidden). */
|
|
11
|
+
debug: 20,
|
|
12
|
+
/** Extremely detailed progress updates (usually hidden). */
|
|
13
|
+
trace: 10
|
|
14
|
+
}, c = 1e3, i = 60 * c, u = 60 * i, f = 24 * u, $ = (a, s = a) => {
|
|
15
|
+
const e = a.getTime() - s.getTime(), t = Math.abs(e), n = e < 0 ? "" : "+";
|
|
16
|
+
return t >= f ? `${n}${Math.round(e / f)}d` : t >= u ? `${n}${Math.round(e / u)}h` : t >= i ? `${n}${Math.round(e / i)}m` : t >= c ? `${n}${Math.round(e / c)}s` : `${n}${e}ms`;
|
|
17
|
+
}, g = (a = {}) => {
|
|
18
|
+
const s = a.console ?? console;
|
|
7
19
|
let e;
|
|
8
20
|
return (t) => {
|
|
9
|
-
const n =
|
|
21
|
+
const n = new Date(t.timestamp), l = [
|
|
10
22
|
{
|
|
11
23
|
include: !0,
|
|
12
24
|
format: "%s",
|
|
@@ -21,7 +33,7 @@ function l(s = {}) {
|
|
|
21
33
|
{
|
|
22
34
|
include: !0,
|
|
23
35
|
format: "%c%s",
|
|
24
|
-
values: ["color: gray",
|
|
36
|
+
values: ["color: gray", $(n, e)]
|
|
25
37
|
},
|
|
26
38
|
{
|
|
27
39
|
include: t.origin.length > 0,
|
|
@@ -31,10 +43,17 @@ function l(s = {}) {
|
|
|
31
43
|
t.origin.join(":")
|
|
32
44
|
]
|
|
33
45
|
}
|
|
34
|
-
].filter((o) => o.include),
|
|
35
|
-
|
|
46
|
+
].filter((o) => o.include), m = l.map((o) => o.format).join(" "), d = l.flatMap((o) => o.values);
|
|
47
|
+
s[h[t.level]](m, ...d), e = n;
|
|
36
48
|
};
|
|
37
|
-
}
|
|
49
|
+
}, h = {
|
|
50
|
+
[r.trace]: "trace",
|
|
51
|
+
[r.debug]: "debug",
|
|
52
|
+
[r.info]: "info",
|
|
53
|
+
[r.warn]: "warn",
|
|
54
|
+
[r.error]: "error",
|
|
55
|
+
[r.fatal]: "error"
|
|
56
|
+
};
|
|
38
57
|
export {
|
|
39
|
-
|
|
58
|
+
g as createConsoleBackend
|
|
40
59
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holz/console-backend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0-rc.2",
|
|
4
4
|
"description": "A console backend for Holz",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -37,16 +37,17 @@
|
|
|
37
37
|
"test:types": "tsc"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@holz/core": "0.
|
|
40
|
+
"@holz/core": "^0.8.0-rc.2"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@holz/core": "^0.
|
|
43
|
+
"@holz/core": "^0.8.0-rc.2",
|
|
44
44
|
"@types/node": "^22.0.0",
|
|
45
45
|
"@vitest/coverage-v8": "^3.0.8",
|
|
46
|
-
"typescript": "^5.
|
|
46
|
+
"typescript": "^5.8.2",
|
|
47
47
|
"vite": "^6.0.0",
|
|
48
48
|
"vite-plugin-dts": "^4.5.3",
|
|
49
49
|
"vite-tsconfig-paths": "^5.1.4",
|
|
50
50
|
"vitest": "^3.0.8"
|
|
51
|
-
}
|
|
51
|
+
},
|
|
52
|
+
"stableVersion": "0.7.0"
|
|
52
53
|
}
|
|
@@ -28,6 +28,20 @@ exports[`Console backend > avoids changing error messages 1`] = `
|
|
|
28
28
|
]
|
|
29
29
|
`;
|
|
30
30
|
|
|
31
|
+
exports[`Console backend > avoids changing fatal messages 1`] = `
|
|
32
|
+
[
|
|
33
|
+
"%s %o %c%s %c%s",
|
|
34
|
+
"a fatal error",
|
|
35
|
+
{
|
|
36
|
+
"id": 1234,
|
|
37
|
+
},
|
|
38
|
+
"color: gray",
|
|
39
|
+
"+0ms",
|
|
40
|
+
"color: rgba(128, 128, 128, 0.6); font-style: italic",
|
|
41
|
+
"ns-1:ns-2",
|
|
42
|
+
]
|
|
43
|
+
`;
|
|
44
|
+
|
|
31
45
|
exports[`Console backend > avoids changing info messages 1`] = `
|
|
32
46
|
[
|
|
33
47
|
"%s %o %c%s %c%s",
|
|
@@ -42,6 +56,20 @@ exports[`Console backend > avoids changing info messages 1`] = `
|
|
|
42
56
|
]
|
|
43
57
|
`;
|
|
44
58
|
|
|
59
|
+
exports[`Console backend > avoids changing trace messages 1`] = `
|
|
60
|
+
[
|
|
61
|
+
"%s %o %c%s %c%s",
|
|
62
|
+
"noise",
|
|
63
|
+
{
|
|
64
|
+
"id": 1234,
|
|
65
|
+
},
|
|
66
|
+
"color: gray",
|
|
67
|
+
"+0ms",
|
|
68
|
+
"color: rgba(128, 128, 128, 0.6); font-style: italic",
|
|
69
|
+
"ns-1:ns-2",
|
|
70
|
+
]
|
|
71
|
+
`;
|
|
72
|
+
|
|
45
73
|
exports[`Console backend > avoids changing warn messages 1`] = `
|
|
46
74
|
[
|
|
47
75
|
"%s %o %c%s %c%s",
|
|
@@ -8,6 +8,7 @@ class MockConsole implements MinimalConsole {
|
|
|
8
8
|
this.print(format(level, ...strings));
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
+
trace = vi.fn(this.fmt);
|
|
11
12
|
debug = vi.fn(this.fmt);
|
|
12
13
|
info = vi.fn(this.fmt);
|
|
13
14
|
warn = vi.fn(this.fmt);
|
|
@@ -97,6 +98,7 @@ describe('Console backend', () => {
|
|
|
97
98
|
// Snapshot the exact output of each log level. This mostly prevents
|
|
98
99
|
// regressions while doing innocent refactors.
|
|
99
100
|
it.each([
|
|
101
|
+
['trace' as const, 'noise', ['ns-1', 'ns-2'], 'trace' as const],
|
|
100
102
|
['debug' as const, 'just spam', ['ns-1', 'ns-2'], 'debug' as const],
|
|
101
103
|
['info' as const, 'a little info', ['ns-1', 'ns-2'], 'info' as const],
|
|
102
104
|
['warn' as const, 'a warning', ['ns-1', 'ns-2'], 'warn' as const],
|
|
@@ -106,6 +108,7 @@ describe('Console backend', () => {
|
|
|
106
108
|
['ns-1', 'ns-2'],
|
|
107
109
|
'error' as const,
|
|
108
110
|
],
|
|
111
|
+
['fatal' as const, 'a fatal error', ['ns-1', 'ns-2'], 'error' as const],
|
|
109
112
|
])('avoids changing %s messages', (method, message, namespace, pipe) => {
|
|
110
113
|
const output = new MockConsole();
|
|
111
114
|
const backend = createConsoleBackend({ console: output });
|
package/src/console-backend.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { level, type LogLevel, type Log, type LogProcessor } from '@holz/core';
|
|
2
2
|
import { timeDelta } from './time-delta';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A backend that pretty-prints logs to a browser console, or any
|
|
6
6
|
* remote-attached console.
|
|
7
7
|
*/
|
|
8
|
-
export
|
|
8
|
+
export const createConsoleBackend = (options: Options = {}): LogProcessor => {
|
|
9
9
|
const output = options.console ?? console;
|
|
10
10
|
let lastTimestamp: Date;
|
|
11
11
|
|
|
12
12
|
return (log: Log) => {
|
|
13
|
-
const
|
|
13
|
+
const time = new Date(log.timestamp);
|
|
14
14
|
|
|
15
15
|
const segments = [
|
|
16
16
|
{
|
|
@@ -26,7 +26,7 @@ export function createConsoleBackend(options: Options = {}): LogProcessor {
|
|
|
26
26
|
{
|
|
27
27
|
include: true,
|
|
28
28
|
format: '%c%s',
|
|
29
|
-
values: ['color: gray', timeDelta(
|
|
29
|
+
values: ['color: gray', timeDelta(time, lastTimestamp)],
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
include: log.origin.length > 0,
|
|
@@ -42,12 +42,21 @@ export function createConsoleBackend(options: Options = {}): LogProcessor {
|
|
|
42
42
|
const values = segments.flatMap<unknown>((segment) => segment.values);
|
|
43
43
|
|
|
44
44
|
// Browsers have UIs for filtering by log level. Leverage that.
|
|
45
|
-
output[log.level](format, ...values);
|
|
45
|
+
output[sink[log.level]](format, ...values);
|
|
46
46
|
|
|
47
47
|
// Track the time spent between logs.
|
|
48
|
-
lastTimestamp =
|
|
48
|
+
lastTimestamp = time;
|
|
49
49
|
};
|
|
50
|
-
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const sink: Record<LogLevel, keyof MinimalConsole> = {
|
|
53
|
+
[level.trace]: 'trace',
|
|
54
|
+
[level.debug]: 'debug',
|
|
55
|
+
[level.info]: 'info',
|
|
56
|
+
[level.warn]: 'warn',
|
|
57
|
+
[level.error]: 'error',
|
|
58
|
+
[level.fatal]: 'error',
|
|
59
|
+
};
|
|
51
60
|
|
|
52
61
|
interface Options {
|
|
53
62
|
console?: MinimalConsole;
|
|
@@ -56,5 +65,11 @@ interface Options {
|
|
|
56
65
|
/**
|
|
57
66
|
* A subset of the Console interface. Must support printf-style interpolation.
|
|
58
67
|
* @see https://console.spec.whatwg.org/#formatting-specifiers
|
|
68
|
+
*
|
|
69
|
+
* Note that `fatal` has no corresponding equivalent. It will be downgraded to
|
|
70
|
+
* `error` when printed.
|
|
59
71
|
*/
|
|
60
|
-
export type MinimalConsole = Pick<
|
|
72
|
+
export type MinimalConsole = Pick<
|
|
73
|
+
Console,
|
|
74
|
+
'trace' | 'debug' | 'info' | 'warn' | 'error'
|
|
75
|
+
>;
|