@orkestrel/console 0.0.11 → 0.0.13
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/README.md +23 -21
- package/dist/src/browser/index.d.ts +85 -74
- package/dist/src/browser/index.js +69 -70
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/core/index.cjs +990 -1143
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +826 -757
- package/dist/src/core/index.d.ts +826 -757
- package/dist/src/core/index.js +987 -1134
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +130 -153
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +222 -199
- package/dist/src/server/index.d.ts +222 -199
- package/dist/src/server/index.js +130 -151
- package/dist/src/server/index.js.map +1 -1
- package/package.json +12 -13
package/dist/src/core/index.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { EmitterErrorHandler } from '@orkestrel/emitter';
|
|
2
|
-
import { EmitterHooks } from '@orkestrel/emitter';
|
|
3
|
-
import { EmitterInterface } from '@orkestrel/emitter';
|
|
1
|
+
import type { EmitterErrorHandler } from '@orkestrel/emitter';
|
|
2
|
+
import type { EmitterHooks } from '@orkestrel/emitter';
|
|
3
|
+
import type { EmitterInterface } from '@orkestrel/emitter';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Pads (or, when over budget, truncates) `text` to exactly `columns` visible columns, positioning
|
|
7
7
|
* it by `alignment`. The width primitive the box / table renderers align every cell with.
|
|
8
8
|
*
|
|
9
9
|
* @remarks
|
|
10
10
|
* Measures with {@link width} (visible code points, ANSI-aware), so a styled string aligns by
|
|
11
|
-
* its visible content, not its escape codes. When `width(text) <
|
|
11
|
+
* its visible content, not its escape codes. When `width(text) < columns`, the deficit is added
|
|
12
12
|
* as spaces — all trailing (`left`), all leading (`right`), or split with the extra space on
|
|
13
|
-
* the right (`center`). When `width(text) >
|
|
14
|
-
* `
|
|
13
|
+
* the right (`center`). When `width(text) > columns`, the visible characters are sliced to
|
|
14
|
+
* `columns` (a defensive guard — the renderers size columns to fit, so this is rarely hit; it
|
|
15
15
|
* slices the stripped text, so it never bisects an escape sequence into a broken half).
|
|
16
16
|
*
|
|
17
17
|
* @param text - The cell content (may be styled)
|
|
18
|
-
* @param
|
|
19
|
-
* @param alignment - Where to position `text` within
|
|
20
|
-
* @returns `text` fitted to exactly `
|
|
18
|
+
* @param columns - The visible column count to fit `text` into
|
|
19
|
+
* @param alignment - Where to position `text` within that budget; defaults to `left`
|
|
20
|
+
* @returns `text` fitted to exactly `columns` visible columns
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* ```ts
|
|
@@ -26,12 +26,14 @@ import { EmitterInterface } from '@orkestrel/emitter';
|
|
|
26
26
|
* align('hi', 5, 'center') // ' hi '
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
|
-
export declare function align(text: string,
|
|
29
|
+
export declare function align(text: string, columns: number, alignment?: Alignment): string;
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
33
|
-
* {@link ColumnSpec} (and the box / separator title) aligns by.
|
|
34
|
-
*
|
|
32
|
+
* Names the horizontal text alignment within a fixed-width cell — `left` / `center` / `right`,
|
|
33
|
+
* the conventional set a {@link ColumnSpec} (and the box / separator title) aligns by.
|
|
34
|
+
*
|
|
35
|
+
* @remarks
|
|
36
|
+
* A value set rather than a binary toggle, so it stays a union.
|
|
35
37
|
*/
|
|
36
38
|
export declare type Alignment = 'left' | 'center' | 'right';
|
|
37
39
|
|
|
@@ -39,13 +41,13 @@ export declare type Alignment = 'left' | 'center' | 'right';
|
|
|
39
41
|
* Matches any ANSI/VT escape sequence — CSI (SGR color/style plus cursor/erase/scroll,
|
|
40
42
|
* including colon-parameterized SGR), OSC / DCS / PM / APC / SOS string sequences
|
|
41
43
|
* (titles, hyperlinks, device strings), the `nF` charset-select family, and the
|
|
42
|
-
* two-byte `Fp` / `Fe` / `Fs` sequences (
|
|
44
|
+
* two-byte `Fp` / `Fe` / `Fs` sequences (for example `ESC 7`, `ESC D`, `ESC c` RIS). Global, so
|
|
43
45
|
* `strip` removes every occurrence.
|
|
44
46
|
*
|
|
45
47
|
* @remarks
|
|
46
|
-
* A global `RegExp` carries a mutable `lastIndex`; a scan must build a
|
|
48
|
+
* A global `RegExp` carries a mutable `lastIndex`; a scan must build a fresh `RegExp`
|
|
47
49
|
* from this one's `source` + `flags` rather than reuse this instance's `lastIndex`. This
|
|
48
|
-
* is the canonical definition, not a shared scanner. The alternation is
|
|
50
|
+
* is the canonical definition, not a shared scanner. The alternation is ordered so the
|
|
49
51
|
* CSI / string-family arms (which can start with a byte a later single-byte arm would
|
|
50
52
|
* also match) win first; every arm uses disjoint, non-nested character classes, so the
|
|
51
53
|
* match is linear in input length — no catastrophic backtracking (ReDoS-safe) even on an
|
|
@@ -55,14 +57,15 @@ export declare type Alignment = 'left' | 'center' | 'right';
|
|
|
55
57
|
export declare const ANSI_PATTERN: RegExp;
|
|
56
58
|
|
|
57
59
|
/**
|
|
58
|
-
*
|
|
59
|
-
* SGR escape codes,
|
|
60
|
-
* is the single styling output the whole console / terminal system uses in a terminal;
|
|
61
|
-
* the browser `%c` / CSS renderer (the C-f branch) implements the SAME contract over
|
|
62
|
-
* the SAME {@link Style}, so retargeting changes the renderer, never the style model.
|
|
60
|
+
* Implements the cross-environment default {@link RendererInterface} — renders style data as ANSI
|
|
61
|
+
* SGR escape codes, stateless and event-free.
|
|
63
62
|
*
|
|
64
63
|
* @remarks
|
|
65
|
-
*
|
|
64
|
+
* It is the single styling output the whole console / terminal system uses in a terminal; the
|
|
65
|
+
* browser `%c` / CSS renderer implements the same contract over the same {@link Style}, so
|
|
66
|
+
* retargeting changes the renderer, never the style model.
|
|
67
|
+
*
|
|
68
|
+
* - **Style is data in, SGR string out.** It reads the style's `foreground` /
|
|
66
69
|
* `background` / `attributes` and emits one `ESC[…m` sequence whose parameters are the
|
|
67
70
|
* mapped SGR numbers (foreground 30–37 / 90–97, background 40–47 / 100–107, attributes
|
|
68
71
|
* 1 / 2 / 3 / 4 / 7 / 9), followed by `text`, terminated by the reset `ESC[0m`.
|
|
@@ -71,24 +74,25 @@ export declare const ANSI_PATTERN: RegExp;
|
|
|
71
74
|
* - **`default` and unset colors emit no code** — a `default` (or absent) `foreground` /
|
|
72
75
|
* `background` leaves the terminal's own ink.
|
|
73
76
|
* - **The empty style and the empty string pass through** — when there is nothing to
|
|
74
|
-
* apply (no colors, no attributes) or `text` is `''`, `text` is returned
|
|
77
|
+
* apply (no colors, no attributes) or `text` is `''`, `text` is returned verbatim with
|
|
75
78
|
* no escape codes, so an unstyled render never injects a stray reset.
|
|
76
79
|
* - **Stateless and event-free** — no fields, no events; safe to share one instance.
|
|
77
80
|
*/
|
|
78
81
|
export declare class ANSIRenderer implements RendererInterface {
|
|
79
82
|
#private;
|
|
80
83
|
/**
|
|
81
|
-
*
|
|
84
|
+
* Wraps `text` in the SGR codes for `style`. Returns `text` unchanged when the style
|
|
82
85
|
* is empty or `text` is `''`.
|
|
83
86
|
*/
|
|
84
87
|
render(style: Style, text: string): string;
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
/**
|
|
88
|
-
*
|
|
91
|
+
* Names a text-style attribute — `bold` / `dim` / `italic` / `underline` / `inverse` /
|
|
92
|
+
* `strikethrough`, the standard SGR text effects.
|
|
89
93
|
*
|
|
90
94
|
* @remarks
|
|
91
|
-
* Style as
|
|
95
|
+
* Style as data: an `Attribute` is a name. The ANSI renderer maps each to its SGR
|
|
92
96
|
* on-code (`bold` → 1, `dim` → 2, `italic` → 3, `underline` → 4, `inverse` → 7,
|
|
93
97
|
* `strikethrough` → 9), composing several at once; a browser renderer maps the same
|
|
94
98
|
* names to CSS (`font-weight`, `font-style`, `text-decoration`, …).
|
|
@@ -96,46 +100,76 @@ export declare class ANSIRenderer implements RendererInterface {
|
|
|
96
100
|
export declare type Attribute = 'bold' | 'dim' | 'italic' | 'underline' | 'inverse' | 'strikethrough';
|
|
97
101
|
|
|
98
102
|
/**
|
|
99
|
-
*
|
|
103
|
+
* Maps each {@link Attribute} to its SGR "on" parameter — `bold` 1, `dim` 2, `italic` 3,
|
|
100
104
|
* `underline` 4, `inverse` 7, `strikethrough` 9. The renderer composes several by
|
|
101
105
|
* joining their codes with `;` in one SGR sequence.
|
|
102
106
|
*/
|
|
103
107
|
export declare const ATTRIBUTE_CODES: Readonly<Record<Attribute, number>>;
|
|
104
108
|
|
|
105
109
|
/**
|
|
106
|
-
*
|
|
110
|
+
* Lists every {@link Attribute}, frozen — the attributes the styler exposes as chainable
|
|
107
111
|
* accessors. The source of truth for the attribute axis.
|
|
108
112
|
*/
|
|
109
113
|
export declare const ATTRIBUTES: readonly Attribute[];
|
|
110
114
|
|
|
111
115
|
/**
|
|
112
|
-
*
|
|
116
|
+
* Maps each {@link Color} to its SGR background parameter — the 8 base colors at 40–47 and their
|
|
113
117
|
* bright variants at 100–107. `default` is intentionally absent (it emits no code).
|
|
114
118
|
*/
|
|
115
119
|
export declare const BACKGROUND_CODES: Readonly<Record<Exclude<Color, 'default'>, number>>;
|
|
116
120
|
|
|
117
121
|
/**
|
|
118
|
-
*
|
|
119
|
-
* progress bar with — the light-shade block `░` (U+2591). A single visible cell; a
|
|
120
|
-
* it
|
|
122
|
+
* Holds the default empty-cell glyph {@link import('./helpers.js').renderBar} draws the remaining
|
|
123
|
+
* run of a progress bar with — the light-shade block `░` (U+2591). A single visible cell; a
|
|
124
|
+
* consumer overrides it through {@link import('./types.js').BarOptions.empty}.
|
|
121
125
|
*/
|
|
122
126
|
export declare const BAR_EMPTY = "\u2591";
|
|
123
127
|
|
|
124
128
|
/**
|
|
125
|
-
*
|
|
126
|
-
* progress bar with — the full block `█` (U+2588). A single visible cell; a consumer
|
|
127
|
-
* {@link import('./types.js').
|
|
129
|
+
* Holds the default filled-cell glyph {@link import('./helpers.js').renderBar} draws the completed
|
|
130
|
+
* run of a progress bar with — the full block `█` (U+2588). A single visible cell; a consumer
|
|
131
|
+
* overrides it through {@link import('./types.js').BarOptions.fill}.
|
|
128
132
|
*/
|
|
129
133
|
export declare const BAR_FILL = "\u2588";
|
|
130
134
|
|
|
131
|
-
/**
|
|
135
|
+
/**
|
|
136
|
+
* Configures the pure {@link import('./helpers.js').renderBar} renderer — a determinate progress
|
|
137
|
+
* bar string (`█████░░░░░ 50% (5/10)`), width-aware and styler-optional.
|
|
138
|
+
*
|
|
139
|
+
* @remarks
|
|
140
|
+
* - `current` / `total` — the filled fraction is `current / total`, clamped to `[0, total]` (a
|
|
141
|
+
* `current` past `total` renders a full bar, a negative one an empty bar) — so a caller's overrun
|
|
142
|
+
* never produces an over-long bar. A `total` of `0` (or below) renders a full bar (nothing to do).
|
|
143
|
+
* - `width` — the visible cell count of the bar track (the glyph run between no brackets); defaults
|
|
144
|
+
* to {@link DEFAULT_BAR_WIDTH}. The percentage + `(current/total)` count follow the track.
|
|
145
|
+
* - `fill` — the filled-cell glyph; defaults to {@link BAR_FILL} (`█`). `empty` — the empty-cell
|
|
146
|
+
* glyph; defaults to {@link BAR_EMPTY} (`░`). Sized in visible columns ({@link
|
|
147
|
+
* import('./helpers.js').width}), so a multi-cell glyph still yields a `width`-wide track.
|
|
148
|
+
* - `styler` — colors the filled run when supplied (the empty run + the trailing label stay plain);
|
|
149
|
+
* the layout is identical with or without color, since the track is measured on visible width.
|
|
150
|
+
* - `style` — an optional by-value style rendered through `styler` for the filled run.
|
|
151
|
+
*/
|
|
152
|
+
export declare interface BarOptions {
|
|
153
|
+
readonly current: number;
|
|
154
|
+
readonly total: number;
|
|
155
|
+
readonly width?: number;
|
|
156
|
+
readonly fill?: string;
|
|
157
|
+
readonly empty?: string;
|
|
158
|
+
readonly styler?: StylerInterface;
|
|
159
|
+
readonly style?: Style;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Holds the bell control character (`U+0007`) that can terminate an OSC sequence. */
|
|
132
163
|
export declare const BEL: string;
|
|
133
164
|
|
|
134
165
|
/**
|
|
135
|
-
*
|
|
136
|
-
* Unicode box-drawing glyphs at
|
|
137
|
-
*
|
|
138
|
-
*
|
|
166
|
+
* Holds the complete {@link BorderChars} junction set for each {@link BorderStyle} — the standard
|
|
167
|
+
* Unicode box-drawing glyphs at each line weight, deeply frozen.
|
|
168
|
+
*
|
|
169
|
+
* @remarks
|
|
170
|
+
* The renderers ({@link import('./helpers.js').renderBox} /
|
|
171
|
+
* {@link import('./helpers.js').renderTable}) look the style up here, so no glyph literal lives in
|
|
172
|
+
* a renderer.
|
|
139
173
|
*
|
|
140
174
|
* @remarks
|
|
141
175
|
* `round` shares `single`'s edges and tees — only its corners differ (the rounded `╭╮╰╯`).
|
|
@@ -143,10 +177,13 @@ export declare const BEL: string;
|
|
|
143
177
|
export declare const BORDER_CHARS: Readonly<Record<BorderStyle, BorderChars>>;
|
|
144
178
|
|
|
145
179
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
180
|
+
* Represents one complete box-drawing junction set for a {@link BorderStyle} — the edges, the
|
|
181
|
+
* corners, and the `T` / cross junctions the box and table renderers need to frame content and
|
|
182
|
+
* rule a table.
|
|
183
|
+
*
|
|
184
|
+
* @remarks
|
|
185
|
+
* Plain data (the value lives in {@link BORDER_CHARS}); the renderers read these so no glyph
|
|
186
|
+
* literal is hard-coded in a renderer.
|
|
150
187
|
*
|
|
151
188
|
* @remarks
|
|
152
189
|
* - `horizontal` / `vertical` — the edge run characters.
|
|
@@ -171,12 +208,13 @@ export declare interface BorderChars {
|
|
|
171
208
|
}
|
|
172
209
|
|
|
173
210
|
/**
|
|
174
|
-
*
|
|
175
|
-
* with
|
|
176
|
-
*
|
|
177
|
-
* never a toggle — so it stays a union.
|
|
211
|
+
* Names a box-drawing border style — `single` / `double` / `round` / `heavy`, the standard
|
|
212
|
+
* Unicode line weights the renderers frame with, each selecting a full junction set in
|
|
213
|
+
* {@link BORDER_CHARS}.
|
|
178
214
|
*
|
|
179
215
|
* @remarks
|
|
216
|
+
* A named, fixed set (an external-spec value family) rather than a toggle, so it stays a union.
|
|
217
|
+
*
|
|
180
218
|
* `single` (`┌─┐`), `double` (`╔═╗`), `round` (`╭─╮` — single edges, rounded corners), and
|
|
181
219
|
* `heavy` (`┏━┓`). The renderer looks the style up in {@link BORDER_CHARS}; styling the
|
|
182
220
|
* border (a color) is a separate, orthogonal concern handled by the optional `styler`.
|
|
@@ -184,14 +222,14 @@ export declare interface BorderChars {
|
|
|
184
222
|
export declare type BorderStyle = 'single' | 'double' | 'round' | 'heavy';
|
|
185
223
|
|
|
186
224
|
/**
|
|
187
|
-
*
|
|
188
|
-
*
|
|
225
|
+
* Configures {@link import('./helpers.js').renderBox} — content framed in box-drawing characters. A
|
|
226
|
+
* `Reporter` supplies its own chrome style only when the caller gives neither `styler` nor `style`.
|
|
189
227
|
*
|
|
190
228
|
* @remarks
|
|
191
229
|
* - `content` — the body text; embedded newlines split it into lines, each framed on its own
|
|
192
230
|
* row. Every row is padded to the inner width measured by {@link import('./helpers.js').width}
|
|
193
|
-
* (the
|
|
194
|
-
* - `title` — an optional caption embedded in the
|
|
231
|
+
* (the visible width), so ANSI-styled content stays aligned inside the frame.
|
|
232
|
+
* - `title` — an optional caption embedded in the top border.
|
|
195
233
|
* - `padding` — horizontal cells of blank padding inside each vertical edge; defaults to
|
|
196
234
|
* {@link DEFAULT_PADDING}.
|
|
197
235
|
* - `border` — the {@link BorderStyle}; defaults to {@link DEFAULT_BORDER} (`single`).
|
|
@@ -213,32 +251,32 @@ export declare interface BoxOptions {
|
|
|
213
251
|
}
|
|
214
252
|
|
|
215
253
|
/**
|
|
216
|
-
*
|
|
217
|
-
* the
|
|
254
|
+
* Implements an observable console interceptor — it takes control of the global `console.*` on
|
|
255
|
+
* the read side. While `active`, every configured `console.x` call is captured as a frozen
|
|
218
256
|
* {@link CapturedMessage}, buffered (total + by level, bounded), emitted on `capture`, and — per
|
|
219
|
-
* options — mirrored to the real console
|
|
257
|
+
* options — mirrored to the real console, forwarded to a {@link SinkInterface}, or both.
|
|
220
258
|
*
|
|
221
259
|
* @remarks
|
|
222
|
-
* - **Snapshot-at-start (the no-capture-loop principle).** `start()` snapshots the
|
|
260
|
+
* - **Snapshot-at-start (the no-capture-loop principle).** `start()` snapshots the current
|
|
223
261
|
* `console[level]` for each configured {@link CaptureLevel}, then installs the wrappers. The
|
|
224
|
-
* mirror writes through that snapshot — so our
|
|
262
|
+
* mirror writes through that snapshot — so our own console sink output (the Logger / Reporter,
|
|
225
263
|
* which snapshot the real `console` at creation) is never recaptured: `Capture` catches
|
|
226
|
-
*
|
|
227
|
-
* - **Idempotent +
|
|
228
|
-
* (never double-patches); `stop()` while inactive is a no-op. It patches the
|
|
229
|
-
* `console`, so at most
|
|
264
|
+
* third-party `console.*`, not our writes. Create your loggers before installing a capture.
|
|
265
|
+
* - **Idempotent + process-global + non-reentrant.** `start()` while already `active` is a no-op
|
|
266
|
+
* (never double-patches); `stop()` while inactive is a no-op. It patches the one global
|
|
267
|
+
* `console`, so at most one capture may be active at a time — running two concurrently
|
|
230
268
|
* interleaves their buffers and clobbers each other's restore.
|
|
231
269
|
* - **Bounded buffers.** `messages()` / `messages(level)` — the total buffer and each by-level
|
|
232
270
|
* bucket are each capped at `limit`
|
|
233
271
|
* (oldest dropped first), never unbounded — the same retention precedent as {@link Logger}.
|
|
234
|
-
* - **Lifecycle
|
|
272
|
+
* - **Lifecycle.** `start` / `stop` toggle interception (emitting `start` / `stop`);
|
|
235
273
|
* `destroy()` stops (restoring `console`) then destroys the emitter.
|
|
236
274
|
*
|
|
237
275
|
* @example
|
|
238
276
|
* ```ts
|
|
239
277
|
* const capture = new Capture({ levels: ['warn', 'error'], mirror: true })
|
|
240
278
|
* capture.start()
|
|
241
|
-
* console.warn('third-party noise') // captured
|
|
279
|
+
* console.warn('third-party noise') // captured and mirrored to the real console
|
|
242
280
|
* capture.messages('warn') // [{ level: 'warn', text: 'third-party noise', time: … }]
|
|
243
281
|
* capture.stop() // console.warn restored
|
|
244
282
|
* ```
|
|
@@ -257,9 +295,10 @@ export declare class Capture implements CaptureInterface {
|
|
|
257
295
|
}
|
|
258
296
|
|
|
259
297
|
/**
|
|
260
|
-
*
|
|
298
|
+
* Maps each {@link CaptureLevel} to its {@link LogLevel} for the optional sink forward — the projection the
|
|
261
299
|
* Capture routes through when writing an intercepted call to a {@link
|
|
262
|
-
* import('./types.js').SinkInterface}
|
|
300
|
+
* import('./types.js').SinkInterface}. `sink.write(text, CAPTURE_LEVEL_MAP[level])` is the call
|
|
301
|
+
* this map backs. `warn` /
|
|
263
302
|
* `error` / `debug` / `info` map to their matching {@link LogLevel}; `log` maps to `info` (a plain
|
|
264
303
|
* console log is informational — the default stream), so a stream-aware sink routes `warn` / `error`
|
|
265
304
|
* captures to the right stream. The source of truth for the capture-to-log projection.
|
|
@@ -267,7 +306,7 @@ export declare class Capture implements CaptureInterface {
|
|
|
267
306
|
export declare const CAPTURE_LEVEL_MAP: Readonly<Record<CaptureLevel, LogLevel>>;
|
|
268
307
|
|
|
269
308
|
/**
|
|
270
|
-
*
|
|
309
|
+
* Lists every {@link CaptureLevel}, frozen — the `console.*` methods a {@link
|
|
271
310
|
* import('./types.js').CaptureInterface} intercepts by default (and the source of truth for the
|
|
272
311
|
* capture-level axis; drives exhaustive tests). The universal console methods: `log`, `info`,
|
|
273
312
|
* `warn`, `error`, `debug`.
|
|
@@ -275,7 +314,7 @@ export declare const CAPTURE_LEVEL_MAP: Readonly<Record<CaptureLevel, LogLevel>>
|
|
|
275
314
|
export declare const CAPTURE_LEVELS: readonly CaptureLevel[];
|
|
276
315
|
|
|
277
316
|
/**
|
|
278
|
-
*
|
|
317
|
+
* Represents one captured console call — an immutable, serializable record of a single intercepted
|
|
279
318
|
* `console.*` invocation. A {@link CaptureInterface} builds one per call, freezes it, buffers it
|
|
280
319
|
* (total + by level), and emits it on `capture`; every consumer reads this exact shape.
|
|
281
320
|
*
|
|
@@ -296,108 +335,114 @@ export declare interface CapturedMessage {
|
|
|
296
335
|
}
|
|
297
336
|
|
|
298
337
|
/**
|
|
299
|
-
*
|
|
338
|
+
* Declares the observable events a {@link CaptureInterface} emits — `capture(message)` per
|
|
339
|
+
* intercepted call, plus the `start` and `stop` lifecycle signals.
|
|
300
340
|
*
|
|
301
341
|
* @remarks
|
|
302
|
-
* - `capture` —
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
* - `start` / `stop` — the lifecycle signals: `start` fires when interception is installed (the
|
|
342
|
+
* - `capture` — fires for every intercepted `console.*` call (one per call, while active),
|
|
343
|
+
* carrying the frozen {@link CapturedMessage}. The hook a live console viewer / tee rides.
|
|
344
|
+
* - `start` / `stop` — `start` fires when interception is installed (the
|
|
306
345
|
* first `start()` on an inactive capture), `stop` when it is torn down (a `stop()` on an active
|
|
307
346
|
* capture, and from `destroy()`); both are pure signals (empty tuples) so a consumer can mirror
|
|
308
|
-
* the global-patch lifecycle (
|
|
347
|
+
* the global-patch lifecycle (for example log that capture is engaged). They earn their place by
|
|
309
348
|
* bracketing the process-global side effect a consumer needs to observe.
|
|
310
349
|
*
|
|
311
|
-
* Listener isolation is the emitter's
|
|
350
|
+
* Listener isolation is the emitter's: a listener throw routes to the emitter's `error`
|
|
312
351
|
* handler, never onto this map — so a buggy `capture` listener can never perturb interception (or
|
|
313
352
|
* the underlying program's own `console.*` call). Declared as a `type` alias (not
|
|
314
|
-
* `interface extends EventMap
|
|
353
|
+
* `interface extends EventMap`): a type-literal satisfies the `EventMap` constraint
|
|
315
354
|
* structurally, whereas an interface lacks the index signature.
|
|
316
355
|
*/
|
|
317
356
|
export declare type CaptureEventMap = {
|
|
318
|
-
/**
|
|
357
|
+
/** Fires on an intercepted `console.*` call — the frozen {@link CapturedMessage}. */
|
|
319
358
|
readonly capture: readonly [message: CapturedMessage];
|
|
320
|
-
/**
|
|
359
|
+
/** Fires after interception was installed (an inactive capture's `start()`). */
|
|
321
360
|
readonly start: readonly [];
|
|
322
|
-
/**
|
|
361
|
+
/** Fires after interception was torn down (an active capture's `stop()` / `destroy()`). */
|
|
323
362
|
readonly stop: readonly [];
|
|
324
363
|
};
|
|
325
364
|
|
|
326
365
|
/**
|
|
327
|
-
*
|
|
328
|
-
* the
|
|
366
|
+
* Declares an observable console interceptor — it takes control of the global `console.*` on
|
|
367
|
+
* the read side: while `active`, every configured `console.x` call is captured as a frozen
|
|
329
368
|
* {@link CapturedMessage}, buffered (total + by level, bounded), emitted on `capture`, and —
|
|
330
|
-
* per options — mirrored to the real console
|
|
369
|
+
* per options — mirrored to the real console, forwarded to a {@link SinkInterface}, or both.
|
|
331
370
|
*
|
|
332
371
|
* @remarks
|
|
333
|
-
* - **Snapshot-at-start.** `start()` snapshots the
|
|
372
|
+
* - **Snapshot-at-start.** `start()` snapshots the current `console[level]` for each configured
|
|
334
373
|
* {@link CaptureLevel}, then installs the wrappers. The mirror writes through that snapshot, so
|
|
335
|
-
* our
|
|
336
|
-
* creation) is never recaptured — `Capture` catches
|
|
337
|
-
* (the no-capture-loop principle). Create your loggers
|
|
374
|
+
* our own console sink output (the Logger / Reporter, which snapshot the real `console` at
|
|
375
|
+
* creation) is never recaptured — `Capture` catches third-party `console.*`, not our writes
|
|
376
|
+
* (the no-capture-loop principle). Create your loggers before installing a capture.
|
|
338
377
|
* - **Idempotent + non-reentrant.** `start()` while already `active` is a no-op (it never
|
|
339
|
-
* double-patches), and `stop()` while inactive is a no-op. It is
|
|
340
|
-
* one global `console` — so at most
|
|
378
|
+
* double-patches), and `stop()` while inactive is a no-op. It is process-global — it patches the
|
|
379
|
+
* one global `console` — so at most one capture may be active at a time; running two
|
|
341
380
|
* concurrently interleaves their buffers and clobbers each other's restore.
|
|
342
381
|
* - **Bounded buffers.** `messages()` returns a copy of the whole buffer (oldest first);
|
|
343
382
|
* `messages(level)` a copy of one {@link CaptureLevel}'s bucket — each capped at `limit`
|
|
344
|
-
* (oldest dropped first), never unbounded. `clear()` empties them (it does
|
|
345
|
-
* - **Lifecycle
|
|
383
|
+
* (oldest dropped first), never unbounded. `clear()` empties them (it does not stop interception).
|
|
384
|
+
* - **Lifecycle.** `start` / `stop` toggle interception; `destroy()` stops (restoring
|
|
346
385
|
* `console`) then destroys the emitter (its listeners go).
|
|
347
386
|
*/
|
|
348
387
|
export declare interface CaptureInterface {
|
|
349
388
|
readonly emitter: EmitterInterface<CaptureEventMap>;
|
|
350
|
-
/**
|
|
389
|
+
/** Reports whether interception is installed (between `start()` and `stop()`). */
|
|
351
390
|
readonly active: boolean;
|
|
352
|
-
/**
|
|
391
|
+
/** Snapshots the configured `console.*` and installs the interceptors — a no-op when already `active`. */
|
|
353
392
|
start(): void;
|
|
354
|
-
/**
|
|
393
|
+
/** Restores the snapshot-original `console.*` — a no-op when not `active`. */
|
|
355
394
|
stop(): void;
|
|
356
|
-
/**
|
|
395
|
+
/**
|
|
396
|
+
* Returns a copy of the whole captured buffer, oldest first (capped at `limit`), or — given
|
|
397
|
+
* a {@link CaptureLevel} — a copy of only that level's bucket.
|
|
398
|
+
*/
|
|
357
399
|
messages(): readonly CapturedMessage[];
|
|
358
|
-
/**
|
|
400
|
+
/** Returns a copy of the captured buffer for one {@link CaptureLevel}, oldest first (capped at `limit`). */
|
|
359
401
|
messages(level: CaptureLevel): readonly CapturedMessage[];
|
|
360
|
-
/**
|
|
402
|
+
/** Drops every buffered message (total + by level); does not stop interception. */
|
|
361
403
|
clear(): void;
|
|
362
|
-
/**
|
|
404
|
+
/** Tears down — `stop()` (restoring `console`) then destroys the emitter. */
|
|
363
405
|
destroy(): void;
|
|
364
406
|
}
|
|
365
407
|
|
|
366
408
|
/**
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
* / `error` / `debug`); a named value family (it indexes {@link CAPTURE_LEVEL_MAP} to a
|
|
370
|
-
* {@link LogLevel} for the optional sink forward), never a binary toggle — so it stays a union.
|
|
409
|
+
* Identifies one intercepted `console` method — `log` / `info` / `warn` / `error` / `debug`, the
|
|
410
|
+
* names a {@link CaptureInterface} patches and reports under.
|
|
371
411
|
*
|
|
372
412
|
* @remarks
|
|
373
|
-
*
|
|
413
|
+
* A named value family (it indexes {@link CAPTURE_LEVEL_MAP} to a {@link LogLevel} for the
|
|
414
|
+
* optional sink forward) rather than a binary toggle, so it stays a union.
|
|
415
|
+
*
|
|
416
|
+
* distinct from {@link LogLevel}: a `CaptureLevel` names the originating console method (which
|
|
374
417
|
* `console.x` was called), not a severity threshold — there is no ordering and no gating (every
|
|
375
418
|
* configured method is captured). `log` and `info` are separate methods (both default-stream),
|
|
376
419
|
* mapped to the sink's default / `info` stream respectively; `warn` / `error` / `debug` map to
|
|
377
|
-
* their matching {@link LogLevel}. The default configured set is {@link
|
|
420
|
+
* their matching {@link LogLevel}. The default configured set is {@link CAPTURE_LEVELS}.
|
|
378
421
|
*/
|
|
379
422
|
export declare type CaptureLevel = 'log' | 'info' | 'warn' | 'error' | 'debug';
|
|
380
423
|
|
|
381
424
|
/**
|
|
382
|
-
*
|
|
425
|
+
* Configures the {@link import('./Capture.js').Capture} constructor — the `on` / `error` emitter
|
|
426
|
+
* keys, the `levels` intercepted, the `mirror` pass-through, the `sink` forward, and the buffer
|
|
427
|
+
* `limit`.
|
|
383
428
|
*
|
|
384
429
|
* @remarks
|
|
385
|
-
* - `on` — the reserved {@link EmitterHooks} key
|
|
386
|
-
* {@link CaptureEventMap}, wired at construction (
|
|
387
|
-
* - `error` — the emitter's listener-error handler
|
|
388
|
-
* - `levels` — which `console.*` methods to intercept; defaults to {@link
|
|
389
|
-
*
|
|
390
|
-
*
|
|
391
|
-
* - `mirror` — when `true`, each intercepted call is
|
|
430
|
+
* - `on` — the reserved {@link EmitterHooks} key: initial listeners for the
|
|
431
|
+
* {@link CaptureEventMap}, wired at construction (for example `{ capture: (m) => tee(m) }`).
|
|
432
|
+
* - `error` — the emitter's listener-error handler; a listener throw routes here.
|
|
433
|
+
* - `levels` — which `console.*` methods to intercept; defaults to {@link CAPTURE_LEVELS}. Only the
|
|
434
|
+
* listed methods are patched — an unlisted method is left untouched and its calls pass through
|
|
435
|
+
* normally.
|
|
436
|
+
* - `mirror` — when `true`, each intercepted call is also forwarded to the snapshot-original
|
|
392
437
|
* `console` method, so the program's own console output still appears while being captured;
|
|
393
|
-
* defaults to `false` (capture silently). Mirrors through the method snapshotted
|
|
438
|
+
* defaults to `false` (capture silently). Mirrors through the method snapshotted at `start()`,
|
|
394
439
|
* never the live (re-patched) one — no echo loop.
|
|
395
440
|
* - `sink` — an optional {@link SinkInterface} each intercepted call is also written to
|
|
396
|
-
* (`sink.write(text, level)` with the {@link CaptureLevel} mapped to a {@link LogLevel}
|
|
441
|
+
* (`sink.write(text, level)` with the {@link CaptureLevel} mapped to a {@link LogLevel} through
|
|
397
442
|
* {@link CAPTURE_LEVEL_MAP}), to tee captured output into the logging pipeline / a file. Absent
|
|
398
443
|
* ⇒ no forward.
|
|
399
444
|
* - `limit` — the bounded buffer cap: at most this many recent messages are retained per buffer
|
|
400
|
-
* (the total buffer and
|
|
445
|
+
* (the total buffer and each by-level bucket; oldest dropped first). Defaults to
|
|
401
446
|
* {@link DEFAULT_CAPTURE_LIMIT}; never unbounded (a long capture can't grow without bound — the
|
|
402
447
|
* same retention precedent as {@link LoggerInterface}).
|
|
403
448
|
*/
|
|
@@ -411,8 +456,8 @@ export declare interface CaptureOptions {
|
|
|
411
456
|
}
|
|
412
457
|
|
|
413
458
|
/**
|
|
414
|
-
*
|
|
415
|
-
* own return `value` plus the
|
|
459
|
+
* Represents the structured outcome of {@link import('./factories.js').createCaptureResult} — the
|
|
460
|
+
* wrapped function's own return `value` plus the `messages` it logged while it ran.
|
|
416
461
|
*
|
|
417
462
|
* @remarks
|
|
418
463
|
* - `value` — whatever the wrapped `fn` returned (its `T`).
|
|
@@ -425,7 +470,7 @@ export declare interface CaptureResult<T> {
|
|
|
425
470
|
}
|
|
426
471
|
|
|
427
472
|
/**
|
|
428
|
-
*
|
|
473
|
+
* Returns the cell at `index` of a (possibly ragged) row — `''` when the row is shorter than the
|
|
429
474
|
* column count, so a short row pads out instead of throwing (the ragged-row guard
|
|
430
475
|
* {@link renderTable} reads every cell through).
|
|
431
476
|
*
|
|
@@ -436,31 +481,31 @@ export declare interface CaptureResult<T> {
|
|
|
436
481
|
export declare function cellAt(row: readonly string[], index: number): string;
|
|
437
482
|
|
|
438
483
|
/**
|
|
439
|
-
*
|
|
484
|
+
* Names a terminal color — the 8 standard base colors, their 8 bright variants, and
|
|
440
485
|
* `default` (the target's own default ink, emitting no color code).
|
|
441
486
|
*
|
|
442
487
|
* @remarks
|
|
443
|
-
* Style as
|
|
488
|
+
* Style as data: a `Color` is a name, not an escape sequence. The renderer maps it to
|
|
444
489
|
* its target's codes — the ANSI renderer to SGR 30–37 / 90–97 (foreground) and 40–47 /
|
|
445
|
-
* 100–107 (background); a browser renderer maps the
|
|
490
|
+
* 100–107 (background); a browser renderer maps the same names to CSS colors.
|
|
446
491
|
* `default` means "leave the target's default" and contributes no code.
|
|
447
492
|
*/
|
|
448
493
|
export declare type Color = 'black' | 'red' | 'green' | 'yellow' | 'blue' | 'magenta' | 'cyan' | 'white' | 'brightBlack' | 'brightRed' | 'brightGreen' | 'brightYellow' | 'brightBlue' | 'brightMagenta' | 'brightCyan' | 'brightWhite' | 'default';
|
|
449
494
|
|
|
450
495
|
/**
|
|
451
|
-
*
|
|
496
|
+
* Lists every named {@link Color} except `default`, frozen — the colors the styler exposes as
|
|
452
497
|
* chainable accessors. The source of truth for the color axis; the styler drives its
|
|
453
498
|
* accessors from this array so the literals live in one place.
|
|
454
499
|
*/
|
|
455
500
|
export declare const COLORS: ReadonlyArray<Exclude<Color, 'default'>>;
|
|
456
501
|
|
|
457
502
|
/**
|
|
458
|
-
*
|
|
503
|
+
* Represents one column of a {@link TableOptions} — its header label and how its cells align.
|
|
459
504
|
*
|
|
460
505
|
* @remarks
|
|
461
506
|
* - `label` — the header text shown in the table's first row.
|
|
462
507
|
* - `align` — how this column's header and cells align within the column width; defaults to
|
|
463
|
-
* {@link DEFAULT_ALIGN} (`left`). The column is sized to the widest
|
|
508
|
+
* {@link DEFAULT_ALIGN} (`left`). The column is sized to the widest visible content
|
|
464
509
|
* (header or any cell, measured by {@link import('./helpers.js').width}), so a styled cell
|
|
465
510
|
* never breaks the column.
|
|
466
511
|
*/
|
|
@@ -470,12 +515,12 @@ export declare interface ColumnSpec {
|
|
|
470
515
|
}
|
|
471
516
|
|
|
472
517
|
/**
|
|
473
|
-
*
|
|
518
|
+
* Carries a {@link ConsoleErrorCode} and an optional `context` bag — the error the console layer
|
|
519
|
+
* throws for an internal invariant violated at a defensive guard.
|
|
474
520
|
*
|
|
475
521
|
* @remarks
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
* (`INVARIANT`) — the one throw site in this codebase today.
|
|
522
|
+
* `INVARIANT` is the code for a guard that is structurally unreachable, so a `catch` branches on
|
|
523
|
+
* `error.code` rather than parsing the message.
|
|
479
524
|
*/
|
|
480
525
|
export declare class ConsoleError extends Error {
|
|
481
526
|
readonly code: ConsoleErrorCode;
|
|
@@ -484,280 +529,152 @@ export declare class ConsoleError extends Error {
|
|
|
484
529
|
}
|
|
485
530
|
|
|
486
531
|
/**
|
|
487
|
-
*
|
|
532
|
+
* Names the machine-readable error code a {@link import('./errors.js').ConsoleError} carries —
|
|
533
|
+
* `INVARIANT`, the only code the package throws.
|
|
488
534
|
*
|
|
489
535
|
* @remarks
|
|
490
|
-
* `INVARIANT`
|
|
491
|
-
* check that
|
|
492
|
-
* forbids speculating a richer taxonomy before a second throw site exists.
|
|
536
|
+
* `INVARIANT` reports that an internal invariant or unreachable guard was violated — a defensive
|
|
537
|
+
* check that is structurally impossible to trip.
|
|
493
538
|
*/
|
|
494
539
|
export declare type ConsoleErrorCode = 'INVARIANT';
|
|
495
540
|
|
|
541
|
+
/**
|
|
542
|
+
* Names the console-method shape a {@link CaptureInterface} snapshots and swaps at the patch
|
|
543
|
+
* boundary — a variadic sink of arbitrary arguments.
|
|
544
|
+
*
|
|
545
|
+
* @remarks
|
|
546
|
+
* It is exactly the universal `console.log` / `info` / `warn` / `error` / `debug` signature, so it
|
|
547
|
+
* types the global `console` viewed as a record keyed by {@link CaptureLevel}. Every
|
|
548
|
+
* `CaptureLevel` is a real `Console` method, so `console` is assignable to that view with no type
|
|
549
|
+
* assertion, which keeps the global-patch boundary honest.
|
|
550
|
+
*/
|
|
496
551
|
export declare type ConsoleMethod = (...args: unknown[]) => void;
|
|
497
552
|
|
|
498
553
|
/**
|
|
499
|
-
* Matches every C0 control character
|
|
554
|
+
* Matches every C0 control character except `\t` / `\n` / `\r` (which are meaningful
|
|
500
555
|
* whitespace), plus DEL (`0x7F`) — the non-printing bytes {@link
|
|
501
556
|
* import('./helpers.js').stripControls} removes. Global, ASCII-only source (no raw
|
|
502
557
|
* control-character literal), so a scan builds a fresh `RegExp` the same way as
|
|
503
558
|
* {@link ANSI_PATTERN} to avoid a mutated `lastIndex`.
|
|
504
559
|
*
|
|
505
560
|
* @remarks
|
|
506
|
-
* Deliberately
|
|
561
|
+
* Deliberately separate from {@link ANSI_PATTERN}: `strip()` must stay pure ANSI-escape
|
|
507
562
|
* removal (width / alignment computations depend on it leaving raw C0 bytes alone), while
|
|
508
|
-
* C0-stripping is an
|
|
563
|
+
* C0-stripping is an additional, orthogonal pass a non-TTY output sink applies on top.
|
|
509
564
|
*/
|
|
510
565
|
export declare const CONTROL_PATTERN: RegExp;
|
|
511
566
|
|
|
512
567
|
/**
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
* without the fluent surface, or to share one instance across stylers.
|
|
568
|
+
* Runs `fn` with the global `console.*` captured for its duration, returning the function's `value`
|
|
569
|
+
* plus the {@link import('./types.js').CapturedMessage}s it logged — the scoped, self-restoring
|
|
570
|
+
* ergonomic form of the {@link Capture} class.
|
|
517
571
|
*
|
|
518
|
-
* @
|
|
572
|
+
* @param fn - The async function to run under capture (returns `Promise<T>`)
|
|
573
|
+
* @param options - See {@link CaptureOptions} (`levels` / `mirror` / `sink` / `limit` / `on` /
|
|
574
|
+
* `error`); the capture is started for the duration of `fn` regardless
|
|
575
|
+
* @returns A `Promise<CaptureResult<T>>` — awaited, then `console` restored
|
|
576
|
+
*
|
|
577
|
+
* @remarks
|
|
578
|
+
* - **Always restores.** `start()` runs before `fn`; `destroy()` (which calls `stop()`) runs on
|
|
579
|
+
* every path — sync success, sync throw, and each async handler — so `console` is restored even
|
|
580
|
+
* if `fn` throws / rejects (the throw / rejection still propagates). The capture is local —
|
|
581
|
+
* created, used, and destroyed within the call.
|
|
582
|
+
* - **Sync vs async.** A `fn` returning a `Promise` is detected and awaited before `stop()`, so
|
|
583
|
+
* captures during the async work are included; a plain `fn` stops synchronously. The return type
|
|
584
|
+
* follows `fn`'s (overloaded).
|
|
585
|
+
* - **process-global caveat.** Like the {@link Capture} class, this patches the one global
|
|
586
|
+
* `console`. Concurrent `createCaptureResult` calls (or one around other capturing code)
|
|
587
|
+
* interleave — each captures every `console.*` call in flight, and the inner `stop()` restores
|
|
588
|
+
* whatever the outer had installed. Use it for sequential, scoped capture, not overlapping captures.
|
|
519
589
|
*
|
|
520
590
|
* @example
|
|
521
591
|
* ```ts
|
|
522
|
-
* import {
|
|
592
|
+
* import { createCaptureResult } from '@orkestrel/console'
|
|
523
593
|
*
|
|
524
|
-
*
|
|
525
|
-
*
|
|
594
|
+
* // The async call is awaited before `console` is restored, so the capture covers the async work.
|
|
595
|
+
* const out = await createCaptureResult(async () => {
|
|
596
|
+
* console.warn('async noise')
|
|
597
|
+
* return 'done'
|
|
598
|
+
* })
|
|
599
|
+
* out.value // 'done'
|
|
600
|
+
* out.messages.map((m) => m.text) // ['async noise']
|
|
526
601
|
* ```
|
|
527
602
|
*/
|
|
528
|
-
export declare function
|
|
603
|
+
export declare function createCaptureResult<T>(fn: () => Promise<T>, options?: CaptureOptions): Promise<CaptureResult<T>>;
|
|
529
604
|
|
|
530
605
|
/**
|
|
531
|
-
*
|
|
532
|
-
*
|
|
533
|
-
* {@link import('./types.js').CapturedMessage}, buffered (total + by level, bounded), emitted on
|
|
534
|
-
* `capture`, and — per options — mirrored to the real console and/or forwarded to a
|
|
535
|
-
* {@link SinkInterface}.
|
|
606
|
+
* Runs `fn` with the global `console.*` captured for its duration, returning the function's `value`
|
|
607
|
+
* plus the {@link import('./types.js').CapturedMessage}s it logged, synchronously.
|
|
536
608
|
*
|
|
609
|
+
* @param fn - The synchronous function to run under capture (returns `T`)
|
|
537
610
|
* @param options - See {@link CaptureOptions}
|
|
538
|
-
* @returns A {@link
|
|
539
|
-
*
|
|
540
|
-
* @remarks
|
|
541
|
-
* - **Snapshot-at-start — no capture loop.** `start()` snapshots the CURRENT `console[level]` per
|
|
542
|
-
* configured level, then patches; the mirror writes through that snapshot. Our OWN console sink
|
|
543
|
-
* output (the Logger / Reporter, which snapshot `console` at creation) is never recaptured —
|
|
544
|
-
* `Capture` catches THIRD-PARTY `console.*`, not our writes. Create your loggers FIRST.
|
|
545
|
-
* - **PROCESS-GLOBAL + NON-REENTRANT.** It patches the one global `console`, so at most ONE
|
|
546
|
-
* capture may be active at a time; two concurrent captures interleave and clobber each other's
|
|
547
|
-
* restore. Prefer {@link withCapture} for a scoped, self-restoring capture.
|
|
548
|
-
* - **Bounded.** `options.limit` (default {@link import('./constants.js').DEFAULT_CAPTURE_LIMIT})
|
|
549
|
-
* caps both the total buffer and each by-level bucket; never unbounded.
|
|
611
|
+
* @returns A {@link CaptureResult}`<T>` — `{ value, messages }`, with `console` already restored
|
|
550
612
|
*
|
|
551
613
|
* @example
|
|
552
614
|
* ```ts
|
|
553
|
-
* import {
|
|
615
|
+
* import { createCaptureResult } from '@orkestrel/console'
|
|
554
616
|
*
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
617
|
+
* // The sync call returns the result directly — no `await`, `console` already restored.
|
|
618
|
+
* const { value, messages } = createCaptureResult(() => {
|
|
619
|
+
* console.log('working')
|
|
620
|
+
* return 42
|
|
621
|
+
* })
|
|
622
|
+
* value // 42
|
|
623
|
+
* messages.map((m) => m.text) // ['working']
|
|
560
624
|
* ```
|
|
561
625
|
*/
|
|
562
|
-
export declare function
|
|
626
|
+
export declare function createCaptureResult<T>(fn: () => T, options?: CaptureOptions): CaptureResult<T>;
|
|
563
627
|
|
|
564
628
|
/**
|
|
565
|
-
*
|
|
566
|
-
* through the `console` methods
|
|
567
|
-
* {@link
|
|
629
|
+
* Creates the default {@link SinkInterface} — a console sink that routes by level and writes
|
|
630
|
+
* through the `console` methods snapshotted at creation. The default output target behind the
|
|
631
|
+
* {@link import('./loggers/Logger.js').Logger}.
|
|
568
632
|
*
|
|
569
633
|
* @returns A console {@link SinkInterface}
|
|
570
634
|
*
|
|
571
635
|
* @remarks
|
|
572
636
|
* - **Snapshotted — no capture loop.** It captures `console.log` / `console.warn` /
|
|
573
|
-
* `console.error`
|
|
574
|
-
* `Capture`
|
|
637
|
+
* `console.error` at call time and writes through those references. So when a later
|
|
638
|
+
* `Capture` patches `console.*`, this sink still reaches the real streams — the
|
|
575
639
|
* writer and the capturer never feed each other (the no-capture-loop principle). Create
|
|
576
|
-
* the sink (or the logger)
|
|
640
|
+
* the sink (or the logger) before installing a capture for this to hold.
|
|
577
641
|
* - **Routes by level.** `error` → the snapshotted `console.error`, `warn` →
|
|
578
642
|
* `console.warn`, every other level → `console.log`. The `level` is supplied by the
|
|
579
|
-
* logger; an omitted `level` goes to `console.log`.
|
|
643
|
+
* logger; an omitted `level` goes to `console.log`. The decision is
|
|
644
|
+
* {@link import('./helpers.js').selectWriter}'s, shared with the browser and server sinks.
|
|
580
645
|
*
|
|
581
646
|
* @example
|
|
582
647
|
* ```ts
|
|
583
|
-
* import { createConsoleSink } from '@
|
|
648
|
+
* import { createConsoleSink } from '@orkestrel/console'
|
|
584
649
|
*
|
|
585
|
-
* const sink = createConsoleSink() // snapshots console.*
|
|
650
|
+
* const sink = createConsoleSink() // snapshots console.* at construction
|
|
586
651
|
* sink.write('boom', 'error') // → the real console.error, even after a later console patch
|
|
587
652
|
* ```
|
|
588
653
|
*/
|
|
589
654
|
export declare function createConsoleSink(): SinkInterface;
|
|
590
655
|
|
|
591
656
|
/**
|
|
592
|
-
*
|
|
593
|
-
*
|
|
594
|
-
* {@link import('./types.js').LogRecord}, gates it by severity, retains a bounded tail,
|
|
595
|
-
* ALWAYS emits it on `entry` (the transport seam), and — unless `silent` — writes a styled
|
|
596
|
-
* line to its sink.
|
|
597
|
-
*
|
|
598
|
-
* @param options - See {@link LoggerOptions}
|
|
599
|
-
* @returns A {@link LoggerInterface}
|
|
600
|
-
*
|
|
601
|
-
* @remarks
|
|
602
|
-
* - **Record + event = transport (§13).** Subscribe `logger.emitter.on('entry', …)` to tee
|
|
603
|
-
* records to a file / JSON / remote transport; the event fires for every accepted record,
|
|
604
|
-
* even when `silent` (silence suppresses only the SINK WRITE).
|
|
605
|
-
* - **Bounded retention.** `entries()` returns the recent records, capped at `options.limit`
|
|
606
|
-
* (default {@link DEFAULT_LOG_LIMIT}); never unbounded.
|
|
607
|
-
* - **Sink + styler defaults.** `options.sink` defaults to {@link createConsoleSink} (the
|
|
608
|
-
* snapshotted, level-routing console sink); `options.styler` to {@link createStyler} (ANSI).
|
|
609
|
-
* Styling is orthogonal to level — a level only chooses a label color.
|
|
610
|
-
*
|
|
611
|
-
* @example
|
|
612
|
-
* ```ts
|
|
613
|
-
* import { createLogger } from '@src/core'
|
|
614
|
-
*
|
|
615
|
-
* const logger = createLogger({ name: 'http', level: 'info' })
|
|
616
|
-
* logger.info('request', { method: 'GET', path: '/' })
|
|
617
|
-
* logger.debug('verbose') // dropped — below the info threshold
|
|
618
|
-
* ```
|
|
619
|
-
*/
|
|
620
|
-
export declare function createLogger(options?: LoggerOptions): LoggerInterface;
|
|
621
|
-
|
|
622
|
-
/**
|
|
623
|
-
* Create an event-free {@link LoggerManagerInterface} — a §9 registry of named loggers plus
|
|
624
|
-
* a convenience fan-out. It mints + stores {@link LoggerInterface}s keyed by name (its
|
|
625
|
-
* defaults flowing into each), looks them up, removes them, and broadcasts a one-off log to
|
|
626
|
-
* every registered logger.
|
|
627
|
-
*
|
|
628
|
-
* @param options - See {@link LoggerManagerOptions}
|
|
629
|
-
* @returns A {@link LoggerManagerInterface}
|
|
657
|
+
* Creates the fluent, composable {@link StylerInterface} — ANSI by default, retargeted by a
|
|
658
|
+
* `renderer` and stripped of color by `enabled: false`.
|
|
630
659
|
*
|
|
631
660
|
* @remarks
|
|
632
|
-
*
|
|
633
|
-
*
|
|
634
|
-
*
|
|
635
|
-
* observable `emitter`) — it is a pure registry.
|
|
636
|
-
*
|
|
637
|
-
* @example
|
|
638
|
-
* ```ts
|
|
639
|
-
* import { createLoggerManager } from '@src/core'
|
|
640
|
-
*
|
|
641
|
-
* const loggers = createLoggerManager({ level: 'warn' })
|
|
642
|
-
* loggers.register('http')
|
|
643
|
-
* loggers.register('db', { level: 'debug' }) // overrides the default
|
|
644
|
-
* loggers.warn('slow', { ms: 900 }) // fans out to both
|
|
645
|
-
* ```
|
|
646
|
-
*/
|
|
647
|
-
export declare function createLoggerManager(options?: LoggerManagerOptions): LoggerManagerInterface;
|
|
648
|
-
|
|
649
|
-
/**
|
|
650
|
-
* Create an update-driven, observable {@link ProgressInterface} — a live progress bar. Each
|
|
651
|
-
* `update(current)` recomputes the bar, writes `\r` + bar to its sink, and emits `{ current, total }`
|
|
652
|
-
* on `update`; `complete` / `failure` commit a final line. The leading `\r` is the sink's to redraw on —
|
|
653
|
-
* a TTY sink (C-g) overwrites, a plain sink (C-f) degrades to a fresh line. NO self-timer — the caller
|
|
654
|
-
* drives the bar.
|
|
655
|
-
*
|
|
656
|
-
* @param options - See {@link ProgressOptions} (`total` is required)
|
|
657
|
-
* @returns A {@link ProgressInterface}
|
|
658
|
-
*
|
|
659
|
-
* @remarks
|
|
660
|
-
* - **Universal + update-driven.** Built on the one styler + the one sink (no `node:*`, no
|
|
661
|
-
* `process.stdout`); progress advances only when the caller reports it. `current` is always clamped
|
|
662
|
-
* to `[0, total]`. `options.sink` defaults to {@link createConsoleSink}, `options.styler` to
|
|
663
|
-
* {@link createStyler} (ANSI).
|
|
664
|
-
* - **Observable (§13).** Subscribe `progress.emitter.on('update', …)` to mirror progress without a
|
|
665
|
-
* terminal; `complete` signals a successful finish.
|
|
666
|
-
*
|
|
667
|
-
* @example
|
|
668
|
-
* ```ts
|
|
669
|
-
* import { createProgress } from '@src/core'
|
|
670
|
-
*
|
|
671
|
-
* const progress = createProgress({ total: 100, message: 'downloading' })
|
|
672
|
-
* progress.update(40)
|
|
673
|
-
* progress.complete('done')
|
|
674
|
-
* ```
|
|
675
|
-
*/
|
|
676
|
-
export declare function createProgress(options: ProgressOptions): ProgressInterface;
|
|
677
|
-
|
|
678
|
-
/**
|
|
679
|
-
* Create a lean, event-free {@link ReporterInterface} — the entry point into narrative
|
|
680
|
-
* reporting. Each verb (`section` / `step` / `timing` / `status` / `table` / `tree` / `box` /
|
|
681
|
-
* `line` / `blank`) formats through the shared styler + the pure layout renderers and writes to
|
|
682
|
-
* the sink — human / build-run narration over the SAME substrate the logger uses.
|
|
683
|
-
*
|
|
684
|
-
* @param options - See {@link ReporterOptions}
|
|
685
|
-
* @returns A {@link ReporterInterface}
|
|
686
|
-
*
|
|
687
|
-
* @remarks
|
|
688
|
-
* - **One styler, one sink.** `options.styler` defaults to {@link createStyler} (ANSI) and
|
|
689
|
-
* `options.sink` to {@link createConsoleSink} (the snapshotted, level-routing console sink) —
|
|
690
|
-
* no second colorizer. A `status('error', …)` routes to the sink's error stream.
|
|
691
|
-
* - **Width-aware.** `options.width` (default {@link DEFAULT_WIDTH}) sizes `section` and a
|
|
692
|
-
* `box` with no explicit width; the renderers align on VISIBLE width so styled content keeps
|
|
693
|
-
* its columns.
|
|
694
|
-
* - **Event-free (§13).** The reporter carries no emitter — a pure formatting front-end, like
|
|
695
|
-
* the renderers and `Scheduler`. Reach for a {@link createLogger} when you need observable,
|
|
696
|
-
* leveled, transportable records instead.
|
|
697
|
-
*
|
|
698
|
-
* @example
|
|
699
|
-
* ```ts
|
|
700
|
-
* import { createReporter } from '@src/core'
|
|
701
|
-
*
|
|
702
|
-
* const reporter = createReporter()
|
|
703
|
-
* reporter.section('Build')
|
|
704
|
-
* reporter.step('bundling', { index: 2, total: 5 }) // [2/5] bundling
|
|
705
|
-
* reporter.status('success', 'built in 1.2s') // ✔ built in 1.2s
|
|
706
|
-
*
|
|
707
|
-
* // Disable color (a non-TTY) — every line is plain.
|
|
708
|
-
* const plain = createReporter({ styler: createStyler({ enabled: false }) })
|
|
709
|
-
* ```
|
|
710
|
-
*/
|
|
711
|
-
export declare function createReporter(options?: ReporterOptions): ReporterInterface;
|
|
712
|
-
|
|
713
|
-
/**
|
|
714
|
-
* Create a self-driving, observable {@link SpinnerInterface} — a live activity spinner. `start()`
|
|
715
|
-
* arms a periodic timer that advances a glyph cycle, writing each `\r` + frame line to its sink and
|
|
716
|
-
* emitting it on `frame`; `success` / `failure` commit a final `✔` / `✖` line. The leading `\r` is the
|
|
717
|
-
* sink's to redraw on — a TTY sink (C-g) overwrites for a smooth animation, a plain sink (C-f)
|
|
718
|
-
* degrades to a fresh line.
|
|
719
|
-
*
|
|
720
|
-
* @param options - See {@link SpinnerOptions}
|
|
721
|
-
* @returns A {@link SpinnerInterface} (inactive until `start()`)
|
|
722
|
-
*
|
|
723
|
-
* @remarks
|
|
724
|
-
* - **Universal + leak-free.** Built on `setInterval` + the one styler + the one sink (no `node:*`,
|
|
725
|
-
* no `process.stdout`); the timer is ALWAYS cleared on `success` / `failure` / `stop` / `destroy`, so
|
|
726
|
-
* it never leaks. `start()` is idempotent (no second timer while `active`).
|
|
727
|
-
* - **Observable (§13).** Subscribe `spinner.emitter.on('frame', …)` to mirror the animation without
|
|
728
|
-
* a terminal; `start` / `stop` bracket the timer lifecycle. `options.sink` defaults to
|
|
729
|
-
* {@link createConsoleSink}, `options.styler` to {@link createStyler} (ANSI).
|
|
730
|
-
*
|
|
731
|
-
* @example
|
|
732
|
-
* ```ts
|
|
733
|
-
* import { createSpinner } from '@src/core'
|
|
734
|
-
*
|
|
735
|
-
* const spinner = createSpinner({ message: 'building' })
|
|
736
|
-
* spinner.start()
|
|
737
|
-
* spinner.success('built in 1.2s') // ✔ built in 1.2s — timer cleared, line committed
|
|
738
|
-
* ```
|
|
739
|
-
*/
|
|
740
|
-
export declare function createSpinner(options?: SpinnerOptions): SpinnerInterface;
|
|
741
|
-
|
|
742
|
-
/**
|
|
743
|
-
* Create the fluent, composable {@link StylerInterface} — the consumer-facing styling
|
|
744
|
-
* API. It builds a {@link import('./types.js').Style} under the hood and renders it
|
|
745
|
-
* through a {@link RendererInterface} (the ANSI default), so `styler.red.bold('hi')`
|
|
746
|
-
* yields styled text. Chains are immutable, so a base styler is freely reusable.
|
|
661
|
+
* It builds a {@link import('./types.js').Style} under the hood and renders it through a
|
|
662
|
+
* {@link import('./types.js').RendererInterface}, so `styler.red.bold('hi')` yields styled text.
|
|
663
|
+
* Chains are immutable, so a base styler is freely reusable.
|
|
747
664
|
*
|
|
748
665
|
* @param options - See {@link StylerOptions}
|
|
749
666
|
* @returns A base {@link StylerInterface}
|
|
750
667
|
*
|
|
751
668
|
* @remarks
|
|
752
669
|
* - `options.renderer` swaps the output target without touching the style model — pass a
|
|
753
|
-
* browser `%c` / CSS renderer (the
|
|
670
|
+
* browser `%c` / CSS renderer (the browser branch) to retarget; defaults to the ANSI
|
|
754
671
|
* renderer (the cross-environment default).
|
|
755
672
|
* - `options.enabled` is the no-color switch: when `false`, the styler returns text
|
|
756
|
-
*
|
|
673
|
+
* verbatim (for a non-TTY, `NO_COLOR`, or piped output); defaults to `true`.
|
|
757
674
|
*
|
|
758
675
|
* @example
|
|
759
676
|
* ```ts
|
|
760
|
-
* import { createStyler } from '@
|
|
677
|
+
* import { createStyler } from '@orkestrel/console'
|
|
761
678
|
*
|
|
762
679
|
* const style = createStyler()
|
|
763
680
|
* style.red.bold('error') // bold red
|
|
@@ -771,7 +688,7 @@ export declare function createSpinner(options?: SpinnerOptions): SpinnerInterfac
|
|
|
771
688
|
export declare function createStyler(options?: StylerOptions): StylerInterface;
|
|
772
689
|
|
|
773
690
|
/**
|
|
774
|
-
*
|
|
691
|
+
* Creates a {@link Theme} — the app-wide semantic style vocabulary, merged role by role over
|
|
775
692
|
* {@link DEFAULT_THEME}. Hand one theme to a logger / reporter / spinner / progress and every
|
|
776
693
|
* surface speaks it; omit `options` for the defaults.
|
|
777
694
|
*
|
|
@@ -779,8 +696,8 @@ export declare function createStyler(options?: StylerOptions): StylerInterface;
|
|
|
779
696
|
* @returns A frozen {@link Theme}
|
|
780
697
|
*
|
|
781
698
|
* @remarks
|
|
782
|
-
* - **Merges per
|
|
783
|
-
* `statuses` merge per
|
|
699
|
+
* - **Merges per role, not per theme.** An omitted role keeps its default, and `levels` /
|
|
700
|
+
* `statuses` merge per entry — `{ levels: { warn: … } }` restyles the `warn` label and
|
|
784
701
|
* leaves `debug` / `info` / `error` untouched.
|
|
785
702
|
* - **Frozen and shareable.** The factory snapshots and deep-freezes every style leaf. The
|
|
786
703
|
* returned theme and its `levels` / `statuses` records are frozen. Each status record is also
|
|
@@ -788,7 +705,7 @@ export declare function createStyler(options?: StylerOptions): StylerInterface;
|
|
|
788
705
|
*
|
|
789
706
|
* @example
|
|
790
707
|
* ```ts
|
|
791
|
-
* import { createStyler, createTheme } from '@
|
|
708
|
+
* import { createStyler, createTheme } from '@orkestrel/console'
|
|
792
709
|
*
|
|
793
710
|
* const styler = createStyler()
|
|
794
711
|
* const theme = createTheme({
|
|
@@ -800,64 +717,70 @@ export declare function createStyler(options?: StylerOptions): StylerInterface;
|
|
|
800
717
|
*/
|
|
801
718
|
export declare function createTheme(options?: ThemeOptions): Theme;
|
|
802
719
|
|
|
803
|
-
/**
|
|
720
|
+
/** Holds the Control Sequence Introducer (`ESC[`) that opens every SGR sequence. */
|
|
804
721
|
export declare const CSI: string;
|
|
805
722
|
|
|
806
|
-
/**
|
|
723
|
+
/** Sets the default cell {@link Alignment} a {@link import('./types.js').ColumnSpec} uses when none is given — `left`. */
|
|
807
724
|
export declare const DEFAULT_ALIGN: Alignment;
|
|
808
725
|
|
|
809
726
|
/**
|
|
810
|
-
*
|
|
811
|
-
* import('./helpers.js').renderBar} fills
|
|
812
|
-
* its bar to
|
|
813
|
-
*
|
|
814
|
-
*
|
|
727
|
+
* Sets the default visible cell count of a progress-bar track — the glyph run
|
|
728
|
+
* {@link import('./helpers.js').renderBar} fills, and the width a
|
|
729
|
+
* {@link import('./types.js').ProgressInterface} sizes its bar to. `30` cells.
|
|
730
|
+
*
|
|
731
|
+
* @remarks
|
|
732
|
+
* Thirty cells is a compact, terminal-friendly default; a consumer overrides it through
|
|
733
|
+
* `options.width`. It is distinct from {@link DEFAULT_WIDTH} (the renderers' 80-column line
|
|
734
|
+
* width) — a bar track is one inline element, not a full-width rule.
|
|
815
735
|
*/
|
|
816
736
|
export declare const DEFAULT_BAR_WIDTH = 30;
|
|
817
737
|
|
|
818
|
-
/**
|
|
738
|
+
/** Sets the default {@link BorderStyle} the box / table renderers frame with when none is given — `single`. */
|
|
819
739
|
export declare const DEFAULT_BORDER: BorderStyle;
|
|
820
740
|
|
|
821
741
|
/**
|
|
822
|
-
*
|
|
823
|
-
*
|
|
824
|
-
*
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
* The default bounded-buffer cap for a {@link import('./types.js').CaptureInterface} — at most this
|
|
830
|
-
* many recent {@link CapturedMessage}s are retained per buffer (the total buffer AND each by-level
|
|
831
|
-
* bucket; oldest dropped first). Capture retention is ALWAYS bounded so a long-running capture can
|
|
832
|
-
* never grow without bound (the same retention precedent as {@link DEFAULT_LOG_LIMIT}); a consumer
|
|
833
|
-
* overrides it via `options.limit`.
|
|
742
|
+
* Sets the default bounded-buffer cap for a {@link import('./types.js').CaptureInterface} — `1000`,
|
|
743
|
+
* so at most that many recent {@link CapturedMessage}s are retained per buffer (the total buffer
|
|
744
|
+
* and each by-level bucket; oldest dropped first) and retention is always bounded.
|
|
745
|
+
*
|
|
746
|
+
* @remarks
|
|
747
|
+
* A long-running capture can never grow without bound (the same retention precedent as
|
|
748
|
+
* {@link DEFAULT_LOG_LIMIT}); a consumer overrides the cap through `options.limit`.
|
|
834
749
|
*/
|
|
835
750
|
export declare const DEFAULT_CAPTURE_LIMIT = 1000;
|
|
836
751
|
|
|
837
|
-
/**
|
|
752
|
+
/** Sets the default {@link LogLevel} threshold a logger gates at when none is supplied — `info`. */
|
|
838
753
|
export declare const DEFAULT_LOG_LEVEL: LogLevel;
|
|
839
754
|
|
|
840
755
|
/**
|
|
841
|
-
*
|
|
842
|
-
* most
|
|
843
|
-
*
|
|
756
|
+
* Sets the default bounded-retention cap for a {@link import('./types.js').LoggerInterface} —
|
|
757
|
+
* `1000`, so at most that many recent records are kept and retention is always bounded.
|
|
758
|
+
*
|
|
759
|
+
* @remarks
|
|
760
|
+
* The oldest record is dropped after the cap is reached; a consumer overrides the cap through
|
|
761
|
+
* `options.limit`.
|
|
844
762
|
*/
|
|
845
763
|
export declare const DEFAULT_LOG_LIMIT = 1000;
|
|
846
764
|
|
|
847
|
-
/**
|
|
765
|
+
/** Sets the default horizontal padding inside a box's edges ({@link import('./helpers.js').renderBox}) — one cell. */
|
|
848
766
|
export declare const DEFAULT_PADDING = 1;
|
|
849
767
|
|
|
850
768
|
/**
|
|
851
|
-
*
|
|
852
|
-
*
|
|
853
|
-
*
|
|
854
|
-
*
|
|
769
|
+
* Sets the default timer period between a {@link import('./types.js').SpinnerInterface}'s frames —
|
|
770
|
+
* the `setInterval` interval `start()` arms, `80` ms (≈12.5 frames/second).
|
|
771
|
+
*
|
|
772
|
+
* @remarks
|
|
773
|
+
* That is the conventional spinner cadence: fast enough to read as motion, slow enough not to
|
|
774
|
+
* thrash a terminal. A consumer overrides it through `options.interval`.
|
|
855
775
|
*/
|
|
856
776
|
export declare const DEFAULT_SPINNER_INTERVAL = 80;
|
|
857
777
|
|
|
858
778
|
/**
|
|
859
|
-
*
|
|
860
|
-
*
|
|
779
|
+
* Holds the default {@link Theme} — every role bound to its default {@link Style}, assembled from
|
|
780
|
+
* {@link LEVEL_COLORS}, {@link STATUS_ICONS}, and {@link STATUS_COLORS} and deeply frozen.
|
|
781
|
+
*
|
|
782
|
+
* @remarks
|
|
783
|
+
* It is the base {@link import('./factories.js').createTheme} merges over, and the theme every
|
|
861
784
|
* entity uses when none is supplied.
|
|
862
785
|
*
|
|
863
786
|
* @remarks
|
|
@@ -871,34 +794,34 @@ export declare const DEFAULT_SPINNER_INTERVAL = 80;
|
|
|
871
794
|
export declare const DEFAULT_THEME: Theme;
|
|
872
795
|
|
|
873
796
|
/**
|
|
874
|
-
*
|
|
797
|
+
* Sets the default visible column width for the width-aware renderers — the separator rule and a
|
|
875
798
|
* {@link import('./helpers.js').renderBox} with no explicit `width`, and the reporter's
|
|
876
|
-
* `section` rule. A sane terminal default (80 columns); a caller overrides it per-call or
|
|
877
|
-
* {@link import('./types.js').ReporterOptions}
|
|
799
|
+
* `section` rule. A sane terminal default (80 columns); a caller overrides it per-call or through
|
|
800
|
+
* {@link import('./types.js').ReporterOptions.width}.
|
|
878
801
|
*/
|
|
879
802
|
export declare const DEFAULT_WIDTH = 80;
|
|
880
803
|
|
|
881
804
|
/**
|
|
882
|
-
*
|
|
805
|
+
* Holds the empty {@link Style} — no foreground, no background, no attributes — frozen. The
|
|
883
806
|
* neutral starting point a base styler builds from, and what a renderer passes through
|
|
884
807
|
* unchanged (it carries no codes). Deeply frozen, so it is safe to share as the base.
|
|
885
808
|
*/
|
|
886
809
|
export declare const EMPTY_STYLE: Style;
|
|
887
810
|
|
|
888
811
|
/**
|
|
889
|
-
*
|
|
812
|
+
* Holds the escape control character (`U+001B`) that begins every ANSI escape sequence. Built
|
|
890
813
|
* with `String.fromCharCode` so no raw control character appears in source.
|
|
891
814
|
*/
|
|
892
815
|
export declare const ESC: string;
|
|
893
816
|
|
|
894
817
|
/**
|
|
895
|
-
*
|
|
818
|
+
* Maps each {@link Color} to its SGR foreground parameter — the 8 base colors at 30–37 and their
|
|
896
819
|
* bright variants at 90–97. `default` is intentionally absent (it emits no code).
|
|
897
820
|
*/
|
|
898
821
|
export declare const FOREGROUND_CODES: Readonly<Record<Exclude<Color, 'default'>, number>>;
|
|
899
822
|
|
|
900
823
|
/**
|
|
901
|
-
*
|
|
824
|
+
* Stringifies a captured `console.*` argument list into one line — the text of a {@link
|
|
902
825
|
* import('./types.js').CapturedMessage}. Each argument is rendered by {@link stringifyValue} and
|
|
903
826
|
* the parts are space-joined, mirroring how a console concatenates its arguments.
|
|
904
827
|
*
|
|
@@ -919,7 +842,7 @@ export declare const FOREGROUND_CODES: Readonly<Record<Exclude<Color, 'default'>
|
|
|
919
842
|
export declare function formatArgs(args: readonly unknown[]): string;
|
|
920
843
|
|
|
921
844
|
/**
|
|
922
|
-
*
|
|
845
|
+
* Formats a millisecond duration as a compact human string — `…ms` below one second, `…s`
|
|
923
846
|
* (seconds to 2 decimal places) at or above one second. The timing rendering behind
|
|
924
847
|
* {@link import('./types.js').ReporterInterface.timing}.
|
|
925
848
|
*
|
|
@@ -933,7 +856,7 @@ export declare function formatArgs(args: readonly unknown[]): string;
|
|
|
933
856
|
export declare function formatDuration(ms: number): string;
|
|
934
857
|
|
|
935
858
|
/**
|
|
936
|
-
*
|
|
859
|
+
* Formats a {@link LogRecord} into a single styled line — the default human line layout a
|
|
937
860
|
* {@link import('./types.js').LoggerInterface} writes to its sink.
|
|
938
861
|
*
|
|
939
862
|
* @remarks
|
|
@@ -942,7 +865,7 @@ export declare function formatDuration(ms: number): string;
|
|
|
942
865
|
* the originating logger's `name` in brackets (omitted when absent), the message, and the
|
|
943
866
|
* structured `data` appended as compact JSON (omitted when absent / empty). Coloring flows
|
|
944
867
|
* through the injected `styler`, so a disabled styler yields a plain line and a browser
|
|
945
|
-
* `%c` styler
|
|
868
|
+
* `%c` styler retargets it — the layout never changes. Pure: same record + styler →
|
|
946
869
|
* same line.
|
|
947
870
|
*
|
|
948
871
|
* @param record - The {@link LogRecord} to render
|
|
@@ -963,10 +886,10 @@ export declare function formatDuration(ms: number): string;
|
|
|
963
886
|
export declare function formatRecord(record: LogRecord, styler: StylerInterface, theme: Theme): string;
|
|
964
887
|
|
|
965
888
|
/**
|
|
966
|
-
*
|
|
889
|
+
* Formats a {@link LogRecord}'s `time` (epoch milliseconds) as an ISO-8601 timestamp string.
|
|
967
890
|
*
|
|
968
891
|
* @remarks
|
|
969
|
-
* Deterministic and serializable — `new Date(time).toISOString()`,
|
|
892
|
+
* Deterministic and serializable — `new Date(time).toISOString()`, for example
|
|
970
893
|
* `1716900000000 → '2024-05-28T12:40:00.000Z'`. The timestamp portion of the formatted log
|
|
971
894
|
* line; kept a pure helper so the line layout and the logger stay decoupled.
|
|
972
895
|
*
|
|
@@ -976,7 +899,8 @@ export declare function formatRecord(record: LogRecord, styler: StylerInterface,
|
|
|
976
899
|
export declare function formatTime(time: number): string;
|
|
977
900
|
|
|
978
901
|
/**
|
|
979
|
-
*
|
|
902
|
+
* Snapshots and deeply freezes one {@link Style} value, including an independent frozen copy of
|
|
903
|
+
* its `attributes`.
|
|
980
904
|
*
|
|
981
905
|
* @param style - The caller-owned style to snapshot
|
|
982
906
|
* @returns A frozen style record with an independently frozen attributes list
|
|
@@ -993,10 +917,10 @@ export declare function formatTime(time: number): string;
|
|
|
993
917
|
export declare function freezeStyle(style: Style): Style;
|
|
994
918
|
|
|
995
919
|
/**
|
|
996
|
-
*
|
|
920
|
+
* Narrows an unknown caught value to a {@link ConsoleError} — the guard a `catch` branches on.
|
|
997
921
|
*
|
|
998
922
|
* @param value - The value to test (typically a `catch` binding)
|
|
999
|
-
* @returns
|
|
923
|
+
* @returns True if `value` is a {@link ConsoleError}; false otherwise
|
|
1000
924
|
*
|
|
1001
925
|
* @example
|
|
1002
926
|
* ```ts
|
|
@@ -1010,8 +934,8 @@ export declare function freezeStyle(style: Style): Style;
|
|
|
1010
934
|
export declare function isConsoleError(value: unknown): value is ConsoleError;
|
|
1011
935
|
|
|
1012
936
|
/**
|
|
1013
|
-
*
|
|
1014
|
-
* is a styling choice
|
|
937
|
+
* Maps each {@link LogLevel} to its default label {@link Color} — the level's visual treatment, which
|
|
938
|
+
* is a styling choice orthogonal to the level itself (never a separate pseudo-level). The
|
|
1015
939
|
* logger colors the level label through its styler with these; swapping a color never
|
|
1016
940
|
* changes leveling. `debug` is cyan, `info` blue, `warn` yellow, `error` red.
|
|
1017
941
|
*
|
|
@@ -1022,32 +946,33 @@ export declare function isConsoleError(value: unknown): value is ConsoleError;
|
|
|
1022
946
|
export declare const LEVEL_COLORS: Readonly<Record<LogLevel, Exclude<Color, 'default'>>>;
|
|
1023
947
|
|
|
1024
948
|
/**
|
|
1025
|
-
*
|
|
949
|
+
* Maps each {@link LogLevel} to its numeric severity — the ascending order the level gate compares
|
|
1026
950
|
* through (`debug` 0 < `info` 1 < `warn` 2 < `error` 3). A record is kept when its level's
|
|
1027
951
|
* severity is at or above the logger's threshold. The source of truth for level ordering.
|
|
1028
952
|
*/
|
|
1029
953
|
export declare const LEVEL_SEVERITY: Readonly<Record<LogLevel, number>>;
|
|
1030
954
|
|
|
1031
955
|
/**
|
|
1032
|
-
*
|
|
956
|
+
* Lists every {@link LogLevel}, in ascending severity order — the levels a logger exposes as
|
|
1033
957
|
* methods and the manager fans out to. The source of truth for the level axis (drives
|
|
1034
958
|
* exhaustive tests); aligned with {@link LEVEL_SEVERITY}.
|
|
1035
959
|
*/
|
|
1036
|
-
export declare const
|
|
960
|
+
export declare const LOG_LEVELS: readonly LogLevel[];
|
|
1037
961
|
|
|
1038
962
|
/**
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
963
|
+
* Represents the line layout a logger writes — `(record, styler, theme) => string`, one
|
|
964
|
+
* {@link LogRecord} plus the styling substrate in and one finished line out.
|
|
965
|
+
* {@link import('./helpers.js').formatRecord} is the default.
|
|
1041
966
|
*
|
|
1042
967
|
* @param record - The frozen record to lay out
|
|
1043
968
|
* @param styler - The logger's {@link StylerInterface} — color through it (and through
|
|
1044
969
|
* {@link StylerInterface.render} for a {@link Theme} role) so a disabled styler yields a
|
|
1045
970
|
* plain line with no second code path
|
|
1046
971
|
* @param theme - The logger's {@link Theme} — the level label style, the chrome surround
|
|
1047
|
-
* @returns The line to write,
|
|
972
|
+
* @returns The line to write, without a trailing terminator (the sink's target supplies it)
|
|
1048
973
|
*
|
|
1049
974
|
* @remarks
|
|
1050
|
-
* The formatter owns the
|
|
975
|
+
* The formatter owns the line; the `entry` event owns the record. A transport that wants
|
|
1051
976
|
* structure rides the event rather than parsing a line back out of this. A formatter throw
|
|
1052
977
|
* propagates to the caller of `logger.info` and prevents that line's write, so keep it total.
|
|
1053
978
|
* A manager fans out sequentially; a formatter throw stops the remaining loggers for that call.
|
|
@@ -1055,25 +980,25 @@ export declare const LEVELS: readonly LogLevel[];
|
|
|
1055
980
|
export declare type LogFormatFunction = (record: LogRecord, styler: StylerInterface, theme: Theme) => string;
|
|
1056
981
|
|
|
1057
982
|
/**
|
|
1058
|
-
*
|
|
983
|
+
* Implements an observable, leveled logger — the entry point into the structured-logging
|
|
1059
984
|
* pipeline. Each `debug` / `info` / `warn` / `error` call builds a frozen {@link LogRecord},
|
|
1060
|
-
* gates it by severity, retains a bounded tail of accepted records,
|
|
985
|
+
* gates it by severity, retains a bounded tail of accepted records, always emits it on
|
|
1061
986
|
* `entry` (the transport seam), and — unless `silent` — formats it into a styled line and
|
|
1062
987
|
* writes it to its {@link SinkInterface}.
|
|
1063
988
|
*
|
|
1064
989
|
* @remarks
|
|
1065
|
-
* - **Record + event = transport
|
|
1066
|
-
* `entry`
|
|
990
|
+
* - **Record + event = transport.** An accepted record is frozen and emitted on
|
|
991
|
+
* `entry` before anything else observable — every file / JSON / remote transport rides
|
|
1067
992
|
* `emitter.on('entry')`. The event fires even when `silent`: silence suppresses only the
|
|
1068
|
-
*
|
|
993
|
+
* sink write, never the record or the event, so transports keep flowing.
|
|
1069
994
|
* - **Leveled gate.** A record whose {@link LogLevel} is below the logger's `level` threshold
|
|
1070
|
-
* is dropped
|
|
995
|
+
* is dropped entirely — no record built past the level check, no event, no retention, no
|
|
1071
996
|
* write (see {@link meetsLevel}).
|
|
1072
997
|
* - **Bounded retention.** Accepted records accrue in a ring capped at `limit` (default
|
|
1073
998
|
* {@link DEFAULT_LOG_LIMIT}); the oldest is dropped when full. `entries()` returns a copy,
|
|
1074
|
-
* oldest first; `clear()` empties it.
|
|
999
|
+
* oldest first; `clear()` empties it. Never unbounded — retention is capped at `limit`.
|
|
1075
1000
|
* - **Styled write, orthogonal to level.** The line ({@link formatRecord}) is colored through
|
|
1076
|
-
* the injected `styler` (the ANSI default, or a browser `%c` styler
|
|
1001
|
+
* the injected `styler` (the ANSI default, or a browser `%c` styler) — a level only
|
|
1077
1002
|
* chooses a label color; styling is not a level. A disabled styler yields a plain line.
|
|
1078
1003
|
* - **Snapshotted sink.** The default {@link createConsoleSink} writes to the `console`
|
|
1079
1004
|
* methods captured at creation, so a later `Capture` patching `console` can't loop the
|
|
@@ -1104,25 +1029,26 @@ export declare class Logger implements LoggerInterface {
|
|
|
1104
1029
|
}
|
|
1105
1030
|
|
|
1106
1031
|
/**
|
|
1107
|
-
*
|
|
1032
|
+
* Declares the observable events a {@link LoggerInterface} emits — `entry(record)` for every
|
|
1033
|
+
* accepted record, the transport seam.
|
|
1108
1034
|
*
|
|
1109
1035
|
* @remarks
|
|
1110
|
-
* `entry`
|
|
1111
|
-
*
|
|
1112
|
-
*
|
|
1113
|
-
* the emitter's
|
|
1036
|
+
* `entry` carries the frozen {@link LogRecord} and fires even when the logger is
|
|
1037
|
+
* `silent` (silence suppresses only the
|
|
1038
|
+
* sink write, never the event, so transports keep receiving records). Listener isolation is
|
|
1039
|
+
* the emitter's: a listener throw routes to the emitter's `error` handler, never onto
|
|
1114
1040
|
* this map — so a buggy transport can never perturb logging.
|
|
1115
1041
|
*
|
|
1116
|
-
* Declared as a `type` alias (not `interface extends EventMap
|
|
1042
|
+
* Declared as a `type` alias (not `interface extends EventMap`): a type-literal
|
|
1117
1043
|
* satisfies the `EventMap` constraint structurally, whereas an interface lacks the index signature.
|
|
1118
1044
|
*/
|
|
1119
1045
|
export declare type LoggerEventMap = {
|
|
1120
|
-
/**
|
|
1046
|
+
/** Fires after a record was logged (passed the level gate) — the frozen {@link LogRecord}. */
|
|
1121
1047
|
readonly entry: readonly [record: LogRecord];
|
|
1122
1048
|
};
|
|
1123
1049
|
|
|
1124
1050
|
/**
|
|
1125
|
-
*
|
|
1051
|
+
* Declares an observable, leveled logger — builds a frozen {@link LogRecord} per call, gates it by
|
|
1126
1052
|
* severity, retains a bounded tail, emits it on `entry`, and (unless silent) writes a
|
|
1127
1053
|
* styled line to its {@link SinkInterface}.
|
|
1128
1054
|
*
|
|
@@ -1130,7 +1056,7 @@ export declare type LoggerEventMap = {
|
|
|
1130
1056
|
* - **Leveled.** Each of `debug` / `info` / `warn` / `error` builds a record at that
|
|
1131
1057
|
* {@link LogLevel}; a record below the logger's `level` threshold is dropped entirely (no
|
|
1132
1058
|
* event, no retention, no write).
|
|
1133
|
-
* - **Transport seam
|
|
1059
|
+
* - **Transport seam.** An accepted record always fires `entry` (even when `silent`),
|
|
1134
1060
|
* carrying the frozen {@link LogRecord} — the hook every file / JSON / remote transport rides.
|
|
1135
1061
|
* - **Bounded retention.** `entries()` returns the recent records, capped at `limit` (oldest
|
|
1136
1062
|
* dropped first) — never an unbounded buffer. `clear()` empties it.
|
|
@@ -1143,39 +1069,40 @@ export declare interface LoggerInterface {
|
|
|
1143
1069
|
readonly emitter: EmitterInterface<LoggerEventMap>;
|
|
1144
1070
|
readonly level: LogLevel;
|
|
1145
1071
|
readonly name?: string;
|
|
1146
|
-
/**
|
|
1072
|
+
/** Logs at `debug` — dropped unless the logger's `level` is `debug`. */
|
|
1147
1073
|
debug(message: string, data?: Record<string, unknown>): void;
|
|
1148
|
-
/**
|
|
1074
|
+
/** Logs at `info`. */
|
|
1149
1075
|
info(message: string, data?: Record<string, unknown>): void;
|
|
1150
|
-
/**
|
|
1076
|
+
/** Logs at `warn`. */
|
|
1151
1077
|
warn(message: string, data?: Record<string, unknown>): void;
|
|
1152
|
-
/**
|
|
1078
|
+
/** Logs at `error`. */
|
|
1153
1079
|
error(message: string, data?: Record<string, unknown>): void;
|
|
1154
|
-
/**
|
|
1080
|
+
/** Returns the bounded tail of recent {@link LogRecord}s, oldest first (capped at `limit`). */
|
|
1155
1081
|
entries(): readonly LogRecord[];
|
|
1156
|
-
/**
|
|
1082
|
+
/** Drops every retained record (does not touch listeners). */
|
|
1157
1083
|
clear(): void;
|
|
1158
|
-
/**
|
|
1084
|
+
/** Tears down — clears retention and destroys the emitter. */
|
|
1159
1085
|
destroy(): void;
|
|
1160
1086
|
}
|
|
1161
1087
|
|
|
1162
1088
|
/**
|
|
1163
|
-
*
|
|
1089
|
+
* Implements an event-free registry of named {@link Logger}s plus a convenience fan-out — the
|
|
1164
1090
|
* manager over the logging layer (a registry, never observable itself; each {@link Logger}
|
|
1165
1091
|
* owns its own `emitter`).
|
|
1166
1092
|
*
|
|
1167
1093
|
* @remarks
|
|
1168
|
-
* - **Registry
|
|
1094
|
+
* - **Registry.** Loggers live in an insertion-ordered `Map` keyed by `name`.
|
|
1169
1095
|
* `register(name, options?)` mints a {@link Logger} named `name` — the manager's default
|
|
1170
1096
|
* `level` / `sink` / `styler` / `theme` / `format` / `limit` / `silent` flow in unless
|
|
1171
|
-
* `options`
|
|
1097
|
+
* `options` overrides them
|
|
1172
1098
|
* (`name` is always the registry key, so any `options.name` is ignored) — stores it (a
|
|
1173
|
-
* re-`register` of the same name
|
|
1099
|
+
* re-`register` of the same name overwrites, last write wins), and returns it. `count` is
|
|
1174
1100
|
* the map size, `logger(name)` looks one up, `loggers()` lists them in insertion order.
|
|
1175
|
-
* - **Removal
|
|
1176
|
-
* `remove(names)` drops a batch (`true`
|
|
1177
|
-
*
|
|
1178
|
-
*
|
|
1101
|
+
* - **Removal.** `remove()` clears all, `remove(name)` drops one (`true` if present),
|
|
1102
|
+
* `remove(names)` drops a batch (`true` only when every name was present; an empty list
|
|
1103
|
+
* succeeds vacuously). Every listed name is attempted whatever the result.
|
|
1104
|
+
* (Removal does not `destroy` the returned loggers — a caller still holding one keeps using
|
|
1105
|
+
* it; the manager stops tracking it.)
|
|
1179
1106
|
* - **Fan-out.** `debug` / `info` / `warn` / `error(message, data?)` forward the one call to
|
|
1180
1107
|
* every registered logger in insertion order; each gates / emits / writes per its own `level`
|
|
1181
1108
|
* and `sink`. A formatter throw is a programmer error and propagates, stopping the remaining
|
|
@@ -1209,17 +1136,18 @@ export declare class LoggerManager implements LoggerManagerInterface {
|
|
|
1209
1136
|
}
|
|
1210
1137
|
|
|
1211
1138
|
/**
|
|
1212
|
-
*
|
|
1213
|
-
*
|
|
1214
|
-
* up, removes them, and broadcasts a one-off log to
|
|
1139
|
+
* Declares an event-free registry of named {@link LoggerInterface}s plus a convenience fan-out — the
|
|
1140
|
+
* manager over the logging layer. It mints + stores loggers keyed by `name`, looks them
|
|
1141
|
+
* up, removes them, and broadcasts a one-off log to every registered logger.
|
|
1215
1142
|
*
|
|
1216
1143
|
* @remarks
|
|
1217
|
-
* - **Registry
|
|
1144
|
+
* - **Registry.** `register(name, options?)` mints a {@link LoggerInterface} (named
|
|
1218
1145
|
* `name`, the manager's defaults flowing in unless `options` overrides them), stores it
|
|
1219
|
-
* (a re-`register` of the same name
|
|
1146
|
+
* (a re-`register` of the same name overwrites — last write wins), and returns it.
|
|
1220
1147
|
* `logger(name)` looks one up; `loggers()` lists them in insertion order; `count` is the size.
|
|
1221
|
-
* - **Removal
|
|
1222
|
-
* a batch (`true` when
|
|
1148
|
+
* - **Removal.** `remove()` clears all, `remove(name)` drops one, `remove(names)` drops
|
|
1149
|
+
* a batch (`true` only when every name was present; an empty list succeeds vacuously).
|
|
1150
|
+
* Every listed name is attempted whatever the result.
|
|
1223
1151
|
* - **Fan-out.** `debug` / `info` / `warn` / `error(message, data?)` forward the call to every
|
|
1224
1152
|
* registered logger (each gates / emits / writes per its own `level` and `sink`).
|
|
1225
1153
|
* - **Event-free.** No emitter, no events — each logger carries its own observability; the
|
|
@@ -1227,32 +1155,41 @@ export declare class LoggerManager implements LoggerManagerInterface {
|
|
|
1227
1155
|
*/
|
|
1228
1156
|
export declare interface LoggerManagerInterface {
|
|
1229
1157
|
readonly count: number;
|
|
1158
|
+
/**
|
|
1159
|
+
* Mints and stores a logger named `name`, the manager's defaults flowing in — a
|
|
1160
|
+
* re-register of the same name overwrites.
|
|
1161
|
+
*/
|
|
1230
1162
|
register(name: string, options?: LoggerOptions): LoggerInterface;
|
|
1163
|
+
/** Looks one registered logger up by name. */
|
|
1231
1164
|
logger(name: string): LoggerInterface | undefined;
|
|
1165
|
+
/** Lists the registered loggers in insertion order. */
|
|
1232
1166
|
loggers(): readonly LoggerInterface[];
|
|
1233
|
-
/**
|
|
1167
|
+
/** Fans out a `debug` log to every registered logger. */
|
|
1234
1168
|
debug(message: string, data?: Record<string, unknown>): void;
|
|
1235
|
-
/**
|
|
1169
|
+
/** Fans out an `info` log to every registered logger. */
|
|
1236
1170
|
info(message: string, data?: Record<string, unknown>): void;
|
|
1237
|
-
/**
|
|
1171
|
+
/** Fans out a `warn` log to every registered logger. */
|
|
1238
1172
|
warn(message: string, data?: Record<string, unknown>): void;
|
|
1239
|
-
/**
|
|
1173
|
+
/** Fans out an `error` log to every registered logger. */
|
|
1240
1174
|
error(message: string, data?: Record<string, unknown>): void;
|
|
1175
|
+
/**
|
|
1176
|
+
* Removes every registered logger with `remove()`, one with `remove(name)`, or a batch
|
|
1177
|
+
* with `remove(names)`.
|
|
1178
|
+
*/
|
|
1241
1179
|
remove(): void;
|
|
1242
1180
|
remove(name: string): boolean;
|
|
1243
1181
|
remove(names: readonly string[]): boolean;
|
|
1244
1182
|
}
|
|
1245
1183
|
|
|
1246
1184
|
/**
|
|
1247
|
-
*
|
|
1185
|
+
* Configures the {@link import('./loggers/LoggerManager.js').LoggerManager} constructor — the
|
|
1186
|
+
* `level` / `sink` / `styler` / `theme` / `format` / `limit` / `silent` defaults flowed into every
|
|
1187
|
+
* logger it mints.
|
|
1248
1188
|
*
|
|
1249
1189
|
* @remarks
|
|
1250
|
-
* The manager is an event-free registry
|
|
1251
|
-
* registered {@link LoggerInterface} owns its observable `emitter`).
|
|
1252
|
-
*
|
|
1253
|
-
* wins: `level` (default threshold), `sink` (shared output target), `styler` (shared
|
|
1254
|
-
* coloring), `theme` (semantic styles), `format` (line layout), `limit` (retention cap),
|
|
1255
|
-
* and `silent`.
|
|
1190
|
+
* The manager is an event-free registry — it carries no emitter of its own (each
|
|
1191
|
+
* registered {@link LoggerInterface} owns its observable `emitter`). A per-`register`
|
|
1192
|
+
* override wins over any default supplied here.
|
|
1256
1193
|
*/
|
|
1257
1194
|
export declare interface LoggerManagerOptions {
|
|
1258
1195
|
readonly level?: LogLevel;
|
|
@@ -1265,13 +1202,15 @@ export declare interface LoggerManagerOptions {
|
|
|
1265
1202
|
}
|
|
1266
1203
|
|
|
1267
1204
|
/**
|
|
1268
|
-
*
|
|
1205
|
+
* Configures the {@link import('./loggers/Logger.js').Logger} constructor — the `on` / `error`
|
|
1206
|
+
* emitter keys, the `level` threshold, the logger's `name`, the `sink` / `styler` / `theme` /
|
|
1207
|
+
* `format` line substrate, the retention `limit`, and the `silent` write switch.
|
|
1269
1208
|
*
|
|
1270
1209
|
* @remarks
|
|
1271
|
-
* - `on` — the reserved {@link EmitterHooks} key
|
|
1272
|
-
* {@link LoggerEventMap}, wired at construction (
|
|
1273
|
-
* - `error` — the emitter's listener-error handler
|
|
1274
|
-
* - `level` — the severity
|
|
1210
|
+
* - `on` — the reserved {@link EmitterHooks} key: initial listeners for the
|
|
1211
|
+
* {@link LoggerEventMap}, wired at construction (for example `{ entry: (r) => sink2.write(...) }`).
|
|
1212
|
+
* - `error` — the emitter's listener-error handler; a listener throw routes here.
|
|
1213
|
+
* - `level` — the severity threshold; records below it are dropped. Defaults to `info`.
|
|
1275
1214
|
* - `name` — the logger's name, stamped onto every {@link LogRecord} (`record.name`) and
|
|
1276
1215
|
* shown in the formatted line. A manager registers each logger under its name.
|
|
1277
1216
|
* - `sink` — where formatted lines are written; defaults to
|
|
@@ -1284,7 +1223,7 @@ export declare interface LoggerManagerOptions {
|
|
|
1284
1223
|
* {@link import('./helpers.js').formatRecord}.
|
|
1285
1224
|
* - `limit` — the bounded retention cap: at most this many recent records are kept
|
|
1286
1225
|
* (oldest dropped first). Defaults to {@link DEFAULT_LOG_LIMIT}; never unbounded.
|
|
1287
|
-
* - `silent` — when `true`, suppresses the
|
|
1226
|
+
* - `silent` — when `true`, suppresses the sink write only; `entry` still fires and the
|
|
1288
1227
|
* record is still retained. Defaults to `false`.
|
|
1289
1228
|
*/
|
|
1290
1229
|
export declare interface LoggerOptions {
|
|
@@ -1301,21 +1240,21 @@ export declare interface LoggerOptions {
|
|
|
1301
1240
|
}
|
|
1302
1241
|
|
|
1303
1242
|
/**
|
|
1304
|
-
*
|
|
1243
|
+
* Names the severity level of a {@link LogRecord} — one coherent, ascending scale, `debug` <
|
|
1244
|
+
* `info` < `warn` < `error`, that a {@link LoggerInterface} gates by threshold.
|
|
1305
1245
|
*
|
|
1306
1246
|
* @remarks
|
|
1307
|
-
*
|
|
1308
|
-
*
|
|
1309
|
-
*
|
|
1310
|
-
* level — its visual treatment (color) is a separate styling concern, NEVER a pseudo-level
|
|
1247
|
+
* A record at or above the logger's `level` is kept (and written), one below it is
|
|
1248
|
+
* dropped (see {@link LEVEL_SEVERITY} for the numeric order). A level is a
|
|
1249
|
+
* level — its visual treatment (color) is a separate styling concern, never a pseudo-level
|
|
1311
1250
|
* like `success` / `ready`.
|
|
1312
1251
|
*/
|
|
1313
1252
|
export declare type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
1314
1253
|
|
|
1315
1254
|
/**
|
|
1316
|
-
*
|
|
1317
|
-
*
|
|
1318
|
-
*
|
|
1255
|
+
* Represents one immutable, serializable log entry. A {@link LoggerInterface} builds one per call,
|
|
1256
|
+
* freezes it, retains a bounded tail of them, and emits it on `entry`; every sink / transport
|
|
1257
|
+
* consumes this exact shape.
|
|
1319
1258
|
*
|
|
1320
1259
|
* @remarks
|
|
1321
1260
|
* - `level` — the record's {@link LogLevel}.
|
|
@@ -1325,9 +1264,9 @@ export declare type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
|
1325
1264
|
* - `name` — the originating logger's `name`, when it has one (a manager-registered logger
|
|
1326
1265
|
* is keyed by name; an anonymous logger omits it).
|
|
1327
1266
|
* - `data` — optional structured context (a flat `Record<string, unknown>`), absent when
|
|
1328
|
-
* no context was supplied. The top-level object is a
|
|
1267
|
+
* no context was supplied. The top-level object is a frozen copy taken at log time (a
|
|
1329
1268
|
* later mutation of the caller's original object never reaches the retained record);
|
|
1330
|
-
* nested values remain
|
|
1269
|
+
* nested values remain by reference (only the top level is copied + frozen).
|
|
1331
1270
|
* - The value is frozen at construction — a consumer reads it, never mutates it.
|
|
1332
1271
|
*/
|
|
1333
1272
|
export declare interface LogRecord {
|
|
@@ -1339,17 +1278,17 @@ export declare interface LogRecord {
|
|
|
1339
1278
|
}
|
|
1340
1279
|
|
|
1341
1280
|
/**
|
|
1342
|
-
*
|
|
1343
|
-
* at or above the threshold's.
|
|
1281
|
+
* Checks whether a record at `level` passes a logger gated at `threshold` — that is, its severity
|
|
1282
|
+
* is at or above the threshold's.
|
|
1344
1283
|
*
|
|
1345
1284
|
* @remarks
|
|
1346
|
-
* The level gate (
|
|
1285
|
+
* The level gate (the comparison lives here, not inlined in the logger). Reads
|
|
1347
1286
|
* the ascending {@link LEVEL_SEVERITY} order: `meetsLevel('warn', 'error')` is `true`
|
|
1348
1287
|
* (error ≥ warn), `meetsLevel('warn', 'info')` is `false` (info < warn).
|
|
1349
1288
|
*
|
|
1350
1289
|
* @param threshold - The logger's configured minimum {@link LogLevel}
|
|
1351
1290
|
* @param level - The record's {@link LogLevel}
|
|
1352
|
-
* @returns
|
|
1291
|
+
* @returns True if `level` is at least as severe as `threshold`; false otherwise
|
|
1353
1292
|
*
|
|
1354
1293
|
* @example
|
|
1355
1294
|
* ```ts
|
|
@@ -1360,12 +1299,12 @@ export declare interface LogRecord {
|
|
|
1360
1299
|
export declare function meetsLevel(threshold: LogLevel, level: LogLevel): boolean;
|
|
1361
1300
|
|
|
1362
1301
|
/**
|
|
1363
|
-
*
|
|
1364
|
-
* single optional-styling primitive every renderer applies to
|
|
1365
|
-
*
|
|
1302
|
+
* Colors `text` through `styler` and an optional by-value {@link Style}, or returns it verbatim
|
|
1303
|
+
* when `styler` is `undefined` — the single optional-styling primitive every renderer applies to
|
|
1304
|
+
* its border / title / connector glyphs.
|
|
1366
1305
|
*
|
|
1367
1306
|
* @remarks
|
|
1368
|
-
* The renderers all take an
|
|
1307
|
+
* The renderers all take an optional `styler`: present ⇒ glyphs are colored, absent ⇒ plain.
|
|
1369
1308
|
* Folding that `styler === undefined ? text : styler(text)` ternary into one exported helper
|
|
1370
1309
|
* keeps the renderers terse and the styling decision in one tested place. A disabled styler
|
|
1371
1310
|
* (`enabled: false`) is still a styler — it returns its text verbatim — so passing one paints
|
|
@@ -1379,31 +1318,34 @@ export declare function meetsLevel(threshold: LogLevel, level: LogLevel): boolea
|
|
|
1379
1318
|
export declare function paint(styler: StylerInterface | undefined, text: string, style?: Style): string;
|
|
1380
1319
|
|
|
1381
1320
|
/**
|
|
1382
|
-
*
|
|
1383
|
-
* {@link renderBar}, writes `\r` + bar to its {@link SinkInterface}, and emits the `{ current,
|
|
1384
|
-
* on `update`.
|
|
1385
|
-
*
|
|
1386
|
-
* UNIVERSAL — the one {@link StylerInterface} + the one {@link SinkInterface}, no `node:*`, no
|
|
1387
|
-
* `process.stdout`. NO self-timer (unlike {@link import('./Spinner.js').Spinner}) — the caller drives it.
|
|
1321
|
+
* Implements an update-driven, observable progress bar — {@link update} recomputes the bar through
|
|
1322
|
+
* {@link renderBar}, writes `\r` + bar to its {@link SinkInterface}, and emits the `{ current,
|
|
1323
|
+
* total }` on `update`. No self-timer, unlike {@link import('./Spinner.js').Spinner} — the caller
|
|
1324
|
+
* drives it.
|
|
1388
1325
|
*
|
|
1389
1326
|
* @remarks
|
|
1327
|
+
* The leading `\r` is what an overwrite-capable sink (the TTY sink) redraws on; a plain sink
|
|
1328
|
+
* degrades to a fresh, non-overwriting line — the line-overwrite is the sink's job. Universal —
|
|
1329
|
+
* the one {@link StylerInterface} + the one {@link SinkInterface}, no `node:*`, no
|
|
1330
|
+
* `process.stdout`.
|
|
1331
|
+
*
|
|
1390
1332
|
* - **Update-driven.** Each {@link update} clamps `current` to `[0, total]`, renders the bar (filled
|
|
1391
|
-
* to `current / total`, with the trailing `percent (current/total)` + message)
|
|
1333
|
+
* to `current / total`, with the trailing `percent (current/total)` + message) through {@link renderBar},
|
|
1392
1334
|
* emits `update`, and writes `'\r' + bar`. Progress advances only when the caller reports it.
|
|
1393
|
-
* - **Outcome lines.** {@link
|
|
1394
|
-
* a newline, emits a final `update` then `
|
|
1395
|
-
* bar at its
|
|
1335
|
+
* - **Outcome lines.** {@link succeed} renders a full bar (`current = total`) + message, terminated by
|
|
1336
|
+
* a newline, emits a final `update` then `succeed`, and marks `succeeded`. {@link fail} renders the
|
|
1337
|
+
* bar at its current fill + message + newline and routes to the sink's error stream (no `succeed` —
|
|
1396
1338
|
* the work did not finish). Both are terminal: a later {@link update} is ignored once `active` is false.
|
|
1397
|
-
* - **Bounded.** `current` is always clamped to `[0, total]`; {@link
|
|
1398
|
-
* {@link
|
|
1399
|
-
* - **Lifecycle
|
|
1339
|
+
* - **Bounded.** `current` is always clamped to `[0, total]`; {@link succeeded} reports whether
|
|
1340
|
+
* {@link succeed} has run; {@link active} is `true` until a {@link succeed} / {@link fail}.
|
|
1341
|
+
* - **Lifecycle.** {@link destroy} destroys the emitter (there is no timer to clear).
|
|
1400
1342
|
*
|
|
1401
1343
|
* @example
|
|
1402
1344
|
* ```ts
|
|
1403
1345
|
* const progress = new Progress({ total: 100, message: 'downloading' })
|
|
1404
1346
|
* progress.update(40) // ████████████░░░░░░░░░░░░░░░░░░ 40% (40/100) downloading
|
|
1405
1347
|
* progress.update(80, 'almost there')
|
|
1406
|
-
* progress.
|
|
1348
|
+
* progress.succeed('done') // a full bar, committed with a newline
|
|
1407
1349
|
* ```
|
|
1408
1350
|
*/
|
|
1409
1351
|
export declare class Progress implements ProgressInterface {
|
|
@@ -1411,125 +1353,102 @@ export declare class Progress implements ProgressInterface {
|
|
|
1411
1353
|
constructor(options: ProgressOptions);
|
|
1412
1354
|
get emitter(): EmitterInterface<ProgressEventMap>;
|
|
1413
1355
|
get active(): boolean;
|
|
1414
|
-
get
|
|
1356
|
+
get succeeded(): boolean;
|
|
1415
1357
|
get current(): number;
|
|
1416
1358
|
get total(): number;
|
|
1417
1359
|
update(current: number, message?: string): void;
|
|
1418
|
-
|
|
1419
|
-
|
|
1360
|
+
succeed(message?: string): void;
|
|
1361
|
+
fail(message?: string): void;
|
|
1420
1362
|
destroy(): void;
|
|
1421
1363
|
}
|
|
1422
1364
|
|
|
1423
1365
|
/**
|
|
1424
|
-
*
|
|
1425
|
-
*
|
|
1366
|
+
* Declares the observable events a {@link ProgressInterface} emits — `update(progress)` per
|
|
1367
|
+
* report, plus a `succeed` signal on a successful finish.
|
|
1426
1368
|
*
|
|
1427
1369
|
* @remarks
|
|
1428
|
-
* - `
|
|
1429
|
-
* `current` past `total` renders a full bar, a negative one an empty bar) — so a caller's overrun
|
|
1430
|
-
* never produces an over-long bar. A `total` of `0` (or below) renders a full bar (nothing to do).
|
|
1431
|
-
* - `width` — the visible cell count of the bar TRACK (the glyph run between no brackets); defaults
|
|
1432
|
-
* to {@link DEFAULT_BAR_WIDTH}. The percentage + `(current/total)` count follow the track.
|
|
1433
|
-
* - `fill` — the filled-cell glyph; defaults to {@link BAR_FILL} (`█`). `empty` — the empty-cell
|
|
1434
|
-
* glyph; defaults to {@link BAR_EMPTY} (`░`). Sized in VISIBLE columns ({@link
|
|
1435
|
-
* import('./helpers.js').width}), so a multi-cell glyph still yields a `width`-wide track.
|
|
1436
|
-
* - `styler` — colors the FILLED run when supplied (the empty run + the trailing label stay plain);
|
|
1437
|
-
* the layout is identical with or without color, since the track is measured on visible width.
|
|
1438
|
-
* - `style` — an optional by-value style rendered through `styler` for the filled run.
|
|
1439
|
-
*/
|
|
1440
|
-
export declare interface ProgressBarOptions {
|
|
1441
|
-
readonly current: number;
|
|
1442
|
-
readonly total: number;
|
|
1443
|
-
readonly width?: number;
|
|
1444
|
-
readonly fill?: string;
|
|
1445
|
-
readonly empty?: string;
|
|
1446
|
-
readonly styler?: StylerInterface;
|
|
1447
|
-
readonly style?: Style;
|
|
1448
|
-
}
|
|
1449
|
-
|
|
1450
|
-
/**
|
|
1451
|
-
* The observable events a {@link ProgressInterface} emits (AGENTS §13).
|
|
1452
|
-
*
|
|
1453
|
-
* @remarks
|
|
1454
|
-
* - `update` — the core event: fires on every `update(current)` (and on `complete` / `failure`),
|
|
1370
|
+
* - `update` — fires on every `update(current)` (and on `succeed` / `fail`),
|
|
1455
1371
|
* carrying the `{ current, total }` progress (the clamped `current`). The hook a non-sink consumer
|
|
1456
1372
|
* rides to observe progress without a terminal.
|
|
1457
|
-
* - `
|
|
1458
|
-
* signal (empty tuple) so a consumer can observe the bar reaching its end. (`
|
|
1459
|
-
* `update` and routes its line to the error stream, but is
|
|
1460
|
-
*
|
|
1373
|
+
* - `succeed` — the terminal signal: fires once from `succeed()` (a successful finish), a pure
|
|
1374
|
+
* signal (empty tuple) so a consumer can observe the bar reaching its end. (`fail()` emits a final
|
|
1375
|
+
* `update` and routes its line to the error stream, but is not a `succeed` — the bar's positive
|
|
1376
|
+
* outcome is the same word the spinner and the reporter use.)
|
|
1461
1377
|
*
|
|
1462
|
-
* Listener isolation is the emitter's
|
|
1463
|
-
* `interface extends EventMap
|
|
1378
|
+
* Listener isolation is the emitter's. Declared as a `type` alias (not
|
|
1379
|
+
* `interface extends EventMap`): a type-literal satisfies the `EventMap` constraint
|
|
1464
1380
|
* structurally, whereas an interface lacks the index signature.
|
|
1465
1381
|
*/
|
|
1466
1382
|
export declare type ProgressEventMap = {
|
|
1467
|
-
/**
|
|
1468
|
-
readonly update: readonly [progress:
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
}];
|
|
1472
|
-
/** The bar reached its end via `complete()` (a successful finish). */
|
|
1473
|
-
readonly complete: readonly [];
|
|
1383
|
+
/** Reports progress advancing — the clamped `{ current, total }` (fires on `update` and on `succeed` / `fail`). */
|
|
1384
|
+
readonly update: readonly [progress: ProgressReport];
|
|
1385
|
+
/** Fires after the bar reached its end through `succeed()` (a successful finish). */
|
|
1386
|
+
readonly succeed: readonly [];
|
|
1474
1387
|
};
|
|
1475
1388
|
|
|
1476
1389
|
/**
|
|
1477
|
-
*
|
|
1478
|
-
* {@link import('./helpers.js').renderBar}, writes `\r` + bar to its {@link SinkInterface}, and
|
|
1479
|
-
* the `{ current, total }` on `update`. The line-
|
|
1480
|
-
* on the `\r`; a plain sink degrades to a fresh line).
|
|
1390
|
+
* Declares an update-driven, observable progress bar — `update(current)` recomputes the bar through
|
|
1391
|
+
* {@link import('./helpers.js').renderBar}, writes `\r` + bar to its {@link SinkInterface}, and
|
|
1392
|
+
* emits the `{ current, total }` on `update`. The line-overwrite is the sink's job (a TTY sink
|
|
1393
|
+
* overwrites on the `\r`; a plain sink degrades to a fresh line). No self-timer — the caller drives
|
|
1394
|
+
* it.
|
|
1481
1395
|
*
|
|
1482
1396
|
* @remarks
|
|
1483
1397
|
* - **Update-driven.** Each `update(current, message?)` clamps `current` to `[0, total]`, renders
|
|
1484
1398
|
* the bar (filled to `current / total`, with the trailing `percent (current/total)` + message),
|
|
1485
1399
|
* emits `update`, and writes `'\r' + bar`. There is no internal timer (unlike {@link
|
|
1486
1400
|
* SpinnerInterface}) — progress advances only when the caller reports it.
|
|
1487
|
-
* - **Outcome lines.** `
|
|
1488
|
-
* terminated by a newline, emits a final `update` then `
|
|
1489
|
-
* `
|
|
1490
|
-
* error stream (no `
|
|
1491
|
-
* a `
|
|
1492
|
-
* - **Bounded.** `current` is always clamped to `[0, total]`; `
|
|
1493
|
-
* `
|
|
1401
|
+
* - **Outcome lines.** `succeed(message?)` renders a full bar (`current = total`) + message,
|
|
1402
|
+
* terminated by a newline, emits a final `update` then `succeed`, and marks `succeeded`.
|
|
1403
|
+
* `fail(message?)` renders the bar at its current fill + message + newline and routes to the sink's
|
|
1404
|
+
* error stream (no `succeed` — the work did not finish). Both are terminal: a later `update` after
|
|
1405
|
+
* a `succeed` / `fail` is ignored (`active` is `false`).
|
|
1406
|
+
* - **Bounded.** `current` is always clamped to `[0, total]`; `succeeded` reports whether
|
|
1407
|
+
* `succeed()` has run; `active` is `true` until a `succeed` / `fail`.
|
|
1494
1408
|
*/
|
|
1495
1409
|
export declare interface ProgressInterface {
|
|
1496
1410
|
readonly emitter: EmitterInterface<ProgressEventMap>;
|
|
1497
|
-
/**
|
|
1411
|
+
/** Reports whether the bar is still advancing (before any `succeed()` / `fail()`). */
|
|
1498
1412
|
readonly active: boolean;
|
|
1499
|
-
/**
|
|
1500
|
-
readonly
|
|
1501
|
-
/**
|
|
1413
|
+
/** Reports whether `succeed()` has run (the bar finished successfully). */
|
|
1414
|
+
readonly succeeded: boolean;
|
|
1415
|
+
/** Holds the current value, clamped to `[0, total]`. */
|
|
1502
1416
|
readonly current: number;
|
|
1503
|
-
/**
|
|
1417
|
+
/** Holds the target value the bar fills toward. */
|
|
1504
1418
|
readonly total: number;
|
|
1505
|
-
/**
|
|
1419
|
+
/**
|
|
1420
|
+
* Reports progress: clamps `current`, re-renders the bar, emits `update`, writes `\r` + bar.
|
|
1421
|
+
* Ignored after a terminal `succeed` or `fail`.
|
|
1422
|
+
*/
|
|
1506
1423
|
update(current: number, message?: string): void;
|
|
1507
|
-
/**
|
|
1508
|
-
|
|
1509
|
-
/**
|
|
1510
|
-
|
|
1511
|
-
/**
|
|
1424
|
+
/** Finishes successfully — renders a full bar + newline, emits a final `update` then `succeed`. */
|
|
1425
|
+
succeed(message?: string): void;
|
|
1426
|
+
/** Finishes unsuccessfully — renders the bar at its current fill + newline to the error stream (no `succeed`). */
|
|
1427
|
+
fail(message?: string): void;
|
|
1428
|
+
/** Tears down — destroys the emitter. */
|
|
1512
1429
|
destroy(): void;
|
|
1513
1430
|
}
|
|
1514
1431
|
|
|
1515
1432
|
/**
|
|
1516
|
-
*
|
|
1433
|
+
* Configures the {@link import('./Progress.js').Progress} constructor — the `on` / `error` emitter
|
|
1434
|
+
* keys, the required `total`, the `message` shown, the bar's `width` / `fill` / `empty` glyphs, and
|
|
1435
|
+
* the `sink` / `styler` / `theme` line substrate.
|
|
1517
1436
|
*
|
|
1518
1437
|
* @remarks
|
|
1519
|
-
* - `on` — the reserved {@link EmitterHooks} key
|
|
1438
|
+
* - `on` — the reserved {@link EmitterHooks} key: initial listeners for the
|
|
1520
1439
|
* {@link ProgressEventMap}, wired at construction.
|
|
1521
|
-
* - `error` — the emitter's listener-error handler
|
|
1522
|
-
* - `total` — the value `current` advances toward (the `100%` point); the only
|
|
1440
|
+
* - `error` — the emitter's listener-error handler; a listener throw routes here.
|
|
1441
|
+
* - `total` — the value `current` advances toward (the `100%` point); the only required option.
|
|
1523
1442
|
* - `message` — text shown after the bar; defaults to `''`. Overridden per-`update` and by a
|
|
1524
|
-
* `
|
|
1443
|
+
* `succeed` / `fail` argument.
|
|
1525
1444
|
* - `width` — the bar track's visible cell count, handed to {@link import('./helpers.js').renderBar};
|
|
1526
1445
|
* defaults to {@link DEFAULT_BAR_WIDTH}.
|
|
1527
1446
|
* - `fill` / `empty` — the filled and empty track glyphs handed to
|
|
1528
1447
|
* {@link import('./helpers.js').renderBar}; default to {@link BAR_FILL} / {@link BAR_EMPTY}.
|
|
1529
1448
|
* - `sink` — where each `\r` + bar line is written; defaults to
|
|
1530
|
-
* {@link import('./factories.js').createConsoleSink}. A TTY sink
|
|
1449
|
+
* {@link import('./factories.js').createConsoleSink}. A TTY sink overwrites on the `\r`.
|
|
1531
1450
|
* - `styler` — the {@link StylerInterface} the filled run is colored through; defaults to
|
|
1532
|
-
* {@link import('./factories.js').createStyler} (ANSI). The
|
|
1451
|
+
* {@link import('./factories.js').createStyler} (ANSI). The one styler the whole system shares.
|
|
1533
1452
|
* - `theme` — the {@link Theme} supplying the filled run's accent role; defaults to
|
|
1534
1453
|
* {@link DEFAULT_THEME}.
|
|
1535
1454
|
*/
|
|
@@ -1547,26 +1466,44 @@ export declare interface ProgressOptions {
|
|
|
1547
1466
|
}
|
|
1548
1467
|
|
|
1549
1468
|
/**
|
|
1550
|
-
*
|
|
1551
|
-
*
|
|
1552
|
-
*
|
|
1553
|
-
*
|
|
1554
|
-
* the
|
|
1469
|
+
* Reports one advance of a {@link ProgressInterface} — the clamped payload carried by the `update`
|
|
1470
|
+
* event of {@link ProgressEventMap}.
|
|
1471
|
+
*
|
|
1472
|
+
* @remarks
|
|
1473
|
+
* `current` is always the value after clamping into `[0, total]`, so a listener never sees an
|
|
1474
|
+
* overrun or a negative. `total` is the bar's fixed target, repeated on every report so a listener
|
|
1475
|
+
* needs no reference to the bar itself. The same record is emitted from `update`, `succeed`, and
|
|
1476
|
+
* `fail`.
|
|
1477
|
+
*/
|
|
1478
|
+
export declare interface ProgressReport {
|
|
1479
|
+
readonly current: number;
|
|
1480
|
+
readonly total: number;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
/**
|
|
1484
|
+
* Renders a determinate progress bar string — a filled / empty glyph track followed by the percentage
|
|
1485
|
+
* and the `(current/total)` count (`█████░░░░░ 50% (5/10)`). Pure and width-aware: same
|
|
1486
|
+
* {@link BarOptions} → same string.
|
|
1555
1487
|
*
|
|
1556
1488
|
* @remarks
|
|
1489
|
+
* It is the animation-layer sibling of the `render*` renderers (box / table / tree / separator),
|
|
1490
|
+
* shared so a {@link import('./types.js').ProgressInterface} and any direct caller draw the one
|
|
1491
|
+
* bar — never a second,
|
|
1492
|
+
* hand-rolled one.
|
|
1493
|
+
*
|
|
1557
1494
|
* - **Fill fraction, clamped.** The filled cell count is `round((current / total) · width)` with
|
|
1558
1495
|
* `current` clamped to `[0, total]`, so an overrun never over-fills and a negative never under-fills.
|
|
1559
|
-
* A `total <= 0` renders a
|
|
1496
|
+
* A `total <= 0` renders a full track (there is nothing to fill toward — the work is trivially done).
|
|
1560
1497
|
* - **Width-aware track.** The filled run is `fill` tiled to the filled cell count and the empty run
|
|
1561
|
-
* `empty` tiled to the remainder, each
|
|
1498
|
+
* `empty` tiled to the remainder, each through {@link repeatTo} — so the track is exactly `width` visible
|
|
1562
1499
|
* columns even for a multi-cell glyph (its escape codes / extra cells never break the width).
|
|
1563
|
-
* - **Styling.** `options.styler` colors the
|
|
1500
|
+
* - **Styling.** `options.styler` colors the filled run only (the empty run + the trailing
|
|
1564
1501
|
* `percent (count)` label stay plain), through {@link paint}; the layout is identical with or
|
|
1565
1502
|
* without color, since the track is measured on visible width.
|
|
1566
|
-
* - **Label.** The percentage is the rounded `current / total` (
|
|
1503
|
+
* - **Label.** The percentage is the rounded `current / total` (for example `50%`); the count is the clamped
|
|
1567
1504
|
* `current` over `total` (`(5/10)`), a single space separating the track, the percent, and the count.
|
|
1568
1505
|
*
|
|
1569
|
-
* @param options - See {@link
|
|
1506
|
+
* @param options - See {@link BarOptions}
|
|
1570
1507
|
* @returns The rendered bar line (no trailing newline)
|
|
1571
1508
|
*
|
|
1572
1509
|
* @example
|
|
@@ -1575,22 +1512,22 @@ export declare interface ProgressOptions {
|
|
|
1575
1512
|
* renderBar({ current: 10, total: 10, width: 4 }) // '████ 100% (10/10)'
|
|
1576
1513
|
* ```
|
|
1577
1514
|
*/
|
|
1578
|
-
export declare function renderBar(options:
|
|
1515
|
+
export declare function renderBar(options: BarOptions): string;
|
|
1579
1516
|
|
|
1580
1517
|
/**
|
|
1581
|
-
*
|
|
1518
|
+
* Renders `content` framed in box-drawing characters, optionally captioned, width-aware so
|
|
1582
1519
|
* styled content stays aligned inside the frame. Pure: same {@link BoxOptions} → same string.
|
|
1583
1520
|
*
|
|
1584
1521
|
* @remarks
|
|
1585
|
-
* - **Lines.** `content` is split on `\n`
|
|
1586
|
-
* exactly as the same text written on POSIX; a
|
|
1522
|
+
* - **Lines.** `content` is split on `\n` or `\r\n`, so caller text written on Windows frames
|
|
1523
|
+
* exactly as the same text written on POSIX; a lone `\r` is kept inside its line (it is a
|
|
1587
1524
|
* cursor control — the animation frame prefix — not a line separator). Each line is padded
|
|
1588
1525
|
* (left-aligned) to the inner
|
|
1589
|
-
* width by {@link align} — measured on
|
|
1526
|
+
* width by {@link align} — measured on visible width, so a styled line never breaks the
|
|
1590
1527
|
* right edge. The inner width is the widest line's visible width (or `width − borders −
|
|
1591
1528
|
* 2·padding` when an explicit `width` is given and is wider), plus `padding` blank cells
|
|
1592
1529
|
* inside each {@link BorderChars.vertical} edge.
|
|
1593
|
-
* - **Title.** An optional `title` is embedded in the
|
|
1530
|
+
* - **Title.** An optional `title` is embedded in the top border (` title `), the remaining
|
|
1594
1531
|
* top edge drawn as fill; a title wider than the inner width widens the box to fit it.
|
|
1595
1532
|
* - **Border + styling.** The {@link BorderStyle} (`options.border`, default
|
|
1596
1533
|
* {@link DEFAULT_BORDER}) selects the glyph set from {@link BORDER_CHARS}; `options.styler`
|
|
@@ -1604,21 +1541,21 @@ export declare function renderBar(options: ProgressBarOptions): string;
|
|
|
1604
1541
|
export declare function renderBox(options: BoxOptions): string;
|
|
1605
1542
|
|
|
1606
1543
|
/**
|
|
1607
|
-
*
|
|
1544
|
+
* Declares a swappable style renderer — the seam that turns style data into output for one
|
|
1608
1545
|
* target. The cross-environment default is the ANSI renderer (SGR escape codes); a
|
|
1609
|
-
* browser `%c` / CSS renderer implements the
|
|
1610
|
-
* model, so it drops in without touching the style data (the
|
|
1546
|
+
* browser `%c` / CSS renderer implements the same contract over the same {@link Style}
|
|
1547
|
+
* model, so it drops in without touching the style data (the browser branch).
|
|
1611
1548
|
*/
|
|
1612
1549
|
export declare interface RendererInterface {
|
|
1613
1550
|
/**
|
|
1614
|
-
*
|
|
1551
|
+
* Renders `text` wrapped in the target codes for `style`. The empty style (no colors,
|
|
1615
1552
|
* no attributes) and the empty string both return `text` unchanged — no wrapping.
|
|
1616
1553
|
*/
|
|
1617
1554
|
render(style: Style, text: string): string;
|
|
1618
1555
|
}
|
|
1619
1556
|
|
|
1620
1557
|
/**
|
|
1621
|
-
*
|
|
1558
|
+
* Renders a horizontal rule — an optional centered title embedded in a line of fill characters,
|
|
1622
1559
|
* to a fixed visible width. Pure: same {@link SeparatorOptions} → same string.
|
|
1623
1560
|
*
|
|
1624
1561
|
* @remarks
|
|
@@ -1627,10 +1564,10 @@ export declare interface RendererInterface {
|
|
|
1627
1564
|
* side) in the line, splitting the remaining fill between the two sides (the extra column,
|
|
1628
1565
|
* when the remainder is odd, goes to the right). The visible width stays exactly `width`,
|
|
1629
1566
|
* even when the title is styled (the title's escape codes don't count toward the budget) —
|
|
1630
|
-
* a title at least as wide as `width` yields
|
|
1567
|
+
* a title at least as wide as `width` yields only the gapped title (no fill).
|
|
1631
1568
|
* - **Styling.** When `options.styler` is given, the fill runs (and the embedded title) are
|
|
1632
1569
|
* colored through it; the layout is identical with or without color, since width is measured
|
|
1633
|
-
* on the visible content (
|
|
1570
|
+
* on the visible content (width-aware through {@link width}).
|
|
1634
1571
|
*
|
|
1635
1572
|
* @param options - See {@link SeparatorOptions}
|
|
1636
1573
|
* @returns The rule line (no trailing newline)
|
|
@@ -1644,17 +1581,17 @@ export declare interface RendererInterface {
|
|
|
1644
1581
|
export declare function renderSeparator(options: SeparatorOptions): string;
|
|
1645
1582
|
|
|
1646
1583
|
/**
|
|
1647
|
-
*
|
|
1584
|
+
* Renders a bordered grid of `columns` + `rows` with per-column alignment and width-aware
|
|
1648
1585
|
* column sizing. Pure: same {@link TableOptions} → same string.
|
|
1649
1586
|
*
|
|
1650
1587
|
* @remarks
|
|
1651
|
-
* - **Column sizing — visible width.** Each column is sized to the widest
|
|
1588
|
+
* - **Column sizing — visible width.** Each column is sized to the widest visible width
|
|
1652
1589
|
* ({@link width}) among its header label and its cells, so an already-styled cell never
|
|
1653
1590
|
* breaks the column (its escape codes don't count toward the width).
|
|
1654
1591
|
* - **Ragged rows.** A row shorter than the column count is padded with empty cells; a longer
|
|
1655
1592
|
* row is truncated to the column count — a ragged input never throws.
|
|
1656
1593
|
* - **Alignment.** Each cell is positioned by its column's {@link ColumnSpec.align} (default
|
|
1657
|
-
* {@link DEFAULT_ALIGN})
|
|
1594
|
+
* {@link DEFAULT_ALIGN}) through {@link align}.
|
|
1658
1595
|
* - **Frame.** The {@link BorderStyle} (`options.border`, default {@link DEFAULT_BORDER})
|
|
1659
1596
|
* draws the outer frame, the header rule (a `teeRight … cross … teeLeft` line), and the
|
|
1660
1597
|
* `vertical` column separators; `options.styler` colors the frame + header labels when
|
|
@@ -1667,8 +1604,8 @@ export declare function renderSeparator(options: SeparatorOptions): string;
|
|
|
1667
1604
|
export declare function renderTable(options: TableOptions): string;
|
|
1668
1605
|
|
|
1669
1606
|
/**
|
|
1670
|
-
*
|
|
1671
|
-
* {@link TreeOptions} → same string.
|
|
1607
|
+
* Renders a nested {@link TreeNode} tree whose connectors derive from the chosen `border` set.
|
|
1608
|
+
* Pure: same {@link TreeOptions} → same string.
|
|
1672
1609
|
*
|
|
1673
1610
|
* @remarks
|
|
1674
1611
|
* The `root` label is the unindented first line; its descendants are drawn beneath it with
|
|
@@ -1692,13 +1629,17 @@ export declare function renderTable(options: TableOptions): string;
|
|
|
1692
1629
|
export declare function renderTree(options: TreeOptions): string;
|
|
1693
1630
|
|
|
1694
1631
|
/**
|
|
1695
|
-
*
|
|
1696
|
-
*
|
|
1697
|
-
*
|
|
1698
|
-
* beneath under the carried guide (`│ ` under a non-last node, ` ` under the last).
|
|
1632
|
+
* Renders the connector-prefixed lines for a {@link TreeNode} list — the recursive core behind
|
|
1633
|
+
* {@link renderTree}, whose third options argument requires `border` and groups the optional
|
|
1634
|
+
* `styler` and `style`.
|
|
1699
1635
|
*
|
|
1700
1636
|
* @remarks
|
|
1701
|
-
*
|
|
1637
|
+
* Each child is drawn as `prefix` + its connector (`├─ ` for any but the last, `└─ ` for the
|
|
1638
|
+
* last) + its label, with its own descendants recursed beneath under the carried guide (`│ `
|
|
1639
|
+
* under a non-last node, ` ` under the last).
|
|
1640
|
+
*
|
|
1641
|
+
* @remarks
|
|
1642
|
+
* A centralized, exported recursion branch so it is directly testable and
|
|
1702
1643
|
* reusable outside {@link renderTree}'s top-level `root.label` framing.
|
|
1703
1644
|
*
|
|
1704
1645
|
* @param nodes - The sibling {@link TreeNode}s to render at this depth
|
|
@@ -1716,17 +1657,17 @@ export declare function renderTree(options: TreeOptions): string;
|
|
|
1716
1657
|
export declare function renderTreeChildren(nodes: readonly TreeNode[], prefix: string, options: Required<Pick<TreeOptions, 'border'>> & Pick<TreeOptions, 'style' | 'styler'>): readonly string[];
|
|
1717
1658
|
|
|
1718
1659
|
/**
|
|
1719
|
-
*
|
|
1660
|
+
* Repeats `unit` until it fills exactly `columns` visible columns, trimming a trailing partial
|
|
1720
1661
|
* unit so the run is never over-wide — the fill primitive the separator + box edges draw with.
|
|
1721
1662
|
*
|
|
1722
1663
|
* @remarks
|
|
1723
1664
|
* Counts in code points ({@link width}-consistent), so a multi-cell or astral `unit` is laid
|
|
1724
|
-
* down whole and the result is sliced to exactly `
|
|
1665
|
+
* down whole and the result is sliced to exactly `columns` visible columns. `columns <= 0` (or an
|
|
1725
1666
|
* empty / zero-width `unit`) yields `''`.
|
|
1726
1667
|
*
|
|
1727
1668
|
* @param unit - The (possibly multi-character) fill unit
|
|
1728
|
-
* @param
|
|
1729
|
-
* @returns `unit` tiled to exactly `
|
|
1669
|
+
* @param columns - The visible column count to fill
|
|
1670
|
+
* @returns `unit` tiled to exactly `columns` visible columns
|
|
1730
1671
|
*
|
|
1731
1672
|
* @example
|
|
1732
1673
|
* ```ts
|
|
@@ -1734,27 +1675,27 @@ export declare function renderTreeChildren(nodes: readonly TreeNode[], prefix: s
|
|
|
1734
1675
|
* repeatTo('=-', 5) // '=-=-='
|
|
1735
1676
|
* ```
|
|
1736
1677
|
*/
|
|
1737
|
-
export declare function repeatTo(unit: string,
|
|
1678
|
+
export declare function repeatTo(unit: string, columns: number): string;
|
|
1738
1679
|
|
|
1739
1680
|
/**
|
|
1740
|
-
*
|
|
1741
|
-
* build-run output. Each verb
|
|
1681
|
+
* Implements a lean, event-free narrative reporter — the composable verb set for human /
|
|
1682
|
+
* build-run output. Each verb formats its line through the shared {@link StylerInterface} and
|
|
1742
1683
|
* the pure layout renderers ({@link renderSeparator} / {@link renderBox} / {@link renderTable}
|
|
1743
|
-
* / {@link renderTree}) and
|
|
1684
|
+
* / {@link renderTree}) and writes it to a {@link SinkInterface} — the same styler + sink
|
|
1744
1685
|
* substrate the logger uses, never a second colorizer.
|
|
1745
1686
|
*
|
|
1746
1687
|
* @remarks
|
|
1747
|
-
* - **A
|
|
1688
|
+
* - **A small set, not a grab-bag.** `section` / `step` / `timing` / `status` / `table` /
|
|
1748
1689
|
* `tree` / `box` / `line` / `blank`. No spinner / bar (the animation chunk), no buffering /
|
|
1749
|
-
* capture (the capture chunk), no level retention (the logger).
|
|
1750
|
-
* - **`status` is a narrative
|
|
1690
|
+
* capture (the capture chunk), no level retention (the logger). Format and write, nothing more.
|
|
1691
|
+
* - **`status` is a narrative outcome, not a log level.** Its {@link StatusLevel} (`success` /
|
|
1751
1692
|
* `error` / `warn` / `info`) is distinct from {@link import('./types.js').LogLevel}: an icon
|
|
1752
1693
|
* supplied theme status icon + style, with `error` routed to the sink's
|
|
1753
1694
|
* error stream (the `level` hint forwarded to {@link SinkInterface.write}) — there is no
|
|
1754
1695
|
* gating and no severity ordering.
|
|
1755
1696
|
* - **Width-aware.** `section` (and a `box` with no explicit `width`) lay out to the reporter's
|
|
1756
|
-
* `#width`; the renderers measure on
|
|
1757
|
-
* - **Event-free
|
|
1697
|
+
* `#width`; the renderers measure on visible width (ANSI-aware), so styled content aligns.
|
|
1698
|
+
* - **Event-free.** No `#emitter` — a pure formatting front-end with no observable
|
|
1758
1699
|
* lifecycle (like the renderers and `Scheduler`). It is reusable and holds no per-call state.
|
|
1759
1700
|
*
|
|
1760
1701
|
* @example
|
|
@@ -1781,61 +1722,63 @@ export declare class Reporter implements ReporterInterface {
|
|
|
1781
1722
|
}
|
|
1782
1723
|
|
|
1783
1724
|
/**
|
|
1784
|
-
*
|
|
1725
|
+
* Declares a lean, event-free narrative reporter — the composable verb set for human / build-run
|
|
1785
1726
|
* output (sections, steps, timings, outcomes, tables, trees, boxes), formatting through the
|
|
1786
1727
|
* shared {@link StylerInterface} + layout renderers and writing to a {@link SinkInterface}.
|
|
1787
1728
|
*
|
|
1788
1729
|
* @remarks
|
|
1789
|
-
* - **A
|
|
1790
|
-
* `table` / `tree` / `box` / `line` / `blank`. Coloring is the
|
|
1730
|
+
* - **A small composable set**, not a grab-bag: `section` / `step` / `timing` / `status` /
|
|
1731
|
+
* `table` / `tree` / `box` / `line` / `blank`. Coloring is the one styler; layout is the
|
|
1791
1732
|
* pure renderers ({@link import('./helpers.js').renderSeparator} /
|
|
1792
1733
|
* {@link import('./helpers.js').renderBox} / {@link import('./helpers.js').renderTable} /
|
|
1793
1734
|
* {@link import('./helpers.js').renderTree}). No second colorizer, no spinner / bar (that
|
|
1794
1735
|
* is the animation chunk), no buffering / capture (that is the capture chunk).
|
|
1795
1736
|
* - **`status` is a narrative outcome, not a log level.** Its {@link StatusLevel} is
|
|
1796
|
-
* `success` / `error` / `warn` / `info` (
|
|
1737
|
+
* `success` / `error` / `warn` / `info` (distinct from {@link LogLevel}); `error` routes to
|
|
1797
1738
|
* the sink's error stream.
|
|
1798
|
-
* - **Event-free
|
|
1799
|
-
*
|
|
1739
|
+
* - **Event-free.** No emitter — a pure formatting front-end. Each verb formats then
|
|
1740
|
+
* writes immediately; there is no retained state worth observing.
|
|
1800
1741
|
*/
|
|
1801
1742
|
export declare interface ReporterInterface {
|
|
1802
|
-
/**
|
|
1743
|
+
/** Writes a titled separator block — a section heading framed by a horizontal rule. */
|
|
1803
1744
|
section(title: string): void;
|
|
1804
|
-
/**
|
|
1745
|
+
/** Writes a step line, optionally prefixed with its `[index/total]` {@link StepPosition}. */
|
|
1805
1746
|
step(message: string, position?: StepPosition): void;
|
|
1806
|
-
/**
|
|
1747
|
+
/** Writes a timing line — `label … 1.23s` (sub-second shown as `…ms`). */
|
|
1807
1748
|
timing(label: string, ms: number): void;
|
|
1808
|
-
/**
|
|
1749
|
+
/** Writes an icon + colored outcome line for `level` (`error` routes to the error stream). */
|
|
1809
1750
|
status(level: StatusLevel, message: string): void;
|
|
1810
|
-
/**
|
|
1751
|
+
/** Renders a {@link TableOptions} grid through {@link import('./helpers.js').renderTable} and writes it. */
|
|
1811
1752
|
table(options: TableOptions): void;
|
|
1812
|
-
/**
|
|
1753
|
+
/** Renders a {@link TreeOptions} tree through {@link import('./helpers.js').renderTree} and writes it. */
|
|
1813
1754
|
tree(options: TreeOptions): void;
|
|
1814
|
-
/**
|
|
1755
|
+
/** Renders a {@link BoxOptions} frame through {@link import('./helpers.js').renderBox} and writes it. */
|
|
1815
1756
|
box(options: BoxOptions): void;
|
|
1816
|
-
/**
|
|
1757
|
+
/** Writes one raw line, colored through the styler if any styling is embedded — no prefix, no icon. */
|
|
1817
1758
|
line(text: string): void;
|
|
1818
|
-
/**
|
|
1759
|
+
/** Writes `count` blank lines (default `1`). */
|
|
1819
1760
|
blank(count?: number): void;
|
|
1820
1761
|
}
|
|
1821
1762
|
|
|
1822
1763
|
/**
|
|
1823
|
-
*
|
|
1764
|
+
* Configures the {@link import('./Reporter.js').Reporter} constructor — the `sink` every line is
|
|
1765
|
+
* written to, the `styler` and `theme` it formats through, and the `width` its layouts measure
|
|
1766
|
+
* against.
|
|
1824
1767
|
*
|
|
1825
1768
|
* @remarks
|
|
1826
1769
|
* - `sink` — where every formatted line is written; defaults to
|
|
1827
1770
|
* {@link import('./factories.js').createConsoleSink} (the snapshotted, level-routing console
|
|
1828
|
-
* sink) — the
|
|
1771
|
+
* sink) — the same seam the logger writes through. A `status('error', …)` passes the
|
|
1829
1772
|
* `error` level so a stream-aware sink routes it to `stderr`.
|
|
1830
1773
|
* - `styler` — the {@link StylerInterface} every line is colored through; defaults to
|
|
1831
|
-
* {@link import('./factories.js').createStyler} (ANSI). The
|
|
1774
|
+
* {@link import('./factories.js').createStyler} (ANSI). The one styler the whole system
|
|
1832
1775
|
* shares — no second colorizer. A disabled styler yields plain narration.
|
|
1833
1776
|
* - `theme` — the {@link Theme} supplying status, accent, and chrome roles; defaults to
|
|
1834
1777
|
* {@link DEFAULT_THEME}.
|
|
1835
1778
|
* - `width` — the default column width handed to the separator / box renderers (the section
|
|
1836
1779
|
* rule, a `box` with no explicit width); defaults to {@link DEFAULT_WIDTH}.
|
|
1837
1780
|
*
|
|
1838
|
-
* Event-free
|
|
1781
|
+
* Event-free: the reporter has no `on` / `error` — it is a formatting front-end with no
|
|
1839
1782
|
* observable lifecycle, so (like the renderers and `Scheduler`) it carries no emitter.
|
|
1840
1783
|
*/
|
|
1841
1784
|
export declare interface ReporterOptions {
|
|
@@ -1845,37 +1788,135 @@ export declare interface ReporterOptions {
|
|
|
1845
1788
|
readonly width?: number;
|
|
1846
1789
|
}
|
|
1847
1790
|
|
|
1848
|
-
/**
|
|
1791
|
+
/** Holds the full SGR reset sequence (`ESC[0m`) appended after a styled run. */
|
|
1849
1792
|
export declare const RESET: string;
|
|
1850
1793
|
|
|
1851
|
-
/**
|
|
1794
|
+
/** Holds the SGR RESET parameter (0) — terminates a styled run, clearing all colors and attributes. */
|
|
1852
1795
|
export declare const RESET_CODE = 0;
|
|
1853
1796
|
|
|
1854
1797
|
/**
|
|
1855
|
-
*
|
|
1856
|
-
*
|
|
1857
|
-
*
|
|
1798
|
+
* Implements the bounded, level-keyed retention engine the console and process captures buffer
|
|
1799
|
+
* through — one capped total buffer
|
|
1800
|
+
* plus one capped bucket per level, generic over the record type each capture carries.
|
|
1801
|
+
*
|
|
1802
|
+
* @remarks
|
|
1803
|
+
* - **One engine, two captures.** The core `Capture` retains
|
|
1804
|
+
* {@link import('./types.js').CapturedMessage}s keyed by
|
|
1805
|
+
* {@link import('./types.js').CaptureLevel}, and the server `ProcessCapture` retains chunks keyed
|
|
1806
|
+
* by its stream level; both compose this, so their retention semantics cannot drift apart.
|
|
1807
|
+
* - **Bounded on both axes.** `add` appends to the total buffer and to the record's bucket, then
|
|
1808
|
+
* drops the oldest of whichever exceeded `limit`, so neither grows without bound.
|
|
1809
|
+
* - **Buckets are fixed at construction.** Only the levels passed to the constructor get a bucket.
|
|
1810
|
+
* A record at any other level still joins the total buffer, and `records(level)` for a level with
|
|
1811
|
+
* no bucket returns an empty list.
|
|
1812
|
+
* - **Copies out.** `records` returns a fresh list each call, so retained state is never reachable
|
|
1813
|
+
* for mutation through a returned value.
|
|
1814
|
+
*
|
|
1815
|
+
* @example
|
|
1816
|
+
* ```ts
|
|
1817
|
+
* const retention = new Retention<{ level: 'warn' | 'error'; text: string }>(['warn'], 2)
|
|
1818
|
+
* retention.add({ level: 'warn', text: 'first' })
|
|
1819
|
+
* retention.add({ level: 'error', text: 'second' }) // no bucket, still in the total buffer
|
|
1820
|
+
* retention.records().length // 2
|
|
1821
|
+
* retention.records('warn').map((record) => record.text) // ['first']
|
|
1822
|
+
* retention.clear()
|
|
1823
|
+
* retention.records() // []
|
|
1824
|
+
* ```
|
|
1825
|
+
*/
|
|
1826
|
+
export declare class Retention<T extends {
|
|
1827
|
+
readonly level: string;
|
|
1828
|
+
}> implements RetentionInterface<T> {
|
|
1829
|
+
#private;
|
|
1830
|
+
constructor(levels: ReadonlyArray<T['level']>, limit: number);
|
|
1831
|
+
add(record: T): void;
|
|
1832
|
+
records(): readonly T[];
|
|
1833
|
+
records(level: T['level']): readonly T[];
|
|
1834
|
+
clear(): void;
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
/**
|
|
1838
|
+
* Declares the bounded, level-keyed retention buffer a capture keeps its records in — one capped total
|
|
1839
|
+
* buffer plus one capped bucket per level configured at construction.
|
|
1840
|
+
*
|
|
1841
|
+
* @remarks
|
|
1842
|
+
* - **Bounded on both axes.** The total buffer and each bucket are capped at the same `limit`,
|
|
1843
|
+
* dropping the oldest record first, so neither can grow without bound.
|
|
1844
|
+
* - **Buckets are fixed at construction.** A record whose `level` has no bucket still joins the
|
|
1845
|
+
* total buffer, and `records(level)` for an unconfigured level returns an empty list rather than
|
|
1846
|
+
* failing.
|
|
1847
|
+
* - **Copies out.** Each `records` call returns a fresh list, so a caller can never mutate the
|
|
1848
|
+
* retained state through the value it receives.
|
|
1849
|
+
*/
|
|
1850
|
+
export declare interface RetentionInterface<T extends {
|
|
1851
|
+
readonly level: string;
|
|
1852
|
+
}> {
|
|
1853
|
+
/**
|
|
1854
|
+
* Retains one record — appends it to the total buffer and to its level's bucket, evicting the
|
|
1855
|
+
* oldest of each past `limit`.
|
|
1856
|
+
*/
|
|
1857
|
+
add(record: T): void;
|
|
1858
|
+
/**
|
|
1859
|
+
* Returns a copy of the whole retained buffer, oldest first, or — given a level — a copy of
|
|
1860
|
+
* that level's bucket, empty for a level with no bucket.
|
|
1861
|
+
*/
|
|
1862
|
+
records(): readonly T[];
|
|
1863
|
+
/** Returns a copy of one level's bucket, oldest first; empty for a level with no bucket. */
|
|
1864
|
+
records(level: T['level']): readonly T[];
|
|
1865
|
+
/** Drops every retained record from the total buffer and every bucket. */
|
|
1866
|
+
clear(): void;
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
/**
|
|
1870
|
+
* Sets the millisecond threshold at or above which {@link import('./helpers.js').formatDuration}
|
|
1871
|
+
* (and so `Reporter.timing`) switches from a `…ms` rendering to a `…s` (seconds, 2 d.p.) rendering
|
|
1872
|
+
* — `1000`, exactly one second.
|
|
1858
1873
|
*/
|
|
1859
1874
|
export declare const SECOND_MS = 1000;
|
|
1860
1875
|
|
|
1861
|
-
/**
|
|
1876
|
+
/**
|
|
1877
|
+
* Selects the member of a {@link WriterSet} a {@link LogLevel} routes to — `error` to `error`,
|
|
1878
|
+
* `warn` to `warn`, every other level and an omitted level to `log`.
|
|
1879
|
+
*
|
|
1880
|
+
* @remarks
|
|
1881
|
+
* The single owner of the level-to-target decision every sink backend shares, so core's console
|
|
1882
|
+
* sink, the browser `%c` sink, and the server stream sink cannot drift apart. A backend that sends
|
|
1883
|
+
* two levels to one destination passes the same member twice: the server sink routes `warn`
|
|
1884
|
+
* alongside `error` by supplying its error stream for both, which matches `console.warn` writing
|
|
1885
|
+
* to `stderr`. The member type is the caller's, so the same leaf selects a bound console method, a
|
|
1886
|
+
* stream target, or a per-target styling fact.
|
|
1887
|
+
*
|
|
1888
|
+
* @param level - The originating record's {@link LogLevel}, or `undefined` when the caller has none
|
|
1889
|
+
* @param writers - See {@link WriterSet}
|
|
1890
|
+
* @returns The member `level` routes to
|
|
1891
|
+
*
|
|
1892
|
+
* @example
|
|
1893
|
+
* ```ts
|
|
1894
|
+
* selectWriter('error', { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stderr'
|
|
1895
|
+
* selectWriter('warn', { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stderr'
|
|
1896
|
+
* selectWriter('debug', { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stdout'
|
|
1897
|
+
* selectWriter(undefined, { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stdout'
|
|
1898
|
+
* ```
|
|
1899
|
+
*/
|
|
1900
|
+
export declare function selectWriter<T>(level: LogLevel | undefined, writers: WriterSet<T>): T;
|
|
1901
|
+
|
|
1902
|
+
/** Holds the default fill character {@link import('./helpers.js').renderSeparator} draws its rule with — `─`. */
|
|
1862
1903
|
export declare const SEPARATOR_FILL = "\u2500";
|
|
1863
1904
|
|
|
1864
1905
|
/**
|
|
1865
|
-
*
|
|
1906
|
+
* Holds the single padding cell on each side of a separator's embedded title (` title `) — keeps the
|
|
1866
1907
|
* title from butting against the rule. One space.
|
|
1867
1908
|
*/
|
|
1868
1909
|
export declare const SEPARATOR_TITLE_GAP = " ";
|
|
1869
1910
|
|
|
1870
1911
|
/**
|
|
1871
|
-
*
|
|
1872
|
-
* carrying a centered title.
|
|
1912
|
+
* Configures {@link import('./helpers.js').renderSeparator} — a horizontal rule, optionally
|
|
1913
|
+
* carrying a centered title. Every key is optional.
|
|
1873
1914
|
*
|
|
1874
1915
|
* @remarks
|
|
1875
|
-
* - `title` — text to embed in the rule (
|
|
1916
|
+
* - `title` — text to embed in the rule (for example a section heading). Omitted ⇒ an unbroken line.
|
|
1876
1917
|
* - `width` — the visible column count of the whole rule; defaults to {@link DEFAULT_WIDTH}.
|
|
1877
1918
|
* - `fill` — the single character the rule is drawn with; defaults to {@link SEPARATOR_FILL}
|
|
1878
|
-
* (`─`). The
|
|
1919
|
+
* (`─`). The visible width of the rule is `width` regardless of the fill's escape codes.
|
|
1879
1920
|
* - `styler` — colors the rule (and the embedded title) when supplied; the layout is
|
|
1880
1921
|
* identical with or without it, since width is measured on the visible content.
|
|
1881
1922
|
* - `style` — an optional by-value style rendered through `styler` for the rule and title.
|
|
@@ -1889,59 +1930,63 @@ export declare interface SeparatorOptions {
|
|
|
1889
1930
|
}
|
|
1890
1931
|
|
|
1891
1932
|
/**
|
|
1892
|
-
*
|
|
1893
|
-
* `Sink` is the
|
|
1933
|
+
* Declares the minimal output primitive — the seam every formatted line is written through. A
|
|
1934
|
+
* `Sink` is the one place text leaves the logging system; redirect output (to a file, a
|
|
1894
1935
|
* buffer, a test recorder, the browser `%c` path, a server TTY) by supplying a different
|
|
1895
1936
|
* `SinkInterface`, with no change to the logger.
|
|
1896
1937
|
*
|
|
1897
1938
|
* @remarks
|
|
1898
1939
|
* - **`write(text)` is the whole contract.** A custom sink (file / buffer / recorder)
|
|
1899
|
-
* implements
|
|
1900
|
-
* a stream-aware sink can
|
|
1940
|
+
* implements only `write(text)` and ignores the rest — the optional `level` exists only so
|
|
1941
|
+
* a stream-aware sink can route. The logger passes the originating record's {@link LogLevel}.
|
|
1901
1942
|
* - **The default {@link import('./factories.js').createConsoleSink} routes by level** —
|
|
1902
1943
|
* `error` → `console.error`, `warn` → `console.warn`, everything else → `console.log` — and
|
|
1903
|
-
* writes to the
|
|
1944
|
+
* writes to the underlying `console` methods snapshotted at creation, so a later `Capture`
|
|
1904
1945
|
* that patches `console` can never feed the sink's own output back into itself (the
|
|
1905
|
-
* no-capture-loop principle). The same `level` seam lets the
|
|
1946
|
+
* no-capture-loop principle). The same `level` seam lets the server TTY sink send
|
|
1906
1947
|
* `error` / `warn` to `stderr`.
|
|
1907
1948
|
*/
|
|
1908
1949
|
export declare interface SinkInterface {
|
|
1909
1950
|
/**
|
|
1910
|
-
*
|
|
1911
|
-
*
|
|
1912
|
-
*
|
|
1913
|
-
*
|
|
1914
|
-
* terminator
|
|
1915
|
-
* `
|
|
1916
|
-
*
|
|
1951
|
+
* Writes one already-formatted chunk of output — one line without its terminator, or a
|
|
1952
|
+
* `\r`-leading redraw frame written verbatim, routed by the optional `level`.
|
|
1953
|
+
*
|
|
1954
|
+
* @remarks
|
|
1955
|
+
* The sink's target supplies the terminator (for example `console.log`; the server TTY sink
|
|
1956
|
+
* appends one), unless `text` begins with `\r`: that is an in-place redraw frame (the
|
|
1957
|
+
* Spinner / Progress animation protocol). A tick frame carries no terminator; a final frame
|
|
1958
|
+
* carries its own. `level` is the originating record's {@link LogLevel} — supplied so a
|
|
1959
|
+
* stream-aware sink can route (for example `error` to `stderr`); a plain sink ignores it.
|
|
1917
1960
|
*/
|
|
1918
1961
|
write(text: string, level?: LogLevel): void;
|
|
1919
1962
|
}
|
|
1920
1963
|
|
|
1921
1964
|
/**
|
|
1922
|
-
*
|
|
1965
|
+
* Implements a self-driving, observable activity spinner — a glyph cycle that advances on a
|
|
1923
1966
|
* periodic timer, writing each `\r` + frame line to its {@link SinkInterface} and emitting it on
|
|
1924
|
-
* `frame`. The
|
|
1925
|
-
* sink (C-f) degrades to a fresh, non-overwriting line — the line-OVERWRITE is the SINK's job, never
|
|
1926
|
-
* the spinner's. UNIVERSAL — `setInterval` + the one {@link StylerInterface} + the one
|
|
1927
|
-
* {@link SinkInterface}, no `node:*`, no `process.stdout`.
|
|
1967
|
+
* `frame`. The timer is always cleared on an outcome, so the spinner is leak-free.
|
|
1928
1968
|
*
|
|
1929
1969
|
* @remarks
|
|
1970
|
+
* The leading `\r` is what an overwrite-capable sink (the TTY sink) redraws on; a plain sink
|
|
1971
|
+
* degrades to a fresh, non-overwriting line — the line-overwrite is the sink's job, never the
|
|
1972
|
+
* spinner's. Universal — `setInterval` + the one {@link StylerInterface} + the one
|
|
1973
|
+
* {@link SinkInterface}, no `node:*`, no `process.stdout`.
|
|
1974
|
+
*
|
|
1930
1975
|
* - **Self-driving but deterministically testable.** `start()` arms a `setInterval` that calls
|
|
1931
1976
|
* {@link tick} each `interval`; each {@link tick} builds the styled `glyph + message` line for the
|
|
1932
1977
|
* current frame, emits it on `frame`, writes `'\r' + line` to the sink, then advances the frame
|
|
1933
1978
|
* index (wrapping). A test drives frames by calling {@link tick} directly, or arms a real short
|
|
1934
1979
|
* `interval` and proves the timer arms / clears through the sink it writes to.
|
|
1935
|
-
* - **Leak-free timer.** The interval is
|
|
1980
|
+
* - **Leak-free timer.** The interval is always cleared on {@link succeed} / {@link fail} /
|
|
1936
1981
|
* {@link stop} / {@link destroy} — `#handle` is the single source of `active`, set on arm and unset
|
|
1937
1982
|
* on clear, so a spinner never leaks a running interval.
|
|
1938
1983
|
* - **Idempotent `start`.** A {@link start} while already `active` is a no-op (it never arms a second
|
|
1939
1984
|
* timer).
|
|
1940
|
-
* - **Outcome lines.** {@link
|
|
1985
|
+
* - **Outcome lines.** {@link succeed} / {@link fail} clear the timer then write + emit a final line —
|
|
1941
1986
|
* the supplied theme status icon + style (`✔` / `✖` by default) + the message — terminated
|
|
1942
|
-
* by a newline (the activity is over; the line is committed, not overwritten). {@link
|
|
1987
|
+
* by a newline (the activity is over; the line is committed, not overwritten). {@link fail} routes to
|
|
1943
1988
|
* the sink's error stream.
|
|
1944
|
-
* - **Lifecycle
|
|
1989
|
+
* - **Lifecycle.** {@link stop} clears the timer and leaves the current line; {@link destroy}
|
|
1945
1990
|
* stops then destroys the emitter. {@link update} swaps the message and re-renders immediately when
|
|
1946
1991
|
* `active`.
|
|
1947
1992
|
*
|
|
@@ -1950,7 +1995,7 @@ export declare interface SinkInterface {
|
|
|
1950
1995
|
* const spinner = new Spinner({ message: 'building' })
|
|
1951
1996
|
* spinner.start() // arms the timer, paints the first frame to the sink
|
|
1952
1997
|
* spinner.update('bundling') // message changes, re-rendered at once
|
|
1953
|
-
* spinner.
|
|
1998
|
+
* spinner.succeed('built in 1.2s') // ✔ built in 1.2s — timer cleared, line committed
|
|
1954
1999
|
* ```
|
|
1955
2000
|
*/
|
|
1956
2001
|
export declare class Spinner implements SpinnerInterface {
|
|
@@ -1962,113 +2007,119 @@ export declare class Spinner implements SpinnerInterface {
|
|
|
1962
2007
|
start(): void;
|
|
1963
2008
|
tick(): void;
|
|
1964
2009
|
update(message: string): void;
|
|
1965
|
-
|
|
1966
|
-
|
|
2010
|
+
succeed(message?: string): void;
|
|
2011
|
+
fail(message?: string): void;
|
|
1967
2012
|
stop(): void;
|
|
1968
2013
|
destroy(): void;
|
|
1969
2014
|
}
|
|
1970
2015
|
|
|
1971
2016
|
/**
|
|
1972
|
-
*
|
|
1973
|
-
* the
|
|
1974
|
-
*
|
|
2017
|
+
* Holds the default spinner frame cycle a {@link import('./types.js').SpinnerInterface} advances
|
|
2018
|
+
* through — the braille-pattern glyphs (`⠋⠙⠹…`, the U+2800 block) that read as a smoothly rotating
|
|
2019
|
+
* dot.
|
|
1975
2020
|
*
|
|
1976
2021
|
* @remarks
|
|
2022
|
+
* The cycle is the universal terminal-spinner convention. Frozen; a consumer swaps the whole
|
|
2023
|
+
* cycle through `options.frames`.
|
|
2024
|
+
*
|
|
1977
2025
|
* Braille glyphs are single visible cells, so every frame occupies one column — the spinner glyph
|
|
1978
2026
|
* never shifts the message beside it as it advances. The source of truth for the default frame axis.
|
|
1979
2027
|
*/
|
|
1980
2028
|
export declare const SPINNER_FRAMES: readonly string[];
|
|
1981
2029
|
|
|
1982
2030
|
/**
|
|
1983
|
-
*
|
|
2031
|
+
* Declares the observable events a {@link SpinnerInterface} emits — `frame(line)` per advance and
|
|
2032
|
+
* per outcome, plus the `start` and `stop` timer-lifecycle signals.
|
|
1984
2033
|
*
|
|
1985
2034
|
* @remarks
|
|
1986
|
-
* - `frame` —
|
|
1987
|
-
* timer or called directly)
|
|
1988
|
-
* line (the
|
|
2035
|
+
* - `frame` — fires once per advance (every `tick()`, whether driven by the internal
|
|
2036
|
+
* timer or called directly) and on the final `succeed` / `fail` line, carrying the rendered frame
|
|
2037
|
+
* line (the same text written to the sink, minus the leading `\r`). The hook a non-sink consumer
|
|
1989
2038
|
* (a test, a remote mirror) rides to observe the animation without a terminal.
|
|
1990
2039
|
* - `start` / `stop` — the lifecycle signals bracketing the internal timer: `start` fires when the
|
|
1991
2040
|
* timer is armed (the first `start()` on an inactive spinner), `stop` when it is cleared (a
|
|
1992
|
-
* `stop()` / `
|
|
2041
|
+
* `stop()` / `succeed()` / `fail()` on an active spinner, and from `destroy()`); both pure signals
|
|
1993
2042
|
* (empty tuples) so a consumer can observe the activity lifecycle.
|
|
1994
2043
|
*
|
|
1995
|
-
* Listener isolation is the emitter's
|
|
1996
|
-
* handler, never onto this map. Declared as a `type` alias (not `interface extends EventMap
|
|
2044
|
+
* Listener isolation is the emitter's: a listener throw routes to the emitter's `error`
|
|
2045
|
+
* handler, never onto this map. Declared as a `type` alias (not `interface extends EventMap`):
|
|
1997
2046
|
* a type-literal satisfies the `EventMap` constraint structurally, whereas an interface lacks the
|
|
1998
2047
|
* index signature.
|
|
1999
2048
|
*/
|
|
2000
2049
|
export declare type SpinnerEventMap = {
|
|
2001
|
-
/**
|
|
2050
|
+
/** Fires after a frame was produced (a `tick()` advance or the final `succeed` / `fail` line) — the rendered line. */
|
|
2002
2051
|
readonly frame: readonly [line: string];
|
|
2003
|
-
/**
|
|
2052
|
+
/** Fires after the internal timer was armed (an inactive spinner's `start()`). */
|
|
2004
2053
|
readonly start: readonly [];
|
|
2005
|
-
/**
|
|
2054
|
+
/** Fires after the internal timer was cleared (an active spinner's `stop()` / `succeed()` / `fail()` / `destroy()`). */
|
|
2006
2055
|
readonly stop: readonly [];
|
|
2007
2056
|
};
|
|
2008
2057
|
|
|
2009
2058
|
/**
|
|
2010
|
-
*
|
|
2059
|
+
* Declares a self-driving, observable activity spinner — a glyph cycle that advances on a
|
|
2011
2060
|
* periodic timer, writing each `\r` + frame line to its {@link SinkInterface} and emitting it on
|
|
2012
|
-
* `frame`. The line-
|
|
2061
|
+
* `frame`. The line-overwrite is the sink's job (a TTY sink overwrites on the `\r`; a plain sink
|
|
2013
2062
|
* degrades to a fresh line).
|
|
2014
2063
|
*
|
|
2015
2064
|
* @remarks
|
|
2016
2065
|
* - **Self-driving but deterministically testable.** `start()` arms a `setInterval` (universal — no
|
|
2017
2066
|
* `node:*`) that calls `tick()` each `interval`; each `tick()` advances the frame index, builds the
|
|
2018
2067
|
* styled `glyph + message` line, emits it on `frame`, and writes `'\r' + line` to the sink. A test
|
|
2019
|
-
* drives frames by calling `tick()` directly (
|
|
2020
|
-
* with fake timers — the timer is
|
|
2068
|
+
* drives frames by calling `tick()` directly (no real clock) and proves the timer arms / clears
|
|
2069
|
+
* with fake timers — the timer is always cleared on `succeed` / `fail` / `stop` / `destroy`, so it
|
|
2021
2070
|
* never leaks.
|
|
2022
2071
|
* - **Idempotent `start`.** A `start()` while already `active` is a no-op (it never arms a second
|
|
2023
|
-
* timer). `active` reflects whether the timer is
|
|
2024
|
-
* - **Outcome lines.** `
|
|
2025
|
-
*
|
|
2072
|
+
* timer). `active` reflects whether the timer is armed.
|
|
2073
|
+
* - **Outcome lines.** `succeed(message?)` / `fail(message?)` clear the timer, then write + emit a
|
|
2074
|
+
* final line — the theme's success / error status icon + style (`✔` / `✖` by default) + the
|
|
2026
2075
|
* message — terminated by a newline (the activity is over; the line is committed, not overwritten).
|
|
2027
|
-
* `
|
|
2028
|
-
* - **Lifecycle
|
|
2076
|
+
* `fail` routes to the sink's error stream.
|
|
2077
|
+
* - **Lifecycle.** `stop()` clears the timer and leaves the current line (no final write);
|
|
2029
2078
|
* `destroy()` stops then destroys the emitter. `update(message)` swaps the message (re-rendering
|
|
2030
2079
|
* immediately when active, so the change shows without waiting for the next tick).
|
|
2031
2080
|
*/
|
|
2032
2081
|
export declare interface SpinnerInterface {
|
|
2033
2082
|
readonly emitter: EmitterInterface<SpinnerEventMap>;
|
|
2034
|
-
/**
|
|
2083
|
+
/** Reports whether the internal timer is armed (between `start()` and `stop` / `succeed` / `fail`). */
|
|
2035
2084
|
readonly active: boolean;
|
|
2036
|
-
/**
|
|
2085
|
+
/** Holds the current message shown beside the glyph. */
|
|
2037
2086
|
readonly message: string;
|
|
2038
|
-
/**
|
|
2087
|
+
/** Arms the periodic timer and renders the first frame — a no-op when already `active`. */
|
|
2039
2088
|
start(): void;
|
|
2040
|
-
/**
|
|
2089
|
+
/** Advances one frame: builds the line, emits `frame`, and writes `\r` + line to the sink. */
|
|
2041
2090
|
tick(): void;
|
|
2042
|
-
/**
|
|
2091
|
+
/** Changes the message; re-renders immediately when `active` so the change shows at once. */
|
|
2043
2092
|
update(message: string): void;
|
|
2044
|
-
/**
|
|
2045
|
-
|
|
2046
|
-
/**
|
|
2047
|
-
|
|
2048
|
-
/**
|
|
2093
|
+
/** Stops with a success line — clears the timer, writes + emits `✔ message` + newline. */
|
|
2094
|
+
succeed(message?: string): void;
|
|
2095
|
+
/** Stops with an error line — clears the timer, writes + emits `✖ message` + newline (error stream). */
|
|
2096
|
+
fail(message?: string): void;
|
|
2097
|
+
/** Clears the timer and leaves the current line (no final write) — a no-op when not `active`. */
|
|
2049
2098
|
stop(): void;
|
|
2050
|
-
/**
|
|
2099
|
+
/** Tears down — `stop()` then destroys the emitter. */
|
|
2051
2100
|
destroy(): void;
|
|
2052
2101
|
}
|
|
2053
2102
|
|
|
2054
2103
|
/**
|
|
2055
|
-
*
|
|
2104
|
+
* Configures the {@link import('./Spinner.js').Spinner} constructor — the `on` / `error` emitter
|
|
2105
|
+
* keys, the `message` shown, the glyph `frames` and their `interval`, and the `sink` / `styler` /
|
|
2106
|
+
* `theme` line substrate.
|
|
2056
2107
|
*
|
|
2057
2108
|
* @remarks
|
|
2058
|
-
* - `on` — the reserved {@link EmitterHooks} key
|
|
2109
|
+
* - `on` — the reserved {@link EmitterHooks} key: initial listeners for the
|
|
2059
2110
|
* {@link SpinnerEventMap}, wired at construction.
|
|
2060
|
-
* - `error` — the emitter's listener-error handler
|
|
2111
|
+
* - `error` — the emitter's listener-error handler; a listener throw routes here.
|
|
2061
2112
|
* - `message` — the text shown beside the spinner glyph; defaults to `''` (a bare glyph). Changed
|
|
2062
|
-
* live
|
|
2113
|
+
* live through `update(message)` and overridden by a `succeed` / `fail` argument.
|
|
2063
2114
|
* - `frames` — the cycle of glyph frames the spinner advances through; defaults to
|
|
2064
2115
|
* {@link SPINNER_FRAMES} (the braille set `⠋⠙⠹…`). Each `tick()` advances to the next, wrapping.
|
|
2065
2116
|
* - `interval` — the timer period in milliseconds between frames; defaults to
|
|
2066
|
-
* {@link DEFAULT_SPINNER_INTERVAL}. The timer is
|
|
2067
|
-
* `destroy`, so it never leaks; tests drive frames deterministically
|
|
2117
|
+
* {@link DEFAULT_SPINNER_INTERVAL}. The timer is always cleared on `succeed` / `fail` / `stop` /
|
|
2118
|
+
* `destroy`, so it never leaks; tests drive frames deterministically through `tick()` (no real clock).
|
|
2068
2119
|
* - `sink` — where each `\r` + frame line is written; defaults to
|
|
2069
|
-
* {@link import('./factories.js').createConsoleSink}. A TTY sink
|
|
2120
|
+
* {@link import('./factories.js').createConsoleSink}. A TTY sink overwrites on the `\r`.
|
|
2070
2121
|
* - `styler` — the {@link StylerInterface} the glyph is colored through; defaults to
|
|
2071
|
-
* {@link import('./factories.js').createStyler} (ANSI). The
|
|
2122
|
+
* {@link import('./factories.js').createStyler} (ANSI). The one styler the whole system shares.
|
|
2072
2123
|
* - `theme` — the {@link Theme} supplying the accent and outcome roles; defaults to
|
|
2073
2124
|
* {@link DEFAULT_THEME}.
|
|
2074
2125
|
*/
|
|
@@ -2084,34 +2135,35 @@ export declare interface SpinnerOptions {
|
|
|
2084
2135
|
}
|
|
2085
2136
|
|
|
2086
2137
|
/**
|
|
2087
|
-
*
|
|
2088
|
-
* in (`success` green, `error` red, `warn` yellow, `info` blue). The
|
|
2138
|
+
* Maps each {@link StatusLevel} to its {@link Color} — the icon + message color a `status` line renders
|
|
2139
|
+
* in (`success` green, `error` red, `warn` yellow, `info` blue). The visual treatment of a
|
|
2089
2140
|
* narrative outcome, colored through the reporter's styler; orthogonal to leveling, like
|
|
2090
2141
|
* {@link LEVEL_COLORS}. Excludes `default` so each value indexes a real styler accessor.
|
|
2091
2142
|
*/
|
|
2092
2143
|
export declare const STATUS_COLORS: Readonly<Record<StatusLevel, Exclude<Color, 'default'>>>;
|
|
2093
2144
|
|
|
2094
2145
|
/**
|
|
2095
|
-
*
|
|
2146
|
+
* Maps each {@link StatusLevel} to its icon glyph — the leading mark a {@link
|
|
2096
2147
|
* import('./types.js').ReporterInterface.status} outcome line shows: `success` ✔, `error` ✖,
|
|
2097
2148
|
* `warn` ⚠, `info` ℹ. The narrative-outcome counterpart to a log level's label; frozen.
|
|
2098
2149
|
*/
|
|
2099
2150
|
export declare const STATUS_ICONS: Readonly<Record<StatusLevel, string>>;
|
|
2100
2151
|
|
|
2101
2152
|
/**
|
|
2102
|
-
*
|
|
2153
|
+
* Lists every {@link StatusLevel}, frozen — the outcomes a `status` line supports (drives exhaustive
|
|
2103
2154
|
* tests). The source of truth for the status axis; aligned with {@link STATUS_ICONS} /
|
|
2104
2155
|
* {@link STATUS_COLORS}.
|
|
2105
2156
|
*/
|
|
2106
2157
|
export declare const STATUS_LEVELS: readonly StatusLevel[];
|
|
2107
2158
|
|
|
2108
2159
|
/**
|
|
2109
|
-
*
|
|
2110
|
-
* with its own icon + color
|
|
2160
|
+
* Names a narrative outcome level — `success` / `error` / `warn` / `info`, the states
|
|
2161
|
+
* {@link ReporterInterface.status} reports, each with its own icon + color
|
|
2162
|
+
* ({@link STATUS_ICONS} / {@link STATUS_COLORS}).
|
|
2111
2163
|
*
|
|
2112
2164
|
* @remarks
|
|
2113
|
-
*
|
|
2114
|
-
* narrative
|
|
2165
|
+
* distinct from {@link LogLevel} (`debug` / `info` / `warn` / `error`): a `StatusLevel` is a
|
|
2166
|
+
* narrative outcome (did the step success?), not a log severity threshold — there is no
|
|
2115
2167
|
* ordering and no gating. `success` (`✔`, green), `error` (`✖`, red), `warn` (`⚠`, yellow),
|
|
2116
2168
|
* `info` (`ℹ`, blue). `error` routes to the sink's error stream (the `level` hint passed to
|
|
2117
2169
|
* {@link SinkInterface.write}); the other three go to the default stream.
|
|
@@ -2119,8 +2171,8 @@ export declare const STATUS_LEVELS: readonly StatusLevel[];
|
|
|
2119
2171
|
export declare type StatusLevel = 'success' | 'error' | 'warn' | 'info';
|
|
2120
2172
|
|
|
2121
2173
|
/**
|
|
2122
|
-
*
|
|
2123
|
-
*
|
|
2174
|
+
* Represents where one step sits in a sequence — what {@link ReporterInterface.step} renders as a
|
|
2175
|
+
* `[2/5]` prefix.
|
|
2124
2176
|
*
|
|
2125
2177
|
* @remarks
|
|
2126
2178
|
* Both are 1-based for display (`{ index: 2, total: 5 }` ⇒ `[2/5]`); the reporter formats
|
|
@@ -2133,17 +2185,18 @@ export declare interface StepPosition {
|
|
|
2133
2185
|
}
|
|
2134
2186
|
|
|
2135
2187
|
/**
|
|
2136
|
-
*
|
|
2188
|
+
* Stringifies one captured console argument into a line fragment — the per-argument rule behind
|
|
2137
2189
|
* {@link formatArgs}: an `Error` → `name: message`, a plain object / array → circular-safe JSON,
|
|
2138
2190
|
* anything else (string, number, boolean, `null`, `undefined`, symbol, function) → `String(value)`.
|
|
2139
2191
|
*
|
|
2140
2192
|
* @remarks
|
|
2141
|
-
* - **Total + never throws.** Like a guard
|
|
2193
|
+
* - **Total + never throws.** Like a guard, this never throws on adversarial input — a value
|
|
2142
2194
|
* carrying a circular reference, a `BigInt`, or a throwing `toJSON` is rendered, not raised. The
|
|
2143
2195
|
* `JSON.stringify` runs with a circular-guard replacer (a seen-set drops a back-reference as
|
|
2144
|
-
* `'[Circular]'`);
|
|
2145
|
-
* `String(value)`. So a `Capture` can never crash the program whose `console.*` it
|
|
2146
|
-
*
|
|
2196
|
+
* `'[Circular]'`); if `JSON.stringify` still throws (for example on a `BigInt`), the value falls
|
|
2197
|
+
* back to `String(value)`. So a `Capture` can never crash the program whose `console.*` it
|
|
2198
|
+
* intercepts.
|
|
2199
|
+
* - **`Error` first.** An `Error` renders as `name: message` (for example `TypeError: bad`) — the useful
|
|
2147
2200
|
* one-line form, since `JSON.stringify(error)` is `{}` (its fields are non-enumerable).
|
|
2148
2201
|
* - **Objects → JSON.** A non-null `object` (including an array) is `JSON.stringify`d; a primitive
|
|
2149
2202
|
* (or `null` / `undefined` / `function` / `symbol`) goes through `String`.
|
|
@@ -2164,11 +2217,11 @@ export declare interface StepPosition {
|
|
|
2164
2217
|
export declare function stringifyValue(value: unknown): string;
|
|
2165
2218
|
|
|
2166
2219
|
/**
|
|
2167
|
-
*
|
|
2220
|
+
* Removes every ANSI escape sequence from `text`, returning the plain visible string.
|
|
2168
2221
|
*
|
|
2169
2222
|
* @remarks
|
|
2170
|
-
* Strips SGR color/style codes
|
|
2171
|
-
* sequences (titles, hyperlinks) — see {@link ANSI_PATTERN}. A
|
|
2223
|
+
* Strips SGR color/style codes and other CSI controls (cursor, erase) plus OSC
|
|
2224
|
+
* sequences (titles, hyperlinks) — see {@link ANSI_PATTERN}. A fresh `RegExp` is built
|
|
2172
2225
|
* per call from the canonical pattern's `source` + `flags`, so the shared global
|
|
2173
2226
|
* pattern's `lastIndex` is never mutated across calls (re-entrant and deterministic).
|
|
2174
2227
|
*
|
|
@@ -2183,14 +2236,15 @@ export declare function stringifyValue(value: unknown): string;
|
|
|
2183
2236
|
export declare function strip(text: string): string;
|
|
2184
2237
|
|
|
2185
2238
|
/**
|
|
2186
|
-
*
|
|
2187
|
-
* (meaningful whitespace), plus DEL —
|
|
2239
|
+
* Removes every non-printing C0 control character from `text` except `\t` / `\n` / `\r`
|
|
2240
|
+
* (meaningful whitespace), plus DEL — a separate pass from {@link strip}, so `width` stays
|
|
2241
|
+
* untouched.
|
|
2188
2242
|
*
|
|
2189
2243
|
* @remarks
|
|
2190
|
-
* Deliberately
|
|
2244
|
+
* Deliberately separate from {@link strip} (ANSI-escape removal only, so `width` /
|
|
2191
2245
|
* `align` stay untouched) — this is the additional pass a non-TTY output sink applies
|
|
2192
2246
|
* on top of `strip`, so a captured `\x07` bell or stray `\x00` never reaches a log file
|
|
2193
|
-
* / non-terminal target. A
|
|
2247
|
+
* / non-terminal target. A fresh `RegExp` is built per call from {@link CONTROL_PATTERN}'s
|
|
2194
2248
|
* `source` + `flags`, the same re-entrant idiom as `strip`.
|
|
2195
2249
|
*
|
|
2196
2250
|
* @param text - Any string, possibly carrying raw control bytes
|
|
@@ -2204,7 +2258,7 @@ export declare function strip(text: string): string;
|
|
|
2204
2258
|
export declare function stripControls(text: string): string;
|
|
2205
2259
|
|
|
2206
2260
|
/**
|
|
2207
|
-
*
|
|
2261
|
+
* Represents text style as data — a frozen, readonly record of a foreground color, a background
|
|
2208
2262
|
* color, and a set of text attributes. The single style value the whole console /
|
|
2209
2263
|
* terminal system shares; a {@link RendererInterface} renders it for one target.
|
|
2210
2264
|
*
|
|
@@ -2213,7 +2267,7 @@ export declare function stripControls(text: string): string;
|
|
|
2213
2267
|
* emits a color code only for a set, non-`default` color.
|
|
2214
2268
|
* - `attributes` is a de-duplicated, order-stable list (a set modelled as an array so
|
|
2215
2269
|
* the value stays plain JSON data — no `Set` to clone or serialize). An empty list +
|
|
2216
|
-
* no colors is the
|
|
2270
|
+
* no colors is the empty style, which renders text unchanged.
|
|
2217
2271
|
* - The value is deeply frozen; compose a new style with the styler rather than mutating.
|
|
2218
2272
|
*/
|
|
2219
2273
|
export declare interface Style {
|
|
@@ -2223,10 +2277,10 @@ export declare interface Style {
|
|
|
2223
2277
|
}
|
|
2224
2278
|
|
|
2225
2279
|
/**
|
|
2226
|
-
*
|
|
2227
|
-
* function (call it with text to render the accumulated style)
|
|
2280
|
+
* Declares the fluent, composable styling surface — the consumer-facing API. It is both a
|
|
2281
|
+
* function (call it with text to render the accumulated style) and a record of
|
|
2228
2282
|
* chainable accessors: every {@link Color} and {@link Attribute} is a getter returning a
|
|
2229
|
-
*
|
|
2283
|
+
* new styler with that token added, so `styler.red.bold('hi')` and
|
|
2230
2284
|
* `styler.red(styler.bold('hi'))` both work and nothing is mutated.
|
|
2231
2285
|
*
|
|
2232
2286
|
* @remarks
|
|
@@ -2234,24 +2288,24 @@ export declare interface Style {
|
|
|
2234
2288
|
* styler is reusable and the chains never interfere.
|
|
2235
2289
|
* - Calling the styler builds the {@link Style} under the hood and renders it through the
|
|
2236
2290
|
* injected renderer. When `enabled` is `false`, it returns the text verbatim.
|
|
2237
|
-
* - `render` is the
|
|
2291
|
+
* - `render` is the data door beside the accessor chain: it renders a {@link Style} value
|
|
2238
2292
|
* (a {@link Theme} role, say) merged over the accumulated style, so a caller styles by
|
|
2239
2293
|
* value where the chain styles by name. Both go through the same renderer and the same
|
|
2240
2294
|
* `enabled` switch.
|
|
2241
|
-
* - `style` exposes the accumulated style
|
|
2295
|
+
* - `style` exposes the accumulated style data (the empty style on a base styler), and
|
|
2242
2296
|
* `enabled` reflects the switch — both inspectable and testable.
|
|
2243
2297
|
* - A later color of the same channel wins (`styler.red.blue` is blue); a repeated
|
|
2244
2298
|
* attribute is idempotent (`styler.bold.bold` carries one `bold`).
|
|
2245
2299
|
*/
|
|
2246
2300
|
export declare interface StylerInterface {
|
|
2247
|
-
/**
|
|
2301
|
+
/** Renders the accumulated style around `text` (verbatim when `enabled` is `false`). */
|
|
2248
2302
|
(text: string): string;
|
|
2249
|
-
/**
|
|
2303
|
+
/** Holds the accumulated style data — the empty style on a base styler. */
|
|
2250
2304
|
readonly style: Style;
|
|
2251
|
-
/**
|
|
2305
|
+
/** Reports whether styling is applied; when `false`, calls return text unchanged. */
|
|
2252
2306
|
readonly enabled: boolean;
|
|
2253
2307
|
/**
|
|
2254
|
-
*
|
|
2308
|
+
* Renders `text` in `style` merged over the accumulated style — the by-value counterpart
|
|
2255
2309
|
* of the accessor chain, and the door a {@link Theme} role is applied through.
|
|
2256
2310
|
*
|
|
2257
2311
|
* @param style - The style to overlay; its colors win over the accumulated ones and its
|
|
@@ -2262,7 +2316,7 @@ export declare interface StylerInterface {
|
|
|
2262
2316
|
*
|
|
2263
2317
|
* @example
|
|
2264
2318
|
* ```ts
|
|
2265
|
-
* import { createStyler, DEFAULT_THEME } from '@
|
|
2319
|
+
* import { createStyler, DEFAULT_THEME } from '@orkestrel/console'
|
|
2266
2320
|
*
|
|
2267
2321
|
* const styler = createStyler()
|
|
2268
2322
|
* styler.render(DEFAULT_THEME.levels.warn, 'WARN') // yellow
|
|
@@ -2295,14 +2349,15 @@ export declare interface StylerInterface {
|
|
|
2295
2349
|
}
|
|
2296
2350
|
|
|
2297
2351
|
/**
|
|
2298
|
-
*
|
|
2352
|
+
* Configures {@link createStyler} — `renderer` selects the output target, defaulting to the ANSI
|
|
2353
|
+
* renderer, and `enabled` is the no-color switch, defaulting to `true`.
|
|
2299
2354
|
*
|
|
2300
2355
|
* @remarks
|
|
2301
|
-
* - `renderer` — the {@link RendererInterface} every style renders through
|
|
2302
|
-
*
|
|
2303
|
-
*
|
|
2304
|
-
* - `enabled` —
|
|
2305
|
-
*
|
|
2356
|
+
* - `renderer` — the {@link RendererInterface} every style renders through, so the styler
|
|
2357
|
+
* works unchanged in any terminal. Inject a browser `%c` renderer to retarget with no
|
|
2358
|
+
* other change.
|
|
2359
|
+
* - `enabled` — when `false`, the styler returns text verbatim, for a non-TTY, a
|
|
2360
|
+
* `NO_COLOR` environment, or piped output.
|
|
2306
2361
|
*/
|
|
2307
2362
|
export declare interface StylerOptions {
|
|
2308
2363
|
readonly renderer?: RendererInterface;
|
|
@@ -2310,8 +2365,9 @@ export declare interface StylerOptions {
|
|
|
2310
2365
|
}
|
|
2311
2366
|
|
|
2312
2367
|
/**
|
|
2313
|
-
*
|
|
2314
|
-
*
|
|
2368
|
+
* Configures {@link import('./helpers.js').renderTable} — a bordered grid of columns + rows with
|
|
2369
|
+
* per-column alignment and width-aware sizing. A `Reporter` supplies its own chrome style only when
|
|
2370
|
+
* the caller gives neither `styler` nor `style`.
|
|
2315
2371
|
*
|
|
2316
2372
|
* @remarks
|
|
2317
2373
|
* - `columns` — the {@link ColumnSpec}s, left to right; their `label`s form the header row.
|
|
@@ -2320,7 +2376,7 @@ export declare interface StylerOptions {
|
|
|
2320
2376
|
* - `border` — the {@link BorderStyle} the frame + header rule + column separators draw in;
|
|
2321
2377
|
* defaults to {@link DEFAULT_BORDER} (`single`).
|
|
2322
2378
|
* - `styler` — colors the border + header labels when supplied; the cells are written as
|
|
2323
|
-
* given (already-styled cells are honored — their
|
|
2379
|
+
* given (already-styled cells are honored — their visible width drives column sizing, never
|
|
2324
2380
|
* their raw `.length`).
|
|
2325
2381
|
* - `style` — an optional by-value style rendered through `styler` for the frame and headers.
|
|
2326
2382
|
*/
|
|
@@ -2333,9 +2389,8 @@ export declare interface TableOptions {
|
|
|
2333
2389
|
}
|
|
2334
2390
|
|
|
2335
2391
|
/**
|
|
2336
|
-
*
|
|
2337
|
-
*
|
|
2338
|
-
* surface speaks it.
|
|
2392
|
+
* Represents the app-wide semantic style vocabulary — each role bound to a {@link Style} value.
|
|
2393
|
+
* Pass one theme to a logger / reporter / spinner / progress and every surface speaks it.
|
|
2339
2394
|
*
|
|
2340
2395
|
* @remarks
|
|
2341
2396
|
* - `levels` — the label style per {@link LogLevel} (a log line's severity label).
|
|
@@ -2345,7 +2400,7 @@ export declare interface TableOptions {
|
|
|
2345
2400
|
* step prefix.
|
|
2346
2401
|
* - `chrome` — the frame role: separators, box / table / tree connectors, and a log line's
|
|
2347
2402
|
* timestamp / name / data surround.
|
|
2348
|
-
* - A theme is the vocabulary the
|
|
2403
|
+
* - A theme is the vocabulary the whole application shares; a per-entity option (a
|
|
2349
2404
|
* `ProgressOptions.fill`, a `BoxOptions.border`) is the presentation of that one instance.
|
|
2350
2405
|
* - A theme returned by {@link createTheme} is frozen with every {@link Style} leaf deeply
|
|
2351
2406
|
* frozen, so one theme is safely shared across every entity.
|
|
@@ -2358,14 +2413,14 @@ export declare interface Theme {
|
|
|
2358
2413
|
}
|
|
2359
2414
|
|
|
2360
2415
|
/**
|
|
2361
|
-
*
|
|
2416
|
+
* Holds the options for {@link createTheme} — the roles to override on {@link DEFAULT_THEME}, a
|
|
2417
|
+
* status supplying its whole copied `{ icon, style }` record.
|
|
2362
2418
|
*
|
|
2363
2419
|
* @remarks
|
|
2364
|
-
* Every key is optional and merges per
|
|
2420
|
+
* Every key is optional and merges per role, never per theme: an omitted role keeps its
|
|
2365
2421
|
* default, and `levels` / `statuses` merge per entry, so `{ levels: { warn: … } }` restyles
|
|
2366
|
-
* the `warn` label and leaves
|
|
2367
|
-
*
|
|
2368
|
-
* style leaf it receives.
|
|
2422
|
+
* the `warn` label and leaves `debug`, `info`, and `error` alone. {@link createTheme}
|
|
2423
|
+
* snapshots and freezes each status record and every style leaf it receives.
|
|
2369
2424
|
*/
|
|
2370
2425
|
export declare interface ThemeOptions {
|
|
2371
2426
|
readonly levels?: Readonly<Partial<Record<LogLevel, Style>>>;
|
|
@@ -2375,12 +2430,12 @@ export declare interface ThemeOptions {
|
|
|
2375
2430
|
}
|
|
2376
2431
|
|
|
2377
2432
|
/**
|
|
2378
|
-
*
|
|
2433
|
+
* Represents one narrative outcome's presentation — the icon glyph a {@link StatusLevel} shows and the
|
|
2379
2434
|
* {@link Style} the line renders in.
|
|
2380
2435
|
*
|
|
2381
2436
|
* @remarks
|
|
2382
2437
|
* The themed counterpart of the {@link STATUS_ICONS} / {@link STATUS_COLORS} defaults: those
|
|
2383
|
-
* two constants are the
|
|
2438
|
+
* two constants are the source of {@link DEFAULT_THEME}'s statuses. A status override supplies
|
|
2384
2439
|
* the whole record — both `icon` and `style` — through {@link ThemeOptions}.
|
|
2385
2440
|
*/
|
|
2386
2441
|
export declare interface ThemeStatus {
|
|
@@ -2389,7 +2444,7 @@ export declare interface ThemeStatus {
|
|
|
2389
2444
|
}
|
|
2390
2445
|
|
|
2391
2446
|
/**
|
|
2392
|
-
*
|
|
2447
|
+
* Represents one node of a {@link TreeOptions} tree — a label plus optional children, recursively.
|
|
2393
2448
|
*
|
|
2394
2449
|
* @remarks
|
|
2395
2450
|
* - `label` — the node's text (a single visible line; it may already be styled).
|
|
@@ -2402,8 +2457,9 @@ export declare interface TreeNode {
|
|
|
2402
2457
|
}
|
|
2403
2458
|
|
|
2404
2459
|
/**
|
|
2405
|
-
*
|
|
2406
|
-
*
|
|
2460
|
+
* Configures {@link import('./helpers.js').renderTree} — a nested {@link TreeNode} tree drawn with
|
|
2461
|
+
* box-drawing connectors. A `Reporter` supplies its own chrome style only when the caller gives
|
|
2462
|
+
* neither `styler` nor `style`.
|
|
2407
2463
|
*
|
|
2408
2464
|
* @remarks
|
|
2409
2465
|
* - `root` — the top {@link TreeNode}; its `label` is the unindented first line and its
|
|
@@ -2422,13 +2478,13 @@ export declare interface TreeOptions {
|
|
|
2422
2478
|
}
|
|
2423
2479
|
|
|
2424
2480
|
/**
|
|
2425
|
-
*
|
|
2481
|
+
* Measures how many visible columns `text` occupies — its length after ANSI escapes are stripped, counted in
|
|
2426
2482
|
* Unicode code points (so an astral character such as an emoji counts as one, not the
|
|
2427
2483
|
* two UTF-16 units `String.length` would report).
|
|
2428
2484
|
*
|
|
2429
2485
|
* @remarks
|
|
2430
2486
|
* The basis for terminal layout (box / table / progress alignment): the column count a
|
|
2431
|
-
* styled string occupies, independent of its escape codes. It does
|
|
2487
|
+
* styled string occupies, independent of its escape codes. It does not account for
|
|
2432
2488
|
* wide (CJK / fullwidth) glyphs occupying two cells — a deliberate, documented
|
|
2433
2489
|
* simplification at this layer; callers needing east-asian width handle it above.
|
|
2434
2490
|
*
|
|
@@ -2442,8 +2498,21 @@ export declare interface TreeOptions {
|
|
|
2442
2498
|
*/
|
|
2443
2499
|
export declare function width(text: string): number;
|
|
2444
2500
|
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2501
|
+
/**
|
|
2502
|
+
* Groups the write targets a level-routing sink chooses between — each of the backend's own member
|
|
2503
|
+
* type.
|
|
2504
|
+
*
|
|
2505
|
+
* @remarks
|
|
2506
|
+
* The member type is the sink's own: a bound `console` method in core, a browser `%c` console
|
|
2507
|
+
* method, a stream target on the server, or any per-target fact routed the same way. A backend
|
|
2508
|
+
* that sends two levels to one place supplies the same member twice; that is how the server sink
|
|
2509
|
+
* routes `warn` alongside `error` to its error stream.
|
|
2510
|
+
* {@link import('./helpers.js').selectWriter} is the one place the level-to-member decision lives.
|
|
2511
|
+
*/
|
|
2512
|
+
export declare interface WriterSet<T> {
|
|
2513
|
+
readonly log: T;
|
|
2514
|
+
readonly warn: T;
|
|
2515
|
+
readonly error: T;
|
|
2516
|
+
}
|
|
2448
2517
|
|
|
2449
2518
|
export { }
|