@mmutils/logger 0.0.0-stage → 0.1.0

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.
Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +901 -2
  3. package/dist/cjs/index.cjs +72 -0
  4. package/dist/cjs/index.cjs.map +1 -0
  5. package/dist/cjs/levels.cjs +82 -0
  6. package/dist/cjs/levels.cjs.map +1 -0
  7. package/dist/cjs/logger.cjs +576 -0
  8. package/dist/cjs/logger.cjs.map +1 -0
  9. package/dist/cjs/outputs.cjs +24 -0
  10. package/dist/cjs/outputs.cjs.map +1 -0
  11. package/dist/cjs/plugins/columns.cjs +782 -0
  12. package/dist/cjs/plugins/columns.cjs.map +1 -0
  13. package/dist/cjs/plugins/graph.cjs +578 -0
  14. package/dist/cjs/plugins/graph.cjs.map +1 -0
  15. package/dist/cjs/plugins/json.cjs +644 -0
  16. package/dist/cjs/plugins/json.cjs.map +1 -0
  17. package/dist/cjs/plugins/message.cjs +108 -0
  18. package/dist/cjs/plugins/message.cjs.map +1 -0
  19. package/dist/cjs/plugins/shared.cjs +194 -0
  20. package/dist/cjs/plugins/shared.cjs.map +1 -0
  21. package/dist/cjs/time.cjs +234 -0
  22. package/dist/cjs/time.cjs.map +1 -0
  23. package/dist/cjs/utils/text.cjs +646 -0
  24. package/dist/cjs/utils/text.cjs.map +1 -0
  25. package/dist/esm/index.js +11 -0
  26. package/dist/esm/index.js.map +1 -0
  27. package/dist/esm/levels.js +72 -0
  28. package/dist/esm/levels.js.map +1 -0
  29. package/dist/esm/logger.js +572 -0
  30. package/dist/esm/logger.js.map +1 -0
  31. package/dist/esm/outputs.js +21 -0
  32. package/dist/esm/outputs.js.map +1 -0
  33. package/dist/esm/plugins/columns.js +778 -0
  34. package/dist/esm/plugins/columns.js.map +1 -0
  35. package/dist/esm/plugins/graph.js +572 -0
  36. package/dist/esm/plugins/graph.js.map +1 -0
  37. package/dist/esm/plugins/json.js +641 -0
  38. package/dist/esm/plugins/json.js.map +1 -0
  39. package/dist/esm/plugins/message.js +105 -0
  40. package/dist/esm/plugins/message.js.map +1 -0
  41. package/dist/esm/plugins/shared.js +187 -0
  42. package/dist/esm/plugins/shared.js.map +1 -0
  43. package/dist/esm/time.js +231 -0
  44. package/dist/esm/time.js.map +1 -0
  45. package/dist/esm/utils/text.js +621 -0
  46. package/dist/esm/utils/text.js.map +1 -0
  47. package/dist/types/index.d.ts +11 -0
  48. package/dist/types/levels.d.ts +50 -0
  49. package/dist/types/logger.d.ts +245 -0
  50. package/dist/types/outputs.d.ts +12 -0
  51. package/dist/types/plugins/columns.d.ts +151 -0
  52. package/dist/types/plugins/graph.d.ts +243 -0
  53. package/dist/types/plugins/json.d.ts +169 -0
  54. package/dist/types/plugins/message.d.ts +181 -0
  55. package/dist/types/plugins/shared.d.ts +74 -0
  56. package/dist/types/time.d.ts +48 -0
  57. package/dist/types/types.d.ts +176 -0
  58. package/dist/types/utils/text.d.ts +231 -0
  59. package/package.json +85 -4
@@ -0,0 +1,243 @@
1
+ import { type TimeUnit } from '@mmutils/time';
2
+ import type { BakedStyles, LoggerPlugin, StyleSheet } from '../types.js';
3
+ import { type Aggregate, type OutputLimits, type Sanitizer } from '../utils/text.js';
4
+ import { type SanitizeOptions, type HeaderOptions } from './shared.js';
5
+ /**
6
+ * Labels of the horizontal axis, displayed under the bars. Strings are shown
7
+ * as given. Numbers are shown as plain numbers or, when `unit` is set, as
8
+ * time formatted with `formatHighResTime` from `@mmutils/time`.
9
+ *
10
+ * ```ts
11
+ * { start: 'Mon', end: 'Fri' } // Mon … Fri
12
+ * { start: 5, end: 10 } // 5 … 10
13
+ * { start: 500, end: 1_000_500, unit: 'ns' } // 500ns … 1ms 500ns
14
+ * { start: 0, end: 2025, unit: 'ms' } // 0ms … 2s 25ms
15
+ * ```
16
+ */
17
+ export interface GraphAxis {
18
+ /** Left label. */
19
+ readonly start?: string | number;
20
+ /** Right label. */
21
+ readonly end?: string | number;
22
+ /** Unit of numeric labels. When set, numbers are formatted as time. */
23
+ readonly unit?: TimeUnit;
24
+ /**
25
+ * Time precision: a unit or a number of units below the largest unit of the
26
+ * value. Default: `2`.
27
+ */
28
+ readonly capTo?: TimeUnit | number;
29
+ }
30
+ /**
31
+ * Formats an axis label. A zero time label takes the smallest unit of the
32
+ * other label, so both show the same precision: `0` next to `2s 25ms`
33
+ * reads `0ms`.
34
+ *
35
+ * @param label Label to format.
36
+ * @param axis Axis settings.
37
+ * @param other The opposite label.
38
+ */
39
+ export declare const formatAxisLabel: (label: string | number | undefined, { unit, capTo }: GraphAxis, other?: string | number) => string;
40
+ /**
41
+ * Where the bars of a graph start: a value, or the bottom (`'min'`) or the
42
+ * top (`'max'`) of the graph.
43
+ */
44
+ export type GraphBaseline = number | 'min' | 'max';
45
+ export interface GraphSettings {
46
+ /**
47
+ * Number of bar columns: the resolution values are scaled to, like `rows`
48
+ * for the height. The frame adds 2 characters, so the graph is `cols + 2`
49
+ * terminal columns wide; use `width` to set that instead. Default: `30`.
50
+ */
51
+ readonly cols?: number;
52
+ /**
53
+ * Total width in terminal columns, frame included: `width: 64` draws 62
54
+ * bars and every row is exactly 64 characters wide, e.g. to fit a layout
55
+ * column. Replaces `cols`: setting both on the plugin throws; per graph,
56
+ * `width` wins. At least `3`.
57
+ */
58
+ readonly width?: number;
59
+ /** Graph height in rows. Default: `3`. */
60
+ readonly rows?: number;
61
+ /** Title in the top row. Default: `''`. */
62
+ readonly title?: string;
63
+ /**
64
+ * Top of the graph. Values above it draw full bars, or nothing when the
65
+ * baseline is the top. Not lower than a numeric `baseline`. Default: the
66
+ * maximum of the original values, raised to a numeric `baseline`.
67
+ */
68
+ readonly max?: number;
69
+ /**
70
+ * Bottom of the graph. Values below it draw full bars, or nothing when the
71
+ * baseline is the bottom. Not higher than a numeric `baseline`. Default:
72
+ * the minimum of the original values, lowered to a numeric `baseline`.
73
+ */
74
+ readonly min?: number;
75
+ /**
76
+ * Where the bars start: bars grow from it up to values above it and down
77
+ * to values below it, in the same color. Default: `0`, moved inside `min`
78
+ * and `max` when they leave it out (`min: 480` alone starts at 480).
79
+ *
80
+ * - A number: the range always holds it, so with values from 80 to 85 the
81
+ * bars grow from 0. Inside the range it splits the graph.
82
+ * - `'min'`: the bottom of the graph; bars only grow up. Zooms in on
83
+ * values far from zero; the smallest value draws no bar.
84
+ * - `'max'`: the top of the graph; bars only grow down.
85
+ *
86
+ * A split graph places the baseline in proportion to the range, on one
87
+ * scale for both sides, so equal distances draw equal bars. A side gets
88
+ * rows only if its longest bar draws at least an eighth of a row.
89
+ */
90
+ readonly baseline?: GraphBaseline;
91
+ /**
92
+ * How values sharing a column are combined when scaled to `cols`:
93
+ * `'average'` (smooth trend), `'max'` (keeps peaks, e.g. latency spikes) or
94
+ * `'min'` (keeps dips). Statistics always use the original values.
95
+ * Default: `'average'`.
96
+ */
97
+ readonly aggregate?: Aggregate;
98
+ /** Unit appended to displayed values, e.g. `'%'`. Default: `''`. */
99
+ readonly unit?: string;
100
+ /** Displayed values precision. Default: `2`. */
101
+ readonly precision?: number;
102
+ /** Show the average value row. Default: `true`. */
103
+ readonly showAverage?: boolean;
104
+ /** Show the minimum value row. Default: `true`. */
105
+ readonly showMin?: boolean;
106
+ /** Show the maximum value row. Default: `true`. */
107
+ readonly showMax?: boolean;
108
+ /** Horizontal axis labels row under the bars. Default: none. */
109
+ readonly axis?: GraphAxis;
110
+ }
111
+ /**
112
+ * Data accepted by the graph kind: plain values or values with settings that
113
+ * override the plugin's settings for a single log.
114
+ */
115
+ export type GraphData = readonly number[] | GraphDataWithSettings;
116
+ export interface GraphDataWithSettings extends GraphSettings {
117
+ readonly values: readonly number[];
118
+ }
119
+ export interface GraphLimits extends OutputLimits {
120
+ /** Maximum `cols`. Default: `500`. */
121
+ readonly cols?: number;
122
+ /** Maximum `rows`. Default: `50`. */
123
+ readonly rows?: number;
124
+ /** Maximum `precision`, at most `100`. Default: `20`. */
125
+ readonly precision?: number;
126
+ }
127
+ export declare const DEFAULT_GRAPH_LIMITS: {
128
+ readonly cols: 500;
129
+ readonly rows: 50;
130
+ readonly precision: 20;
131
+ };
132
+ export interface GraphPluginOptions extends HeaderOptions, SanitizeOptions, GraphSettings {
133
+ /**
134
+ * Upper limits of the size settings. Kept out of the per-log settings, so
135
+ * logged data can't raise them. Default: `DEFAULT_GRAPH_LIMITS`.
136
+ */
137
+ readonly limits?: GraphLimits;
138
+ /** Kind rendered by this plugin. Default: `'graph'`. */
139
+ readonly kind?: string;
140
+ /** Styles merged over the default text styles. */
141
+ readonly styles?: StyleSheet;
142
+ /** String destination. Default: `console.log`. */
143
+ readonly write?: (text: string) => void;
144
+ }
145
+ /**
146
+ * Logs a graph of values.
147
+ *
148
+ * @param values Values to plot.
149
+ * @param settings Settings for this graph only.
150
+ */
151
+ export type GraphMethod = (values: readonly number[], settings?: GraphSettings) => void;
152
+ /**
153
+ * Graph method per log type: `infoGraph`, `errorGraph`, etc.
154
+ */
155
+ export interface GraphMethods {
156
+ /**
157
+ * Logs a bar graph of values with fatal level.
158
+ *
159
+ * @param values Numeric values to plot. Scaled to the graph's columns.
160
+ * @param settings Settings for this graph only, e.g. `{ title: 'CPU' }`.
161
+ */
162
+ fatalGraph(values: readonly number[], settings?: GraphSettings): void;
163
+ /**
164
+ * Logs a bar graph of values with error level.
165
+ *
166
+ * @param values Numeric values to plot. Scaled to the graph's columns.
167
+ * @param settings Settings for this graph only, e.g. `{ title: 'CPU' }`.
168
+ */
169
+ errorGraph(values: readonly number[], settings?: GraphSettings): void;
170
+ /**
171
+ * Logs a bar graph of values with warning level.
172
+ *
173
+ * @param values Numeric values to plot. Scaled to the graph's columns.
174
+ * @param settings Settings for this graph only, e.g. `{ title: 'CPU' }`.
175
+ */
176
+ warningGraph(values: readonly number[], settings?: GraphSettings): void;
177
+ /**
178
+ * Logs a bar graph of values with info level.
179
+ *
180
+ * @param values Numeric values to plot. Scaled to the graph's columns.
181
+ * @param settings Settings for this graph only, e.g. `{ title: 'CPU' }`.
182
+ */
183
+ infoGraph(values: readonly number[], settings?: GraphSettings): void;
184
+ /**
185
+ * Logs a bar graph of values with debug level.
186
+ *
187
+ * @param values Numeric values to plot. Scaled to the graph's columns.
188
+ * @param settings Settings for this graph only, e.g. `{ title: 'CPU' }`.
189
+ */
190
+ debugGraph(values: readonly number[], settings?: GraphSettings): void;
191
+ /**
192
+ * Logs a bar graph of values with trace level.
193
+ *
194
+ * @param values Numeric values to plot. Scaled to the graph's columns.
195
+ * @param settings Settings for this graph only, e.g. `{ title: 'CPU' }`.
196
+ */
197
+ traceGraph(values: readonly number[], settings?: GraphSettings): void;
198
+ /**
199
+ * Logs a bar graph of values with verbose level.
200
+ *
201
+ * @param values Numeric values to plot. Scaled to the graph's columns.
202
+ * @param settings Settings for this graph only, e.g. `{ title: 'CPU' }`.
203
+ */
204
+ verboseGraph(values: readonly number[], settings?: GraphSettings): void;
205
+ }
206
+ type ResolvedGraphSettings = Required<Omit<GraphSettings, 'max' | 'min' | 'axis' | 'width' | 'baseline'>> & Pick<GraphSettings, 'max' | 'min' | 'axis' | 'baseline'>;
207
+ /**
208
+ * Converts values to rows of bar symbols growing up from `min`, top row
209
+ * first.
210
+ *
211
+ * @param max Top of the graph: higher values draw full bars.
212
+ * @param min Bottom of the graph. Default: `0`.
213
+ */
214
+ export declare const valuesToBars: (values: readonly number[], rows: number, max: number, min?: number) => string[];
215
+ /**
216
+ * Renders a framed graph with an optional axis row and value statistics:
217
+ * title, bars, frame and values in `textHighlight`, legend labels in
218
+ * `textNormal`, axis labels and units in `textDim`. When the baseline splits
219
+ * the graph, a `baseline` row follows the average.
220
+ *
221
+ * Average, min, max and the default top and bottom are computed from the
222
+ * original values, so peaks blunted by scaling are still reported. Bars are
223
+ * scaled to `cols` with `settings.aggregate`. The top value is shown on the
224
+ * title row, the bottom value on the average row.
225
+ *
226
+ * Title, unit and axis labels are sanitized as single line `label`s and
227
+ * measured in terminal columns with `textWidth` (wide characters take two,
228
+ * as in columns). Default: `'safe'` (see `Sanitize`).
229
+ */
230
+ export declare const renderGraph: (values: readonly number[], settings: ResolvedGraphSettings, { textNormal, textDim, textHighlight, reset, }?: BakedStyles, { label }?: Sanitizer) => string;
231
+ /**
232
+ * Renders logs of a given kind as bar graphs. Adds a graph method per log
233
+ * type to the logger: `infoGraph`, `errorGraph`, etc.
234
+ *
235
+ * ```
236
+ * 2026/03/16 15:35:00 [i] info
237
+ * CPU 82.00 %
238
+ * │▁▁▁▂▃▃▃▄▄▄▆▆▆▇██▇▆▆▆▄▄▄▃▃▃▂▁▁▁│
239
+ * average: 41.33 % 0.00 %
240
+ * ```
241
+ */
242
+ export declare const graphPlugin: (options?: GraphPluginOptions) => LoggerPlugin<GraphMethods>;
243
+ export {};
@@ -0,0 +1,169 @@
1
+ import type { LoggerPlugin } from '../types.js';
2
+ import { type OutputLimits } from '../utils/text.js';
3
+ type Limits = Required<OutputLimits>;
4
+ /**
5
+ * Time of a JSON line, in its `time` property, from the logger's clock:
6
+ * - `'iso'`: ISO 8601 in UTC, a string: `"2026-03-16T15:35:00.000Z"`, with
7
+ * 9 fraction digits with the `'precise'` clock;
8
+ * - `'epoch'`: epoch milliseconds, a number: `1773675300000`; with the
9
+ * `'precise'` clock followed by `"ns"`, the nanoseconds within the
10
+ * millisecond;
11
+ * - `false`: no `time`.
12
+ */
13
+ export type JsonTime = 'epoch' | 'iso' | false;
14
+ export interface JsonPluginOptions {
15
+ /** Kind rendered by this plugin. Default: `'json'`. */
16
+ readonly kind?: string;
17
+ /**
18
+ * Make `kind` the logger's default kind, so all logs without an explicit
19
+ * kind are written as JSON lines. The last plugin used that sets the
20
+ * default wins. Use `jsonPlugin` instead of `messagePlugin`, not next to
21
+ * it: both render the whole log. Default: `true`.
22
+ */
23
+ readonly setAsDefault?: boolean;
24
+ /**
25
+ * Format of the `time` property, from the logger's `clock`. Lines have no
26
+ * time when the logger's `timestamp` is `false`. Default: `'iso'`.
27
+ */
28
+ readonly time?: JsonTime;
29
+ /**
30
+ * Output size limits: elements and keys per object, characters per string
31
+ * and per nested JSON value. `Infinity` turns a limit off. Default:
32
+ * `DEFAULT_OUTPUT_LIMITS` (`{ items: 100, stringLength: 10_000 }`).
33
+ */
34
+ readonly limits?: OutputLimits;
35
+ /**
36
+ * Also escape DEL and C1 control characters (`U+007F`-`U+009F`) as
37
+ * `\u00XX`. `JSON.stringify` escapes C0 controls (including ESC and
38
+ * newlines) but writes these raw; some terminals act on C1 controls when
39
+ * the lines are shown raw (`cat`, `tail -f`). The parsed JSON is the same.
40
+ * Costs about 1 ns per character. Default: `false`.
41
+ */
42
+ readonly escapeControls?: boolean;
43
+ /**
44
+ * Write the log's `kind` after `type`, e.g. `"kind":"audit"`. Turn it on
45
+ * when several JSON kinds share a destination (all logs to stdout in a
46
+ * container), so readers can tell them apart. Default: `false` (one
47
+ * destination per kind makes it redundant).
48
+ */
49
+ readonly writeKind?: boolean;
50
+ /** Line destination, called once per log. Default: `console.log`. */
51
+ readonly write?: (line: string) => void;
52
+ }
53
+ /**
54
+ * Serializes logged data to JSON text. Never throws, and always returns
55
+ * valid JSON (or `undefined`, like `JSON.stringify`, for `undefined`):
56
+ * - ordinary data is one native `JSON.stringify`;
57
+ * - errors, also as property values and from other realms:
58
+ * `{"name","message","stack",...own properties,"cause"}`, causes up to 5
59
+ * deep;
60
+ * - buffers and typed arrays: a one-line description (`describeBinary`);
61
+ * - bigints: JSON numbers with every digit; functions and symbols:
62
+ * `"[Function: name]"`, `"Symbol(x)"`, never source code;
63
+ * - maps, sets and regular expressions: a description (`describeObject`);
64
+ * - strings longer than `stringLength`: cut, with `… N more characters`;
65
+ * - arrays and objects longer than `items` (the data and its direct
66
+ * properties): the first `items` and `"… N more items"`;
67
+ * - arrays and objects whose JSON is longer than `stringLength`: cut
68
+ * structurally, keeping their type (`cutJson`);
69
+ * - throwing getters and revoked proxies: placeholder strings; circular
70
+ * references: `"[Circular]"`; the rest of the data still renders and
71
+ * keeps its type.
72
+ *
73
+ * Errors, binary data, bigints, functions and long arrays are found one
74
+ * level deep only: in the data and in its direct properties (`{ err }`).
75
+ * This is for performance: ordinary data is one native `JSON.stringify`,
76
+ * and a walker for every object would slow down all logs. Deeper ones get
77
+ * native JSON, so a deeper error keeps only its own enumerable properties
78
+ * (`{ request: { err } }` loses message and stack).
79
+ *
80
+ * @param limits Output limits. Default: `DEFAULT_OUTPUT_LIMITS`.
81
+ */
82
+ export declare const renderJsonData: (data: unknown, limits?: Limits) => string | undefined;
83
+ /**
84
+ * Log methods re-declared by `jsonPlugin` when it becomes the default kind:
85
+ * any data, written as one JSON line.
86
+ */
87
+ export interface JsonMethods {
88
+ /**
89
+ * Logs a fatal error that leads to an immediate halt of all operations, as
90
+ * a JSON line.
91
+ *
92
+ * @param data Any value, written as the line's `data`. Errors keep their
93
+ * name, message, stack, properties and cause.
94
+ * @param kind Log kind. Default: `'json'`.
95
+ */
96
+ fatal(data: unknown, kind?: string): void;
97
+ /**
98
+ * Logs an error that might lead to a halt of the current operation, as a
99
+ * JSON line.
100
+ *
101
+ * @param data Any value, written as the line's `data`. Errors keep their
102
+ * name, message, stack, properties and cause.
103
+ * @param kind Log kind. Default: `'json'`.
104
+ */
105
+ error(data: unknown, kind?: string): void;
106
+ /**
107
+ * Logs a warning about something that might produce an unexpected result
108
+ * later in the execution, as a JSON line.
109
+ *
110
+ * @param data Any value, written as the line's `data`.
111
+ * @param kind Log kind. Default: `'json'`.
112
+ */
113
+ warning(data: unknown, kind?: string): void;
114
+ /**
115
+ * Logs an important milestone of the execution flow, relevant in
116
+ * production, as a JSON line.
117
+ *
118
+ * @param data Any value, written as the line's `data`.
119
+ * @param kind Log kind. Default: `'json'`.
120
+ */
121
+ info(data: unknown, kind?: string): void;
122
+ /**
123
+ * Logs information that helps to debug a problem, as a JSON line.
124
+ *
125
+ * @param data Any value, written as the line's `data`.
126
+ * @param kind Log kind. Default: `'json'`.
127
+ */
128
+ debug(data: unknown, kind?: string): void;
129
+ /**
130
+ * Logs an execution checkpoint, to narrow down the execution path, as a
131
+ * JSON line.
132
+ *
133
+ * @param data Any value, written as the line's `data`.
134
+ * @param kind Log kind. Default: `'json'`.
135
+ */
136
+ trace(data: unknown, kind?: string): void;
137
+ /**
138
+ * Logs information of importance during a close examination of the
139
+ * execution flow, as a JSON line.
140
+ *
141
+ * @param data Any value, written as the line's `data`.
142
+ * @param kind Log kind. Default: `'json'`.
143
+ */
144
+ verbose(data: unknown, kind?: string): void;
145
+ }
146
+ /**
147
+ * Methods typed by `jsonPlugin`: the re-declared log methods, unless the
148
+ * plugin does not become the default kind.
149
+ */
150
+ export type JsonPluginMethods<O extends JsonPluginOptions> = O extends {
151
+ readonly setAsDefault: false;
152
+ } ? object : JsonMethods;
153
+ /**
154
+ * Writes logs of a given kind as JSON lines (NDJSON) and, by default, makes
155
+ * that kind the logger's default, so `logger.info({ user: 'alice' })`
156
+ * writes:
157
+ *
158
+ * ```
159
+ * {"id":1,"time":"2026-03-16T15:35:00.000Z","type":"info","data":{"user":"alice"}}
160
+ * ```
161
+ *
162
+ * Logging never throws because of the data; see `renderJsonData`. Errors of
163
+ * `write` propagate.
164
+ *
165
+ * @throws RangeError if `time` or `limits` are invalid.
166
+ * @throws TypeError if `write` is not a function.
167
+ */
168
+ export declare const jsonPlugin: <const O extends JsonPluginOptions = JsonPluginOptions>(options?: O) => LoggerPlugin<JsonPluginMethods<O>>;
169
+ export {};
@@ -0,0 +1,181 @@
1
+ import type { BakedStyles, LoggerPlugin, StyleSheet } from '../types.js';
2
+ import { type OutputLimits, type Sanitizer } from '../utils/text.js';
3
+ import { type HeaderOptions, type SanitizeOptions } from './shared.js';
4
+ export interface MessagePluginOptions extends HeaderOptions, SanitizeOptions {
5
+ /**
6
+ * Output size limits: elements and keys per object, characters per string.
7
+ * `Infinity` turns a limit off. Default: `DEFAULT_OUTPUT_LIMITS`
8
+ * (`{ items: 100, stringLength: 10_000 }`).
9
+ */
10
+ readonly limits?: OutputLimits;
11
+ /** Kind rendered by this plugin. Default: `'message'`. */
12
+ readonly kind?: string;
13
+ /**
14
+ * Make `kind` the logger's default kind, so all logs without an explicit
15
+ * kind are rendered as messages. The last plugin used that sets the
16
+ * default wins. Use `messagePlugin` instead of `jsonPlugin`, not next to
17
+ * it: both render the whole log. Default: `true`.
18
+ */
19
+ readonly setAsDefault?: boolean;
20
+ /** Styles merged over the default text styles. */
21
+ readonly styles?: StyleSheet;
22
+ /** String destination. Default: `console.log`. */
23
+ readonly write?: (text: string) => void;
24
+ }
25
+ /**
26
+ * Renders message data with the text styles:
27
+ * - strings: `textHighlight`, on the header line;
28
+ * - errors: `name: message` in `textHighlight` and stack frames in `textDim`,
29
+ * below the header;
30
+ * - objects and arrays: one `key: value` per line below the header, keys in
31
+ * `textNormal` and JSON values in `textHighlight`; empty ones inline in
32
+ * `textDim`;
33
+ * - other values: `textNormal`, on the header line.
34
+ *
35
+ * Strings, symbols, functions and error messages are sanitized as `text`;
36
+ * keys, values and stack frames as `label`. Default: `'safe'` (see
37
+ * `Sanitize`).
38
+ *
39
+ * Never throws: data that can't be read (throwing getters, revoked proxies,
40
+ * broken errors) gives dim placeholders.
41
+ */
42
+ export declare const renderMessageData: (data: unknown, styles: BakedStyles, sanitizer?: Sanitizer, limits?: Required<OutputLimits>) => string;
43
+ /**
44
+ * Log methods re-declared by `messagePlugin` when it becomes the default kind:
45
+ * the data is a text message, rendered as a styled line.
46
+ */
47
+ export interface MessageMethods {
48
+ /**
49
+ * Logs a fatal error that leads to an immediate halt of all operations, as
50
+ * a styled text line.
51
+ *
52
+ * @param message Text to display.
53
+ * @param kind Log kind. Default: `'message'`.
54
+ */
55
+ fatal(message: string, kind?: string): void;
56
+ /**
57
+ * Logs a fatal error that leads to an immediate halt of all operations.
58
+ *
59
+ * @param data Object or array (each property on a new line) or error
60
+ * (message and stack on new lines).
61
+ * @param kind Log kind. Default: `'message'`.
62
+ */
63
+ fatal(data: object, kind?: string): void;
64
+ /**
65
+ * Logs an error that might lead to a halt of the current operation, as a
66
+ * styled text line.
67
+ *
68
+ * @param message Text to display.
69
+ * @param kind Log kind. Default: `'message'`.
70
+ */
71
+ error(message: string, kind?: string): void;
72
+ /**
73
+ * Logs an error that might lead to a halt of the current operation.
74
+ *
75
+ * @param data Object or array (each property on a new line) or error
76
+ * (message and stack on new lines).
77
+ * @param kind Log kind. Default: `'message'`.
78
+ */
79
+ error(data: object, kind?: string): void;
80
+ /**
81
+ * Logs a warning about something that might produce an unexpected result
82
+ * later in the execution, as a styled text line.
83
+ *
84
+ * @param message Text to display.
85
+ * @param kind Log kind. Default: `'message'`.
86
+ */
87
+ warning(message: string, kind?: string): void;
88
+ /**
89
+ * Logs a warning about something that might produce an unexpected result
90
+ * later in the execution.
91
+ *
92
+ * @param data Object or array (each property on a new line) or error
93
+ * (message and stack on new lines).
94
+ * @param kind Log kind. Default: `'message'`.
95
+ */
96
+ warning(data: object, kind?: string): void;
97
+ /**
98
+ * Logs an important milestone of the execution flow, relevant in
99
+ * production, as a styled text line.
100
+ *
101
+ * @param message Text to display.
102
+ * @param kind Log kind. Default: `'message'`.
103
+ */
104
+ info(message: string, kind?: string): void;
105
+ /**
106
+ * Logs an important milestone of the execution flow, relevant in
107
+ * production.
108
+ *
109
+ * @param data Object or array (each property on a new line) or error
110
+ * (message and stack on new lines).
111
+ * @param kind Log kind. Default: `'message'`.
112
+ */
113
+ info(data: object, kind?: string): void;
114
+ /**
115
+ * Logs information that helps to debug a problem, as a styled text line.
116
+ *
117
+ * @param message Text to display.
118
+ * @param kind Log kind. Default: `'message'`.
119
+ */
120
+ debug(message: string, kind?: string): void;
121
+ /**
122
+ * Logs information that helps to debug a problem.
123
+ *
124
+ * @param data Object or array (each property on a new line) or error
125
+ * (message and stack on new lines).
126
+ * @param kind Log kind. Default: `'message'`.
127
+ */
128
+ debug(data: object, kind?: string): void;
129
+ /**
130
+ * Logs an execution checkpoint, to narrow down the execution path, as a
131
+ * styled text line.
132
+ *
133
+ * @param message Text to display.
134
+ * @param kind Log kind. Default: `'message'`.
135
+ */
136
+ trace(message: string, kind?: string): void;
137
+ /**
138
+ * Logs an execution checkpoint, to narrow down the execution path.
139
+ *
140
+ * @param data Object or array (each property on a new line) or error
141
+ * (message and stack on new lines).
142
+ * @param kind Log kind. Default: `'message'`.
143
+ */
144
+ trace(data: object, kind?: string): void;
145
+ /**
146
+ * Logs information of importance during a close examination of the
147
+ * execution flow, as a styled text line.
148
+ *
149
+ * @param message Text to display.
150
+ * @param kind Log kind. Default: `'message'`.
151
+ */
152
+ verbose(message: string, kind?: string): void;
153
+ /**
154
+ * Logs information of importance during a close examination of the
155
+ * execution flow.
156
+ *
157
+ * @param data Object or array (each property on a new line) or error
158
+ * (message and stack on new lines).
159
+ * @param kind Log kind. Default: `'message'`.
160
+ */
161
+ verbose(data: object, kind?: string): void;
162
+ }
163
+ /**
164
+ * Methods typed by `messagePlugin`: the re-declared log methods, unless the
165
+ * plugin does not become the default kind.
166
+ */
167
+ export type MessagePluginMethods<O extends MessagePluginOptions> = O extends {
168
+ readonly setAsDefault: false;
169
+ } ? object : MessageMethods;
170
+ /**
171
+ * Renders logs of a given kind as styled text and, by default, makes that
172
+ * kind the logger's default, so `logger.info('Server started')` prints:
173
+ *
174
+ * ```
175
+ * 2026/03/16 15:35:00 [i] info Server started
176
+ * ```
177
+ *
178
+ * Objects and arrays print each property on a new line; errors print their
179
+ * message and stack on new lines. See `renderMessageData` for the styles.
180
+ */
181
+ export declare const messagePlugin: <const O extends MessagePluginOptions = MessagePluginOptions>(options?: O) => LoggerPlugin<MessagePluginMethods<O>>;
@@ -0,0 +1,74 @@
1
+ import type { BakedStyles, LogType, StyleSheet, TemplateMap } from '../types.js';
2
+ import { type Sanitize, type Sanitizer } from '../utils/text.js';
3
+ /**
4
+ * Default text styles shared by the bundled plugins. Plugins may override
5
+ * them by registering the same style names.
6
+ *
7
+ * - `textDim`: secondary information: id, timestamp, symbols, units and
8
+ * stack frames. Gray.
9
+ * - `textNormal`: the terminal's default text style: object keys, graph
10
+ * legend labels, other values.
11
+ * - `textHighlight`: text messages, error messages, object values; graph
12
+ * titles, bars, frames and values. The level's color, bold.
13
+ * - `textBadge`: log type badge, the level's color as background.
14
+ *
15
+ * Colors: red for fatal (its badge white on red), bright red for error,
16
+ * yellow for warning, blue for info, magenta for debug, cyan for trace and
17
+ * gray (bright black) for verbose. They are the terminal's 16 basic colors,
18
+ * so they follow its theme.
19
+ */
20
+ export declare const DEFAULT_TEXT_STYLES: StyleSheet;
21
+ /**
22
+ * Wraps text in a style and a reset. Empty text or an empty style produce no
23
+ * escape codes.
24
+ */
25
+ export declare const paint: (style: string, text: string, reset: string) => string;
26
+ /**
27
+ * Dim placeholder for data whose rendering threw, so logging never throws
28
+ * because of the logged data.
29
+ */
30
+ export declare const paintUnrenderable: (thrown: unknown, { textDim, reset }: BakedStyles, { label }: Sanitizer) => string;
31
+ /**
32
+ * Merges style sheets group by group, so overriding one style of a type keeps
33
+ * the other base styles of that type.
34
+ *
35
+ * The result has no prototype and reads own groups only, so a `__proto__` key
36
+ * (e.g. from a sheet parsed from JSON) is a plain, unused group instead of
37
+ * replacing the sheet's prototype.
38
+ */
39
+ export declare const mergeStyleSheets: (base: StyleSheet, override: StyleSheet | undefined) => StyleSheet;
40
+ export interface SanitizeOptions {
41
+ /**
42
+ * Sanitization of logged text: strings, object keys and values, errors and
43
+ * graph labels. See `Sanitize`. Default: `'safe'`.
44
+ */
45
+ readonly sanitize?: Sanitize;
46
+ }
47
+ /**
48
+ * Default symbols in front of the type badge: three ASCII characters each,
49
+ * which every terminal and font draws, one column per character. Emoji are
50
+ * missing from some fonts and their width differs between terminals, which
51
+ * shifts the badge.
52
+ */
53
+ export declare const DEFAULT_SYMBOLS: Readonly<Record<LogType, string>>;
54
+ /** One symbol for every log type, or symbols per type. */
55
+ export type Symbols = string | Readonly<Partial<Record<LogType, string>>>;
56
+ export interface HeaderOptions {
57
+ /** Show the log id. Default: `false`. */
58
+ readonly showId?: boolean;
59
+ /**
60
+ * Symbol in front of the type badge. A string is used as is for every
61
+ * type (`''` for none). Symbols per type are merged over
62
+ * `DEFAULT_SYMBOLS` (`undefined` keeps the default) and padded with spaces
63
+ * to the widest one plus one, so the badges line up. Default:
64
+ * `DEFAULT_SYMBOLS`.
65
+ */
66
+ readonly symbol?: Symbols;
67
+ }
68
+ /**
69
+ * Template functions rendering the common log header: dim id, timestamp and
70
+ * symbol, the type badge and a hidden kind.
71
+ *
72
+ * @throws TypeError if a symbol is not a string.
73
+ */
74
+ export declare const headerTemplates: ({ showId, symbol, }: HeaderOptions) => TemplateMap;