@orkestrel/console 0.0.12 → 0.0.14
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 +8 -8
- package/dist/src/browser/index.d.ts +47 -38
- package/dist/src/browser/index.js +27 -18
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/core/index.cjs +121 -82
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +263 -174
- package/dist/src/core/index.d.ts +263 -174
- package/dist/src/core/index.js +121 -82
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +64 -45
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +115 -80
- package/dist/src/server/index.d.ts +115 -80
- package/dist/src/server/index.js +64 -45
- package/dist/src/server/index.js.map +1 -1
- package/package.json +15 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts","../../../src/core/helpers.ts","../../../src/core/renderers/ANSIRenderer.ts","../../../src/core/Retention.ts","../../../src/core/Capture.ts","../../../src/core/Styler.ts","../../../src/core/factories.ts","../../../src/core/loggers/Logger.ts","../../../src/core/loggers/LoggerManager.ts","../../../src/core/Reporter.ts","../../../src/core/Spinner.ts","../../../src/core/Progress.ts"],"sourcesContent":["import type {\n\tAlignment,\n\tAttribute,\n\tBorderChars,\n\tBorderStyle,\n\tCaptureLevel,\n\tColor,\n\tLogLevel,\n\tStyle,\n\tStatusLevel,\n\tTheme,\n} from './types.js'\n\n// The SGR (Select Graphic Rendition) code data the ANSI renderer maps style data\n// through, plus the reset terminator and the ANSI-strip pattern. UPPER_SNAKE,\n// `Object.freeze`d, every member exported. These are the standard SGR\n// numbers (ECMA-48) — a fixed external spec, so the literals are the source of truth.\n// `default` carries no code (it leaves the target's own ink) and so is absent from the\n// color maps — the renderer emits a code only for a present, non-`default` color.\n\n/**\n * Maps each {@link Color} to its SGR foreground parameter — the 8 base colors at 30–37 and their\n * bright variants at 90–97. `default` is intentionally absent (it emits no code).\n */\nexport const FOREGROUND_CODES: Readonly<Record<Exclude<Color, 'default'>, number>> = Object.freeze({\n\tblack: 30,\n\tred: 31,\n\tgreen: 32,\n\tyellow: 33,\n\tblue: 34,\n\tmagenta: 35,\n\tcyan: 36,\n\twhite: 37,\n\tbrightBlack: 90,\n\tbrightRed: 91,\n\tbrightGreen: 92,\n\tbrightYellow: 93,\n\tbrightBlue: 94,\n\tbrightMagenta: 95,\n\tbrightCyan: 96,\n\tbrightWhite: 97,\n})\n\n/**\n * Maps each {@link Color} to its SGR background parameter — the 8 base colors at 40–47 and their\n * bright variants at 100–107. `default` is intentionally absent (it emits no code).\n */\nexport const BACKGROUND_CODES: Readonly<Record<Exclude<Color, 'default'>, number>> = Object.freeze({\n\tblack: 40,\n\tred: 41,\n\tgreen: 42,\n\tyellow: 43,\n\tblue: 44,\n\tmagenta: 45,\n\tcyan: 46,\n\twhite: 47,\n\tbrightBlack: 100,\n\tbrightRed: 101,\n\tbrightGreen: 102,\n\tbrightYellow: 103,\n\tbrightBlue: 104,\n\tbrightMagenta: 105,\n\tbrightCyan: 106,\n\tbrightWhite: 107,\n})\n\n/**\n * Maps each {@link Attribute} to its SGR \"on\" parameter — `bold` 1, `dim` 2, `italic` 3,\n * `underline` 4, `inverse` 7, `strikethrough` 9. The renderer composes several by\n * joining their codes with `;` in one SGR sequence.\n */\nexport const ATTRIBUTE_CODES: Readonly<Record<Attribute, number>> = Object.freeze({\n\tbold: 1,\n\tdim: 2,\n\titalic: 3,\n\tunderline: 4,\n\tinverse: 7,\n\tstrikethrough: 9,\n})\n\n/**\n * Holds the empty {@link Style} — no foreground, no background, no attributes — frozen. The\n * neutral starting point a base styler builds from, and what a renderer passes through\n * unchanged (it carries no codes). Deeply frozen, so it is safe to share as the base.\n */\nexport const EMPTY_STYLE: Style = Object.freeze({ attributes: Object.freeze([]) })\n\n/**\n * Lists every named {@link Color} except `default`, frozen — the colors the styler exposes as\n * chainable accessors. The source of truth for the color axis; the styler drives its\n * accessors from this array so the literals live in one place.\n */\nexport const COLORS: ReadonlyArray<Exclude<Color, 'default'>> = Object.freeze([\n\t'black',\n\t'red',\n\t'green',\n\t'yellow',\n\t'blue',\n\t'magenta',\n\t'cyan',\n\t'white',\n\t'brightBlack',\n\t'brightRed',\n\t'brightGreen',\n\t'brightYellow',\n\t'brightBlue',\n\t'brightMagenta',\n\t'brightCyan',\n\t'brightWhite',\n])\n\n/**\n * Lists every {@link Attribute}, frozen — the attributes the styler exposes as chainable\n * accessors. The source of truth for the attribute axis.\n */\nexport const ATTRIBUTES: readonly Attribute[] = Object.freeze([\n\t'bold',\n\t'dim',\n\t'italic',\n\t'underline',\n\t'inverse',\n\t'strikethrough',\n])\n\n/** Holds the SGR RESET parameter (0) — terminates a styled run, clearing all colors and attributes. */\nexport const RESET_CODE = 0\n\n/**\n * Holds the ESC control character (`U+001B`) that begins every ANSI escape sequence. Built\n * with `String.fromCharCode` so no raw control character appears in source.\n */\nexport const ESC = String.fromCharCode(27)\n\n/** Holds the BEL control character (`U+0007`) that can terminate an OSC sequence. */\nexport const BEL = String.fromCharCode(7)\n\n/** Holds the Control Sequence Introducer (`ESC[`) that opens every SGR sequence. */\nexport const CSI = `${ESC}[`\n\n/** Holds the full SGR reset sequence (`ESC[0m`) appended after a styled run. */\nexport const RESET = `${CSI}${RESET_CODE}m`\n\n/**\n * Matches any ANSI/VT escape sequence — CSI (SGR color/style plus cursor/erase/scroll,\n * including colon-parameterized SGR), OSC / DCS / PM / APC / SOS string sequences\n * (titles, hyperlinks, device strings), the `nF` charset-select family, and the\n * two-byte `Fp` / `Fe` / `Fs` sequences (for example `ESC 7`, `ESC D`, `ESC c` RIS). Global, so\n * `strip` removes every occurrence.\n *\n * @remarks\n * A global `RegExp` carries a mutable `lastIndex`; a scan must build a fresh `RegExp`\n * from this one's `source` + `flags` rather than reuse this instance's `lastIndex`. This\n * is the canonical definition, not a shared scanner. The alternation is ordered so the\n * CSI / string-family arms (which can start with a byte a later single-byte arm would\n * also match) win first; every arm uses disjoint, non-nested character classes, so the\n * match is linear in input length — no catastrophic backtracking (ReDoS-safe) even on an\n * adversarial run of digits inside an unterminated CSI. Built from `String.fromCharCode`\n * so no control-character literal appears in a regex source (the codebase idiom).\n */\nexport const ANSI_PATTERN = new RegExp(\n\t`${ESC}(?:` +\n\t\t`\\\\[[0-?]*[ -/]*[@-~]` +\n\t\t`|\\\\][^${BEL}${ESC}]*(?:${BEL}|${ESC}\\\\\\\\)` +\n\t\t`|[P^_X][^${BEL}${ESC}]*(?:${BEL}|${ESC}\\\\\\\\)` +\n\t\t`|[ -/]+[0-~]` +\n\t\t`|[0-?]` +\n\t\t`|[@-OQ-WYZ\\\\\\\\]` +\n\t\t`|[\\`-~]` +\n\t\t`)`,\n\t'g',\n)\n\n/**\n * Matches every C0 control character except `\\t` / `\\n` / `\\r` (which are meaningful\n * whitespace), plus DEL (`0x7F`) — the non-printing bytes {@link\n * import('./helpers.js').stripControls} removes. Global, ASCII-only source (no raw\n * control-character literal), so a scan builds a fresh `RegExp` the same way as\n * {@link ANSI_PATTERN} to avoid a mutated `lastIndex`.\n *\n * @remarks\n * Deliberately separate from {@link ANSI_PATTERN}: `strip()` must stay pure ANSI-escape\n * removal (width / alignment computations depend on it leaving raw C0 bytes alone), while\n * C0-stripping is an additional, orthogonal pass a non-TTY output sink applies on top.\n */\nexport const CONTROL_PATTERN = new RegExp(\n\t`[${String.fromCharCode(0)}-${String.fromCharCode(8)}${String.fromCharCode(11)}${String.fromCharCode(12)}${String.fromCharCode(14)}-${String.fromCharCode(31)}${String.fromCharCode(127)}]`,\n\t'g',\n)\n\n// Structured-logging constants — the severity order the level gate compares through, the\n// default colors a level renders in (styling is orthogonal to level — a level → color map,\n// not a level), and the default bounded-retention cap. UPPER_SNAKE, `Object.freeze`d, every\n// member exported.\n\n/**\n * Maps each {@link LogLevel} to its numeric severity — the ascending order the level gate compares\n * through (`debug` 0 < `info` 1 < `warn` 2 < `error` 3). A record is kept when its level's\n * severity is at or above the logger's threshold. The source of truth for level ordering.\n */\nexport const LEVEL_SEVERITY: Readonly<Record<LogLevel, number>> = Object.freeze({\n\tdebug: 0,\n\tinfo: 1,\n\twarn: 2,\n\terror: 3,\n})\n\n/**\n * Maps each {@link LogLevel} to its default label {@link Color} — the level's visual treatment, which\n * is a styling choice orthogonal to the level itself (never a separate pseudo-level). The\n * logger colors the level label through its styler with these; swapping a color never\n * changes leveling. `debug` is cyan, `info` blue, `warn` yellow, `error` red.\n *\n * @remarks\n * Excludes `default` so each value indexes a real styler accessor (the styler exposes a\n * getter per non-`default` {@link Color}) — a level always renders in a concrete color.\n */\nexport const LEVEL_COLORS: Readonly<Record<LogLevel, Exclude<Color, 'default'>>> = Object.freeze({\n\tdebug: 'cyan',\n\tinfo: 'blue',\n\twarn: 'yellow',\n\terror: 'red',\n})\n\n/**\n * Sets the default bounded-retention cap for a {@link import('./types.js').LoggerInterface} — at\n * most this many recent records are kept (oldest dropped first). Retention is always bounded — the\n * oldest record is dropped after the cap is reached; a consumer overrides it through `options.limit`.\n */\nexport const DEFAULT_LOG_LIMIT = 1000\n\n/** Sets the default {@link LogLevel} threshold a logger gates at when none is supplied — `info`. */\nexport const DEFAULT_LOG_LEVEL: LogLevel = 'info'\n\n/**\n * Lists every {@link LogLevel}, in ascending severity order — the levels a logger exposes as\n * methods and the manager fans out to. The source of truth for the level axis (drives\n * exhaustive tests); aligned with {@link LEVEL_SEVERITY}.\n */\nexport const LOG_LEVELS: readonly LogLevel[] = Object.freeze(['debug', 'info', 'warn', 'error'])\n\n// Narrative-rendering constants — the box-drawing junction sets the renderers frame with, the\n// status icons + colors a `Reporter.status` outcome shows, the tree connectors, and the default\n// widths / paddings / glyphs. UPPER_SNAKE, deeply `Object.freeze`d data, every member exported.\n// The box-drawing glyphs are the standard Unicode set (U+2500 block) — a fixed\n// external spec, so the literals are the source of truth.\n\n/**\n * Holds the complete {@link BorderChars} junction set for each {@link BorderStyle} — the standard\n * Unicode box-drawing glyphs at the four line weights. The renderers ({@link\n * import('./helpers.js').renderBox} / {@link import('./helpers.js').renderTable}) look the\n * style up here, so no glyph literal lives in a renderer. Deeply frozen.\n *\n * @remarks\n * `round` shares `single`'s edges and tees — only its corners differ (the rounded `╭╮╰╯`).\n */\nexport const BORDER_CHARS: Readonly<Record<BorderStyle, BorderChars>> = Object.freeze({\n\tsingle: Object.freeze({\n\t\thorizontal: '─',\n\t\tvertical: '│',\n\t\ttopLeft: '┌',\n\t\ttopRight: '┐',\n\t\tbottomLeft: '└',\n\t\tbottomRight: '┘',\n\t\tcross: '┼',\n\t\tteeDown: '┬',\n\t\tteeUp: '┴',\n\t\tteeRight: '├',\n\t\tteeLeft: '┤',\n\t}),\n\tdouble: Object.freeze({\n\t\thorizontal: '═',\n\t\tvertical: '║',\n\t\ttopLeft: '╔',\n\t\ttopRight: '╗',\n\t\tbottomLeft: '╚',\n\t\tbottomRight: '╝',\n\t\tcross: '╬',\n\t\tteeDown: '╦',\n\t\tteeUp: '╩',\n\t\tteeRight: '╠',\n\t\tteeLeft: '╣',\n\t}),\n\tround: Object.freeze({\n\t\thorizontal: '─',\n\t\tvertical: '│',\n\t\ttopLeft: '╭',\n\t\ttopRight: '╮',\n\t\tbottomLeft: '╰',\n\t\tbottomRight: '╯',\n\t\tcross: '┼',\n\t\tteeDown: '┬',\n\t\tteeUp: '┴',\n\t\tteeRight: '├',\n\t\tteeLeft: '┤',\n\t}),\n\theavy: Object.freeze({\n\t\thorizontal: '━',\n\t\tvertical: '┃',\n\t\ttopLeft: '┏',\n\t\ttopRight: '┓',\n\t\tbottomLeft: '┗',\n\t\tbottomRight: '┛',\n\t\tcross: '╋',\n\t\tteeDown: '┳',\n\t\tteeUp: '┻',\n\t\tteeRight: '┣',\n\t\tteeLeft: '┫',\n\t}),\n})\n\n/**\n * Maps each {@link StatusLevel} to its icon glyph — the leading mark a {@link\n * import('./types.js').ReporterInterface.status} outcome line shows: `success` ✔, `error` ✖,\n * `warn` ⚠, `info` ℹ. The narrative-outcome counterpart to a log level's label; frozen.\n */\nexport const STATUS_ICONS: Readonly<Record<StatusLevel, string>> = Object.freeze({\n\tsuccess: '✔',\n\terror: '✖',\n\twarn: '⚠',\n\tinfo: 'ℹ',\n})\n\n/**\n * Maps each {@link StatusLevel} to its {@link Color} — the icon + message color a `status` line renders\n * in (`success` green, `error` red, `warn` yellow, `info` blue). The visual treatment of a\n * narrative outcome, colored through the reporter's styler; orthogonal to leveling, like\n * {@link LEVEL_COLORS}. Excludes `default` so each value indexes a real styler accessor.\n */\nexport const STATUS_COLORS: Readonly<Record<StatusLevel, Exclude<Color, 'default'>>> =\n\tObject.freeze({\n\t\tsuccess: 'green',\n\t\terror: 'red',\n\t\twarn: 'yellow',\n\t\tinfo: 'blue',\n\t})\n\n/**\n * Lists every {@link StatusLevel}, frozen — the outcomes a `status` line supports (drives exhaustive\n * tests). The source of truth for the status axis; aligned with {@link STATUS_ICONS} /\n * {@link STATUS_COLORS}.\n */\nexport const STATUS_LEVELS: readonly StatusLevel[] = Object.freeze([\n\t'success',\n\t'error',\n\t'warn',\n\t'info',\n])\n\n/**\n * Sets the default visible column width for the width-aware renderers — the separator rule and a\n * {@link import('./helpers.js').renderBox} with no explicit `width`, and the reporter's\n * `section` rule. A sane terminal default (80 columns); a caller overrides it per-call or through\n * {@link import('./types.js').ReporterOptions}`.width`.\n */\nexport const DEFAULT_WIDTH = 80\n\n/** Sets the default horizontal padding inside a box's edges ({@link import('./helpers.js').renderBox}) — one cell. */\nexport const DEFAULT_PADDING = 1\n\n/** Sets the default {@link BorderStyle} the box / table renderers frame with when none is given — `single`. */\nexport const DEFAULT_BORDER: BorderStyle = 'single'\n\n/** Sets the default cell {@link Alignment} a {@link import('./types.js').ColumnSpec} uses when none is given — `left`. */\nexport const DEFAULT_ALIGN: Alignment = 'left'\n\n/** Holds the default fill character {@link import('./helpers.js').renderSeparator} draws its rule with — `─`. */\nexport const SEPARATOR_FILL = '─'\n\n/**\n * Holds the single padding cell on each side of a separator's embedded title (` title `) — keeps the\n * title from butting against the rule. One space.\n */\nexport const SEPARATOR_TITLE_GAP = ' '\n\n/**\n * Sets the number of milliseconds at or above which {@link import('./helpers.js').formatDuration}\n * (and so `Reporter.timing`) switches from a `…ms` rendering to a `…s` (seconds, 2 d.p.)\n * rendering — exactly one second.\n */\nexport const SECOND_MS = 1000\n\n// Console-interception constants — the default set of `console.*` methods a Capture patches, the\n// default bounded-buffer cap, and the CaptureLevel → LogLevel projection the optional sink forward\n// routes through. UPPER_SNAKE, `Object.freeze`d, every member exported. The five level\n// names are the universal `console.*` method names — a fixed external surface, so the literals are\n// the source of truth.\n\n/**\n * Lists every {@link CaptureLevel}, frozen — the `console.*` methods a {@link\n * import('./types.js').CaptureInterface} intercepts by default (and the source of truth for the\n * capture-level axis; drives exhaustive tests). The universal console methods: `log`, `info`,\n * `warn`, `error`, `debug`.\n */\nexport const CAPTURE_LEVELS: readonly CaptureLevel[] = Object.freeze([\n\t'log',\n\t'info',\n\t'warn',\n\t'error',\n\t'debug',\n])\n\n/**\n * Sets the default bounded-buffer cap for a {@link import('./types.js').CaptureInterface} — at most this\n * many recent {@link CapturedMessage}s are retained per buffer (the total buffer and each by-level\n * bucket; oldest dropped first). Capture retention is always bounded so a long-running capture can\n * never grow without bound (the same retention precedent as {@link DEFAULT_LOG_LIMIT}); a consumer\n * overrides it through `options.limit`.\n */\nexport const DEFAULT_CAPTURE_LIMIT = 1000\n\n/**\n * Maps each {@link CaptureLevel} to its {@link LogLevel} for the optional sink forward — the projection the\n * Capture routes through when writing an intercepted call to a {@link\n * import('./types.js').SinkInterface} (`sink.write(text, CAPTURE_LEVEL_MAP[level])`). `warn` /\n * `error` / `debug` / `info` map to their matching {@link LogLevel}; `log` maps to `info` (a plain\n * console log is informational — the default stream), so a stream-aware sink routes `warn` / `error`\n * captures to the right stream. The source of truth for the capture-to-log projection.\n */\nexport const CAPTURE_LEVEL_MAP: Readonly<Record<CaptureLevel, LogLevel>> = Object.freeze({\n\tlog: 'info',\n\tinfo: 'info',\n\twarn: 'warn',\n\terror: 'error',\n\tdebug: 'debug',\n})\n\n// Live-animation constants — the spinner's glyph frame set + default timer period, and the\n// determinate bar's fill / empty glyphs + default track width. UPPER_SNAKE, `Object.freeze`d, every\n// member exported. The braille spinner frames + the block bar glyphs are the standard\n// Unicode sets (the braille-patterns block U+2800 / the block-elements `█` U+2588 / `░` U+2591) — a\n// fixed external glyph spec, so the literals are the source of truth. There is one frame set and\n// one bar glyph pair; a caller overrides either through options rather than declaring a second.\n\n/**\n * Holds the default spinner frame cycle a {@link import('./types.js').SpinnerInterface} advances through —\n * the ten braille-pattern glyphs (U+2800 block) that read as a smoothly rotating dot, the universal\n * terminal-spinner convention. Frozen; a consumer swaps the whole cycle through `options.frames`.\n *\n * @remarks\n * Braille glyphs are single visible cells, so every frame occupies one column — the spinner glyph\n * never shifts the message beside it as it advances. The source of truth for the default frame axis.\n */\nexport const SPINNER_FRAMES: readonly string[] = Object.freeze([\n\t'⠋',\n\t'⠙',\n\t'⠹',\n\t'⠸',\n\t'⠼',\n\t'⠴',\n\t'⠦',\n\t'⠧',\n\t'⠇',\n\t'⠏',\n])\n\n/**\n * Sets the default timer period in milliseconds between a {@link import('./types.js').SpinnerInterface}'s\n * frames — the `setInterval` interval `start()` arms. Eighty milliseconds (≈12.5 frames/second) is\n * the conventional spinner cadence: fast enough to read as motion, slow enough not to thrash a\n * terminal. A consumer overrides it through `options.interval`.\n */\nexport const DEFAULT_SPINNER_INTERVAL = 80\n\n/**\n * Holds the default filled-cell glyph {@link import('./helpers.js').renderBar} draws the completed run of a\n * progress bar with — the full block `█` (U+2588). A single visible cell; a consumer overrides it\n * through {@link import('./types.js').BarOptions}`.fill`.\n */\nexport const BAR_FILL = '█'\n\n/**\n * Holds the default empty-cell glyph {@link import('./helpers.js').renderBar} draws the remaining run of a\n * progress bar with — the light-shade block `░` (U+2591). A single visible cell; a consumer overrides\n * it through {@link import('./types.js').BarOptions}`.empty`.\n */\nexport const BAR_EMPTY = '░'\n\n/**\n * Sets the default visible cell count of a progress-bar track — the glyph run {@link\n * import('./helpers.js').renderBar} fills (and a {@link import('./types.js').ProgressInterface} sizes\n * its bar to). Thirty cells is a compact, terminal-friendly default; a consumer overrides it through\n * `options.width`. Distinct from {@link DEFAULT_WIDTH} (the renderers' 80-column line width) — a bar\n * track is one inline element, not a full-width rule.\n */\nexport const DEFAULT_BAR_WIDTH = 30\n\n// The default theme — the semantic style vocabulary every entity speaks unless a consumer\n// supplies its own. Assembled from the constants above (LEVEL_COLORS / STATUS_ICONS /\n// STATUS_COLORS), never restating them: a level's color, a status's icon + color each keep\n// one source, and the theme is the shape that binds them to a role. UPPER_SNAKE, deeply\n// `Object.freeze`d data.\n\n/**\n * Holds the default {@link Theme} — every role bound to its default {@link Style}, deeply frozen.\n * The base {@link import('./factories.js').createTheme} merges over, and the theme every\n * entity uses when none is supplied.\n *\n * @remarks\n * - `levels` — each {@link LogLevel} label in its {@link LEVEL_COLORS} color, no attributes.\n * - `statuses` — each {@link StatusLevel}'s {@link STATUS_ICONS} glyph in its\n * {@link STATUS_COLORS} color.\n * - `accent` — `cyan`: the spinner glyph, the progress fill, a step prefix.\n * - `chrome` — `dim`: separators, box / table / tree frames, and a log line's timestamp /\n * name / data surround. A color-free attribute, so chrome recedes on any background.\n */\nexport const DEFAULT_THEME: Theme = Object.freeze({\n\tlevels: Object.freeze({\n\t\tdebug: Object.freeze({ foreground: LEVEL_COLORS.debug, attributes: EMPTY_STYLE.attributes }),\n\t\tinfo: Object.freeze({ foreground: LEVEL_COLORS.info, attributes: EMPTY_STYLE.attributes }),\n\t\twarn: Object.freeze({ foreground: LEVEL_COLORS.warn, attributes: EMPTY_STYLE.attributes }),\n\t\terror: Object.freeze({ foreground: LEVEL_COLORS.error, attributes: EMPTY_STYLE.attributes }),\n\t}),\n\tstatuses: Object.freeze({\n\t\tsuccess: Object.freeze({\n\t\t\ticon: STATUS_ICONS.success,\n\t\t\tstyle: Object.freeze({\n\t\t\t\tforeground: STATUS_COLORS.success,\n\t\t\t\tattributes: EMPTY_STYLE.attributes,\n\t\t\t}),\n\t\t}),\n\t\terror: Object.freeze({\n\t\t\ticon: STATUS_ICONS.error,\n\t\t\tstyle: Object.freeze({ foreground: STATUS_COLORS.error, attributes: EMPTY_STYLE.attributes }),\n\t\t}),\n\t\twarn: Object.freeze({\n\t\t\ticon: STATUS_ICONS.warn,\n\t\t\tstyle: Object.freeze({ foreground: STATUS_COLORS.warn, attributes: EMPTY_STYLE.attributes }),\n\t\t}),\n\t\tinfo: Object.freeze({\n\t\t\ticon: STATUS_ICONS.info,\n\t\t\tstyle: Object.freeze({ foreground: STATUS_COLORS.info, attributes: EMPTY_STYLE.attributes }),\n\t\t}),\n\t}),\n\taccent: Object.freeze({ foreground: 'cyan', attributes: EMPTY_STYLE.attributes }),\n\tchrome: Object.freeze({ attributes: Object.freeze<readonly Attribute[]>(['dim']) }),\n})\n","import type { ConsoleErrorCode } from './types.js'\n\n// An internal invariant / unreachable-guard violation `throw`s, always a\n// `ConsoleError` carrying a machine-readable `code` so a `catch` branches on\n// `error.code` instead of parsing the message.\n\n/**\n * Represents an error thrown by the console layer.\n *\n * @remarks\n * Carries a {@link ConsoleErrorCode} and an optional `context` bag. Thrown for: an\n * internal invariant violated at a defensive, structurally-unreachable guard\n * (`INVARIANT`).\n */\nexport class ConsoleError extends Error {\n\treadonly code: ConsoleErrorCode\n\treadonly context?: Readonly<Record<string, unknown>>\n\n\tconstructor(\n\t\tcode: ConsoleErrorCode,\n\t\tmessage: string,\n\t\tcontext?: Readonly<Record<string, unknown>>,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'ConsoleError'\n\t\tthis.code = code\n\t\tif (context !== undefined) this.context = context\n\t}\n}\n\n/**\n * Narrows an unknown caught value to a {@link ConsoleError}.\n *\n * @param value - The value to test (typically a `catch` binding)\n * @returns True if `value` is a {@link ConsoleError}; false otherwise\n *\n * @example\n * ```ts\n * try {\n * \tcreateStyler().style\n * } catch (error) {\n * \tif (isConsoleError(error) && error.code === 'INVARIANT') report(error)\n * }\n * ```\n */\nexport function isConsoleError(value: unknown): value is ConsoleError {\n\treturn value instanceof ConsoleError\n}\n","import type {\n\tAlignment,\n\tBarOptions,\n\tBoxOptions,\n\tLogLevel,\n\tLogRecord,\n\tSeparatorOptions,\n\tStyle,\n\tStylerInterface,\n\tTableOptions,\n\tTreeNode,\n\tTreeOptions,\n\tTheme,\n\tWriterSet,\n} from './types.js'\nimport {\n\tANSI_PATTERN,\n\tBAR_EMPTY,\n\tBAR_FILL,\n\tBORDER_CHARS,\n\tCONTROL_PATTERN,\n\tDEFAULT_ALIGN,\n\tDEFAULT_BAR_WIDTH,\n\tDEFAULT_BORDER,\n\tDEFAULT_PADDING,\n\tDEFAULT_WIDTH,\n\tLEVEL_SEVERITY,\n\tSECOND_MS,\n\tSEPARATOR_FILL,\n\tSEPARATOR_TITLE_GAP,\n} from './constants.js'\n\n// Pure, universal string helpers for the console / terminal system. `strip` removes\n// ANSI escapes; `width` is the visible length (strip then count). Both are needed later\n// by the box / table / progress layout — kept here, environment-agnostic, so every\n// surface shares one implementation. Every function exported.\n// The logging helpers (`meetsLevel`, `formatTime`, `formatRecord`) are likewise pure and\n// shared — the level gate's comparison and the styled-line layout, kept off the impl class.\n\n/**\n * Removes every ANSI escape sequence from `text`, returning the plain visible string.\n *\n * @remarks\n * Strips SGR color/style codes and other CSI controls (cursor, erase) plus OSC\n * sequences (titles, hyperlinks) — see {@link ANSI_PATTERN}. A fresh `RegExp` is built\n * per call from the canonical pattern's `source` + `flags`, so the shared global\n * pattern's `lastIndex` is never mutated across calls (re-entrant and deterministic).\n *\n * @param text - Any string, styled or plain\n * @returns `text` with all ANSI escapes removed\n *\n * @example\n * ```ts\n * strip('\\x1b[31mred\\x1b[0m') // 'red'\n * ```\n */\nexport function strip(text: string): string {\n\treturn text.replace(new RegExp(ANSI_PATTERN.source, ANSI_PATTERN.flags), '')\n}\n\n/**\n * Removes every non-printing C0 control character from `text` except `\\t` / `\\n` / `\\r`\n * (meaningful whitespace), plus DEL — returning the sanitized string.\n *\n * @remarks\n * Deliberately separate from {@link strip} (ANSI-escape removal only, so `width` /\n * `align` stay untouched) — this is the additional pass a non-TTY output sink applies\n * on top of `strip`, so a captured `\\x07` bell or stray `\\x00` never reaches a log file\n * / non-terminal target. A fresh `RegExp` is built per call from {@link CONTROL_PATTERN}'s\n * `source` + `flags`, the same re-entrant idiom as `strip`.\n *\n * @param text - Any string, possibly carrying raw control bytes\n * @returns `text` with C0 controls (other than tab/newline/CR) and DEL removed\n *\n * @example\n * ```ts\n * stripControls('a\\x07b\\nc') // 'ab\\nc'\n * ```\n */\nexport function stripControls(text: string): string {\n\treturn text.replace(new RegExp(CONTROL_PATTERN.source, CONTROL_PATTERN.flags), '')\n}\n\n/**\n * Measures how many visible columns `text` occupies — its length after ANSI escapes are stripped, counted in\n * Unicode code points (so an astral character such as an emoji counts as one, not the\n * two UTF-16 units `String.length` would report).\n *\n * @remarks\n * The basis for terminal layout (box / table / progress alignment): the column count a\n * styled string occupies, independent of its escape codes. It does not account for\n * wide (CJK / fullwidth) glyphs occupying two cells — a deliberate, documented\n * simplification at this layer; callers needing east-asian width handle it above.\n *\n * @param text - Any string, styled or plain\n * @returns The count of visible code points\n *\n * @example\n * ```ts\n * width('\\x1b[1mhi\\x1b[0m') // 2\n * ```\n */\nexport function width(text: string): number {\n\treturn [...strip(text)].length\n}\n\n/**\n * Snapshots and deeply freezes one {@link Style} value.\n *\n * @param style - The caller-owned style to snapshot\n * @returns A frozen style record with an independently frozen attributes list\n *\n * @remarks\n * The record spread captures accessor values once and preserves each present color channel.\n * Copying `attributes` prevents later mutation of a caller-owned list from changing the result.\n *\n * @example\n * ```ts\n * freezeStyle({ foreground: 'red', attributes: ['bold'] })\n * ```\n */\nexport function freezeStyle(style: Style): Style {\n\treturn Object.freeze({ ...style, attributes: Object.freeze([...style.attributes]) })\n}\n\n/**\n * Checks whether a record at `level` passes a logger gated at `threshold` — that is, its severity\n * is at or above the threshold's.\n *\n * @remarks\n * The level gate (the comparison lives here, not inlined in the logger). Reads\n * the ascending {@link LEVEL_SEVERITY} order: `meetsLevel('warn', 'error')` is `true`\n * (error ≥ warn), `meetsLevel('warn', 'info')` is `false` (info < warn).\n *\n * @param threshold - The logger's configured minimum {@link LogLevel}\n * @param level - The record's {@link LogLevel}\n * @returns True if `level` is at least as severe as `threshold`; false otherwise\n *\n * @example\n * ```ts\n * meetsLevel('info', 'error') // true\n * meetsLevel('error', 'warn') // false\n * ```\n */\nexport function meetsLevel(threshold: LogLevel, level: LogLevel): boolean {\n\treturn LEVEL_SEVERITY[level] >= LEVEL_SEVERITY[threshold]\n}\n\n/**\n * Selects the member of a {@link WriterSet} a {@link LogLevel} routes to — `error` to `error`,\n * `warn` to `warn`, every other level and an omitted level to `log`.\n *\n * @remarks\n * The single owner of the level-to-target decision every sink backend shares, so core's console\n * sink, the browser `%c` sink, and the server stream sink cannot drift apart. A backend that sends\n * two levels to one destination passes the same member twice: the server sink routes `warn`\n * alongside `error` by supplying its error stream for both, which matches `console.warn` writing\n * to `stderr`. The member type is the caller's, so the same leaf selects a bound console method, a\n * stream target, or a per-target styling fact.\n *\n * @param level - The originating record's {@link LogLevel}, or `undefined` when the caller has none\n * @param writers - See {@link WriterSet}\n * @returns The member `level` routes to\n *\n * @example\n * ```ts\n * selectWriter('error', { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stderr'\n * selectWriter('warn', { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stderr'\n * selectWriter('debug', { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stdout'\n * selectWriter(undefined, { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stdout'\n * ```\n */\nexport function selectWriter<T>(level: LogLevel | undefined, writers: WriterSet<T>): T {\n\tif (level === 'error') return writers.error\n\tif (level === 'warn') return writers.warn\n\treturn writers.log\n}\n\n/**\n * Formats a {@link LogRecord}'s `time` (epoch milliseconds) as an ISO-8601 timestamp string.\n *\n * @remarks\n * Deterministic and serializable — `new Date(time).toISOString()`, for example\n * `1716900000000 → '2024-05-28T12:40:00.000Z'`. The timestamp portion of the formatted log\n * line; kept a pure helper so the line layout and the logger stay decoupled.\n *\n * @param time - Epoch milliseconds (a record's `time`)\n * @returns The ISO-8601 timestamp\n */\nexport function formatTime(time: number): string {\n\treturn new Date(time).toISOString()\n}\n\n/**\n * Formats a {@link LogRecord} into a single styled line — the default human line layout a\n * {@link import('./types.js').LoggerInterface} writes to its sink.\n *\n * @remarks\n * Layout: `{time} {LEVEL} {[name]} {message}{ data}` — the ISO timestamp (dimmed), the\n * upper-cased level label (rendered through the theme's level role),\n * the originating logger's `name` in brackets (omitted when absent), the message, and the\n * structured `data` appended as compact JSON (omitted when absent / empty). Coloring flows\n * through the injected `styler`, so a disabled styler yields a plain line and a browser\n * `%c` styler retargets it — the layout never changes. Pure: same record + styler →\n * same line.\n *\n * @param record - The {@link LogRecord} to render\n * @param styler - The {@link StylerInterface} the labels are colored through\n * @param theme - The {@link Theme} supplying the level and chrome roles\n * @returns The formatted, styled line (no trailing newline — the sink's target adds it)\n *\n * @example\n * ```ts\n * formatRecord(\n * \t{ level: 'warn', message: 'low disk', time: 0, name: 'fs' },\n * \tcreateStyler(),\n * \tDEFAULT_THEME,\n * )\n * // '<dim>1970-01-01T00:00:00.000Z</> <yellow>WARN</> [fs] low disk'\n * ```\n */\nexport function formatRecord(record: LogRecord, styler: StylerInterface, theme: Theme): string {\n\tconst time = styler.render(theme.chrome, formatTime(record.time))\n\tconst label = styler.render(theme.levels[record.level], record.level.toUpperCase())\n\tconst name =\n\t\trecord.name === undefined ? '' : ` ${styler.render(theme.chrome, `[${record.name}]`)}`\n\tconst data =\n\t\trecord.data === undefined || Object.keys(record.data).length === 0\n\t\t\t? ''\n\t\t\t: ` ${styler.render(theme.chrome, JSON.stringify(record.data))}`\n\treturn `${time} ${label}${name} ${record.message}${data}`\n}\n\n/**\n * Pads (or, when over budget, truncates) `text` to exactly `columns` visible columns, positioning\n * it by `alignment`. The width primitive the box / table renderers align every cell with.\n *\n * @remarks\n * Measures with {@link width} (visible code points, ANSI-aware), so a styled string aligns by\n * its visible content, not its escape codes. When `width(text) < columns`, the deficit is added\n * as spaces — all trailing (`left`), all leading (`right`), or split with the extra space on\n * the right (`center`). When `width(text) > columns`, the visible characters are sliced to\n * `columns` (a defensive guard — the renderers size columns to fit, so this is rarely hit; it\n * slices the stripped text, so it never bisects an escape sequence into a broken half).\n *\n * @param text - The cell content (may be styled)\n * @param columns - The visible column count to fit `text` into\n * @param alignment - Where to position `text` within that budget; defaults to `left`\n * @returns `text` fitted to exactly `columns` visible columns\n *\n * @example\n * ```ts\n * align('hi', 5) // 'hi '\n * align('hi', 5, 'right') // ' hi'\n * align('hi', 5, 'center') // ' hi '\n * ```\n */\nexport function align(text: string, columns: number, alignment: Alignment = DEFAULT_ALIGN): string {\n\tconst visible = width(text)\n\tif (visible > columns) return [...strip(text)].slice(0, columns).join('')\n\tconst deficit = columns - visible\n\tif (alignment === 'right') return `${' '.repeat(deficit)}${text}`\n\tif (alignment === 'center') {\n\t\tconst left = Math.floor(deficit / 2)\n\t\treturn `${' '.repeat(left)}${text}${' '.repeat(deficit - left)}`\n\t}\n\treturn `${text}${' '.repeat(deficit)}`\n}\n\n/**\n * Formats a millisecond duration as a compact human string — `…ms` below one second, `…s`\n * (seconds to 2 decimal places) at or above one second. The timing rendering behind\n * {@link import('./types.js').ReporterInterface.timing}.\n *\n * @remarks\n * `999 → '999ms'`, `1000 → '1.00s'`, `1230 → '1.23s'` (the threshold is {@link SECOND_MS}).\n * Pure and deterministic; kept a shared helper so the layout and the reporter stay decoupled.\n *\n * @param ms - The duration in milliseconds\n * @returns The formatted duration (`'<n>ms'` or `'<n>s'`)\n */\nexport function formatDuration(ms: number): string {\n\treturn ms < SECOND_MS ? `${ms}ms` : `${(ms / SECOND_MS).toFixed(2)}s`\n}\n\n/**\n * Colors `text` through `styler`, or returns it verbatim when `styler` is `undefined` — the\n * single optional-styling primitive every renderer applies to its border / title / connector\n * glyphs (the one styler seam, shared, never re-hand-rolled per renderer).\n *\n * @remarks\n * The renderers all take an optional `styler`: present ⇒ glyphs are colored, absent ⇒ plain.\n * Folding that `styler === undefined ? text : styler(text)` ternary into one exported helper\n * keeps the renderers terse and the styling decision in one tested place. A disabled styler\n * (`enabled: false`) is still a styler — it returns its text verbatim — so passing one paints\n * a no-op, exactly as omitting it does.\n *\n * @param styler - The {@link StylerInterface} to color with, or `undefined` for no styling\n * @param text - The glyphs / text to color\n * @param style - An optional {@link Style} to render by value instead of the styler's chain\n * @returns `styler(text)` when a styler is given, else `text` unchanged\n */\nexport function paint(styler: StylerInterface | undefined, text: string, style?: Style): string {\n\tif (styler === undefined) return text\n\treturn style === undefined ? styler(text) : styler.render(style, text)\n}\n\n/**\n * Repeats `unit` until it fills exactly `columns` visible columns, trimming a trailing partial\n * unit so the run is never over-wide — the fill primitive the separator + box edges draw with.\n *\n * @remarks\n * Counts in code points ({@link width}-consistent), so a multi-cell or astral `unit` is laid\n * down whole and the result is sliced to exactly `columns` visible columns. `columns <= 0` (or an\n * empty / zero-width `unit`) yields `''`.\n *\n * @param unit - The (possibly multi-character) fill unit\n * @param columns - The visible column count to fill\n * @returns `unit` tiled to exactly `columns` visible columns\n *\n * @example\n * ```ts\n * repeatTo('─', 4) // '────'\n * repeatTo('=-', 5) // '=-=-='\n * ```\n */\nexport function repeatTo(unit: string, columns: number): string {\n\tif (columns <= 0) return ''\n\tconst per = width(unit)\n\tif (per === 0) return ''\n\tconst built = unit.repeat(Math.ceil(columns / per))\n\treturn [...built].slice(0, columns).join('')\n}\n\n/**\n * Returns the cell at `index` of a (possibly ragged) row — `''` when the row is shorter than the\n * column count, so a short row pads out instead of throwing (the ragged-row guard\n * {@link renderTable} reads every cell through).\n *\n * @param row - The row's cells\n * @param index - The column index to read\n * @returns The cell text, or `''` when the row has no cell at `index`\n */\nexport function cellAt(row: readonly string[], index: number): string {\n\treturn row[index] ?? ''\n}\n\n/**\n * Renders a horizontal rule — an optional centered title embedded in a line of fill characters,\n * to a fixed visible width. Pure: same {@link SeparatorOptions} → same string.\n *\n * @remarks\n * - **Plain rule.** With no `title`, returns `fill` repeated to `width` visible columns.\n * - **Titled rule.** With a `title`, centers ` title ` (one {@link SEPARATOR_TITLE_GAP} each\n * side) in the line, splitting the remaining fill between the two sides (the extra column,\n * when the remainder is odd, goes to the right). The visible width stays exactly `width`,\n * even when the title is styled (the title's escape codes don't count toward the budget) —\n * a title at least as wide as `width` yields only the gapped title (no fill).\n * - **Styling.** When `options.styler` is given, the fill runs (and the embedded title) are\n * colored through it; the layout is identical with or without color, since width is measured\n * on the visible content (width-aware through {@link width}).\n *\n * @param options - See {@link SeparatorOptions}\n * @returns The rule line (no trailing newline)\n *\n * @example\n * ```ts\n * renderSeparator({ width: 10 }) // '──────────'\n * renderSeparator({ title: 'Build', width: 13 }) // '── Build ──' (centered)\n * ```\n */\nexport function renderSeparator(options: SeparatorOptions): string {\n\tconst total = options.width ?? DEFAULT_WIDTH\n\tconst fill = options.fill ?? SEPARATOR_FILL\n\tif (options.title === undefined)\n\t\treturn paint(options.styler, repeatTo(fill, total), options.style)\n\tconst gapped = `${SEPARATOR_TITLE_GAP}${paint(options.styler, options.title, options.style)}${SEPARATOR_TITLE_GAP}`\n\tconst room = total - width(options.title) - SEPARATOR_TITLE_GAP.length * 2\n\tif (room <= 0) return gapped\n\tconst left = Math.floor(room / 2)\n\treturn `${paint(options.styler, repeatTo(fill, left), options.style)}${gapped}${paint(options.styler, repeatTo(fill, room - left), options.style)}`\n}\n\n/**\n * Renders `content` framed in box-drawing characters, optionally captioned, width-aware so\n * styled content stays aligned inside the frame. Pure: same {@link BoxOptions} → same string.\n *\n * @remarks\n * - **Lines.** `content` is split on `\\n` or `\\r\\n`, so caller text written on Windows frames\n * exactly as the same text written on POSIX; a lone `\\r` is kept inside its line (it is a\n * cursor control — the animation frame prefix — not a line separator). Each line is padded\n * (left-aligned) to the inner\n * width by {@link align} — measured on visible width, so a styled line never breaks the\n * right edge. The inner width is the widest line's visible width (or `width − borders −\n * 2·padding` when an explicit `width` is given and is wider), plus `padding` blank cells\n * inside each {@link BorderChars.vertical} edge.\n * - **Title.** An optional `title` is embedded in the top border (` title `), the remaining\n * top edge drawn as fill; a title wider than the inner width widens the box to fit it.\n * - **Border + styling.** The {@link BorderStyle} (`options.border`, default\n * {@link DEFAULT_BORDER}) selects the glyph set from {@link BORDER_CHARS}; `options.styler`\n * colors the frame + title when given (content cells are written as supplied).\n * - **Multi-line result.** Returns the box as `\\n`-joined rows (top, one row per content line,\n * bottom) with no trailing newline.\n *\n * @param options - See {@link BoxOptions}\n * @returns The framed box (multiple lines joined by `\\n`)\n */\nexport function renderBox(options: BoxOptions): string {\n\tconst chars = BORDER_CHARS[options.border ?? DEFAULT_BORDER]\n\tconst padding = Math.max(0, Math.trunc(options.padding ?? DEFAULT_PADDING))\n\tconst styler = options.styler\n\t// Split on a line feed or a CRLF pair, so caller text written on Windows frames exactly as the\n\t// same text written on POSIX. A lone carriage return is deliberately not a separator: the\n\t// animation frame prefix is a bare `\\r` cursor control, so splitting on it would cut a frame in\n\t// half. The literal is local because this is the one caller-text split in the module.\n\tconst lines = options.content.split(/\\r\\n|\\n/)\n\t// The inner content width: the widest line, the title (when present), and any explicit\n\t// `width` budget (minus the two edges and the two padding gutters) all compete — the\n\t// widest wins, so nothing is ever clipped and an explicit width only ever pads outward.\n\t// The title's claim is its embedded form ` title ` (a gap each side) plus one lead fill\n\t// glyph, all spanning `inner + 2·padding` — so the top edge stays exactly as wide as the\n\t// rest of the box (the frame is always rectangular) and a long title widens the box.\n\tconst titleRoom =\n\t\toptions.title === undefined\n\t\t\t? 0\n\t\t\t: width(options.title) + SEPARATOR_TITLE_GAP.length * 2 + 1 - padding * 2\n\tconst budget = options.width === undefined ? 0 : options.width - 2 - padding * 2\n\tconst inner = lines.reduce(\n\t\t(max, line) => Math.max(max, width(line)),\n\t\tMath.max(0, titleRoom, budget),\n\t)\n\tconst gutter = ' '.repeat(padding)\n\tconst bar = paint(styler, chars.vertical, options.style)\n\t// The top border — the two corners with the horizontal run between, optionally carrying a\n\t// leading ` title ` embedded in the run. `span` is the full inner run (`inner + 2·padding`):\n\t// with no `title` the whole run is fill between the corners; with one, ` title ` sits after a\n\t// single leading fill glyph, the remainder drawn as fill — its visible width stays `span` (the\n\t// title's escape codes don't count).\n\tconst span = inner + padding * 2\n\tlet top: string\n\tif (options.title === undefined) {\n\t\ttop = paint(\n\t\t\tstyler,\n\t\t\t`${chars.topLeft}${repeatTo(chars.horizontal, span)}${chars.topRight}`,\n\t\t\toptions.style,\n\t\t)\n\t} else {\n\t\tconst caption = `${SEPARATOR_TITLE_GAP}${options.title}${SEPARATOR_TITLE_GAP}`\n\t\tconst room = span - width(caption)\n\t\tconst lead = paint(styler, repeatTo(chars.horizontal, 1), options.style)\n\t\tconst rest =\n\t\t\troom - 1 <= 0 ? '' : paint(styler, repeatTo(chars.horizontal, room - 1), options.style)\n\t\ttop = `${paint(styler, chars.topLeft, options.style)}${lead}${paint(styler, caption, options.style)}${rest}${paint(styler, chars.topRight, options.style)}`\n\t}\n\tconst bottom = paint(\n\t\tstyler,\n\t\t`${chars.bottomLeft}${repeatTo(chars.horizontal, inner + padding * 2)}${chars.bottomRight}`,\n\t\toptions.style,\n\t)\n\tconst body = lines.map((line) => `${bar}${gutter}${align(line, inner)}${gutter}${bar}`)\n\treturn [top, ...body, bottom].join('\\n')\n}\n\n/**\n * Renders a bordered grid of `columns` + `rows` with per-column alignment and width-aware\n * column sizing. Pure: same {@link TableOptions} → same string.\n *\n * @remarks\n * - **Column sizing — visible width.** Each column is sized to the widest visible width\n * ({@link width}) among its header label and its cells, so an already-styled cell never\n * breaks the column (its escape codes don't count toward the width).\n * - **Ragged rows.** A row shorter than the column count is padded with empty cells; a longer\n * row is truncated to the column count — a ragged input never throws.\n * - **Alignment.** Each cell is positioned by its column's {@link ColumnSpec.align} (default\n * {@link DEFAULT_ALIGN}) through {@link align}.\n * - **Frame.** The {@link BorderStyle} (`options.border`, default {@link DEFAULT_BORDER})\n * draws the outer frame, the header rule (a `teeRight … cross … teeLeft` line), and the\n * `vertical` column separators; `options.styler` colors the frame + header labels when\n * given. Returns the table as `\\n`-joined rows (top, header, rule, one row per data row,\n * bottom), no trailing newline.\n *\n * @param options - See {@link TableOptions}\n * @returns The rendered table (multiple lines joined by `\\n`)\n */\nexport function renderTable(options: TableOptions): string {\n\tconst chars = BORDER_CHARS[options.border ?? DEFAULT_BORDER]\n\tconst styler = options.styler\n\tconst columns = options.columns\n\t// Each column's visible width: the max of its header label and every cell it holds.\n\tconst widths = columns.map((column, index) =>\n\t\toptions.rows.reduce(\n\t\t\t(max, row) => Math.max(max, width(cellAt(row, index))),\n\t\t\twidth(column.label),\n\t\t),\n\t)\n\tconst aligns = columns.map((column) => column.align ?? DEFAULT_ALIGN)\n\tconst rows = [\n\t\tcolumns.map((column) => paint(styler, column.label, options.style)),\n\t\t...options.rows.map((row) => columns.map((_column, index) => cellAt(row, index))),\n\t]\n\t// Frame the header and every body row in one pass: align each cell to its column width, add\n\t// one-space gutters, and join with the painted vertical separator.\n\tconst renderedRows = rows.map((cells) => {\n\t\tconst bar = paint(styler, chars.vertical, options.style)\n\t\tconst inner = cells\n\t\t\t.map(\n\t\t\t\t(cell, index) =>\n\t\t\t\t\t` ${align(cell, widths[index] ?? width(cell), aligns[index] ?? DEFAULT_ALIGN)} `,\n\t\t\t)\n\t\t\t.join(bar)\n\t\treturn `${bar}${inner}${bar}`\n\t})\n\tconst segments = widths.map((columnWidth) => repeatTo(chars.horizontal, columnWidth + 2))\n\tconst top = paint(\n\t\tstyler,\n\t\t`${chars.topLeft}${segments.join(chars.teeDown)}${chars.topRight}`,\n\t\toptions.style,\n\t)\n\tconst rule = paint(\n\t\tstyler,\n\t\t`${chars.teeRight}${segments.join(chars.cross)}${chars.teeLeft}`,\n\t\toptions.style,\n\t)\n\tconst bottom = paint(\n\t\tstyler,\n\t\t`${chars.bottomLeft}${segments.join(chars.teeUp)}${chars.bottomRight}`,\n\t\toptions.style,\n\t)\n\treturn [top, ...renderedRows.slice(0, 1), rule, ...renderedRows.slice(1), bottom].join('\\n')\n}\n\n/**\n * Renders a nested {@link TreeNode} tree with box-drawing connectors. Pure: same\n * {@link TreeOptions} → same string.\n *\n * @remarks\n * The `root` label is the unindented first line; its descendants are drawn beneath it with\n * {@link BORDER_CHARS} — `├─ ` before each child but the last, `└─ ` before the last, and the\n * carried prefix using `│ ` under an ancestor that still has later siblings or ` ` under a\n * last ancestor (so the guides line up exactly under the branch they descend from). Node\n * labels are written as given (an already-styled label is honored); `options.styler` colors\n * the connectors when supplied. Returns the tree as `\\n`-joined lines, no trailing newline.\n *\n * @param options - See {@link TreeOptions}\n * @returns The rendered tree (multiple lines joined by `\\n`)\n *\n * @example\n * ```ts\n * renderTree({ root: { label: 'root', children: [{ label: 'a' }, { label: 'b' }] } })\n * // root\n * // ├─ a\n * // └─ b\n * ```\n */\nexport function renderTree(options: TreeOptions): string {\n\tconst border = options.border ?? DEFAULT_BORDER\n\treturn [\n\t\toptions.root.label,\n\t\t...renderTreeChildren(options.root.children ?? [], '', { ...options, border }),\n\t].join('\\n')\n}\n\n/**\n * Renders the connector-prefixed lines for a {@link TreeNode} list — the recursive core\n * behind {@link renderTree}. Each child is drawn as `prefix` + its connector (`├─ ` for\n * any but the last, `└─ ` for the last) + its label, with its own descendants recursed\n * beneath under the carried guide (`│ ` under a non-last node, ` ` under the last).\n *\n * @remarks\n * A centralized, exported recursion branch so it is directly testable and\n * reusable outside {@link renderTree}'s top-level `root.label` framing.\n *\n * @param nodes - The sibling {@link TreeNode}s to render at this depth\n * @param prefix - The guide/gap string carried in from the ancestor chain (`''` at the root)\n * @param options - The required `border` selection plus optional connector `styler` and\n * by-value `style`\n * @returns The rendered lines for `nodes` and all their descendants\n *\n * @example\n * ```ts\n * renderTreeChildren([{ label: 'a' }, { label: 'b' }], '', { border: 'single' })\n * // ['├─ a', '└─ b']\n * ```\n */\nexport function renderTreeChildren(\n\tnodes: readonly TreeNode[],\n\tprefix: string,\n\toptions: Required<Pick<TreeOptions, 'border'>> & Pick<TreeOptions, 'style' | 'styler'>,\n): readonly string[] {\n\tconst chars = BORDER_CHARS[options.border]\n\tconst branch = `${chars.teeRight}${chars.horizontal} `\n\tconst corner = `${chars.bottomLeft}${chars.horizontal} `\n\tconst guide = `${chars.vertical} `\n\tconst lines: string[] = []\n\tnodes.forEach((node, index) => {\n\t\tconst last = index === nodes.length - 1\n\t\tlines.push(\n\t\t\t`${prefix}${paint(options.styler, last ? corner : branch, options.style)}${node.label}`,\n\t\t)\n\t\tconst carry = `${prefix}${paint(options.styler, last ? ' ' : guide, options.style)}`\n\t\tlines.push(...renderTreeChildren(node.children ?? [], carry, options))\n\t})\n\treturn lines\n}\n\n/**\n * Stringifies one captured console argument into a line fragment — the per-argument rule behind\n * {@link formatArgs}: an `Error` → `name: message`, a plain object / array → circular-safe JSON,\n * anything else (string, number, boolean, `null`, `undefined`, symbol, function) → `String(value)`.\n *\n * @remarks\n * - **Total + never throws.** Like a guard, this never throws on adversarial input — a value\n * carrying a circular reference, a `BigInt`, or a throwing `toJSON` is rendered, not raised. The\n * `JSON.stringify` runs with a circular-guard replacer (a seen-set drops a back-reference as\n * `'[Circular]'`); if `JSON.stringify` still throws (for example on a `BigInt`), the value falls\n * back to `String(value)`. So a `Capture` can never crash the program whose `console.*` it\n * intercepts.\n * - **`Error` first.** An `Error` renders as `name: message` (for example `TypeError: bad`) — the useful\n * one-line form, since `JSON.stringify(error)` is `{}` (its fields are non-enumerable).\n * - **Objects → JSON.** A non-null `object` (including an array) is `JSON.stringify`d; a primitive\n * (or `null` / `undefined` / `function` / `symbol`) goes through `String`.\n *\n * @param value - One console argument (any value)\n * @returns The argument's one-line string form\n *\n * @example\n * ```ts\n * stringifyValue('hi') // 'hi'\n * stringifyValue({ a: 1 }) // '{\"a\":1}'\n * stringifyValue(new TypeError('bad')) // 'TypeError: bad'\n * const cycle: Record<string, unknown> = {}\n * cycle.self = cycle\n * stringifyValue(cycle) // '{\"self\":\"[Circular]\"}'\n * ```\n */\nexport function stringifyValue(value: unknown): string {\n\tif (value instanceof Error) return `${value.name}: ${value.message}`\n\tif (value === null || typeof value !== 'object') return String(value)\n\t// A circular-safe replacer — a seen-set drops any back-reference so a cyclic graph serializes\n\t// instead of throwing (total, like a guard). A residual throw (for example a BigInt field) falls\n\t// back to String(value), so this helper is total on every input.\n\tconst seen = new WeakSet<object>()\n\ttry {\n\t\treturn JSON.stringify(value, (_key, nested: unknown) => {\n\t\t\tif (nested !== null && typeof nested === 'object') {\n\t\t\t\tif (seen.has(nested)) return '[Circular]'\n\t\t\t\tseen.add(nested)\n\t\t\t}\n\t\t\treturn nested\n\t\t})\n\t} catch {\n\t\treturn String(value)\n\t}\n}\n\n/**\n * Stringifies a captured `console.*` argument list into one line — the text of a {@link\n * import('./types.js').CapturedMessage}. Each argument is rendered by {@link stringifyValue} and\n * the parts are space-joined, mirroring how a console concatenates its arguments.\n *\n * @remarks\n * Total and never throws (it composes {@link stringifyValue}, which is total) — a `Capture` builds\n * every message through this, so intercepting `console.*` can never crash the underlying program.\n * An empty argument list yields `''` (an empty `console.log()` is captured as a blank line).\n *\n * @param args - The arguments a `console.*` method was called with\n * @returns The arguments stringified and space-joined into one line\n *\n * @example\n * ```ts\n * formatArgs(['count', 3, { ok: true }]) // 'count 3 {\"ok\":true}'\n * formatArgs([]) // ''\n * ```\n */\nexport function formatArgs(args: readonly unknown[]): string {\n\treturn args.map(stringifyValue).join(' ')\n}\n\n/**\n * Renders a determinate progress bar string — a filled / empty glyph track followed by the percentage\n * and the `(current/total)` count (`█████░░░░░ 50% (5/10)`). Pure: same {@link BarOptions} →\n * same string. The animation-layer sibling of the `render*` renderers (box / table / tree /\n * separator), shared so a {@link import('./types.js').ProgressInterface} and any direct caller draw\n * the one bar — never a second, hand-rolled one.\n *\n * @remarks\n * - **Fill fraction, clamped.** The filled cell count is `round((current / total) · width)` with\n * `current` clamped to `[0, total]`, so an overrun never over-fills and a negative never under-fills.\n * A `total <= 0` renders a full track (there is nothing to fill toward — the work is trivially done).\n * - **Width-aware track.** The filled run is `fill` tiled to the filled cell count and the empty run\n * `empty` tiled to the remainder, each through {@link repeatTo} — so the track is exactly `width` visible\n * columns even for a multi-cell glyph (its escape codes / extra cells never break the width).\n * - **Styling.** `options.styler` colors the filled run only (the empty run + the trailing\n * `percent (count)` label stay plain), through {@link paint}; the layout is identical with or\n * without color, since the track is measured on visible width.\n * - **Label.** The percentage is the rounded `current / total` (for example `50%`); the count is the clamped\n * `current` over `total` (`(5/10)`), a single space separating the track, the percent, and the count.\n *\n * @param options - See {@link BarOptions}\n * @returns The rendered bar line (no trailing newline)\n *\n * @example\n * ```ts\n * renderBar({ current: 5, total: 10, width: 10 }) // '█████░░░░░ 50% (5/10)'\n * renderBar({ current: 10, total: 10, width: 4 }) // '████ 100% (10/10)'\n * ```\n */\nexport function renderBar(options: BarOptions): string {\n\tconst track = options.width ?? DEFAULT_BAR_WIDTH\n\tconst fill = options.fill ?? BAR_FILL\n\tconst empty = options.empty ?? BAR_EMPTY\n\t// Clamp `current` into [0, total], and treat a non-positive `total` as already complete (a full\n\t// track) — so the fraction is always a sound [0, 1] and an overrun / negative never breaks the bar.\n\tconst current = options.total <= 0 ? 0 : Math.max(0, Math.min(options.total, options.current))\n\tconst fraction = options.total <= 0 ? 1 : current / options.total\n\tconst filledCells = Math.round(fraction * track)\n\tconst bar = `${paint(options.styler, repeatTo(fill, filledCells), options.style)}${repeatTo(empty, track - filledCells)}`\n\tconst percent = Math.round(fraction * 100)\n\treturn `${bar} ${percent}% (${current}/${options.total})`\n}\n","import type { RendererInterface, Style } from '../types.js'\nimport { ATTRIBUTE_CODES, BACKGROUND_CODES, CSI, FOREGROUND_CODES, RESET } from '../constants.js'\n\n/**\n * Implements the cross-environment default {@link RendererInterface} — renders style data as ANSI\n * SGR escape codes, exactly as `Scheduler` is the `setTimeout` default for its seam. It\n * is the single styling output the whole console / terminal system uses in a terminal;\n * the browser `%c` / CSS renderer implements the same contract over\n * the same {@link Style}, so retargeting changes the renderer, never the style model.\n *\n * @remarks\n * - **Style is data in, SGR string out.** It reads the style's `foreground` /\n * `background` / `attributes` and emits one `ESC[…m` sequence whose parameters are the\n * mapped SGR numbers (foreground 30–37 / 90–97, background 40–47 / 100–107, attributes\n * 1 / 2 / 3 / 4 / 7 / 9), followed by `text`, terminated by the reset `ESC[0m`.\n * - **Multiple attributes compose** — their codes join with `;` in a single sequence\n * (`ESC[1;4;31m` for bold + underline + red), so one open and one reset wrap the run.\n * - **`default` and unset colors emit no code** — a `default` (or absent) `foreground` /\n * `background` leaves the terminal's own ink.\n * - **The empty style and the empty string pass through** — when there is nothing to\n * apply (no colors, no attributes) or `text` is `''`, `text` is returned verbatim with\n * no escape codes, so an unstyled render never injects a stray reset.\n * - **Stateless and event-free** — no fields, no events; safe to share one instance.\n */\nexport class ANSIRenderer implements RendererInterface {\n\t/**\n\t * Wraps `text` in the SGR codes for `style`. Returns `text` unchanged when the style\n\t * is empty or `text` is `''`.\n\t */\n\trender(style: Style, text: string): string {\n\t\tif (text === '') return text\n\t\tconst codes = this.#codes(style)\n\t\tif (codes.length === 0) return text\n\t\treturn `${CSI}${codes.join(';')}m${text}${RESET}`\n\t}\n\n\t// Collect the SGR parameters for a style, in a stable order — attributes first (in\n\t// their `attributes` order), then foreground, then background. A `default` or absent\n\t// color contributes nothing; an empty result signals \"no wrapping\" to `render`.\n\t#codes(style: Style): readonly number[] {\n\t\tconst codes: number[] = []\n\t\tfor (const attribute of style.attributes) codes.push(ATTRIBUTE_CODES[attribute])\n\t\tif (style.foreground !== undefined && style.foreground !== 'default') {\n\t\t\tcodes.push(FOREGROUND_CODES[style.foreground])\n\t\t}\n\t\tif (style.background !== undefined && style.background !== 'default') {\n\t\t\tcodes.push(BACKGROUND_CODES[style.background])\n\t\t}\n\t\treturn codes\n\t}\n}\n","import type { RetentionInterface } from './types.js'\n\n/**\n * Implements the bounded, level-keyed retention engine both captures buffer through — one capped total buffer\n * plus one capped bucket per level, generic over the record type each capture carries.\n *\n * @remarks\n * - **One engine, two captures.** The core `Capture` retains\n * {@link import('./types.js').CapturedMessage}s keyed by\n * {@link import('./types.js').CaptureLevel}, and the server `ProcessCapture` retains chunks keyed\n * by its stream level; both compose this, so their retention semantics cannot drift apart.\n * - **Bounded on both axes.** `add` appends to the total buffer and to the record's bucket, then\n * drops the oldest of whichever exceeded `limit`, so neither grows without bound.\n * - **Buckets are fixed at construction.** Only the levels passed to the constructor get a bucket.\n * A record at any other level still joins the total buffer, and `records(level)` for a level with\n * no bucket returns an empty list.\n * - **Copies out.** `records` returns a fresh list each call, so retained state is never reachable\n * for mutation through a returned value.\n *\n * @example\n * ```ts\n * const retention = new Retention<{ level: 'warn' | 'error'; text: string }>(['warn'], 2)\n * retention.add({ level: 'warn', text: 'first' })\n * retention.add({ level: 'error', text: 'second' }) // no bucket, still in the total buffer\n * retention.records().length // 2\n * retention.records('warn').map((record) => record.text) // ['first']\n * retention.clear()\n * retention.records() // []\n * ```\n */\nexport class Retention<T extends { readonly level: string }> implements RetentionInterface<T> {\n\treadonly #limit: number\n\t// The bounded total buffer — every retained record, oldest first, capped at #limit.\n\treadonly #records: T[] = []\n\t// The bounded per-level buckets — one capped buffer per level supplied at construction.\n\treadonly #buckets = new Map<T['level'], T[]>()\n\n\tconstructor(levels: ReadonlyArray<T['level']>, limit: number) {\n\t\tthis.#limit = limit\n\t\tfor (const level of levels) this.#buckets.set(level, [])\n\t}\n\n\tadd(record: T): void {\n\t\tthis.#push(this.#records, record)\n\t\tconst bucket = this.#buckets.get(record.level)\n\t\tif (bucket !== undefined) this.#push(bucket, record)\n\t}\n\n\trecords(): readonly T[]\n\trecords(level: T['level']): readonly T[]\n\trecords(level?: T['level']): readonly T[] {\n\t\tif (level === undefined) return [...this.#records]\n\t\treturn [...(this.#buckets.get(level) ?? [])]\n\t}\n\n\tclear(): void {\n\t\tthis.#records.length = 0\n\t\tfor (const bucket of this.#buckets.values()) bucket.length = 0\n\t}\n\n\t// Bounded push — append, then drop the oldest while over the cap.\n\t#push(buffer: T[], record: T): void {\n\t\tbuffer.push(record)\n\t\tif (buffer.length > this.#limit) buffer.shift()\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tCaptureEventMap,\n\tCaptureInterface,\n\tCaptureLevel,\n\tCaptureOptions,\n\tCapturedMessage,\n\tRetentionInterface,\n\tSinkInterface,\n\tConsoleMethod,\n} from './types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { CAPTURE_LEVEL_MAP, CAPTURE_LEVELS, DEFAULT_CAPTURE_LIMIT } from './constants.js'\nimport { formatArgs } from './helpers.js'\nimport { Retention } from './Retention.js'\n\n/**\n * Implements an observable console interceptor — it takes control of the global `console.*` on\n * the read side. While `active`, every configured `console.x` call is captured as a frozen\n * {@link CapturedMessage}, buffered (total + by level, bounded), emitted on `capture`, and — per\n * options — mirrored to the real console, forwarded to a {@link SinkInterface}, or both.\n *\n * @remarks\n * - **Snapshot-at-start (the no-capture-loop principle).** `start()` snapshots the current\n * `console[level]` for each configured {@link CaptureLevel}, then installs the wrappers. The\n * mirror writes through that snapshot — so our own console sink output (the Logger / Reporter,\n * which snapshot the real `console` at creation) is never recaptured: `Capture` catches\n * third-party `console.*`, not our writes. Create your loggers before installing a capture.\n * - **Idempotent + process-global + non-reentrant.** `start()` while already `active` is a no-op\n * (never double-patches); `stop()` while inactive is a no-op. It patches the one global\n * `console`, so at most one capture may be active at a time — running two concurrently\n * interleaves their buffers and clobbers each other's restore.\n * - **Bounded buffers.** `messages()` / `messages(level)` — the total buffer and each by-level\n * bucket are each capped at `limit`\n * (oldest dropped first), never unbounded — the same retention precedent as {@link Logger}.\n * - **Lifecycle.** `start` / `stop` toggle interception (emitting `start` / `stop`);\n * `destroy()` stops (restoring `console`) then destroys the emitter.\n *\n * @example\n * ```ts\n * const capture = new Capture({ levels: ['warn', 'error'], mirror: true })\n * capture.start()\n * console.warn('third-party noise') // captured and mirrored to the real console\n * capture.messages('warn') // [{ level: 'warn', text: 'third-party noise', time: … }]\n * capture.stop() // console.warn restored\n * ```\n */\nexport class Capture implements CaptureInterface {\n\t// The push observation surface — owned, never inherited. The emitter isolates a listener\n\t// throw (routing it to the `error` handler), so a buggy `capture` listener can never escape into\n\t// the underlying program's `console.*` call.\n\treadonly #emitter: Emitter<CaptureEventMap>\n\treadonly #levels: readonly CaptureLevel[]\n\treadonly #mirror: boolean\n\treadonly #sink: SinkInterface | undefined\n\t// The bounded buffers — the total one and one per configured CaptureLevel — owned by the shared\n\t// retention engine the server's ProcessCapture composes too.\n\treadonly #retention: RetentionInterface<CapturedMessage>\n\t// The snapshot-original console methods, captured at start() and restored at stop(); empty\n\t// while inactive.\n\treadonly #originals = new Map<CaptureLevel, ConsoleMethod>()\n\t// Stored rather than derived from #originals: an empty `levels` list patches no console method,\n\t// so a started capture configured with no level leaves #originals empty while still being active.\n\t#active = false\n\n\tconstructor(options?: CaptureOptions) {\n\t\tthis.#emitter = new Emitter<CaptureEventMap>({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#levels = options?.levels ?? CAPTURE_LEVELS\n\t\tthis.#mirror = options?.mirror ?? false\n\t\tthis.#sink = options?.sink\n\t\tthis.#retention = new Retention<CapturedMessage>(\n\t\t\tthis.#levels,\n\t\t\toptions?.limit ?? DEFAULT_CAPTURE_LIMIT,\n\t\t)\n\t}\n\n\tget emitter(): EmitterInterface<CaptureEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget active(): boolean {\n\t\treturn this.#active\n\t}\n\n\tstart(): void {\n\t\t// Idempotent — never double-patch an already-active capture (that would snapshot the\n\t\t// wrappers as the \"originals\" and break restore).\n\t\tif (this.#active) return\n\t\tthis.#active = true\n\t\tconst target: Record<CaptureLevel, ConsoleMethod> = console\n\t\tfor (const level of this.#levels) {\n\t\t\t// Snapshot the current method reference before replacing it — stop() restores exactly this\n\t\t\t// reference, leaving `console` pristine (the wrapper is never snapshotted as the original).\n\t\t\tconst original = target[level]\n\t\t\tthis.#originals.set(level, original)\n\t\t\t// The mirror target is the snapshot original bound to `console`, computed once here — so a\n\t\t\t// mirrored call reaches the real method with its proper receiver, through the snapshot and\n\t\t\t// never the live (patched) `console` (no capture loop). The restore reference stays the\n\t\t\t// pristine unbound `original` above; only the mirror uses the bound form.\n\t\t\tconst mirror = original.bind(console)\n\t\t\ttarget[level] = this.#captureCall.bind(this, level, mirror)\n\t\t}\n\t\tthis.#emitter.emit('start')\n\t}\n\n\tstop(): void {\n\t\t// Safe when not active — nothing to restore.\n\t\tif (!this.#active) return\n\t\tthis.#active = false\n\t\tconst target: Record<CaptureLevel, ConsoleMethod> = console\n\t\tfor (const [level, original] of this.#originals) target[level] = original\n\t\tthis.#originals.clear()\n\t\tthis.#emitter.emit('stop')\n\t}\n\n\tmessages(): readonly CapturedMessage[]\n\tmessages(level: CaptureLevel): readonly CapturedMessage[]\n\tmessages(level?: CaptureLevel): readonly CapturedMessage[] {\n\t\tif (level === undefined) return this.#retention.records()\n\t\treturn this.#retention.records(level)\n\t}\n\n\tclear(): void {\n\t\tthis.#retention.clear()\n\t}\n\n\tdestroy(): void {\n\t\tthis.stop()\n\t\tthis.#emitter.destroy()\n\t}\n\n\t// Adapt the patched console's variadic call shape to the captured argument collection consumed\n\t// by #intercept. Binding level and mirror in start() leaves the exact ConsoleMethod signature.\n\t#captureCall(level: CaptureLevel, mirror: ConsoleMethod, ...args: unknown[]): void {\n\t\tthis.#intercept(level, args, mirror)\n\t}\n\n\t// The wrapper body behind every patched `console.x`: build the frozen message, buffer it\n\t// (total + by level, bounded), emit `capture`, then — per options — mirror to the real console\n\t// and forward to the sink. `mirror` is the snapshot original bound to `console` (computed at\n\t// start()); the program's own call is replayed through it (with its proper receiver) only when\n\t// the `mirror` option is set.\n\t#intercept(level: CaptureLevel, args: unknown[], mirror: ConsoleMethod): void {\n\t\tconst message = this.#capture(level, args)\n\t\tthis.#retention.add(message)\n\t\tthis.#emitter.emit('capture', message)\n\t\tif (this.#mirror) mirror(...args)\n\t\t// The wrapper never throws into the patched global — a misbehaving sink is best-effort\n\t\t// and swallowed, never allowed to break the underlying program's own console.* call.\n\t\tif (this.#sink !== undefined) {\n\t\t\ttry {\n\t\t\t\tthis.#sink.write(message.text, CAPTURE_LEVEL_MAP[level])\n\t\t\t} catch {\n\t\t\t\t// Swallowed — see comment above.\n\t\t\t}\n\t\t}\n\t}\n\n\t// Build the immutable, serializable captured message — args stringified to one line (total,\n\t// never throws — see formatArgs), stamped with the capture instant. Frozen so a consumer (or\n\t// the `capture` listener) can never mutate it after the fact.\n\t#capture(level: CaptureLevel, args: readonly unknown[]): CapturedMessage {\n\t\treturn Object.freeze({ level, text: formatArgs(args), time: Date.now() })\n\t}\n}\n","import type { Attribute, Color, RendererInterface, Style, StylerInterface } from './types.js'\nimport { ATTRIBUTES, COLORS } from './constants.js'\nimport { ConsoleError } from './errors.js'\n\n/**\n * Builds the fluent, composable styling surface — the consumer-facing API over the style\n * engine. It\n * builds a {@link Style} (style as data) and renders it through an injected\n * {@link RendererInterface} (the ANSI default, or a browser `%c` renderer). Each\n * color / attribute accessor is immutable copy-on-write: it returns a new styler's\n * surface with the token added, so `styler.red.bold('hi')` composes without mutating,\n * and a base styler is freely reusable.\n *\n * @remarks\n * - **Callable surface.** A `Styler` is not itself callable; its {@link surface} getter\n * returns the {@link StylerInterface} — a render function carrying the chainable\n * accessors. The accessors are installed as lazy getters (`Object.defineProperties`),\n * so a chain materializes only the stylers it actually walks — never the full tree —\n * and the recursion terminates. The factory returns that surface; this class is the\n * engine behind it.\n * - **Immutable.** `#foreground` and `#attribute` return a fresh `Styler` (the style is\n * rebuilt, never mutated). A later color of the same channel wins (last write); a\n * repeated attribute is idempotent (de-duplicated, order preserved).\n * - **Styling by value.** `render(style, text)` merges a {@link Style} over the accumulated\n * one and renders that — the same precedence a chain applies, reached with data instead of\n * accessor names. It is how a {@link import('./types.js').Theme} role is drawn.\n * - **`enabled` switch.** When `false`, the render function returns text verbatim — no\n * renderer call, no escape codes (for a non-TTY / `NO_COLOR` / piped output).\n * - **Event-free** — a pure styling primitive, like `Scheduler`.\n */\nexport class Styler {\n\treadonly #renderer: RendererInterface\n\treadonly #enabled: boolean\n\treadonly #style: Style\n\n\tconstructor(renderer: RendererInterface, enabled: boolean, style: Style) {\n\t\tthis.#renderer = renderer\n\t\tthis.#enabled = enabled\n\t\tthis.#style = style\n\t}\n\n\t/** Holds the accumulated style data — the empty style on a base styler. */\n\tget style(): Style {\n\t\treturn this.#style\n\t}\n\n\t/** Reports whether styling is applied; when `false`, the surface returns text unchanged. */\n\tget enabled(): boolean {\n\t\treturn this.#enabled\n\t}\n\n\t/**\n\t * Builds the fluent {@link StylerInterface} value — a render function (`text => string`) with\n\t * `style`, `enabled`, and every {@link Color} / {@link Attribute} as a lazy accessor\n\t * (each computes the next styler's surface only when read). This is what consumers\n\t * hold and call.\n\t *\n\t * @remarks\n\t * The accessors are defined as getters (not eagerly-merged values), so accessing one\n\t * builds exactly one child styler — the tree is never fully materialized and the\n\t * construction terminates. The assembled function is then narrowed to\n\t * {@link StylerInterface} through {@link #isSurface} (a real structural check), so no\n\t * type assertion is used — narrow, never assert.\n\t */\n\tget surface(): StylerInterface {\n\t\tconst callable = this.#render.bind(this)\n\t\tconst descriptors: PropertyDescriptorMap = {\n\t\t\tstyle: { value: this.#style, enumerable: true },\n\t\t\tenabled: { value: this.#enabled, enumerable: true },\n\t\t\trender: { value: this.render.bind(this), enumerable: true },\n\t\t}\n\t\tfor (const color of COLORS) {\n\t\t\tdescriptors[color] = {\n\t\t\t\tget: this.#foregroundSurface.bind(this, color),\n\t\t\t\tenumerable: true,\n\t\t\t}\n\t\t}\n\t\tfor (const attribute of ATTRIBUTES) {\n\t\t\tdescriptors[attribute] = {\n\t\t\t\tget: this.#attributeSurface.bind(this, attribute),\n\t\t\t\tenumerable: true,\n\t\t\t}\n\t\t}\n\t\tconst surface = Object.defineProperties(callable, descriptors)\n\t\tif (this.#isSurface(surface)) return surface\n\t\t// Unreachable: the descriptors above install every accessor the guard checks for.\n\t\tthrow new ConsoleError('INVARIANT', 'console: styler surface construction is incomplete')\n\t}\n\n\t/**\n\t * Renders `text` in `style` merged over the accumulated style — the by-value door beside\n\t * the accessor chain, and how a {@link import('./types.js').Theme} role is applied.\n\t *\n\t * @param style - The style to overlay; its colors win over the accumulated ones and its\n\t * attributes join them (de-duplicated, the accumulated ones first)\n\t * @param text - The text to wrap\n\t * @returns The rendered text — verbatim when `enabled` is `false`, and (by the\n\t * {@link RendererInterface} contract) when the merged style or `text` is empty\n\t *\n\t * @example\n\t * ```ts\n\t * import { createStyler, DEFAULT_THEME } from '@orkestrel/console'\n\t *\n\t * const styler = createStyler()\n\t * styler.render(DEFAULT_THEME.levels.warn, 'WARN') // yellow\n\t * styler.bold.render(DEFAULT_THEME.chrome, '│') // dim, over the accumulated bold\n\t * ```\n\t */\n\trender(style: Style, text: string): string {\n\t\treturn this.#enabled ? this.#renderer.render(this.#merge(style), text) : text\n\t}\n\n\t// Render through the configured target, or pass text through when styling is disabled.\n\t#render(text: string): string {\n\t\treturn this.#enabled ? this.#renderer.render(this.#style, text) : text\n\t}\n\n\t// Overlay `style` on the accumulated style: a set color of either channel wins (last\n\t// write, as in a chain), and the attribute sets union — accumulated order first, the\n\t// overlay's new ones appended, each carried once. Frozen, like every style this engine\n\t// builds; the caller's value is read, never touched.\n\t#merge(style: Style): Style {\n\t\tconst attributes: Attribute[] = [...this.#style.attributes]\n\t\tfor (const attribute of style.attributes) {\n\t\t\tif (!attributes.includes(attribute)) attributes.push(attribute)\n\t\t}\n\t\treturn Object.freeze({\n\t\t\t...this.#style,\n\t\t\t...style,\n\t\t\tattributes: Object.freeze(attributes),\n\t\t})\n\t}\n\n\t// Resolve one lazy foreground accessor to the next immutable styler surface.\n\t#foregroundSurface(color: Color): StylerInterface {\n\t\treturn this.#foreground(color).surface\n\t}\n\n\t// Resolve one lazy attribute accessor to the next immutable styler surface.\n\t#attributeSurface(attribute: Attribute): StylerInterface {\n\t\treturn this.#attribute(attribute).surface\n\t}\n\n\t// Structurally confirm an assembled value is a usable styler surface — callable, with\n\t// the data members and a representative color/attribute accessor present. A genuine\n\t// runtime narrowing, not a cast: it lets `surface` return `StylerInterface`\n\t// without `as`/`!`.\n\t#isSurface(value: ((text: string) => string) & object): value is StylerInterface {\n\t\treturn (\n\t\t\ttypeof value === 'function' &&\n\t\t\t'style' in value &&\n\t\t\t'enabled' in value &&\n\t\t\t'render' in value &&\n\t\t\t'red' in value &&\n\t\t\t'bold' in value\n\t\t)\n\t}\n\n\t// A new styler with `color` as the foreground — last write wins (replaces any prior\n\t// foreground); background and attributes carried forward unchanged.\n\t#foreground(color: Color): Styler {\n\t\treturn new Styler(\n\t\t\tthis.#renderer,\n\t\t\tthis.#enabled,\n\t\t\tObject.freeze({ ...this.#style, foreground: color }),\n\t\t)\n\t}\n\n\t// A new styler with `attribute` added to the set — de-duplicated and order-stable, so\n\t// a repeated attribute is idempotent.\n\t#attribute(attribute: Attribute): Styler {\n\t\tif (this.#style.attributes.includes(attribute)) return this\n\t\treturn new Styler(\n\t\t\tthis.#renderer,\n\t\t\tthis.#enabled,\n\t\t\tObject.freeze({\n\t\t\t\t...this.#style,\n\t\t\t\tattributes: Object.freeze([...this.#style.attributes, attribute]),\n\t\t\t}),\n\t\t)\n\t}\n}\n","import type {\n\tCaptureOptions,\n\tCaptureResult,\n\tLogLevel,\n\tSinkInterface,\n\tStylerInterface,\n\tStylerOptions,\n\tTheme,\n\tThemeOptions,\n} from './types.js'\nimport { ANSIRenderer } from './renderers/ANSIRenderer.js'\nimport { Capture } from './Capture.js'\nimport { DEFAULT_THEME, EMPTY_STYLE, LOG_LEVELS, STATUS_LEVELS } from './constants.js'\nimport { freezeStyle, selectWriter } from './helpers.js'\nimport { Styler } from './Styler.js'\n\n/**\n * Creates the fluent, composable {@link StylerInterface} — the consumer-facing styling\n * API. It builds a {@link import('./types.js').Style} under the hood and renders it\n * through a {@link import('./types.js').RendererInterface} (the ANSI default), so\n * `styler.red.bold('hi')` yields styled text. Chains are immutable, so a base styler is freely reusable.\n *\n * @param options - See {@link StylerOptions}\n * @returns A base {@link StylerInterface}\n *\n * @remarks\n * - `options.renderer` swaps the output target without touching the style model — pass a\n * browser `%c` / CSS renderer (the browser branch) to retarget; defaults to the ANSI\n * renderer (the cross-environment default).\n * - `options.enabled` is the no-color switch: when `false`, the styler returns text\n * verbatim (for a non-TTY, `NO_COLOR`, or piped output); defaults to `true`.\n *\n * @example\n * ```ts\n * import { createStyler } from '@orkestrel/console'\n *\n * const style = createStyler()\n * style.red.bold('error') // bold red\n * style.red(style.underline('link')) // composes either way\n *\n * // Disable for a non-TTY — every call returns its text unchanged.\n * const plain = createStyler({ enabled: false })\n * plain.green('ok') // 'ok'\n * ```\n */\nexport function createStyler(options?: StylerOptions): StylerInterface {\n\tconst renderer = options?.renderer ?? new ANSIRenderer()\n\tconst enabled = options?.enabled ?? true\n\treturn new Styler(renderer, enabled, EMPTY_STYLE).surface\n}\n\n/**\n * Creates a {@link Theme} — the app-wide semantic style vocabulary, merged role by role over\n * {@link DEFAULT_THEME}. Hand one theme to a logger / reporter / spinner / progress and every\n * surface speaks it; omit `options` for the defaults.\n *\n * @param options - See {@link ThemeOptions}\n * @returns A frozen {@link Theme}\n *\n * @remarks\n * - **Merges per role, not per theme.** An omitted role keeps its default, and `levels` /\n * `statuses` merge per entry — `{ levels: { warn: … } }` restyles the `warn` label and\n * leaves `debug` / `info` / `error` untouched.\n * - **Frozen and shareable.** The factory snapshots and deep-freezes every style leaf. The\n * returned theme and its `levels` / `statuses` records are frozen. Each status record is also\n * copied and frozen. One theme is therefore safely shared across every entity.\n *\n * @example\n * ```ts\n * import { createStyler, createTheme } from '@orkestrel/console'\n *\n * const styler = createStyler()\n * const theme = createTheme({\n * \tlevels: { warn: styler.brightYellow.bold.style }, // only the warn label changes\n * \taccent: styler.magenta.style, // spinner glyph, progress fill, step prefix\n * })\n * theme.levels.error // still the default red\n * ```\n */\nexport function createTheme(options?: ThemeOptions): Theme {\n\tconst levels = { ...DEFAULT_THEME.levels }\n\tfor (const level of LOG_LEVELS) {\n\t\tlevels[level] = freezeStyle(options?.levels?.[level] ?? DEFAULT_THEME.levels[level])\n\t}\n\tconst statuses = { ...DEFAULT_THEME.statuses }\n\tfor (const status of STATUS_LEVELS) {\n\t\tconst source = options?.statuses?.[status] ?? DEFAULT_THEME.statuses[status]\n\t\tstatuses[status] = Object.freeze({ icon: source.icon, style: freezeStyle(source.style) })\n\t}\n\treturn Object.freeze({\n\t\tlevels: Object.freeze(levels),\n\t\tstatuses: Object.freeze(statuses),\n\t\taccent: freezeStyle(options?.accent ?? DEFAULT_THEME.accent),\n\t\tchrome: freezeStyle(options?.chrome ?? DEFAULT_THEME.chrome),\n\t})\n}\n\n/**\n * Creates the default {@link SinkInterface} — a console sink that routes by level and writes\n * through the `console` methods snapshotted at creation. The default output target behind the\n * {@link import('./loggers/Logger.js').Logger}.\n *\n * @returns A console {@link SinkInterface}\n *\n * @remarks\n * - **Snapshotted — no capture loop.** It captures `console.log` / `console.warn` /\n * `console.error` at call time and writes through those references. So when a later\n * `Capture` patches `console.*`, this sink still reaches the real streams — the\n * writer and the capturer never feed each other (the no-capture-loop principle). Create\n * the sink (or the logger) before installing a capture for this to hold.\n * - **Routes by level.** `error` → the snapshotted `console.error`, `warn` →\n * `console.warn`, every other level → `console.log`. The `level` is supplied by the\n * logger; an omitted `level` goes to `console.log`. The decision is\n * {@link import('./helpers.js').selectWriter}'s, shared with the browser and server sinks.\n *\n * @example\n * ```ts\n * import { createConsoleSink } from '@orkestrel/console'\n *\n * const sink = createConsoleSink() // snapshots console.* at construction\n * sink.write('boom', 'error') // → the real console.error, even after a later console patch\n * ```\n */\nexport function createConsoleSink(): SinkInterface {\n\t// Snapshot the console writers at construction — bound to their `console` receiver — so a later\n\t// patch of `console.*` (by Capture) can never reach this sink's output (no capture loop).\n\tconst log = console.log.bind(console)\n\tconst warn = console.warn.bind(console)\n\tconst error = console.error.bind(console)\n\treturn {\n\t\twrite(text: string, level?: LogLevel): void {\n\t\t\tselectWriter(level, { log, warn, error })(text)\n\t\t},\n\t}\n}\n\n/**\n * Runs `fn` with the global `console.*` captured for its duration, returning the function's `value`\n * plus the {@link import('./types.js').CapturedMessage}s it logged — the scoped, self-restoring\n * ergonomic form of the {@link Capture} class.\n *\n * @param fn - The async function to run under capture (returns `Promise<T>`)\n * @param options - See {@link CaptureOptions} (`levels` / `mirror` / `sink` / `limit` / `on` /\n * `error`); the capture is started for the duration of `fn` regardless\n * @returns A `Promise<CaptureResult<T>>` — awaited, then `console` restored\n *\n * @remarks\n * - **Always restores.** `start()` runs before `fn`; `destroy()` (which calls `stop()`) runs on\n * every path — sync success, sync throw, and each async handler — so `console` is restored even\n * if `fn` throws / rejects (the throw / rejection still propagates). The capture is local —\n * created, used, and destroyed within the call.\n * - **Sync vs async.** A `fn` returning a `Promise` is detected and awaited before `stop()`, so\n * captures during the async work are included; a plain `fn` stops synchronously. The return type\n * follows `fn`'s (overloaded).\n * - **process-global caveat.** Like the {@link Capture} class, this patches the one global\n * `console`. Concurrent `createCaptureResult` calls (or one around other capturing code)\n * interleave — each captures every `console.*` call in flight, and the inner `stop()` restores\n * whatever the outer had installed. Use it for sequential, scoped capture, not overlapping captures.\n *\n * @example\n * ```ts\n * import { createCaptureResult } from '@orkestrel/console'\n *\n * // The async call is awaited before `console` is restored, so the capture covers the async work.\n * const out = await createCaptureResult(async () => {\n * \tconsole.warn('async noise')\n * \treturn 'done'\n * })\n * out.value // 'done'\n * out.messages.map((m) => m.text) // ['async noise']\n * ```\n */\nexport function createCaptureResult<T>(\n\tfn: () => Promise<T>,\n\toptions?: CaptureOptions,\n): Promise<CaptureResult<T>>\n/**\n * Runs `fn` with the global `console.*` captured for its duration, returning the function's `value`\n * plus the {@link import('./types.js').CapturedMessage}s it logged, synchronously.\n *\n * @param fn - The synchronous function to run under capture (returns `T`)\n * @param options - See {@link CaptureOptions}\n * @returns A {@link CaptureResult}`<T>` — `{ value, messages }`, with `console` already restored\n *\n * @example\n * ```ts\n * import { createCaptureResult } from '@orkestrel/console'\n *\n * // The sync call returns the result directly — no `await`, `console` already restored.\n * const { value, messages } = createCaptureResult(() => {\n * \tconsole.log('working')\n * \treturn 42\n * })\n * value // 42\n * messages.map((m) => m.text) // ['working']\n * ```\n */\nexport function createCaptureResult<T>(fn: () => T, options?: CaptureOptions): CaptureResult<T>\n// The one implementation behind both overloads: start the capture, run `fn`, and destroy the\n// capture on every path — sync success, sync throw, and each async handler — so `console` is always\n// restored and only the buffered messages are returned.\nexport function createCaptureResult<T>(\n\tfn: () => T | Promise<T>,\n\toptions?: CaptureOptions,\n): CaptureResult<T> | Promise<CaptureResult<T>> {\n\tconst capture = new Capture(options)\n\tcapture.start()\n\ttry {\n\t\tconst result = fn()\n\t\tif (result instanceof Promise) {\n\t\t\treturn result.then(\n\t\t\t\t(value) => {\n\t\t\t\t\tconst messages = capture.messages()\n\t\t\t\t\tcapture.destroy()\n\t\t\t\t\treturn { value, messages }\n\t\t\t\t},\n\t\t\t\t(error: unknown) => {\n\t\t\t\t\tcapture.destroy()\n\t\t\t\t\tthrow error\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t\tconst messages = capture.messages()\n\t\tcapture.destroy()\n\t\treturn { value: result, messages }\n\t} catch (error) {\n\t\t// A sync throw — restore console before rethrowing (the async rejection path is handled above).\n\t\tcapture.destroy()\n\t\tthrow error\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tLoggerEventMap,\n\tLogFormatFunction,\n\tLoggerInterface,\n\tLoggerOptions,\n\tLogLevel,\n\tLogRecord,\n\tSinkInterface,\n\tStylerInterface,\n\tTheme,\n} from '../types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { DEFAULT_LOG_LEVEL, DEFAULT_LOG_LIMIT, DEFAULT_THEME } from '../constants.js'\nimport { createConsoleSink, createStyler } from '../factories.js'\nimport { formatRecord, meetsLevel } from '../helpers.js'\n\n/**\n * Implements an observable, leveled logger — the entry point into the structured-logging\n * pipeline. Each `debug` / `info` / `warn` / `error` call builds a frozen {@link LogRecord},\n * gates it by severity, retains a bounded tail of accepted records, always emits it on\n * `entry` (the transport seam), and — unless `silent` — formats it into a styled line and\n * writes it to its {@link SinkInterface}.\n *\n * @remarks\n * - **Record + event = transport.** An accepted record is frozen and emitted on\n * `entry` before anything else observable — every file / JSON / remote transport rides\n * `emitter.on('entry')`. The event fires even when `silent`: silence suppresses only the\n * sink write, never the record or the event, so transports keep flowing.\n * - **Leveled gate.** A record whose {@link LogLevel} is below the logger's `level` threshold\n * is dropped entirely — no record built past the level check, no event, no retention, no\n * write (see {@link meetsLevel}).\n * - **Bounded retention.** Accepted records accrue in a ring capped at `limit` (default\n * {@link DEFAULT_LOG_LIMIT}); the oldest is dropped when full. `entries()` returns a copy,\n * oldest first; `clear()` empties it. Never unbounded — retention is capped at `limit`.\n * - **Styled write, orthogonal to level.** The line ({@link formatRecord}) is colored through\n * the injected `styler` (the ANSI default, or a browser `%c` styler) — a level only\n * chooses a label color; styling is not a level. A disabled styler yields a plain line.\n * - **Snapshotted sink.** The default {@link createConsoleSink} writes to the `console`\n * methods captured at creation, so a later `Capture` patching `console` can't loop the\n * sink's output back into itself.\n *\n * @example\n * ```ts\n * const logger = new Logger({ name: 'http', level: 'info' })\n * logger.emitter.on('entry', (record) => archive(record)) // transport hook\n * logger.info('request', { method: 'GET', path: '/' }) // styled line to the console sink\n * logger.debug('verbose') // dropped — below the `info` threshold\n * logger.entries() // [the info record]\n * ```\n */\nexport class Logger implements LoggerInterface {\n\t// The push observation surface — owned, never inherited. The emitter isolates a\n\t// listener throw (routing it to the `error` handler), so a buggy transport can never\n\t// escape into a log call.\n\treadonly #emitter: Emitter<LoggerEventMap>\n\treadonly #level: LogLevel\n\treadonly #sink: SinkInterface\n\treadonly #styler: StylerInterface\n\treadonly #theme: Theme\n\treadonly #format: LogFormatFunction\n\treadonly #limit: number\n\treadonly #silent: boolean\n\t// The bounded retention ring — accepted records, oldest first, capped at #limit.\n\treadonly #entries: LogRecord[] = []\n\treadonly name?: string\n\n\tconstructor(options?: LoggerOptions) {\n\t\tthis.#emitter = new Emitter<LoggerEventMap>({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#level = options?.level ?? DEFAULT_LOG_LEVEL\n\t\tif (options?.name !== undefined) this.name = options.name\n\t\tthis.#sink = options?.sink ?? createConsoleSink()\n\t\tthis.#styler = options?.styler ?? createStyler()\n\t\tthis.#theme = options?.theme ?? DEFAULT_THEME\n\t\tthis.#format = options?.format ?? formatRecord\n\t\tthis.#limit = options?.limit ?? DEFAULT_LOG_LIMIT\n\t\tthis.#silent = options?.silent ?? false\n\t}\n\n\tget emitter(): EmitterInterface<LoggerEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget level(): LogLevel {\n\t\treturn this.#level\n\t}\n\n\tdebug(message: string, data?: Record<string, unknown>): void {\n\t\tthis.#log('debug', message, data)\n\t}\n\n\tinfo(message: string, data?: Record<string, unknown>): void {\n\t\tthis.#log('info', message, data)\n\t}\n\n\twarn(message: string, data?: Record<string, unknown>): void {\n\t\tthis.#log('warn', message, data)\n\t}\n\n\terror(message: string, data?: Record<string, unknown>): void {\n\t\tthis.#log('error', message, data)\n\t}\n\n\tentries(): readonly LogRecord[] {\n\t\treturn [...this.#entries]\n\t}\n\n\tclear(): void {\n\t\tthis.#entries.length = 0\n\t}\n\n\tdestroy(): void {\n\t\tthis.#entries.length = 0\n\t\tthis.#emitter.destroy()\n\t}\n\n\t// The single log path behind every level method: gate by severity, then for an accepted\n\t// record build it frozen, retain it (bounded), emit `entry` always, and write the styled\n\t// line unless silent. A dropped (below-threshold) record does nothing observable.\n\t#log(level: LogLevel, message: string, data: Record<string, unknown> | undefined): void {\n\t\tif (!meetsLevel(this.#level, level)) return\n\t\tconst record = this.#record(level, message, data)\n\t\tthis.#retain(record)\n\t\t// The transport seam — fires even when silent (silence suppresses only the write).\n\t\tthis.#emitter.emit('entry', record)\n\t\tif (this.#silent) return\n\t\t// Pass the level so a stream-aware sink (the default console sink, the TTY sink)\n\t\t// can route error/warn to the right stream; a plain sink ignores it.\n\t\tthis.#sink.write(this.#format(record, this.#styler, this.#theme), level)\n\t}\n\n\t// Build the immutable, serializable record — `name` / `data` omitted when absent so the\n\t// frozen value carries only what was supplied. Frozen so a consumer (or transport) can\n\t// never mutate it after the fact.\n\t#record(level: LogLevel, message: string, data: Record<string, unknown> | undefined): LogRecord {\n\t\treturn Object.freeze({\n\t\t\tlevel,\n\t\t\tmessage,\n\t\t\ttime: Date.now(),\n\t\t\t...(this.name === undefined ? {} : { name: this.name }),\n\t\t\t...(data === undefined ? {} : { data: Object.freeze({ ...data }) }),\n\t\t})\n\t}\n\n\t// Push onto the bounded ring, evicting the oldest when at capacity — the retention stays\n\t// capped at #limit, never growing without bound.\n\t#retain(record: LogRecord): void {\n\t\tthis.#entries.push(record)\n\t\tif (this.#entries.length > this.#limit) this.#entries.shift()\n\t}\n}\n","import type {\n\tLoggerInterface,\n\tLoggerManagerInterface,\n\tLoggerManagerOptions,\n\tLoggerOptions,\n} from '../types.js'\nimport { isArray } from '@orkestrel/contract'\nimport { Logger } from './Logger.js'\n\n/**\n * Implements an event-free registry of named {@link Logger}s plus a convenience fan-out — the\n * manager over the logging layer (a registry, never observable itself; each {@link Logger}\n * owns its own `emitter`).\n *\n * @remarks\n * - **Registry.** Loggers live in an insertion-ordered `Map` keyed by `name`.\n * `register(name, options?)` mints a {@link Logger} named `name` — the manager's default\n * `level` / `sink` / `styler` / `theme` / `format` / `limit` / `silent` flow in unless\n * `options` overrides them\n * (`name` is always the registry key, so any `options.name` is ignored) — stores it (a\n * re-`register` of the same name overwrites, last write wins), and returns it. `count` is\n * the map size, `logger(name)` looks one up, `loggers()` lists them in insertion order.\n * - **Removal.** `remove()` clears all, `remove(name)` drops one (`true` if present),\n * `remove(names)` drops a batch (`true` only when every name was present; an empty list\n * succeeds vacuously). Every listed name is attempted whatever the result.\n * (Removal does not `destroy` the returned loggers — a caller still holding one keeps using\n * it; the manager stops tracking it.)\n * - **Fan-out.** `debug` / `info` / `warn` / `error(message, data?)` forward the one call to\n * every registered logger in insertion order; each gates / emits / writes per its own `level`\n * and `sink`. A formatter throw is a programmer error and propagates, stopping the remaining\n * loggers for that call. A fan-out over an empty registry is a no-op.\n * - **Event-free.** No emitter, no events — the manager is a pure registry; observability is\n * per-{@link Logger}.\n *\n * @example\n * ```ts\n * const manager = new LoggerManager({ level: 'warn' })\n * manager.register('http') // inherits the `warn` default\n * manager.register('db', { level: 'debug' }) // overrides to `debug`\n * manager.warn('slow', { ms: 900 }) // fans out to both loggers\n * manager.count // 2\n * ```\n */\nexport class LoggerManager implements LoggerManagerInterface {\n\treadonly #loggers = new Map<string, LoggerInterface>()\n\t// The defaults flowed into every logger `register` mints (a per-register override wins).\n\treadonly #level: LoggerManagerOptions['level']\n\treadonly #sink: LoggerManagerOptions['sink']\n\treadonly #styler: LoggerManagerOptions['styler']\n\treadonly #theme: LoggerManagerOptions['theme']\n\treadonly #format: LoggerManagerOptions['format']\n\treadonly #limit: LoggerManagerOptions['limit']\n\treadonly #silent: LoggerManagerOptions['silent']\n\n\tconstructor(options?: LoggerManagerOptions) {\n\t\tthis.#level = options?.level\n\t\tthis.#sink = options?.sink\n\t\tthis.#styler = options?.styler\n\t\tthis.#theme = options?.theme\n\t\tthis.#format = options?.format\n\t\tthis.#limit = options?.limit\n\t\tthis.#silent = options?.silent\n\t}\n\n\tget count(): number {\n\t\treturn this.#loggers.size\n\t}\n\n\tregister(name: string, options?: LoggerOptions): LoggerInterface {\n\t\t// The manager's defaults flow in first; the per-register `options` override them; `name`\n\t\t// is forced last so it always keys the registry (an `options.name` can't desync the key).\n\t\tconst logger = new Logger({\n\t\t\t...(this.#level !== undefined ? { level: this.#level } : {}),\n\t\t\t...(this.#sink !== undefined ? { sink: this.#sink } : {}),\n\t\t\t...(this.#styler !== undefined ? { styler: this.#styler } : {}),\n\t\t\t...(this.#theme !== undefined ? { theme: this.#theme } : {}),\n\t\t\t...(this.#format !== undefined ? { format: this.#format } : {}),\n\t\t\t...(this.#limit !== undefined ? { limit: this.#limit } : {}),\n\t\t\t...(this.#silent !== undefined ? { silent: this.#silent } : {}),\n\t\t\t...options,\n\t\t\tname,\n\t\t})\n\t\tthis.#loggers.set(name, logger)\n\t\treturn logger\n\t}\n\n\tlogger(name: string): LoggerInterface | undefined {\n\t\treturn this.#loggers.get(name)\n\t}\n\n\tloggers(): readonly LoggerInterface[] {\n\t\treturn [...this.#loggers.values()]\n\t}\n\n\tdebug(message: string, data?: Record<string, unknown>): void {\n\t\tfor (const logger of this.#loggers.values()) logger.debug(message, data)\n\t}\n\n\tinfo(message: string, data?: Record<string, unknown>): void {\n\t\tfor (const logger of this.#loggers.values()) logger.info(message, data)\n\t}\n\n\twarn(message: string, data?: Record<string, unknown>): void {\n\t\tfor (const logger of this.#loggers.values()) logger.warn(message, data)\n\t}\n\n\terror(message: string, data?: Record<string, unknown>): void {\n\t\tfor (const logger of this.#loggers.values()) logger.error(message, data)\n\t}\n\n\t// all / one / batch under one verb — the array overload declared first by the project\n\t// convention (a `name` is a string, never an array, so the two never overlap).\n\tremove(names: readonly string[]): boolean\n\tremove(name: string): boolean\n\tremove(): void\n\tremove(names?: string | readonly string[]): void | boolean {\n\t\tif (names === undefined) {\n\t\t\tthis.#loggers.clear()\n\t\t\treturn\n\t\t}\n\t\tif (isArray(names)) {\n\t\t\t// Every name is attempted, and the batch succeeds only when every one was present — an\n\t\t\t// empty list has no failing member, so it succeeds vacuously.\n\t\t\tlet removed = true\n\t\t\tfor (const name of names) {\n\t\t\t\tif (!this.#loggers.delete(name)) removed = false\n\t\t\t}\n\t\t\treturn removed\n\t\t}\n\t\treturn this.#loggers.delete(names)\n\t}\n}\n","import type {\n\tBoxOptions,\n\tReporterInterface,\n\tReporterOptions,\n\tSinkInterface,\n\tStatusLevel,\n\tStepPosition,\n\tStylerInterface,\n\tTableOptions,\n\tTheme,\n\tTreeOptions,\n} from './types.js'\nimport { DEFAULT_THEME, DEFAULT_WIDTH } from './constants.js'\nimport { createConsoleSink, createStyler } from './factories.js'\nimport { formatDuration, renderBox, renderSeparator, renderTable, renderTree } from './helpers.js'\n\n/**\n * Implements a lean, event-free narrative reporter — the composable verb set for human /\n * build-run output. Each verb formats its line through the shared {@link StylerInterface} and\n * the pure layout renderers ({@link renderSeparator} / {@link renderBox} / {@link renderTable}\n * / {@link renderTree}) and writes it to a {@link SinkInterface} — the same styler + sink\n * substrate the logger uses, never a second colorizer.\n *\n * @remarks\n * - **A small set, not a grab-bag.** `section` / `step` / `timing` / `status` / `table` /\n * `tree` / `box` / `line` / `blank`. No spinner / bar (the animation chunk), no buffering /\n * capture (the capture chunk), no level retention (the logger). Format and write, nothing more.\n * - **`status` is a narrative outcome, not a log level.** Its {@link StatusLevel} (`success` /\n * `error` / `warn` / `info`) is distinct from {@link import('./types.js').LogLevel}: an icon\n * supplied theme status icon + style, with `error` routed to the sink's\n * error stream (the `level` hint forwarded to {@link SinkInterface.write}) — there is no\n * gating and no severity ordering.\n * - **Width-aware.** `section` (and a `box` with no explicit `width`) lay out to the reporter's\n * `#width`; the renderers measure on visible width (ANSI-aware), so styled content aligns.\n * - **Event-free.** No `#emitter` — a pure formatting front-end with no observable\n * lifecycle (like the renderers and `Scheduler`). It is reusable and holds no per-call state.\n *\n * @example\n * ```ts\n * const reporter = new Reporter()\n * reporter.section('Build')\n * reporter.step('compiling', { index: 1, total: 3 }) // [1/3] compiling\n * reporter.timing('bundle', 1234) // bundle … 1.23s\n * reporter.status('success', 'done') // ✔ done\n * ```\n */\nexport class Reporter implements ReporterInterface {\n\treadonly #sink: SinkInterface\n\treadonly #styler: StylerInterface\n\treadonly #theme: Theme\n\treadonly #width: number\n\n\tconstructor(options?: ReporterOptions) {\n\t\tthis.#sink = options?.sink ?? createConsoleSink()\n\t\tthis.#styler = options?.styler ?? createStyler()\n\t\tthis.#theme = options?.theme ?? DEFAULT_THEME\n\t\tthis.#width = options?.width ?? DEFAULT_WIDTH\n\t}\n\n\tsection(title: string): void {\n\t\t// The theme's chrome role styles the rule and title through the shared styler.\n\t\tthis.#sink.write(\n\t\t\trenderSeparator({\n\t\t\t\ttitle,\n\t\t\t\twidth: this.#width,\n\t\t\t\tstyler: this.#styler,\n\t\t\t\tstyle: this.#theme.chrome,\n\t\t\t}),\n\t\t)\n\t}\n\n\tstep(message: string, position?: StepPosition): void {\n\t\tconst prefix =\n\t\t\tposition === undefined\n\t\t\t\t? ''\n\t\t\t\t: `${this.#styler.render(this.#theme.accent, `[${position.index}/${position.total}]`)} `\n\t\tthis.#sink.write(`${prefix}${message}`)\n\t}\n\n\ttiming(label: string, ms: number): void {\n\t\tthis.#sink.write(\n\t\t\t`${label} ${this.#styler.render(this.#theme.chrome, `… ${formatDuration(ms)}`)}`,\n\t\t)\n\t}\n\n\tstatus(level: StatusLevel, message: string): void {\n\t\tconst status = this.#theme.statuses[level]\n\t\tconst line = `${this.#styler.render(status.style, status.icon)} ${this.#styler.render(status.style, message)}`\n\t\t// `error` is the one outcome that routes to the sink's error stream; the rest write plain.\n\t\tthis.#sink.write(line, level === 'error' ? 'error' : undefined)\n\t}\n\n\ttable(options: TableOptions): void {\n\t\tthis.#sink.write(renderTable(this.#resolveStyle(options)))\n\t}\n\n\ttree(options: TreeOptions): void {\n\t\tthis.#sink.write(renderTree(this.#resolveStyle(options)))\n\t}\n\n\tbox(options: BoxOptions): void {\n\t\t// Default the box width here; explicit options win.\n\t\tthis.#sink.write(renderBox(this.#resolveStyle({ width: this.#width, ...options })))\n\t}\n\n\tline(text: string): void {\n\t\tthis.#sink.write(text)\n\t}\n\n\tblank(count = 1): void {\n\t\tfor (let index = 0; index < count; index += 1) this.#sink.write('')\n\t}\n\n\t// Use theme chrome only when the caller supplied neither half of the styling decision. The\n\t// reporter's base styler still renders a caller's by-value style when no caller styler exists.\n\t#resolveStyle<T extends BoxOptions | TableOptions | TreeOptions>(options: T): T {\n\t\treturn {\n\t\t\tstyler: this.#styler,\n\t\t\t...(options.styler === undefined && options.style === undefined\n\t\t\t\t? { style: this.#theme.chrome }\n\t\t\t\t: {}),\n\t\t\t...options,\n\t\t}\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tSinkInterface,\n\tSpinnerEventMap,\n\tSpinnerInterface,\n\tSpinnerOptions,\n\tStylerInterface,\n\tTheme,\n} from './types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { DEFAULT_SPINNER_INTERVAL, DEFAULT_THEME, SPINNER_FRAMES } from './constants.js'\nimport { createConsoleSink, createStyler } from './factories.js'\n\n/**\n * Implements a self-driving, observable activity spinner — a glyph cycle that advances on a\n * periodic timer, writing each `\\r` + frame line to its {@link SinkInterface} and emitting it on\n * `frame`. The leading `\\r` is what an overwrite-capable sink (the TTY sink) redraws on; a plain\n * sink degrades to a fresh, non-overwriting line — the line-overwrite is the sink's job, never\n * the spinner's. Universal — `setInterval` + the one {@link StylerInterface} + the one\n * {@link SinkInterface}, no `node:*`, no `process.stdout`.\n *\n * @remarks\n * - **Self-driving but deterministically testable.** `start()` arms a `setInterval` that calls\n * {@link tick} each `interval`; each {@link tick} builds the styled `glyph + message` line for the\n * current frame, emits it on `frame`, writes `'\\r' + line` to the sink, then advances the frame\n * index (wrapping). A test drives frames by calling {@link tick} directly, or arms a real short\n * `interval` and proves the timer arms / clears through the sink it writes to.\n * - **Leak-free timer.** The interval is always cleared on {@link succeed} / {@link fail} /\n * {@link stop} / {@link destroy} — `#handle` is the single source of `active`, set on arm and unset\n * on clear, so a spinner never leaks a running interval.\n * - **Idempotent `start`.** A {@link start} while already `active` is a no-op (it never arms a second\n * timer).\n * - **Outcome lines.** {@link succeed} / {@link fail} clear the timer then write + emit a final line —\n * the supplied theme status icon + style (`✔` / `✖` by default) + the message — terminated\n * by a newline (the activity is over; the line is committed, not overwritten). {@link fail} routes to\n * the sink's error stream.\n * - **Lifecycle.** {@link stop} clears the timer and leaves the current line; {@link destroy}\n * stops then destroys the emitter. {@link update} swaps the message and re-renders immediately when\n * `active`.\n *\n * @example\n * ```ts\n * const spinner = new Spinner({ message: 'building' })\n * spinner.start() // arms the timer, paints the first frame to the sink\n * spinner.update('bundling') // message changes, re-rendered at once\n * spinner.succeed('built in 1.2s') // ✔ built in 1.2s — timer cleared, line committed\n * ```\n */\nexport class Spinner implements SpinnerInterface {\n\t// The push observation surface — owned, never inherited. The emitter isolates a listener\n\t// throw (routing it to the `error` handler), so a buggy `frame` listener can never escape the tick.\n\treadonly #emitter: Emitter<SpinnerEventMap>\n\treadonly #frames: readonly string[]\n\treadonly #interval: number\n\treadonly #sink: SinkInterface\n\treadonly #styler: StylerInterface\n\treadonly #theme: Theme\n\t#message: string\n\t// The running interval handle — undefined while inactive. Its presence is `active`; the timer is\n\t// armed in start() and cleared everywhere the spinner stops, so it is never leaked.\n\t#handle: ReturnType<typeof setInterval> | undefined\n\t// The current frame index into #frames — advanced (wrapping) after each rendered tick.\n\t#index = 0\n\n\tconstructor(options?: SpinnerOptions) {\n\t\tthis.#emitter = new Emitter<SpinnerEventMap>({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\t// An explicitly-empty `frames` array falls back to the default cycle too — an empty cycle\n\t\t// would divide by zero on every wrap in tick().\n\t\tconst frames = options?.frames ?? SPINNER_FRAMES\n\t\tthis.#frames = frames.length === 0 ? SPINNER_FRAMES : frames\n\t\tthis.#interval = options?.interval ?? DEFAULT_SPINNER_INTERVAL\n\t\tthis.#sink = options?.sink ?? createConsoleSink()\n\t\tthis.#styler = options?.styler ?? createStyler()\n\t\tthis.#theme = options?.theme ?? DEFAULT_THEME\n\t\tthis.#message = options?.message ?? ''\n\t}\n\n\tget emitter(): EmitterInterface<SpinnerEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget active(): boolean {\n\t\treturn this.#handle !== undefined\n\t}\n\n\tget message(): string {\n\t\treturn this.#message\n\t}\n\n\tstart(): void {\n\t\t// Idempotent — never arm a second interval over a running one (that would leak the first handle).\n\t\tif (this.#handle !== undefined) return\n\t\tthis.#handle = setInterval(() => this.tick(), this.#interval)\n\t\tthis.#emitter.emit('start')\n\t\t// Paint the first frame immediately so the spinner shows at once, not only after one interval.\n\t\tthis.tick()\n\t}\n\n\ttick(): void {\n\t\t// Render the current frame, then advance — so the first tick() shows frame 0.\n\t\tthis.#paint(this.#line())\n\t\tthis.#index = (this.#index + 1) % this.#frames.length\n\t}\n\n\tupdate(message: string): void {\n\t\tthis.#message = message\n\t\t// Re-render the current frame (no advance) so the new message shows without waiting for a tick.\n\t\tif (this.#handle !== undefined) this.#paint(this.#line())\n\t}\n\n\tsucceed(message?: string): void {\n\t\tthis.#finish('success', message)\n\t}\n\n\tfail(message?: string): void {\n\t\tthis.#finish('error', message)\n\t}\n\n\tstop(): void {\n\t\t// Clear the timer and leave the current line untouched — a no-op when not active.\n\t\tif (this.#handle === undefined) return\n\t\tclearInterval(this.#handle)\n\t\tthis.#handle = undefined\n\t\tthis.#emitter.emit('stop')\n\t}\n\n\tdestroy(): void {\n\t\tthis.stop()\n\t\tthis.#emitter.destroy()\n\t}\n\n\t// Stop the timer (emitting `stop` when it was running) and write + emit the final outcome line —\n\t// the status icon + message, colored through the styler, terminated by a newline (the activity is\n\t// over, so the line is committed, not overwritten). `error` routes to the sink's error stream. The\n\t// shared body of succeed()/fail() — the single home for the outcome path.\n\t#finish(level: 'success' | 'error', message?: string): void {\n\t\tthis.stop()\n\t\tconst text = message ?? this.#message\n\t\tif (message !== undefined) this.#message = message\n\t\tconst status = this.#theme.statuses[level]\n\t\tconst line = `${this.#styler.render(status.style, status.icon)} ${this.#styler.render(status.style, text)}`\n\t\tthis.#emitter.emit('frame', line)\n\t\t// The trailing newline commits the line; `error` is the one outcome routed to the error stream.\n\t\tthis.#sink.write(`\\r${line}\\n`, level === 'error' ? 'error' : undefined)\n\t}\n\n\t// Build the styled frame line for the current index — the colored spinner glyph, then the message\n\t// when present (a bare glyph otherwise). Kept off the public surface (a render fragment).\n\t#line(): string {\n\t\tconst glyph = this.#styler.render(this.#theme.accent, this.#frames[this.#index] ?? '')\n\t\treturn this.#message === '' ? glyph : `${glyph} ${this.#message}`\n\t}\n\n\t// Emit the frame line and write it to the sink with the leading `\\r` an overwrite-capable sink\n\t// redraws on — the same line both places, the `\\r` added only on the write (the event carries the\n\t// bare line). The single per-tick render path shared by tick() and update().\n\t#paint(line: string): void {\n\t\tthis.#emitter.emit('frame', line)\n\t\tthis.#sink.write(`\\r${line}`)\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tProgressEventMap,\n\tProgressInterface,\n\tProgressOptions,\n\tProgressReport,\n\tSinkInterface,\n\tStylerInterface,\n\tTheme,\n} from './types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { DEFAULT_BAR_WIDTH, DEFAULT_THEME } from './constants.js'\nimport { createConsoleSink, createStyler } from './factories.js'\nimport { renderBar } from './helpers.js'\n\n/**\n * Implements an update-driven, observable progress bar — {@link update} recomputes the bar through\n * {@link renderBar}, writes `\\r` + bar to its {@link SinkInterface}, and emits the `{ current, total }`\n * on `update`. The leading `\\r` is what an overwrite-capable sink (the TTY sink) redraws on; a\n * plain sink degrades to a fresh, non-overwriting line — the line-overwrite is the sink's job.\n * Universal — the one {@link StylerInterface} + the one {@link SinkInterface}, no `node:*`, no\n * `process.stdout`. No self-timer (unlike {@link import('./Spinner.js').Spinner}) — the caller drives it.\n *\n * @remarks\n * - **Update-driven.** Each {@link update} clamps `current` to `[0, total]`, renders the bar (filled\n * to `current / total`, with the trailing `percent (current/total)` + message) through {@link renderBar},\n * emits `update`, and writes `'\\r' + bar`. Progress advances only when the caller reports it.\n * - **Outcome lines.** {@link succeed} renders a full bar (`current = total`) + message, terminated by\n * a newline, emits a final `update` then `succeed`, and marks `succeeded`. {@link fail} renders the\n * bar at its current fill + message + newline and routes to the sink's error stream (no `succeed` —\n * the work did not finish). Both are terminal: a later {@link update} is ignored once `active` is false.\n * - **Bounded.** `current` is always clamped to `[0, total]`; {@link succeeded} reports whether\n * {@link succeed} has run; {@link active} is `true` until a {@link succeed} / {@link fail}.\n * - **Lifecycle.** {@link destroy} destroys the emitter (there is no timer to clear).\n *\n * @example\n * ```ts\n * const progress = new Progress({ total: 100, message: 'downloading' })\n * progress.update(40) // ████████████░░░░░░░░░░░░░░░░░░ 40% (40/100) downloading\n * progress.update(80, 'almost there')\n * progress.succeed('done') // a full bar, committed with a newline\n * ```\n */\nexport class Progress implements ProgressInterface {\n\t// The push observation surface — owned, never inherited. The emitter isolates a listener\n\t// throw (routing it to the `error` handler), so a buggy `update` listener can never escape a report.\n\treadonly #emitter: Emitter<ProgressEventMap>\n\treadonly #total: number\n\treadonly #width: number\n\treadonly #fill: ProgressOptions['fill']\n\treadonly #empty: ProgressOptions['empty']\n\treadonly #sink: SinkInterface\n\treadonly #styler: StylerInterface\n\treadonly #theme: Theme\n\t#message: string\n\t#current = 0\n\t#active = true\n\t#succeeded = false\n\n\tconstructor(options: ProgressOptions) {\n\t\tthis.#emitter = new Emitter<ProgressEventMap>({\n\t\t\t...(options.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#total = options.total\n\t\tthis.#width = options.width ?? DEFAULT_BAR_WIDTH\n\t\tthis.#fill = options.fill\n\t\tthis.#empty = options.empty\n\t\tthis.#sink = options.sink ?? createConsoleSink()\n\t\tthis.#styler = options.styler ?? createStyler()\n\t\tthis.#theme = options.theme ?? DEFAULT_THEME\n\t\tthis.#message = options.message ?? ''\n\t}\n\n\tget emitter(): EmitterInterface<ProgressEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget active(): boolean {\n\t\treturn this.#active\n\t}\n\n\tget succeeded(): boolean {\n\t\treturn this.#succeeded\n\t}\n\n\tget current(): number {\n\t\treturn this.#current\n\t}\n\n\tget total(): number {\n\t\treturn this.#total\n\t}\n\n\tupdate(current: number, message?: string): void {\n\t\t// Terminal bars ignore further updates — a succeed()/fail() has committed the final line.\n\t\tif (!this.#active) return\n\t\tthis.#advance(current, message)\n\t\tthis.#paint(false)\n\t}\n\n\tsucceed(message?: string): void {\n\t\tif (!this.#active) return\n\t\t// Finish full — drive to `total`, commit the line, then signal the successful outcome.\n\t\tthis.#advance(this.#total, message)\n\t\tthis.#active = false\n\t\tthis.#succeeded = true\n\t\tthis.#paint(true)\n\t\tthis.#emitter.emit('succeed')\n\t}\n\n\tfail(message?: string): void {\n\t\tif (!this.#active) return\n\t\t// Finish at the current fill (the work stopped short) — commit to the error stream, no succeed.\n\t\t// #advance emits a final `update` at the current fill (identical current/total), same as succeed().\n\t\tthis.#advance(this.#current, message)\n\t\tthis.#active = false\n\t\tthis.#paint(true, 'error')\n\t}\n\n\tdestroy(): void {\n\t\tthis.#emitter.destroy()\n\t}\n\n\t// Clamp `current` into [0, total], adopt the optional message, and emit the `update` progress —\n\t// the shared state-advance behind update()/succeed(). The clamp keeps `current`\n\t// bounded regardless of the value the caller reports (an overrun saturates, a negative floors).\n\t#advance(current: number, message?: string): void {\n\t\tthis.#current = Math.max(0, Math.min(this.#total, current))\n\t\tif (message !== undefined) this.#message = message\n\t\tconst report: ProgressReport = { current: this.#current, total: this.#total }\n\t\tthis.#emitter.emit('update', report)\n\t}\n\n\t// Render the bar at the current state and write `\\r` + bar to the sink — the leading `\\r` an\n\t// overwrite-capable sink redraws on. `final` appends a newline that commits the line (a finished\n\t// bar is not overwritten); `level` routes a fail() write to the error stream. The single render\n\t// path shared by update()/succeed()/fail().\n\t#paint(final: boolean, level?: 'error'): void {\n\t\tconst bar = renderBar({\n\t\t\tcurrent: this.#current,\n\t\t\ttotal: this.#total,\n\t\t\twidth: this.#width,\n\t\t\t...(this.#fill === undefined ? {} : { fill: this.#fill }),\n\t\t\t...(this.#empty === undefined ? {} : { empty: this.#empty }),\n\t\t\tstyler: this.#styler,\n\t\t\tstyle: this.#theme.accent,\n\t\t})\n\t\tconst line = this.#message === '' ? bar : `${bar} ${this.#message}`\n\t\tthis.#sink.write(`\\r${line}${final ? '\\n' : ''}`, level)\n\t}\n}\n"],"mappings":";;;;;;;AAwBA,IAAa,mBAAwE,OAAO,OAAO;CAClG,OAAO;CACP,KAAK;CACL,OAAO;CACP,QAAQ;CACR,MAAM;CACN,SAAS;CACT,MAAM;CACN,OAAO;CACP,aAAa;CACb,WAAW;CACX,aAAa;CACb,cAAc;CACd,YAAY;CACZ,eAAe;CACf,YAAY;CACZ,aAAa;AACd,CAAC;;;;;AAMD,IAAa,mBAAwE,OAAO,OAAO;CAClG,OAAO;CACP,KAAK;CACL,OAAO;CACP,QAAQ;CACR,MAAM;CACN,SAAS;CACT,MAAM;CACN,OAAO;CACP,aAAa;CACb,WAAW;CACX,aAAa;CACb,cAAc;CACd,YAAY;CACZ,eAAe;CACf,YAAY;CACZ,aAAa;AACd,CAAC;;;;;;AAOD,IAAa,kBAAuD,OAAO,OAAO;CACjF,MAAM;CACN,KAAK;CACL,QAAQ;CACR,WAAW;CACX,SAAS;CACT,eAAe;AAChB,CAAC;;;;;;AAOD,IAAa,cAAqB,OAAO,OAAO,EAAE,YAAY,OAAO,OAAO,CAAC,CAAC,EAAE,CAAC;;;;;;AAOjF,IAAa,SAAmD,OAAO,OAAO;CAC7E;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC;;;;;AAMD,IAAa,aAAmC,OAAO,OAAO;CAC7D;CACA;CACA;CACA;CACA;CACA;AACD,CAAC;;AAGD,IAAa,aAAa;;;;;AAM1B,IAAa,MAAM,OAAO,aAAa,EAAE;;AAGzC,IAAa,MAAM,OAAO,aAAa,CAAC;;AAGxC,IAAa,MAAM;;AAGnB,IAAa,QAAQ,GAAG;;;;;;;;;;;;;;;;;;AAmBxB,IAAa,eAAe,IAAI,OAC/B,kHASA,GACD;;;;;;;;;;;;;AAcA,IAAa,kBAAkB,IAAI,OAClC,IAAI,OAAO,aAAa,CAAC,EAAE,GAAG,OAAO,aAAa,CAAC,IAAI,OAAO,aAAa,EAAE,IAAI,OAAO,aAAa,EAAE,IAAI,OAAO,aAAa,EAAE,EAAE,GAAG,OAAO,aAAa,EAAE,IAAI,OAAO,aAAa,GAAG,EAAE,IACzL,GACD;;;;;;AAYA,IAAa,iBAAqD,OAAO,OAAO;CAC/E,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;AACR,CAAC;;;;;;;;;;;AAYD,IAAa,eAAsE,OAAO,OAAO;CAChG,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;AACR,CAAC;;;;;;AAOD,IAAa,oBAAoB;;AAGjC,IAAa,oBAA8B;;;;;;AAO3C,IAAa,aAAkC,OAAO,OAAO;CAAC;CAAS;CAAQ;CAAQ;AAAO,CAAC;;;;;;;;;;AAiB/F,IAAa,eAA2D,OAAO,OAAO;CACrF,QAAQ,OAAO,OAAO;EACrB,YAAY;EACZ,UAAU;EACV,SAAS;EACT,UAAU;EACV,YAAY;EACZ,aAAa;EACb,OAAO;EACP,SAAS;EACT,OAAO;EACP,UAAU;EACV,SAAS;CACV,CAAC;CACD,QAAQ,OAAO,OAAO;EACrB,YAAY;EACZ,UAAU;EACV,SAAS;EACT,UAAU;EACV,YAAY;EACZ,aAAa;EACb,OAAO;EACP,SAAS;EACT,OAAO;EACP,UAAU;EACV,SAAS;CACV,CAAC;CACD,OAAO,OAAO,OAAO;EACpB,YAAY;EACZ,UAAU;EACV,SAAS;EACT,UAAU;EACV,YAAY;EACZ,aAAa;EACb,OAAO;EACP,SAAS;EACT,OAAO;EACP,UAAU;EACV,SAAS;CACV,CAAC;CACD,OAAO,OAAO,OAAO;EACpB,YAAY;EACZ,UAAU;EACV,SAAS;EACT,UAAU;EACV,YAAY;EACZ,aAAa;EACb,OAAO;EACP,SAAS;EACT,OAAO;EACP,UAAU;EACV,SAAS;CACV,CAAC;AACF,CAAC;;;;;;AAOD,IAAa,eAAsD,OAAO,OAAO;CAChF,SAAS;CACT,OAAO;CACP,MAAM;CACN,MAAM;AACP,CAAC;;;;;;;AAQD,IAAa,gBACZ,OAAO,OAAO;CACb,SAAS;CACT,OAAO;CACP,MAAM;CACN,MAAM;AACP,CAAC;;;;;;AAOF,IAAa,gBAAwC,OAAO,OAAO;CAClE;CACA;CACA;CACA;AACD,CAAC;;;;;;;AAQD,IAAa,gBAAgB;;AAG7B,IAAa,kBAAkB;;AAG/B,IAAa,iBAA8B;;AAG3C,IAAa,gBAA2B;;AAGxC,IAAa,iBAAiB;;;;;AAM9B,IAAa,sBAAsB;;;;;;AAOnC,IAAa,YAAY;;;;;;;AAczB,IAAa,iBAA0C,OAAO,OAAO;CACpE;CACA;CACA;CACA;CACA;AACD,CAAC;;;;;;;;AASD,IAAa,wBAAwB;;;;;;;;;AAUrC,IAAa,oBAA8D,OAAO,OAAO;CACxF,KAAK;CACL,MAAM;CACN,MAAM;CACN,OAAO;CACP,OAAO;AACR,CAAC;;;;;;;;;;AAkBD,IAAa,iBAAoC,OAAO,OAAO;CAC9D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC;;;;;;;AAQD,IAAa,2BAA2B;;;;;;AAOxC,IAAa,WAAW;;;;;;AAOxB,IAAa,YAAY;;;;;;;;AASzB,IAAa,oBAAoB;;;;;;;;;;;;;;AAqBjC,IAAa,gBAAuB,OAAO,OAAO;CACjD,QAAQ,OAAO,OAAO;EACrB,OAAO,OAAO,OAAO;GAAE,YAAY,aAAa;GAAO,YAAY,YAAY;EAAW,CAAC;EAC3F,MAAM,OAAO,OAAO;GAAE,YAAY,aAAa;GAAM,YAAY,YAAY;EAAW,CAAC;EACzF,MAAM,OAAO,OAAO;GAAE,YAAY,aAAa;GAAM,YAAY,YAAY;EAAW,CAAC;EACzF,OAAO,OAAO,OAAO;GAAE,YAAY,aAAa;GAAO,YAAY,YAAY;EAAW,CAAC;CAC5F,CAAC;CACD,UAAU,OAAO,OAAO;EACvB,SAAS,OAAO,OAAO;GACtB,MAAM,aAAa;GACnB,OAAO,OAAO,OAAO;IACpB,YAAY,cAAc;IAC1B,YAAY,YAAY;GACzB,CAAC;EACF,CAAC;EACD,OAAO,OAAO,OAAO;GACpB,MAAM,aAAa;GACnB,OAAO,OAAO,OAAO;IAAE,YAAY,cAAc;IAAO,YAAY,YAAY;GAAW,CAAC;EAC7F,CAAC;EACD,MAAM,OAAO,OAAO;GACnB,MAAM,aAAa;GACnB,OAAO,OAAO,OAAO;IAAE,YAAY,cAAc;IAAM,YAAY,YAAY;GAAW,CAAC;EAC5F,CAAC;EACD,MAAM,OAAO,OAAO;GACnB,MAAM,aAAa;GACnB,OAAO,OAAO,OAAO;IAAE,YAAY,cAAc;IAAM,YAAY,YAAY;GAAW,CAAC;EAC5F,CAAC;CACF,CAAC;CACD,QAAQ,OAAO,OAAO;EAAE,YAAY;EAAQ,YAAY,YAAY;CAAW,CAAC;CAChF,QAAQ,OAAO,OAAO,EAAE,YAAY,OAAO,OAA6B,CAAC,KAAK,CAAC,EAAE,CAAC;AACnF,CAAC;;;;;;;;;;;ACzgBD,IAAa,eAAb,cAAkC,MAAM;CACvC;CACA;CAEA,YACC,MACA,SACA,SACC;EACD,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,IAAI,YAAY,KAAA,GAAW,KAAK,UAAU;CAC3C;AACD;;;;;;;;;;;;;;;;AAiBA,SAAgB,eAAe,OAAuC;CACrE,OAAO,iBAAiB;AACzB;;;;;;;;;;;;;;;;;;;;ACSA,SAAgB,MAAM,MAAsB;CAC3C,OAAO,KAAK,QAAQ,IAAI,OAAO,aAAa,QAAQ,aAAa,KAAK,GAAG,EAAE;AAC5E;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,cAAc,MAAsB;CACnD,OAAO,KAAK,QAAQ,IAAI,OAAO,gBAAgB,QAAQ,gBAAgB,KAAK,GAAG,EAAE;AAClF;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,MAAM,MAAsB;CAC3C,OAAO,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC;AACzB;;;;;;;;;;;;;;;;AAiBA,SAAgB,YAAY,OAAqB;CAChD,OAAO,OAAO,OAAO;EAAE,GAAG;EAAO,YAAY,OAAO,OAAO,CAAC,GAAG,MAAM,UAAU,CAAC;CAAE,CAAC;AACpF;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,WAAW,WAAqB,OAA0B;CACzE,OAAO,eAAe,UAAU,eAAe;AAChD;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,aAAgB,OAA6B,SAA0B;CACtF,IAAI,UAAU,SAAS,OAAO,QAAQ;CACtC,IAAI,UAAU,QAAQ,OAAO,QAAQ;CACrC,OAAO,QAAQ;AAChB;;;;;;;;;;;;AAaA,SAAgB,WAAW,MAAsB;CAChD,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,YAAY;AACnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,aAAa,QAAmB,QAAyB,OAAsB;CAC9F,MAAM,OAAO,OAAO,OAAO,MAAM,QAAQ,WAAW,OAAO,IAAI,CAAC;CAChE,MAAM,QAAQ,OAAO,OAAO,MAAM,OAAO,OAAO,QAAQ,OAAO,MAAM,YAAY,CAAC;CAClF,MAAM,OACL,OAAO,SAAS,KAAA,IAAY,KAAK,IAAI,OAAO,OAAO,MAAM,QAAQ,IAAI,OAAO,KAAK,EAAE;CACpF,MAAM,OACL,OAAO,SAAS,KAAA,KAAa,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,WAAW,IAC9D,KACA,IAAI,OAAO,OAAO,MAAM,QAAQ,KAAK,UAAU,OAAO,IAAI,CAAC;CAC/D,OAAO,GAAG,KAAK,GAAG,QAAQ,KAAK,GAAG,OAAO,UAAU;AACpD;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,MAAM,MAAc,SAAiB,YAAuB,eAAuB;CAClG,MAAM,UAAU,MAAM,IAAI;CAC1B,IAAI,UAAU,SAAS,OAAO,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,KAAK,EAAE;CACxE,MAAM,UAAU,UAAU;CAC1B,IAAI,cAAc,SAAS,OAAO,GAAG,IAAI,OAAO,OAAO,IAAI;CAC3D,IAAI,cAAc,UAAU;EAC3B,MAAM,OAAO,KAAK,MAAM,UAAU,CAAC;EACnC,OAAO,GAAG,IAAI,OAAO,IAAI,IAAI,OAAO,IAAI,OAAO,UAAU,IAAI;CAC9D;CACA,OAAO,GAAG,OAAO,IAAI,OAAO,OAAO;AACpC;;;;;;;;;;;;;AAcA,SAAgB,eAAe,IAAoB;CAClD,OAAO,KAAA,MAAiB,GAAG,GAAG,MAAM,IAAI,KAAK,UAAA,CAAW,QAAQ,CAAC,EAAE;AACpE;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,MAAM,QAAqC,MAAc,OAAuB;CAC/F,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,OAAO,UAAU,KAAA,IAAY,OAAO,IAAI,IAAI,OAAO,OAAO,OAAO,IAAI;AACtE;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,SAAS,MAAc,SAAyB;CAC/D,IAAI,WAAW,GAAG,OAAO;CACzB,MAAM,MAAM,MAAM,IAAI;CACtB,IAAI,QAAQ,GAAG,OAAO;CAEtB,OAAO,CAAC,GADM,KAAK,OAAO,KAAK,KAAK,UAAU,GAAG,CACtC,CAAK,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,KAAK,EAAE;AAC5C;;;;;;;;;;AAWA,SAAgB,OAAO,KAAwB,OAAuB;CACrE,OAAO,IAAI,UAAU;AACtB;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,gBAAgB,SAAmC;CAClE,MAAM,QAAQ,QAAQ,SAAA;CACtB,MAAM,OAAO,QAAQ,QAAA;CACrB,IAAI,QAAQ,UAAU,KAAA,GACrB,OAAO,MAAM,QAAQ,QAAQ,SAAS,MAAM,KAAK,GAAG,QAAQ,KAAK;CAClE,MAAM,SAAS,IAAyB,MAAM,QAAQ,QAAQ,QAAQ,OAAO,QAAQ,KAAK;CAC1F,MAAM,OAAO,QAAQ,MAAM,QAAQ,KAAK,IAAA;CACxC,IAAI,QAAQ,GAAG,OAAO;CACtB,MAAM,OAAO,KAAK,MAAM,OAAO,CAAC;CAChC,OAAO,GAAG,MAAM,QAAQ,QAAQ,SAAS,MAAM,IAAI,GAAG,QAAQ,KAAK,IAAI,SAAS,MAAM,QAAQ,QAAQ,SAAS,MAAM,OAAO,IAAI,GAAG,QAAQ,KAAK;AACjJ;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,UAAU,SAA6B;CACtD,MAAM,QAAQ,aAAa,QAAQ,UAAA;CACnC,MAAM,UAAU,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,WAAA,CAA0B,CAAC;CAC1E,MAAM,SAAS,QAAQ;CAKvB,MAAM,QAAQ,QAAQ,QAAQ,MAAM,SAAS;CAO7C,MAAM,YACL,QAAQ,UAAU,KAAA,IACf,IACA,MAAM,QAAQ,KAAK,IAAA,IAAqC,IAAI,UAAU;CAC1E,MAAM,SAAS,QAAQ,UAAU,KAAA,IAAY,IAAI,QAAQ,QAAQ,IAAI,UAAU;CAC/E,MAAM,QAAQ,MAAM,QAClB,KAAK,SAAS,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC,GACxC,KAAK,IAAI,GAAG,WAAW,MAAM,CAC9B;CACA,MAAM,SAAS,IAAI,OAAO,OAAO;CACjC,MAAM,MAAM,MAAM,QAAQ,MAAM,UAAU,QAAQ,KAAK;CAMvD,MAAM,OAAO,QAAQ,UAAU;CAC/B,IAAI;CACJ,IAAI,QAAQ,UAAU,KAAA,GACrB,MAAM,MACL,QACA,GAAG,MAAM,UAAU,SAAS,MAAM,YAAY,IAAI,IAAI,MAAM,YAC5D,QAAQ,KACT;MACM;EACN,MAAM,UAAU,IAAyB,QAAQ;EACjD,MAAM,OAAO,OAAO,MAAM,OAAO;EACjC,MAAM,OAAO,MAAM,QAAQ,SAAS,MAAM,YAAY,CAAC,GAAG,QAAQ,KAAK;EACvE,MAAM,OACL,OAAO,KAAK,IAAI,KAAK,MAAM,QAAQ,SAAS,MAAM,YAAY,OAAO,CAAC,GAAG,QAAQ,KAAK;EACvF,MAAM,GAAG,MAAM,QAAQ,MAAM,SAAS,QAAQ,KAAK,IAAI,OAAO,MAAM,QAAQ,SAAS,QAAQ,KAAK,IAAI,OAAO,MAAM,QAAQ,MAAM,UAAU,QAAQ,KAAK;CACzJ;CACA,MAAM,SAAS,MACd,QACA,GAAG,MAAM,aAAa,SAAS,MAAM,YAAY,QAAQ,UAAU,CAAC,IAAI,MAAM,eAC9E,QAAQ,KACT;CACA,MAAM,OAAO,MAAM,KAAK,SAAS,GAAG,MAAM,SAAS,MAAM,MAAM,KAAK,IAAI,SAAS,KAAK;CACtF,OAAO;EAAC;EAAK,GAAG;EAAM;CAAM,CAAC,CAAC,KAAK,IAAI;AACxC;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,YAAY,SAA+B;CAC1D,MAAM,QAAQ,aAAa,QAAQ,UAAA;CACnC,MAAM,SAAS,QAAQ;CACvB,MAAM,UAAU,QAAQ;CAExB,MAAM,SAAS,QAAQ,KAAK,QAAQ,UACnC,QAAQ,KAAK,QACX,KAAK,QAAQ,KAAK,IAAI,KAAK,MAAM,OAAO,KAAK,KAAK,CAAC,CAAC,GACrD,MAAM,OAAO,KAAK,CACnB,CACD;CACA,MAAM,SAAS,QAAQ,KAAK,WAAW,OAAO,SAAA,MAAsB;CAOpE,MAAM,eAAe,CALpB,QAAQ,KAAK,WAAW,MAAM,QAAQ,OAAO,OAAO,QAAQ,KAAK,CAAC,GAClE,GAAG,QAAQ,KAAK,KAAK,QAAQ,QAAQ,KAAK,SAAS,UAAU,OAAO,KAAK,KAAK,CAAC,CAAC,CAI5D,CAAA,CAAK,KAAK,UAAU;EACxC,MAAM,MAAM,MAAM,QAAQ,MAAM,UAAU,QAAQ,KAAK;EAOvD,OAAO,GAAG,MANI,MACZ,KACC,MAAM,UACN,IAAI,MAAM,MAAM,OAAO,UAAU,MAAM,IAAI,GAAG,OAAO,UAAA,MAAuB,EAAE,EAChF,CAAC,CACA,KAAK,GACS,IAAQ;CACzB,CAAC;CACD,MAAM,WAAW,OAAO,KAAK,gBAAgB,SAAS,MAAM,YAAY,cAAc,CAAC,CAAC;CACxF,MAAM,MAAM,MACX,QACA,GAAG,MAAM,UAAU,SAAS,KAAK,MAAM,OAAO,IAAI,MAAM,YACxD,QAAQ,KACT;CACA,MAAM,OAAO,MACZ,QACA,GAAG,MAAM,WAAW,SAAS,KAAK,MAAM,KAAK,IAAI,MAAM,WACvD,QAAQ,KACT;CACA,MAAM,SAAS,MACd,QACA,GAAG,MAAM,aAAa,SAAS,KAAK,MAAM,KAAK,IAAI,MAAM,eACzD,QAAQ,KACT;CACA,OAAO;EAAC;EAAK,GAAG,aAAa,MAAM,GAAG,CAAC;EAAG;EAAM,GAAG,aAAa,MAAM,CAAC;EAAG;CAAM,CAAC,CAAC,KAAK,IAAI;AAC5F;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,WAAW,SAA8B;CACxD,MAAM,SAAS,QAAQ,UAAA;CACvB,OAAO,CACN,QAAQ,KAAK,OACb,GAAG,mBAAmB,QAAQ,KAAK,YAAY,CAAC,GAAG,IAAI;EAAE,GAAG;EAAS;CAAO,CAAC,CAC9E,CAAC,CAAC,KAAK,IAAI;AACZ;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,mBACf,OACA,QACA,SACoB;CACpB,MAAM,QAAQ,aAAa,QAAQ;CACnC,MAAM,SAAS,GAAG,MAAM,WAAW,MAAM,WAAW;CACpD,MAAM,SAAS,GAAG,MAAM,aAAa,MAAM,WAAW;CACtD,MAAM,QAAQ,GAAG,MAAM,SAAS;CAChC,MAAM,QAAkB,CAAC;CACzB,MAAM,SAAS,MAAM,UAAU;EAC9B,MAAM,OAAO,UAAU,MAAM,SAAS;EACtC,MAAM,KACL,GAAG,SAAS,MAAM,QAAQ,QAAQ,OAAO,SAAS,QAAQ,QAAQ,KAAK,IAAI,KAAK,OACjF;EACA,MAAM,QAAQ,GAAG,SAAS,MAAM,QAAQ,QAAQ,OAAO,QAAQ,OAAO,QAAQ,KAAK;EACnF,MAAM,KAAK,GAAG,mBAAmB,KAAK,YAAY,CAAC,GAAG,OAAO,OAAO,CAAC;CACtE,CAAC;CACD,OAAO;AACR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,SAAgB,eAAe,OAAwB;CACtD,IAAI,iBAAiB,OAAO,OAAO,GAAG,MAAM,KAAK,IAAI,MAAM;CAC3D,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU,OAAO,OAAO,KAAK;CAIpE,MAAM,uBAAO,IAAI,QAAgB;CACjC,IAAI;EACH,OAAO,KAAK,UAAU,QAAQ,MAAM,WAAoB;GACvD,IAAI,WAAW,QAAQ,OAAO,WAAW,UAAU;IAClD,IAAI,KAAK,IAAI,MAAM,GAAG,OAAO;IAC7B,KAAK,IAAI,MAAM;GAChB;GACA,OAAO;EACR,CAAC;CACF,QAAQ;EACP,OAAO,OAAO,KAAK;CACpB;AACD;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,WAAW,MAAkC;CAC5D,OAAO,KAAK,IAAI,cAAc,CAAC,CAAC,KAAK,GAAG;AACzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,UAAU,SAA6B;CACtD,MAAM,QAAQ,QAAQ,SAAA;CACtB,MAAM,OAAO,QAAQ,QAAA;CACrB,MAAM,QAAQ,QAAQ,SAAA;CAGtB,MAAM,UAAU,QAAQ,SAAS,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,OAAO,QAAQ,OAAO,CAAC;CAC7F,MAAM,WAAW,QAAQ,SAAS,IAAI,IAAI,UAAU,QAAQ;CAC5D,MAAM,cAAc,KAAK,MAAM,WAAW,KAAK;CAG/C,OAAO,GAAG,GAFK,MAAM,QAAQ,QAAQ,SAAS,MAAM,WAAW,GAAG,QAAQ,KAAK,IAAI,SAAS,OAAO,QAAQ,WAAW,IAExG,GADE,KAAK,MAAM,WAAW,GACrB,EAAQ,KAAK,QAAQ,GAAG,QAAQ,MAAM;AACxD;;;;;;;;;;;;;;;;;;;;;;;;ACvrBA,IAAa,eAAb,MAAuD;;;;;CAKtD,OAAO,OAAc,MAAsB;EAC1C,IAAI,SAAS,IAAI,OAAO;EACxB,MAAM,QAAQ,KAAK,OAAO,KAAK;EAC/B,IAAI,MAAM,WAAW,GAAG,OAAO;EAC/B,OAAO,GAAG,MAAM,MAAM,KAAK,GAAG,EAAE,GAAG,OAAO;CAC3C;CAKA,OAAO,OAAiC;EACvC,MAAM,QAAkB,CAAC;EACzB,KAAK,MAAM,aAAa,MAAM,YAAY,MAAM,KAAK,gBAAgB,UAAU;EAC/E,IAAI,MAAM,eAAe,KAAA,KAAa,MAAM,eAAe,WAC1D,MAAM,KAAK,iBAAiB,MAAM,WAAW;EAE9C,IAAI,MAAM,eAAe,KAAA,KAAa,MAAM,eAAe,WAC1D,MAAM,KAAK,iBAAiB,MAAM,WAAW;EAE9C,OAAO;CACR;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpBA,IAAa,YAAb,MAA8F;CAC7F;CAEA,WAAyB,CAAC;CAE1B,2BAAoB,IAAI,IAAqB;CAE7C,YAAY,QAAmC,OAAe;EAC7D,KAAK,SAAS;EACd,KAAK,MAAM,SAAS,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,CAAC;CACxD;CAEA,IAAI,QAAiB;EACpB,KAAK,MAAM,KAAK,UAAU,MAAM;EAChC,MAAM,SAAS,KAAK,SAAS,IAAI,OAAO,KAAK;EAC7C,IAAI,WAAW,KAAA,GAAW,KAAK,MAAM,QAAQ,MAAM;CACpD;CAIA,QAAQ,OAAkC;EACzC,IAAI,UAAU,KAAA,GAAW,OAAO,CAAC,GAAG,KAAK,QAAQ;EACjD,OAAO,CAAC,GAAI,KAAK,SAAS,IAAI,KAAK,KAAK,CAAC,CAAE;CAC5C;CAEA,QAAc;EACb,KAAK,SAAS,SAAS;EACvB,KAAK,MAAM,UAAU,KAAK,SAAS,OAAO,GAAG,OAAO,SAAS;CAC9D;CAGA,MAAM,QAAa,QAAiB;EACnC,OAAO,KAAK,MAAM;EAClB,IAAI,OAAO,SAAS,KAAK,QAAQ,OAAO,MAAM;CAC/C;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AClBA,IAAa,UAAb,MAAiD;CAIhD;CACA;CACA;CACA;CAGA;CAGA,6BAAsB,IAAI,IAAiC;CAG3D,UAAU;CAEV,YAAY,SAA0B;EACrC,KAAK,WAAW,IAAI,QAAyB;GAC5C,GAAI,SAAS,OAAO,KAAA,IAAY,EAAE,IAAI,QAAQ,GAAG,IAAI,CAAC;GACtD,GAAI,SAAS,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;EAChE,CAAC;EACD,KAAK,UAAU,SAAS,UAAU;EAClC,KAAK,UAAU,SAAS,UAAU;EAClC,KAAK,QAAQ,SAAS;EACtB,KAAK,aAAa,IAAI,UACrB,KAAK,SACL,SAAS,SAAA,GACV;CACD;CAEA,IAAI,UAA6C;EAChD,OAAO,KAAK;CACb;CAEA,IAAI,SAAkB;EACrB,OAAO,KAAK;CACb;CAEA,QAAc;EAGb,IAAI,KAAK,SAAS;EAClB,KAAK,UAAU;EACf,MAAM,SAA8C;EACpD,KAAK,MAAM,SAAS,KAAK,SAAS;GAGjC,MAAM,WAAW,OAAO;GACxB,KAAK,WAAW,IAAI,OAAO,QAAQ;GAKnC,MAAM,SAAS,SAAS,KAAK,OAAO;GACpC,OAAO,SAAS,KAAK,aAAa,KAAK,MAAM,OAAO,MAAM;EAC3D;EACA,KAAK,SAAS,KAAK,OAAO;CAC3B;CAEA,OAAa;EAEZ,IAAI,CAAC,KAAK,SAAS;EACnB,KAAK,UAAU;EACf,MAAM,SAA8C;EACpD,KAAK,MAAM,CAAC,OAAO,aAAa,KAAK,YAAY,OAAO,SAAS;EACjE,KAAK,WAAW,MAAM;EACtB,KAAK,SAAS,KAAK,MAAM;CAC1B;CAIA,SAAS,OAAkD;EAC1D,IAAI,UAAU,KAAA,GAAW,OAAO,KAAK,WAAW,QAAQ;EACxD,OAAO,KAAK,WAAW,QAAQ,KAAK;CACrC;CAEA,QAAc;EACb,KAAK,WAAW,MAAM;CACvB;CAEA,UAAgB;EACf,KAAK,KAAK;EACV,KAAK,SAAS,QAAQ;CACvB;CAIA,aAAa,OAAqB,QAAuB,GAAG,MAAuB;EAClF,KAAK,WAAW,OAAO,MAAM,MAAM;CACpC;CAOA,WAAW,OAAqB,MAAiB,QAA6B;EAC7E,MAAM,UAAU,KAAK,SAAS,OAAO,IAAI;EACzC,KAAK,WAAW,IAAI,OAAO;EAC3B,KAAK,SAAS,KAAK,WAAW,OAAO;EACrC,IAAI,KAAK,SAAS,OAAO,GAAG,IAAI;EAGhC,IAAI,KAAK,UAAU,KAAA,GAClB,IAAI;GACH,KAAK,MAAM,MAAM,QAAQ,MAAM,kBAAkB,MAAM;EACxD,QAAQ,CAER;CAEF;CAKA,SAAS,OAAqB,MAA2C;EACxE,OAAO,OAAO,OAAO;GAAE;GAAO,MAAM,WAAW,IAAI;GAAG,MAAM,KAAK,IAAI;EAAE,CAAC;CACzE;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACzIA,IAAa,SAAb,MAAa,OAAO;CACnB;CACA;CACA;CAEA,YAAY,UAA6B,SAAkB,OAAc;EACxE,KAAK,YAAY;EACjB,KAAK,WAAW;EAChB,KAAK,SAAS;CACf;;CAGA,IAAI,QAAe;EAClB,OAAO,KAAK;CACb;;CAGA,IAAI,UAAmB;EACtB,OAAO,KAAK;CACb;;;;;;;;;;;;;;CAeA,IAAI,UAA2B;EAC9B,MAAM,WAAW,KAAK,QAAQ,KAAK,IAAI;EACvC,MAAM,cAAqC;GAC1C,OAAO;IAAE,OAAO,KAAK;IAAQ,YAAY;GAAK;GAC9C,SAAS;IAAE,OAAO,KAAK;IAAU,YAAY;GAAK;GAClD,QAAQ;IAAE,OAAO,KAAK,OAAO,KAAK,IAAI;IAAG,YAAY;GAAK;EAC3D;EACA,KAAK,MAAM,SAAS,QACnB,YAAY,SAAS;GACpB,KAAK,KAAK,mBAAmB,KAAK,MAAM,KAAK;GAC7C,YAAY;EACb;EAED,KAAK,MAAM,aAAa,YACvB,YAAY,aAAa;GACxB,KAAK,KAAK,kBAAkB,KAAK,MAAM,SAAS;GAChD,YAAY;EACb;EAED,MAAM,UAAU,OAAO,iBAAiB,UAAU,WAAW;EAC7D,IAAI,KAAK,WAAW,OAAO,GAAG,OAAO;EAErC,MAAM,IAAI,aAAa,aAAa,oDAAoD;CACzF;;;;;;;;;;;;;;;;;;;;CAqBA,OAAO,OAAc,MAAsB;EAC1C,OAAO,KAAK,WAAW,KAAK,UAAU,OAAO,KAAK,OAAO,KAAK,GAAG,IAAI,IAAI;CAC1E;CAGA,QAAQ,MAAsB;EAC7B,OAAO,KAAK,WAAW,KAAK,UAAU,OAAO,KAAK,QAAQ,IAAI,IAAI;CACnE;CAMA,OAAO,OAAqB;EAC3B,MAAM,aAA0B,CAAC,GAAG,KAAK,OAAO,UAAU;EAC1D,KAAK,MAAM,aAAa,MAAM,YAC7B,IAAI,CAAC,WAAW,SAAS,SAAS,GAAG,WAAW,KAAK,SAAS;EAE/D,OAAO,OAAO,OAAO;GACpB,GAAG,KAAK;GACR,GAAG;GACH,YAAY,OAAO,OAAO,UAAU;EACrC,CAAC;CACF;CAGA,mBAAmB,OAA+B;EACjD,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC;CAChC;CAGA,kBAAkB,WAAuC;EACxD,OAAO,KAAK,WAAW,SAAS,CAAC,CAAC;CACnC;CAMA,WAAW,OAAsE;EAChF,OACC,OAAO,UAAU,cACjB,WAAW,SACX,aAAa,SACb,YAAY,SACZ,SAAS,SACT,UAAU;CAEZ;CAIA,YAAY,OAAsB;EACjC,OAAO,IAAI,OACV,KAAK,WACL,KAAK,UACL,OAAO,OAAO;GAAE,GAAG,KAAK;GAAQ,YAAY;EAAM,CAAC,CACpD;CACD;CAIA,WAAW,WAA8B;EACxC,IAAI,KAAK,OAAO,WAAW,SAAS,SAAS,GAAG,OAAO;EACvD,OAAO,IAAI,OACV,KAAK,WACL,KAAK,UACL,OAAO,OAAO;GACb,GAAG,KAAK;GACR,YAAY,OAAO,OAAO,CAAC,GAAG,KAAK,OAAO,YAAY,SAAS,CAAC;EACjE,CAAC,CACF;CACD;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACxIA,SAAgB,aAAa,SAA0C;CAGtE,OAAO,IAAI,OAFM,SAAS,YAAY,IAAI,aAAa,GACvC,SAAS,WAAW,MACC,WAAW,CAAC,CAAC;AACnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,YAAY,SAA+B;CAC1D,MAAM,SAAS,EAAE,GAAG,cAAc,OAAO;CACzC,KAAK,MAAM,SAAS,YACnB,OAAO,SAAS,YAAY,SAAS,SAAS,UAAU,cAAc,OAAO,MAAM;CAEpF,MAAM,WAAW,EAAE,GAAG,cAAc,SAAS;CAC7C,KAAK,MAAM,UAAU,eAAe;EACnC,MAAM,SAAS,SAAS,WAAW,WAAW,cAAc,SAAS;EACrE,SAAS,UAAU,OAAO,OAAO;GAAE,MAAM,OAAO;GAAM,OAAO,YAAY,OAAO,KAAK;EAAE,CAAC;CACzF;CACA,OAAO,OAAO,OAAO;EACpB,QAAQ,OAAO,OAAO,MAAM;EAC5B,UAAU,OAAO,OAAO,QAAQ;EAChC,QAAQ,YAAY,SAAS,UAAU,cAAc,MAAM;EAC3D,QAAQ,YAAY,SAAS,UAAU,cAAc,MAAM;CAC5D,CAAC;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,oBAAmC;CAGlD,MAAM,MAAM,QAAQ,IAAI,KAAK,OAAO;CACpC,MAAM,OAAO,QAAQ,KAAK,KAAK,OAAO;CACtC,MAAM,QAAQ,QAAQ,MAAM,KAAK,OAAO;CACxC,OAAO,EACN,MAAM,MAAc,OAAwB;EAC3C,aAAa,OAAO;GAAE;GAAK;GAAM;EAAM,CAAC,CAAC,CAAC,IAAI;CAC/C,EACD;AACD;AAmEA,SAAgB,oBACf,IACA,SAC+C;CAC/C,MAAM,UAAU,IAAI,QAAQ,OAAO;CACnC,QAAQ,MAAM;CACd,IAAI;EACH,MAAM,SAAS,GAAG;EAClB,IAAI,kBAAkB,SACrB,OAAO,OAAO,MACZ,UAAU;GACV,MAAM,WAAW,QAAQ,SAAS;GAClC,QAAQ,QAAQ;GAChB,OAAO;IAAE;IAAO;GAAS;EAC1B,IACC,UAAmB;GACnB,QAAQ,QAAQ;GAChB,MAAM;EACP,CACD;EAED,MAAM,WAAW,QAAQ,SAAS;EAClC,QAAQ,QAAQ;EAChB,OAAO;GAAE,OAAO;GAAQ;EAAS;CAClC,SAAS,OAAO;EAEf,QAAQ,QAAQ;EAChB,MAAM;CACP;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACnLA,IAAa,SAAb,MAA+C;CAI9C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA,WAAiC,CAAC;CAClC;CAEA,YAAY,SAAyB;EACpC,KAAK,WAAW,IAAI,QAAwB;GAC3C,GAAI,SAAS,OAAO,KAAA,IAAY,EAAE,IAAI,QAAQ,GAAG,IAAI,CAAC;GACtD,GAAI,SAAS,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;EAChE,CAAC;EACD,KAAK,SAAS,SAAS,SAAA;EACvB,IAAI,SAAS,SAAS,KAAA,GAAW,KAAK,OAAO,QAAQ;EACrD,KAAK,QAAQ,SAAS,QAAQ,kBAAkB;EAChD,KAAK,UAAU,SAAS,UAAU,aAAa;EAC/C,KAAK,SAAS,SAAS,SAAS;EAChC,KAAK,UAAU,SAAS,UAAU;EAClC,KAAK,SAAS,SAAS,SAAA;EACvB,KAAK,UAAU,SAAS,UAAU;CACnC;CAEA,IAAI,UAA4C;EAC/C,OAAO,KAAK;CACb;CAEA,IAAI,QAAkB;EACrB,OAAO,KAAK;CACb;CAEA,MAAM,SAAiB,MAAsC;EAC5D,KAAK,KAAK,SAAS,SAAS,IAAI;CACjC;CAEA,KAAK,SAAiB,MAAsC;EAC3D,KAAK,KAAK,QAAQ,SAAS,IAAI;CAChC;CAEA,KAAK,SAAiB,MAAsC;EAC3D,KAAK,KAAK,QAAQ,SAAS,IAAI;CAChC;CAEA,MAAM,SAAiB,MAAsC;EAC5D,KAAK,KAAK,SAAS,SAAS,IAAI;CACjC;CAEA,UAAgC;EAC/B,OAAO,CAAC,GAAG,KAAK,QAAQ;CACzB;CAEA,QAAc;EACb,KAAK,SAAS,SAAS;CACxB;CAEA,UAAgB;EACf,KAAK,SAAS,SAAS;EACvB,KAAK,SAAS,QAAQ;CACvB;CAKA,KAAK,OAAiB,SAAiB,MAAiD;EACvF,IAAI,CAAC,WAAW,KAAK,QAAQ,KAAK,GAAG;EACrC,MAAM,SAAS,KAAK,QAAQ,OAAO,SAAS,IAAI;EAChD,KAAK,QAAQ,MAAM;EAEnB,KAAK,SAAS,KAAK,SAAS,MAAM;EAClC,IAAI,KAAK,SAAS;EAGlB,KAAK,MAAM,MAAM,KAAK,QAAQ,QAAQ,KAAK,SAAS,KAAK,MAAM,GAAG,KAAK;CACxE;CAKA,QAAQ,OAAiB,SAAiB,MAAsD;EAC/F,OAAO,OAAO,OAAO;GACpB;GACA;GACA,MAAM,KAAK,IAAI;GACf,GAAI,KAAK,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK;GACrD,GAAI,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,OAAO,OAAO,EAAE,GAAG,KAAK,CAAC,EAAE;EAClE,CAAC;CACF;CAIA,QAAQ,QAAyB;EAChC,KAAK,SAAS,KAAK,MAAM;EACzB,IAAI,KAAK,SAAS,SAAS,KAAK,QAAQ,KAAK,SAAS,MAAM;CAC7D;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC9GA,IAAa,gBAAb,MAA6D;CAC5D,2BAAoB,IAAI,IAA6B;CAErD;CACA;CACA;CACA;CACA;CACA;CACA;CAEA,YAAY,SAAgC;EAC3C,KAAK,SAAS,SAAS;EACvB,KAAK,QAAQ,SAAS;EACtB,KAAK,UAAU,SAAS;EACxB,KAAK,SAAS,SAAS;EACvB,KAAK,UAAU,SAAS;EACxB,KAAK,SAAS,SAAS;EACvB,KAAK,UAAU,SAAS;CACzB;CAEA,IAAI,QAAgB;EACnB,OAAO,KAAK,SAAS;CACtB;CAEA,SAAS,MAAc,SAA0C;EAGhE,MAAM,SAAS,IAAI,OAAO;GACzB,GAAI,KAAK,WAAW,KAAA,IAAY,EAAE,OAAO,KAAK,OAAO,IAAI,CAAC;GAC1D,GAAI,KAAK,UAAU,KAAA,IAAY,EAAE,MAAM,KAAK,MAAM,IAAI,CAAC;GACvD,GAAI,KAAK,YAAY,KAAA,IAAY,EAAE,QAAQ,KAAK,QAAQ,IAAI,CAAC;GAC7D,GAAI,KAAK,WAAW,KAAA,IAAY,EAAE,OAAO,KAAK,OAAO,IAAI,CAAC;GAC1D,GAAI,KAAK,YAAY,KAAA,IAAY,EAAE,QAAQ,KAAK,QAAQ,IAAI,CAAC;GAC7D,GAAI,KAAK,WAAW,KAAA,IAAY,EAAE,OAAO,KAAK,OAAO,IAAI,CAAC;GAC1D,GAAI,KAAK,YAAY,KAAA,IAAY,EAAE,QAAQ,KAAK,QAAQ,IAAI,CAAC;GAC7D,GAAG;GACH;EACD,CAAC;EACD,KAAK,SAAS,IAAI,MAAM,MAAM;EAC9B,OAAO;CACR;CAEA,OAAO,MAA2C;EACjD,OAAO,KAAK,SAAS,IAAI,IAAI;CAC9B;CAEA,UAAsC;EACrC,OAAO,CAAC,GAAG,KAAK,SAAS,OAAO,CAAC;CAClC;CAEA,MAAM,SAAiB,MAAsC;EAC5D,KAAK,MAAM,UAAU,KAAK,SAAS,OAAO,GAAG,OAAO,MAAM,SAAS,IAAI;CACxE;CAEA,KAAK,SAAiB,MAAsC;EAC3D,KAAK,MAAM,UAAU,KAAK,SAAS,OAAO,GAAG,OAAO,KAAK,SAAS,IAAI;CACvE;CAEA,KAAK,SAAiB,MAAsC;EAC3D,KAAK,MAAM,UAAU,KAAK,SAAS,OAAO,GAAG,OAAO,KAAK,SAAS,IAAI;CACvE;CAEA,MAAM,SAAiB,MAAsC;EAC5D,KAAK,MAAM,UAAU,KAAK,SAAS,OAAO,GAAG,OAAO,MAAM,SAAS,IAAI;CACxE;CAOA,OAAO,OAAoD;EAC1D,IAAI,UAAU,KAAA,GAAW;GACxB,KAAK,SAAS,MAAM;GACpB;EACD;EACA,IAAI,QAAQ,KAAK,GAAG;GAGnB,IAAI,UAAU;GACd,KAAK,MAAM,QAAQ,OAClB,IAAI,CAAC,KAAK,SAAS,OAAO,IAAI,GAAG,UAAU;GAE5C,OAAO;EACR;EACA,OAAO,KAAK,SAAS,OAAO,KAAK;CAClC;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrFA,IAAa,WAAb,MAAmD;CAClD;CACA;CACA;CACA;CAEA,YAAY,SAA2B;EACtC,KAAK,QAAQ,SAAS,QAAQ,kBAAkB;EAChD,KAAK,UAAU,SAAS,UAAU,aAAa;EAC/C,KAAK,SAAS,SAAS,SAAS;EAChC,KAAK,SAAS,SAAS,SAAA;CACxB;CAEA,QAAQ,OAAqB;EAE5B,KAAK,MAAM,MACV,gBAAgB;GACf;GACA,OAAO,KAAK;GACZ,QAAQ,KAAK;GACb,OAAO,KAAK,OAAO;EACpB,CAAC,CACF;CACD;CAEA,KAAK,SAAiB,UAA+B;EACpD,MAAM,SACL,aAAa,KAAA,IACV,KACA,GAAG,KAAK,QAAQ,OAAO,KAAK,OAAO,QAAQ,IAAI,SAAS,MAAM,GAAG,SAAS,MAAM,EAAE,EAAE;EACxF,KAAK,MAAM,MAAM,GAAG,SAAS,SAAS;CACvC;CAEA,OAAO,OAAe,IAAkB;EACvC,KAAK,MAAM,MACV,GAAG,MAAM,GAAG,KAAK,QAAQ,OAAO,KAAK,OAAO,QAAQ,KAAK,eAAe,EAAE,GAAG,GAC9E;CACD;CAEA,OAAO,OAAoB,SAAuB;EACjD,MAAM,SAAS,KAAK,OAAO,SAAS;EACpC,MAAM,OAAO,GAAG,KAAK,QAAQ,OAAO,OAAO,OAAO,OAAO,IAAI,EAAE,GAAG,KAAK,QAAQ,OAAO,OAAO,OAAO,OAAO;EAE3G,KAAK,MAAM,MAAM,MAAM,UAAU,UAAU,UAAU,KAAA,CAAS;CAC/D;CAEA,MAAM,SAA6B;EAClC,KAAK,MAAM,MAAM,YAAY,KAAK,cAAc,OAAO,CAAC,CAAC;CAC1D;CAEA,KAAK,SAA4B;EAChC,KAAK,MAAM,MAAM,WAAW,KAAK,cAAc,OAAO,CAAC,CAAC;CACzD;CAEA,IAAI,SAA2B;EAE9B,KAAK,MAAM,MAAM,UAAU,KAAK,cAAc;GAAE,OAAO,KAAK;GAAQ,GAAG;EAAQ,CAAC,CAAC,CAAC;CACnF;CAEA,KAAK,MAAoB;EACxB,KAAK,MAAM,MAAM,IAAI;CACtB;CAEA,MAAM,QAAQ,GAAS;EACtB,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,SAAS,GAAG,KAAK,MAAM,MAAM,EAAE;CACnE;CAIA,cAAiE,SAAe;EAC/E,OAAO;GACN,QAAQ,KAAK;GACb,GAAI,QAAQ,WAAW,KAAA,KAAa,QAAQ,UAAU,KAAA,IACnD,EAAE,OAAO,KAAK,OAAO,OAAO,IAC5B,CAAC;GACJ,GAAG;EACJ;CACD;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC5EA,IAAa,UAAb,MAAiD;CAGhD;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CAEA,SAAS;CAET,YAAY,SAA0B;EACrC,KAAK,WAAW,IAAI,QAAyB;GAC5C,GAAI,SAAS,OAAO,KAAA,IAAY,EAAE,IAAI,QAAQ,GAAG,IAAI,CAAC;GACtD,GAAI,SAAS,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;EAChE,CAAC;EAGD,MAAM,SAAS,SAAS,UAAU;EAClC,KAAK,UAAU,OAAO,WAAW,IAAI,iBAAiB;EACtD,KAAK,YAAY,SAAS,YAAA;EAC1B,KAAK,QAAQ,SAAS,QAAQ,kBAAkB;EAChD,KAAK,UAAU,SAAS,UAAU,aAAa;EAC/C,KAAK,SAAS,SAAS,SAAS;EAChC,KAAK,WAAW,SAAS,WAAW;CACrC;CAEA,IAAI,UAA6C;EAChD,OAAO,KAAK;CACb;CAEA,IAAI,SAAkB;EACrB,OAAO,KAAK,YAAY,KAAA;CACzB;CAEA,IAAI,UAAkB;EACrB,OAAO,KAAK;CACb;CAEA,QAAc;EAEb,IAAI,KAAK,YAAY,KAAA,GAAW;EAChC,KAAK,UAAU,kBAAkB,KAAK,KAAK,GAAG,KAAK,SAAS;EAC5D,KAAK,SAAS,KAAK,OAAO;EAE1B,KAAK,KAAK;CACX;CAEA,OAAa;EAEZ,KAAK,OAAO,KAAK,MAAM,CAAC;EACxB,KAAK,UAAU,KAAK,SAAS,KAAK,KAAK,QAAQ;CAChD;CAEA,OAAO,SAAuB;EAC7B,KAAK,WAAW;EAEhB,IAAI,KAAK,YAAY,KAAA,GAAW,KAAK,OAAO,KAAK,MAAM,CAAC;CACzD;CAEA,QAAQ,SAAwB;EAC/B,KAAK,QAAQ,WAAW,OAAO;CAChC;CAEA,KAAK,SAAwB;EAC5B,KAAK,QAAQ,SAAS,OAAO;CAC9B;CAEA,OAAa;EAEZ,IAAI,KAAK,YAAY,KAAA,GAAW;EAChC,cAAc,KAAK,OAAO;EAC1B,KAAK,UAAU,KAAA;EACf,KAAK,SAAS,KAAK,MAAM;CAC1B;CAEA,UAAgB;EACf,KAAK,KAAK;EACV,KAAK,SAAS,QAAQ;CACvB;CAMA,QAAQ,OAA4B,SAAwB;EAC3D,KAAK,KAAK;EACV,MAAM,OAAO,WAAW,KAAK;EAC7B,IAAI,YAAY,KAAA,GAAW,KAAK,WAAW;EAC3C,MAAM,SAAS,KAAK,OAAO,SAAS;EACpC,MAAM,OAAO,GAAG,KAAK,QAAQ,OAAO,OAAO,OAAO,OAAO,IAAI,EAAE,GAAG,KAAK,QAAQ,OAAO,OAAO,OAAO,IAAI;EACxG,KAAK,SAAS,KAAK,SAAS,IAAI;EAEhC,KAAK,MAAM,MAAM,KAAK,KAAK,KAAK,UAAU,UAAU,UAAU,KAAA,CAAS;CACxE;CAIA,QAAgB;EACf,MAAM,QAAQ,KAAK,QAAQ,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,KAAK,WAAW,EAAE;EACrF,OAAO,KAAK,aAAa,KAAK,QAAQ,GAAG,MAAM,GAAG,KAAK;CACxD;CAKA,OAAO,MAAoB;EAC1B,KAAK,SAAS,KAAK,SAAS,IAAI;EAChC,KAAK,MAAM,MAAM,KAAK,MAAM;CAC7B;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACxHA,IAAa,WAAb,MAAmD;CAGlD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,WAAW;CACX,UAAU;CACV,aAAa;CAEb,YAAY,SAA0B;EACrC,KAAK,WAAW,IAAI,QAA0B;GAC7C,GAAI,QAAQ,OAAO,KAAA,IAAY,EAAE,IAAI,QAAQ,GAAG,IAAI,CAAC;GACrD,GAAI,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;EAC/D,CAAC;EACD,KAAK,SAAS,QAAQ;EACtB,KAAK,SAAS,QAAQ,SAAA;EACtB,KAAK,QAAQ,QAAQ;EACrB,KAAK,SAAS,QAAQ;EACtB,KAAK,QAAQ,QAAQ,QAAQ,kBAAkB;EAC/C,KAAK,UAAU,QAAQ,UAAU,aAAa;EAC9C,KAAK,SAAS,QAAQ,SAAS;EAC/B,KAAK,WAAW,QAAQ,WAAW;CACpC;CAEA,IAAI,UAA8C;EACjD,OAAO,KAAK;CACb;CAEA,IAAI,SAAkB;EACrB,OAAO,KAAK;CACb;CAEA,IAAI,YAAqB;EACxB,OAAO,KAAK;CACb;CAEA,IAAI,UAAkB;EACrB,OAAO,KAAK;CACb;CAEA,IAAI,QAAgB;EACnB,OAAO,KAAK;CACb;CAEA,OAAO,SAAiB,SAAwB;EAE/C,IAAI,CAAC,KAAK,SAAS;EACnB,KAAK,SAAS,SAAS,OAAO;EAC9B,KAAK,OAAO,KAAK;CAClB;CAEA,QAAQ,SAAwB;EAC/B,IAAI,CAAC,KAAK,SAAS;EAEnB,KAAK,SAAS,KAAK,QAAQ,OAAO;EAClC,KAAK,UAAU;EACf,KAAK,aAAa;EAClB,KAAK,OAAO,IAAI;EAChB,KAAK,SAAS,KAAK,SAAS;CAC7B;CAEA,KAAK,SAAwB;EAC5B,IAAI,CAAC,KAAK,SAAS;EAGnB,KAAK,SAAS,KAAK,UAAU,OAAO;EACpC,KAAK,UAAU;EACf,KAAK,OAAO,MAAM,OAAO;CAC1B;CAEA,UAAgB;EACf,KAAK,SAAS,QAAQ;CACvB;CAKA,SAAS,SAAiB,SAAwB;EACjD,KAAK,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,QAAQ,OAAO,CAAC;EAC1D,IAAI,YAAY,KAAA,GAAW,KAAK,WAAW;EAC3C,MAAM,SAAyB;GAAE,SAAS,KAAK;GAAU,OAAO,KAAK;EAAO;EAC5E,KAAK,SAAS,KAAK,UAAU,MAAM;CACpC;CAMA,OAAO,OAAgB,OAAuB;EAC7C,MAAM,MAAM,UAAU;GACrB,SAAS,KAAK;GACd,OAAO,KAAK;GACZ,OAAO,KAAK;GACZ,GAAI,KAAK,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;GACvD,GAAI,KAAK,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO;GAC1D,QAAQ,KAAK;GACb,OAAO,KAAK,OAAO;EACpB,CAAC;EACD,MAAM,OAAO,KAAK,aAAa,KAAK,MAAM,GAAG,IAAI,GAAG,KAAK;EACzD,KAAK,MAAM,MAAM,KAAK,OAAO,QAAQ,OAAO,MAAM,KAAK;CACxD;AACD"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts","../../../src/core/helpers.ts","../../../src/core/renderers/ANSIRenderer.ts","../../../src/core/Retention.ts","../../../src/core/Capture.ts","../../../src/core/Styler.ts","../../../src/core/factories.ts","../../../src/core/loggers/Logger.ts","../../../src/core/loggers/LoggerManager.ts","../../../src/core/Reporter.ts","../../../src/core/Spinner.ts","../../../src/core/Progress.ts"],"sourcesContent":["import type {\n\tAlignment,\n\tAttribute,\n\tBorderChars,\n\tBorderStyle,\n\tCaptureLevel,\n\tColor,\n\tLogLevel,\n\tStyle,\n\tStatusLevel,\n\tTheme,\n} from './types.js'\n\n// The SGR (Select Graphic Rendition) code data the ANSI renderer maps style data\n// through, plus the reset terminator and the ANSI-strip pattern. UPPER_SNAKE,\n// `Object.freeze`d, every member exported. These are the standard SGR\n// numbers (ECMA-48) — a fixed external spec, so the literals are the source of truth.\n// `default` carries no code (it leaves the target's own ink) and so is absent from the\n// color maps — the renderer emits a code only for a present, non-`default` color.\n\n/**\n * Maps each {@link Color} to its SGR foreground parameter — the 8 base colors at 30–37 and their\n * bright variants at 90–97. `default` is intentionally absent (it emits no code).\n */\nexport const FOREGROUND_CODES: Readonly<Record<Exclude<Color, 'default'>, number>> = Object.freeze({\n\tblack: 30,\n\tred: 31,\n\tgreen: 32,\n\tyellow: 33,\n\tblue: 34,\n\tmagenta: 35,\n\tcyan: 36,\n\twhite: 37,\n\tbrightBlack: 90,\n\tbrightRed: 91,\n\tbrightGreen: 92,\n\tbrightYellow: 93,\n\tbrightBlue: 94,\n\tbrightMagenta: 95,\n\tbrightCyan: 96,\n\tbrightWhite: 97,\n})\n\n/**\n * Maps each {@link Color} to its SGR background parameter — the 8 base colors at 40–47 and their\n * bright variants at 100–107. `default` is intentionally absent (it emits no code).\n */\nexport const BACKGROUND_CODES: Readonly<Record<Exclude<Color, 'default'>, number>> = Object.freeze({\n\tblack: 40,\n\tred: 41,\n\tgreen: 42,\n\tyellow: 43,\n\tblue: 44,\n\tmagenta: 45,\n\tcyan: 46,\n\twhite: 47,\n\tbrightBlack: 100,\n\tbrightRed: 101,\n\tbrightGreen: 102,\n\tbrightYellow: 103,\n\tbrightBlue: 104,\n\tbrightMagenta: 105,\n\tbrightCyan: 106,\n\tbrightWhite: 107,\n})\n\n/**\n * Maps each {@link Attribute} to its SGR \"on\" parameter — `bold` 1, `dim` 2, `italic` 3,\n * `underline` 4, `inverse` 7, `strikethrough` 9. The renderer composes several by\n * joining their codes with `;` in one SGR sequence.\n */\nexport const ATTRIBUTE_CODES: Readonly<Record<Attribute, number>> = Object.freeze({\n\tbold: 1,\n\tdim: 2,\n\titalic: 3,\n\tunderline: 4,\n\tinverse: 7,\n\tstrikethrough: 9,\n})\n\n/**\n * Holds the empty {@link Style} — no foreground, no background, no attributes — frozen. The\n * neutral starting point a base styler builds from, and what a renderer passes through\n * unchanged (it carries no codes). Deeply frozen, so it is safe to share as the base.\n */\nexport const EMPTY_STYLE: Style = Object.freeze({ attributes: Object.freeze([]) })\n\n/**\n * Lists every named {@link Color} except `default`, frozen — the colors the styler exposes as\n * chainable accessors. The source of truth for the color axis; the styler drives its\n * accessors from this array so the literals live in one place.\n */\nexport const COLORS: ReadonlyArray<Exclude<Color, 'default'>> = Object.freeze([\n\t'black',\n\t'red',\n\t'green',\n\t'yellow',\n\t'blue',\n\t'magenta',\n\t'cyan',\n\t'white',\n\t'brightBlack',\n\t'brightRed',\n\t'brightGreen',\n\t'brightYellow',\n\t'brightBlue',\n\t'brightMagenta',\n\t'brightCyan',\n\t'brightWhite',\n])\n\n/**\n * Lists every {@link Attribute}, frozen — the attributes the styler exposes as chainable\n * accessors. The source of truth for the attribute axis.\n */\nexport const ATTRIBUTES: readonly Attribute[] = Object.freeze([\n\t'bold',\n\t'dim',\n\t'italic',\n\t'underline',\n\t'inverse',\n\t'strikethrough',\n])\n\n/** Holds the SGR RESET parameter (0) — terminates a styled run, clearing all colors and attributes. */\nexport const RESET_CODE = 0\n\n/**\n * Holds the escape control character (`U+001B`) that begins every ANSI escape sequence. Built\n * with `String.fromCharCode` so no raw control character appears in source.\n */\nexport const ESC = String.fromCharCode(27)\n\n/** Holds the bell control character (`U+0007`) that can terminate an OSC sequence. */\nexport const BEL = String.fromCharCode(7)\n\n/** Holds the Control Sequence Introducer (`ESC[`) that opens every SGR sequence. */\nexport const CSI = `${ESC}[`\n\n/** Holds the full SGR reset sequence (`ESC[0m`) appended after a styled run. */\nexport const RESET = `${CSI}${RESET_CODE}m`\n\n/**\n * Matches any ANSI/VT escape sequence — CSI (SGR color/style plus cursor/erase/scroll,\n * including colon-parameterized SGR), OSC / DCS / PM / APC / SOS string sequences\n * (titles, hyperlinks, device strings), the `nF` charset-select family, and the\n * two-byte `Fp` / `Fe` / `Fs` sequences (for example `ESC 7`, `ESC D`, `ESC c` RIS). Global, so\n * `strip` removes every occurrence.\n *\n * @remarks\n * A global `RegExp` carries a mutable `lastIndex`; a scan must build a fresh `RegExp`\n * from this one's `source` + `flags` rather than reuse this instance's `lastIndex`. This\n * is the canonical definition, not a shared scanner. The alternation is ordered so the\n * CSI / string-family arms (which can start with a byte a later single-byte arm would\n * also match) win first; every arm uses disjoint, non-nested character classes, so the\n * match is linear in input length — no catastrophic backtracking (ReDoS-safe) even on an\n * adversarial run of digits inside an unterminated CSI. Built from `String.fromCharCode`\n * so no control-character literal appears in a regex source (the codebase idiom).\n */\nexport const ANSI_PATTERN = new RegExp(\n\t`${ESC}(?:` +\n\t\t`\\\\[[0-?]*[ -/]*[@-~]` +\n\t\t`|\\\\][^${BEL}${ESC}]*(?:${BEL}|${ESC}\\\\\\\\)` +\n\t\t`|[P^_X][^${BEL}${ESC}]*(?:${BEL}|${ESC}\\\\\\\\)` +\n\t\t`|[ -/]+[0-~]` +\n\t\t`|[0-?]` +\n\t\t`|[@-OQ-WYZ\\\\\\\\]` +\n\t\t`|[\\`-~]` +\n\t\t`)`,\n\t'g',\n)\n\n/**\n * Matches every C0 control character except `\\t` / `\\n` / `\\r` (which are meaningful\n * whitespace), plus DEL (`0x7F`) — the non-printing bytes {@link\n * import('./helpers.js').stripControls} removes. Global, ASCII-only source (no raw\n * control-character literal), so a scan builds a fresh `RegExp` the same way as\n * {@link ANSI_PATTERN} to avoid a mutated `lastIndex`.\n *\n * @remarks\n * Deliberately separate from {@link ANSI_PATTERN}: `strip()` must stay pure ANSI-escape\n * removal (width / alignment computations depend on it leaving raw C0 bytes alone), while\n * C0-stripping is an additional, orthogonal pass a non-TTY output sink applies on top.\n */\nexport const CONTROL_PATTERN = new RegExp(\n\t`[${String.fromCharCode(0)}-${String.fromCharCode(8)}${String.fromCharCode(11)}${String.fromCharCode(12)}${String.fromCharCode(14)}-${String.fromCharCode(31)}${String.fromCharCode(127)}]`,\n\t'g',\n)\n\n// Structured-logging constants — the severity order the level gate compares through, the\n// default colors a level renders in (styling is orthogonal to level — a level → color map,\n// not a level), and the default bounded-retention cap. UPPER_SNAKE, `Object.freeze`d, every\n// member exported.\n\n/**\n * Maps each {@link LogLevel} to its numeric severity — the ascending order the level gate compares\n * through (`debug` 0 < `info` 1 < `warn` 2 < `error` 3). A record is kept when its level's\n * severity is at or above the logger's threshold. The source of truth for level ordering.\n */\nexport const LEVEL_SEVERITY: Readonly<Record<LogLevel, number>> = Object.freeze({\n\tdebug: 0,\n\tinfo: 1,\n\twarn: 2,\n\terror: 3,\n})\n\n/**\n * Maps each {@link LogLevel} to its default label {@link Color} — the level's visual treatment, which\n * is a styling choice orthogonal to the level itself (never a separate pseudo-level). The\n * logger colors the level label through its styler with these; swapping a color never\n * changes leveling. `debug` is cyan, `info` blue, `warn` yellow, `error` red.\n *\n * @remarks\n * Excludes `default` so each value indexes a real styler accessor (the styler exposes a\n * getter per non-`default` {@link Color}) — a level always renders in a concrete color.\n */\nexport const LEVEL_COLORS: Readonly<Record<LogLevel, Exclude<Color, 'default'>>> = Object.freeze({\n\tdebug: 'cyan',\n\tinfo: 'blue',\n\twarn: 'yellow',\n\terror: 'red',\n})\n\n/**\n * Sets the default bounded-retention cap for a {@link import('./types.js').LoggerInterface} —\n * `1000`, so at most that many recent records are kept and retention is always bounded.\n *\n * @remarks\n * The oldest record is dropped after the cap is reached; a consumer overrides the cap through\n * `options.limit`.\n */\nexport const DEFAULT_LOG_LIMIT = 1000\n\n/** Sets the default {@link LogLevel} threshold a logger gates at when none is supplied — `info`. */\nexport const DEFAULT_LOG_LEVEL: LogLevel = 'info'\n\n/**\n * Lists every {@link LogLevel}, in ascending severity order — the levels a logger exposes as\n * methods and the manager fans out to. The source of truth for the level axis (drives\n * exhaustive tests); aligned with {@link LEVEL_SEVERITY}.\n */\nexport const LOG_LEVELS: readonly LogLevel[] = Object.freeze(['debug', 'info', 'warn', 'error'])\n\n// Narrative-rendering constants — the box-drawing junction sets the renderers frame with, the\n// status icons + colors a `Reporter.status` outcome shows, the tree connectors, and the default\n// widths / paddings / glyphs. UPPER_SNAKE, deeply `Object.freeze`d data, every member exported.\n// The box-drawing glyphs are the standard Unicode set (U+2500 block) — a fixed\n// external spec, so the literals are the source of truth.\n\n/**\n * Holds the complete {@link BorderChars} junction set for each {@link BorderStyle} — the standard\n * Unicode box-drawing glyphs at each line weight, deeply frozen.\n *\n * @remarks\n * The renderers ({@link import('./helpers.js').renderBox} /\n * {@link import('./helpers.js').renderTable}) look the style up here, so no glyph literal lives in\n * a renderer.\n *\n * @remarks\n * `round` shares `single`'s edges and tees — only its corners differ (the rounded `╭╮╰╯`).\n */\nexport const BORDER_CHARS: Readonly<Record<BorderStyle, BorderChars>> = Object.freeze({\n\tsingle: Object.freeze({\n\t\thorizontal: '─',\n\t\tvertical: '│',\n\t\ttopLeft: '┌',\n\t\ttopRight: '┐',\n\t\tbottomLeft: '└',\n\t\tbottomRight: '┘',\n\t\tcross: '┼',\n\t\tteeDown: '┬',\n\t\tteeUp: '┴',\n\t\tteeRight: '├',\n\t\tteeLeft: '┤',\n\t}),\n\tdouble: Object.freeze({\n\t\thorizontal: '═',\n\t\tvertical: '║',\n\t\ttopLeft: '╔',\n\t\ttopRight: '╗',\n\t\tbottomLeft: '╚',\n\t\tbottomRight: '╝',\n\t\tcross: '╬',\n\t\tteeDown: '╦',\n\t\tteeUp: '╩',\n\t\tteeRight: '╠',\n\t\tteeLeft: '╣',\n\t}),\n\tround: Object.freeze({\n\t\thorizontal: '─',\n\t\tvertical: '│',\n\t\ttopLeft: '╭',\n\t\ttopRight: '╮',\n\t\tbottomLeft: '╰',\n\t\tbottomRight: '╯',\n\t\tcross: '┼',\n\t\tteeDown: '┬',\n\t\tteeUp: '┴',\n\t\tteeRight: '├',\n\t\tteeLeft: '┤',\n\t}),\n\theavy: Object.freeze({\n\t\thorizontal: '━',\n\t\tvertical: '┃',\n\t\ttopLeft: '┏',\n\t\ttopRight: '┓',\n\t\tbottomLeft: '┗',\n\t\tbottomRight: '┛',\n\t\tcross: '╋',\n\t\tteeDown: '┳',\n\t\tteeUp: '┻',\n\t\tteeRight: '┣',\n\t\tteeLeft: '┫',\n\t}),\n})\n\n/**\n * Maps each {@link StatusLevel} to its icon glyph — the leading mark a {@link\n * import('./types.js').ReporterInterface.status} outcome line shows: `success` ✔, `error` ✖,\n * `warn` ⚠, `info` ℹ. The narrative-outcome counterpart to a log level's label; frozen.\n */\nexport const STATUS_ICONS: Readonly<Record<StatusLevel, string>> = Object.freeze({\n\tsuccess: '✔',\n\terror: '✖',\n\twarn: '⚠',\n\tinfo: 'ℹ',\n})\n\n/**\n * Maps each {@link StatusLevel} to its {@link Color} — the icon + message color a `status` line renders\n * in (`success` green, `error` red, `warn` yellow, `info` blue). The visual treatment of a\n * narrative outcome, colored through the reporter's styler; orthogonal to leveling, like\n * {@link LEVEL_COLORS}. Excludes `default` so each value indexes a real styler accessor.\n */\nexport const STATUS_COLORS: Readonly<Record<StatusLevel, Exclude<Color, 'default'>>> =\n\tObject.freeze({\n\t\tsuccess: 'green',\n\t\terror: 'red',\n\t\twarn: 'yellow',\n\t\tinfo: 'blue',\n\t})\n\n/**\n * Lists every {@link StatusLevel}, frozen — the outcomes a `status` line supports (drives exhaustive\n * tests). The source of truth for the status axis; aligned with {@link STATUS_ICONS} /\n * {@link STATUS_COLORS}.\n */\nexport const STATUS_LEVELS: readonly StatusLevel[] = Object.freeze([\n\t'success',\n\t'error',\n\t'warn',\n\t'info',\n])\n\n/**\n * Sets the default visible column width for the width-aware renderers — the separator rule and a\n * {@link import('./helpers.js').renderBox} with no explicit `width`, and the reporter's\n * `section` rule. A sane terminal default (80 columns); a caller overrides it per-call or through\n * {@link import('./types.js').ReporterOptions.width}.\n */\nexport const DEFAULT_WIDTH = 80\n\n/** Sets the default horizontal padding inside a box's edges ({@link import('./helpers.js').renderBox}) — one cell. */\nexport const DEFAULT_PADDING = 1\n\n/** Sets the default {@link BorderStyle} the box / table renderers frame with when none is given — `single`. */\nexport const DEFAULT_BORDER: BorderStyle = 'single'\n\n/** Sets the default cell {@link Alignment} a {@link import('./types.js').ColumnSpec} uses when none is given — `left`. */\nexport const DEFAULT_ALIGN: Alignment = 'left'\n\n/** Holds the default fill character {@link import('./helpers.js').renderSeparator} draws its rule with — `─`. */\nexport const SEPARATOR_FILL = '─'\n\n/**\n * Holds the single padding cell on each side of a separator's embedded title (` title `) — keeps the\n * title from butting against the rule. One space.\n */\nexport const SEPARATOR_TITLE_GAP = ' '\n\n/**\n * Sets the millisecond threshold at or above which {@link import('./helpers.js').formatDuration}\n * (and so `Reporter.timing`) switches from a `…ms` rendering to a `…s` (seconds, 2 d.p.) rendering\n * — `1000`, exactly one second.\n */\nexport const SECOND_MS = 1000\n\n// Console-interception constants — the default set of `console.*` methods a Capture patches, the\n// default bounded-buffer cap, and the CaptureLevel → LogLevel projection the optional sink forward\n// routes through. UPPER_SNAKE, `Object.freeze`d, every member exported. The five level\n// names are the universal `console.*` method names — a fixed external surface, so the literals are\n// the source of truth.\n\n/**\n * Lists every {@link CaptureLevel}, frozen — the `console.*` methods a {@link\n * import('./types.js').CaptureInterface} intercepts by default (and the source of truth for the\n * capture-level axis; drives exhaustive tests). The universal console methods: `log`, `info`,\n * `warn`, `error`, `debug`.\n */\nexport const CAPTURE_LEVELS: readonly CaptureLevel[] = Object.freeze([\n\t'log',\n\t'info',\n\t'warn',\n\t'error',\n\t'debug',\n])\n\n/**\n * Sets the default bounded-buffer cap for a {@link import('./types.js').CaptureInterface} — `1000`,\n * so at most that many recent {@link CapturedMessage}s are retained per buffer (the total buffer\n * and each by-level bucket; oldest dropped first) and retention is always bounded.\n *\n * @remarks\n * A long-running capture can never grow without bound (the same retention precedent as\n * {@link DEFAULT_LOG_LIMIT}); a consumer overrides the cap through `options.limit`.\n */\nexport const DEFAULT_CAPTURE_LIMIT = 1000\n\n/**\n * Maps each {@link CaptureLevel} to its {@link LogLevel} for the optional sink forward — the projection the\n * Capture routes through when writing an intercepted call to a {@link\n * import('./types.js').SinkInterface}. `sink.write(text, CAPTURE_LEVEL_MAP[level])` is the call\n * this map backs. `warn` /\n * `error` / `debug` / `info` map to their matching {@link LogLevel}; `log` maps to `info` (a plain\n * console log is informational — the default stream), so a stream-aware sink routes `warn` / `error`\n * captures to the right stream. The source of truth for the capture-to-log projection.\n */\nexport const CAPTURE_LEVEL_MAP: Readonly<Record<CaptureLevel, LogLevel>> = Object.freeze({\n\tlog: 'info',\n\tinfo: 'info',\n\twarn: 'warn',\n\terror: 'error',\n\tdebug: 'debug',\n})\n\n// Live-animation constants — the spinner's glyph frame set + default timer period, and the\n// determinate bar's fill / empty glyphs + default track width. UPPER_SNAKE, `Object.freeze`d, every\n// member exported. The braille spinner frames + the block bar glyphs are the standard\n// Unicode sets (the braille-patterns block U+2800 / the block-elements `█` U+2588 / `░` U+2591) — a\n// fixed external glyph spec, so the literals are the source of truth. There is one frame set and\n// one bar glyph pair; a caller overrides either through options rather than declaring a second.\n\n/**\n * Holds the default spinner frame cycle a {@link import('./types.js').SpinnerInterface} advances\n * through — the braille-pattern glyphs (`⠋⠙⠹…`, the U+2800 block) that read as a smoothly rotating\n * dot.\n *\n * @remarks\n * The cycle is the universal terminal-spinner convention. Frozen; a consumer swaps the whole\n * cycle through `options.frames`.\n *\n * Braille glyphs are single visible cells, so every frame occupies one column — the spinner glyph\n * never shifts the message beside it as it advances. The source of truth for the default frame axis.\n */\nexport const SPINNER_FRAMES: readonly string[] = Object.freeze([\n\t'⠋',\n\t'⠙',\n\t'⠹',\n\t'⠸',\n\t'⠼',\n\t'⠴',\n\t'⠦',\n\t'⠧',\n\t'⠇',\n\t'⠏',\n])\n\n/**\n * Sets the default timer period between a {@link import('./types.js').SpinnerInterface}'s frames —\n * the `setInterval` interval `start()` arms, `80` ms (≈12.5 frames/second).\n *\n * @remarks\n * That is the conventional spinner cadence: fast enough to read as motion, slow enough not to\n * thrash a terminal. A consumer overrides it through `options.interval`.\n */\nexport const DEFAULT_SPINNER_INTERVAL = 80\n\n/**\n * Holds the default filled-cell glyph {@link import('./helpers.js').renderBar} draws the completed\n * run of a progress bar with — the full block `█` (U+2588). A single visible cell; a consumer\n * overrides it through {@link import('./types.js').BarOptions.fill}.\n */\nexport const BAR_FILL = '█'\n\n/**\n * Holds the default empty-cell glyph {@link import('./helpers.js').renderBar} draws the remaining\n * run of a progress bar with — the light-shade block `░` (U+2591). A single visible cell; a\n * consumer overrides it through {@link import('./types.js').BarOptions.empty}.\n */\nexport const BAR_EMPTY = '░'\n\n/**\n * Sets the default visible cell count of a progress-bar track — the glyph run\n * {@link import('./helpers.js').renderBar} fills, and the width a\n * {@link import('./types.js').ProgressInterface} sizes its bar to. `30` cells.\n *\n * @remarks\n * Thirty cells is a compact, terminal-friendly default; a consumer overrides it through\n * `options.width`. It is distinct from {@link DEFAULT_WIDTH} (the renderers' 80-column line\n * width) — a bar track is one inline element, not a full-width rule.\n */\nexport const DEFAULT_BAR_WIDTH = 30\n\n// The default theme — the semantic style vocabulary every entity speaks unless a consumer\n// supplies its own. Assembled from the constants above (LEVEL_COLORS / STATUS_ICONS /\n// STATUS_COLORS), never restating them: a level's color, a status's icon + color each keep\n// one source, and the theme is the shape that binds them to a role. UPPER_SNAKE, deeply\n// `Object.freeze`d data.\n\n/**\n * Holds the default {@link Theme} — every role bound to its default {@link Style}, assembled from\n * {@link LEVEL_COLORS}, {@link STATUS_ICONS}, and {@link STATUS_COLORS} and deeply frozen.\n *\n * @remarks\n * It is the base {@link import('./factories.js').createTheme} merges over, and the theme every\n * entity uses when none is supplied.\n *\n * @remarks\n * - `levels` — each {@link LogLevel} label in its {@link LEVEL_COLORS} color, no attributes.\n * - `statuses` — each {@link StatusLevel}'s {@link STATUS_ICONS} glyph in its\n * {@link STATUS_COLORS} color.\n * - `accent` — `cyan`: the spinner glyph, the progress fill, a step prefix.\n * - `chrome` — `dim`: separators, box / table / tree frames, and a log line's timestamp /\n * name / data surround. A color-free attribute, so chrome recedes on any background.\n */\nexport const DEFAULT_THEME: Theme = Object.freeze({\n\tlevels: Object.freeze({\n\t\tdebug: Object.freeze({ foreground: LEVEL_COLORS.debug, attributes: EMPTY_STYLE.attributes }),\n\t\tinfo: Object.freeze({ foreground: LEVEL_COLORS.info, attributes: EMPTY_STYLE.attributes }),\n\t\twarn: Object.freeze({ foreground: LEVEL_COLORS.warn, attributes: EMPTY_STYLE.attributes }),\n\t\terror: Object.freeze({ foreground: LEVEL_COLORS.error, attributes: EMPTY_STYLE.attributes }),\n\t}),\n\tstatuses: Object.freeze({\n\t\tsuccess: Object.freeze({\n\t\t\ticon: STATUS_ICONS.success,\n\t\t\tstyle: Object.freeze({\n\t\t\t\tforeground: STATUS_COLORS.success,\n\t\t\t\tattributes: EMPTY_STYLE.attributes,\n\t\t\t}),\n\t\t}),\n\t\terror: Object.freeze({\n\t\t\ticon: STATUS_ICONS.error,\n\t\t\tstyle: Object.freeze({ foreground: STATUS_COLORS.error, attributes: EMPTY_STYLE.attributes }),\n\t\t}),\n\t\twarn: Object.freeze({\n\t\t\ticon: STATUS_ICONS.warn,\n\t\t\tstyle: Object.freeze({ foreground: STATUS_COLORS.warn, attributes: EMPTY_STYLE.attributes }),\n\t\t}),\n\t\tinfo: Object.freeze({\n\t\t\ticon: STATUS_ICONS.info,\n\t\t\tstyle: Object.freeze({ foreground: STATUS_COLORS.info, attributes: EMPTY_STYLE.attributes }),\n\t\t}),\n\t}),\n\taccent: Object.freeze({ foreground: 'cyan', attributes: EMPTY_STYLE.attributes }),\n\tchrome: Object.freeze({ attributes: Object.freeze<readonly Attribute[]>(['dim']) }),\n})\n","import type { ConsoleErrorCode } from './types.js'\nimport { isInstance } from '@orkestrel/contract'\n\n// An internal invariant / unreachable-guard violation `throw`s, always a\n// `ConsoleError` carrying a machine-readable `code` so a `catch` branches on\n// `error.code` instead of parsing the message.\n\n/**\n * Carries a {@link ConsoleErrorCode} and an optional `context` bag — the error the console layer\n * throws for an internal invariant violated at a defensive guard.\n *\n * @remarks\n * `INVARIANT` is the code for a guard that is structurally unreachable, so a `catch` branches on\n * `error.code` rather than parsing the message.\n */\nexport class ConsoleError extends Error {\n\treadonly code: ConsoleErrorCode\n\treadonly context?: Readonly<Record<string, unknown>>\n\n\tconstructor(\n\t\tcode: ConsoleErrorCode,\n\t\tmessage: string,\n\t\tcontext?: Readonly<Record<string, unknown>>,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'ConsoleError'\n\t\tthis.code = code\n\t\tif (context !== undefined) this.context = context\n\t}\n}\n\n/**\n * Narrows an unknown caught value to a {@link ConsoleError} — the guard a `catch` branches on.\n *\n * @param value - The value to test (typically a `catch` binding)\n * @returns True if `value` is a {@link ConsoleError}; false otherwise\n *\n * @example\n * ```ts\n * try {\n * \tcreateStyler().style\n * } catch (error) {\n * \tif (isConsoleError(error) && error.code === 'INVARIANT') report(error)\n * }\n * ```\n */\nexport function isConsoleError(value: unknown): value is ConsoleError {\n\treturn isInstance(value, ConsoleError)\n}\n","import type {\n\tAlignment,\n\tBarOptions,\n\tBoxOptions,\n\tLogLevel,\n\tLogRecord,\n\tSeparatorOptions,\n\tStyle,\n\tStylerInterface,\n\tTableOptions,\n\tTreeNode,\n\tTreeOptions,\n\tTheme,\n\tWriterSet,\n} from './types.js'\nimport { isError, isObject } from '@orkestrel/contract'\nimport {\n\tANSI_PATTERN,\n\tBAR_EMPTY,\n\tBAR_FILL,\n\tBORDER_CHARS,\n\tCONTROL_PATTERN,\n\tDEFAULT_ALIGN,\n\tDEFAULT_BAR_WIDTH,\n\tDEFAULT_BORDER,\n\tDEFAULT_PADDING,\n\tDEFAULT_WIDTH,\n\tLEVEL_SEVERITY,\n\tSECOND_MS,\n\tSEPARATOR_FILL,\n\tSEPARATOR_TITLE_GAP,\n} from './constants.js'\n\n// Pure, universal string helpers for the console / terminal system. `strip` removes\n// ANSI escapes; `width` is the visible length (strip then count). Both are needed later\n// by the box / table / progress layout — kept here, environment-agnostic, so every\n// surface shares one implementation. Every function exported.\n// The logging helpers (`meetsLevel`, `formatTime`, `formatRecord`) are likewise pure and\n// shared — the level gate's comparison and the styled-line layout, kept off the impl class.\n\n/**\n * Removes every ANSI escape sequence from `text`, returning the plain visible string.\n *\n * @remarks\n * Strips SGR color/style codes and other CSI controls (cursor, erase) plus OSC\n * sequences (titles, hyperlinks) — see {@link ANSI_PATTERN}. A fresh `RegExp` is built\n * per call from the canonical pattern's `source` + `flags`, so the shared global\n * pattern's `lastIndex` is never mutated across calls (re-entrant and deterministic).\n *\n * @param text - Any string, styled or plain\n * @returns `text` with all ANSI escapes removed\n *\n * @example\n * ```ts\n * strip('\\x1b[31mred\\x1b[0m') // 'red'\n * ```\n */\nexport function strip(text: string): string {\n\treturn text.replace(new RegExp(ANSI_PATTERN.source, ANSI_PATTERN.flags), '')\n}\n\n/**\n * Removes every non-printing C0 control character from `text` except `\\t` / `\\n` / `\\r`\n * (meaningful whitespace), plus DEL — a separate pass from {@link strip}, so `width` stays\n * untouched.\n *\n * @remarks\n * Deliberately separate from {@link strip} (ANSI-escape removal only, so `width` /\n * `align` stay untouched) — this is the additional pass a non-TTY output sink applies\n * on top of `strip`, so a captured `\\x07` bell or stray `\\x00` never reaches a log file\n * / non-terminal target. A fresh `RegExp` is built per call from {@link CONTROL_PATTERN}'s\n * `source` + `flags`, the same re-entrant idiom as `strip`.\n *\n * @param text - Any string, possibly carrying raw control bytes\n * @returns `text` with C0 controls (other than tab/newline/CR) and DEL removed\n *\n * @example\n * ```ts\n * stripControls('a\\x07b\\nc') // 'ab\\nc'\n * ```\n */\nexport function stripControls(text: string): string {\n\treturn text.replace(new RegExp(CONTROL_PATTERN.source, CONTROL_PATTERN.flags), '')\n}\n\n/**\n * Measures how many visible columns `text` occupies — its length after ANSI escapes are stripped, counted in\n * Unicode code points (so an astral character such as an emoji counts as one, not the\n * two UTF-16 units `String.length` would report).\n *\n * @remarks\n * The basis for terminal layout (box / table / progress alignment): the column count a\n * styled string occupies, independent of its escape codes. It does not account for\n * wide (CJK / fullwidth) glyphs occupying two cells — a deliberate, documented\n * simplification at this layer; callers needing east-asian width handle it above.\n *\n * @param text - Any string, styled or plain\n * @returns The count of visible code points\n *\n * @example\n * ```ts\n * width('\\x1b[1mhi\\x1b[0m') // 2\n * ```\n */\nexport function width(text: string): number {\n\treturn [...strip(text)].length\n}\n\n/**\n * Snapshots and deeply freezes one {@link Style} value, including an independent frozen copy of\n * its `attributes`.\n *\n * @param style - The caller-owned style to snapshot\n * @returns A frozen style record with an independently frozen attributes list\n *\n * @remarks\n * The record spread captures accessor values once and preserves each present color channel.\n * Copying `attributes` prevents later mutation of a caller-owned list from changing the result.\n *\n * @example\n * ```ts\n * freezeStyle({ foreground: 'red', attributes: ['bold'] })\n * ```\n */\nexport function freezeStyle(style: Style): Style {\n\treturn Object.freeze({ ...style, attributes: Object.freeze([...style.attributes]) })\n}\n\n/**\n * Checks whether a record at `level` passes a logger gated at `threshold` — that is, its severity\n * is at or above the threshold's.\n *\n * @remarks\n * The level gate (the comparison lives here, not inlined in the logger). Reads\n * the ascending {@link LEVEL_SEVERITY} order: `meetsLevel('warn', 'error')` is `true`\n * (error ≥ warn), `meetsLevel('warn', 'info')` is `false` (info < warn).\n *\n * @param threshold - The logger's configured minimum {@link LogLevel}\n * @param level - The record's {@link LogLevel}\n * @returns True if `level` is at least as severe as `threshold`; false otherwise\n *\n * @example\n * ```ts\n * meetsLevel('info', 'error') // true\n * meetsLevel('error', 'warn') // false\n * ```\n */\nexport function meetsLevel(threshold: LogLevel, level: LogLevel): boolean {\n\treturn LEVEL_SEVERITY[level] >= LEVEL_SEVERITY[threshold]\n}\n\n/**\n * Selects the member of a {@link WriterSet} a {@link LogLevel} routes to — `error` to `error`,\n * `warn` to `warn`, every other level and an omitted level to `log`.\n *\n * @remarks\n * The single owner of the level-to-target decision every sink backend shares, so core's console\n * sink, the browser `%c` sink, and the server stream sink cannot drift apart. A backend that sends\n * two levels to one destination passes the same member twice: the server sink routes `warn`\n * alongside `error` by supplying its error stream for both, which matches `console.warn` writing\n * to `stderr`. The member type is the caller's, so the same leaf selects a bound console method, a\n * stream target, or a per-target styling fact.\n *\n * @param level - The originating record's {@link LogLevel}, or `undefined` when the caller has none\n * @param writers - See {@link WriterSet}\n * @returns The member `level` routes to\n *\n * @example\n * ```ts\n * selectWriter('error', { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stderr'\n * selectWriter('warn', { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stderr'\n * selectWriter('debug', { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stdout'\n * selectWriter(undefined, { log: 'stdout', warn: 'stderr', error: 'stderr' }) // 'stdout'\n * ```\n */\nexport function selectWriter<T>(level: LogLevel | undefined, writers: WriterSet<T>): T {\n\tif (level === 'error') return writers.error\n\tif (level === 'warn') return writers.warn\n\treturn writers.log\n}\n\n/**\n * Formats a {@link LogRecord}'s `time` (epoch milliseconds) as an ISO-8601 timestamp string.\n *\n * @remarks\n * Deterministic and serializable — `new Date(time).toISOString()`, for example\n * `1716900000000 → '2024-05-28T12:40:00.000Z'`. The timestamp portion of the formatted log\n * line; kept a pure helper so the line layout and the logger stay decoupled.\n *\n * @param time - Epoch milliseconds (a record's `time`)\n * @returns The ISO-8601 timestamp\n */\nexport function formatTime(time: number): string {\n\treturn new Date(time).toISOString()\n}\n\n/**\n * Formats a {@link LogRecord} into a single styled line — the default human line layout a\n * {@link import('./types.js').LoggerInterface} writes to its sink.\n *\n * @remarks\n * Layout: `{time} {LEVEL} {[name]} {message}{ data}` — the ISO timestamp (dimmed), the\n * upper-cased level label (rendered through the theme's level role),\n * the originating logger's `name` in brackets (omitted when absent), the message, and the\n * structured `data` appended as compact JSON (omitted when absent / empty). Coloring flows\n * through the injected `styler`, so a disabled styler yields a plain line and a browser\n * `%c` styler retargets it — the layout never changes. Pure: same record + styler →\n * same line.\n *\n * @param record - The {@link LogRecord} to render\n * @param styler - The {@link StylerInterface} the labels are colored through\n * @param theme - The {@link Theme} supplying the level and chrome roles\n * @returns The formatted, styled line (no trailing newline — the sink's target adds it)\n *\n * @example\n * ```ts\n * formatRecord(\n * \t{ level: 'warn', message: 'low disk', time: 0, name: 'fs' },\n * \tcreateStyler(),\n * \tDEFAULT_THEME,\n * )\n * // '<dim>1970-01-01T00:00:00.000Z</> <yellow>WARN</> [fs] low disk'\n * ```\n */\nexport function formatRecord(record: LogRecord, styler: StylerInterface, theme: Theme): string {\n\tconst time = styler.render(theme.chrome, formatTime(record.time))\n\tconst label = styler.render(theme.levels[record.level], record.level.toUpperCase())\n\tconst name =\n\t\trecord.name === undefined ? '' : ` ${styler.render(theme.chrome, `[${record.name}]`)}`\n\tconst data =\n\t\trecord.data === undefined || Object.keys(record.data).length === 0\n\t\t\t? ''\n\t\t\t: ` ${styler.render(theme.chrome, JSON.stringify(record.data))}`\n\treturn `${time} ${label}${name} ${record.message}${data}`\n}\n\n/**\n * Pads (or, when over budget, truncates) `text` to exactly `columns` visible columns, positioning\n * it by `alignment`. The width primitive the box / table renderers align every cell with.\n *\n * @remarks\n * Measures with {@link width} (visible code points, ANSI-aware), so a styled string aligns by\n * its visible content, not its escape codes. When `width(text) < columns`, the deficit is added\n * as spaces — all trailing (`left`), all leading (`right`), or split with the extra space on\n * the right (`center`). When `width(text) > columns`, the visible characters are sliced to\n * `columns` (a defensive guard — the renderers size columns to fit, so this is rarely hit; it\n * slices the stripped text, so it never bisects an escape sequence into a broken half).\n *\n * @param text - The cell content (may be styled)\n * @param columns - The visible column count to fit `text` into\n * @param alignment - Where to position `text` within that budget; defaults to `left`\n * @returns `text` fitted to exactly `columns` visible columns\n *\n * @example\n * ```ts\n * align('hi', 5) // 'hi '\n * align('hi', 5, 'right') // ' hi'\n * align('hi', 5, 'center') // ' hi '\n * ```\n */\nexport function align(text: string, columns: number, alignment: Alignment = DEFAULT_ALIGN): string {\n\tconst visible = width(text)\n\tif (visible > columns) return [...strip(text)].slice(0, columns).join('')\n\tconst deficit = columns - visible\n\tif (alignment === 'right') return `${' '.repeat(deficit)}${text}`\n\tif (alignment === 'center') {\n\t\tconst left = Math.floor(deficit / 2)\n\t\treturn `${' '.repeat(left)}${text}${' '.repeat(deficit - left)}`\n\t}\n\treturn `${text}${' '.repeat(deficit)}`\n}\n\n/**\n * Formats a millisecond duration as a compact human string — `…ms` below one second, `…s`\n * (seconds to 2 decimal places) at or above one second. The timing rendering behind\n * {@link import('./types.js').ReporterInterface.timing}.\n *\n * @remarks\n * `999 → '999ms'`, `1000 → '1.00s'`, `1230 → '1.23s'` (the threshold is {@link SECOND_MS}).\n * Pure and deterministic; kept a shared helper so the layout and the reporter stay decoupled.\n *\n * @param ms - The duration in milliseconds\n * @returns The formatted duration (`'<n>ms'` or `'<n>s'`)\n */\nexport function formatDuration(ms: number): string {\n\treturn ms < SECOND_MS ? `${ms}ms` : `${(ms / SECOND_MS).toFixed(2)}s`\n}\n\n/**\n * Colors `text` through `styler` and an optional by-value {@link Style}, or returns it verbatim\n * when `styler` is `undefined` — the single optional-styling primitive every renderer applies to\n * its border / title / connector glyphs.\n *\n * @remarks\n * The renderers all take an optional `styler`: present ⇒ glyphs are colored, absent ⇒ plain.\n * Folding that `styler === undefined ? text : styler(text)` ternary into one exported helper\n * keeps the renderers terse and the styling decision in one tested place. A disabled styler\n * (`enabled: false`) is still a styler — it returns its text verbatim — so passing one paints\n * a no-op, exactly as omitting it does.\n *\n * @param styler - The {@link StylerInterface} to color with, or `undefined` for no styling\n * @param text - The glyphs / text to color\n * @param style - An optional {@link Style} to render by value instead of the styler's chain\n * @returns `styler(text)` when a styler is given, else `text` unchanged\n */\nexport function paint(styler: StylerInterface | undefined, text: string, style?: Style): string {\n\tif (styler === undefined) return text\n\treturn style === undefined ? styler(text) : styler.render(style, text)\n}\n\n/**\n * Repeats `unit` until it fills exactly `columns` visible columns, trimming a trailing partial\n * unit so the run is never over-wide — the fill primitive the separator + box edges draw with.\n *\n * @remarks\n * Counts in code points ({@link width}-consistent), so a multi-cell or astral `unit` is laid\n * down whole and the result is sliced to exactly `columns` visible columns. `columns <= 0` (or an\n * empty / zero-width `unit`) yields `''`.\n *\n * @param unit - The (possibly multi-character) fill unit\n * @param columns - The visible column count to fill\n * @returns `unit` tiled to exactly `columns` visible columns\n *\n * @example\n * ```ts\n * repeatTo('─', 4) // '────'\n * repeatTo('=-', 5) // '=-=-='\n * ```\n */\nexport function repeatTo(unit: string, columns: number): string {\n\tif (columns <= 0) return ''\n\tconst per = width(unit)\n\tif (per === 0) return ''\n\tconst built = unit.repeat(Math.ceil(columns / per))\n\treturn [...built].slice(0, columns).join('')\n}\n\n/**\n * Returns the cell at `index` of a (possibly ragged) row — `''` when the row is shorter than the\n * column count, so a short row pads out instead of throwing (the ragged-row guard\n * {@link renderTable} reads every cell through).\n *\n * @param row - The row's cells\n * @param index - The column index to read\n * @returns The cell text, or `''` when the row has no cell at `index`\n */\nexport function cellAt(row: readonly string[], index: number): string {\n\treturn row[index] ?? ''\n}\n\n/**\n * Renders a horizontal rule — an optional centered title embedded in a line of fill characters,\n * to a fixed visible width. Pure: same {@link SeparatorOptions} → same string.\n *\n * @remarks\n * - **Plain rule.** With no `title`, returns `fill` repeated to `width` visible columns.\n * - **Titled rule.** With a `title`, centers ` title ` (one {@link SEPARATOR_TITLE_GAP} each\n * side) in the line, splitting the remaining fill between the two sides (the extra column,\n * when the remainder is odd, goes to the right). The visible width stays exactly `width`,\n * even when the title is styled (the title's escape codes don't count toward the budget) —\n * a title at least as wide as `width` yields only the gapped title (no fill).\n * - **Styling.** When `options.styler` is given, the fill runs (and the embedded title) are\n * colored through it; the layout is identical with or without color, since width is measured\n * on the visible content (width-aware through {@link width}).\n *\n * @param options - See {@link SeparatorOptions}\n * @returns The rule line (no trailing newline)\n *\n * @example\n * ```ts\n * renderSeparator({ width: 10 }) // '──────────'\n * renderSeparator({ title: 'Build', width: 13 }) // '── Build ──' (centered)\n * ```\n */\nexport function renderSeparator(options: SeparatorOptions): string {\n\tconst total = options.width ?? DEFAULT_WIDTH\n\tconst fill = options.fill ?? SEPARATOR_FILL\n\tif (options.title === undefined)\n\t\treturn paint(options.styler, repeatTo(fill, total), options.style)\n\tconst gapped = `${SEPARATOR_TITLE_GAP}${paint(options.styler, options.title, options.style)}${SEPARATOR_TITLE_GAP}`\n\tconst room = total - width(options.title) - SEPARATOR_TITLE_GAP.length * 2\n\tif (room <= 0) return gapped\n\tconst left = Math.floor(room / 2)\n\treturn `${paint(options.styler, repeatTo(fill, left), options.style)}${gapped}${paint(options.styler, repeatTo(fill, room - left), options.style)}`\n}\n\n/**\n * Renders `content` framed in box-drawing characters, optionally captioned, width-aware so\n * styled content stays aligned inside the frame. Pure: same {@link BoxOptions} → same string.\n *\n * @remarks\n * - **Lines.** `content` is split on `\\n` or `\\r\\n`, so caller text written on Windows frames\n * exactly as the same text written on POSIX; a lone `\\r` is kept inside its line (it is a\n * cursor control — the animation frame prefix — not a line separator). Each line is padded\n * (left-aligned) to the inner\n * width by {@link align} — measured on visible width, so a styled line never breaks the\n * right edge. The inner width is the widest line's visible width (or `width − borders −\n * 2·padding` when an explicit `width` is given and is wider), plus `padding` blank cells\n * inside each {@link BorderChars.vertical} edge.\n * - **Title.** An optional `title` is embedded in the top border (` title `), the remaining\n * top edge drawn as fill; a title wider than the inner width widens the box to fit it.\n * - **Border + styling.** The {@link BorderStyle} (`options.border`, default\n * {@link DEFAULT_BORDER}) selects the glyph set from {@link BORDER_CHARS}; `options.styler`\n * colors the frame + title when given (content cells are written as supplied).\n * - **Multi-line result.** Returns the box as `\\n`-joined rows (top, one row per content line,\n * bottom) with no trailing newline.\n *\n * @param options - See {@link BoxOptions}\n * @returns The framed box (multiple lines joined by `\\n`)\n */\nexport function renderBox(options: BoxOptions): string {\n\tconst chars = BORDER_CHARS[options.border ?? DEFAULT_BORDER]\n\tconst padding = Math.max(0, Math.trunc(options.padding ?? DEFAULT_PADDING))\n\tconst styler = options.styler\n\t// Split on a line feed or a CRLF pair, so caller text written on Windows frames exactly as the\n\t// same text written on POSIX. A lone carriage return is deliberately not a separator: the\n\t// animation frame prefix is a bare `\\r` cursor control, so splitting on it would cut a frame in\n\t// half. The literal is local because this is the one caller-text split in the module.\n\tconst lines = options.content.split(/\\r\\n|\\n/)\n\t// The inner content width: the widest line, the title (when present), and any explicit\n\t// `width` budget (minus the two edges and the two padding gutters) all compete — the\n\t// widest wins, so nothing is ever clipped and an explicit width only ever pads outward.\n\t// The title's claim is its embedded form ` title ` (a gap each side) plus one lead fill\n\t// glyph, all spanning `inner + 2·padding` — so the top edge stays exactly as wide as the\n\t// rest of the box (the frame is always rectangular) and a long title widens the box.\n\tconst titleRoom =\n\t\toptions.title === undefined\n\t\t\t? 0\n\t\t\t: width(options.title) + SEPARATOR_TITLE_GAP.length * 2 + 1 - padding * 2\n\tconst budget = options.width === undefined ? 0 : options.width - 2 - padding * 2\n\tconst inner = lines.reduce(\n\t\t(max, line) => Math.max(max, width(line)),\n\t\tMath.max(0, titleRoom, budget),\n\t)\n\tconst gutter = ' '.repeat(padding)\n\tconst bar = paint(styler, chars.vertical, options.style)\n\t// The top border — the two corners with the horizontal run between, optionally carrying a\n\t// leading ` title ` embedded in the run. `span` is the full inner run (`inner + 2·padding`):\n\t// with no `title` the whole run is fill between the corners; with one, ` title ` sits after a\n\t// single leading fill glyph, the remainder drawn as fill — its visible width stays `span` (the\n\t// title's escape codes don't count).\n\tconst span = inner + padding * 2\n\tlet top: string\n\tif (options.title === undefined) {\n\t\ttop = paint(\n\t\t\tstyler,\n\t\t\t`${chars.topLeft}${repeatTo(chars.horizontal, span)}${chars.topRight}`,\n\t\t\toptions.style,\n\t\t)\n\t} else {\n\t\tconst caption = `${SEPARATOR_TITLE_GAP}${options.title}${SEPARATOR_TITLE_GAP}`\n\t\tconst room = span - width(caption)\n\t\tconst lead = paint(styler, repeatTo(chars.horizontal, 1), options.style)\n\t\tconst rest =\n\t\t\troom - 1 <= 0 ? '' : paint(styler, repeatTo(chars.horizontal, room - 1), options.style)\n\t\ttop = `${paint(styler, chars.topLeft, options.style)}${lead}${paint(styler, caption, options.style)}${rest}${paint(styler, chars.topRight, options.style)}`\n\t}\n\tconst bottom = paint(\n\t\tstyler,\n\t\t`${chars.bottomLeft}${repeatTo(chars.horizontal, inner + padding * 2)}${chars.bottomRight}`,\n\t\toptions.style,\n\t)\n\tconst body = lines.map((line) => `${bar}${gutter}${align(line, inner)}${gutter}${bar}`)\n\treturn [top, ...body, bottom].join('\\n')\n}\n\n/**\n * Renders a bordered grid of `columns` + `rows` with per-column alignment and width-aware\n * column sizing. Pure: same {@link TableOptions} → same string.\n *\n * @remarks\n * - **Column sizing — visible width.** Each column is sized to the widest visible width\n * ({@link width}) among its header label and its cells, so an already-styled cell never\n * breaks the column (its escape codes don't count toward the width).\n * - **Ragged rows.** A row shorter than the column count is padded with empty cells; a longer\n * row is truncated to the column count — a ragged input never throws.\n * - **Alignment.** Each cell is positioned by its column's {@link ColumnSpec.align} (default\n * {@link DEFAULT_ALIGN}) through {@link align}.\n * - **Frame.** The {@link BorderStyle} (`options.border`, default {@link DEFAULT_BORDER})\n * draws the outer frame, the header rule (a `teeRight … cross … teeLeft` line), and the\n * `vertical` column separators; `options.styler` colors the frame + header labels when\n * given. Returns the table as `\\n`-joined rows (top, header, rule, one row per data row,\n * bottom), no trailing newline.\n *\n * @param options - See {@link TableOptions}\n * @returns The rendered table (multiple lines joined by `\\n`)\n */\nexport function renderTable(options: TableOptions): string {\n\tconst chars = BORDER_CHARS[options.border ?? DEFAULT_BORDER]\n\tconst styler = options.styler\n\tconst columns = options.columns\n\t// Each column's visible width: the max of its header label and every cell it holds.\n\tconst widths = columns.map((column, index) =>\n\t\toptions.rows.reduce(\n\t\t\t(max, row) => Math.max(max, width(cellAt(row, index))),\n\t\t\twidth(column.label),\n\t\t),\n\t)\n\tconst aligns = columns.map((column) => column.align ?? DEFAULT_ALIGN)\n\tconst rows = [\n\t\tcolumns.map((column) => paint(styler, column.label, options.style)),\n\t\t...options.rows.map((row) => columns.map((_column, index) => cellAt(row, index))),\n\t]\n\t// Frame the header and every body row in one pass: align each cell to its column width, add\n\t// one-space gutters, and join with the painted vertical separator.\n\tconst renderedRows = rows.map((cells) => {\n\t\tconst bar = paint(styler, chars.vertical, options.style)\n\t\tconst inner = cells\n\t\t\t.map(\n\t\t\t\t(cell, index) =>\n\t\t\t\t\t` ${align(cell, widths[index] ?? width(cell), aligns[index] ?? DEFAULT_ALIGN)} `,\n\t\t\t)\n\t\t\t.join(bar)\n\t\treturn `${bar}${inner}${bar}`\n\t})\n\tconst segments = widths.map((columnWidth) => repeatTo(chars.horizontal, columnWidth + 2))\n\tconst top = paint(\n\t\tstyler,\n\t\t`${chars.topLeft}${segments.join(chars.teeDown)}${chars.topRight}`,\n\t\toptions.style,\n\t)\n\tconst rule = paint(\n\t\tstyler,\n\t\t`${chars.teeRight}${segments.join(chars.cross)}${chars.teeLeft}`,\n\t\toptions.style,\n\t)\n\tconst bottom = paint(\n\t\tstyler,\n\t\t`${chars.bottomLeft}${segments.join(chars.teeUp)}${chars.bottomRight}`,\n\t\toptions.style,\n\t)\n\treturn [top, ...renderedRows.slice(0, 1), rule, ...renderedRows.slice(1), bottom].join('\\n')\n}\n\n/**\n * Renders a nested {@link TreeNode} tree whose connectors derive from the chosen `border` set.\n * Pure: same {@link TreeOptions} → same string.\n *\n * @remarks\n * The `root` label is the unindented first line; its descendants are drawn beneath it with\n * {@link BORDER_CHARS} — `├─ ` before each child but the last, `└─ ` before the last, and the\n * carried prefix using `│ ` under an ancestor that still has later siblings or ` ` under a\n * last ancestor (so the guides line up exactly under the branch they descend from). Node\n * labels are written as given (an already-styled label is honored); `options.styler` colors\n * the connectors when supplied. Returns the tree as `\\n`-joined lines, no trailing newline.\n *\n * @param options - See {@link TreeOptions}\n * @returns The rendered tree (multiple lines joined by `\\n`)\n *\n * @example\n * ```ts\n * renderTree({ root: { label: 'root', children: [{ label: 'a' }, { label: 'b' }] } })\n * // root\n * // ├─ a\n * // └─ b\n * ```\n */\nexport function renderTree(options: TreeOptions): string {\n\tconst border = options.border ?? DEFAULT_BORDER\n\treturn [\n\t\toptions.root.label,\n\t\t...renderTreeChildren(options.root.children ?? [], '', { ...options, border }),\n\t].join('\\n')\n}\n\n/**\n * Renders the connector-prefixed lines for a {@link TreeNode} list — the recursive core behind\n * {@link renderTree}, whose third options argument requires `border` and groups the optional\n * `styler` and `style`.\n *\n * @remarks\n * Each child is drawn as `prefix` + its connector (`├─ ` for any but the last, `└─ ` for the\n * last) + its label, with its own descendants recursed beneath under the carried guide (`│ `\n * under a non-last node, ` ` under the last).\n *\n * @remarks\n * A centralized, exported recursion branch so it is directly testable and\n * reusable outside {@link renderTree}'s top-level `root.label` framing.\n *\n * @param nodes - The sibling {@link TreeNode}s to render at this depth\n * @param prefix - The guide/gap string carried in from the ancestor chain (`''` at the root)\n * @param options - The required `border` selection plus optional connector `styler` and\n * by-value `style`\n * @returns The rendered lines for `nodes` and all their descendants\n *\n * @example\n * ```ts\n * renderTreeChildren([{ label: 'a' }, { label: 'b' }], '', { border: 'single' })\n * // ['├─ a', '└─ b']\n * ```\n */\nexport function renderTreeChildren(\n\tnodes: readonly TreeNode[],\n\tprefix: string,\n\toptions: Required<Pick<TreeOptions, 'border'>> & Pick<TreeOptions, 'style' | 'styler'>,\n): readonly string[] {\n\tconst chars = BORDER_CHARS[options.border]\n\tconst branch = `${chars.teeRight}${chars.horizontal} `\n\tconst corner = `${chars.bottomLeft}${chars.horizontal} `\n\tconst guide = `${chars.vertical} `\n\tconst lines: string[] = []\n\tnodes.forEach((node, index) => {\n\t\tconst last = index === nodes.length - 1\n\t\tlines.push(\n\t\t\t`${prefix}${paint(options.styler, last ? corner : branch, options.style)}${node.label}`,\n\t\t)\n\t\tconst carry = `${prefix}${paint(options.styler, last ? ' ' : guide, options.style)}`\n\t\tlines.push(...renderTreeChildren(node.children ?? [], carry, options))\n\t})\n\treturn lines\n}\n\n/**\n * Stringifies one captured console argument into a line fragment — the per-argument rule behind\n * {@link formatArgs}: an `Error` → `name: message`, a plain object / array → circular-safe JSON,\n * anything else (string, number, boolean, `null`, `undefined`, symbol, function) → `String(value)`.\n *\n * @remarks\n * - **Total + never throws.** Like a guard, this never throws on adversarial input — a value\n * carrying a circular reference, a `BigInt`, or a throwing `toJSON` is rendered, not raised. The\n * `JSON.stringify` runs with a circular-guard replacer (a seen-set drops a back-reference as\n * `'[Circular]'`); if `JSON.stringify` still throws (for example on a `BigInt`), the value falls\n * back to `String(value)`. So a `Capture` can never crash the program whose `console.*` it\n * intercepts.\n * - **`Error` first.** An `Error` renders as `name: message` (for example `TypeError: bad`) — the useful\n * one-line form, since `JSON.stringify(error)` is `{}` (its fields are non-enumerable).\n * - **Objects → JSON.** A non-null `object` (including an array) is `JSON.stringify`d; a primitive\n * (or `null` / `undefined` / `function` / `symbol`) goes through `String`.\n *\n * @param value - One console argument (any value)\n * @returns The argument's one-line string form\n *\n * @example\n * ```ts\n * stringifyValue('hi') // 'hi'\n * stringifyValue({ a: 1 }) // '{\"a\":1}'\n * stringifyValue(new TypeError('bad')) // 'TypeError: bad'\n * const cycle: Record<string, unknown> = {}\n * cycle.self = cycle\n * stringifyValue(cycle) // '{\"self\":\"[Circular]\"}'\n * ```\n */\nexport function stringifyValue(value: unknown): string {\n\tif (isError(value)) return `${value.name}: ${value.message}`\n\tif (!isObject(value)) return String(value)\n\t// A circular-safe replacer — a seen-set drops any back-reference so a cyclic graph serializes\n\t// instead of throwing (total, like a guard). A residual throw (for example a BigInt field) falls\n\t// back to String(value), so this helper is total on every input.\n\tconst seen = new WeakSet<object>()\n\ttry {\n\t\treturn JSON.stringify(value, (_key, nested: unknown) => {\n\t\t\tif (isObject(nested)) {\n\t\t\t\tif (seen.has(nested)) return '[Circular]'\n\t\t\t\tseen.add(nested)\n\t\t\t}\n\t\t\treturn nested\n\t\t})\n\t} catch {\n\t\treturn String(value)\n\t}\n}\n\n/**\n * Stringifies a captured `console.*` argument list into one line — the text of a {@link\n * import('./types.js').CapturedMessage}. Each argument is rendered by {@link stringifyValue} and\n * the parts are space-joined, mirroring how a console concatenates its arguments.\n *\n * @remarks\n * Total and never throws (it composes {@link stringifyValue}, which is total) — a `Capture` builds\n * every message through this, so intercepting `console.*` can never crash the underlying program.\n * An empty argument list yields `''` (an empty `console.log()` is captured as a blank line).\n *\n * @param args - The arguments a `console.*` method was called with\n * @returns The arguments stringified and space-joined into one line\n *\n * @example\n * ```ts\n * formatArgs(['count', 3, { ok: true }]) // 'count 3 {\"ok\":true}'\n * formatArgs([]) // ''\n * ```\n */\nexport function formatArgs(args: readonly unknown[]): string {\n\treturn args.map(stringifyValue).join(' ')\n}\n\n/**\n * Renders a determinate progress bar string — a filled / empty glyph track followed by the percentage\n * and the `(current/total)` count (`█████░░░░░ 50% (5/10)`). Pure and width-aware: same\n * {@link BarOptions} → same string.\n *\n * @remarks\n * It is the animation-layer sibling of the `render*` renderers (box / table / tree / separator),\n * shared so a {@link import('./types.js').ProgressInterface} and any direct caller draw the one\n * bar — never a second,\n * hand-rolled one.\n *\n * - **Fill fraction, clamped.** The filled cell count is `round((current / total) · width)` with\n * `current` clamped to `[0, total]`, so an overrun never over-fills and a negative never under-fills.\n * A `total <= 0` renders a full track (there is nothing to fill toward — the work is trivially done).\n * - **Width-aware track.** The filled run is `fill` tiled to the filled cell count and the empty run\n * `empty` tiled to the remainder, each through {@link repeatTo} — so the track is exactly `width` visible\n * columns even for a multi-cell glyph (its escape codes / extra cells never break the width).\n * - **Styling.** `options.styler` colors the filled run only (the empty run + the trailing\n * `percent (count)` label stay plain), through {@link paint}; the layout is identical with or\n * without color, since the track is measured on visible width.\n * - **Label.** The percentage is the rounded `current / total` (for example `50%`); the count is the clamped\n * `current` over `total` (`(5/10)`), a single space separating the track, the percent, and the count.\n *\n * @param options - See {@link BarOptions}\n * @returns The rendered bar line (no trailing newline)\n *\n * @example\n * ```ts\n * renderBar({ current: 5, total: 10, width: 10 }) // '█████░░░░░ 50% (5/10)'\n * renderBar({ current: 10, total: 10, width: 4 }) // '████ 100% (10/10)'\n * ```\n */\nexport function renderBar(options: BarOptions): string {\n\tconst track = options.width ?? DEFAULT_BAR_WIDTH\n\tconst fill = options.fill ?? BAR_FILL\n\tconst empty = options.empty ?? BAR_EMPTY\n\t// Clamp `current` into [0, total], and treat a non-positive `total` as already complete (a full\n\t// track) — so the fraction is always a sound [0, 1] and an overrun / negative never breaks the bar.\n\tconst current = options.total <= 0 ? 0 : Math.max(0, Math.min(options.total, options.current))\n\tconst fraction = options.total <= 0 ? 1 : current / options.total\n\tconst filledCells = Math.round(fraction * track)\n\tconst bar = `${paint(options.styler, repeatTo(fill, filledCells), options.style)}${repeatTo(empty, track - filledCells)}`\n\tconst percent = Math.round(fraction * 100)\n\treturn `${bar} ${percent}% (${current}/${options.total})`\n}\n","import type { RendererInterface, Style } from '../types.js'\nimport { ATTRIBUTE_CODES, BACKGROUND_CODES, CSI, FOREGROUND_CODES, RESET } from '../constants.js'\n\n/**\n * Implements the cross-environment default {@link RendererInterface} — renders style data as ANSI\n * SGR escape codes, stateless and event-free.\n *\n * @remarks\n * It is the single styling output the whole console / terminal system uses in a terminal; the\n * browser `%c` / CSS renderer implements the same contract over the same {@link Style}, so\n * retargeting changes the renderer, never the style model.\n *\n * - **Style is data in, SGR string out.** It reads the style's `foreground` /\n * `background` / `attributes` and emits one `ESC[…m` sequence whose parameters are the\n * mapped SGR numbers (foreground 30–37 / 90–97, background 40–47 / 100–107, attributes\n * 1 / 2 / 3 / 4 / 7 / 9), followed by `text`, terminated by the reset `ESC[0m`.\n * - **Multiple attributes compose** — their codes join with `;` in a single sequence\n * (`ESC[1;4;31m` for bold + underline + red), so one open and one reset wrap the run.\n * - **`default` and unset colors emit no code** — a `default` (or absent) `foreground` /\n * `background` leaves the terminal's own ink.\n * - **The empty style and the empty string pass through** — when there is nothing to\n * apply (no colors, no attributes) or `text` is `''`, `text` is returned verbatim with\n * no escape codes, so an unstyled render never injects a stray reset.\n * - **Stateless and event-free** — no fields, no events; safe to share one instance.\n */\nexport class ANSIRenderer implements RendererInterface {\n\t/**\n\t * Wraps `text` in the SGR codes for `style`. Returns `text` unchanged when the style\n\t * is empty or `text` is `''`.\n\t */\n\trender(style: Style, text: string): string {\n\t\tif (text === '') return text\n\t\tconst codes = this.#codes(style)\n\t\tif (codes.length === 0) return text\n\t\treturn `${CSI}${codes.join(';')}m${text}${RESET}`\n\t}\n\n\t// Collect the SGR parameters for a style, in a stable order — attributes first (in\n\t// their `attributes` order), then foreground, then background. A `default` or absent\n\t// color contributes nothing; an empty result signals \"no wrapping\" to `render`.\n\t#codes(style: Style): readonly number[] {\n\t\tconst codes: number[] = []\n\t\tfor (const attribute of style.attributes) codes.push(ATTRIBUTE_CODES[attribute])\n\t\tif (style.foreground !== undefined && style.foreground !== 'default') {\n\t\t\tcodes.push(FOREGROUND_CODES[style.foreground])\n\t\t}\n\t\tif (style.background !== undefined && style.background !== 'default') {\n\t\t\tcodes.push(BACKGROUND_CODES[style.background])\n\t\t}\n\t\treturn codes\n\t}\n}\n","import type { RetentionInterface } from './types.js'\n\n/**\n * Implements the bounded, level-keyed retention engine the console and process captures buffer\n * through — one capped total buffer\n * plus one capped bucket per level, generic over the record type each capture carries.\n *\n * @remarks\n * - **One engine, two captures.** The core `Capture` retains\n * {@link import('./types.js').CapturedMessage}s keyed by\n * {@link import('./types.js').CaptureLevel}, and the server `ProcessCapture` retains chunks keyed\n * by its stream level; both compose this, so their retention semantics cannot drift apart.\n * - **Bounded on both axes.** `add` appends to the total buffer and to the record's bucket, then\n * drops the oldest of whichever exceeded `limit`, so neither grows without bound.\n * - **Buckets are fixed at construction.** Only the levels passed to the constructor get a bucket.\n * A record at any other level still joins the total buffer, and `records(level)` for a level with\n * no bucket returns an empty list.\n * - **Copies out.** `records` returns a fresh list each call, so retained state is never reachable\n * for mutation through a returned value.\n *\n * @example\n * ```ts\n * const retention = new Retention<{ level: 'warn' | 'error'; text: string }>(['warn'], 2)\n * retention.add({ level: 'warn', text: 'first' })\n * retention.add({ level: 'error', text: 'second' }) // no bucket, still in the total buffer\n * retention.records().length // 2\n * retention.records('warn').map((record) => record.text) // ['first']\n * retention.clear()\n * retention.records() // []\n * ```\n */\nexport class Retention<T extends { readonly level: string }> implements RetentionInterface<T> {\n\treadonly #limit: number\n\t// The bounded total buffer — every retained record, oldest first, capped at #limit.\n\treadonly #records: T[] = []\n\t// The bounded per-level buckets — one capped buffer per level supplied at construction.\n\treadonly #buckets = new Map<T['level'], T[]>()\n\n\tconstructor(levels: ReadonlyArray<T['level']>, limit: number) {\n\t\tthis.#limit = limit\n\t\tfor (const level of levels) this.#buckets.set(level, [])\n\t}\n\n\tadd(record: T): void {\n\t\tthis.#push(this.#records, record)\n\t\tconst bucket = this.#buckets.get(record.level)\n\t\tif (bucket !== undefined) this.#push(bucket, record)\n\t}\n\n\trecords(): readonly T[]\n\trecords(level: T['level']): readonly T[]\n\trecords(level?: T['level']): readonly T[] {\n\t\tif (level === undefined) return [...this.#records]\n\t\treturn [...(this.#buckets.get(level) ?? [])]\n\t}\n\n\tclear(): void {\n\t\tthis.#records.length = 0\n\t\tfor (const bucket of this.#buckets.values()) bucket.length = 0\n\t}\n\n\t// Bounded push — append, then drop the oldest while over the cap.\n\t#push(buffer: T[], record: T): void {\n\t\tbuffer.push(record)\n\t\tif (buffer.length > this.#limit) buffer.shift()\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tCaptureEventMap,\n\tCaptureInterface,\n\tCaptureLevel,\n\tCaptureOptions,\n\tCapturedMessage,\n\tRetentionInterface,\n\tSinkInterface,\n\tConsoleMethod,\n} from './types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { CAPTURE_LEVEL_MAP, CAPTURE_LEVELS, DEFAULT_CAPTURE_LIMIT } from './constants.js'\nimport { formatArgs } from './helpers.js'\nimport { Retention } from './Retention.js'\n\n/**\n * Implements an observable console interceptor — it takes control of the global `console.*` on\n * the read side. While `active`, every configured `console.x` call is captured as a frozen\n * {@link CapturedMessage}, buffered (total + by level, bounded), emitted on `capture`, and — per\n * options — mirrored to the real console, forwarded to a {@link SinkInterface}, or both.\n *\n * @remarks\n * - **Snapshot-at-start (the no-capture-loop principle).** `start()` snapshots the current\n * `console[level]` for each configured {@link CaptureLevel}, then installs the wrappers. The\n * mirror writes through that snapshot — so our own console sink output (the Logger / Reporter,\n * which snapshot the real `console` at creation) is never recaptured: `Capture` catches\n * third-party `console.*`, not our writes. Create your loggers before installing a capture.\n * - **Idempotent + process-global + non-reentrant.** `start()` while already `active` is a no-op\n * (never double-patches); `stop()` while inactive is a no-op. It patches the one global\n * `console`, so at most one capture may be active at a time — running two concurrently\n * interleaves their buffers and clobbers each other's restore.\n * - **Bounded buffers.** `messages()` / `messages(level)` — the total buffer and each by-level\n * bucket are each capped at `limit`\n * (oldest dropped first), never unbounded — the same retention precedent as {@link Logger}.\n * - **Lifecycle.** `start` / `stop` toggle interception (emitting `start` / `stop`);\n * `destroy()` stops (restoring `console`) then destroys the emitter.\n *\n * @example\n * ```ts\n * const capture = new Capture({ levels: ['warn', 'error'], mirror: true })\n * capture.start()\n * console.warn('third-party noise') // captured and mirrored to the real console\n * capture.messages('warn') // [{ level: 'warn', text: 'third-party noise', time: … }]\n * capture.stop() // console.warn restored\n * ```\n */\nexport class Capture implements CaptureInterface {\n\t// The push observation surface — owned, never inherited. The emitter isolates a listener\n\t// throw (routing it to the `error` handler), so a buggy `capture` listener can never escape into\n\t// the underlying program's `console.*` call.\n\treadonly #emitter: Emitter<CaptureEventMap>\n\treadonly #levels: readonly CaptureLevel[]\n\treadonly #mirror: boolean\n\treadonly #sink: SinkInterface | undefined\n\t// The bounded buffers — the total one and one per configured CaptureLevel — owned by the shared\n\t// retention engine the server's ProcessCapture composes too.\n\treadonly #retention: RetentionInterface<CapturedMessage>\n\t// The snapshot-original console methods, captured at start() and restored at stop(); empty\n\t// while inactive.\n\treadonly #originals = new Map<CaptureLevel, ConsoleMethod>()\n\t// Stored rather than derived from #originals: an empty `levels` list patches no console method,\n\t// so a started capture configured with no level leaves #originals empty while still being active.\n\t#active = false\n\n\tconstructor(options?: CaptureOptions) {\n\t\tthis.#emitter = new Emitter<CaptureEventMap>({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#levels = options?.levels ?? CAPTURE_LEVELS\n\t\tthis.#mirror = options?.mirror ?? false\n\t\tthis.#sink = options?.sink\n\t\tthis.#retention = new Retention<CapturedMessage>(\n\t\t\tthis.#levels,\n\t\t\toptions?.limit ?? DEFAULT_CAPTURE_LIMIT,\n\t\t)\n\t}\n\n\tget emitter(): EmitterInterface<CaptureEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget active(): boolean {\n\t\treturn this.#active\n\t}\n\n\tstart(): void {\n\t\t// Idempotent — never double-patch an already-active capture (that would snapshot the\n\t\t// wrappers as the \"originals\" and break restore).\n\t\tif (this.#active) return\n\t\tthis.#active = true\n\t\tconst target: Record<CaptureLevel, ConsoleMethod> = console\n\t\tfor (const level of this.#levels) {\n\t\t\t// Snapshot the current method reference before replacing it — stop() restores exactly this\n\t\t\t// reference, leaving `console` pristine (the wrapper is never snapshotted as the original).\n\t\t\tconst original = target[level]\n\t\t\tthis.#originals.set(level, original)\n\t\t\t// The mirror target is the snapshot original bound to `console`, computed once here — so a\n\t\t\t// mirrored call reaches the real method with its proper receiver, through the snapshot and\n\t\t\t// never the live (patched) `console` (no capture loop). The restore reference stays the\n\t\t\t// pristine unbound `original` above; only the mirror uses the bound form.\n\t\t\tconst mirror = original.bind(console)\n\t\t\ttarget[level] = this.#captureCall.bind(this, level, mirror)\n\t\t}\n\t\tthis.#emitter.emit('start')\n\t}\n\n\tstop(): void {\n\t\t// Safe when not active — nothing to restore.\n\t\tif (!this.#active) return\n\t\tthis.#active = false\n\t\tconst target: Record<CaptureLevel, ConsoleMethod> = console\n\t\tfor (const [level, original] of this.#originals) target[level] = original\n\t\tthis.#originals.clear()\n\t\tthis.#emitter.emit('stop')\n\t}\n\n\tmessages(): readonly CapturedMessage[]\n\tmessages(level: CaptureLevel): readonly CapturedMessage[]\n\tmessages(level?: CaptureLevel): readonly CapturedMessage[] {\n\t\tif (level === undefined) return this.#retention.records()\n\t\treturn this.#retention.records(level)\n\t}\n\n\tclear(): void {\n\t\tthis.#retention.clear()\n\t}\n\n\tdestroy(): void {\n\t\tthis.stop()\n\t\tthis.#emitter.destroy()\n\t}\n\n\t// Adapt the patched console's variadic call shape to the captured argument collection consumed\n\t// by #intercept. Binding level and mirror in start() leaves the exact ConsoleMethod signature.\n\t#captureCall(level: CaptureLevel, mirror: ConsoleMethod, ...args: unknown[]): void {\n\t\tthis.#intercept(level, args, mirror)\n\t}\n\n\t// The wrapper body behind every patched `console.x`: build the frozen message, buffer it\n\t// (total + by level, bounded), emit `capture`, then — per options — mirror to the real console\n\t// and forward to the sink. `mirror` is the snapshot original bound to `console` (computed at\n\t// start()); the program's own call is replayed through it (with its proper receiver) only when\n\t// the `mirror` option is set.\n\t#intercept(level: CaptureLevel, args: unknown[], mirror: ConsoleMethod): void {\n\t\tconst message = this.#capture(level, args)\n\t\tthis.#retention.add(message)\n\t\tthis.#emitter.emit('capture', message)\n\t\tif (this.#mirror) mirror(...args)\n\t\t// The wrapper never throws into the patched global — a misbehaving sink is best-effort\n\t\t// and swallowed, never allowed to break the underlying program's own console.* call.\n\t\tif (this.#sink !== undefined) {\n\t\t\ttry {\n\t\t\t\tthis.#sink.write(message.text, CAPTURE_LEVEL_MAP[level])\n\t\t\t} catch {\n\t\t\t\t// Swallowed — see comment above.\n\t\t\t}\n\t\t}\n\t}\n\n\t// Build the immutable, serializable captured message — args stringified to one line (total,\n\t// never throws — see formatArgs), stamped with the capture instant. Frozen so a consumer (or\n\t// the `capture` listener) can never mutate it after the fact.\n\t#capture(level: CaptureLevel, args: readonly unknown[]): CapturedMessage {\n\t\treturn Object.freeze({ level, text: formatArgs(args), time: Date.now() })\n\t}\n}\n","import type { Attribute, Color, RendererInterface, Style, StylerInterface } from './types.js'\nimport { isFunction } from '@orkestrel/contract'\nimport { ATTRIBUTES, COLORS } from './constants.js'\nimport { ConsoleError } from './errors.js'\n\n/**\n * Builds the fluent, composable styling surface — the consumer-facing API over the style\n * engine. It\n * builds a {@link Style} (style as data) and renders it through an injected\n * {@link RendererInterface} (the ANSI default, or a browser `%c` renderer). Each\n * color / attribute accessor is immutable copy-on-write: it returns a new styler's\n * surface with the token added, so `styler.red.bold('hi')` composes without mutating,\n * and a base styler is freely reusable.\n *\n * @remarks\n * - **Callable surface.** A `Styler` is not itself callable; its {@link surface} getter\n * returns the {@link StylerInterface} — a render function carrying the chainable\n * accessors. The accessors are installed as lazy getters (`Object.defineProperties`),\n * so a chain materializes only the stylers it actually walks — never the full tree —\n * and the recursion terminates. The factory returns that surface; this class is the\n * engine behind it.\n * - **Immutable.** `#foreground` and `#attribute` return a fresh `Styler` (the style is\n * rebuilt, never mutated). A later color of the same channel wins (last write); a\n * repeated attribute is idempotent (de-duplicated, order preserved).\n * - **Styling by value.** `render(style, text)` merges a {@link Style} over the accumulated\n * one and renders that — the same precedence a chain applies, reached with data instead of\n * accessor names. It is how a {@link import('./types.js').Theme} role is drawn.\n * - **`enabled` switch.** When `false`, the render function returns text verbatim — no\n * renderer call, no escape codes (for a non-TTY / `NO_COLOR` / piped output).\n * - **Event-free** — a pure styling primitive, like `Scheduler`.\n */\nexport class Styler {\n\treadonly #renderer: RendererInterface\n\treadonly #enabled: boolean\n\treadonly #style: Style\n\n\tconstructor(renderer: RendererInterface, enabled: boolean, style: Style) {\n\t\tthis.#renderer = renderer\n\t\tthis.#enabled = enabled\n\t\tthis.#style = style\n\t}\n\n\t/** Holds the accumulated style data — the empty style on a base styler. */\n\tget style(): Style {\n\t\treturn this.#style\n\t}\n\n\t/** Reports whether styling is applied; when `false`, the surface returns text unchanged. */\n\tget enabled(): boolean {\n\t\treturn this.#enabled\n\t}\n\n\t/**\n\t * Builds the fluent {@link StylerInterface} value — a render function (`text => string`) with\n\t * `style`, `enabled`, and every {@link Color} / {@link Attribute} as a lazy accessor\n\t * (each computes the next styler's surface only when read). This is what consumers\n\t * hold and call.\n\t *\n\t * @remarks\n\t * The accessors are defined as getters (not eagerly-merged values), so accessing one\n\t * builds exactly one child styler — the tree is never fully materialized and the\n\t * construction terminates. The assembled function is then narrowed to\n\t * {@link StylerInterface} through {@link #isSurface} (a real structural check), so no\n\t * type assertion is used — narrow, never assert.\n\t */\n\tget surface(): StylerInterface {\n\t\tconst callable = this.#render.bind(this)\n\t\tconst descriptors: PropertyDescriptorMap = {\n\t\t\tstyle: { value: this.#style, enumerable: true },\n\t\t\tenabled: { value: this.#enabled, enumerable: true },\n\t\t\trender: { value: this.render.bind(this), enumerable: true },\n\t\t}\n\t\tfor (const color of COLORS) {\n\t\t\tdescriptors[color] = {\n\t\t\t\tget: this.#foregroundSurface.bind(this, color),\n\t\t\t\tenumerable: true,\n\t\t\t}\n\t\t}\n\t\tfor (const attribute of ATTRIBUTES) {\n\t\t\tdescriptors[attribute] = {\n\t\t\t\tget: this.#attributeSurface.bind(this, attribute),\n\t\t\t\tenumerable: true,\n\t\t\t}\n\t\t}\n\t\tconst surface = Object.defineProperties(callable, descriptors)\n\t\tif (this.#isSurface(surface)) return surface\n\t\t// Unreachable: the descriptors above install every accessor the guard checks for.\n\t\tthrow new ConsoleError('INVARIANT', 'console: styler surface construction is incomplete')\n\t}\n\n\t/**\n\t * Renders `text` in `style` merged over the accumulated style — the by-value door beside\n\t * the accessor chain, and how a {@link import('./types.js').Theme} role is applied.\n\t *\n\t * @param style - The style to overlay; its colors win over the accumulated ones and its\n\t * attributes join them (de-duplicated, the accumulated ones first)\n\t * @param text - The text to wrap\n\t * @returns The rendered text — verbatim when `enabled` is `false`, and (by the\n\t * {@link RendererInterface} contract) when the merged style or `text` is empty\n\t *\n\t * @example\n\t * ```ts\n\t * import { createStyler, DEFAULT_THEME } from '@orkestrel/console'\n\t *\n\t * const styler = createStyler()\n\t * styler.render(DEFAULT_THEME.levels.warn, 'WARN') // yellow\n\t * styler.bold.render(DEFAULT_THEME.chrome, '│') // dim, over the accumulated bold\n\t * ```\n\t */\n\trender(style: Style, text: string): string {\n\t\treturn this.#enabled ? this.#renderer.render(this.#merge(style), text) : text\n\t}\n\n\t// Render through the configured target, or pass text through when styling is disabled.\n\t#render(text: string): string {\n\t\treturn this.#enabled ? this.#renderer.render(this.#style, text) : text\n\t}\n\n\t// Overlay `style` on the accumulated style: a set color of either channel wins (last\n\t// write, as in a chain), and the attribute sets union — accumulated order first, the\n\t// overlay's new ones appended, each carried once. Frozen, like every style this engine\n\t// builds; the caller's value is read, never touched.\n\t#merge(style: Style): Style {\n\t\tconst attributes: Attribute[] = [...this.#style.attributes]\n\t\tfor (const attribute of style.attributes) {\n\t\t\tif (!attributes.includes(attribute)) attributes.push(attribute)\n\t\t}\n\t\treturn Object.freeze({\n\t\t\t...this.#style,\n\t\t\t...style,\n\t\t\tattributes: Object.freeze(attributes),\n\t\t})\n\t}\n\n\t// Resolve one lazy foreground accessor to the next immutable styler surface.\n\t#foregroundSurface(color: Color): StylerInterface {\n\t\treturn this.#foreground(color).surface\n\t}\n\n\t// Resolve one lazy attribute accessor to the next immutable styler surface.\n\t#attributeSurface(attribute: Attribute): StylerInterface {\n\t\treturn this.#attribute(attribute).surface\n\t}\n\n\t// Structurally confirm an assembled value is a usable styler surface — callable, with\n\t// the data members and a representative color/attribute accessor present. A genuine\n\t// runtime narrowing, not a cast: it lets `surface` return `StylerInterface`\n\t// without `as`/`!`.\n\t#isSurface(value: ((text: string) => string) & object): value is StylerInterface {\n\t\treturn (\n\t\t\tisFunction(value) &&\n\t\t\t'style' in value &&\n\t\t\t'enabled' in value &&\n\t\t\t'render' in value &&\n\t\t\t'red' in value &&\n\t\t\t'bold' in value\n\t\t)\n\t}\n\n\t// A new styler with `color` as the foreground — last write wins (replaces any prior\n\t// foreground); background and attributes carried forward unchanged.\n\t#foreground(color: Color): Styler {\n\t\treturn new Styler(\n\t\t\tthis.#renderer,\n\t\t\tthis.#enabled,\n\t\t\tObject.freeze({ ...this.#style, foreground: color }),\n\t\t)\n\t}\n\n\t// A new styler with `attribute` added to the set — de-duplicated and order-stable, so\n\t// a repeated attribute is idempotent.\n\t#attribute(attribute: Attribute): Styler {\n\t\tif (this.#style.attributes.includes(attribute)) return this\n\t\treturn new Styler(\n\t\t\tthis.#renderer,\n\t\t\tthis.#enabled,\n\t\t\tObject.freeze({\n\t\t\t\t...this.#style,\n\t\t\t\tattributes: Object.freeze([...this.#style.attributes, attribute]),\n\t\t\t}),\n\t\t)\n\t}\n}\n","import type {\n\tCaptureOptions,\n\tCaptureResult,\n\tLogLevel,\n\tSinkInterface,\n\tStylerInterface,\n\tStylerOptions,\n\tTheme,\n\tThemeOptions,\n} from './types.js'\nimport { ANSIRenderer } from './renderers/ANSIRenderer.js'\nimport { Capture } from './Capture.js'\nimport { DEFAULT_THEME, EMPTY_STYLE, LOG_LEVELS, STATUS_LEVELS } from './constants.js'\nimport { freezeStyle, selectWriter } from './helpers.js'\nimport { Styler } from './Styler.js'\n\n/**\n * Creates the fluent, composable {@link StylerInterface} — ANSI by default, retargeted by a\n * `renderer` and stripped of color by `enabled: false`.\n *\n * @remarks\n * It builds a {@link import('./types.js').Style} under the hood and renders it through a\n * {@link import('./types.js').RendererInterface}, so `styler.red.bold('hi')` yields styled text.\n * Chains are immutable, so a base styler is freely reusable.\n *\n * @param options - See {@link StylerOptions}\n * @returns A base {@link StylerInterface}\n *\n * @remarks\n * - `options.renderer` swaps the output target without touching the style model — pass a\n * browser `%c` / CSS renderer (the browser branch) to retarget; defaults to the ANSI\n * renderer (the cross-environment default).\n * - `options.enabled` is the no-color switch: when `false`, the styler returns text\n * verbatim (for a non-TTY, `NO_COLOR`, or piped output); defaults to `true`.\n *\n * @example\n * ```ts\n * import { createStyler } from '@orkestrel/console'\n *\n * const style = createStyler()\n * style.red.bold('error') // bold red\n * style.red(style.underline('link')) // composes either way\n *\n * // Disable for a non-TTY — every call returns its text unchanged.\n * const plain = createStyler({ enabled: false })\n * plain.green('ok') // 'ok'\n * ```\n */\nexport function createStyler(options?: StylerOptions): StylerInterface {\n\tconst renderer = options?.renderer ?? new ANSIRenderer()\n\tconst enabled = options?.enabled ?? true\n\treturn new Styler(renderer, enabled, EMPTY_STYLE).surface\n}\n\n/**\n * Creates a {@link Theme} — the app-wide semantic style vocabulary, merged role by role over\n * {@link DEFAULT_THEME}. Hand one theme to a logger / reporter / spinner / progress and every\n * surface speaks it; omit `options` for the defaults.\n *\n * @param options - See {@link ThemeOptions}\n * @returns A frozen {@link Theme}\n *\n * @remarks\n * - **Merges per role, not per theme.** An omitted role keeps its default, and `levels` /\n * `statuses` merge per entry — `{ levels: { warn: … } }` restyles the `warn` label and\n * leaves `debug` / `info` / `error` untouched.\n * - **Frozen and shareable.** The factory snapshots and deep-freezes every style leaf. The\n * returned theme and its `levels` / `statuses` records are frozen. Each status record is also\n * copied and frozen. One theme is therefore safely shared across every entity.\n *\n * @example\n * ```ts\n * import { createStyler, createTheme } from '@orkestrel/console'\n *\n * const styler = createStyler()\n * const theme = createTheme({\n * \tlevels: { warn: styler.brightYellow.bold.style }, // only the warn label changes\n * \taccent: styler.magenta.style, // spinner glyph, progress fill, step prefix\n * })\n * theme.levels.error // still the default red\n * ```\n */\nexport function createTheme(options?: ThemeOptions): Theme {\n\tconst levels = { ...DEFAULT_THEME.levels }\n\tfor (const level of LOG_LEVELS) {\n\t\tlevels[level] = freezeStyle(options?.levels?.[level] ?? DEFAULT_THEME.levels[level])\n\t}\n\tconst statuses = { ...DEFAULT_THEME.statuses }\n\tfor (const status of STATUS_LEVELS) {\n\t\tconst source = options?.statuses?.[status] ?? DEFAULT_THEME.statuses[status]\n\t\tstatuses[status] = Object.freeze({ icon: source.icon, style: freezeStyle(source.style) })\n\t}\n\treturn Object.freeze({\n\t\tlevels: Object.freeze(levels),\n\t\tstatuses: Object.freeze(statuses),\n\t\taccent: freezeStyle(options?.accent ?? DEFAULT_THEME.accent),\n\t\tchrome: freezeStyle(options?.chrome ?? DEFAULT_THEME.chrome),\n\t})\n}\n\n/**\n * Creates the default {@link SinkInterface} — a console sink that routes by level and writes\n * through the `console` methods snapshotted at creation. The default output target behind the\n * {@link import('./loggers/Logger.js').Logger}.\n *\n * @returns A console {@link SinkInterface}\n *\n * @remarks\n * - **Snapshotted — no capture loop.** It captures `console.log` / `console.warn` /\n * `console.error` at call time and writes through those references. So when a later\n * `Capture` patches `console.*`, this sink still reaches the real streams — the\n * writer and the capturer never feed each other (the no-capture-loop principle). Create\n * the sink (or the logger) before installing a capture for this to hold.\n * - **Routes by level.** `error` → the snapshotted `console.error`, `warn` →\n * `console.warn`, every other level → `console.log`. The `level` is supplied by the\n * logger; an omitted `level` goes to `console.log`. The decision is\n * {@link import('./helpers.js').selectWriter}'s, shared with the browser and server sinks.\n *\n * @example\n * ```ts\n * import { createConsoleSink } from '@orkestrel/console'\n *\n * const sink = createConsoleSink() // snapshots console.* at construction\n * sink.write('boom', 'error') // → the real console.error, even after a later console patch\n * ```\n */\nexport function createConsoleSink(): SinkInterface {\n\t// Snapshot the console writers at construction — bound to their `console` receiver — so a later\n\t// patch of `console.*` (by Capture) can never reach this sink's output (no capture loop).\n\tconst log = console.log.bind(console)\n\tconst warn = console.warn.bind(console)\n\tconst error = console.error.bind(console)\n\treturn {\n\t\twrite(text: string, level?: LogLevel): void {\n\t\t\tselectWriter(level, { log, warn, error })(text)\n\t\t},\n\t}\n}\n\n/**\n * Runs `fn` with the global `console.*` captured for its duration, returning the function's `value`\n * plus the {@link import('./types.js').CapturedMessage}s it logged — the scoped, self-restoring\n * ergonomic form of the {@link Capture} class.\n *\n * @param fn - The async function to run under capture (returns `Promise<T>`)\n * @param options - See {@link CaptureOptions} (`levels` / `mirror` / `sink` / `limit` / `on` /\n * `error`); the capture is started for the duration of `fn` regardless\n * @returns A `Promise<CaptureResult<T>>` — awaited, then `console` restored\n *\n * @remarks\n * - **Always restores.** `start()` runs before `fn`; `destroy()` (which calls `stop()`) runs on\n * every path — sync success, sync throw, and each async handler — so `console` is restored even\n * if `fn` throws / rejects (the throw / rejection still propagates). The capture is local —\n * created, used, and destroyed within the call.\n * - **Sync vs async.** A `fn` returning a `Promise` is detected and awaited before `stop()`, so\n * captures during the async work are included; a plain `fn` stops synchronously. The return type\n * follows `fn`'s (overloaded).\n * - **process-global caveat.** Like the {@link Capture} class, this patches the one global\n * `console`. Concurrent `createCaptureResult` calls (or one around other capturing code)\n * interleave — each captures every `console.*` call in flight, and the inner `stop()` restores\n * whatever the outer had installed. Use it for sequential, scoped capture, not overlapping captures.\n *\n * @example\n * ```ts\n * import { createCaptureResult } from '@orkestrel/console'\n *\n * // The async call is awaited before `console` is restored, so the capture covers the async work.\n * const out = await createCaptureResult(async () => {\n * \tconsole.warn('async noise')\n * \treturn 'done'\n * })\n * out.value // 'done'\n * out.messages.map((m) => m.text) // ['async noise']\n * ```\n */\nexport function createCaptureResult<T>(\n\tfn: () => Promise<T>,\n\toptions?: CaptureOptions,\n): Promise<CaptureResult<T>>\n/**\n * Runs `fn` with the global `console.*` captured for its duration, returning the function's `value`\n * plus the {@link import('./types.js').CapturedMessage}s it logged, synchronously.\n *\n * @param fn - The synchronous function to run under capture (returns `T`)\n * @param options - See {@link CaptureOptions}\n * @returns A {@link CaptureResult}`<T>` — `{ value, messages }`, with `console` already restored\n *\n * @example\n * ```ts\n * import { createCaptureResult } from '@orkestrel/console'\n *\n * // The sync call returns the result directly — no `await`, `console` already restored.\n * const { value, messages } = createCaptureResult(() => {\n * \tconsole.log('working')\n * \treturn 42\n * })\n * value // 42\n * messages.map((m) => m.text) // ['working']\n * ```\n */\nexport function createCaptureResult<T>(fn: () => T, options?: CaptureOptions): CaptureResult<T>\n// The one implementation behind both overloads: start the capture, run `fn`, and destroy the\n// capture on every path — sync success, sync throw, and each async handler — so `console` is always\n// restored and only the buffered messages are returned.\nexport function createCaptureResult<T>(\n\tfn: () => T | Promise<T>,\n\toptions?: CaptureOptions,\n): CaptureResult<T> | Promise<CaptureResult<T>> {\n\tconst capture = new Capture(options)\n\tcapture.start()\n\ttry {\n\t\tconst result = fn()\n\t\tif (result instanceof Promise) {\n\t\t\treturn result.then(\n\t\t\t\t(value) => {\n\t\t\t\t\tconst messages = capture.messages()\n\t\t\t\t\tcapture.destroy()\n\t\t\t\t\treturn { value, messages }\n\t\t\t\t},\n\t\t\t\t(error: unknown) => {\n\t\t\t\t\tcapture.destroy()\n\t\t\t\t\tthrow error\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t\tconst messages = capture.messages()\n\t\tcapture.destroy()\n\t\treturn { value: result, messages }\n\t} catch (error) {\n\t\t// A sync throw — restore console before rethrowing (the async rejection path is handled above).\n\t\tcapture.destroy()\n\t\tthrow error\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tLoggerEventMap,\n\tLogFormatFunction,\n\tLoggerInterface,\n\tLoggerOptions,\n\tLogLevel,\n\tLogRecord,\n\tSinkInterface,\n\tStylerInterface,\n\tTheme,\n} from '../types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { DEFAULT_LOG_LEVEL, DEFAULT_LOG_LIMIT, DEFAULT_THEME } from '../constants.js'\nimport { createConsoleSink, createStyler } from '../factories.js'\nimport { formatRecord, meetsLevel } from '../helpers.js'\n\n/**\n * Implements an observable, leveled logger — the entry point into the structured-logging\n * pipeline. Each `debug` / `info` / `warn` / `error` call builds a frozen {@link LogRecord},\n * gates it by severity, retains a bounded tail of accepted records, always emits it on\n * `entry` (the transport seam), and — unless `silent` — formats it into a styled line and\n * writes it to its {@link SinkInterface}.\n *\n * @remarks\n * - **Record + event = transport.** An accepted record is frozen and emitted on\n * `entry` before anything else observable — every file / JSON / remote transport rides\n * `emitter.on('entry')`. The event fires even when `silent`: silence suppresses only the\n * sink write, never the record or the event, so transports keep flowing.\n * - **Leveled gate.** A record whose {@link LogLevel} is below the logger's `level` threshold\n * is dropped entirely — no record built past the level check, no event, no retention, no\n * write (see {@link meetsLevel}).\n * - **Bounded retention.** Accepted records accrue in a ring capped at `limit` (default\n * {@link DEFAULT_LOG_LIMIT}); the oldest is dropped when full. `entries()` returns a copy,\n * oldest first; `clear()` empties it. Never unbounded — retention is capped at `limit`.\n * - **Styled write, orthogonal to level.** The line ({@link formatRecord}) is colored through\n * the injected `styler` (the ANSI default, or a browser `%c` styler) — a level only\n * chooses a label color; styling is not a level. A disabled styler yields a plain line.\n * - **Snapshotted sink.** The default {@link createConsoleSink} writes to the `console`\n * methods captured at creation, so a later `Capture` patching `console` can't loop the\n * sink's output back into itself.\n *\n * @example\n * ```ts\n * const logger = new Logger({ name: 'http', level: 'info' })\n * logger.emitter.on('entry', (record) => archive(record)) // transport hook\n * logger.info('request', { method: 'GET', path: '/' }) // styled line to the console sink\n * logger.debug('verbose') // dropped — below the `info` threshold\n * logger.entries() // [the info record]\n * ```\n */\nexport class Logger implements LoggerInterface {\n\t// The push observation surface — owned, never inherited. The emitter isolates a\n\t// listener throw (routing it to the `error` handler), so a buggy transport can never\n\t// escape into a log call.\n\treadonly #emitter: Emitter<LoggerEventMap>\n\treadonly #level: LogLevel\n\treadonly #sink: SinkInterface\n\treadonly #styler: StylerInterface\n\treadonly #theme: Theme\n\treadonly #format: LogFormatFunction\n\treadonly #limit: number\n\treadonly #silent: boolean\n\t// The bounded retention ring — accepted records, oldest first, capped at #limit.\n\treadonly #entries: LogRecord[] = []\n\treadonly name?: string\n\n\tconstructor(options?: LoggerOptions) {\n\t\tthis.#emitter = new Emitter<LoggerEventMap>({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#level = options?.level ?? DEFAULT_LOG_LEVEL\n\t\tif (options?.name !== undefined) this.name = options.name\n\t\tthis.#sink = options?.sink ?? createConsoleSink()\n\t\tthis.#styler = options?.styler ?? createStyler()\n\t\tthis.#theme = options?.theme ?? DEFAULT_THEME\n\t\tthis.#format = options?.format ?? formatRecord\n\t\tthis.#limit = options?.limit ?? DEFAULT_LOG_LIMIT\n\t\tthis.#silent = options?.silent ?? false\n\t}\n\n\tget emitter(): EmitterInterface<LoggerEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget level(): LogLevel {\n\t\treturn this.#level\n\t}\n\n\tdebug(message: string, data?: Record<string, unknown>): void {\n\t\tthis.#log('debug', message, data)\n\t}\n\n\tinfo(message: string, data?: Record<string, unknown>): void {\n\t\tthis.#log('info', message, data)\n\t}\n\n\twarn(message: string, data?: Record<string, unknown>): void {\n\t\tthis.#log('warn', message, data)\n\t}\n\n\terror(message: string, data?: Record<string, unknown>): void {\n\t\tthis.#log('error', message, data)\n\t}\n\n\tentries(): readonly LogRecord[] {\n\t\treturn [...this.#entries]\n\t}\n\n\tclear(): void {\n\t\tthis.#entries.length = 0\n\t}\n\n\tdestroy(): void {\n\t\tthis.#entries.length = 0\n\t\tthis.#emitter.destroy()\n\t}\n\n\t// The single log path behind every level method: gate by severity, then for an accepted\n\t// record build it frozen, retain it (bounded), emit `entry` always, and write the styled\n\t// line unless silent. A dropped (below-threshold) record does nothing observable.\n\t#log(level: LogLevel, message: string, data: Record<string, unknown> | undefined): void {\n\t\tif (!meetsLevel(this.#level, level)) return\n\t\tconst record = this.#record(level, message, data)\n\t\tthis.#retain(record)\n\t\t// The transport seam — fires even when silent (silence suppresses only the write).\n\t\tthis.#emitter.emit('entry', record)\n\t\tif (this.#silent) return\n\t\t// Pass the level so a stream-aware sink (the default console sink, the TTY sink)\n\t\t// can route error/warn to the right stream; a plain sink ignores it.\n\t\tthis.#sink.write(this.#format(record, this.#styler, this.#theme), level)\n\t}\n\n\t// Build the immutable, serializable record — `name` / `data` omitted when absent so the\n\t// frozen value carries only what was supplied. Frozen so a consumer (or transport) can\n\t// never mutate it after the fact.\n\t#record(level: LogLevel, message: string, data: Record<string, unknown> | undefined): LogRecord {\n\t\treturn Object.freeze({\n\t\t\tlevel,\n\t\t\tmessage,\n\t\t\ttime: Date.now(),\n\t\t\t...(this.name === undefined ? {} : { name: this.name }),\n\t\t\t...(data === undefined ? {} : { data: Object.freeze({ ...data }) }),\n\t\t})\n\t}\n\n\t// Push onto the bounded ring, evicting the oldest when at capacity — the retention stays\n\t// capped at #limit, never growing without bound.\n\t#retain(record: LogRecord): void {\n\t\tthis.#entries.push(record)\n\t\tif (this.#entries.length > this.#limit) this.#entries.shift()\n\t}\n}\n","import type {\n\tLoggerInterface,\n\tLoggerManagerInterface,\n\tLoggerManagerOptions,\n\tLoggerOptions,\n} from '../types.js'\nimport { isArray } from '@orkestrel/contract'\nimport { Logger } from './Logger.js'\n\n/**\n * Implements an event-free registry of named {@link Logger}s plus a convenience fan-out — the\n * manager over the logging layer (a registry, never observable itself; each {@link Logger}\n * owns its own `emitter`).\n *\n * @remarks\n * - **Registry.** Loggers live in an insertion-ordered `Map` keyed by `name`.\n * `register(name, options?)` mints a {@link Logger} named `name` — the manager's default\n * `level` / `sink` / `styler` / `theme` / `format` / `limit` / `silent` flow in unless\n * `options` overrides them\n * (`name` is always the registry key, so any `options.name` is ignored) — stores it (a\n * re-`register` of the same name overwrites, last write wins), and returns it. `count` is\n * the map size, `logger(name)` looks one up, `loggers()` lists them in insertion order.\n * - **Removal.** `remove()` clears all, `remove(name)` drops one (`true` if present),\n * `remove(names)` drops a batch (`true` only when every name was present; an empty list\n * succeeds vacuously). Every listed name is attempted whatever the result.\n * (Removal does not `destroy` the returned loggers — a caller still holding one keeps using\n * it; the manager stops tracking it.)\n * - **Fan-out.** `debug` / `info` / `warn` / `error(message, data?)` forward the one call to\n * every registered logger in insertion order; each gates / emits / writes per its own `level`\n * and `sink`. A formatter throw is a programmer error and propagates, stopping the remaining\n * loggers for that call. A fan-out over an empty registry is a no-op.\n * - **Event-free.** No emitter, no events — the manager is a pure registry; observability is\n * per-{@link Logger}.\n *\n * @example\n * ```ts\n * const manager = new LoggerManager({ level: 'warn' })\n * manager.register('http') // inherits the `warn` default\n * manager.register('db', { level: 'debug' }) // overrides to `debug`\n * manager.warn('slow', { ms: 900 }) // fans out to both loggers\n * manager.count // 2\n * ```\n */\nexport class LoggerManager implements LoggerManagerInterface {\n\treadonly #loggers = new Map<string, LoggerInterface>()\n\t// The defaults flowed into every logger `register` mints (a per-register override wins).\n\treadonly #level: LoggerManagerOptions['level']\n\treadonly #sink: LoggerManagerOptions['sink']\n\treadonly #styler: LoggerManagerOptions['styler']\n\treadonly #theme: LoggerManagerOptions['theme']\n\treadonly #format: LoggerManagerOptions['format']\n\treadonly #limit: LoggerManagerOptions['limit']\n\treadonly #silent: LoggerManagerOptions['silent']\n\n\tconstructor(options?: LoggerManagerOptions) {\n\t\tthis.#level = options?.level\n\t\tthis.#sink = options?.sink\n\t\tthis.#styler = options?.styler\n\t\tthis.#theme = options?.theme\n\t\tthis.#format = options?.format\n\t\tthis.#limit = options?.limit\n\t\tthis.#silent = options?.silent\n\t}\n\n\tget count(): number {\n\t\treturn this.#loggers.size\n\t}\n\n\tregister(name: string, options?: LoggerOptions): LoggerInterface {\n\t\t// The manager's defaults flow in first; the per-register `options` override them; `name`\n\t\t// is forced last so it always keys the registry (an `options.name` can't desync the key).\n\t\tconst logger = new Logger({\n\t\t\t...(this.#level !== undefined ? { level: this.#level } : {}),\n\t\t\t...(this.#sink !== undefined ? { sink: this.#sink } : {}),\n\t\t\t...(this.#styler !== undefined ? { styler: this.#styler } : {}),\n\t\t\t...(this.#theme !== undefined ? { theme: this.#theme } : {}),\n\t\t\t...(this.#format !== undefined ? { format: this.#format } : {}),\n\t\t\t...(this.#limit !== undefined ? { limit: this.#limit } : {}),\n\t\t\t...(this.#silent !== undefined ? { silent: this.#silent } : {}),\n\t\t\t...options,\n\t\t\tname,\n\t\t})\n\t\tthis.#loggers.set(name, logger)\n\t\treturn logger\n\t}\n\n\tlogger(name: string): LoggerInterface | undefined {\n\t\treturn this.#loggers.get(name)\n\t}\n\n\tloggers(): readonly LoggerInterface[] {\n\t\treturn [...this.#loggers.values()]\n\t}\n\n\tdebug(message: string, data?: Record<string, unknown>): void {\n\t\tfor (const logger of this.#loggers.values()) logger.debug(message, data)\n\t}\n\n\tinfo(message: string, data?: Record<string, unknown>): void {\n\t\tfor (const logger of this.#loggers.values()) logger.info(message, data)\n\t}\n\n\twarn(message: string, data?: Record<string, unknown>): void {\n\t\tfor (const logger of this.#loggers.values()) logger.warn(message, data)\n\t}\n\n\terror(message: string, data?: Record<string, unknown>): void {\n\t\tfor (const logger of this.#loggers.values()) logger.error(message, data)\n\t}\n\n\t// all / one / batch under one verb — the array overload declared first by the project\n\t// convention (a `name` is a string, never an array, so the two never overlap).\n\tremove(names: readonly string[]): boolean\n\tremove(name: string): boolean\n\tremove(): void\n\tremove(names?: string | readonly string[]): void | boolean {\n\t\tif (names === undefined) {\n\t\t\tthis.#loggers.clear()\n\t\t\treturn\n\t\t}\n\t\tif (isArray(names)) {\n\t\t\t// Every name is attempted, and the batch succeeds only when every one was present — an\n\t\t\t// empty list has no failing member, so it succeeds vacuously.\n\t\t\tlet removed = true\n\t\t\tfor (const name of names) {\n\t\t\t\tif (!this.#loggers.delete(name)) removed = false\n\t\t\t}\n\t\t\treturn removed\n\t\t}\n\t\treturn this.#loggers.delete(names)\n\t}\n}\n","import type {\n\tBoxOptions,\n\tReporterInterface,\n\tReporterOptions,\n\tSinkInterface,\n\tStatusLevel,\n\tStepPosition,\n\tStylerInterface,\n\tTableOptions,\n\tTheme,\n\tTreeOptions,\n} from './types.js'\nimport { DEFAULT_THEME, DEFAULT_WIDTH } from './constants.js'\nimport { createConsoleSink, createStyler } from './factories.js'\nimport { formatDuration, renderBox, renderSeparator, renderTable, renderTree } from './helpers.js'\n\n/**\n * Implements a lean, event-free narrative reporter — the composable verb set for human /\n * build-run output. Each verb formats its line through the shared {@link StylerInterface} and\n * the pure layout renderers ({@link renderSeparator} / {@link renderBox} / {@link renderTable}\n * / {@link renderTree}) and writes it to a {@link SinkInterface} — the same styler + sink\n * substrate the logger uses, never a second colorizer.\n *\n * @remarks\n * - **A small set, not a grab-bag.** `section` / `step` / `timing` / `status` / `table` /\n * `tree` / `box` / `line` / `blank`. No spinner / bar (the animation chunk), no buffering /\n * capture (the capture chunk), no level retention (the logger). Format and write, nothing more.\n * - **`status` is a narrative outcome, not a log level.** Its {@link StatusLevel} (`success` /\n * `error` / `warn` / `info`) is distinct from {@link import('./types.js').LogLevel}: an icon\n * supplied theme status icon + style, with `error` routed to the sink's\n * error stream (the `level` hint forwarded to {@link SinkInterface.write}) — there is no\n * gating and no severity ordering.\n * - **Width-aware.** `section` (and a `box` with no explicit `width`) lay out to the reporter's\n * `#width`; the renderers measure on visible width (ANSI-aware), so styled content aligns.\n * - **Event-free.** No `#emitter` — a pure formatting front-end with no observable\n * lifecycle (like the renderers and `Scheduler`). It is reusable and holds no per-call state.\n *\n * @example\n * ```ts\n * const reporter = new Reporter()\n * reporter.section('Build')\n * reporter.step('compiling', { index: 1, total: 3 }) // [1/3] compiling\n * reporter.timing('bundle', 1234) // bundle … 1.23s\n * reporter.status('success', 'done') // ✔ done\n * ```\n */\nexport class Reporter implements ReporterInterface {\n\treadonly #sink: SinkInterface\n\treadonly #styler: StylerInterface\n\treadonly #theme: Theme\n\treadonly #width: number\n\n\tconstructor(options?: ReporterOptions) {\n\t\tthis.#sink = options?.sink ?? createConsoleSink()\n\t\tthis.#styler = options?.styler ?? createStyler()\n\t\tthis.#theme = options?.theme ?? DEFAULT_THEME\n\t\tthis.#width = options?.width ?? DEFAULT_WIDTH\n\t}\n\n\tsection(title: string): void {\n\t\t// The theme's chrome role styles the rule and title through the shared styler.\n\t\tthis.#sink.write(\n\t\t\trenderSeparator({\n\t\t\t\ttitle,\n\t\t\t\twidth: this.#width,\n\t\t\t\tstyler: this.#styler,\n\t\t\t\tstyle: this.#theme.chrome,\n\t\t\t}),\n\t\t)\n\t}\n\n\tstep(message: string, position?: StepPosition): void {\n\t\tconst prefix =\n\t\t\tposition === undefined\n\t\t\t\t? ''\n\t\t\t\t: `${this.#styler.render(this.#theme.accent, `[${position.index}/${position.total}]`)} `\n\t\tthis.#sink.write(`${prefix}${message}`)\n\t}\n\n\ttiming(label: string, ms: number): void {\n\t\tthis.#sink.write(\n\t\t\t`${label} ${this.#styler.render(this.#theme.chrome, `… ${formatDuration(ms)}`)}`,\n\t\t)\n\t}\n\n\tstatus(level: StatusLevel, message: string): void {\n\t\tconst status = this.#theme.statuses[level]\n\t\tconst line = `${this.#styler.render(status.style, status.icon)} ${this.#styler.render(status.style, message)}`\n\t\t// `error` is the one outcome that routes to the sink's error stream; the rest write plain.\n\t\tthis.#sink.write(line, level === 'error' ? 'error' : undefined)\n\t}\n\n\ttable(options: TableOptions): void {\n\t\tthis.#sink.write(renderTable(this.#resolveStyle(options)))\n\t}\n\n\ttree(options: TreeOptions): void {\n\t\tthis.#sink.write(renderTree(this.#resolveStyle(options)))\n\t}\n\n\tbox(options: BoxOptions): void {\n\t\t// Default the box width here; explicit options win.\n\t\tthis.#sink.write(renderBox(this.#resolveStyle({ width: this.#width, ...options })))\n\t}\n\n\tline(text: string): void {\n\t\tthis.#sink.write(text)\n\t}\n\n\tblank(count = 1): void {\n\t\tfor (let index = 0; index < count; index += 1) this.#sink.write('')\n\t}\n\n\t// Use theme chrome only when the caller supplied neither half of the styling decision. The\n\t// reporter's base styler still renders a caller's by-value style when no caller styler exists.\n\t#resolveStyle<T extends BoxOptions | TableOptions | TreeOptions>(options: T): T {\n\t\treturn {\n\t\t\tstyler: this.#styler,\n\t\t\t...(options.styler === undefined && options.style === undefined\n\t\t\t\t? { style: this.#theme.chrome }\n\t\t\t\t: {}),\n\t\t\t...options,\n\t\t}\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tSinkInterface,\n\tSpinnerEventMap,\n\tSpinnerInterface,\n\tSpinnerOptions,\n\tStylerInterface,\n\tTheme,\n} from './types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { DEFAULT_SPINNER_INTERVAL, DEFAULT_THEME, SPINNER_FRAMES } from './constants.js'\nimport { createConsoleSink, createStyler } from './factories.js'\n\n/**\n * Implements a self-driving, observable activity spinner — a glyph cycle that advances on a\n * periodic timer, writing each `\\r` + frame line to its {@link SinkInterface} and emitting it on\n * `frame`. The timer is always cleared on an outcome, so the spinner is leak-free.\n *\n * @remarks\n * The leading `\\r` is what an overwrite-capable sink (the TTY sink) redraws on; a plain sink\n * degrades to a fresh, non-overwriting line — the line-overwrite is the sink's job, never the\n * spinner's. Universal — `setInterval` + the one {@link StylerInterface} + the one\n * {@link SinkInterface}, no `node:*`, no `process.stdout`.\n *\n * - **Self-driving but deterministically testable.** `start()` arms a `setInterval` that calls\n * {@link tick} each `interval`; each {@link tick} builds the styled `glyph + message` line for the\n * current frame, emits it on `frame`, writes `'\\r' + line` to the sink, then advances the frame\n * index (wrapping). A test drives frames by calling {@link tick} directly, or arms a real short\n * `interval` and proves the timer arms / clears through the sink it writes to.\n * - **Leak-free timer.** The interval is always cleared on {@link succeed} / {@link fail} /\n * {@link stop} / {@link destroy} — `#handle` is the single source of `active`, set on arm and unset\n * on clear, so a spinner never leaks a running interval.\n * - **Idempotent `start`.** A {@link start} while already `active` is a no-op (it never arms a second\n * timer).\n * - **Outcome lines.** {@link succeed} / {@link fail} clear the timer then write + emit a final line —\n * the supplied theme status icon + style (`✔` / `✖` by default) + the message — terminated\n * by a newline (the activity is over; the line is committed, not overwritten). {@link fail} routes to\n * the sink's error stream.\n * - **Lifecycle.** {@link stop} clears the timer and leaves the current line; {@link destroy}\n * stops then destroys the emitter. {@link update} swaps the message and re-renders immediately when\n * `active`.\n *\n * @example\n * ```ts\n * const spinner = new Spinner({ message: 'building' })\n * spinner.start() // arms the timer, paints the first frame to the sink\n * spinner.update('bundling') // message changes, re-rendered at once\n * spinner.succeed('built in 1.2s') // ✔ built in 1.2s — timer cleared, line committed\n * ```\n */\nexport class Spinner implements SpinnerInterface {\n\t// The push observation surface — owned, never inherited. The emitter isolates a listener\n\t// throw (routing it to the `error` handler), so a buggy `frame` listener can never escape the tick.\n\treadonly #emitter: Emitter<SpinnerEventMap>\n\treadonly #frames: readonly string[]\n\treadonly #interval: number\n\treadonly #sink: SinkInterface\n\treadonly #styler: StylerInterface\n\treadonly #theme: Theme\n\t#message: string\n\t// The running interval handle — undefined while inactive. Its presence is `active`; the timer is\n\t// armed in start() and cleared everywhere the spinner stops, so it is never leaked.\n\t#handle: ReturnType<typeof setInterval> | undefined\n\t// The current frame index into #frames — advanced (wrapping) after each rendered tick.\n\t#index = 0\n\n\tconstructor(options?: SpinnerOptions) {\n\t\tthis.#emitter = new Emitter<SpinnerEventMap>({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\t// An explicitly-empty `frames` array falls back to the default cycle too — an empty cycle\n\t\t// would divide by zero on every wrap in tick().\n\t\tconst frames = options?.frames ?? SPINNER_FRAMES\n\t\tthis.#frames = frames.length === 0 ? SPINNER_FRAMES : frames\n\t\tthis.#interval = options?.interval ?? DEFAULT_SPINNER_INTERVAL\n\t\tthis.#sink = options?.sink ?? createConsoleSink()\n\t\tthis.#styler = options?.styler ?? createStyler()\n\t\tthis.#theme = options?.theme ?? DEFAULT_THEME\n\t\tthis.#message = options?.message ?? ''\n\t}\n\n\tget emitter(): EmitterInterface<SpinnerEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget active(): boolean {\n\t\treturn this.#handle !== undefined\n\t}\n\n\tget message(): string {\n\t\treturn this.#message\n\t}\n\n\tstart(): void {\n\t\t// Idempotent — never arm a second interval over a running one (that would leak the first handle).\n\t\tif (this.#handle !== undefined) return\n\t\tthis.#handle = setInterval(() => this.tick(), this.#interval)\n\t\tthis.#emitter.emit('start')\n\t\t// Paint the first frame immediately so the spinner shows at once, not only after one interval.\n\t\tthis.tick()\n\t}\n\n\ttick(): void {\n\t\t// Render the current frame, then advance — so the first tick() shows frame 0.\n\t\tthis.#paint(this.#line())\n\t\tthis.#index = (this.#index + 1) % this.#frames.length\n\t}\n\n\tupdate(message: string): void {\n\t\tthis.#message = message\n\t\t// Re-render the current frame (no advance) so the new message shows without waiting for a tick.\n\t\tif (this.#handle !== undefined) this.#paint(this.#line())\n\t}\n\n\tsucceed(message?: string): void {\n\t\tthis.#finish('success', message)\n\t}\n\n\tfail(message?: string): void {\n\t\tthis.#finish('error', message)\n\t}\n\n\tstop(): void {\n\t\t// Clear the timer and leave the current line untouched — a no-op when not active.\n\t\tif (this.#handle === undefined) return\n\t\tclearInterval(this.#handle)\n\t\tthis.#handle = undefined\n\t\tthis.#emitter.emit('stop')\n\t}\n\n\tdestroy(): void {\n\t\tthis.stop()\n\t\tthis.#emitter.destroy()\n\t}\n\n\t// Stop the timer (emitting `stop` when it was running) and write + emit the final outcome line —\n\t// the status icon + message, colored through the styler, terminated by a newline (the activity is\n\t// over, so the line is committed, not overwritten). `error` routes to the sink's error stream. The\n\t// shared body of succeed()/fail() — the single home for the outcome path.\n\t#finish(level: 'success' | 'error', message?: string): void {\n\t\tthis.stop()\n\t\tconst text = message ?? this.#message\n\t\tif (message !== undefined) this.#message = message\n\t\tconst status = this.#theme.statuses[level]\n\t\tconst line = `${this.#styler.render(status.style, status.icon)} ${this.#styler.render(status.style, text)}`\n\t\tthis.#emitter.emit('frame', line)\n\t\t// The trailing newline commits the line; `error` is the one outcome routed to the error stream.\n\t\tthis.#sink.write(`\\r${line}\\n`, level === 'error' ? 'error' : undefined)\n\t}\n\n\t// Build the styled frame line for the current index — the colored spinner glyph, then the message\n\t// when present (a bare glyph otherwise). Kept off the public surface (a render fragment).\n\t#line(): string {\n\t\tconst glyph = this.#styler.render(this.#theme.accent, this.#frames[this.#index] ?? '')\n\t\treturn this.#message === '' ? glyph : `${glyph} ${this.#message}`\n\t}\n\n\t// Emit the frame line and write it to the sink with the leading `\\r` an overwrite-capable sink\n\t// redraws on — the same line both places, the `\\r` added only on the write (the event carries the\n\t// bare line). The single per-tick render path shared by tick() and update().\n\t#paint(line: string): void {\n\t\tthis.#emitter.emit('frame', line)\n\t\tthis.#sink.write(`\\r${line}`)\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tProgressEventMap,\n\tProgressInterface,\n\tProgressOptions,\n\tProgressReport,\n\tSinkInterface,\n\tStylerInterface,\n\tTheme,\n} from './types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { DEFAULT_BAR_WIDTH, DEFAULT_THEME } from './constants.js'\nimport { createConsoleSink, createStyler } from './factories.js'\nimport { renderBar } from './helpers.js'\n\n/**\n * Implements an update-driven, observable progress bar — {@link update} recomputes the bar through\n * {@link renderBar}, writes `\\r` + bar to its {@link SinkInterface}, and emits the `{ current,\n * total }` on `update`. No self-timer, unlike {@link import('./Spinner.js').Spinner} — the caller\n * drives it.\n *\n * @remarks\n * The leading `\\r` is what an overwrite-capable sink (the TTY sink) redraws on; a plain sink\n * degrades to a fresh, non-overwriting line — the line-overwrite is the sink's job. Universal —\n * the one {@link StylerInterface} + the one {@link SinkInterface}, no `node:*`, no\n * `process.stdout`.\n *\n * - **Update-driven.** Each {@link update} clamps `current` to `[0, total]`, renders the bar (filled\n * to `current / total`, with the trailing `percent (current/total)` + message) through {@link renderBar},\n * emits `update`, and writes `'\\r' + bar`. Progress advances only when the caller reports it.\n * - **Outcome lines.** {@link succeed} renders a full bar (`current = total`) + message, terminated by\n * a newline, emits a final `update` then `succeed`, and marks `succeeded`. {@link fail} renders the\n * bar at its current fill + message + newline and routes to the sink's error stream (no `succeed` —\n * the work did not finish). Both are terminal: a later {@link update} is ignored once `active` is false.\n * - **Bounded.** `current` is always clamped to `[0, total]`; {@link succeeded} reports whether\n * {@link succeed} has run; {@link active} is `true` until a {@link succeed} / {@link fail}.\n * - **Lifecycle.** {@link destroy} destroys the emitter (there is no timer to clear).\n *\n * @example\n * ```ts\n * const progress = new Progress({ total: 100, message: 'downloading' })\n * progress.update(40) // ████████████░░░░░░░░░░░░░░░░░░ 40% (40/100) downloading\n * progress.update(80, 'almost there')\n * progress.succeed('done') // a full bar, committed with a newline\n * ```\n */\nexport class Progress implements ProgressInterface {\n\t// The push observation surface — owned, never inherited. The emitter isolates a listener\n\t// throw (routing it to the `error` handler), so a buggy `update` listener can never escape a report.\n\treadonly #emitter: Emitter<ProgressEventMap>\n\treadonly #total: number\n\treadonly #width: number\n\treadonly #fill: ProgressOptions['fill']\n\treadonly #empty: ProgressOptions['empty']\n\treadonly #sink: SinkInterface\n\treadonly #styler: StylerInterface\n\treadonly #theme: Theme\n\t#message: string\n\t#current = 0\n\t#active = true\n\t#succeeded = false\n\n\tconstructor(options: ProgressOptions) {\n\t\tthis.#emitter = new Emitter<ProgressEventMap>({\n\t\t\t...(options.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#total = options.total\n\t\tthis.#width = options.width ?? DEFAULT_BAR_WIDTH\n\t\tthis.#fill = options.fill\n\t\tthis.#empty = options.empty\n\t\tthis.#sink = options.sink ?? createConsoleSink()\n\t\tthis.#styler = options.styler ?? createStyler()\n\t\tthis.#theme = options.theme ?? DEFAULT_THEME\n\t\tthis.#message = options.message ?? ''\n\t}\n\n\tget emitter(): EmitterInterface<ProgressEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget active(): boolean {\n\t\treturn this.#active\n\t}\n\n\tget succeeded(): boolean {\n\t\treturn this.#succeeded\n\t}\n\n\tget current(): number {\n\t\treturn this.#current\n\t}\n\n\tget total(): number {\n\t\treturn this.#total\n\t}\n\n\tupdate(current: number, message?: string): void {\n\t\t// Terminal bars ignore further updates — a succeed()/fail() has committed the final line.\n\t\tif (!this.#active) return\n\t\tthis.#advance(current, message)\n\t\tthis.#paint(false)\n\t}\n\n\tsucceed(message?: string): void {\n\t\tif (!this.#active) return\n\t\t// Finish full — drive to `total`, commit the line, then signal the successful outcome.\n\t\tthis.#advance(this.#total, message)\n\t\tthis.#active = false\n\t\tthis.#succeeded = true\n\t\tthis.#paint(true)\n\t\tthis.#emitter.emit('succeed')\n\t}\n\n\tfail(message?: string): void {\n\t\tif (!this.#active) return\n\t\t// Finish at the current fill (the work stopped short) — commit to the error stream, no succeed.\n\t\t// #advance emits a final `update` at the current fill (identical current/total), same as succeed().\n\t\tthis.#advance(this.#current, message)\n\t\tthis.#active = false\n\t\tthis.#paint(true, 'error')\n\t}\n\n\tdestroy(): void {\n\t\tthis.#emitter.destroy()\n\t}\n\n\t// Clamp `current` into [0, total], adopt the optional message, and emit the `update` progress —\n\t// the shared state-advance behind update()/succeed(). The clamp keeps `current`\n\t// bounded regardless of the value the caller reports (an overrun saturates, a negative floors).\n\t#advance(current: number, message?: string): void {\n\t\tthis.#current = Math.max(0, Math.min(this.#total, current))\n\t\tif (message !== undefined) this.#message = message\n\t\tconst report: ProgressReport = { current: this.#current, total: this.#total }\n\t\tthis.#emitter.emit('update', report)\n\t}\n\n\t// Render the bar at the current state and write `\\r` + bar to the sink — the leading `\\r` an\n\t// overwrite-capable sink redraws on. `final` appends a newline that commits the line (a finished\n\t// bar is not overwritten); `level` routes a fail() write to the error stream. The single render\n\t// path shared by update()/succeed()/fail().\n\t#paint(final: boolean, level?: 'error'): void {\n\t\tconst bar = renderBar({\n\t\t\tcurrent: this.#current,\n\t\t\ttotal: this.#total,\n\t\t\twidth: this.#width,\n\t\t\t...(this.#fill === undefined ? {} : { fill: this.#fill }),\n\t\t\t...(this.#empty === undefined ? {} : { empty: this.#empty }),\n\t\t\tstyler: this.#styler,\n\t\t\tstyle: this.#theme.accent,\n\t\t})\n\t\tconst line = this.#message === '' ? bar : `${bar} ${this.#message}`\n\t\tthis.#sink.write(`\\r${line}${final ? '\\n' : ''}`, level)\n\t}\n}\n"],"mappings":"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"}
|