UNPKG

@steve02081504/virtual-console

Version:

A virtual console for capturing and manipulating terminal output.

211 lines (188 loc) 8.51 kB
/** * 浏览器和 Node.js 两端共用的类型定义。 * 请通过 `@steve02081504/virtual-console``@steve02081504/virtual-console/node` 导入, * 不要直接引用此文件。 */ /** * 所有环境下都会产生的日志级别(来自被代理的 console 方法) */ export type EntryLevel = 'log' | 'info' | 'warn' | 'error' | 'debug' /** * 捕获条目上 {@link LogEntry#level} 的语义值:`methodNameToLevel` 归一化后的结果。 * `console.trace` / `writeAs('trace')``debug`;Node `stdout`/`stderr``log` / `error`;其余字符串透传。 */ export type CapturedLogLevel = EntryLevel | (string & {}) /** * `writeAs(level, …)` 等方法可用的逻辑方法名(传入 `methodNameToLevel` 之前)。 * 与 {@link CapturedLogLevel} 不同:此处可出现 `stdout``stderr``trace` 等键名。 */ export type WriteAsLevelArg = | EntryLevel | 'dir' | 'trace' | 'stdout' | 'stderr' | (string & {}) /** * 调用栈帧信息(Node.js 和浏览器均支持;file:// URL 在 Node.js 中自动解析为绝对路径) */ export interface StackFrame { /** 函数名称 */ functionName: string /** 文件路径 */ filePath: string /** 行号 */ line: number /** 列号 */ column: number /** 原始栈帧字符串 */ raw: string } /** 惰性展开占位(`ref` 由宿主进程内注册;空字符串表示不可展开) */ export interface ArgSnapshotTruncated { kind: 'truncated' ref: string label?: string } /** * `serializeArgSnapshot` / `toSegments` 产生的 JSON 可传输快照(含 `truncated`)。 * - `kind: 'Error'`**`name`****`message`****`stack`**(由 `parseErrorStack(error)` 得到的帧数组,平铺字段与 {@link StackFrame} 一致;**不**存原始 `error.stack` 字符串);另有 **`entries`** 承载其它自有枚举属性。 * - `kind: 'Date'`**`value`**`Date#getTime()` 毫秒数(无效 Date 为 **`NaN`**)。经 `JSON.stringify` 往返后无效日期的 `NaN` 变为 **`null`**;渲染时格式化为与 Node `util.inspect` 一致的 ISO 字符串或 **`Invalid Date`****不**在快照里存 ISO 字符串)。 */ export type ArgSnapshot = Record<string, unknown> | ArgSnapshotTruncated /** * 结构化日志片段(与 `LogEntry#toSegments()` 一致,可 JSON 传输) */ /** `console.dir` 第二参数的 JSON 可传输子集(与 Node `util.inspect` 选项名对齐)。 */ export interface DirOptionsPayload { /** 对象展开深度 */ depth?: number /** 是否着色(对应渲染管线中的 `colorize`*/ colors?: boolean } /** * 结构化日志片段:仅 `text` / `css` / `value` / `trace` 四类(可 JSON 传输)。 * - `text`:原始终端字节串(可含 CSI/OSC8);换行用 `\n` 字符表达。 * - `css``%c` 样式串;`renderAnsi` 映射颜色(真彩色)、粗/斜/划/删、`opacity`/`lighter`/半透明色等(含 SGR dim);HTML 侧用 `span` 作用域。 * - `value``ArgSnapshot` 树,渲染时格式化为 plain/ANSI/HTML(不再预烘焙 `ansiText`)。 * - `trace`:已解析的 {@link StackFrame} 数组(与 `LogEntry#stack` 同源,不再嵌套 ArgSnapshot)。 */ export type LogSegment = | { kind: 'text'; text: string } | { kind: 'css'; css: string } | { kind: 'value'; snapshot: ArgSnapshot; dirOptions?: DirOptionsPayload } | { kind: 'trace'; stack: StackFrame[] } /** 单条日志条目接口 */ export interface LogEntry { /** 经 `methodNameToLevel` 归一化后的语义级别 */ level: CapturedLogLevel /** 对应的 console / 流方法名(如 `log``trace`、Node 下 `stdout`*/ method: string /** 原始参数数组(`stdout` / `stderr` 条目为单元素文本数组) */ readonly args: unknown[] /** `freshLine` 主 id(非 freshLine 条目可为空) */ readonly id?: string /** 调用栈帧数组(两端均支持) */ stack: StackFrame[] /** 日志记录时的 Unix 时间戳(毫秒) */ timestamp: number /** 展示来源:优先片段中首个 Error 的栈帧,否则为捕获调用栈中第一条 */ readonly primaryCallsite: StackFrame | null /** 宿主是否允许 ANSI(影响 `value`/`trace` 等着色与 OSC8) */ supportsAnsi: boolean /** Node `stdout`/`stderr`:合并后的原始流文本;非流条目无此字段 */ text?: string /** 终端 ANSI 串(流条目为原始合并文本) */ toString(): string /** 无 ANSI 的纯文本 */ toPlainText(): string /** 由 `toSegments` 渲染的 HTML */ toHtml(): string /** 参数快照,深度默认与内置序列化一致 */ serializeArgs(maxDepth?: number): ArgSnapshot[] /** 结构化片段,便于前端按需映射 DOM */ toSegments(): LogSegment[] /** JSON 传输视图(默认与 wire 载荷字段对齐) */ toJSON(): Record<string, unknown> } /** 按宿主环境细分的日志条目(覆盖 `level` 联合) */ export type BaseLogEntry<L extends string = string> = Omit<LogEntry, 'level'> & { level: L } /** * 虚拟控制台配置选项基础接口 */ export interface BaseVirtualConsoleOptions<VC = unknown, L extends string = EntryLevel> { /** 如果为 true,则在捕获输出的同时,也调用底层控制台进行实际输出。默认 false */ realConsoleOutput?: boolean /** * 若为 true,则捕获输出并写入 `outputEntries`(及聚合的 `outputs` / `outputsHtml`); * 为 false 时不追加条目(`realConsoleOutput` 等旁路仍可按配置执行)。默认 true */ recordOutput?: boolean /** * `realConsoleOutput` 的透传目标,以及构造时未指定时的 ANSI 继承来源。 * 未指定时由各平台在运行时解析(Node 使用当前上下文的活动控制台,浏览器同理)。 * 设为另一个 `VirtualConsole` 时,会自动继承其 `supportsAnsi` 设置。 */ baseConsole?: VC | Console /** 最多保留的日志条目数量,超出后自动丢弃最旧的条目。默认 Infinity */ maxLogEntries?: number } /** * `getGlobalConsoleResolver()` 返回的三元组:取当前活动控制台、绑定活动控制台、在指定控制台上下文中运行回调。 */ export interface GlobalConsoleRouting<VC = unknown> { /** 返回当前 `AsyncLocalStorage` / 平台模拟上下文中应激活的 `VirtualConsole` */ getActiveConsole: () => VC /** 将指定实例设为当前上下文的活动控制台 */ setActiveConsole: (value: VC) => void /** 在以指定实例为活动控制台的新上下文中执行回调,返回回调结果的 Promise */ runWithActiveConsole: <T>(value: VC, fn: () => T | Promise<T>) => Promise<T> } /** 下列声明的实现分布在 Node / 浏览器入口 `.mjs`,此处集中声明以供平台 `.d.mts` 重导出。 */ export declare const DEFAULT_SNAPSHOT_DEPTH: number export declare function serializeArgSnapshot( value: unknown, options?: { maxDepth?: number; expansionScope?: object | null } ): ArgSnapshot export declare function createExpansionScope(entry: object): { allocRef(target: object): string } export declare function expandSnapshotRef( ref: string, maxDepth?: number ): { ok: true; snapshot: ArgSnapshot } | { ok: false; error: string } export declare function getStackInfo(leadingLinesToSkip?: number): StackFrame[] export declare function parseErrorStack(error: unknown, skipNum?: number): StackFrame[] export declare function trimLeadingRuntimeInternalFrames(frames: StackFrame[]): StackFrame[] export declare function newLogEntry(options: object): LogEntry export declare function renderPlain( segments: LogSegment[], options?: { indent?: string; maxDepth?: number } ): string export declare function renderAnsi( segments: LogSegment[], options?: { colorize?: boolean; omitPrintfCss?: boolean; indent?: string; maxDepth?: number } ): string export declare function renderHtml(segments: LogSegment[], options?: Record<string, unknown>): string export declare function stripTerminalDecorations(text: string): string export declare function stripOscTitleSequences(text: string): string export declare function escapeHtml(str: string): string export declare function collectPrintfFormatParts( format: string, args: unknown[], startArgIndex?: number ): { parts: Array< | { kind: 'literal'; text: string } | { kind: 'arg'; spec: string; value: unknown } | { kind: 'missingSpec'; spec: string } > nextArgIndex: number } export declare function buildArgsSegments( args: unknown[], expansionScope?: object | null, snapshotDepth?: number ): LogSegment[]