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