@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,48 @@
1
+ /**
2
+ * Default timestamp pattern, local time: `2026/03/16 15:35:00`. Change the
3
+ * default here; see `compileTimestamp` for the tokens.
4
+ */
5
+ export declare const DEFAULT_TIMESTAMP_FORMAT = "YYYY/MM/DD HH:mm:ss";
6
+ /**
7
+ * Formats the time of a log.
8
+ *
9
+ * @param time Epoch time in whole milliseconds.
10
+ * @param timeNs Nanoseconds within the millisecond (0-999,999); `0` unless
11
+ * the logger's clock is `'precise'`.
12
+ */
13
+ export type TimestampFormatter = (time: number, timeNs: number) => string;
14
+ export interface CompileTimestampOptions {
15
+ /** Format the time in UTC instead of local time. Default: `false`. */
16
+ readonly utc?: boolean;
17
+ /**
18
+ * Start of the elapsed time tokens (`E`, `EEE`), as epoch milliseconds and
19
+ * nanoseconds within the millisecond. Default: when the pattern is
20
+ * compiled, from `Date.now()`.
21
+ */
22
+ readonly start?: readonly [time: number, timeNs: number];
23
+ }
24
+ /**
25
+ * Compiles a timestamp pattern once, dayjs-style:
26
+ *
27
+ * | Token | Output |
28
+ * | --- | --- |
29
+ * | `YYYY` `YY` | `2026` `26` |
30
+ * | `MMMM` `MMM` `MM` `M` | `March` `Mar` `03` `3` |
31
+ * | `DD` `D` | `16` `16` |
32
+ * | `dddd` `ddd` | `Monday` `Mon` |
33
+ * | `HH` `H` | `15` `15` (24 hours) |
34
+ * | `hh` `h` `A` `a` | `03` `3` `PM` `pm` (12 hours) |
35
+ * | `mm` `m`, `ss` `s` | minutes, seconds |
36
+ * | `SSS` `SSSSSS` `SSSSSSSSS` | milliseconds, microseconds, nanoseconds |
37
+ * | `Z` `ZZ` | `+02:00` `+0200` |
38
+ * | `E` | elapsed since the start: `+1s 32ms 400µs` |
39
+ * | `EEE` | elapsed in milliseconds: `+1032.400123ms` |
40
+ * | `[text]` | `text` as is |
41
+ *
42
+ * Other characters are written as is. Text that changes at most once per
43
+ * second is rendered with `Date` getters and cached, so a log only pays a
44
+ * comparison plus its fraction and elapsed tokens.
45
+ *
46
+ * @throws RangeError when formatting a time that is not a finite number.
47
+ */
48
+ export declare const compileTimestamp: (pattern: string, { utc, start }?: CompileTimestampOptions) => TimestampFormatter;
@@ -0,0 +1,176 @@
1
+ import type { SecProperty } from 'style-escape-codes';
2
+ import type { BaseLogger } from './logger.js';
3
+ import type { TimestampFormatter } from './time.js';
4
+ /**
5
+ * Supported logging levels, ordered from the lowest verbosity (`'silent'`),
6
+ * which suppresses all output, to the highest verbosity (`'verbose'`).
7
+ */
8
+ export type LogLevel = 'silent' | 'fatal' | 'error' | 'warning' | 'info' | 'debug' | 'trace' | 'verbose';
9
+ /**
10
+ * Actual message log type. Excludes `'silent'` as a message can not be silent.
11
+ */
12
+ export type LogType = Exclude<LogLevel, 'silent'>;
13
+ /**
14
+ * Log object travelling through the transformers pipeline. The logger creates
15
+ * it with `id`, `timestamp` (when enabled), `type`, `kind` and `data` keys, in
16
+ * that order. Each log gets its own fresh object, so transformers are free to
17
+ * mutate it.
18
+ */
19
+ export type LogEntry = Record<string, unknown>;
20
+ /**
21
+ * Named ANSI escape code strings, baked once for a particular log type.
22
+ * When styles are disabled every value is an empty string.
23
+ */
24
+ export type BakedStyles = Readonly<Record<string, string>>;
25
+ /**
26
+ * Per-log information shared by transformers, template functions and outputs.
27
+ */
28
+ export interface LogContext {
29
+ readonly type: LogType;
30
+ readonly kind: string;
31
+ /**
32
+ * Epoch time of the log in whole milliseconds, read once from the logger's
33
+ * `clock`; the entry's `timestamp` is formatted from it. `undefined` when
34
+ * timestamps are off (`timestamp: false`). For outputs that need machine
35
+ * time, e.g. JSON.
36
+ */
37
+ readonly time?: number | undefined;
38
+ /**
39
+ * Nanoseconds within `time`'s millisecond (0-999,999), only with the
40
+ * `'precise'` clock; `undefined` otherwise (millisecond resolution).
41
+ */
42
+ readonly timeNs?: number | undefined;
43
+ /** Styles baked for `type`. */
44
+ readonly styles: BakedStyles;
45
+ /** Template map registered for `kind`, if any. */
46
+ readonly templateMap: TemplateMap | undefined;
47
+ }
48
+ /**
49
+ * A single step of the pipeline. Receives the current entry and returns the
50
+ * entry to be passed to the next step.
51
+ */
52
+ export type Transformer = (entry: LogEntry, ctx: LogContext) => LogEntry;
53
+ /**
54
+ * Converts a single log entry property.
55
+ *
56
+ * @param value Current value of the property.
57
+ * @param ctx Current log context.
58
+ * @param key Name of the property.
59
+ */
60
+ export type TemplateFn = (value: unknown, ctx: LogContext, key: string) => unknown;
61
+ /**
62
+ * Template functions keyed by log entry property name. Properties without a
63
+ * template function pass through unchanged.
64
+ */
65
+ export type TemplateMap = Readonly<Record<string, TemplateFn>>;
66
+ /**
67
+ * Final destination of a log entry, after all transformers were applied.
68
+ */
69
+ export type Output = (entry: LogEntry, ctx: LogContext) => void;
70
+ /**
71
+ * Anything that can be baked to an escape code string: a raw string or a
72
+ * `style-escape-codes` chain such as `sec.b.fgRed`.
73
+ */
74
+ export type StyleInput = string | SecProperty;
75
+ /**
76
+ * Named styles grouped by log type. Styles under `'*'` apply to all types and
77
+ * are overridden by type specific ones.
78
+ */
79
+ export type StyleSheet = Partial<Record<LogType | '*', Readonly<Record<string, StyleInput>>>>;
80
+ /**
81
+ * Transformer with an optional position in the logger's transformers list.
82
+ * Without position it is appended.
83
+ */
84
+ export interface PluginTransformer {
85
+ readonly transformer: Transformer;
86
+ readonly position?: number;
87
+ }
88
+ /**
89
+ * Extension of the logger. Plugins own their configuration (usually taken by a
90
+ * plugin factory function), so the logger never has to know its shape.
91
+ *
92
+ * @template M Methods the plugin adds to the logger's type, usually created by
93
+ * `methods`. A plugin may also re-declare existing logger methods (e.g. to
94
+ * narrow parameters and replace docs after changing the default kind) without
95
+ * implementing them in `methods`.
96
+ */
97
+ export interface LoggerPlugin<M extends object = object> {
98
+ /** Unique plugin name. A plugin can be used only once per logger. */
99
+ readonly name: string;
100
+ /** Styles available to all template maps and outputs. */
101
+ readonly styles?: StyleSheet;
102
+ /** Template maps keyed by log kind. Merged with existing maps. */
103
+ readonly templateMaps?: Readonly<Record<string, TemplateMap>>;
104
+ /** Transformers to be inserted into the pipeline. */
105
+ readonly transformers?: readonly PluginTransformer[];
106
+ /** Outputs keyed by log kind. Replace the default output for that kind. */
107
+ readonly outputs?: Readonly<Record<string, Output>>;
108
+ /** Factory for methods attached to the logger instance. */
109
+ readonly methods?: (logger: BaseLogger) => M;
110
+ /** Kind used by logs without an explicit kind, e.g. `'message'`. */
111
+ readonly defaultKind?: string;
112
+ /**
113
+ * Rejects functions, which would otherwise match this shape through their
114
+ * `name` property, e.g. `use(graphPlugin)` instead of `use(graphPlugin())`.
115
+ */
116
+ readonly call?: never;
117
+ }
118
+ /**
119
+ * Timestamp options. The pattern is compiled once, when the logger is
120
+ * created.
121
+ */
122
+ export interface TimestampOptions {
123
+ /**
124
+ * dayjs-style pattern, e.g. `'YYYY-MM-DD HH:mm:ss.SSS'`; see
125
+ * `compileTimestamp` for the tokens. Default: `DEFAULT_TIMESTAMP_FORMAT`
126
+ * (`'YYYY/MM/DD HH:mm:ss'`).
127
+ */
128
+ readonly format?: string;
129
+ /** Format in UTC instead of local time. Default: `false`. */
130
+ readonly utc?: boolean;
131
+ }
132
+ /**
133
+ * Time source of the logs:
134
+ * - `'wall'`: `Date.now()`, millisecond resolution, follows the system clock;
135
+ * - `'precise'`: `process.hrtime` anchored to `Date.now()` when the logger
136
+ * is created: nanosecond resolution and monotonic, so it can drift from
137
+ * the system clock (NTP corrections, sleep) on long-running processes;
138
+ * - a function returning epoch milliseconds, e.g. a fixed time in tests. It
139
+ * is the time of the log, not a duration: durations belong in the data.
140
+ */
141
+ export type Clock = 'wall' | 'precise' | (() => number);
142
+ type UnionToIntersection<U> = (U extends unknown ? (union: U) => void : never) extends ((intersection: infer I) => void) ? I : never;
143
+ /**
144
+ * `T` with the members of `M`. Members of `T` that `M` re-declares are
145
+ * replaced, together with their docs, instead of being merged into overloads.
146
+ */
147
+ export type Override<T, M> = [
148
+ keyof M & keyof T
149
+ ] extends [never] ? T & M : Omit<T, keyof M> & M;
150
+ type MethodsOf<P> = P extends LoggerPlugin<infer M> ? M : never;
151
+ /**
152
+ * Methods added by a list of plugins, combined.
153
+ */
154
+ export type PluginMethods<P extends readonly LoggerPlugin[]> = UnionToIntersection<MethodsOf<P[number]>>;
155
+ export interface LoggerOptions<P extends readonly LoggerPlugin[] = readonly LoggerPlugin[]> {
156
+ /** Minimum level to output. Default: `'info'`. */
157
+ readonly level?: LogLevel;
158
+ /** Plugins to use, in order. */
159
+ readonly plugins?: P;
160
+ /** Kind of logs without an explicit kind. Default: `'default'`. */
161
+ readonly defaultKind?: string;
162
+ /**
163
+ * Timestamp: a pattern (`'HH:mm:ss.SSS'`), options (`{ format, utc }`), a
164
+ * formatter `(time, timeNs) => string` called on every log, or `false` to
165
+ * omit timestamps (and skip reading the clock). Default:
166
+ * `DEFAULT_TIMESTAMP_FORMAT` in local time.
167
+ */
168
+ readonly timestamp?: string | TimestampOptions | TimestampFormatter | false;
169
+ /** Output used for kinds without plugin output. Default: `console.log`. */
170
+ readonly output?: Output;
171
+ /** Bake styles to escape codes or to empty strings. Default: `true`. */
172
+ readonly useStyles?: boolean;
173
+ /** Time source of the logs, see `Clock`. Default: `'wall'`. */
174
+ readonly clock?: Clock;
175
+ }
176
+ export {};
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Centers `text` by padding it left and right. Text longer than `length` is
3
+ * returned unchanged.
4
+ */
5
+ export declare const padTextMiddle: (text: string, length: number, padString?: string) => string;
6
+ /**
7
+ * Justifies two strings to the left and right of a column. If the column is
8
+ * too narrow, each text is placed on its own line.
9
+ */
10
+ export declare const justifyLeftRight: (leftText: string, rightText: string, columnWidth: number) => string;
11
+ /**
12
+ * Rules for the control characters of logged text. C0 controls (except `\t`
13
+ * and `\n`), DEL and C1 controls are always shown as `\xHH`, like
14
+ * `util.inspect`: ESC and C1 start terminal escape sequences (cursor moves,
15
+ * screen clears, window titles, hyperlinks, clipboard writes), `\r` and `\b`
16
+ * overwrite printed text.
17
+ */
18
+ export interface SanitizeRules {
19
+ /**
20
+ * SGR sequences (`\x1B[...m`: colors, bold, etc.): `'keep'` them and end
21
+ * the text with a reset, so they can't leak into the following output, or
22
+ * `'escape'` them. Default: `'keep'`.
23
+ */
24
+ readonly colors?: 'keep' | 'escape';
25
+ /**
26
+ * Newlines: `'keep'` them, `'indent'` the continuation lines, so logged text
27
+ * can't start a line that looks like a log header, or `'escape'` them as
28
+ * `\x0A`. Default: `'indent'`.
29
+ */
30
+ readonly newlines?: 'keep' | 'indent' | 'escape';
31
+ }
32
+ /**
33
+ * Sanitization of logged text:
34
+ * - `'safe'`: colors kept, continuation lines indented, other control
35
+ * characters escaped;
36
+ * - `'strict'`: all control characters, colors and newlines escaped;
37
+ * - `'none'`: text is written as is, at no cost. Only for trusted text;
38
+ * - `SanitizeRules`: custom rules, missing ones as in `'safe'`.
39
+ */
40
+ export type Sanitize = 'none' | 'safe' | 'strict' | SanitizeRules;
41
+ /**
42
+ * Sanitizing functions built by `createSanitizer`. Clean text is returned as
43
+ * is, without allocation.
44
+ */
45
+ export interface Sanitizer {
46
+ /** Free text, e.g. messages: newlines follow the rules. */
47
+ readonly text: (text: string) => string;
48
+ /**
49
+ * Single line text, e.g. object keys, stack frames, graph labels: newlines
50
+ * are always escaped.
51
+ */
52
+ readonly label: (text: string) => string;
53
+ }
54
+ /**
55
+ * Creates the sanitizing functions of a given setting. Create it once (e.g. in
56
+ * a plugin factory) and reuse it for every log.
57
+ *
58
+ * @param sanitize Preset or custom rules. Default: `'safe'`.
59
+ */
60
+ export declare const createSanitizer: (sanitize?: Sanitize) => Sanitizer;
61
+ /**
62
+ * Length of text without SGR sequences: the columns it takes on a terminal,
63
+ * for single-width characters. Sanitized text contains no other sequences.
64
+ * `textWidth` also counts wide characters as two columns.
65
+ */
66
+ export declare const visibleLength: (text: string) => number;
67
+ /**
68
+ * Characters that are not one terminal column wide, escape codes and tabs:
69
+ * lines without them are wrapped by slicing. Box drawing and block
70
+ * characters (graphs) are not in it.
71
+ */
72
+ export declare const SLOW_CHARS: RegExp;
73
+ /**
74
+ * Terminal columns a code point takes: 0 for controls, combining marks,
75
+ * zero-width characters, variation selectors and skin tones, 2 for East
76
+ * Asian wide characters and most emoji, 1 otherwise.
77
+ */
78
+ export declare const charWidth: (codePoint: number) => number;
79
+ /**
80
+ * Terminal columns a text takes: SGR sequences take none, wide characters
81
+ * two. Tabs count as one column; `wrapText` expands them.
82
+ */
83
+ export declare const textWidth: (text: string) => number;
84
+ /**
85
+ * Describes a thrown value as `Name: message`. Never throws, even for thrown
86
+ * values with throwing getters or revoked proxies.
87
+ */
88
+ export declare const describeThrown: (thrown: unknown) => string;
89
+ /**
90
+ * Splits an error to its `name: message` head, which can span multiple
91
+ * lines, and its stack frames. Never throws: a head or stack that can't be
92
+ * read (throwing getters, `Error.prepareStackTrace`) becomes a placeholder.
93
+ */
94
+ export declare const splitError: (error: Error) => [head: string, frames: string[]];
95
+ /**
96
+ * Output size limits, like `util.inspect`'s `maxArrayLength` and
97
+ * `maxStringLength`. They keep a single log of a large buffer, array or
98
+ * string from blocking the process and flooding the output.
99
+ */
100
+ export interface OutputLimits {
101
+ /**
102
+ * Maximum rendered array, buffer and typed array elements, object keys and
103
+ * map and set entries. `Infinity` for no limit. Default: `100`.
104
+ */
105
+ readonly items?: number;
106
+ /**
107
+ * Maximum characters of a string, key, error message or JSON value, cut
108
+ * before sanitizing. `Infinity` for no limit. Default: `10_000`.
109
+ */
110
+ readonly stringLength?: number;
111
+ }
112
+ export declare const DEFAULT_OUTPUT_LIMITS: {
113
+ readonly items: 100;
114
+ readonly stringLength: 10000;
115
+ };
116
+ /**
117
+ * No output limits: the default of the text utilities, which only truncate
118
+ * when given limits.
119
+ */
120
+ export declare const NO_OUTPUT_LIMITS: {
121
+ readonly items: number;
122
+ readonly stringLength: number;
123
+ };
124
+ /**
125
+ * Fills in the default output limits and validates them.
126
+ *
127
+ * @param what Prefix of error messages, e.g. `messagePlugin`.
128
+ * @throws RangeError if a limit is not a positive integer or `Infinity`.
129
+ */
130
+ export declare const resolveOutputLimits: (limits: OutputLimits | undefined, what: string) => Required<OutputLimits>;
131
+ /**
132
+ * Note on what output limits left out: `… 3 more items`, `… 1 more item`.
133
+ */
134
+ export declare const describeLeftOut: (count: number, unit: "character" | "item" | "byte" | "entry" | "frame") => string;
135
+ /**
136
+ * Cuts text to `maxLength` characters, never inside a surrogate pair, and
137
+ * tells how many were left out: `xxx… 1000 more characters`. Shorter text is
138
+ * returned as is.
139
+ */
140
+ export declare const truncate: (text: string, maxLength: number) => string;
141
+ /**
142
+ * Keys of an object to render, at most `items`. Large arrays are indexed
143
+ * without listing all their keys first.
144
+ *
145
+ * @returns The keys and the number of keys left out.
146
+ */
147
+ export declare const limitKeys: (data: object, items: number) => [keys: string[], more: number];
148
+ /**
149
+ * JSON of an object property. Never throws: a getter that throws gives a
150
+ * placeholder, so one bad property doesn't hide the others.
151
+ */
152
+ export declare const stringifyProperty: (data: object, key: string, limits?: Required<OutputLimits>) => string;
153
+ /**
154
+ * Short description of a function, like `util.inspect`: `[Function: name]`
155
+ * or `[class Name]`, never its source code.
156
+ */
157
+ export declare const describeFunction: (fn: object) => string;
158
+ /**
159
+ * Describes buffers and typed arrays in one line, like `util.inspect`:
160
+ * `<Buffer 68 69 … 998 more bytes>`, `Uint8Array(3) [1, 2, 3]`. Their JSON
161
+ * (and their keys) would list every element.
162
+ */
163
+ export declare const describeBinary: (view: ArrayBufferView, items: number) => string;
164
+ /**
165
+ * Checks for errors of other realms (`vm` contexts, workers), which fail
166
+ * `instanceof Error`.
167
+ */
168
+ export declare const isForeignError: (value: object) => boolean;
169
+ /**
170
+ * Describes objects JSON shows as `{}`: dates (ISO), maps, sets, regular
171
+ * expressions and errors of other realms, like `util.inspect`. Entries of
172
+ * maps and sets are JSON, so nesting can't recurse.
173
+ *
174
+ * @returns `undefined` for other objects.
175
+ */
176
+ export declare const describeObject: (value: object, limits?: Required<OutputLimits>) => string | undefined;
177
+ /**
178
+ * `JSON.stringify` that never throws and describes what JSON can't:
179
+ * - functions and classes: `[Function: name]`, `[class Name]`, no source;
180
+ * - bigints: `1n`;
181
+ * - errors: `Name: message` and their own properties' JSON;
182
+ * - buffers and typed arrays: see `describeBinary`;
183
+ * - dates, maps, sets, regular expressions and errors of other realms that
184
+ * JSON shows as `{}`: see `describeObject`;
185
+ * - symbols and `undefined`: `String`;
186
+ * - circular structures: `"[Unserializable]"`.
187
+ *
188
+ * Nested values are serialized whole by the native `JSON.stringify` and the
189
+ * result is cut to `limits.stringLength`.
190
+ *
191
+ * @param limits Output limits. Default: none.
192
+ */
193
+ export declare const safeStringify: (value: unknown, limits?: Required<OutputLimits>) => string;
194
+ /**
195
+ * Text of a top-level value that is neither a string nor an object:
196
+ * functions and classes are described, bigints get their `n` suffix.
197
+ */
198
+ export declare const stringifyPrimitive: (value: unknown) => string;
199
+ /**
200
+ * Converts any log data to text:
201
+ * - strings are returned as is;
202
+ * - errors are represented by their `name: message` and stack frames;
203
+ * - buffers and typed arrays are described in one line;
204
+ * - objects and arrays print each own property as `key: JSON` on a new line;
205
+ * - everything else is converted with `String`.
206
+ *
207
+ * Never throws: data that can't be read (throwing getters, revoked proxies,
208
+ * broken errors) gives placeholders.
209
+ *
210
+ * @param sanitizer Sanitizes strings (`text`), keys, values and stack frames
211
+ * (`label`). Default: none.
212
+ * @param limits Output limits. Default: none.
213
+ */
214
+ export declare const stringifyData: (data: unknown, sanitizer?: Sanitizer, limits?: Required<OutputLimits>) => string;
215
+ /**
216
+ * How the source cells overlapping a new cell are combined:
217
+ * - `'average'`: weighted average, a smooth trend that keeps the overall mean;
218
+ * - `'max'`: the largest value, keeps peaks;
219
+ * - `'min'`: the smallest value, keeps dips.
220
+ */
221
+ export type Aggregate = 'average' | 'max' | 'min';
222
+ /**
223
+ * Scales an array to a new length by combining the overlapping source cells
224
+ * of each new cell.
225
+ *
226
+ * @param data Values to scale.
227
+ * @param newLength Length of the result.
228
+ * @param aggregate How overlapping cells are combined. Default: `'average'`.
229
+ * @throws TypeError if `newLength` is not a non-negative integer.
230
+ */
231
+ export declare const scaleArray: (data: readonly number[], newLength: number, aggregate?: Aggregate) => number[];
package/package.json CHANGED
@@ -1,6 +1,87 @@
1
1
  {
2
2
  "name": "@mmutils/logger",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Plugin-extensible TypeScript logger: a transformer pipeline, baked ANSI styles, styled messages, terminal bar graphs, side-by-side columns and JSON lines.",
5
+ "keywords": [
6
+ "logger",
7
+ "logging",
8
+ "log",
9
+ "plugin",
10
+ "terminal",
11
+ "console",
12
+ "ansi",
13
+ "colors",
14
+ "graph",
15
+ "typescript",
16
+ "json",
17
+ "ndjson",
18
+ "columns",
19
+ "mmutils"
20
+ ],
21
+ "author": "Tihomir Trifonov",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/mastermind-0xff/mm-logger.git"
26
+ },
27
+ "homepage": "https://github.com/mastermind-0xff/mm-logger#readme",
28
+ "bugs": {
29
+ "url": "https://github.com/mastermind-0xff/mm-logger/issues"
30
+ },
31
+ "type": "module",
32
+ "main": "./dist/cjs/index.cjs",
33
+ "module": "./dist/esm/index.js",
34
+ "types": "./dist/types/index.d.ts",
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/types/index.d.ts",
38
+ "import": "./dist/esm/index.js",
39
+ "require": "./dist/cjs/index.cjs"
40
+ },
41
+ "./package.json": "./package.json"
42
+ },
43
+ "files": [
44
+ "dist"
45
+ ],
46
+ "sideEffects": false,
47
+ "engines": {
48
+ "node": ">=20"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "scripts": {
54
+ "build": "npm run clean && rollup -c && tsc -p tsconfig.build.json",
55
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
56
+ "test": "vitest run",
57
+ "test:watch": "vitest",
58
+ "coverage": "vitest run --coverage",
59
+ "typecheck": "tsc --noEmit",
60
+ "lint": "eslint .",
61
+ "format": "prettier --write .",
62
+ "format:check": "prettier --check .",
63
+ "demo": "node examples/demo.js",
64
+ "images": "node scripts/readme-images.js",
65
+ "check": "npm run format:check && npm run lint && npm run typecheck && npm test",
66
+ "prepublishOnly": "npm run check && npm run build"
67
+ },
68
+ "dependencies": {
69
+ "@mmutils/time": "^0.0.3",
70
+ "style-escape-codes": "^2.0.0"
71
+ },
72
+ "devDependencies": {
73
+ "@eslint/js": "^10.0.1",
74
+ "@rollup/plugin-typescript": "^12.3.0",
75
+ "@types/node": "^26.6.3",
76
+ "@vitest/coverage-v8": "^5.0.2",
77
+ "eslint": "^10.11.0",
78
+ "eslint-config-prettier": "^10.1.8",
79
+ "globals": "^17.13.0",
80
+ "prettier": "^3.9.9",
81
+ "rollup": "^4.63.5",
82
+ "tslib": "^2.8.1",
83
+ "typescript": "^6.0.3",
84
+ "typescript-eslint": "^8.70.1",
85
+ "vitest": "^5.0.2"
86
+ }
87
+ }