@loglayer/transport-pretty-terminal 4.1.8 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -20
- package/dist/index.d.mts +9 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["Utils.indent","Utils.getMaxIndexLength","pairs: string[]","headerContent: string[]","footerContent: string[]","mainContent: string[]","prettyjson\n .render","Database","moonlight: PrettyTerminalTheme","sunlight: PrettyTerminalTheme","neon: PrettyTerminalTheme","nature: PrettyTerminalTheme","pastel: PrettyTerminalTheme","renderer: LogRenderer","storage: LogStorage","LoggerlessTransport","simpleViewConfig: Required<ViewConfig>","detailedViewConfig: Required<DetailedViewConfig>"],"sources":["../src/vendor/utils.js","../src/vendor/prettyjson.js","../src/views/utils.ts","../src/views/DetailView.ts","../src/views/SelectionView.ts","../src/views/SimpleView.ts","../src/LogRenderer.ts","../src/LogStorage.ts","../src/themes.ts","../src/UIManager.ts","../src/PrettyTerminalTransport.ts","../src/index.ts"],"sourcesContent":["/**\n * Creates a string with the same length as `numSpaces` parameter\n **/\nexport function indent(numSpaces) {\n return new Array(numSpaces + 1).join(\" \");\n}\n\n/**\n * Gets the string length of the longer index in a hash\n **/\nexport function getMaxIndexLength(input) {\n var maxWidth = 0;\n\n Object.getOwnPropertyNames(input).forEach((key) => {\n // Skip undefined values.\n if (input[key] === undefined) {\n return;\n }\n\n maxWidth = Math.max(maxWidth, key.length);\n });\n return maxWidth;\n}\n\nexport function isIsoStringDate(isoString) {\n if (typeof isoString !== \"string\") {\n return false;\n }\n // More flexible regex that handles:\n // - Optional milliseconds\n // - Optional timezone offset or Z\n // - Optional T separator (space also valid)\n if (!/^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?$/.test(isoString)) {\n return false;\n }\n const testDate = new Date(isoString);\n return !Number.isNaN(testDate.getTime());\n}\n","// @ts-nocheck\nimport chalk from \"chalk\";\nimport * as Utils from \"./utils.js\";\nimport { isIsoStringDate } from \"./utils.js\";\n\nconst conflictChars = /[^\\w\\s\\n\\r\\v\\t.,]/i;\n\n// Helper function to detect if an object should be printed or ignored\nconst isPrintable = (input, options) => input !== undefined || options.renderUndefined;\n\n// Helper function to detect if an object can be directly serializable\nconst isSerializable = (input, onlyPrimitives, options) => {\n if (\n typeof input === \"boolean\" ||\n typeof input === \"number\" ||\n typeof input === \"function\" ||\n input === null ||\n input === undefined ||\n input instanceof Date\n ) {\n return true;\n }\n if (typeof input === \"string\" && input.indexOf(\"\\n\") === -1) {\n return true;\n }\n\n if (options.inlineArrays && !onlyPrimitives) {\n if (Array.isArray(input) && isSerializable(input[0], true, options)) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * @param {Function} colorFn\n * @param {PrettyJSONOptions} options\n */\nconst getColorRenderer = (colorFn, options) => {\n if (options.noColor) {\n return (text) => text;\n }\n\n if (typeof colorFn !== \"function\") {\n return (text) => text;\n }\n\n return colorFn;\n};\n\nconst addColorToData = (input, options) => {\n if (options.noColor) {\n return input;\n }\n\n if (input instanceof Date) {\n return getColorRenderer(options.dateColor, options)(input.toISOString());\n }\n if (typeof input === \"string\") {\n if (isIsoStringDate(input)) {\n return getColorRenderer(options.dateColor, options)(input);\n }\n // Print strings in regular terminal color\n return getColorRenderer(options.stringColor, options)(input);\n }\n\n const sInput = `${input}`;\n\n if (typeof input === \"boolean\") {\n return getColorRenderer(options.booleanColor, options)(sInput);\n }\n if (input === null || input === undefined) {\n return getColorRenderer(options.nullUndefinedColor, options)(sInput);\n }\n if (typeof input === \"number\") {\n if (input >= 0) {\n return getColorRenderer(options.positiveNumberColor, options)(sInput);\n }\n return getColorRenderer(options.negativeNumberColor, options)(sInput);\n }\n if (typeof input === \"function\") {\n return \"function() {}\";\n }\n\n if (Array.isArray(input)) {\n return input.join(\", \");\n }\n\n return sInput;\n};\n\nconst colorMultilineString = (options, line) => getColorRenderer(options.multilineStringColor, options)(line);\n\nconst indentLines = (string, spaces, options) => {\n let lines = string.split(\"\\n\");\n lines = lines.map((line) => Utils.indent(spaces) + colorMultilineString(options, line));\n return lines.join(\"\\n\");\n};\n\nconst renderToArray = (data, options, indentation) => {\n if (typeof data === \"string\" && data.match(conflictChars) && options.escape) {\n data = JSON.stringify(data);\n }\n\n if (!isPrintable(data, options)) {\n return [];\n }\n\n if (isSerializable(data, false, options)) {\n return [Utils.indent(indentation) + addColorToData(data, options)];\n }\n\n // Unserializable string means it's multiline\n if (typeof data === \"string\") {\n return [\n Utils.indent(indentation) + colorMultilineString(options, '\"\"\"'),\n indentLines(data, indentation + options.defaultIndentation, options),\n Utils.indent(indentation) + colorMultilineString(options, '\"\"\"'),\n ];\n }\n\n if (Array.isArray(data)) {\n // If the array is empty, render the `emptyArrayMsg`\n if (data.length === 0) {\n return [Utils.indent(indentation) + options.emptyArrayMsg];\n }\n\n // If arrays should be collapsed and there's data, show [...]\n if (options.collapseArrays && data.length > 0) {\n return [`${Utils.indent(indentation)}[... ${data.length} items]`];\n }\n\n const outputArray = [];\n\n data.forEach((element) => {\n if (!isPrintable(element, options)) {\n return;\n }\n\n // Prepend the dash at the beginning of each array's element line\n let line = \"- \";\n line = getColorRenderer(options.dashColor, options)(line);\n line = Utils.indent(indentation) + line;\n\n // If the element of the array is a string, bool, number, or null\n // render it in the same line\n if (isSerializable(element, false, options)) {\n line += renderToArray(element, options, 0)[0];\n outputArray.push(line);\n\n // If the element is an array or object, render it in next line\n } else {\n outputArray.push(line);\n outputArray.push.apply(outputArray, renderToArray(element, options, indentation + options.defaultIndentation));\n }\n });\n\n return outputArray;\n }\n\n if (data instanceof Error) {\n return renderToArray(\n {\n message: data.message,\n stack: data.stack.split(\"\\n\"),\n },\n options,\n indentation,\n );\n }\n\n // If values alignment is enabled, get the size of the longest index\n // to align all the values\n const maxIndexLength = options.noAlign ? 0 : Utils.getMaxIndexLength(data);\n let key;\n const output = [];\n\n Object.getOwnPropertyNames(data).forEach((i) => {\n if (!isPrintable(data[i], options)) {\n return;\n }\n\n // Prepend the index at the beginning of the line\n key = `${i}: `;\n key = getColorRenderer(options.keysColor, options)(key);\n key = Utils.indent(indentation) + key;\n\n // If the value is serializable, render it in the same line\n if (isSerializable(data[i], false, options)) {\n const nextIndentation = options.noAlign ? 0 : maxIndexLength - i.length;\n key += renderToArray(data[i], options, nextIndentation)[0];\n output.push(key);\n\n // If the index is an array or object, render it in next line\n } else {\n output.push(key);\n output.push.apply(output, renderToArray(data[i], options, indentation + options.defaultIndentation));\n }\n });\n return output;\n};\n/**\n * @typedef {Object} PrettyJSONOptions\n * @property {Function} [stringColor=null] Chalk color function for strings\n * @property {Function} [multilineStringColor=null] Chalk color function for multiline strings\n * @property {Function} [keysColor=chalk.green] Chalk color function for keys in hashes\n * @property {Function} [dashColor=chalk.green] Chalk color function for dashes in arrays\n * @property {Function} [numberColor=chalk.blue] Default Chalk color function for numbers\n * @property {Function} [positiveNumberColor=numberColor] Chalk color function for positive numbers\n * @property {Function} [negativeNumberColor=numberColor] Chalk color function for negative numbers\n * @property {Function} [booleanColor=chalk.cyan] Chalk color function for boolean values\n * @property {Function} [nullUndefinedColor=chalk.grey] Chalk color function for null || undefined\n * @property {Function} [dateColor=chalk.magenta] Chalk color function for Date objects\n * @property {number} [defaultIndentation=2] Indentation spaces per object level\n * @property {string} [emptyArrayMsg=\"(empty array)\"] Replace empty strings with\n * @property {boolean} [noColor] Flag to disable colors\n * @property {boolean} [noAlign] Flag to disable alignment\n * @property {boolean} [escape] Flag to escape printed content\n * @property {boolean} [collapseArrays] Flag to collapse arrays\n */\n/**\n * Mutating function that ensures we have a valid options object\n * @param {PrettyJSONOptions} options\n * @returns PrettyJSONOptions\n */\nconst validateOptionsAndSetDefaults = (options) => {\n options = options || {};\n options.emptyArrayMsg = options.emptyArrayMsg || \"(empty array)\";\n options.keysColor = options.keysColor || chalk.green;\n options.dashColor = options.dashColor || chalk.green;\n options.booleanColor = options.booleanColor || chalk.cyan;\n options.nullUndefinedColor = options.nullUndefinedColor || chalk.grey;\n options.numberColor = options.numberColor || chalk.blue;\n options.positiveNumberColor = options.positiveNumberColor || options.numberColor;\n options.negativeNumberColor = options.negativeNumberColor || options.numberColor;\n options.dateColor = options.dateColor || chalk.magenta;\n options.defaultIndentation = options.defaultIndentation || 2;\n options.noColor = !!options.noColor;\n options.noAlign = !!options.noAlign;\n options.escape = !!options.escape;\n options.renderUndefined = !!options.renderUndefined;\n options.collapseArrays = !!options.collapseArrays;\n\n options.stringColor = options.stringColor || null;\n options.multilineStringColor = options.multilineStringColor || options.stringColor || null;\n\n return options;\n};\n/**\n * ### Render function\n * *Parameters:*\n *\n * @param {*} data: Data to render\n * @param {PrettyJSONOptions} options: Hash of different options\n * @param {*} indentation **`indentation`**: Base indentation of the output\n *\n * *Example of options hash:*\n *\n * {\n * emptyArrayMsg: '(empty)', // Rendered message on empty strings\n * keysColor: 'blue', // Color for keys in hashes\n * dashColor: 'red', // Color for the dashes in arrays\n * stringColor: 'grey', // Color for strings\n * multilineStringColor: 'cyan' // Color for multiline strings\n * defaultIndentation: 2 // Indentation on nested objects\n * }\n * @returns string with the rendered data\n */\nexport function render(data, options, indentation) {\n // Default values\n indentation = indentation || 0;\n options = validateOptionsAndSetDefaults(options);\n\n return renderToArray(data, options, indentation).join(\"\\n\");\n}\n\n/**\n * ### Render from string function\n * *Parameters:*\n *\n * @param {*} data: Data to render\n * @param {PrettyJSONOptions} options: Hash of different options\n * @param {*} indentation **`indentation`**: Base indentation of the output\n *\n * *Example of options hash:*\n *\n * {\n * emptyArrayMsg: '(empty)', // Rendered message on empty strings\n * keysColor: 'blue', // Color for keys in hashes\n * dashColor: 'red', // Color for the dashes in arrays\n * defaultIndentation: 2 // Indentation on nested objects\n * }\n */\nexport function renderString(data, options, indentation) {\n let output = \"\";\n let parsedData;\n // If the input is not a string or if it's empty, just return an empty string\n if (typeof data !== \"string\" || data === \"\") {\n return \"\";\n }\n\n // Remove non-JSON characters from the beginning string\n if (data[0] !== \"{\" && data[0] !== \"[\") {\n let beginingOfJson;\n if (data.indexOf(\"{\") === -1) {\n beginingOfJson = data.indexOf(\"[\");\n } else if (data.indexOf(\"[\") === -1) {\n beginingOfJson = data.indexOf(\"{\");\n } else if (data.indexOf(\"{\") < data.indexOf(\"[\")) {\n beginingOfJson = data.indexOf(\"{\");\n } else {\n beginingOfJson = data.indexOf(\"[\");\n }\n output += `${data.substr(0, beginingOfJson)}\\n`;\n data = data.substr(beginingOfJson);\n }\n\n try {\n parsedData = JSON.parse(data);\n } catch (_e) {\n // Return an error in case of an invalid JSON\n return `${chalk.red(\"Error:\")} Not valid JSON!`;\n }\n\n // Call the real render() method\n output += exports.render(parsedData, options, indentation);\n return output;\n}\n","import chalk from \"chalk\";\nimport truncate from \"cli-truncate\";\nimport type { ColorConfig, ViewConfig } from \"../types.js\";\nimport * as prettyjson from \"../vendor/prettyjson.js\";\n\n/**\n * Formats a timestamp into a human-readable string.\n * Format: HH:MM:SS.mmm\n */\nexport function formatTimestamp(timestamp: number, colorFn: (inp: string) => string): string {\n const date = new Date(timestamp);\n return colorFn(\n `${date.getHours().toString().padStart(2, \"0\")}:${date.getMinutes().toString().padStart(2, \"0\")}:${date.getSeconds().toString().padStart(2, \"0\")}.${date.getMilliseconds().toString().padStart(3, \"0\")}`,\n );\n}\n\n/**\n * Gets the color function for a log level.\n */\nexport function getLevelColor(level: string, colors: ColorConfig): typeof chalk.white {\n return colors[level] || chalk.white;\n}\n\n/**\n * Formats a value for display.\n */\nexport function formatValue(value: any, expanded = false): string {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") return value.toString();\n if (value === null) return \"null\";\n if (value === undefined) return \"undefined\";\n if (Array.isArray(value)) return expanded ? JSON.stringify(value) : \"[...]\";\n if (typeof value === \"object\") return expanded ? JSON.stringify(value) : \"{...}\";\n return value.toString();\n}\n\n/**\n * Formats structured data for inline display with depth limiting.\n */\nexport function formatInlineData(\n data: any,\n config: ViewConfig,\n maxDepth: number,\n maxLength: number,\n expanded = false,\n): string {\n if (!data) return \"\";\n\n const pairs: string[] = [];\n const traverse = (obj: any, prefix = \"\", depth = 0) => {\n if (!expanded && depth >= maxDepth) return;\n\n for (const [key, value] of Object.entries(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n if (expanded) {\n pairs.push(`${config.dataKeyColor(fullKey)}=${config.dataValueColor(JSON.stringify(value))}`);\n } else {\n traverse(value, fullKey, depth + 1);\n }\n } else {\n pairs.push(`${config.dataKeyColor(fullKey)}=${config.dataValueColor(formatValue(value, expanded))}`);\n }\n }\n };\n\n traverse(data);\n const result = pairs.join(\" \");\n return expanded ? result : truncate(result, maxLength);\n}\n\n/**\n * Formats structured data for selection view (shows full data).\n */\nexport function formatSelectionData(data: any, config: ViewConfig): string {\n if (!data) return \"\";\n\n return prettyjson.render(data, {\n keysColor: config.dataKeyColor,\n dashColor: config.dataKeyColor,\n stringColor: config.dataValueColor,\n numberColor: config.dataValueColor,\n booleanColor: config.dataValueColor,\n nullUndefinedColor: config.dataValueColor,\n defaultIndentation: 2,\n });\n}\n","import chalk from \"chalk\";\nimport wrap from \"wrap-ansi\";\nimport type { LogEntry } from \"../types.js\";\nimport * as prettyjson from \"../vendor/prettyjson.js\";\nimport type { DetailViewConfig, View } from \"./types.js\";\nimport { formatTimestamp, getLevelColor } from \"./utils.js\";\n\n/**\n * Handles rendering of the detail view mode.\n * Shows a full-screen view of a single log entry with:\n * - Previous/next log context\n * - Full timestamp information\n * - Pretty-printed data\n * - Navigation help\n */\nexport class DetailView implements View {\n private termWidth: number;\n private config: DetailViewConfig;\n private detailViewContent: string[] = [];\n\n constructor(config: DetailViewConfig) {\n this.config = config;\n this.termWidth = process.stdout.columns || 80;\n }\n\n public updateTerminalWidth(width: number): void {\n this.termWidth = width;\n }\n\n /**\n * Formats a compact single-line version of a log entry\n */\n private formatCompactLogLine(entry: LogEntry | null, prefix = \"\"): string {\n if (!entry) return \"\";\n\n const levelColor = getLevelColor(entry.level, this.config.config.colors);\n const logId = this.config.config.logIdColor(`[${entry.id}]`);\n const line = `${prefix}${levelColor(entry.level.toUpperCase())} ${logId} ${entry.message}`;\n return this.config.config.separatorColor(wrap(line, this.termWidth, { hard: true }));\n }\n\n /**\n * Formats a timestamp into a human-readable relative time\n */\n private formatRelativeTime(timestamp: Date): string {\n const now = new Date();\n const diffMs = now.getTime() - timestamp.getTime();\n const diffSecs = Math.floor(diffMs / 1000);\n const diffMins = Math.floor(diffSecs / 60);\n const diffHours = Math.floor(diffMins / 60);\n const diffDays = Math.floor(diffHours / 24);\n\n if (diffSecs < 60) return `${diffSecs}s ago`;\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays === 1) return \"yesterday\";\n if (diffDays < 30) return `${diffDays}d ago`;\n\n return timestamp.toLocaleDateString();\n }\n\n public render(): void {\n console.clear();\n\n // Add padding at the top to handle terminal buffer overflow\n console.log(\"\\n\".repeat(5));\n\n // If in JSON view mode, show raw JSON\n if (this.config.isJsonView) {\n if (this.config.entry.data) {\n console.log(JSON.stringify(JSON.parse(this.config.entry.data)));\n } else {\n console.log(\"{}\");\n }\n console.log(`\\n${this.config.config.separatorColor(\"TAB to return to detailed view\")}`);\n return;\n }\n\n // Calculate fixed header content (previous entry)\n const headerContent: string[] = [];\n if (this.config.prevEntry) {\n const prevLine = this.formatCompactLogLine(this.config.prevEntry, \"← \");\n headerContent.push(prevLine);\n headerContent.push(this.config.config.separatorColor(\"─\".repeat(this.termWidth)));\n }\n\n // Calculate fixed footer content (next entry)\n const footerContent: string[] = [];\n if (this.config.nextEntry) {\n footerContent.push(this.config.config.separatorColor(\"─\".repeat(this.termWidth)));\n const nextLine = this.formatCompactLogLine(this.config.nextEntry, \"→ \");\n footerContent.push(nextLine);\n }\n footerContent.push(\"\"); // Empty line before help text\n footerContent.push(this.config.config.separatorColor(\"↑/↓ scroll • Q/W page up/down • J raw JSON\"));\n footerContent.push(this.config.config.separatorColor(\"←/→ navigate • A/S first/last log • C toggle arrays\"));\n\n // Calculate main scrollable content\n const mainContent: string[] = [];\n const levelColor = getLevelColor(this.config.entry.level, this.config.config.colors);\n\n // Build header with filter context if present\n let headerText = `=== Log Detail [${this.config.entry.id}] (${this.config.currentLogIndex} / ${this.config.totalLogs})`;\n if (this.config.filterText) {\n headerText += ` [Filter: ${this.config.filterText}]`;\n }\n headerText += \" ===\";\n\n const header = levelColor(headerText);\n mainContent.push(header);\n\n // Format timestamp with both ISO and relative time\n const timestamp = new Date(this.config.entry.timestamp);\n const isoTime = formatTimestamp(this.config.entry.timestamp, this.config.config.dataValueColor);\n const relativeTime = this.formatRelativeTime(timestamp);\n mainContent.push(`${this.config.config.labelColor(\"Timestamp:\")} ${isoTime} (${relativeTime})`);\n\n mainContent.push(\n `${this.config.config.labelColor(\"Level:\")} ${levelColor.bold(this.config.entry.level.toUpperCase())}`,\n );\n\n if (this.config.entry.message) {\n mainContent.push(\n `${this.config.config.labelColor(\"Message:\")} ${this.config.config.dataValueColor(this.config.entry.message)}`,\n );\n } else {\n mainContent.push(\n `${this.config.config.labelColor(\"Message:\")} ${this.config.config.dataValueColor.dim(\"(no message)\")}`,\n );\n }\n\n // Pretty-print structured data if present\n if (this.config.entry.data) {\n mainContent.push(this.config.config.labelColor(\"\\nData:\"));\n const jsonLines = prettyjson\n .render(JSON.parse(this.config.entry.data), {\n ...this.config.config.jsonColors,\n defaultIndentation: 2,\n collapseArrays: this.config.isArraysCollapsed,\n })\n .split(\"\\n\");\n mainContent.push(...jsonLines);\n }\n\n // Store the complete content for future scrolling\n this.detailViewContent = mainContent;\n\n // Calculate available height for main content\n const headerHeight = headerContent.length;\n const footerHeight = footerContent.length;\n const scrollIndicatorLines = 2; // Space for up/down indicators\n const bufferSpace = 4; // Extra buffer to prevent content from being cut off\n const topPadding = 2; // Account for the padding we added at the top\n const availableHeight = Math.max(\n 0,\n process.stdout.rows - headerHeight - footerHeight - scrollIndicatorLines - bufferSpace - topPadding,\n );\n\n // Render fixed header\n for (const line of headerContent) {\n console.log(line);\n }\n\n // Show scroll indicator if needed\n if (this.config.scrollPos > 0) {\n console.log(chalk.dim(\"↑ More content above\"));\n }\n\n // Display visible portion of main content\n const startIndex = this.config.scrollPos;\n const visibleContent = mainContent.slice(startIndex, startIndex + availableHeight);\n for (const line of visibleContent) {\n console.log(line);\n }\n\n // Show scroll indicator if there's more content below\n if (this.config.scrollPos + availableHeight < mainContent.length) {\n console.log(chalk.dim(\"↓ More content below\"));\n } else {\n console.log(chalk.dim(\"End of content\"));\n }\n\n // Render fixed footer\n for (const line of footerContent) {\n console.log(line);\n }\n }\n\n /**\n * Gets the maximum scroll position based on current content and window size\n */\n public getMaxScrollPosition(): number {\n const headerHeight = this.config.prevEntry ? 2 : 0;\n const footerHeight = 5;\n const scrollIndicatorLines = 2;\n const bufferSpace = 2;\n const topPadding = 2; // Account for the padding we added at the top\n const availableHeight = Math.max(\n 0,\n process.stdout.rows - headerHeight - footerHeight - scrollIndicatorLines - bufferSpace - topPadding,\n );\n\n return Math.max(0, this.detailViewContent.length - availableHeight);\n }\n}\n","import chalk from \"chalk\";\nimport wrap from \"wrap-ansi\";\nimport type { SelectionViewConfig, View } from \"./types.js\";\nimport { formatInlineData, formatTimestamp, getLevelColor } from \"./utils.js\";\n\n/**\n * Handles rendering of the selection view mode.\n * Shows an interactive list of logs with:\n * - Filtering capability\n * - Selected item highlighting\n * - Full data preview inline\n * - Scroll indicators\n */\nexport class SelectionView implements View {\n private termWidth: number;\n private config: SelectionViewConfig;\n\n constructor(config: SelectionViewConfig) {\n this.config = config;\n this.termWidth = process.stdout.columns || 80;\n }\n\n public updateTerminalWidth(width: number): void {\n this.termWidth = width;\n }\n\n public render(): void {\n console.clear();\n\n // Add padding at the top to handle terminal buffer overflow\n console.log(\"\\n\".repeat(5));\n\n // Calculate available height for logs\n const filterHeight = this.config.filterText ? 2 : 0; // Filter + separator line\n const footerHeight = 2; // Help text + blank line before it\n const topPadding = 5; // Account for the padding we added\n const availableHeight = process.stdout.rows - filterHeight - footerHeight - topPadding;\n\n if (this.config.logs.length === 0) {\n console.log(chalk.yellow(\"No matching logs found\"));\n } else {\n // Calculate the window of logs to show\n const visibleLines = Math.min(availableHeight, 20); // Show at most 20 lines at a time\n const bottomPadding = 2; // Keep selected item this many lines from the bottom\n\n let startIdx = Math.max(0, this.config.selectedIndex - (visibleLines - bottomPadding - 1));\n const endIdx = Math.min(this.config.logs.length, startIdx + visibleLines);\n\n // Adjust start index if we're near the end\n if (endIdx - startIdx < visibleLines && endIdx < this.config.logs.length) {\n startIdx = Math.max(0, endIdx - visibleLines);\n }\n\n // Show scroll indicator if there are logs above\n if (startIdx > 0) {\n console.log(chalk.dim(\" ↑ More logs above\"));\n }\n\n // Render visible logs with selection highlight\n this.config.logs.slice(startIdx, endIdx).forEach((entry, index) => {\n const actualIndex = startIdx + index;\n const isSelected = actualIndex === this.config.selectedIndex;\n const prefix = isSelected ? this.config.config.selectorColor(\"► \") : \" \";\n const timestamp = formatTimestamp(entry.timestamp, this.config.config.logIdColor);\n const levelColor = getLevelColor(entry.level, this.config.config.colors);\n const chevron = levelColor(`${entry.level.toUpperCase()} `);\n const logId = chalk.dim(`[${entry.id}]`);\n const message = entry.message;\n const data = entry.data ? ` ${formatInlineData(JSON.parse(entry.data), this.config.config, 0, 0, true)}` : \"\";\n\n // Construct and wrap the main line with full data\n const mainLine = `${prefix}${timestamp} ${chevron}${logId} ${message}${data}`;\n const wrappedText = wrap(mainLine, this.termWidth - 2, { hard: true });\n\n if (isSelected) {\n // For selected items, add vertical bar and indentation to all lines except the first\n const lines = wrappedText.split(\"\\n\");\n console.log(lines[0]);\n for (const line of lines.slice(1)) {\n console.log(` ${this.config.config.selectorColor(\"│\")} ${line}`);\n }\n } else {\n console.log(wrappedText);\n }\n });\n\n // Show scroll indicator if there are logs below\n if (endIdx < this.config.logs.length || this.config.newLogCount > 0) {\n const moreLogsText =\n this.config.newLogCount > 0\n ? this.config.config.selectorColor(\n ` ↓ ${this.config.newLogCount} new log${this.config.newLogCount === 1 ? \"\" : \"s\"} available (press ↓ to view)`,\n )\n : chalk.dim(\" ↓ More logs below\");\n console.log(moreLogsText);\n }\n }\n\n // Show help text and filter at the bottom\n console.log(chalk.dim(\"\\nType to filter • Enter to view details • TAB to exit\"));\n\n // Show active filter if any\n if (this.config.filterText) {\n console.log(chalk.dim(\"─\".repeat(this.termWidth)));\n console.log(chalk.cyan(\"Filter:\"), chalk.white(this.config.filterText));\n }\n }\n}\n","import wrap from \"wrap-ansi\";\nimport type { LogEntry } from \"../types.js\";\nimport type { SimpleViewConfig, View } from \"./types.js\";\nimport { formatInlineData, formatTimestamp, getLevelColor } from \"./utils.js\";\n\n/**\n * Handles rendering of the simple view mode.\n * Supports three display modes:\n * - Truncated: Shows all log details with truncated data\n * - Condensed: Shows timestamp, level and message\n * - Full: Shows all details with complete data\n */\nexport class SimpleView implements View {\n private termWidth: number;\n private config: SimpleViewConfig;\n\n constructor(config: SimpleViewConfig) {\n this.config = config;\n this.termWidth = process.stdout.columns || 80;\n }\n\n public updateTerminalWidth(width: number): void {\n this.termWidth = width;\n }\n\n /**\n * Renders a single log entry based on the current view mode\n */\n public renderLogLine(entry: LogEntry): void {\n const levelColor = getLevelColor(entry.level, this.config.config.colors);\n const chevron = levelColor(`▶ ${entry.level.toUpperCase()} `);\n const message = entry.message || \"(no message)\";\n const timestamp = formatTimestamp(entry.timestamp, this.config.config.logIdColor);\n\n switch (this.config.viewMode) {\n case \"condensed\": {\n // Condensed view shows timestamp, level and message\n const condensedLine = `${timestamp} ${chevron}${message}`;\n console.log(wrap(condensedLine, this.termWidth, { hard: true }));\n break;\n }\n\n case \"full\": {\n // Full view shows all details with complete data\n const logId = this.config.config.logIdColor(`[${entry.id}]`);\n const fullData = entry.data\n ? formatInlineData(\n JSON.parse(entry.data),\n this.config.config,\n this.config.maxInlineDepth,\n this.config.maxInlineLength,\n true,\n )\n : \"\";\n const expandedLine = `${timestamp} ${chevron}${logId} ${message}${fullData ? ` ${fullData}` : \"\"}`;\n console.log(wrap(expandedLine, this.termWidth, { hard: true }));\n break;\n }\n\n default: {\n // 'truncated'\n // Truncated view shows all details with truncated data\n const logId = this.config.config.logIdColor(`[${entry.id}]`);\n const normalData = entry.data\n ? formatInlineData(\n JSON.parse(entry.data),\n this.config.config,\n this.config.maxInlineDepth,\n this.config.maxInlineLength,\n )\n : \"\";\n const normalLine = `${timestamp} ${chevron}${logId} ${message}${normalData ? ` ${normalData}` : \"\"}`;\n console.log(wrap(normalLine, this.termWidth, { hard: true }));\n break;\n }\n }\n }\n\n public render(): void {\n throw new Error(\"SimpleView.render() should not be called directly. Use renderLogLine() instead.\");\n }\n}\n","/**\n * LogRenderer handles all terminal output formatting and rendering.\n * Provides multiple view modes with different levels of detail:\n * - Simple view for real-time log output\n * - Compact view for context in detailed view\n * - Detailed view for inspecting individual logs\n * - Selection view for browsing and filtering logs\n *\n * Features:\n * - Color-coded log levels\n * - Structured data formatting\n * - Terminal width awareness\n * - Pretty-printed JSON\n * - Truncation of long content\n */\n\nimport type { DetailedViewConfig, LogEntry, ViewConfig } from \"./types.js\";\nimport { DetailView, SelectionView, SimpleView } from \"./views/index.js\";\n\n/**\n * LogRenderer coordinates between different view modes and manages the overall rendering state.\n * Delegates actual rendering to specialized view implementations:\n * - SimpleView: For real-time log output\n * - SelectionView: For interactive log browsing\n * - DetailView: For in-depth log inspection\n */\nexport class LogRenderer {\n /** Current terminal width in characters */\n private termWidth: number;\n\n /** Maximum depth for displaying nested objects inline */\n private maxInlineDepth: number;\n\n /** Maximum length for inline data before truncating */\n private maxInlineLength: number;\n\n /** Whether arrays are currently collapsed in detail view */\n private isArraysCollapsed = true;\n\n /** Current view mode in simple mode */\n private viewMode: \"truncated\" | \"condensed\" | \"full\" = \"full\";\n\n /** Color and formatting config for simple log view */\n private simpleViewConfig: Required<ViewConfig>;\n\n /** Color and formatting config for detailed view */\n private detailedViewConfig: Required<DetailedViewConfig>;\n\n /** Whether we're showing raw JSON view */\n private isJsonView = false;\n\n /** Current scroll position in detailed view */\n private detailViewScrollPos = 0;\n\n /** View instances */\n private simpleView: SimpleView;\n private detailView: DetailView | null = null;\n private selectionView: SelectionView | null = null;\n\n /**\n * Creates a new LogRenderer instance.\n *\n * @param simpleViewConfig - Configuration for simple log view\n * @param detailedViewConfig - Configuration for detailed view\n * @param maxInlineDepth - Maximum depth for inline object display\n * @param maxInlineLength - Maximum length before truncation\n */\n constructor(\n simpleViewConfig: Required<ViewConfig>,\n detailedViewConfig: Required<DetailedViewConfig>,\n maxInlineDepth: number,\n maxInlineLength: number,\n ) {\n this.simpleViewConfig = simpleViewConfig;\n this.detailedViewConfig = detailedViewConfig;\n this.maxInlineDepth = maxInlineDepth;\n this.maxInlineLength = maxInlineLength;\n this.termWidth = process.stdout.columns || 80;\n\n // Initialize views with their configurations\n this.simpleView = new SimpleView({\n viewMode: this.viewMode,\n maxInlineDepth: this.maxInlineDepth,\n maxInlineLength: this.maxInlineLength,\n config: this.simpleViewConfig,\n });\n\n // Detail view will be initialized when needed with actual log entry\n this.detailView = null as any; // Will be set when entering detail view\n\n // Selection view will be initialized when needed with actual logs\n this.selectionView = null as any; // Will be set when entering selection view\n\n // Update terminal width when window is resized\n process.stdout.on(\"resize\", () => {\n this.termWidth = process.stdout.columns || 80;\n this.simpleView.updateTerminalWidth(this.termWidth);\n if (this.detailView) {\n this.detailView.updateTerminalWidth(this.termWidth);\n }\n if (this.selectionView) {\n this.selectionView.updateTerminalWidth(this.termWidth);\n }\n });\n }\n\n /**\n * Renders a single log line in simple view format.\n * Format: [timestamp] LEVEL [id] message data\n * Condensed Format: [timestamp] LEVEL message\n * Expanded Format: [timestamp] LEVEL [id] message full_data\n *\n * @param entry - Log entry to render\n */\n public renderLogLine(entry: LogEntry): void {\n this.simpleView.renderLogLine(entry);\n }\n\n /**\n * Renders the detailed view of a log entry.\n * Shows full entry details with context and formatted data.\n *\n * @param entry - Log entry to show in detail\n * @param prevEntry - Previous entry for context\n * @param nextEntry - Next entry for context\n * @param scrollPos - Current scroll position\n * @param currentLogIndex - Current log index (optional)\n * @param totalLogs - Total logs count (optional)\n * @param filterText - Current filter text (if any)\n */\n public renderDetailView(\n entry: LogEntry,\n prevEntry: LogEntry | null,\n nextEntry: LogEntry | null,\n scrollPos = 0,\n currentLogIndex?: number,\n totalLogs?: number,\n filterText = \"\",\n ): void {\n // Create or update detail view configuration\n const config = {\n entry,\n prevEntry,\n nextEntry,\n scrollPos,\n isArraysCollapsed: this.isArraysCollapsed,\n isJsonView: this.isJsonView,\n currentLogIndex: currentLogIndex ?? (prevEntry ? 2 : nextEntry ? 1 : 1), // Use provided index or fallback\n totalLogs: totalLogs ?? 1, // Use provided total or fallback\n filterText,\n config: this.detailedViewConfig,\n };\n\n // Create new detail view instance or update existing one\n if (!this.detailView) {\n this.detailView = new DetailView(config);\n } else {\n this.detailView = new DetailView(config);\n }\n\n this.detailView.render();\n }\n\n /**\n * Updates the scroll position in detailed view\n * @param delta - Number of lines to scroll\n */\n public scrollDetailView(delta: number): void {\n if (!this.detailView) return;\n\n const maxScroll = this.detailView.getMaxScrollPosition();\n this.detailViewScrollPos = Math.max(0, Math.min(maxScroll, this.detailViewScrollPos + delta));\n }\n\n /**\n * Gets the current scroll position\n */\n public getDetailViewScrollPos(): number {\n return this.detailViewScrollPos;\n }\n\n /**\n * Renders the selection view with a list of logs.\n * Shows filtered logs with selection highlight and data preview.\n *\n * @param logs - Array of logs to display\n * @param selectedIndex - Index of currently selected log\n * @param filterText - Current filter text (if any)\n * @param newLogCount - Number of new logs available\n */\n public renderSelectionView(logs: LogEntry[], selectedIndex: number, filterText: string, newLogCount: number): void {\n // Create or update selection view configuration\n const config = {\n logs,\n selectedIndex,\n filterText,\n newLogCount,\n config: this.detailedViewConfig,\n };\n\n // Create new selection view instance or update existing one\n if (!this.selectionView) {\n this.selectionView = new SelectionView(config);\n } else {\n this.selectionView = new SelectionView(config);\n }\n\n this.selectionView.render();\n }\n\n /**\n * Toggles JSON view state\n */\n public toggleJsonView(): void {\n this.isJsonView = !this.isJsonView;\n }\n\n /**\n * Gets current JSON view state\n */\n public isInJsonView(): boolean {\n return this.isJsonView;\n }\n\n /**\n * Toggles array collapse state in detail view\n */\n public toggleArrayCollapse(): void {\n this.isArraysCollapsed = !this.isArraysCollapsed;\n }\n\n /**\n * Cycles through view modes: full -> truncated -> condensed\n */\n public cycleViewMode(): string {\n switch (this.viewMode) {\n case \"full\":\n this.viewMode = \"truncated\";\n break;\n case \"truncated\":\n this.viewMode = \"condensed\";\n break;\n case \"condensed\":\n this.viewMode = \"full\";\n break;\n }\n\n // Update simple view configuration\n this.simpleView = new SimpleView({\n viewMode: this.viewMode,\n maxInlineDepth: this.maxInlineDepth,\n maxInlineLength: this.maxInlineLength,\n config: this.simpleViewConfig,\n });\n\n return this.viewMode;\n }\n\n /**\n * Gets current view mode\n */\n public getViewMode(): string {\n return this.viewMode;\n }\n}\n","/**\n * LogStorage handles the persistence of log entries using SQLite.\n * Uses an in-memory database for fast access and temporary storage.\n */\n\nimport { resolve } from \"node:path\";\nimport Database from \"better-sqlite3\";\nimport type { LogEntry } from \"./types.js\";\n\n/**\n * Handles storage and retrieval of log entries using SQLite.\n * Uses an in-memory database for optimal performance and automatic cleanup.\n *\n * The database schema includes:\n * - id: Unique identifier for each log\n * - timestamp: Unix timestamp in milliseconds\n * - level: Log level (trace, debug, info, etc.)\n * - message: Main log message\n * - data: Optional structured data as JSON string\n */\nexport class LogStorage {\n /** SQLite database instance */\n private db: Database.Database;\n\n /**\n * Creates a new LogStorage instance.\n * Initializes a SQLite database and creates the logs table.\n *\n * @param logFile - Optional path to SQLite file for persistent storage.\n * If not provided, uses in-memory database.\n * Relative paths are resolved from the current working directory.\n */\n constructor(logFile?: string) {\n // Use specified log file or fallback to in-memory database\n const dbPath = logFile ? (logFile.startsWith(\"/\") ? logFile : resolve(process.cwd(), logFile)) : \":memory:\";\n this.db = new Database(dbPath);\n this.initializeDatabase();\n }\n\n /**\n * Initializes the database schema.\n * Creates the logs table with appropriate columns and indexes.\n * If the table already exists, it will be dropped to ensure a clean state.\n * @private\n */\n private initializeDatabase(): void {\n this.db.exec(`\n DROP TABLE IF EXISTS logs;\n CREATE TABLE logs (\n id TEXT PRIMARY KEY,\n timestamp INTEGER,\n level TEXT,\n message TEXT,\n data TEXT\n )\n `);\n }\n\n /**\n * Stores a new log entry in the database.\n * Uses prepared statements for efficient and safe insertion.\n *\n * @param entry - The log entry to store\n * @example\n * storage.store({\n * id: \"abc123\",\n * timestamp: Date.now(),\n * level: \"info\",\n * message: \"User logged in\",\n * data: JSON.stringify({ userId: 123 })\n * });\n */\n public store(entry: LogEntry): void {\n this.db\n .prepare(`\n INSERT INTO logs (id, timestamp, level, message, data)\n VALUES (?, ?, ?, ?, ?)\n `)\n .run(entry.id, entry.timestamp, entry.level, entry.message, entry.data);\n }\n\n /**\n * Retrieves all logs from the database in chronological order.\n * Used when displaying the full log history or clearing filters.\n *\n * @returns Array of log entries sorted by timestamp\n */\n public getAllLogs(): LogEntry[] {\n return this.db.prepare(\"SELECT * FROM logs ORDER BY timestamp ASC\").all() as LogEntry[];\n }\n\n /**\n * Searches logs based on a text query.\n * Performs a case-insensitive search across multiple fields:\n * - Log ID\n * - Message content\n * - Structured data\n *\n * @param searchText - Text to search for\n * @returns Array of matching log entries sorted by timestamp\n * @example\n * const errorLogs = storage.searchLogs(\"error\");\n * const userLogs = storage.searchLogs(\"userId:123\");\n */\n public searchLogs(searchText: string): LogEntry[] {\n const query = `\n SELECT * FROM logs \n WHERE id LIKE ? \n OR message LIKE ? \n OR data LIKE ? \n ORDER BY timestamp ASC\n `;\n const pattern = `%${searchText}%`;\n return this.db.prepare(query).all(pattern, pattern, pattern) as LogEntry[];\n }\n\n /**\n * Gets the total number of logs in the database.\n * Uses an efficient COUNT query instead of loading all logs.\n *\n * @returns Total number of log entries\n */\n public getLogCount(): number {\n const result = this.db.prepare(\"SELECT COUNT(*) as count FROM logs\").get() as { count: number };\n return result.count;\n }\n\n /**\n * Gets the total number of logs matching a search query.\n * Uses an efficient COUNT query instead of loading all logs.\n *\n * @param searchText - Text to search for\n * @returns Number of matching log entries\n */\n public getFilteredLogCount(searchText: string): number {\n const query = `\n SELECT COUNT(*) as count FROM logs \n WHERE id LIKE ? \n OR message LIKE ? \n OR data LIKE ?\n `;\n const pattern = `%${searchText}%`;\n const result = this.db.prepare(query).get(pattern, pattern, pattern) as { count: number };\n return result.count;\n }\n\n /**\n * Closes the database connection and performs cleanup.\n * Should be called when the application exits or the transport is destroyed.\n */\n public close(): void {\n this.db.close();\n }\n}\n","import chalk from \"chalk\";\nimport type { PrettyTerminalTheme } from \"./types.js\";\n\n/**\n * Moonlight - A dark theme with cool blue tones\n * Inspired by moonlit nights and modern IDEs\n *\n * Color Palette:\n * - Primary: Cool blues and soft greens\n * - Accents: Warm yellows and soft reds\n * - Background: Assumes dark terminal (black or very dark grey)\n *\n * Best used with:\n * - Dark terminal themes\n * - Night-time coding sessions\n * - Environments where eye strain is a concern\n */\nexport const moonlight: PrettyTerminalTheme = {\n simpleView: {\n colors: {\n trace: chalk.rgb(114, 135, 153), // Muted blue-grey for less important info\n debug: chalk.rgb(130, 170, 255), // Soft blue that pops but doesn't strain\n info: chalk.rgb(195, 232, 141), // Sage green for good readability\n warn: chalk.rgb(255, 203, 107), // Warm yellow, less harsh than pure yellow\n error: chalk.rgb(247, 118, 142), // Soft red that stands out without being aggressive\n fatal: chalk.bgRgb(247, 118, 142).white, // Inverted soft red for maximum visibility\n },\n logIdColor: chalk.rgb(84, 98, 117), // Darker blue-grey for secondary information\n dataValueColor: chalk.rgb(209, 219, 231), // Light grey-blue for primary content\n dataKeyColor: chalk.rgb(130, 170, 255), // Matching debug blue for consistency\n selectorColor: chalk.rgb(137, 221, 255), // Ice blue for selection indicators\n },\n detailedView: {\n colors: {\n trace: chalk.rgb(114, 135, 153),\n debug: chalk.rgb(130, 170, 255),\n info: chalk.rgb(195, 232, 141),\n warn: chalk.rgb(255, 203, 107),\n error: chalk.rgb(247, 118, 142),\n fatal: chalk.bgRgb(247, 118, 142).white,\n },\n logIdColor: chalk.rgb(84, 98, 117),\n dataValueColor: chalk.rgb(209, 219, 231),\n dataKeyColor: chalk.rgb(130, 170, 255),\n selectorColor: chalk.rgb(137, 221, 255), // Ice blue for selection indicators\n headerColor: chalk.rgb(137, 221, 255),\n labelColor: chalk.rgb(137, 221, 255).bold,\n separatorColor: chalk.rgb(84, 98, 117),\n jsonColors: {\n keysColor: chalk.rgb(130, 170, 255),\n dashColor: chalk.rgb(209, 219, 231),\n numberColor: chalk.rgb(247, 140, 108),\n stringColor: chalk.rgb(195, 232, 141),\n multilineStringColor: chalk.rgb(195, 232, 141),\n positiveNumberColor: chalk.rgb(195, 232, 141),\n negativeNumberColor: chalk.rgb(247, 118, 142),\n booleanColor: chalk.rgb(255, 203, 107),\n nullUndefinedColor: chalk.rgb(114, 135, 153),\n dateColor: chalk.rgb(199, 146, 234),\n },\n },\n};\n\n/**\n * Sunlight - A light theme with warm tones\n * Inspired by daylight reading and paper documentation\n *\n * Color Palette:\n * - Primary: Deep, rich colors that contrast well with white\n * - Accents: Earth tones and deep jewel tones\n * - Background: Assumes light terminal (white or very light grey)\n *\n * Best used with:\n * - Light terminal themes\n * - Daytime coding sessions\n * - High-glare environments\n * - Printed documentation\n */\nexport const sunlight: PrettyTerminalTheme = {\n simpleView: {\n colors: {\n trace: chalk.rgb(110, 110, 110), // Dark grey for subtle information\n debug: chalk.rgb(32, 96, 159), // Deep blue for strong contrast on white\n info: chalk.rgb(35, 134, 54), // Forest green, easier on the eyes than bright green\n warn: chalk.rgb(176, 95, 0), // Brown-orange for natural warning color\n error: chalk.rgb(191, 0, 0), // Deep red for clear visibility on light backgrounds\n fatal: chalk.bgRgb(191, 0, 0).white, // White on deep red for critical issues\n },\n logIdColor: chalk.rgb(110, 110, 110),\n dataValueColor: chalk.rgb(0, 0, 0),\n dataKeyColor: chalk.rgb(32, 96, 159),\n selectorColor: chalk.rgb(0, 91, 129), // Deep blue for strong contrast\n },\n detailedView: {\n colors: {\n trace: chalk.rgb(110, 110, 110),\n debug: chalk.rgb(32, 96, 159),\n info: chalk.rgb(35, 134, 54),\n warn: chalk.rgb(176, 95, 0),\n error: chalk.rgb(191, 0, 0),\n fatal: chalk.bgRgb(191, 0, 0).white,\n },\n logIdColor: chalk.rgb(110, 110, 110),\n dataValueColor: chalk.rgb(0, 0, 0),\n dataKeyColor: chalk.rgb(32, 96, 159),\n selectorColor: chalk.rgb(0, 91, 129), // Deep blue for strong contrast\n headerColor: chalk.rgb(0, 91, 129),\n labelColor: chalk.rgb(0, 91, 129).bold,\n separatorColor: chalk.rgb(110, 110, 110),\n jsonColors: {\n keysColor: chalk.rgb(32, 96, 159),\n dashColor: chalk.rgb(0, 0, 0),\n numberColor: chalk.rgb(170, 55, 49),\n stringColor: chalk.rgb(35, 134, 54),\n multilineStringColor: chalk.rgb(35, 134, 54),\n positiveNumberColor: chalk.rgb(46, 125, 50),\n negativeNumberColor: chalk.rgb(183, 28, 28),\n booleanColor: chalk.rgb(176, 95, 0),\n nullUndefinedColor: chalk.rgb(110, 110, 110),\n dateColor: chalk.rgb(123, 31, 162),\n },\n },\n};\n\n/**\n * Neon - A dark theme with vibrant cyberpunk colors\n * Inspired by neon-lit cityscapes and retro-futuristic aesthetics\n *\n * Color Palette:\n * - Primary: Electric blues and hot pinks\n * - Accents: Bright purples and cyber greens\n * - Background: Assumes dark terminal (black or very dark grey)\n *\n * Best used with:\n * - Dark terminal themes\n * - High-contrast preferences\n * - Modern, tech-focused applications\n */\nexport const neon: PrettyTerminalTheme = {\n simpleView: {\n colors: {\n trace: chalk.rgb(108, 108, 255), // Electric blue\n debug: chalk.rgb(255, 82, 246), // Hot pink\n info: chalk.rgb(0, 255, 163), // Cyber green\n warn: chalk.rgb(255, 231, 46), // Electric yellow\n error: chalk.rgb(255, 53, 91), // Neon red\n fatal: chalk.bgRgb(255, 53, 91).rgb(0, 255, 163), // Neon red bg with cyber green text\n },\n logIdColor: chalk.rgb(187, 134, 252), // Bright purple\n dataValueColor: chalk.rgb(255, 255, 255), // Pure white\n dataKeyColor: chalk.rgb(0, 255, 240), // Cyan\n selectorColor: chalk.rgb(0, 255, 240), // Electric cyan for cyberpunk feel\n },\n detailedView: {\n colors: {\n trace: chalk.rgb(108, 108, 255),\n debug: chalk.rgb(255, 82, 246),\n info: chalk.rgb(0, 255, 163),\n warn: chalk.rgb(255, 231, 46),\n error: chalk.rgb(255, 53, 91),\n fatal: chalk.bgRgb(255, 53, 91).rgb(0, 255, 163),\n },\n logIdColor: chalk.rgb(187, 134, 252),\n dataValueColor: chalk.rgb(255, 255, 255),\n dataKeyColor: chalk.rgb(0, 255, 240),\n selectorColor: chalk.rgb(0, 255, 240), // Electric cyan for cyberpunk feel\n headerColor: chalk.rgb(255, 82, 246),\n labelColor: chalk.rgb(255, 82, 246).bold,\n separatorColor: chalk.rgb(108, 108, 255),\n jsonColors: {\n keysColor: chalk.rgb(0, 255, 240),\n dashColor: chalk.rgb(255, 255, 255),\n numberColor: chalk.rgb(255, 82, 246),\n stringColor: chalk.rgb(0, 255, 163),\n multilineStringColor: chalk.rgb(0, 255, 163),\n positiveNumberColor: chalk.rgb(0, 255, 163),\n negativeNumberColor: chalk.rgb(255, 53, 91),\n booleanColor: chalk.rgb(255, 231, 46),\n nullUndefinedColor: chalk.rgb(108, 108, 255),\n dateColor: chalk.rgb(187, 134, 252),\n },\n },\n};\n\n/**\n * Nature - A light theme with organic, earthy colors\n * Inspired by forest landscapes and natural elements\n *\n * Color Palette:\n * - Primary: Deep forest greens and rich browns\n * - Accents: Autumn reds and golden yellows\n * - Background: Assumes light terminal (white or very light grey)\n *\n * Best used with:\n * - Light terminal themes\n * - Nature-inspired interfaces\n * - Applications focusing on readability\n */\nexport const nature: PrettyTerminalTheme = {\n simpleView: {\n colors: {\n trace: chalk.rgb(121, 85, 72), // Wooden brown\n debug: chalk.rgb(46, 125, 50), // Forest green\n info: chalk.rgb(0, 105, 92), // Deep teal\n warn: chalk.rgb(175, 115, 0), // Golden amber\n error: chalk.rgb(183, 28, 28), // Autumn red\n fatal: chalk.bgRgb(183, 28, 28).rgb(255, 250, 240), // Red bg with soft white\n },\n logIdColor: chalk.rgb(93, 64, 55), // Deep bark brown\n dataValueColor: chalk.rgb(27, 27, 27), // Near black\n dataKeyColor: chalk.rgb(56, 142, 60), // Leaf green\n selectorColor: chalk.rgb(0, 105, 92), // Deep teal for natural feel\n },\n detailedView: {\n colors: {\n trace: chalk.rgb(121, 85, 72),\n debug: chalk.rgb(46, 125, 50),\n info: chalk.rgb(0, 105, 92),\n warn: chalk.rgb(175, 115, 0),\n error: chalk.rgb(183, 28, 28),\n fatal: chalk.bgRgb(183, 28, 28).rgb(255, 250, 240),\n },\n logIdColor: chalk.rgb(93, 64, 55),\n dataValueColor: chalk.rgb(27, 27, 27),\n dataKeyColor: chalk.rgb(56, 142, 60),\n selectorColor: chalk.rgb(0, 105, 92), // Deep teal for natural feel\n headerColor: chalk.rgb(0, 77, 64),\n labelColor: chalk.rgb(0, 77, 64).bold,\n separatorColor: chalk.rgb(121, 85, 72),\n jsonColors: {\n keysColor: chalk.rgb(56, 142, 60),\n dashColor: chalk.rgb(27, 27, 27),\n numberColor: chalk.rgb(230, 81, 0),\n stringColor: chalk.rgb(0, 105, 92),\n multilineStringColor: chalk.rgb(0, 105, 92),\n positiveNumberColor: chalk.rgb(46, 125, 50),\n negativeNumberColor: chalk.rgb(183, 28, 28),\n booleanColor: chalk.rgb(175, 115, 0),\n nullUndefinedColor: chalk.rgb(121, 85, 72),\n dateColor: chalk.rgb(123, 31, 162),\n },\n },\n};\n\n/**\n * Pastel - A soft, calming theme with gentle colors\n * Inspired by watercolor paintings and cotton candy skies\n *\n * Color Palette:\n * - Primary: Soft pinks and lavenders\n * - Accents: Mint greens and baby blues\n * - Background: Assumes dark terminal (black or very dark grey)\n *\n * Best used with:\n * - Dark terminal themes\n * - Long coding sessions where eye comfort is priority\n * - Environments where a gentler aesthetic is preferred\n * - Applications focusing on reduced visual stress\n */\nexport const pastel: PrettyTerminalTheme = {\n simpleView: {\n colors: {\n trace: chalk.rgb(179, 189, 203), // Soft slate blue\n debug: chalk.rgb(189, 178, 255), // Gentle lavender\n info: chalk.rgb(170, 236, 205), // Mint green\n warn: chalk.rgb(255, 223, 186), // Peach\n error: chalk.rgb(255, 188, 188), // Soft coral\n fatal: chalk.bgRgb(255, 188, 188).rgb(76, 40, 40), // Coral bg with deep brown\n },\n logIdColor: chalk.rgb(203, 195, 227), // Dusty lavender\n dataValueColor: chalk.rgb(236, 236, 236), // Soft white\n dataKeyColor: chalk.rgb(186, 207, 255), // Baby blue\n selectorColor: chalk.rgb(189, 178, 255), // Soft lavender for gentle highlighting\n },\n detailedView: {\n colors: {\n trace: chalk.rgb(179, 189, 203),\n debug: chalk.rgb(189, 178, 255),\n info: chalk.rgb(170, 236, 205),\n warn: chalk.rgb(255, 223, 186),\n error: chalk.rgb(255, 188, 188),\n fatal: chalk.bgRgb(255, 188, 188).rgb(76, 40, 40),\n },\n logIdColor: chalk.rgb(203, 195, 227),\n dataValueColor: chalk.rgb(236, 236, 236),\n dataKeyColor: chalk.rgb(186, 207, 255),\n selectorColor: chalk.rgb(189, 178, 255), // Soft lavender for gentle highlighting\n headerColor: chalk.rgb(255, 198, 255), // Cotton candy pink\n labelColor: chalk.rgb(255, 198, 255).bold,\n separatorColor: chalk.rgb(179, 189, 203),\n jsonColors: {\n keysColor: chalk.rgb(186, 207, 255), // Baby blue\n dashColor: chalk.rgb(236, 236, 236), // Soft white\n numberColor: chalk.rgb(255, 198, 255), // Cotton candy pink\n stringColor: chalk.rgb(170, 236, 205), // Mint green\n multilineStringColor: chalk.rgb(170, 236, 205),\n positiveNumberColor: chalk.rgb(170, 236, 205),\n negativeNumberColor: chalk.rgb(255, 188, 188),\n booleanColor: chalk.rgb(255, 223, 186), // Peach\n nullUndefinedColor: chalk.rgb(179, 189, 203),\n dateColor: chalk.rgb(189, 178, 255), // Gentle lavender\n },\n },\n};\n","/**\n * UIManager handles all user interaction and view state management.\n * This class is responsible for:\n * - Managing keyboard input and navigation\n * - Coordinating between views (simple, selection, detail)\n * - Handling filtering and search\n * - Managing the selection state\n * - Coordinating between storage and rendering\n *\n * The UI has three main modes:\n * 1. Simple View: Real-time log output (default)\n * 2. Selection View: Interactive log browsing with filtering\n * 3. Detail View: In-depth view of a single log entry\n *\n * Navigation Controls:\n * - TAB: Toggle selection mode\n * - Up/Down: Navigate logs in selection mode, scroll in detail mode\n * - Left/Right: Navigate between logs in detail mode\n * - Enter: View log details\n * - Type: Filter logs\n * - Backspace: Clear filter\n * - CTRL+C: Exit\n */\n\nimport chalk from \"chalk\";\n// @ts-expect-error\nimport keypress from \"keypress\";\nimport type { LogRenderer } from \"./LogRenderer.js\";\nimport type { LogStorage } from \"./LogStorage.js\";\nimport type { LogEntry } from \"./types.js\";\n\n/**\n * Manages UI state and user interaction.\n * Acts as the controller between the storage and rendering layers.\n * Handles all keyboard input and view transitions.\n */\nexport class UIManager {\n /** Whether the UI is in log selection mode */\n private isSelectionMode = false;\n\n /** Whether the UI is showing detailed log view */\n private isDetailView = false;\n\n /** Whether log streaming is paused */\n private isPaused = false;\n\n /** Whether interactive mode is disabled */\n private isInteractiveDisabled: boolean;\n\n /** Buffer for logs received while paused */\n private pauseBuffer: LogEntry[] = [];\n\n /** Buffer for new logs in selection mode */\n private selectionBuffer: LogEntry[] = [];\n\n /** Index of currently selected log entry */\n private selectedIndex = 0;\n\n /** Current filter text for log searching */\n private filterText = \"\";\n\n /** Cached array of filtered log entries */\n private logs: LogEntry[] = [];\n\n /** Polling interval for checking new logs in detail view */\n private detailViewPollInterval: NodeJS.Timeout | null = null;\n\n /** Polling interval for checking new logs in selection view */\n private selectionViewPollInterval: NodeJS.Timeout | null = null;\n\n /** Current terminal width in characters */\n private termWidth: number = process.stdout.columns || 80;\n\n /**\n * Creates a new UIManager instance.\n * Sets up keyboard handling and cleanup handlers.\n *\n * @param renderer - Instance for handling log display\n * @param storage - Instance for log persistence\n * @param disableInteractiveMode - Whether to disable interactive mode\n */\n constructor(\n private renderer: LogRenderer,\n private storage: LogStorage,\n disableInteractiveMode = false,\n ) {\n this.isInteractiveDisabled = disableInteractiveMode;\n if (!this.isInteractiveDisabled) {\n this.setupKeyboardHandling();\n }\n // Update terminal width when window is resized\n process.stdout.on(\"resize\", () => {\n this.termWidth = process.stdout.columns || 80;\n // Re-render the current view\n if (this.isDetailView) {\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(entry, prevEntry, nextEntry, this.renderer.getDetailViewScrollPos());\n } else if (this.isSelectionMode) {\n this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);\n }\n });\n }\n\n /**\n * Sets up keyboard input handling and cleanup.\n * Configures raw mode for immediate key processing.\n * Sets up process exit handlers for cleanup.\n * @private\n */\n private setupKeyboardHandling(): void {\n keypress(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.on(\"keypress\", this.handleKeypress.bind(this));\n\n // Setup cleanup handlers for graceful exit\n const cleanup = () => {\n if (this.detailViewPollInterval) {\n clearInterval(this.detailViewPollInterval);\n }\n if (this.selectionViewPollInterval) {\n clearInterval(this.selectionViewPollInterval);\n }\n process.stdin.setRawMode(false);\n process.stdin.removeAllListeners(\"keypress\");\n console.clear();\n this.storage.close();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", cleanup); // Handle Ctrl+C\n process.on(\"SIGTERM\", cleanup); // Handle termination request\n }\n\n /**\n * Starts polling for new logs in selection view\n * @private\n */\n private startSelectionViewPolling(): void {\n // Clear any existing interval\n if (this.selectionViewPollInterval) {\n clearInterval(this.selectionViewPollInterval);\n }\n\n // Set up new polling interval\n this.selectionViewPollInterval = setInterval(() => {\n if (!this.isSelectionMode) {\n clearInterval(this.selectionViewPollInterval!);\n this.selectionViewPollInterval = null;\n return;\n }\n\n // Re-render with notification about buffered logs if any\n if (this.selectionBuffer.length > 0) {\n this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);\n }\n }, 2000); // Poll every 2 seconds\n }\n\n /**\n * Starts polling for new logs in detail view\n * @private\n */\n private startDetailViewPolling(): void {\n // Clear any existing interval\n if (this.detailViewPollInterval) {\n clearInterval(this.detailViewPollInterval);\n }\n\n // Set up new polling interval\n this.detailViewPollInterval = setInterval(() => {\n if (!this.isDetailView) {\n clearInterval(this.detailViewPollInterval!);\n this.detailViewPollInterval = null;\n return;\n }\n\n // Check if total count has changed\n const totalCount = this.filterText\n ? this.storage.getFilteredLogCount(this.filterText)\n : this.storage.getLogCount();\n if (totalCount !== this.logs.length) {\n // Only load the logs we need for display\n const storedLogs = this.filterText ? this.storage.searchLogs(this.filterText) : this.storage.getAllLogs();\n this.logs = storedLogs;\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n totalCount,\n this.filterText,\n );\n }\n }, 2000); // Poll every 2 seconds\n }\n\n /**\n * Updates the filtered list of logs based on search text.\n * Handles both full list and filtered views.\n * Maintains selection state when filter changes.\n * @private\n */\n private updateFilteredLogs(): void {\n // Get the total count first to check if we need to update\n const totalCount = this.filterText ? this.storage.getFilteredLogCount(this.filterText) : this.storage.getLogCount();\n const effectiveCount = totalCount - this.selectionBuffer.length;\n\n // Only reload logs if the count has changed\n if (effectiveCount !== this.logs.length) {\n // Always get fresh logs from storage, but don't include buffered logs\n const storedLogs = this.filterText ? this.storage.searchLogs(this.filterText) : this.storage.getAllLogs();\n this.logs = storedLogs.slice(0, storedLogs.length - this.selectionBuffer.length);\n\n // Ensure selection remains valid after filter\n if (this.logs.length > 0) {\n this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.logs.length - 1));\n } else {\n this.selectedIndex = 0;\n }\n }\n }\n\n private updateNewLogsNotification(): void {\n if (!this.isSelectionMode || !this.selectionBuffer.length) return;\n\n // Move cursor up 2 lines (to the line above the help text), clear it, and write notification\n process.stdout.write(`\\x1b[2A\\r${\" \".repeat(this.termWidth)}\\r`);\n const notification = chalk.dim(\n `${this.selectionBuffer.length} new log${this.selectionBuffer.length === 1 ? \"\" : \"s\"} available (press ↓ to view)`,\n );\n process.stdout.write(`${notification}\\n\\n`);\n }\n\n /**\n * Handles new log entries from the transport.\n * Stores the log and updates the display if needed.\n *\n * @param entry - New log entry to process\n */\n public handleNewLog(entry: LogEntry): void {\n this.storage.store(entry);\n\n // If interactive mode is disabled, always render in simple mode\n if (this.isInteractiveDisabled) {\n this.renderer.renderLogLine(entry);\n return;\n }\n\n // Buffer logs in selection mode\n if (this.isSelectionMode) {\n this.selectionBuffer.push(entry);\n this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);\n return;\n }\n\n // Only handle display in simple view mode (not in selection or detail view)\n if (!this.isDetailView) {\n if (this.isPaused) {\n // Add to pause buffer if paused\n this.pauseBuffer.push(entry);\n // Show pause indicator with buffer size\n process.stdout.write(`\\r${chalk.yellow(`⏸ Paused (${this.pauseBuffer.length} new logs)`)}${\" \".repeat(20)}`);\n } else {\n this.renderer.renderLogLine(entry);\n }\n }\n }\n\n /**\n * Processes keyboard input and manages UI state.\n * Handles navigation, mode switching, and filtering.\n *\n * Key mappings:\n * - CTRL+C: Exit application\n * - TAB: Toggle selection mode\n * - Up/Down: Navigate logs\n * - Enter: View log details\n * - Backspace: Edit filter\n * - P: Toggle pause in simple view\n * - Other keys: Add to filter\n *\n * @param ch - Character input if available\n * @param key - Key event information\n * @private\n */\n private handleKeypress(ch: string, key: any): void {\n // Handle application exit (CTRL+C)\n if (key?.ctrl && key?.name === \"c\") {\n process.stdin.setRawMode(false);\n process.stdin.removeAllListeners(\"keypress\");\n console.clear();\n this.storage.close();\n process.exit(0);\n return;\n }\n\n // Handle pause toggle in simple view\n if (!this.isSelectionMode && !this.isDetailView && ch === \"p\") {\n this.isPaused = !this.isPaused;\n if (!this.isPaused && this.pauseBuffer.length > 0) {\n // Clear the pause indicator\n process.stdout.write(`\\r${\" \".repeat(50)}\\r`);\n // Render buffered logs\n for (const entry of this.pauseBuffer) {\n this.renderer.renderLogLine(entry);\n }\n this.pauseBuffer = [];\n } else if (this.isPaused) {\n // Show initial pause indicator\n process.stdout.write(`\\r${chalk.yellow(\"⏸ Paused (0 new logs)\")}${\" \".repeat(20)}`);\n }\n return;\n }\n\n // Handle entering selection mode from simple view with up/down keys\n if (!this.isSelectionMode && !this.isDetailView && (key?.name === \"up\" || key?.name === \"down\")) {\n this.isSelectionMode = true;\n this.filterText = \"\";\n this.isPaused = true; // Pause the log stream when entering selection mode\n\n // Get all logs up to this point\n const storedLogs = this.storage.getAllLogs();\n this.logs = storedLogs;\n this.selectedIndex = key.name === \"up\" ? Math.max(0, this.logs.length - 1) : Math.max(0, this.logs.length - 1);\n\n this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);\n this.startSelectionViewPolling(); // Start polling when entering selection mode\n return;\n }\n\n // Handle condensed view toggle in simple view\n if (!this.isSelectionMode && !this.isDetailView && ch === \"c\") {\n // Cycle through view modes\n const newMode = this.renderer.cycleViewMode();\n // Clear screen and re-render all logs with new view mode\n console.clear();\n const logs = this.storage.getAllLogs();\n for (const entry of logs) {\n this.renderer.renderLogLine(entry);\n }\n // Show view mode indicator with appropriate description\n const modeDescriptions = {\n full: \"Full view enabled (all data shown without truncation)\",\n truncated: \"Truncated view enabled (timestamp, ID, level, message, truncated data)\",\n condensed: \"Condensed view enabled (timestamp, level and message only)\",\n };\n process.stdout.write(`\\r${chalk.cyan(`ℹ ${modeDescriptions[newMode]}`)}${\" \".repeat(20)}`);\n setTimeout(() => {\n process.stdout.write(`\\r${\" \".repeat(100)}\\r`);\n }, 3000);\n return;\n }\n\n // Handle selection mode navigation and filtering\n if (this.isSelectionMode) {\n if (key) {\n switch (key.name) {\n case \"up\": {\n // Move selection up\n this.selectedIndex = Math.max(0, this.selectedIndex - 1);\n this.renderer.renderSelectionView(\n this.logs,\n this.selectedIndex,\n this.filterText,\n this.selectionBuffer.length,\n );\n return;\n }\n case \"down\": {\n // Move selection down\n if (this.selectedIndex === this.logs.length - 1 && this.selectionBuffer.length > 0) {\n // Append buffered logs when user reaches the bottom\n this.logs.push(...this.selectionBuffer);\n this.selectionBuffer = [];\n }\n this.selectedIndex = Math.min(this.logs.length - 1, this.selectedIndex + 1);\n this.renderer.renderSelectionView(\n this.logs,\n this.selectedIndex,\n this.filterText,\n this.selectionBuffer.length,\n );\n return;\n }\n case \"return\": {\n // Enter detail view for selected log\n if (this.logs.length > 0) {\n this.isSelectionMode = false;\n this.isDetailView = true;\n console.clear(); // Clear console before entering detail view\n const selectedEntry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n selectedEntry,\n prevEntry,\n nextEntry,\n 0,\n this.selectedIndex + 1,\n this.logs.length,\n this.filterText,\n );\n this.startDetailViewPolling(); // Start polling when entering detail view\n }\n return;\n }\n case \"backspace\": {\n // Remove last character from filter\n if (this.filterText.length > 0) {\n this.filterText = this.filterText.slice(0, -1);\n this.updateFilteredLogs();\n this.renderer.renderSelectionView(\n this.logs,\n this.selectedIndex,\n this.filterText,\n this.selectionBuffer.length,\n );\n }\n return;\n }\n case \"tab\": {\n // Exit selection mode back to simple view\n this.isSelectionMode = false;\n this.isPaused = false; // Resume log stream when exiting selection mode\n if (this.selectionViewPollInterval) {\n clearInterval(this.selectionViewPollInterval);\n this.selectionViewPollInterval = null;\n }\n this.filterText = \"\";\n console.clear();\n // Re-render all logs in reverse chronological order\n const logs = this.storage.getAllLogs();\n for (const entry of logs) {\n this.renderer.renderLogLine(entry);\n }\n // Also render any buffered logs\n if (this.selectionBuffer.length > 0) {\n for (const entry of this.selectionBuffer) {\n this.renderer.renderLogLine(entry);\n }\n this.selectionBuffer = [];\n }\n return;\n }\n }\n }\n\n // Handle text input for filtering\n if (ch && (!key || (!key.ctrl && !key.meta)) && ch.length === 1) {\n this.filterText += ch;\n this.updateFilteredLogs();\n this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);\n return;\n }\n }\n\n // Handle detail view navigation\n if (this.isDetailView) {\n // Handle named keys\n if (key?.name) {\n switch (key.name) {\n case \"up\": {\n // Scroll up one line\n this.renderer.scrollDetailView(-1);\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n this.logs.length,\n this.filterText,\n );\n break;\n }\n case \"down\": {\n // Scroll down one line\n this.renderer.scrollDetailView(1);\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n this.logs.length,\n this.filterText,\n );\n break;\n }\n case \"left\": {\n // Show previous log in detail view\n if (this.selectedIndex > 0) {\n this.selectedIndex = Math.max(0, this.selectedIndex - 1);\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n 0,\n this.selectedIndex + 1,\n this.logs.length,\n this.filterText,\n );\n }\n break;\n }\n case \"right\": {\n // Show next log in detail view\n if (this.selectedIndex < this.logs.length - 1) {\n this.selectedIndex = Math.min(this.logs.length - 1, this.selectedIndex + 1);\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n 0,\n this.selectedIndex + 1,\n this.logs.length,\n this.filterText,\n );\n }\n break;\n }\n case \"tab\": {\n // If in JSON view, return to detail view\n if (this.renderer.isInJsonView()) {\n this.renderer.toggleJsonView();\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n this.logs.length,\n this.filterText,\n );\n break;\n }\n\n // Otherwise return to selection view\n this.isDetailView = false;\n if (this.detailViewPollInterval) {\n clearInterval(this.detailViewPollInterval);\n this.detailViewPollInterval = null;\n }\n this.isSelectionMode = true;\n this.updateFilteredLogs(); // Refresh logs when returning to selection view\n this.renderer.renderSelectionView(\n this.logs,\n this.selectedIndex,\n this.filterText,\n this.selectionBuffer.length,\n );\n break;\n }\n }\n }\n\n // Handle character inputs (Q/W for page scrolling, A/S for first/last, C for array toggle)\n if (ch) {\n switch (ch.toLowerCase()) {\n case \"w\": {\n // Scroll down one page\n this.renderer.scrollDetailView(process.stdout.rows - 8); // Account for header/footer space\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n this.logs.length,\n );\n break;\n }\n case \"q\": {\n // Scroll up one page\n this.renderer.scrollDetailView(-process.stdout.rows + 8); // Account for header/footer space\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n this.logs.length,\n );\n break;\n }\n case \"a\": {\n // Jump to first log\n if (this.selectedIndex !== 0) {\n this.selectedIndex = 0;\n const entry = this.logs[this.selectedIndex];\n const prevEntry = null; // No previous entry when at first log\n const nextEntry = this.logs.length > 1 ? this.logs[1] : null;\n this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, 1, this.logs.length);\n }\n break;\n }\n case \"s\": {\n // Jump to last log\n const lastIndex = this.logs.length - 1;\n if (this.selectedIndex !== lastIndex) {\n this.selectedIndex = lastIndex;\n const entry = this.logs[this.selectedIndex];\n const prevEntry = lastIndex > 0 ? this.logs[lastIndex - 1] : null;\n const nextEntry = null; // No next entry when at last log\n this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, this.logs.length, this.logs.length);\n }\n break;\n }\n case \"c\": {\n // Toggle array collapse\n this.renderer.toggleArrayCollapse();\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n this.logs.length,\n );\n break;\n }\n case \"j\": {\n // Toggle JSON view\n this.renderer.toggleJsonView();\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, this.selectedIndex + 1, this.logs.length);\n break;\n }\n }\n }\n }\n }\n}\n","/**\n * A transport for LogLayer that provides a pretty terminal output with interactive features.\n * This transport implements an interactive terminal UI for viewing and filtering logs.\n *\n * Features:\n * - Real-time log display with color-coded levels\n * - Interactive selection mode for browsing logs\n * - Detailed view for inspecting individual log entries\n * - Search/filter functionality\n * - JSON data pretty printing\n * - Configurable themes and colors\n *\n * The transport uses a singleton pattern to ensure only one instance exists,\n * as it manages terminal input and output which cannot be shared.\n */\n\nimport type { LogLayerTransportParams } from \"@loglayer/transport\";\nimport { LoggerlessTransport } from \"@loglayer/transport\";\nimport chalk from \"chalk\";\nimport { LogRenderer } from \"./LogRenderer.js\";\nimport { LogStorage } from \"./LogStorage.js\";\nimport { moonlight } from \"./themes.js\";\nimport type { DetailedViewConfig, PrettyTerminalConfig, ViewConfig } from \"./types.js\";\nimport { UIManager } from \"./UIManager.js\";\n\n/**\n * Main transport class that handles pretty terminal output and interactive features.\n * This class coordinates between different components:\n * - LogStorage: Handles persistence of logs in SQLite\n * - LogRenderer: Manages all rendering and formatting\n * - UIManager: Handles user interaction and view state\n *\n * The transport supports two main view modes:\n * 1. Simple View: Real-time log output with basic formatting\n * 2. Interactive View: Full-screen mode with navigation and filtering\n *\n * Usage:\n * ```typescript\n * const transport = PrettyTerminalTransport.getInstance({\n * maxInlineDepth: 4,\n * maxInlineLength: 120,\n * theme: customTheme\n * });\n * ```\n */\nexport class PrettyTerminalTransport extends LoggerlessTransport {\n /** Singleton instance of the transport */\n private static instance: PrettyTerminalTransport | null = null;\n\n /** Handles all rendering and formatting of logs */\n private renderer: LogRenderer;\n\n /** Manages log persistence in SQLite database */\n private storage: LogStorage;\n\n /** Manages user interaction and view state */\n private uiManager: UIManager;\n\n /** Configuration options */\n private config: PrettyTerminalConfig;\n\n /**\n * Creates a new PrettyTerminalTransport instance.\n * This is a singleton class - only one instance can exist at a time.\n * Use getInstance() instead of constructor directly.\n *\n * @param config - Configuration options for the transport\n * @throws Error if attempting to create multiple instances\n */\n constructor(config: PrettyTerminalConfig = {}) {\n if (PrettyTerminalTransport.instance) {\n throw new Error(\"PrettyTerminalTransport is a singleton. Use getPrettyTerminal() instead.\");\n }\n super(config);\n\n // Store configuration\n this.config = config;\n\n // If transport is disabled, don't initialize anything\n if (config.enabled === false) {\n return;\n }\n\n // Initialize configuration with defaults\n const maxInlineDepth = config.maxInlineDepth || 4;\n const maxInlineLength = config.maxInlineLength || 120;\n const theme = config.theme || moonlight;\n const logFile = config.logFile; // Get optional log file path from config\n\n // Initialize view configurations with defaults\n // Simple view is used for real-time log output\n const simpleViewConfig: Required<ViewConfig> = {\n colors: {\n trace: chalk.gray, // Lowest level, used for verbose output\n debug: chalk.blue, // Debug information\n info: chalk.green, // Normal operation\n warn: chalk.yellow, // Warning conditions\n error: chalk.red, // Error conditions\n fatal: chalk.bgRed.white, // Critical errors\n ...theme.simpleView.colors,\n },\n logIdColor: theme.simpleView.logIdColor || chalk.dim,\n dataValueColor: theme.simpleView.dataValueColor || chalk.white,\n dataKeyColor: theme.simpleView.dataKeyColor || chalk.dim,\n selectorColor: theme.simpleView.selectorColor || chalk.cyan,\n };\n\n // Detailed view is used in interactive mode\n const detailedViewConfig: Required<DetailedViewConfig> = {\n colors: {\n trace: chalk.gray,\n debug: chalk.blue,\n info: chalk.green,\n warn: chalk.yellow,\n error: chalk.red,\n fatal: chalk.bgRed.white,\n ...theme.detailedView?.colors,\n },\n logIdColor: theme.detailedView?.logIdColor || chalk.dim,\n dataValueColor: theme.detailedView?.dataValueColor || chalk.white,\n dataKeyColor: theme.detailedView?.dataKeyColor || chalk.dim,\n selectorColor: theme.detailedView?.selectorColor || chalk.cyan,\n headerColor: theme.detailedView?.headerColor || chalk.cyan,\n labelColor: theme.detailedView?.labelColor || chalk.cyan.bold,\n separatorColor: theme.detailedView?.separatorColor || chalk.dim,\n // JSON formatting colors for detailed data view\n jsonColors: {\n keysColor: chalk.yellow, // Object property names\n dashColor: chalk.white, // Array bullets\n numberColor: chalk.yellow, // Default number color\n stringColor: chalk.white, // Single-line strings\n multilineStringColor: chalk.white, // Multi-line strings\n positiveNumberColor: chalk.green, // Numbers > 0\n negativeNumberColor: chalk.red, // Numbers < 0\n booleanColor: chalk.cyan, // true/false values\n nullUndefinedColor: chalk.grey, // null/undefined\n dateColor: chalk.magenta, // Date objects\n ...theme.detailedView?.jsonColors,\n },\n };\n\n // Initialize components in dependency order\n this.storage = new LogStorage(logFile);\n this.renderer = new LogRenderer(simpleViewConfig, detailedViewConfig, maxInlineDepth, maxInlineLength);\n this.uiManager = new UIManager(this.renderer, this.storage, config.disableInteractiveMode);\n\n PrettyTerminalTransport.instance = this;\n }\n\n /**\n * Gets or creates the singleton instance of PrettyTerminalTransport.\n * This is the recommended way to obtain a transport instance.\n *\n * @param config - Configuration options for the transport\n * @returns The singleton instance of PrettyTerminalTransport\n */\n public static getInstance(config: PrettyTerminalConfig = {}): PrettyTerminalTransport {\n if (!PrettyTerminalTransport.instance) {\n PrettyTerminalTransport.instance = new PrettyTerminalTransport(config);\n }\n return PrettyTerminalTransport.instance;\n }\n\n /**\n * Generates a random ID for each log entry.\n * Uses base36 encoding for compact, readable IDs.\n *\n * @returns A 6-character string ID\n * @example\n * \"a1b2c3\" // Example generated ID\n */\n private generateId(): string {\n return Math.random().toString(36).substring(2, 8);\n }\n\n /**\n * Main transport method that receives logs from LogLayer.\n * This method is called for each log event and handles:\n * - Generating a unique ID for the log\n * - Converting the log data to a storable format\n * - Storing the log in the database\n * - Rendering the log if not in selection mode\n *\n * @param logLevel - The severity level of the log\n * @param messages - Array of message strings to be joined\n * @param data - Additional structured data to be logged\n * @param hasData - Whether the log includes additional data\n * @returns The original messages array\n */\n shipToLogger({ logLevel, messages, data, hasData }: LogLayerTransportParams): any[] {\n // If transport is disabled, return messages without processing\n if (this.config.enabled === false) {\n return messages;\n }\n\n const entry = {\n id: this.generateId(),\n timestamp: Date.now(),\n level: logLevel,\n message: messages.join(\" \"),\n data: hasData ? JSON.stringify(data) : null,\n };\n\n this.uiManager.handleNewLog(entry);\n return messages;\n }\n}\n","import { PrettyTerminalTransport } from \"./PrettyTerminalTransport.js\";\nimport type { PrettyTerminalConfig } from \"./types.js\";\n\nexport * as chalk from \"chalk\";\n\nexport * from \"./PrettyTerminalTransport.js\";\nexport * from \"./themes.js\";\nexport * from \"./types.js\";\n\nexport function getPrettyTerminal(config: PrettyTerminalConfig = {}) {\n return PrettyTerminalTransport.getInstance(config);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,SAAgB,OAAO,WAAW;AAChC,QAAO,IAAI,MAAM,YAAY,EAAE,CAAC,KAAK,IAAI;;;;;AAM3C,SAAgB,kBAAkB,OAAO;CACvC,IAAI,WAAW;AAEf,QAAO,oBAAoB,MAAM,CAAC,SAAS,QAAQ;AAEjD,MAAI,MAAM,SAAS,OACjB;AAGF,aAAW,KAAK,IAAI,UAAU,IAAI,OAAO;GACzC;AACF,QAAO;;AAGT,SAAgB,gBAAgB,WAAW;AACzC,KAAI,OAAO,cAAc,SACvB,QAAO;AAMT,KAAI,CAAC,4EAA4E,KAAK,UAAU,CAC9F,QAAO;CAET,MAAM,WAAW,IAAI,KAAK,UAAU;AACpC,QAAO,CAAC,OAAO,MAAM,SAAS,SAAS,CAAC;;;;;AC/B1C,MAAM,gBAAgB;AAGtB,MAAM,eAAe,OAAO,YAAY,UAAU,UAAa,QAAQ;AAGvE,MAAM,kBAAkB,OAAO,gBAAgB,YAAY;AACzD,KACE,OAAO,UAAU,aACjB,OAAO,UAAU,YACjB,OAAO,UAAU,cACjB,UAAU,QACV,UAAU,UACV,iBAAiB,KAEjB,QAAO;AAET,KAAI,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,KAAK,GACvD,QAAO;AAGT,KAAI,QAAQ,gBAAgB,CAAC,gBAC3B;MAAI,MAAM,QAAQ,MAAM,IAAI,eAAe,MAAM,IAAI,MAAM,QAAQ,CACjE,QAAO;;AAIX,QAAO;;;;;;AAOT,MAAM,oBAAoB,SAAS,YAAY;AAC7C,KAAI,QAAQ,QACV,SAAQ,SAAS;AAGnB,KAAI,OAAO,YAAY,WACrB,SAAQ,SAAS;AAGnB,QAAO;;AAGT,MAAM,kBAAkB,OAAO,YAAY;AACzC,KAAI,QAAQ,QACV,QAAO;AAGT,KAAI,iBAAiB,KACnB,QAAO,iBAAiB,QAAQ,WAAW,QAAQ,CAAC,MAAM,aAAa,CAAC;AAE1E,KAAI,OAAO,UAAU,UAAU;AAC7B,MAAI,gBAAgB,MAAM,CACxB,QAAO,iBAAiB,QAAQ,WAAW,QAAQ,CAAC,MAAM;AAG5D,SAAO,iBAAiB,QAAQ,aAAa,QAAQ,CAAC,MAAM;;CAG9D,MAAM,SAAS,GAAG;AAElB,KAAI,OAAO,UAAU,UACnB,QAAO,iBAAiB,QAAQ,cAAc,QAAQ,CAAC,OAAO;AAEhE,KAAI,UAAU,QAAQ,UAAU,OAC9B,QAAO,iBAAiB,QAAQ,oBAAoB,QAAQ,CAAC,OAAO;AAEtE,KAAI,OAAO,UAAU,UAAU;AAC7B,MAAI,SAAS,EACX,QAAO,iBAAiB,QAAQ,qBAAqB,QAAQ,CAAC,OAAO;AAEvE,SAAO,iBAAiB,QAAQ,qBAAqB,QAAQ,CAAC,OAAO;;AAEvE,KAAI,OAAO,UAAU,WACnB,QAAO;AAGT,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,MAAM,KAAK,KAAK;AAGzB,QAAO;;AAGT,MAAM,wBAAwB,SAAS,SAAS,iBAAiB,QAAQ,sBAAsB,QAAQ,CAAC,KAAK;AAE7G,MAAM,eAAe,QAAQ,QAAQ,YAAY;CAC/C,IAAI,QAAQ,OAAO,MAAM,KAAK;AAC9B,SAAQ,MAAM,KAAK,SAASA,OAAa,OAAO,GAAG,qBAAqB,SAAS,KAAK,CAAC;AACvF,QAAO,MAAM,KAAK,KAAK;;AAGzB,MAAM,iBAAiB,MAAM,SAAS,gBAAgB;AACpD,KAAI,OAAO,SAAS,YAAY,KAAK,MAAM,cAAc,IAAI,QAAQ,OACnE,QAAO,KAAK,UAAU,KAAK;AAG7B,KAAI,CAAC,YAAY,MAAM,QAAQ,CAC7B,QAAO,EAAE;AAGX,KAAI,eAAe,MAAM,OAAO,QAAQ,CACtC,QAAO,CAACA,OAAa,YAAY,GAAG,eAAe,MAAM,QAAQ,CAAC;AAIpE,KAAI,OAAO,SAAS,SAClB,QAAO;EACLA,OAAa,YAAY,GAAG,qBAAqB,SAAS,SAAM;EAChE,YAAY,MAAM,cAAc,QAAQ,oBAAoB,QAAQ;EACpEA,OAAa,YAAY,GAAG,qBAAqB,SAAS,SAAM;EACjE;AAGH,KAAI,MAAM,QAAQ,KAAK,EAAE;AAEvB,MAAI,KAAK,WAAW,EAClB,QAAO,CAACA,OAAa,YAAY,GAAG,QAAQ,cAAc;AAI5D,MAAI,QAAQ,kBAAkB,KAAK,SAAS,EAC1C,QAAO,CAAC,GAAGA,OAAa,YAAY,CAAC,OAAO,KAAK,OAAO,SAAS;EAGnE,MAAM,cAAc,EAAE;AAEtB,OAAK,SAAS,YAAY;AACxB,OAAI,CAAC,YAAY,SAAS,QAAQ,CAChC;GAIF,IAAI,OAAO;AACX,UAAO,iBAAiB,QAAQ,WAAW,QAAQ,CAAC,KAAK;AACzD,UAAOA,OAAa,YAAY,GAAG;AAInC,OAAI,eAAe,SAAS,OAAO,QAAQ,EAAE;AAC3C,YAAQ,cAAc,SAAS,SAAS,EAAE,CAAC;AAC3C,gBAAY,KAAK,KAAK;UAGjB;AACL,gBAAY,KAAK,KAAK;AACtB,gBAAY,KAAK,MAAM,aAAa,cAAc,SAAS,SAAS,cAAc,QAAQ,mBAAmB,CAAC;;IAEhH;AAEF,SAAO;;AAGT,KAAI,gBAAgB,MAClB,QAAO,cACL;EACE,SAAS,KAAK;EACd,OAAO,KAAK,MAAM,MAAM,KAAK;EAC9B,EACD,SACA,YACD;CAKH,MAAM,iBAAiB,QAAQ,UAAU,IAAIC,kBAAwB,KAAK;CAC1E,IAAI;CACJ,MAAM,SAAS,EAAE;AAEjB,QAAO,oBAAoB,KAAK,CAAC,SAAS,MAAM;AAC9C,MAAI,CAAC,YAAY,KAAK,IAAI,QAAQ,CAChC;AAIF,QAAM,GAAG,EAAE;AACX,QAAM,iBAAiB,QAAQ,WAAW,QAAQ,CAAC,IAAI;AACvD,QAAMD,OAAa,YAAY,GAAG;AAGlC,MAAI,eAAe,KAAK,IAAI,OAAO,QAAQ,EAAE;GAC3C,MAAM,kBAAkB,QAAQ,UAAU,IAAI,iBAAiB,EAAE;AACjE,UAAO,cAAc,KAAK,IAAI,SAAS,gBAAgB,CAAC;AACxD,UAAO,KAAK,IAAI;SAGX;AACL,UAAO,KAAK,IAAI;AAChB,UAAO,KAAK,MAAM,QAAQ,cAAc,KAAK,IAAI,SAAS,cAAc,QAAQ,mBAAmB,CAAC;;GAEtG;AACF,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BT,MAAM,iCAAiC,YAAY;AACjD,WAAU,WAAW,EAAE;AACvB,SAAQ,gBAAgB,QAAQ,iBAAiB;AACjD,SAAQ,YAAY,QAAQ,aAAa,cAAM;AAC/C,SAAQ,YAAY,QAAQ,aAAa,cAAM;AAC/C,SAAQ,eAAe,QAAQ,gBAAgB,cAAM;AACrD,SAAQ,qBAAqB,QAAQ,sBAAsB,cAAM;AACjE,SAAQ,cAAc,QAAQ,eAAe,cAAM;AACnD,SAAQ,sBAAsB,QAAQ,uBAAuB,QAAQ;AACrE,SAAQ,sBAAsB,QAAQ,uBAAuB,QAAQ;AACrE,SAAQ,YAAY,QAAQ,aAAa,cAAM;AAC/C,SAAQ,qBAAqB,QAAQ,sBAAsB;AAC3D,SAAQ,UAAU,CAAC,CAAC,QAAQ;AAC5B,SAAQ,UAAU,CAAC,CAAC,QAAQ;AAC5B,SAAQ,SAAS,CAAC,CAAC,QAAQ;AAC3B,SAAQ,kBAAkB,CAAC,CAAC,QAAQ;AACpC,SAAQ,iBAAiB,CAAC,CAAC,QAAQ;AAEnC,SAAQ,cAAc,QAAQ,eAAe;AAC7C,SAAQ,uBAAuB,QAAQ,wBAAwB,QAAQ,eAAe;AAEtF,QAAO;;;;;;;;;;;;;;;;;;;;;;AAsBT,SAAgB,OAAO,MAAM,SAAS,aAAa;AAEjD,eAAc,eAAe;AAC7B,WAAU,8BAA8B,QAAQ;AAEhD,QAAO,cAAc,MAAM,SAAS,YAAY,CAAC,KAAK,KAAK;;;;;;;;;ACzQ7D,SAAgB,gBAAgB,WAAmB,SAA0C;CAC3F,MAAM,OAAO,IAAI,KAAK,UAAU;AAChC,QAAO,QACL,GAAG,KAAK,UAAU,CAAC,UAAU,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,KAAK,YAAY,CAAC,UAAU,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,KAAK,YAAY,CAAC,UAAU,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,KAAK,iBAAiB,CAAC,UAAU,CAAC,SAAS,GAAG,IAAI,GACvM;;;;;AAMH,SAAgB,cAAc,OAAe,QAAyC;AACpF,QAAO,OAAO,UAAU,cAAM;;;;;AAMhC,SAAgB,YAAY,OAAY,WAAW,OAAe;AAChE,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,KAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO,MAAM,UAAU;AACpF,KAAI,UAAU,KAAM,QAAO;AAC3B,KAAI,UAAU,OAAW,QAAO;AAChC,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,WAAW,KAAK,UAAU,MAAM,GAAG;AACpE,KAAI,OAAO,UAAU,SAAU,QAAO,WAAW,KAAK,UAAU,MAAM,GAAG;AACzE,QAAO,MAAM,UAAU;;;;;AAMzB,SAAgB,iBACd,MACA,QACA,UACA,WACA,WAAW,OACH;AACR,KAAI,CAAC,KAAM,QAAO;CAElB,MAAME,QAAkB,EAAE;CAC1B,MAAM,YAAY,KAAU,SAAS,IAAI,QAAQ,MAAM;AACrD,MAAI,CAAC,YAAY,SAAS,SAAU;AAEpC,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,EAAE;GAC9C,MAAM,UAAU,SAAS,GAAG,OAAO,GAAG,QAAQ;AAE9C,OAAI,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,MAAM,CAC7D,KAAI,SACF,OAAM,KAAK,GAAG,OAAO,aAAa,QAAQ,CAAC,GAAG,OAAO,eAAe,KAAK,UAAU,MAAM,CAAC,GAAG;OAE7F,UAAS,OAAO,SAAS,QAAQ,EAAE;OAGrC,OAAM,KAAK,GAAG,OAAO,aAAa,QAAQ,CAAC,GAAG,OAAO,eAAe,YAAY,OAAO,SAAS,CAAC,GAAG;;;AAK1G,UAAS,KAAK;CACd,MAAM,SAAS,MAAM,KAAK,IAAI;AAC9B,QAAO,WAAW,mCAAkB,QAAQ,UAAU;;;;;;;;;;;;;ACtDxD,IAAa,aAAb,MAAwC;CACtC,AAAQ;CACR,AAAQ;CACR,AAAQ,oBAA8B,EAAE;CAExC,YAAY,QAA0B;AACpC,OAAK,SAAS;AACd,OAAK,YAAY,QAAQ,OAAO,WAAW;;CAG7C,AAAO,oBAAoB,OAAqB;AAC9C,OAAK,YAAY;;;;;CAMnB,AAAQ,qBAAqB,OAAwB,SAAS,IAAY;AACxE,MAAI,CAAC,MAAO,QAAO;EAEnB,MAAM,aAAa,cAAc,MAAM,OAAO,KAAK,OAAO,OAAO,OAAO;EACxE,MAAM,QAAQ,KAAK,OAAO,OAAO,WAAW,IAAI,MAAM,GAAG,GAAG;EAC5D,MAAM,OAAO,GAAG,SAAS,WAAW,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM;AACjF,SAAO,KAAK,OAAO,OAAO,sCAAoB,MAAM,KAAK,WAAW,EAAE,MAAM,MAAM,CAAC,CAAC;;;;;CAMtF,AAAQ,mBAAmB,WAAyB;EAElD,MAAM,0BADM,IAAI,MAAM,EACH,SAAS,GAAG,UAAU,SAAS;EAClD,MAAM,WAAW,KAAK,MAAM,SAAS,IAAK;EAC1C,MAAM,WAAW,KAAK,MAAM,WAAW,GAAG;EAC1C,MAAM,YAAY,KAAK,MAAM,WAAW,GAAG;EAC3C,MAAM,WAAW,KAAK,MAAM,YAAY,GAAG;AAE3C,MAAI,WAAW,GAAI,QAAO,GAAG,SAAS;AACtC,MAAI,WAAW,GAAI,QAAO,GAAG,SAAS;AACtC,MAAI,YAAY,GAAI,QAAO,GAAG,UAAU;AACxC,MAAI,aAAa,EAAG,QAAO;AAC3B,MAAI,WAAW,GAAI,QAAO,GAAG,SAAS;AAEtC,SAAO,UAAU,oBAAoB;;CAGvC,AAAO,SAAe;AACpB,UAAQ,OAAO;AAGf,UAAQ,IAAI,KAAK,OAAO,EAAE,CAAC;AAG3B,MAAI,KAAK,OAAO,YAAY;AAC1B,OAAI,KAAK,OAAO,MAAM,KACpB,SAAQ,IAAI,KAAK,UAAU,KAAK,MAAM,KAAK,OAAO,MAAM,KAAK,CAAC,CAAC;OAE/D,SAAQ,IAAI,KAAK;AAEnB,WAAQ,IAAI,KAAK,KAAK,OAAO,OAAO,eAAe,iCAAiC,GAAG;AACvF;;EAIF,MAAMC,gBAA0B,EAAE;AAClC,MAAI,KAAK,OAAO,WAAW;GACzB,MAAM,WAAW,KAAK,qBAAqB,KAAK,OAAO,WAAW,KAAK;AACvE,iBAAc,KAAK,SAAS;AAC5B,iBAAc,KAAK,KAAK,OAAO,OAAO,eAAe,IAAI,OAAO,KAAK,UAAU,CAAC,CAAC;;EAInF,MAAMC,gBAA0B,EAAE;AAClC,MAAI,KAAK,OAAO,WAAW;AACzB,iBAAc,KAAK,KAAK,OAAO,OAAO,eAAe,IAAI,OAAO,KAAK,UAAU,CAAC,CAAC;GACjF,MAAM,WAAW,KAAK,qBAAqB,KAAK,OAAO,WAAW,KAAK;AACvE,iBAAc,KAAK,SAAS;;AAE9B,gBAAc,KAAK,GAAG;AACtB,gBAAc,KAAK,KAAK,OAAO,OAAO,eAAe,6CAA6C,CAAC;AACnG,gBAAc,KAAK,KAAK,OAAO,OAAO,eAAe,sDAAsD,CAAC;EAG5G,MAAMC,cAAwB,EAAE;EAChC,MAAM,aAAa,cAAc,KAAK,OAAO,MAAM,OAAO,KAAK,OAAO,OAAO,OAAO;EAGpF,IAAI,aAAa,mBAAmB,KAAK,OAAO,MAAM,GAAG,KAAK,KAAK,OAAO,gBAAgB,KAAK,KAAK,OAAO,UAAU;AACrH,MAAI,KAAK,OAAO,WACd,eAAc,aAAa,KAAK,OAAO,WAAW;AAEpD,gBAAc;EAEd,MAAM,SAAS,WAAW,WAAW;AACrC,cAAY,KAAK,OAAO;EAGxB,MAAM,YAAY,IAAI,KAAK,KAAK,OAAO,MAAM,UAAU;EACvD,MAAM,UAAU,gBAAgB,KAAK,OAAO,MAAM,WAAW,KAAK,OAAO,OAAO,eAAe;EAC/F,MAAM,eAAe,KAAK,mBAAmB,UAAU;AACvD,cAAY,KAAK,GAAG,KAAK,OAAO,OAAO,WAAW,aAAa,CAAC,GAAG,QAAQ,IAAI,aAAa,GAAG;AAE/F,cAAY,KACV,GAAG,KAAK,OAAO,OAAO,WAAW,SAAS,CAAC,GAAG,WAAW,KAAK,KAAK,OAAO,MAAM,MAAM,aAAa,CAAC,GACrG;AAED,MAAI,KAAK,OAAO,MAAM,QACpB,aAAY,KACV,GAAG,KAAK,OAAO,OAAO,WAAW,WAAW,CAAC,GAAG,KAAK,OAAO,OAAO,eAAe,KAAK,OAAO,MAAM,QAAQ,GAC7G;MAED,aAAY,KACV,GAAG,KAAK,OAAO,OAAO,WAAW,WAAW,CAAC,GAAG,KAAK,OAAO,OAAO,eAAe,IAAI,eAAe,GACtG;AAIH,MAAI,KAAK,OAAO,MAAM,MAAM;AAC1B,eAAY,KAAK,KAAK,OAAO,OAAO,WAAW,UAAU,CAAC;GAC1D,MAAM,YAAYC,OACR,KAAK,MAAM,KAAK,OAAO,MAAM,KAAK,EAAE;IAC1C,GAAG,KAAK,OAAO,OAAO;IACtB,oBAAoB;IACpB,gBAAgB,KAAK,OAAO;IAC7B,CAAC,CACD,MAAM,KAAK;AACd,eAAY,KAAK,GAAG,UAAU;;AAIhC,OAAK,oBAAoB;EAGzB,MAAM,eAAe,cAAc;EACnC,MAAM,eAAe,cAAc;EAInC,MAAM,kBAAkB,KAAK,IAC3B,GACA,QAAQ,OAAO,OAAO,eAAe,eALV,IACT,IACD,EAIlB;AAGD,OAAK,MAAM,QAAQ,cACjB,SAAQ,IAAI,KAAK;AAInB,MAAI,KAAK,OAAO,YAAY,EAC1B,SAAQ,IAAI,cAAM,IAAI,uBAAuB,CAAC;EAIhD,MAAM,aAAa,KAAK,OAAO;EAC/B,MAAM,iBAAiB,YAAY,MAAM,YAAY,aAAa,gBAAgB;AAClF,OAAK,MAAM,QAAQ,eACjB,SAAQ,IAAI,KAAK;AAInB,MAAI,KAAK,OAAO,YAAY,kBAAkB,YAAY,OACxD,SAAQ,IAAI,cAAM,IAAI,uBAAuB,CAAC;MAE9C,SAAQ,IAAI,cAAM,IAAI,iBAAiB,CAAC;AAI1C,OAAK,MAAM,QAAQ,cACjB,SAAQ,IAAI,KAAK;;;;;CAOrB,AAAO,uBAA+B;EACpC,MAAM,eAAe,KAAK,OAAO,YAAY,IAAI;EAKjD,MAAM,kBAAkB,KAAK,IAC3B,GACA,QAAQ,OAAO,OAAO,eANH,IACQ,IACT,IACD,EAIlB;AAED,SAAO,KAAK,IAAI,GAAG,KAAK,kBAAkB,SAAS,gBAAgB;;;;;;;;;;;;;;AC7LvE,IAAa,gBAAb,MAA2C;CACzC,AAAQ;CACR,AAAQ;CAER,YAAY,QAA6B;AACvC,OAAK,SAAS;AACd,OAAK,YAAY,QAAQ,OAAO,WAAW;;CAG7C,AAAO,oBAAoB,OAAqB;AAC9C,OAAK,YAAY;;CAGnB,AAAO,SAAe;AACpB,UAAQ,OAAO;AAGf,UAAQ,IAAI,KAAK,OAAO,EAAE,CAAC;EAG3B,MAAM,eAAe,KAAK,OAAO,aAAa,IAAI;EAGlD,MAAM,kBAAkB,QAAQ,OAAO,OAAO,eAFzB,IACF;AAGnB,MAAI,KAAK,OAAO,KAAK,WAAW,EAC9B,SAAQ,IAAI,cAAM,OAAO,yBAAyB,CAAC;OAC9C;GAEL,MAAM,eAAe,KAAK,IAAI,iBAAiB,GAAG;GAGlD,IAAI,WAAW,KAAK,IAAI,GAAG,KAAK,OAAO,iBAAiB,eAFlC,IAEiE,GAAG;GAC1F,MAAM,SAAS,KAAK,IAAI,KAAK,OAAO,KAAK,QAAQ,WAAW,aAAa;AAGzE,OAAI,SAAS,WAAW,gBAAgB,SAAS,KAAK,OAAO,KAAK,OAChE,YAAW,KAAK,IAAI,GAAG,SAAS,aAAa;AAI/C,OAAI,WAAW,EACb,SAAQ,IAAI,cAAM,IAAI,sBAAsB,CAAC;AAI/C,QAAK,OAAO,KAAK,MAAM,UAAU,OAAO,CAAC,SAAS,OAAO,UAAU;IAEjE,MAAM,aADc,WAAW,UACI,KAAK,OAAO;IAW/C,MAAM,qCADW,GATF,aAAa,KAAK,OAAO,OAAO,cAAc,KAAK,GAAG,OACnD,gBAAgB,MAAM,WAAW,KAAK,OAAO,OAAO,WAAW,CAQ1C,GAPpB,cAAc,MAAM,OAAO,KAAK,OAAO,OAAO,OAAO,CAC7C,GAAG,MAAM,MAAM,aAAa,CAAC,GAAG,GAC7C,cAAM,IAAI,IAAI,MAAM,GAAG,GAAG,CAKkB,GAJ1C,MAAM,UACT,MAAM,OAAO,IAAI,iBAAiB,KAAK,MAAM,MAAM,KAAK,EAAE,KAAK,OAAO,QAAQ,GAAG,GAAG,KAAK,KAAK,MAIxE,KAAK,YAAY,GAAG,EAAE,MAAM,MAAM,CAAC;AAEtE,QAAI,YAAY;KAEd,MAAM,QAAQ,YAAY,MAAM,KAAK;AACrC,aAAQ,IAAI,MAAM,GAAG;AACrB,UAAK,MAAM,QAAQ,MAAM,MAAM,EAAE,CAC/B,SAAQ,IAAI,KAAK,KAAK,OAAO,OAAO,cAAc,IAAI,CAAC,GAAG,OAAO;UAGnE,SAAQ,IAAI,YAAY;KAE1B;AAGF,OAAI,SAAS,KAAK,OAAO,KAAK,UAAU,KAAK,OAAO,cAAc,GAAG;IACnE,MAAM,eACJ,KAAK,OAAO,cAAc,IACtB,KAAK,OAAO,OAAO,cACjB,OAAO,KAAK,OAAO,YAAY,UAAU,KAAK,OAAO,gBAAgB,IAAI,KAAK,IAAI,8BACnF,GACD,cAAM,IAAI,sBAAsB;AACtC,YAAQ,IAAI,aAAa;;;AAK7B,UAAQ,IAAI,cAAM,IAAI,yDAAyD,CAAC;AAGhF,MAAI,KAAK,OAAO,YAAY;AAC1B,WAAQ,IAAI,cAAM,IAAI,IAAI,OAAO,KAAK,UAAU,CAAC,CAAC;AAClD,WAAQ,IAAI,cAAM,KAAK,UAAU,EAAE,cAAM,MAAM,KAAK,OAAO,WAAW,CAAC;;;;;;;;;;;;;;AC5F7E,IAAa,aAAb,MAAwC;CACtC,AAAQ;CACR,AAAQ;CAER,YAAY,QAA0B;AACpC,OAAK,SAAS;AACd,OAAK,YAAY,QAAQ,OAAO,WAAW;;CAG7C,AAAO,oBAAoB,OAAqB;AAC9C,OAAK,YAAY;;;;;CAMnB,AAAO,cAAc,OAAuB;EAE1C,MAAM,UADa,cAAc,MAAM,OAAO,KAAK,OAAO,OAAO,OAAO,CAC7C,KAAK,MAAM,MAAM,aAAa,CAAC,GAAG;EAC7D,MAAM,UAAU,MAAM,WAAW;EACjC,MAAM,YAAY,gBAAgB,MAAM,WAAW,KAAK,OAAO,OAAO,WAAW;AAEjF,UAAQ,KAAK,OAAO,UAApB;GACE,KAAK,aAAa;IAEhB,MAAM,gBAAgB,GAAG,UAAU,GAAG,UAAU;AAChD,YAAQ,2BAAS,eAAe,KAAK,WAAW,EAAE,MAAM,MAAM,CAAC,CAAC;AAChE;;GAGF,KAAK,QAAQ;IAEX,MAAM,QAAQ,KAAK,OAAO,OAAO,WAAW,IAAI,MAAM,GAAG,GAAG;IAC5D,MAAM,WAAW,MAAM,OACnB,iBACE,KAAK,MAAM,MAAM,KAAK,EACtB,KAAK,OAAO,QACZ,KAAK,OAAO,gBACZ,KAAK,OAAO,iBACZ,KACD,GACD;IACJ,MAAM,eAAe,GAAG,UAAU,GAAG,UAAU,MAAM,GAAG,UAAU,WAAW,IAAI,aAAa;AAC9F,YAAQ,2BAAS,cAAc,KAAK,WAAW,EAAE,MAAM,MAAM,CAAC,CAAC;AAC/D;;GAGF,SAAS;IAGP,MAAM,QAAQ,KAAK,OAAO,OAAO,WAAW,IAAI,MAAM,GAAG,GAAG;IAC5D,MAAM,aAAa,MAAM,OACrB,iBACE,KAAK,MAAM,MAAM,KAAK,EACtB,KAAK,OAAO,QACZ,KAAK,OAAO,gBACZ,KAAK,OAAO,gBACb,GACD;IACJ,MAAM,aAAa,GAAG,UAAU,GAAG,UAAU,MAAM,GAAG,UAAU,aAAa,IAAI,eAAe;AAChG,YAAQ,2BAAS,YAAY,KAAK,WAAW,EAAE,MAAM,MAAM,CAAC,CAAC;AAC7D;;;;CAKN,AAAO,SAAe;AACpB,QAAM,IAAI,MAAM,kFAAkF;;;;;;;;;;;;;ACrDtG,IAAa,cAAb,MAAyB;;CAEvB,AAAQ;;CAGR,AAAQ;;CAGR,AAAQ;;CAGR,AAAQ,oBAAoB;;CAG5B,AAAQ,WAA+C;;CAGvD,AAAQ;;CAGR,AAAQ;;CAGR,AAAQ,aAAa;;CAGrB,AAAQ,sBAAsB;;CAG9B,AAAQ;CACR,AAAQ,aAAgC;CACxC,AAAQ,gBAAsC;;;;;;;;;CAU9C,YACE,kBACA,oBACA,gBACA,iBACA;AACA,OAAK,mBAAmB;AACxB,OAAK,qBAAqB;AAC1B,OAAK,iBAAiB;AACtB,OAAK,kBAAkB;AACvB,OAAK,YAAY,QAAQ,OAAO,WAAW;AAG3C,OAAK,aAAa,IAAI,WAAW;GAC/B,UAAU,KAAK;GACf,gBAAgB,KAAK;GACrB,iBAAiB,KAAK;GACtB,QAAQ,KAAK;GACd,CAAC;AAGF,OAAK,aAAa;AAGlB,OAAK,gBAAgB;AAGrB,UAAQ,OAAO,GAAG,gBAAgB;AAChC,QAAK,YAAY,QAAQ,OAAO,WAAW;AAC3C,QAAK,WAAW,oBAAoB,KAAK,UAAU;AACnD,OAAI,KAAK,WACP,MAAK,WAAW,oBAAoB,KAAK,UAAU;AAErD,OAAI,KAAK,cACP,MAAK,cAAc,oBAAoB,KAAK,UAAU;IAExD;;;;;;;;;;CAWJ,AAAO,cAAc,OAAuB;AAC1C,OAAK,WAAW,cAAc,MAAM;;;;;;;;;;;;;;CAetC,AAAO,iBACL,OACA,WACA,WACA,YAAY,GACZ,iBACA,WACA,aAAa,IACP;EAEN,MAAM,SAAS;GACb;GACA;GACA;GACA;GACA,mBAAmB,KAAK;GACxB,YAAY,KAAK;GACjB,iBAAiB,oBAAoB,YAAY,IAAI,YAAY,IAAI;GACrE,WAAW,aAAa;GACxB;GACA,QAAQ,KAAK;GACd;AAGD,MAAI,CAAC,KAAK,WACR,MAAK,aAAa,IAAI,WAAW,OAAO;MAExC,MAAK,aAAa,IAAI,WAAW,OAAO;AAG1C,OAAK,WAAW,QAAQ;;;;;;CAO1B,AAAO,iBAAiB,OAAqB;AAC3C,MAAI,CAAC,KAAK,WAAY;EAEtB,MAAM,YAAY,KAAK,WAAW,sBAAsB;AACxD,OAAK,sBAAsB,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW,KAAK,sBAAsB,MAAM,CAAC;;;;;CAM/F,AAAO,yBAAiC;AACtC,SAAO,KAAK;;;;;;;;;;;CAYd,AAAO,oBAAoB,MAAkB,eAAuB,YAAoB,aAA2B;EAEjH,MAAM,SAAS;GACb;GACA;GACA;GACA;GACA,QAAQ,KAAK;GACd;AAGD,MAAI,CAAC,KAAK,cACR,MAAK,gBAAgB,IAAI,cAAc,OAAO;MAE9C,MAAK,gBAAgB,IAAI,cAAc,OAAO;AAGhD,OAAK,cAAc,QAAQ;;;;;CAM7B,AAAO,iBAAuB;AAC5B,OAAK,aAAa,CAAC,KAAK;;;;;CAM1B,AAAO,eAAwB;AAC7B,SAAO,KAAK;;;;;CAMd,AAAO,sBAA4B;AACjC,OAAK,oBAAoB,CAAC,KAAK;;;;;CAMjC,AAAO,gBAAwB;AAC7B,UAAQ,KAAK,UAAb;GACE,KAAK;AACH,SAAK,WAAW;AAChB;GACF,KAAK;AACH,SAAK,WAAW;AAChB;GACF,KAAK;AACH,SAAK,WAAW;AAChB;;AAIJ,OAAK,aAAa,IAAI,WAAW;GAC/B,UAAU,KAAK;GACf,gBAAgB,KAAK;GACrB,iBAAiB,KAAK;GACtB,QAAQ,KAAK;GACd,CAAC;AAEF,SAAO,KAAK;;;;;CAMd,AAAO,cAAsB;AAC3B,SAAO,KAAK;;;;;;;;;;;;;;;;;;;;;AClPhB,IAAa,aAAb,MAAwB;;CAEtB,AAAQ;;;;;;;;;CAUR,YAAY,SAAkB;AAG5B,OAAK,KAAK,IAAIC,uBADC,UAAW,QAAQ,WAAW,IAAI,GAAG,iCAAkB,QAAQ,KAAK,EAAE,QAAQ,GAAI,WACnE;AAC9B,OAAK,oBAAoB;;;;;;;;CAS3B,AAAQ,qBAA2B;AACjC,OAAK,GAAG,KAAK;;;;;;;;;MASX;;;;;;;;;;;;;;;;CAiBJ,AAAO,MAAM,OAAuB;AAClC,OAAK,GACF,QAAQ;;;QAGP,CACD,IAAI,MAAM,IAAI,MAAM,WAAW,MAAM,OAAO,MAAM,SAAS,MAAM,KAAK;;;;;;;;CAS3E,AAAO,aAAyB;AAC9B,SAAO,KAAK,GAAG,QAAQ,4CAA4C,CAAC,KAAK;;;;;;;;;;;;;;;CAgB3E,AAAO,WAAW,YAAgC;EAChD,MAAM,QAAQ;;;;;;;EAOd,MAAM,UAAU,IAAI,WAAW;AAC/B,SAAO,KAAK,GAAG,QAAQ,MAAM,CAAC,IAAI,SAAS,SAAS,QAAQ;;;;;;;;CAS9D,AAAO,cAAsB;AAE3B,SADe,KAAK,GAAG,QAAQ,qCAAqC,CAAC,KAAK,CAC5D;;;;;;;;;CAUhB,AAAO,oBAAoB,YAA4B;EACrD,MAAM,QAAQ;;;;;;EAMd,MAAM,UAAU,IAAI,WAAW;AAE/B,SADe,KAAK,GAAG,QAAQ,MAAM,CAAC,IAAI,SAAS,SAAS,QAAQ,CACtD;;;;;;CAOhB,AAAO,QAAc;AACnB,OAAK,GAAG,OAAO;;;;;;;;;;;;;;;;;;;;ACtInB,MAAaC,YAAiC;CAC5C,YAAY;EACV,QAAQ;GACN,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,MAAM,cAAM,IAAI,KAAK,KAAK,IAAI;GAC9B,MAAM,cAAM,IAAI,KAAK,KAAK,IAAI;GAC9B,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,OAAO,cAAM,MAAM,KAAK,KAAK,IAAI,CAAC;GACnC;EACD,YAAY,cAAM,IAAI,IAAI,IAAI,IAAI;EAClC,gBAAgB,cAAM,IAAI,KAAK,KAAK,IAAI;EACxC,cAAc,cAAM,IAAI,KAAK,KAAK,IAAI;EACtC,eAAe,cAAM,IAAI,KAAK,KAAK,IAAI;EACxC;CACD,cAAc;EACZ,QAAQ;GACN,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,MAAM,cAAM,IAAI,KAAK,KAAK,IAAI;GAC9B,MAAM,cAAM,IAAI,KAAK,KAAK,IAAI;GAC9B,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,OAAO,cAAM,MAAM,KAAK,KAAK,IAAI,CAAC;GACnC;EACD,YAAY,cAAM,IAAI,IAAI,IAAI,IAAI;EAClC,gBAAgB,cAAM,IAAI,KAAK,KAAK,IAAI;EACxC,cAAc,cAAM,IAAI,KAAK,KAAK,IAAI;EACtC,eAAe,cAAM,IAAI,KAAK,KAAK,IAAI;EACvC,aAAa,cAAM,IAAI,KAAK,KAAK,IAAI;EACrC,YAAY,cAAM,IAAI,KAAK,KAAK,IAAI,CAAC;EACrC,gBAAgB,cAAM,IAAI,IAAI,IAAI,IAAI;EACtC,YAAY;GACV,WAAW,cAAM,IAAI,KAAK,KAAK,IAAI;GACnC,WAAW,cAAM,IAAI,KAAK,KAAK,IAAI;GACnC,aAAa,cAAM,IAAI,KAAK,KAAK,IAAI;GACrC,aAAa,cAAM,IAAI,KAAK,KAAK,IAAI;GACrC,sBAAsB,cAAM,IAAI,KAAK,KAAK,IAAI;GAC9C,qBAAqB,cAAM,IAAI,KAAK,KAAK,IAAI;GAC7C,qBAAqB,cAAM,IAAI,KAAK,KAAK,IAAI;GAC7C,cAAc,cAAM,IAAI,KAAK,KAAK,IAAI;GACtC,oBAAoB,cAAM,IAAI,KAAK,KAAK,IAAI;GAC5C,WAAW,cAAM,IAAI,KAAK,KAAK,IAAI;GACpC;EACF;CACF;;;;;;;;;;;;;;;;AAiBD,MAAaC,WAAgC;CAC3C,YAAY;EACV,QAAQ;GACN,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,OAAO,cAAM,IAAI,IAAI,IAAI,IAAI;GAC7B,MAAM,cAAM,IAAI,IAAI,KAAK,GAAG;GAC5B,MAAM,cAAM,IAAI,KAAK,IAAI,EAAE;GAC3B,OAAO,cAAM,IAAI,KAAK,GAAG,EAAE;GAC3B,OAAO,cAAM,MAAM,KAAK,GAAG,EAAE,CAAC;GAC/B;EACD,YAAY,cAAM,IAAI,KAAK,KAAK,IAAI;EACpC,gBAAgB,cAAM,IAAI,GAAG,GAAG,EAAE;EAClC,cAAc,cAAM,IAAI,IAAI,IAAI,IAAI;EACpC,eAAe,cAAM,IAAI,GAAG,IAAI,IAAI;EACrC;CACD,cAAc;EACZ,QAAQ;GACN,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,OAAO,cAAM,IAAI,IAAI,IAAI,IAAI;GAC7B,MAAM,cAAM,IAAI,IAAI,KAAK,GAAG;GAC5B,MAAM,cAAM,IAAI,KAAK,IAAI,EAAE;GAC3B,OAAO,cAAM,IAAI,KAAK,GAAG,EAAE;GAC3B,OAAO,cAAM,MAAM,KAAK,GAAG,EAAE,CAAC;GAC/B;EACD,YAAY,cAAM,IAAI,KAAK,KAAK,IAAI;EACpC,gBAAgB,cAAM,IAAI,GAAG,GAAG,EAAE;EAClC,cAAc,cAAM,IAAI,IAAI,IAAI,IAAI;EACpC,eAAe,cAAM,IAAI,GAAG,IAAI,IAAI;EACpC,aAAa,cAAM,IAAI,GAAG,IAAI,IAAI;EAClC,YAAY,cAAM,IAAI,GAAG,IAAI,IAAI,CAAC;EAClC,gBAAgB,cAAM,IAAI,KAAK,KAAK,IAAI;EACxC,YAAY;GACV,WAAW,cAAM,IAAI,IAAI,IAAI,IAAI;GACjC,WAAW,cAAM,IAAI,GAAG,GAAG,EAAE;GAC7B,aAAa,cAAM,IAAI,KAAK,IAAI,GAAG;GACnC,aAAa,cAAM,IAAI,IAAI,KAAK,GAAG;GACnC,sBAAsB,cAAM,IAAI,IAAI,KAAK,GAAG;GAC5C,qBAAqB,cAAM,IAAI,IAAI,KAAK,GAAG;GAC3C,qBAAqB,cAAM,IAAI,KAAK,IAAI,GAAG;GAC3C,cAAc,cAAM,IAAI,KAAK,IAAI,EAAE;GACnC,oBAAoB,cAAM,IAAI,KAAK,KAAK,IAAI;GAC5C,WAAW,cAAM,IAAI,KAAK,IAAI,IAAI;GACnC;EACF;CACF;;;;;;;;;;;;;;;AAgBD,MAAaC,OAA4B;CACvC,YAAY;EACV,QAAQ;GACN,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,OAAO,cAAM,IAAI,KAAK,IAAI,IAAI;GAC9B,MAAM,cAAM,IAAI,GAAG,KAAK,IAAI;GAC5B,MAAM,cAAM,IAAI,KAAK,KAAK,GAAG;GAC7B,OAAO,cAAM,IAAI,KAAK,IAAI,GAAG;GAC7B,OAAO,cAAM,MAAM,KAAK,IAAI,GAAG,CAAC,IAAI,GAAG,KAAK,IAAI;GACjD;EACD,YAAY,cAAM,IAAI,KAAK,KAAK,IAAI;EACpC,gBAAgB,cAAM,IAAI,KAAK,KAAK,IAAI;EACxC,cAAc,cAAM,IAAI,GAAG,KAAK,IAAI;EACpC,eAAe,cAAM,IAAI,GAAG,KAAK,IAAI;EACtC;CACD,cAAc;EACZ,QAAQ;GACN,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,OAAO,cAAM,IAAI,KAAK,IAAI,IAAI;GAC9B,MAAM,cAAM,IAAI,GAAG,KAAK,IAAI;GAC5B,MAAM,cAAM,IAAI,KAAK,KAAK,GAAG;GAC7B,OAAO,cAAM,IAAI,KAAK,IAAI,GAAG;GAC7B,OAAO,cAAM,MAAM,KAAK,IAAI,GAAG,CAAC,IAAI,GAAG,KAAK,IAAI;GACjD;EACD,YAAY,cAAM,IAAI,KAAK,KAAK,IAAI;EACpC,gBAAgB,cAAM,IAAI,KAAK,KAAK,IAAI;EACxC,cAAc,cAAM,IAAI,GAAG,KAAK,IAAI;EACpC,eAAe,cAAM,IAAI,GAAG,KAAK,IAAI;EACrC,aAAa,cAAM,IAAI,KAAK,IAAI,IAAI;EACpC,YAAY,cAAM,IAAI,KAAK,IAAI,IAAI,CAAC;EACpC,gBAAgB,cAAM,IAAI,KAAK,KAAK,IAAI;EACxC,YAAY;GACV,WAAW,cAAM,IAAI,GAAG,KAAK,IAAI;GACjC,WAAW,cAAM,IAAI,KAAK,KAAK,IAAI;GACnC,aAAa,cAAM,IAAI,KAAK,IAAI,IAAI;GACpC,aAAa,cAAM,IAAI,GAAG,KAAK,IAAI;GACnC,sBAAsB,cAAM,IAAI,GAAG,KAAK,IAAI;GAC5C,qBAAqB,cAAM,IAAI,GAAG,KAAK,IAAI;GAC3C,qBAAqB,cAAM,IAAI,KAAK,IAAI,GAAG;GAC3C,cAAc,cAAM,IAAI,KAAK,KAAK,GAAG;GACrC,oBAAoB,cAAM,IAAI,KAAK,KAAK,IAAI;GAC5C,WAAW,cAAM,IAAI,KAAK,KAAK,IAAI;GACpC;EACF;CACF;;;;;;;;;;;;;;;AAgBD,MAAaC,SAA8B;CACzC,YAAY;EACV,QAAQ;GACN,OAAO,cAAM,IAAI,KAAK,IAAI,GAAG;GAC7B,OAAO,cAAM,IAAI,IAAI,KAAK,GAAG;GAC7B,MAAM,cAAM,IAAI,GAAG,KAAK,GAAG;GAC3B,MAAM,cAAM,IAAI,KAAK,KAAK,EAAE;GAC5B,OAAO,cAAM,IAAI,KAAK,IAAI,GAAG;GAC7B,OAAO,cAAM,MAAM,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,IAAI;GACnD;EACD,YAAY,cAAM,IAAI,IAAI,IAAI,GAAG;EACjC,gBAAgB,cAAM,IAAI,IAAI,IAAI,GAAG;EACrC,cAAc,cAAM,IAAI,IAAI,KAAK,GAAG;EACpC,eAAe,cAAM,IAAI,GAAG,KAAK,GAAG;EACrC;CACD,cAAc;EACZ,QAAQ;GACN,OAAO,cAAM,IAAI,KAAK,IAAI,GAAG;GAC7B,OAAO,cAAM,IAAI,IAAI,KAAK,GAAG;GAC7B,MAAM,cAAM,IAAI,GAAG,KAAK,GAAG;GAC3B,MAAM,cAAM,IAAI,KAAK,KAAK,EAAE;GAC5B,OAAO,cAAM,IAAI,KAAK,IAAI,GAAG;GAC7B,OAAO,cAAM,MAAM,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,IAAI;GACnD;EACD,YAAY,cAAM,IAAI,IAAI,IAAI,GAAG;EACjC,gBAAgB,cAAM,IAAI,IAAI,IAAI,GAAG;EACrC,cAAc,cAAM,IAAI,IAAI,KAAK,GAAG;EACpC,eAAe,cAAM,IAAI,GAAG,KAAK,GAAG;EACpC,aAAa,cAAM,IAAI,GAAG,IAAI,GAAG;EACjC,YAAY,cAAM,IAAI,GAAG,IAAI,GAAG,CAAC;EACjC,gBAAgB,cAAM,IAAI,KAAK,IAAI,GAAG;EACtC,YAAY;GACV,WAAW,cAAM,IAAI,IAAI,KAAK,GAAG;GACjC,WAAW,cAAM,IAAI,IAAI,IAAI,GAAG;GAChC,aAAa,cAAM,IAAI,KAAK,IAAI,EAAE;GAClC,aAAa,cAAM,IAAI,GAAG,KAAK,GAAG;GAClC,sBAAsB,cAAM,IAAI,GAAG,KAAK,GAAG;GAC3C,qBAAqB,cAAM,IAAI,IAAI,KAAK,GAAG;GAC3C,qBAAqB,cAAM,IAAI,KAAK,IAAI,GAAG;GAC3C,cAAc,cAAM,IAAI,KAAK,KAAK,EAAE;GACpC,oBAAoB,cAAM,IAAI,KAAK,IAAI,GAAG;GAC1C,WAAW,cAAM,IAAI,KAAK,IAAI,IAAI;GACnC;EACF;CACF;;;;;;;;;;;;;;;;AAiBD,MAAaC,SAA8B;CACzC,YAAY;EACV,QAAQ;GACN,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,MAAM,cAAM,IAAI,KAAK,KAAK,IAAI;GAC9B,MAAM,cAAM,IAAI,KAAK,KAAK,IAAI;GAC9B,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,OAAO,cAAM,MAAM,KAAK,KAAK,IAAI,CAAC,IAAI,IAAI,IAAI,GAAG;GAClD;EACD,YAAY,cAAM,IAAI,KAAK,KAAK,IAAI;EACpC,gBAAgB,cAAM,IAAI,KAAK,KAAK,IAAI;EACxC,cAAc,cAAM,IAAI,KAAK,KAAK,IAAI;EACtC,eAAe,cAAM,IAAI,KAAK,KAAK,IAAI;EACxC;CACD,cAAc;EACZ,QAAQ;GACN,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,MAAM,cAAM,IAAI,KAAK,KAAK,IAAI;GAC9B,MAAM,cAAM,IAAI,KAAK,KAAK,IAAI;GAC9B,OAAO,cAAM,IAAI,KAAK,KAAK,IAAI;GAC/B,OAAO,cAAM,MAAM,KAAK,KAAK,IAAI,CAAC,IAAI,IAAI,IAAI,GAAG;GAClD;EACD,YAAY,cAAM,IAAI,KAAK,KAAK,IAAI;EACpC,gBAAgB,cAAM,IAAI,KAAK,KAAK,IAAI;EACxC,cAAc,cAAM,IAAI,KAAK,KAAK,IAAI;EACtC,eAAe,cAAM,IAAI,KAAK,KAAK,IAAI;EACvC,aAAa,cAAM,IAAI,KAAK,KAAK,IAAI;EACrC,YAAY,cAAM,IAAI,KAAK,KAAK,IAAI,CAAC;EACrC,gBAAgB,cAAM,IAAI,KAAK,KAAK,IAAI;EACxC,YAAY;GACV,WAAW,cAAM,IAAI,KAAK,KAAK,IAAI;GACnC,WAAW,cAAM,IAAI,KAAK,KAAK,IAAI;GACnC,aAAa,cAAM,IAAI,KAAK,KAAK,IAAI;GACrC,aAAa,cAAM,IAAI,KAAK,KAAK,IAAI;GACrC,sBAAsB,cAAM,IAAI,KAAK,KAAK,IAAI;GAC9C,qBAAqB,cAAM,IAAI,KAAK,KAAK,IAAI;GAC7C,qBAAqB,cAAM,IAAI,KAAK,KAAK,IAAI;GAC7C,cAAc,cAAM,IAAI,KAAK,KAAK,IAAI;GACtC,oBAAoB,cAAM,IAAI,KAAK,KAAK,IAAI;GAC5C,WAAW,cAAM,IAAI,KAAK,KAAK,IAAI;GACpC;EACF;CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC3QD,IAAa,YAAb,MAAuB;;CAErB,AAAQ,kBAAkB;;CAG1B,AAAQ,eAAe;;CAGvB,AAAQ,WAAW;;CAGnB,AAAQ;;CAGR,AAAQ,cAA0B,EAAE;;CAGpC,AAAQ,kBAA8B,EAAE;;CAGxC,AAAQ,gBAAgB;;CAGxB,AAAQ,aAAa;;CAGrB,AAAQ,OAAmB,EAAE;;CAG7B,AAAQ,yBAAgD;;CAGxD,AAAQ,4BAAmD;;CAG3D,AAAQ,YAAoB,QAAQ,OAAO,WAAW;;;;;;;;;CAUtD,YACE,AAAQC,UACR,AAAQC,SACR,yBAAyB,OACzB;EAHQ;EACA;AAGR,OAAK,wBAAwB;AAC7B,MAAI,CAAC,KAAK,sBACR,MAAK,uBAAuB;AAG9B,UAAQ,OAAO,GAAG,gBAAgB;AAChC,QAAK,YAAY,QAAQ,OAAO,WAAW;AAE3C,OAAI,KAAK,cAAc;IACrB,MAAM,QAAQ,KAAK,KAAK,KAAK;IAC7B,MAAM,YAAY,KAAK,gBAAgB,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;IAC/E,MAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;AAClG,SAAK,SAAS,iBAAiB,OAAO,WAAW,WAAW,KAAK,SAAS,wBAAwB,CAAC;cAC1F,KAAK,gBACd,MAAK,SAAS,oBAAoB,KAAK,MAAM,KAAK,eAAe,KAAK,YAAY,KAAK,gBAAgB,OAAO;IAEhH;;;;;;;;CASJ,AAAQ,wBAA8B;AACpC,wBAAS,QAAQ,MAAM;AACvB,UAAQ,MAAM,WAAW,KAAK;AAC9B,UAAQ,MAAM,GAAG,YAAY,KAAK,eAAe,KAAK,KAAK,CAAC;EAG5D,MAAM,gBAAgB;AACpB,OAAI,KAAK,uBACP,eAAc,KAAK,uBAAuB;AAE5C,OAAI,KAAK,0BACP,eAAc,KAAK,0BAA0B;AAE/C,WAAQ,MAAM,WAAW,MAAM;AAC/B,WAAQ,MAAM,mBAAmB,WAAW;AAC5C,WAAQ,OAAO;AACf,QAAK,QAAQ,OAAO;AACpB,WAAQ,KAAK,EAAE;;AAGjB,UAAQ,GAAG,UAAU,QAAQ;AAC7B,UAAQ,GAAG,WAAW,QAAQ;;;;;;CAOhC,AAAQ,4BAAkC;AAExC,MAAI,KAAK,0BACP,eAAc,KAAK,0BAA0B;AAI/C,OAAK,4BAA4B,kBAAkB;AACjD,OAAI,CAAC,KAAK,iBAAiB;AACzB,kBAAc,KAAK,0BAA2B;AAC9C,SAAK,4BAA4B;AACjC;;AAIF,OAAI,KAAK,gBAAgB,SAAS,EAChC,MAAK,SAAS,oBAAoB,KAAK,MAAM,KAAK,eAAe,KAAK,YAAY,KAAK,gBAAgB,OAAO;KAE/G,IAAK;;;;;;CAOV,AAAQ,yBAA+B;AAErC,MAAI,KAAK,uBACP,eAAc,KAAK,uBAAuB;AAI5C,OAAK,yBAAyB,kBAAkB;AAC9C,OAAI,CAAC,KAAK,cAAc;AACtB,kBAAc,KAAK,uBAAwB;AAC3C,SAAK,yBAAyB;AAC9B;;GAIF,MAAM,aAAa,KAAK,aACpB,KAAK,QAAQ,oBAAoB,KAAK,WAAW,GACjD,KAAK,QAAQ,aAAa;AAC9B,OAAI,eAAe,KAAK,KAAK,QAAQ;AAGnC,SAAK,OADc,KAAK,aAAa,KAAK,QAAQ,WAAW,KAAK,WAAW,GAAG,KAAK,QAAQ,YAAY;IAEzG,MAAM,QAAQ,KAAK,KAAK,KAAK;IAC7B,MAAM,YAAY,KAAK,gBAAgB,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;IAC/E,MAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;AAClG,SAAK,SAAS,iBACZ,OACA,WACA,WACA,KAAK,SAAS,wBAAwB,EACtC,KAAK,gBAAgB,GACrB,YACA,KAAK,WACN;;KAEF,IAAK;;;;;;;;CASV,AAAQ,qBAA2B;AAMjC,OAJmB,KAAK,aAAa,KAAK,QAAQ,oBAAoB,KAAK,WAAW,GAAG,KAAK,QAAQ,aAAa,IAC/E,KAAK,gBAAgB,WAGlC,KAAK,KAAK,QAAQ;GAEvC,MAAM,aAAa,KAAK,aAAa,KAAK,QAAQ,WAAW,KAAK,WAAW,GAAG,KAAK,QAAQ,YAAY;AACzG,QAAK,OAAO,WAAW,MAAM,GAAG,WAAW,SAAS,KAAK,gBAAgB,OAAO;AAGhF,OAAI,KAAK,KAAK,SAAS,EACrB,MAAK,gBAAgB,KAAK,IAAI,KAAK,eAAe,KAAK,IAAI,GAAG,KAAK,KAAK,SAAS,EAAE,CAAC;OAEpF,MAAK,gBAAgB;;;CAK3B,AAAQ,4BAAkC;AACxC,MAAI,CAAC,KAAK,mBAAmB,CAAC,KAAK,gBAAgB,OAAQ;AAG3D,UAAQ,OAAO,MAAM,YAAY,IAAI,OAAO,KAAK,UAAU,CAAC,IAAI;EAChE,MAAM,eAAe,cAAM,IACzB,GAAG,KAAK,gBAAgB,OAAO,UAAU,KAAK,gBAAgB,WAAW,IAAI,KAAK,IAAI,8BACvF;AACD,UAAQ,OAAO,MAAM,GAAG,aAAa,MAAM;;;;;;;;CAS7C,AAAO,aAAa,OAAuB;AACzC,OAAK,QAAQ,MAAM,MAAM;AAGzB,MAAI,KAAK,uBAAuB;AAC9B,QAAK,SAAS,cAAc,MAAM;AAClC;;AAIF,MAAI,KAAK,iBAAiB;AACxB,QAAK,gBAAgB,KAAK,MAAM;AAChC,QAAK,SAAS,oBAAoB,KAAK,MAAM,KAAK,eAAe,KAAK,YAAY,KAAK,gBAAgB,OAAO;AAC9G;;AAIF,MAAI,CAAC,KAAK,aACR,KAAI,KAAK,UAAU;AAEjB,QAAK,YAAY,KAAK,MAAM;AAE5B,WAAQ,OAAO,MAAM,KAAK,cAAM,OAAO,cAAc,KAAK,YAAY,OAAO,YAAY,GAAG,IAAI,OAAO,GAAG,GAAG;QAE7G,MAAK,SAAS,cAAc,MAAM;;;;;;;;;;;;;;;;;;;CAsBxC,AAAQ,eAAe,IAAY,KAAgB;AAEjD,MAAI,KAAK,QAAQ,KAAK,SAAS,KAAK;AAClC,WAAQ,MAAM,WAAW,MAAM;AAC/B,WAAQ,MAAM,mBAAmB,WAAW;AAC5C,WAAQ,OAAO;AACf,QAAK,QAAQ,OAAO;AACpB,WAAQ,KAAK,EAAE;AACf;;AAIF,MAAI,CAAC,KAAK,mBAAmB,CAAC,KAAK,gBAAgB,OAAO,KAAK;AAC7D,QAAK,WAAW,CAAC,KAAK;AACtB,OAAI,CAAC,KAAK,YAAY,KAAK,YAAY,SAAS,GAAG;AAEjD,YAAQ,OAAO,MAAM,KAAK,IAAI,OAAO,GAAG,CAAC,IAAI;AAE7C,SAAK,MAAM,SAAS,KAAK,YACvB,MAAK,SAAS,cAAc,MAAM;AAEpC,SAAK,cAAc,EAAE;cACZ,KAAK,SAEd,SAAQ,OAAO,MAAM,KAAK,cAAM,OAAO,yBAAyB,GAAG,IAAI,OAAO,GAAG,GAAG;AAEtF;;AAIF,MAAI,CAAC,KAAK,mBAAmB,CAAC,KAAK,iBAAiB,KAAK,SAAS,QAAQ,KAAK,SAAS,SAAS;AAC/F,QAAK,kBAAkB;AACvB,QAAK,aAAa;AAClB,QAAK,WAAW;AAIhB,QAAK,OADc,KAAK,QAAQ,YAAY;AAE5C,QAAK,gBAAgB,IAAI,SAAS,OAAO,KAAK,IAAI,GAAG,KAAK,KAAK,SAAS,EAAE,GAAG,KAAK,IAAI,GAAG,KAAK,KAAK,SAAS,EAAE;AAE9G,QAAK,SAAS,oBAAoB,KAAK,MAAM,KAAK,eAAe,KAAK,YAAY,KAAK,gBAAgB,OAAO;AAC9G,QAAK,2BAA2B;AAChC;;AAIF,MAAI,CAAC,KAAK,mBAAmB,CAAC,KAAK,gBAAgB,OAAO,KAAK;GAE7D,MAAM,UAAU,KAAK,SAAS,eAAe;AAE7C,WAAQ,OAAO;GACf,MAAM,OAAO,KAAK,QAAQ,YAAY;AACtC,QAAK,MAAM,SAAS,KAClB,MAAK,SAAS,cAAc,MAAM;AAQpC,WAAQ,OAAO,MAAM,KAAK,cAAM,KAAK,MALZ;IACvB,MAAM;IACN,WAAW;IACX,WAAW;IACZ,CAC2D,WAAW,GAAG,IAAI,OAAO,GAAG,GAAG;AAC3F,oBAAiB;AACf,YAAQ,OAAO,MAAM,KAAK,IAAI,OAAO,IAAI,CAAC,IAAI;MAC7C,IAAK;AACR;;AAIF,MAAI,KAAK,iBAAiB;AACxB,OAAI,IACF,SAAQ,IAAI,MAAZ;IACE,KAAK;AAEH,UAAK,gBAAgB,KAAK,IAAI,GAAG,KAAK,gBAAgB,EAAE;AACxD,UAAK,SAAS,oBACZ,KAAK,MACL,KAAK,eACL,KAAK,YACL,KAAK,gBAAgB,OACtB;AACD;IAEF,KAAK;AAEH,SAAI,KAAK,kBAAkB,KAAK,KAAK,SAAS,KAAK,KAAK,gBAAgB,SAAS,GAAG;AAElF,WAAK,KAAK,KAAK,GAAG,KAAK,gBAAgB;AACvC,WAAK,kBAAkB,EAAE;;AAE3B,UAAK,gBAAgB,KAAK,IAAI,KAAK,KAAK,SAAS,GAAG,KAAK,gBAAgB,EAAE;AAC3E,UAAK,SAAS,oBACZ,KAAK,MACL,KAAK,eACL,KAAK,YACL,KAAK,gBAAgB,OACtB;AACD;IAEF,KAAK;AAEH,SAAI,KAAK,KAAK,SAAS,GAAG;AACxB,WAAK,kBAAkB;AACvB,WAAK,eAAe;AACpB,cAAQ,OAAO;MACf,MAAM,gBAAgB,KAAK,KAAK,KAAK;MACrC,MAAM,YAAY,KAAK,gBAAgB,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;MAC/E,MAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;AAClG,WAAK,SAAS,iBACZ,eACA,WACA,WACA,GACA,KAAK,gBAAgB,GACrB,KAAK,KAAK,QACV,KAAK,WACN;AACD,WAAK,wBAAwB;;AAE/B;IAEF,KAAK;AAEH,SAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,WAAK,aAAa,KAAK,WAAW,MAAM,GAAG,GAAG;AAC9C,WAAK,oBAAoB;AACzB,WAAK,SAAS,oBACZ,KAAK,MACL,KAAK,eACL,KAAK,YACL,KAAK,gBAAgB,OACtB;;AAEH;IAEF,KAAK,OAAO;AAEV,UAAK,kBAAkB;AACvB,UAAK,WAAW;AAChB,SAAI,KAAK,2BAA2B;AAClC,oBAAc,KAAK,0BAA0B;AAC7C,WAAK,4BAA4B;;AAEnC,UAAK,aAAa;AAClB,aAAQ,OAAO;KAEf,MAAM,OAAO,KAAK,QAAQ,YAAY;AACtC,UAAK,MAAM,SAAS,KAClB,MAAK,SAAS,cAAc,MAAM;AAGpC,SAAI,KAAK,gBAAgB,SAAS,GAAG;AACnC,WAAK,MAAM,SAAS,KAAK,gBACvB,MAAK,SAAS,cAAc,MAAM;AAEpC,WAAK,kBAAkB,EAAE;;AAE3B;;;AAMN,OAAI,OAAO,CAAC,OAAQ,CAAC,IAAI,QAAQ,CAAC,IAAI,SAAU,GAAG,WAAW,GAAG;AAC/D,SAAK,cAAc;AACnB,SAAK,oBAAoB;AACzB,SAAK,SAAS,oBAAoB,KAAK,MAAM,KAAK,eAAe,KAAK,YAAY,KAAK,gBAAgB,OAAO;AAC9G;;;AAKJ,MAAI,KAAK,cAAc;AAErB,OAAI,KAAK,KACP,SAAQ,IAAI,MAAZ;IACE,KAAK,MAAM;AAET,UAAK,SAAS,iBAAiB,GAAG;KAClC,MAAM,QAAQ,KAAK,KAAK,KAAK;KAC7B,MAAM,YAAY,KAAK,gBAAgB,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;KAC/E,MAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;AAClG,UAAK,SAAS,iBACZ,OACA,WACA,WACA,KAAK,SAAS,wBAAwB,EACtC,KAAK,gBAAgB,GACrB,KAAK,KAAK,QACV,KAAK,WACN;AACD;;IAEF,KAAK,QAAQ;AAEX,UAAK,SAAS,iBAAiB,EAAE;KACjC,MAAM,QAAQ,KAAK,KAAK,KAAK;KAC7B,MAAM,YAAY,KAAK,gBAAgB,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;KAC/E,MAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;AAClG,UAAK,SAAS,iBACZ,OACA,WACA,WACA,KAAK,SAAS,wBAAwB,EACtC,KAAK,gBAAgB,GACrB,KAAK,KAAK,QACV,KAAK,WACN;AACD;;IAEF,KAAK;AAEH,SAAI,KAAK,gBAAgB,GAAG;AAC1B,WAAK,gBAAgB,KAAK,IAAI,GAAG,KAAK,gBAAgB,EAAE;MACxD,MAAM,QAAQ,KAAK,KAAK,KAAK;MAC7B,MAAM,YAAY,KAAK,gBAAgB,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;MAC/E,MAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;AAClG,WAAK,SAAS,iBACZ,OACA,WACA,WACA,GACA,KAAK,gBAAgB,GACrB,KAAK,KAAK,QACV,KAAK,WACN;;AAEH;IAEF,KAAK;AAEH,SAAI,KAAK,gBAAgB,KAAK,KAAK,SAAS,GAAG;AAC7C,WAAK,gBAAgB,KAAK,IAAI,KAAK,KAAK,SAAS,GAAG,KAAK,gBAAgB,EAAE;MAC3E,MAAM,QAAQ,KAAK,KAAK,KAAK;MAC7B,MAAM,YAAY,KAAK,gBAAgB,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;MAC/E,MAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;AAClG,WAAK,SAAS,iBACZ,OACA,WACA,WACA,GACA,KAAK,gBAAgB,GACrB,KAAK,KAAK,QACV,KAAK,WACN;;AAEH;IAEF,KAAK;AAEH,SAAI,KAAK,SAAS,cAAc,EAAE;AAChC,WAAK,SAAS,gBAAgB;MAC9B,MAAM,QAAQ,KAAK,KAAK,KAAK;MAC7B,MAAM,YAAY,KAAK,gBAAgB,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;MAC/E,MAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;AAClG,WAAK,SAAS,iBACZ,OACA,WACA,WACA,KAAK,SAAS,wBAAwB,EACtC,KAAK,gBAAgB,GACrB,KAAK,KAAK,QACV,KAAK,WACN;AACD;;AAIF,UAAK,eAAe;AACpB,SAAI,KAAK,wBAAwB;AAC/B,oBAAc,KAAK,uBAAuB;AAC1C,WAAK,yBAAyB;;AAEhC,UAAK,kBAAkB;AACvB,UAAK,oBAAoB;AACzB,UAAK,SAAS,oBACZ,KAAK,MACL,KAAK,eACL,KAAK,YACL,KAAK,gBAAgB,OACtB;AACD;;AAMN,OAAI,GACF,SAAQ,GAAG,aAAa,EAAxB;IACE,KAAK,KAAK;AAER,UAAK,SAAS,iBAAiB,QAAQ,OAAO,OAAO,EAAE;KACvD,MAAM,QAAQ,KAAK,KAAK,KAAK;KAC7B,MAAM,YAAY,KAAK,gBAAgB,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;KAC/E,MAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;AAClG,UAAK,SAAS,iBACZ,OACA,WACA,WACA,KAAK,SAAS,wBAAwB,EACtC,KAAK,gBAAgB,GACrB,KAAK,KAAK,OACX;AACD;;IAEF,KAAK,KAAK;AAER,UAAK,SAAS,iBAAiB,CAAC,QAAQ,OAAO,OAAO,EAAE;KACxD,MAAM,QAAQ,KAAK,KAAK,KAAK;KAC7B,MAAM,YAAY,KAAK,gBAAgB,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;KAC/E,MAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;AAClG,UAAK,SAAS,iBACZ,OACA,WACA,WACA,KAAK,SAAS,wBAAwB,EACtC,KAAK,gBAAgB,GACrB,KAAK,KAAK,OACX;AACD;;IAEF,KAAK;AAEH,SAAI,KAAK,kBAAkB,GAAG;AAC5B,WAAK,gBAAgB;MACrB,MAAM,QAAQ,KAAK,KAAK,KAAK;MAC7B,MAAM,YAAY;MAClB,MAAM,YAAY,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK;AACxD,WAAK,SAAS,iBAAiB,OAAO,WAAW,WAAW,GAAG,GAAG,KAAK,KAAK,OAAO;;AAErF;IAEF,KAAK,KAAK;KAER,MAAM,YAAY,KAAK,KAAK,SAAS;AACrC,SAAI,KAAK,kBAAkB,WAAW;AACpC,WAAK,gBAAgB;MACrB,MAAM,QAAQ,KAAK,KAAK,KAAK;MAC7B,MAAM,YAAY,YAAY,IAAI,KAAK,KAAK,YAAY,KAAK;AAE7D,WAAK,SAAS,iBAAiB,OAAO,WADpB,MAC0C,GAAG,KAAK,KAAK,QAAQ,KAAK,KAAK,OAAO;;AAEpG;;IAEF,KAAK,KAAK;AAER,UAAK,SAAS,qBAAqB;KACnC,MAAM,QAAQ,KAAK,KAAK,KAAK;KAC7B,MAAM,YAAY,KAAK,gBAAgB,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;KAC/E,MAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;AAClG,UAAK,SAAS,iBACZ,OACA,WACA,WACA,KAAK,SAAS,wBAAwB,EACtC,KAAK,gBAAgB,GACrB,KAAK,KAAK,OACX;AACD;;IAEF,KAAK,KAAK;AAER,UAAK,SAAS,gBAAgB;KAC9B,MAAM,QAAQ,KAAK,KAAK,KAAK;KAC7B,MAAM,YAAY,KAAK,gBAAgB,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;KAC/E,MAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,gBAAgB,KAAK;AAClG,UAAK,SAAS,iBAAiB,OAAO,WAAW,WAAW,GAAG,KAAK,gBAAgB,GAAG,KAAK,KAAK,OAAO;AACxG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrmBZ,IAAa,0BAAb,MAAa,gCAAgCC,yCAAoB;;CAE/D,OAAe,WAA2C;;CAG1D,AAAQ;;CAGR,AAAQ;;CAGR,AAAQ;;CAGR,AAAQ;;;;;;;;;CAUR,YAAY,SAA+B,EAAE,EAAE;AAC7C,MAAI,wBAAwB,SAC1B,OAAM,IAAI,MAAM,2EAA2E;AAE7F,QAAM,OAAO;AAGb,OAAK,SAAS;AAGd,MAAI,OAAO,YAAY,MACrB;EAIF,MAAM,iBAAiB,OAAO,kBAAkB;EAChD,MAAM,kBAAkB,OAAO,mBAAmB;EAClD,MAAM,QAAQ,OAAO,SAAS;EAC9B,MAAM,UAAU,OAAO;EAIvB,MAAMC,mBAAyC;GAC7C,QAAQ;IACN,OAAO,cAAM;IACb,OAAO,cAAM;IACb,MAAM,cAAM;IACZ,MAAM,cAAM;IACZ,OAAO,cAAM;IACb,OAAO,cAAM,MAAM;IACnB,GAAG,MAAM,WAAW;IACrB;GACD,YAAY,MAAM,WAAW,cAAc,cAAM;GACjD,gBAAgB,MAAM,WAAW,kBAAkB,cAAM;GACzD,cAAc,MAAM,WAAW,gBAAgB,cAAM;GACrD,eAAe,MAAM,WAAW,iBAAiB,cAAM;GACxD;EAGD,MAAMC,qBAAmD;GACvD,QAAQ;IACN,OAAO,cAAM;IACb,OAAO,cAAM;IACb,MAAM,cAAM;IACZ,MAAM,cAAM;IACZ,OAAO,cAAM;IACb,OAAO,cAAM,MAAM;IACnB,GAAG,MAAM,cAAc;IACxB;GACD,YAAY,MAAM,cAAc,cAAc,cAAM;GACpD,gBAAgB,MAAM,cAAc,kBAAkB,cAAM;GAC5D,cAAc,MAAM,cAAc,gBAAgB,cAAM;GACxD,eAAe,MAAM,cAAc,iBAAiB,cAAM;GAC1D,aAAa,MAAM,cAAc,eAAe,cAAM;GACtD,YAAY,MAAM,cAAc,cAAc,cAAM,KAAK;GACzD,gBAAgB,MAAM,cAAc,kBAAkB,cAAM;GAE5D,YAAY;IACV,WAAW,cAAM;IACjB,WAAW,cAAM;IACjB,aAAa,cAAM;IACnB,aAAa,cAAM;IACnB,sBAAsB,cAAM;IAC5B,qBAAqB,cAAM;IAC3B,qBAAqB,cAAM;IAC3B,cAAc,cAAM;IACpB,oBAAoB,cAAM;IAC1B,WAAW,cAAM;IACjB,GAAG,MAAM,cAAc;IACxB;GACF;AAGD,OAAK,UAAU,IAAI,WAAW,QAAQ;AACtC,OAAK,WAAW,IAAI,YAAY,kBAAkB,oBAAoB,gBAAgB,gBAAgB;AACtG,OAAK,YAAY,IAAI,UAAU,KAAK,UAAU,KAAK,SAAS,OAAO,uBAAuB;AAE1F,0BAAwB,WAAW;;;;;;;;;CAUrC,OAAc,YAAY,SAA+B,EAAE,EAA2B;AACpF,MAAI,CAAC,wBAAwB,SAC3B,yBAAwB,WAAW,IAAI,wBAAwB,OAAO;AAExE,SAAO,wBAAwB;;;;;;;;;;CAWjC,AAAQ,aAAqB;AAC3B,SAAO,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,UAAU,GAAG,EAAE;;;;;;;;;;;;;;;;CAiBnD,aAAa,EAAE,UAAU,UAAU,MAAM,WAA2C;AAElF,MAAI,KAAK,OAAO,YAAY,MAC1B,QAAO;EAGT,MAAM,QAAQ;GACZ,IAAI,KAAK,YAAY;GACrB,WAAW,KAAK,KAAK;GACrB,OAAO;GACP,SAAS,SAAS,KAAK,IAAI;GAC3B,MAAM,UAAU,KAAK,UAAU,KAAK,GAAG;GACxC;AAED,OAAK,UAAU,aAAa,MAAM;AAClC,SAAO;;;;;;ACnMX,SAAgB,kBAAkB,SAA+B,EAAE,EAAE;AACnE,QAAO,wBAAwB,YAAY,OAAO"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["Utils.indent","Utils.getMaxIndexLength","prettyjson\n .render","Database","LoggerlessTransport"],"sources":["../src/vendor/utils.js","../src/vendor/prettyjson.js","../src/views/utils.ts","../src/views/DetailView.ts","../src/views/SelectionView.ts","../src/views/SimpleView.ts","../src/LogRenderer.ts","../src/LogStorage.ts","../src/themes.ts","../src/UIManager.ts","../src/PrettyTerminalTransport.ts","../src/index.ts"],"sourcesContent":["/**\n * Creates a string with the same length as `numSpaces` parameter\n **/\nexport function indent(numSpaces) {\n return new Array(numSpaces + 1).join(\" \");\n}\n\n/**\n * Gets the string length of the longer index in a hash\n **/\nexport function getMaxIndexLength(input) {\n var maxWidth = 0;\n\n Object.getOwnPropertyNames(input).forEach((key) => {\n // Skip undefined values.\n if (input[key] === undefined) {\n return;\n }\n\n maxWidth = Math.max(maxWidth, key.length);\n });\n return maxWidth;\n}\n\nexport function isIsoStringDate(isoString) {\n if (typeof isoString !== \"string\") {\n return false;\n }\n // More flexible regex that handles:\n // - Optional milliseconds\n // - Optional timezone offset or Z\n // - Optional T separator (space also valid)\n if (!/^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?$/.test(isoString)) {\n return false;\n }\n const testDate = new Date(isoString);\n return !Number.isNaN(testDate.getTime());\n}\n","// @ts-nocheck\nimport chalk from \"chalk\";\nimport * as Utils from \"./utils.js\";\nimport { isIsoStringDate } from \"./utils.js\";\n\nconst conflictChars = /[^\\w\\s\\n\\r\\v\\t.,]/i;\n\n// Helper function to detect if an object should be printed or ignored\nconst isPrintable = (input, options) => input !== undefined || options.renderUndefined;\n\n// Helper function to detect if an object can be directly serializable\nconst isSerializable = (input, onlyPrimitives, options) => {\n if (\n typeof input === \"boolean\" ||\n typeof input === \"number\" ||\n typeof input === \"function\" ||\n input === null ||\n input === undefined ||\n input instanceof Date\n ) {\n return true;\n }\n if (typeof input === \"string\" && input.indexOf(\"\\n\") === -1) {\n return true;\n }\n\n if (options.inlineArrays && !onlyPrimitives) {\n if (Array.isArray(input) && isSerializable(input[0], true, options)) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * @param {Function} colorFn\n * @param {PrettyJSONOptions} options\n */\nconst getColorRenderer = (colorFn, options) => {\n if (options.noColor) {\n return (text) => text;\n }\n\n if (typeof colorFn !== \"function\") {\n return (text) => text;\n }\n\n return colorFn;\n};\n\nconst addColorToData = (input, options) => {\n if (options.noColor) {\n return input;\n }\n\n if (input instanceof Date) {\n return getColorRenderer(options.dateColor, options)(input.toISOString());\n }\n if (typeof input === \"string\") {\n if (isIsoStringDate(input)) {\n return getColorRenderer(options.dateColor, options)(input);\n }\n // Print strings in regular terminal color\n return getColorRenderer(options.stringColor, options)(input);\n }\n\n const sInput = `${input}`;\n\n if (typeof input === \"boolean\") {\n return getColorRenderer(options.booleanColor, options)(sInput);\n }\n if (input === null || input === undefined) {\n return getColorRenderer(options.nullUndefinedColor, options)(sInput);\n }\n if (typeof input === \"number\") {\n if (input >= 0) {\n return getColorRenderer(options.positiveNumberColor, options)(sInput);\n }\n return getColorRenderer(options.negativeNumberColor, options)(sInput);\n }\n if (typeof input === \"function\") {\n return \"function() {}\";\n }\n\n if (Array.isArray(input)) {\n return input.join(\", \");\n }\n\n return sInput;\n};\n\nconst colorMultilineString = (options, line) => getColorRenderer(options.multilineStringColor, options)(line);\n\nconst indentLines = (string, spaces, options) => {\n let lines = string.split(\"\\n\");\n lines = lines.map((line) => Utils.indent(spaces) + colorMultilineString(options, line));\n return lines.join(\"\\n\");\n};\n\nconst renderToArray = (data, options, indentation) => {\n if (typeof data === \"string\" && data.match(conflictChars) && options.escape) {\n data = JSON.stringify(data);\n }\n\n if (!isPrintable(data, options)) {\n return [];\n }\n\n if (isSerializable(data, false, options)) {\n return [Utils.indent(indentation) + addColorToData(data, options)];\n }\n\n // Unserializable string means it's multiline\n if (typeof data === \"string\") {\n return [\n Utils.indent(indentation) + colorMultilineString(options, '\"\"\"'),\n indentLines(data, indentation + options.defaultIndentation, options),\n Utils.indent(indentation) + colorMultilineString(options, '\"\"\"'),\n ];\n }\n\n if (Array.isArray(data)) {\n // If the array is empty, render the `emptyArrayMsg`\n if (data.length === 0) {\n return [Utils.indent(indentation) + options.emptyArrayMsg];\n }\n\n // If arrays should be collapsed and there's data, show [...]\n if (options.collapseArrays && data.length > 0) {\n return [`${Utils.indent(indentation)}[... ${data.length} items]`];\n }\n\n const outputArray = [];\n\n data.forEach((element) => {\n if (!isPrintable(element, options)) {\n return;\n }\n\n // Prepend the dash at the beginning of each array's element line\n let line = \"- \";\n line = getColorRenderer(options.dashColor, options)(line);\n line = Utils.indent(indentation) + line;\n\n // If the element of the array is a string, bool, number, or null\n // render it in the same line\n if (isSerializable(element, false, options)) {\n line += renderToArray(element, options, 0)[0];\n outputArray.push(line);\n\n // If the element is an array or object, render it in next line\n } else {\n outputArray.push(line);\n outputArray.push.apply(outputArray, renderToArray(element, options, indentation + options.defaultIndentation));\n }\n });\n\n return outputArray;\n }\n\n if (data instanceof Error) {\n return renderToArray(\n {\n message: data.message,\n stack: data.stack.split(\"\\n\"),\n },\n options,\n indentation,\n );\n }\n\n // If values alignment is enabled, get the size of the longest index\n // to align all the values\n const maxIndexLength = options.noAlign ? 0 : Utils.getMaxIndexLength(data);\n let key;\n const output = [];\n\n Object.getOwnPropertyNames(data).forEach((i) => {\n if (!isPrintable(data[i], options)) {\n return;\n }\n\n // Prepend the index at the beginning of the line\n key = `${i}: `;\n key = getColorRenderer(options.keysColor, options)(key);\n key = Utils.indent(indentation) + key;\n\n // If the value is serializable, render it in the same line\n if (isSerializable(data[i], false, options)) {\n const nextIndentation = options.noAlign ? 0 : maxIndexLength - i.length;\n key += renderToArray(data[i], options, nextIndentation)[0];\n output.push(key);\n\n // If the index is an array or object, render it in next line\n } else {\n output.push(key);\n output.push.apply(output, renderToArray(data[i], options, indentation + options.defaultIndentation));\n }\n });\n return output;\n};\n/**\n * @typedef {Object} PrettyJSONOptions\n * @property {Function} [stringColor=null] Chalk color function for strings\n * @property {Function} [multilineStringColor=null] Chalk color function for multiline strings\n * @property {Function} [keysColor=chalk.green] Chalk color function for keys in hashes\n * @property {Function} [dashColor=chalk.green] Chalk color function for dashes in arrays\n * @property {Function} [numberColor=chalk.blue] Default Chalk color function for numbers\n * @property {Function} [positiveNumberColor=numberColor] Chalk color function for positive numbers\n * @property {Function} [negativeNumberColor=numberColor] Chalk color function for negative numbers\n * @property {Function} [booleanColor=chalk.cyan] Chalk color function for boolean values\n * @property {Function} [nullUndefinedColor=chalk.grey] Chalk color function for null || undefined\n * @property {Function} [dateColor=chalk.magenta] Chalk color function for Date objects\n * @property {number} [defaultIndentation=2] Indentation spaces per object level\n * @property {string} [emptyArrayMsg=\"(empty array)\"] Replace empty strings with\n * @property {boolean} [noColor] Flag to disable colors\n * @property {boolean} [noAlign] Flag to disable alignment\n * @property {boolean} [escape] Flag to escape printed content\n * @property {boolean} [collapseArrays] Flag to collapse arrays\n */\n/**\n * Mutating function that ensures we have a valid options object\n * @param {PrettyJSONOptions} options\n * @returns PrettyJSONOptions\n */\nconst validateOptionsAndSetDefaults = (options) => {\n options = options || {};\n options.emptyArrayMsg = options.emptyArrayMsg || \"(empty array)\";\n options.keysColor = options.keysColor || chalk.green;\n options.dashColor = options.dashColor || chalk.green;\n options.booleanColor = options.booleanColor || chalk.cyan;\n options.nullUndefinedColor = options.nullUndefinedColor || chalk.grey;\n options.numberColor = options.numberColor || chalk.blue;\n options.positiveNumberColor = options.positiveNumberColor || options.numberColor;\n options.negativeNumberColor = options.negativeNumberColor || options.numberColor;\n options.dateColor = options.dateColor || chalk.magenta;\n options.defaultIndentation = options.defaultIndentation || 2;\n options.noColor = !!options.noColor;\n options.noAlign = !!options.noAlign;\n options.escape = !!options.escape;\n options.renderUndefined = !!options.renderUndefined;\n options.collapseArrays = !!options.collapseArrays;\n\n options.stringColor = options.stringColor || null;\n options.multilineStringColor = options.multilineStringColor || options.stringColor || null;\n\n return options;\n};\n/**\n * ### Render function\n * *Parameters:*\n *\n * @param {*} data: Data to render\n * @param {PrettyJSONOptions} options: Hash of different options\n * @param {*} indentation **`indentation`**: Base indentation of the output\n *\n * *Example of options hash:*\n *\n * {\n * emptyArrayMsg: '(empty)', // Rendered message on empty strings\n * keysColor: 'blue', // Color for keys in hashes\n * dashColor: 'red', // Color for the dashes in arrays\n * stringColor: 'grey', // Color for strings\n * multilineStringColor: 'cyan' // Color for multiline strings\n * defaultIndentation: 2 // Indentation on nested objects\n * }\n * @returns string with the rendered data\n */\nexport function render(data, options, indentation) {\n // Default values\n indentation = indentation || 0;\n options = validateOptionsAndSetDefaults(options);\n\n return renderToArray(data, options, indentation).join(\"\\n\");\n}\n\n/**\n * ### Render from string function\n * *Parameters:*\n *\n * @param {*} data: Data to render\n * @param {PrettyJSONOptions} options: Hash of different options\n * @param {*} indentation **`indentation`**: Base indentation of the output\n *\n * *Example of options hash:*\n *\n * {\n * emptyArrayMsg: '(empty)', // Rendered message on empty strings\n * keysColor: 'blue', // Color for keys in hashes\n * dashColor: 'red', // Color for the dashes in arrays\n * defaultIndentation: 2 // Indentation on nested objects\n * }\n */\nexport function renderString(data, options, indentation) {\n let output = \"\";\n let parsedData;\n // If the input is not a string or if it's empty, just return an empty string\n if (typeof data !== \"string\" || data === \"\") {\n return \"\";\n }\n\n // Remove non-JSON characters from the beginning string\n if (data[0] !== \"{\" && data[0] !== \"[\") {\n let beginingOfJson;\n if (data.indexOf(\"{\") === -1) {\n beginingOfJson = data.indexOf(\"[\");\n } else if (data.indexOf(\"[\") === -1) {\n beginingOfJson = data.indexOf(\"{\");\n } else if (data.indexOf(\"{\") < data.indexOf(\"[\")) {\n beginingOfJson = data.indexOf(\"{\");\n } else {\n beginingOfJson = data.indexOf(\"[\");\n }\n output += `${data.substr(0, beginingOfJson)}\\n`;\n data = data.substr(beginingOfJson);\n }\n\n try {\n parsedData = JSON.parse(data);\n } catch (_e) {\n // Return an error in case of an invalid JSON\n return `${chalk.red(\"Error:\")} Not valid JSON!`;\n }\n\n // Call the real render() method\n output += exports.render(parsedData, options, indentation);\n return output;\n}\n","import chalk from \"chalk\";\nimport truncate from \"cli-truncate\";\nimport type { ColorConfig, ViewConfig } from \"../types.js\";\nimport * as prettyjson from \"../vendor/prettyjson.js\";\n\n/**\n * Formats a timestamp into a human-readable string.\n * Format: HH:MM:SS.mmm\n */\nexport function formatTimestamp(timestamp: number, colorFn: (inp: string) => string): string {\n const date = new Date(timestamp);\n return colorFn(\n `${date.getHours().toString().padStart(2, \"0\")}:${date.getMinutes().toString().padStart(2, \"0\")}:${date.getSeconds().toString().padStart(2, \"0\")}.${date.getMilliseconds().toString().padStart(3, \"0\")}`,\n );\n}\n\n/**\n * Gets the color function for a log level.\n */\nexport function getLevelColor(level: string, colors: ColorConfig): typeof chalk.white {\n return colors[level] || chalk.white;\n}\n\n/**\n * Formats a value for display.\n */\nexport function formatValue(value: any, expanded = false): string {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") return value.toString();\n if (value === null) return \"null\";\n if (value === undefined) return \"undefined\";\n if (Array.isArray(value)) return expanded ? JSON.stringify(value) : \"[...]\";\n if (typeof value === \"object\") return expanded ? JSON.stringify(value) : \"{...}\";\n return value.toString();\n}\n\n/**\n * Formats structured data for inline display with depth limiting.\n */\nexport function formatInlineData(\n data: any,\n config: ViewConfig,\n maxDepth: number,\n maxLength: number,\n expanded = false,\n): string {\n if (!data) return \"\";\n\n const pairs: string[] = [];\n const traverse = (obj: any, prefix = \"\", depth = 0) => {\n if (!expanded && depth >= maxDepth) return;\n\n for (const [key, value] of Object.entries(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n if (expanded) {\n pairs.push(`${config.dataKeyColor(fullKey)}=${config.dataValueColor(JSON.stringify(value))}`);\n } else {\n traverse(value, fullKey, depth + 1);\n }\n } else {\n pairs.push(`${config.dataKeyColor(fullKey)}=${config.dataValueColor(formatValue(value, expanded))}`);\n }\n }\n };\n\n traverse(data);\n const result = pairs.join(\" \");\n return expanded ? result : truncate(result, maxLength);\n}\n\n/**\n * Formats structured data for selection view (shows full data).\n */\nexport function formatSelectionData(data: any, config: ViewConfig): string {\n if (!data) return \"\";\n\n return prettyjson.render(data, {\n keysColor: config.dataKeyColor,\n dashColor: config.dataKeyColor,\n stringColor: config.dataValueColor,\n numberColor: config.dataValueColor,\n booleanColor: config.dataValueColor,\n nullUndefinedColor: config.dataValueColor,\n defaultIndentation: 2,\n });\n}\n","import chalk from \"chalk\";\nimport wrap from \"wrap-ansi\";\nimport type { LogEntry } from \"../types.js\";\nimport * as prettyjson from \"../vendor/prettyjson.js\";\nimport type { DetailViewConfig, View } from \"./types.js\";\nimport { formatTimestamp, getLevelColor } from \"./utils.js\";\n\n/**\n * Handles rendering of the detail view mode.\n * Shows a full-screen view of a single log entry with:\n * - Previous/next log context\n * - Full timestamp information\n * - Pretty-printed data\n * - Navigation help\n */\nexport class DetailView implements View {\n private termWidth: number;\n private config: DetailViewConfig;\n private detailViewContent: string[] = [];\n\n constructor(config: DetailViewConfig) {\n this.config = config;\n this.termWidth = process.stdout.columns || 80;\n }\n\n public updateTerminalWidth(width: number): void {\n this.termWidth = width;\n }\n\n /**\n * Formats a compact single-line version of a log entry\n */\n private formatCompactLogLine(entry: LogEntry | null, prefix = \"\"): string {\n if (!entry) return \"\";\n\n const levelColor = getLevelColor(entry.level, this.config.config.colors);\n const logId = this.config.config.logIdColor(`[${entry.id}]`);\n const line = `${prefix}${levelColor(entry.level.toUpperCase())} ${logId} ${entry.message}`;\n return this.config.config.separatorColor(wrap(line, this.termWidth, { hard: true }));\n }\n\n /**\n * Formats a timestamp into a human-readable relative time\n */\n private formatRelativeTime(timestamp: Date): string {\n const now = new Date();\n const diffMs = now.getTime() - timestamp.getTime();\n const diffSecs = Math.floor(diffMs / 1000);\n const diffMins = Math.floor(diffSecs / 60);\n const diffHours = Math.floor(diffMins / 60);\n const diffDays = Math.floor(diffHours / 24);\n\n if (diffSecs < 60) return `${diffSecs}s ago`;\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays === 1) return \"yesterday\";\n if (diffDays < 30) return `${diffDays}d ago`;\n\n return timestamp.toLocaleDateString();\n }\n\n public render(): void {\n console.clear();\n\n // Add padding at the top to handle terminal buffer overflow\n console.log(\"\\n\".repeat(5));\n\n // If in JSON view mode, show raw JSON\n if (this.config.isJsonView) {\n if (this.config.entry.data) {\n console.log(JSON.stringify(JSON.parse(this.config.entry.data)));\n } else {\n console.log(\"{}\");\n }\n console.log(`\\n${this.config.config.separatorColor(\"TAB to return to detailed view\")}`);\n return;\n }\n\n // Calculate fixed header content (previous entry)\n const headerContent: string[] = [];\n if (this.config.prevEntry) {\n const prevLine = this.formatCompactLogLine(this.config.prevEntry, \"← \");\n headerContent.push(prevLine);\n headerContent.push(this.config.config.separatorColor(\"─\".repeat(this.termWidth)));\n }\n\n // Calculate fixed footer content (next entry)\n const footerContent: string[] = [];\n if (this.config.nextEntry) {\n footerContent.push(this.config.config.separatorColor(\"─\".repeat(this.termWidth)));\n const nextLine = this.formatCompactLogLine(this.config.nextEntry, \"→ \");\n footerContent.push(nextLine);\n }\n footerContent.push(\"\"); // Empty line before help text\n footerContent.push(this.config.config.separatorColor(\"↑/↓ scroll • Q/W page up/down • J raw JSON\"));\n footerContent.push(this.config.config.separatorColor(\"←/→ navigate • A/S first/last log • C toggle arrays\"));\n\n // Calculate main scrollable content\n const mainContent: string[] = [];\n const levelColor = getLevelColor(this.config.entry.level, this.config.config.colors);\n\n // Build header with filter context if present\n let headerText = `=== Log Detail [${this.config.entry.id}] (${this.config.currentLogIndex} / ${this.config.totalLogs})`;\n if (this.config.filterText) {\n headerText += ` [Filter: ${this.config.filterText}]`;\n }\n headerText += \" ===\";\n\n const header = levelColor(headerText);\n mainContent.push(header);\n\n // Format timestamp with both ISO and relative time\n const timestamp = new Date(this.config.entry.timestamp);\n const isoTime = formatTimestamp(this.config.entry.timestamp, this.config.config.dataValueColor);\n const relativeTime = this.formatRelativeTime(timestamp);\n mainContent.push(`${this.config.config.labelColor(\"Timestamp:\")} ${isoTime} (${relativeTime})`);\n\n mainContent.push(\n `${this.config.config.labelColor(\"Level:\")} ${levelColor.bold(this.config.entry.level.toUpperCase())}`,\n );\n\n if (this.config.entry.message) {\n mainContent.push(\n `${this.config.config.labelColor(\"Message:\")} ${this.config.config.dataValueColor(this.config.entry.message)}`,\n );\n } else {\n mainContent.push(\n `${this.config.config.labelColor(\"Message:\")} ${this.config.config.dataValueColor.dim(\"(no message)\")}`,\n );\n }\n\n // Pretty-print structured data if present\n if (this.config.entry.data) {\n mainContent.push(this.config.config.labelColor(\"\\nData:\"));\n const jsonLines = prettyjson\n .render(JSON.parse(this.config.entry.data), {\n ...this.config.config.jsonColors,\n defaultIndentation: 2,\n collapseArrays: this.config.isArraysCollapsed,\n })\n .split(\"\\n\");\n mainContent.push(...jsonLines);\n }\n\n // Store the complete content for future scrolling\n this.detailViewContent = mainContent;\n\n // Calculate available height for main content\n const headerHeight = headerContent.length;\n const footerHeight = footerContent.length;\n const scrollIndicatorLines = 2; // Space for up/down indicators\n const bufferSpace = 4; // Extra buffer to prevent content from being cut off\n const topPadding = 2; // Account for the padding we added at the top\n const availableHeight = Math.max(\n 0,\n process.stdout.rows - headerHeight - footerHeight - scrollIndicatorLines - bufferSpace - topPadding,\n );\n\n // Render fixed header\n for (const line of headerContent) {\n console.log(line);\n }\n\n // Show scroll indicator if needed\n if (this.config.scrollPos > 0) {\n console.log(chalk.dim(\"↑ More content above\"));\n }\n\n // Display visible portion of main content\n const startIndex = this.config.scrollPos;\n const visibleContent = mainContent.slice(startIndex, startIndex + availableHeight);\n for (const line of visibleContent) {\n console.log(line);\n }\n\n // Show scroll indicator if there's more content below\n if (this.config.scrollPos + availableHeight < mainContent.length) {\n console.log(chalk.dim(\"↓ More content below\"));\n } else {\n console.log(chalk.dim(\"End of content\"));\n }\n\n // Render fixed footer\n for (const line of footerContent) {\n console.log(line);\n }\n }\n\n /**\n * Gets the maximum scroll position based on current content and window size\n */\n public getMaxScrollPosition(): number {\n const headerHeight = this.config.prevEntry ? 2 : 0;\n const footerHeight = 5;\n const scrollIndicatorLines = 2;\n const bufferSpace = 2;\n const topPadding = 2; // Account for the padding we added at the top\n const availableHeight = Math.max(\n 0,\n process.stdout.rows - headerHeight - footerHeight - scrollIndicatorLines - bufferSpace - topPadding,\n );\n\n return Math.max(0, this.detailViewContent.length - availableHeight);\n }\n}\n","import chalk from \"chalk\";\nimport wrap from \"wrap-ansi\";\nimport type { SelectionViewConfig, View } from \"./types.js\";\nimport { formatInlineData, formatTimestamp, getLevelColor } from \"./utils.js\";\n\n/**\n * Handles rendering of the selection view mode.\n * Shows an interactive list of logs with:\n * - Filtering capability\n * - Selected item highlighting\n * - Full data preview inline\n * - Scroll indicators\n */\nexport class SelectionView implements View {\n private termWidth: number;\n private config: SelectionViewConfig;\n\n constructor(config: SelectionViewConfig) {\n this.config = config;\n this.termWidth = process.stdout.columns || 80;\n }\n\n public updateTerminalWidth(width: number): void {\n this.termWidth = width;\n }\n\n public render(): void {\n console.clear();\n\n // Add padding at the top to handle terminal buffer overflow\n console.log(\"\\n\".repeat(5));\n\n // Calculate available height for logs\n const filterHeight = this.config.filterText ? 2 : 0; // Filter + separator line\n const footerHeight = 2; // Help text + blank line before it\n const topPadding = 5; // Account for the padding we added\n const availableHeight = process.stdout.rows - filterHeight - footerHeight - topPadding;\n\n if (this.config.logs.length === 0) {\n console.log(chalk.yellow(\"No matching logs found\"));\n } else {\n // Calculate the window of logs to show\n const visibleLines = Math.min(availableHeight, 20); // Show at most 20 lines at a time\n const bottomPadding = 2; // Keep selected item this many lines from the bottom\n\n let startIdx = Math.max(0, this.config.selectedIndex - (visibleLines - bottomPadding - 1));\n const endIdx = Math.min(this.config.logs.length, startIdx + visibleLines);\n\n // Adjust start index if we're near the end\n if (endIdx - startIdx < visibleLines && endIdx < this.config.logs.length) {\n startIdx = Math.max(0, endIdx - visibleLines);\n }\n\n // Show scroll indicator if there are logs above\n if (startIdx > 0) {\n console.log(chalk.dim(\" ↑ More logs above\"));\n }\n\n // Render visible logs with selection highlight\n this.config.logs.slice(startIdx, endIdx).forEach((entry, index) => {\n const actualIndex = startIdx + index;\n const isSelected = actualIndex === this.config.selectedIndex;\n const prefix = isSelected ? this.config.config.selectorColor(\"► \") : \" \";\n const timestamp = formatTimestamp(entry.timestamp, this.config.config.logIdColor);\n const levelColor = getLevelColor(entry.level, this.config.config.colors);\n const chevron = levelColor(`${entry.level.toUpperCase()} `);\n const logId = chalk.dim(`[${entry.id}]`);\n const message = entry.message;\n const data = entry.data ? ` ${formatInlineData(JSON.parse(entry.data), this.config.config, 0, 0, true)}` : \"\";\n\n // Construct and wrap the main line with full data\n const mainLine = `${prefix}${timestamp} ${chevron}${logId} ${message}${data}`;\n const wrappedText = wrap(mainLine, this.termWidth - 2, { hard: true });\n\n if (isSelected) {\n // For selected items, add vertical bar and indentation to all lines except the first\n const lines = wrappedText.split(\"\\n\");\n console.log(lines[0]);\n for (const line of lines.slice(1)) {\n console.log(` ${this.config.config.selectorColor(\"│\")} ${line}`);\n }\n } else {\n console.log(wrappedText);\n }\n });\n\n // Show scroll indicator if there are logs below\n if (endIdx < this.config.logs.length || this.config.newLogCount > 0) {\n const moreLogsText =\n this.config.newLogCount > 0\n ? this.config.config.selectorColor(\n ` ↓ ${this.config.newLogCount} new log${this.config.newLogCount === 1 ? \"\" : \"s\"} available (press ↓ to view)`,\n )\n : chalk.dim(\" ↓ More logs below\");\n console.log(moreLogsText);\n }\n }\n\n // Show help text and filter at the bottom\n console.log(chalk.dim(\"\\nType to filter • Enter to view details • TAB to exit\"));\n\n // Show active filter if any\n if (this.config.filterText) {\n console.log(chalk.dim(\"─\".repeat(this.termWidth)));\n console.log(chalk.cyan(\"Filter:\"), chalk.white(this.config.filterText));\n }\n }\n}\n","import wrap from \"wrap-ansi\";\nimport type { LogEntry } from \"../types.js\";\nimport type { SimpleViewConfig, View } from \"./types.js\";\nimport { formatInlineData, formatTimestamp, getLevelColor } from \"./utils.js\";\n\n/**\n * Handles rendering of the simple view mode.\n * Supports three display modes:\n * - Truncated: Shows all log details with truncated data\n * - Condensed: Shows timestamp, level and message\n * - Full: Shows all details with complete data\n */\nexport class SimpleView implements View {\n private termWidth: number;\n private config: SimpleViewConfig;\n\n constructor(config: SimpleViewConfig) {\n this.config = config;\n this.termWidth = process.stdout.columns || 80;\n }\n\n public updateTerminalWidth(width: number): void {\n this.termWidth = width;\n }\n\n /**\n * Renders a single log entry based on the current view mode\n */\n public renderLogLine(entry: LogEntry): void {\n const levelColor = getLevelColor(entry.level, this.config.config.colors);\n const chevron = levelColor(`▶ ${entry.level.toUpperCase()} `);\n const message = entry.message || \"(no message)\";\n const timestamp = formatTimestamp(entry.timestamp, this.config.config.logIdColor);\n\n switch (this.config.viewMode) {\n case \"condensed\": {\n // Condensed view shows timestamp, level and message\n const condensedLine = `${timestamp} ${chevron}${message}`;\n console.log(wrap(condensedLine, this.termWidth, { hard: true }));\n break;\n }\n\n case \"full\": {\n // Full view shows all details with complete data\n const logId = this.config.config.logIdColor(`[${entry.id}]`);\n const fullData = entry.data\n ? formatInlineData(\n JSON.parse(entry.data),\n this.config.config,\n this.config.maxInlineDepth,\n this.config.maxInlineLength,\n true,\n )\n : \"\";\n const expandedLine = `${timestamp} ${chevron}${logId} ${message}${fullData ? ` ${fullData}` : \"\"}`;\n console.log(wrap(expandedLine, this.termWidth, { hard: true }));\n break;\n }\n\n default: {\n // 'truncated'\n // Truncated view shows all details with truncated data\n const logId = this.config.config.logIdColor(`[${entry.id}]`);\n const normalData = entry.data\n ? formatInlineData(\n JSON.parse(entry.data),\n this.config.config,\n this.config.maxInlineDepth,\n this.config.maxInlineLength,\n )\n : \"\";\n const normalLine = `${timestamp} ${chevron}${logId} ${message}${normalData ? ` ${normalData}` : \"\"}`;\n console.log(wrap(normalLine, this.termWidth, { hard: true }));\n break;\n }\n }\n }\n\n public render(): void {\n throw new Error(\"SimpleView.render() should not be called directly. Use renderLogLine() instead.\");\n }\n}\n","/**\n * LogRenderer handles all terminal output formatting and rendering.\n * Provides multiple view modes with different levels of detail:\n * - Simple view for real-time log output\n * - Compact view for context in detailed view\n * - Detailed view for inspecting individual logs\n * - Selection view for browsing and filtering logs\n *\n * Features:\n * - Color-coded log levels\n * - Structured data formatting\n * - Terminal width awareness\n * - Pretty-printed JSON\n * - Truncation of long content\n */\n\nimport type { DetailedViewConfig, LogEntry, ViewConfig } from \"./types.js\";\nimport { DetailView, SelectionView, SimpleView } from \"./views/index.js\";\n\n/**\n * LogRenderer coordinates between different view modes and manages the overall rendering state.\n * Delegates actual rendering to specialized view implementations:\n * - SimpleView: For real-time log output\n * - SelectionView: For interactive log browsing\n * - DetailView: For in-depth log inspection\n */\nexport class LogRenderer {\n /** Current terminal width in characters */\n private termWidth: number;\n\n /** Maximum depth for displaying nested objects inline */\n private maxInlineDepth: number;\n\n /** Maximum length for inline data before truncating */\n private maxInlineLength: number;\n\n /** Whether arrays are currently collapsed in detail view */\n private isArraysCollapsed = true;\n\n /** Current view mode in simple mode */\n private viewMode: \"truncated\" | \"condensed\" | \"full\" = \"full\";\n\n /** Color and formatting config for simple log view */\n private simpleViewConfig: Required<ViewConfig>;\n\n /** Color and formatting config for detailed view */\n private detailedViewConfig: Required<DetailedViewConfig>;\n\n /** Whether we're showing raw JSON view */\n private isJsonView = false;\n\n /** Current scroll position in detailed view */\n private detailViewScrollPos = 0;\n\n /** View instances */\n private simpleView: SimpleView;\n private detailView: DetailView | null = null;\n private selectionView: SelectionView | null = null;\n\n /**\n * Creates a new LogRenderer instance.\n *\n * @param simpleViewConfig - Configuration for simple log view\n * @param detailedViewConfig - Configuration for detailed view\n * @param maxInlineDepth - Maximum depth for inline object display\n * @param maxInlineLength - Maximum length before truncation\n */\n constructor(\n simpleViewConfig: Required<ViewConfig>,\n detailedViewConfig: Required<DetailedViewConfig>,\n maxInlineDepth: number,\n maxInlineLength: number,\n ) {\n this.simpleViewConfig = simpleViewConfig;\n this.detailedViewConfig = detailedViewConfig;\n this.maxInlineDepth = maxInlineDepth;\n this.maxInlineLength = maxInlineLength;\n this.termWidth = process.stdout.columns || 80;\n\n // Initialize views with their configurations\n this.simpleView = new SimpleView({\n viewMode: this.viewMode,\n maxInlineDepth: this.maxInlineDepth,\n maxInlineLength: this.maxInlineLength,\n config: this.simpleViewConfig,\n });\n\n // Detail view will be initialized when needed with actual log entry\n this.detailView = null as any; // Will be set when entering detail view\n\n // Selection view will be initialized when needed with actual logs\n this.selectionView = null as any; // Will be set when entering selection view\n\n // Update terminal width when window is resized\n process.stdout.on(\"resize\", () => {\n this.termWidth = process.stdout.columns || 80;\n this.simpleView.updateTerminalWidth(this.termWidth);\n if (this.detailView) {\n this.detailView.updateTerminalWidth(this.termWidth);\n }\n if (this.selectionView) {\n this.selectionView.updateTerminalWidth(this.termWidth);\n }\n });\n }\n\n /**\n * Renders a single log line in simple view format.\n * Format: [timestamp] LEVEL [id] message data\n * Condensed Format: [timestamp] LEVEL message\n * Expanded Format: [timestamp] LEVEL [id] message full_data\n *\n * @param entry - Log entry to render\n */\n public renderLogLine(entry: LogEntry): void {\n this.simpleView.renderLogLine(entry);\n }\n\n /**\n * Renders the detailed view of a log entry.\n * Shows full entry details with context and formatted data.\n *\n * @param entry - Log entry to show in detail\n * @param prevEntry - Previous entry for context\n * @param nextEntry - Next entry for context\n * @param scrollPos - Current scroll position\n * @param currentLogIndex - Current log index (optional)\n * @param totalLogs - Total logs count (optional)\n * @param filterText - Current filter text (if any)\n */\n public renderDetailView(\n entry: LogEntry,\n prevEntry: LogEntry | null,\n nextEntry: LogEntry | null,\n scrollPos = 0,\n currentLogIndex?: number,\n totalLogs?: number,\n filterText = \"\",\n ): void {\n // Create or update detail view configuration\n const config = {\n entry,\n prevEntry,\n nextEntry,\n scrollPos,\n isArraysCollapsed: this.isArraysCollapsed,\n isJsonView: this.isJsonView,\n currentLogIndex: currentLogIndex ?? (prevEntry ? 2 : nextEntry ? 1 : 1), // Use provided index or fallback\n totalLogs: totalLogs ?? 1, // Use provided total or fallback\n filterText,\n config: this.detailedViewConfig,\n };\n\n // Create new detail view instance or update existing one\n if (!this.detailView) {\n this.detailView = new DetailView(config);\n } else {\n this.detailView = new DetailView(config);\n }\n\n this.detailView.render();\n }\n\n /**\n * Updates the scroll position in detailed view\n * @param delta - Number of lines to scroll\n */\n public scrollDetailView(delta: number): void {\n if (!this.detailView) return;\n\n const maxScroll = this.detailView.getMaxScrollPosition();\n this.detailViewScrollPos = Math.max(0, Math.min(maxScroll, this.detailViewScrollPos + delta));\n }\n\n /**\n * Gets the current scroll position\n */\n public getDetailViewScrollPos(): number {\n return this.detailViewScrollPos;\n }\n\n /**\n * Renders the selection view with a list of logs.\n * Shows filtered logs with selection highlight and data preview.\n *\n * @param logs - Array of logs to display\n * @param selectedIndex - Index of currently selected log\n * @param filterText - Current filter text (if any)\n * @param newLogCount - Number of new logs available\n */\n public renderSelectionView(logs: LogEntry[], selectedIndex: number, filterText: string, newLogCount: number): void {\n // Create or update selection view configuration\n const config = {\n logs,\n selectedIndex,\n filterText,\n newLogCount,\n config: this.detailedViewConfig,\n };\n\n // Create new selection view instance or update existing one\n if (!this.selectionView) {\n this.selectionView = new SelectionView(config);\n } else {\n this.selectionView = new SelectionView(config);\n }\n\n this.selectionView.render();\n }\n\n /**\n * Toggles JSON view state\n */\n public toggleJsonView(): void {\n this.isJsonView = !this.isJsonView;\n }\n\n /**\n * Gets current JSON view state\n */\n public isInJsonView(): boolean {\n return this.isJsonView;\n }\n\n /**\n * Toggles array collapse state in detail view\n */\n public toggleArrayCollapse(): void {\n this.isArraysCollapsed = !this.isArraysCollapsed;\n }\n\n /**\n * Cycles through view modes: full -> truncated -> condensed\n */\n public cycleViewMode(): string {\n switch (this.viewMode) {\n case \"full\":\n this.viewMode = \"truncated\";\n break;\n case \"truncated\":\n this.viewMode = \"condensed\";\n break;\n case \"condensed\":\n this.viewMode = \"full\";\n break;\n }\n\n // Update simple view configuration\n this.simpleView = new SimpleView({\n viewMode: this.viewMode,\n maxInlineDepth: this.maxInlineDepth,\n maxInlineLength: this.maxInlineLength,\n config: this.simpleViewConfig,\n });\n\n return this.viewMode;\n }\n\n /**\n * Gets current view mode\n */\n public getViewMode(): string {\n return this.viewMode;\n }\n}\n","/**\n * LogStorage handles the persistence of log entries using SQLite.\n * Uses an in-memory database for fast access and temporary storage.\n */\n\nimport { resolve } from \"node:path\";\nimport Database from \"better-sqlite3\";\nimport type { LogEntry } from \"./types.js\";\n\n/**\n * Handles storage and retrieval of log entries using SQLite.\n * Uses an in-memory database for optimal performance and automatic cleanup.\n *\n * The database schema includes:\n * - id: Unique identifier for each log\n * - timestamp: Unix timestamp in milliseconds\n * - level: Log level (trace, debug, info, etc.)\n * - message: Main log message\n * - data: Optional structured data as JSON string\n */\nexport class LogStorage {\n /** SQLite database instance */\n private db: Database.Database;\n\n /**\n * Creates a new LogStorage instance.\n * Initializes a SQLite database and creates the logs table.\n *\n * @param logFile - Optional path to SQLite file for persistent storage.\n * If not provided, uses in-memory database.\n * Relative paths are resolved from the current working directory.\n */\n constructor(logFile?: string) {\n // Use specified log file or fallback to in-memory database\n const dbPath = logFile ? (logFile.startsWith(\"/\") ? logFile : resolve(process.cwd(), logFile)) : \":memory:\";\n this.db = new Database(dbPath);\n this.initializeDatabase();\n }\n\n /**\n * Initializes the database schema.\n * Creates the logs table with appropriate columns and indexes.\n * If the table already exists, it will be dropped to ensure a clean state.\n * @private\n */\n private initializeDatabase(): void {\n this.db.exec(`\n DROP TABLE IF EXISTS logs;\n CREATE TABLE logs (\n id TEXT PRIMARY KEY,\n timestamp INTEGER,\n level TEXT,\n message TEXT,\n data TEXT\n )\n `);\n }\n\n /**\n * Stores a new log entry in the database.\n * Uses prepared statements for efficient and safe insertion.\n *\n * @param entry - The log entry to store\n * @example\n * storage.store({\n * id: \"abc123\",\n * timestamp: Date.now(),\n * level: \"info\",\n * message: \"User logged in\",\n * data: JSON.stringify({ userId: 123 })\n * });\n */\n public store(entry: LogEntry): void {\n this.db\n .prepare(`\n INSERT INTO logs (id, timestamp, level, message, data)\n VALUES (?, ?, ?, ?, ?)\n `)\n .run(entry.id, entry.timestamp, entry.level, entry.message, entry.data);\n }\n\n /**\n * Retrieves all logs from the database in chronological order.\n * Used when displaying the full log history or clearing filters.\n *\n * @returns Array of log entries sorted by timestamp\n */\n public getAllLogs(): LogEntry[] {\n return this.db.prepare(\"SELECT * FROM logs ORDER BY timestamp ASC\").all() as LogEntry[];\n }\n\n /**\n * Searches logs based on a text query.\n * Performs a case-insensitive search across multiple fields:\n * - Log ID\n * - Message content\n * - Structured data\n *\n * @param searchText - Text to search for\n * @returns Array of matching log entries sorted by timestamp\n * @example\n * const errorLogs = storage.searchLogs(\"error\");\n * const userLogs = storage.searchLogs(\"userId:123\");\n */\n public searchLogs(searchText: string): LogEntry[] {\n const query = `\n SELECT * FROM logs \n WHERE id LIKE ? \n OR message LIKE ? \n OR data LIKE ? \n ORDER BY timestamp ASC\n `;\n const pattern = `%${searchText}%`;\n return this.db.prepare(query).all(pattern, pattern, pattern) as LogEntry[];\n }\n\n /**\n * Gets the total number of logs in the database.\n * Uses an efficient COUNT query instead of loading all logs.\n *\n * @returns Total number of log entries\n */\n public getLogCount(): number {\n const result = this.db.prepare(\"SELECT COUNT(*) as count FROM logs\").get() as { count: number };\n return result.count;\n }\n\n /**\n * Gets the total number of logs matching a search query.\n * Uses an efficient COUNT query instead of loading all logs.\n *\n * @param searchText - Text to search for\n * @returns Number of matching log entries\n */\n public getFilteredLogCount(searchText: string): number {\n const query = `\n SELECT COUNT(*) as count FROM logs \n WHERE id LIKE ? \n OR message LIKE ? \n OR data LIKE ?\n `;\n const pattern = `%${searchText}%`;\n const result = this.db.prepare(query).get(pattern, pattern, pattern) as { count: number };\n return result.count;\n }\n\n /**\n * Closes the database connection and performs cleanup.\n * Should be called when the application exits or the transport is destroyed.\n */\n public close(): void {\n this.db.close();\n }\n}\n","import chalk from \"chalk\";\nimport type { PrettyTerminalTheme } from \"./types.js\";\n\n/**\n * Moonlight - A dark theme with cool blue tones\n * Inspired by moonlit nights and modern IDEs\n *\n * Color Palette:\n * - Primary: Cool blues and soft greens\n * - Accents: Warm yellows and soft reds\n * - Background: Assumes dark terminal (black or very dark grey)\n *\n * Best used with:\n * - Dark terminal themes\n * - Night-time coding sessions\n * - Environments where eye strain is a concern\n */\nexport const moonlight: PrettyTerminalTheme = {\n simpleView: {\n colors: {\n trace: chalk.rgb(114, 135, 153), // Muted blue-grey for less important info\n debug: chalk.rgb(130, 170, 255), // Soft blue that pops but doesn't strain\n info: chalk.rgb(195, 232, 141), // Sage green for good readability\n warn: chalk.rgb(255, 203, 107), // Warm yellow, less harsh than pure yellow\n error: chalk.rgb(247, 118, 142), // Soft red that stands out without being aggressive\n fatal: chalk.bgRgb(247, 118, 142).white, // Inverted soft red for maximum visibility\n },\n logIdColor: chalk.rgb(84, 98, 117), // Darker blue-grey for secondary information\n dataValueColor: chalk.rgb(209, 219, 231), // Light grey-blue for primary content\n dataKeyColor: chalk.rgb(130, 170, 255), // Matching debug blue for consistency\n selectorColor: chalk.rgb(137, 221, 255), // Ice blue for selection indicators\n },\n detailedView: {\n colors: {\n trace: chalk.rgb(114, 135, 153),\n debug: chalk.rgb(130, 170, 255),\n info: chalk.rgb(195, 232, 141),\n warn: chalk.rgb(255, 203, 107),\n error: chalk.rgb(247, 118, 142),\n fatal: chalk.bgRgb(247, 118, 142).white,\n },\n logIdColor: chalk.rgb(84, 98, 117),\n dataValueColor: chalk.rgb(209, 219, 231),\n dataKeyColor: chalk.rgb(130, 170, 255),\n selectorColor: chalk.rgb(137, 221, 255), // Ice blue for selection indicators\n headerColor: chalk.rgb(137, 221, 255),\n labelColor: chalk.rgb(137, 221, 255).bold,\n separatorColor: chalk.rgb(84, 98, 117),\n jsonColors: {\n keysColor: chalk.rgb(130, 170, 255),\n dashColor: chalk.rgb(209, 219, 231),\n numberColor: chalk.rgb(247, 140, 108),\n stringColor: chalk.rgb(195, 232, 141),\n multilineStringColor: chalk.rgb(195, 232, 141),\n positiveNumberColor: chalk.rgb(195, 232, 141),\n negativeNumberColor: chalk.rgb(247, 118, 142),\n booleanColor: chalk.rgb(255, 203, 107),\n nullUndefinedColor: chalk.rgb(114, 135, 153),\n dateColor: chalk.rgb(199, 146, 234),\n },\n },\n};\n\n/**\n * Sunlight - A light theme with warm tones\n * Inspired by daylight reading and paper documentation\n *\n * Color Palette:\n * - Primary: Deep, rich colors that contrast well with white\n * - Accents: Earth tones and deep jewel tones\n * - Background: Assumes light terminal (white or very light grey)\n *\n * Best used with:\n * - Light terminal themes\n * - Daytime coding sessions\n * - High-glare environments\n * - Printed documentation\n */\nexport const sunlight: PrettyTerminalTheme = {\n simpleView: {\n colors: {\n trace: chalk.rgb(110, 110, 110), // Dark grey for subtle information\n debug: chalk.rgb(32, 96, 159), // Deep blue for strong contrast on white\n info: chalk.rgb(35, 134, 54), // Forest green, easier on the eyes than bright green\n warn: chalk.rgb(176, 95, 0), // Brown-orange for natural warning color\n error: chalk.rgb(191, 0, 0), // Deep red for clear visibility on light backgrounds\n fatal: chalk.bgRgb(191, 0, 0).white, // White on deep red for critical issues\n },\n logIdColor: chalk.rgb(110, 110, 110),\n dataValueColor: chalk.rgb(0, 0, 0),\n dataKeyColor: chalk.rgb(32, 96, 159),\n selectorColor: chalk.rgb(0, 91, 129), // Deep blue for strong contrast\n },\n detailedView: {\n colors: {\n trace: chalk.rgb(110, 110, 110),\n debug: chalk.rgb(32, 96, 159),\n info: chalk.rgb(35, 134, 54),\n warn: chalk.rgb(176, 95, 0),\n error: chalk.rgb(191, 0, 0),\n fatal: chalk.bgRgb(191, 0, 0).white,\n },\n logIdColor: chalk.rgb(110, 110, 110),\n dataValueColor: chalk.rgb(0, 0, 0),\n dataKeyColor: chalk.rgb(32, 96, 159),\n selectorColor: chalk.rgb(0, 91, 129), // Deep blue for strong contrast\n headerColor: chalk.rgb(0, 91, 129),\n labelColor: chalk.rgb(0, 91, 129).bold,\n separatorColor: chalk.rgb(110, 110, 110),\n jsonColors: {\n keysColor: chalk.rgb(32, 96, 159),\n dashColor: chalk.rgb(0, 0, 0),\n numberColor: chalk.rgb(170, 55, 49),\n stringColor: chalk.rgb(35, 134, 54),\n multilineStringColor: chalk.rgb(35, 134, 54),\n positiveNumberColor: chalk.rgb(46, 125, 50),\n negativeNumberColor: chalk.rgb(183, 28, 28),\n booleanColor: chalk.rgb(176, 95, 0),\n nullUndefinedColor: chalk.rgb(110, 110, 110),\n dateColor: chalk.rgb(123, 31, 162),\n },\n },\n};\n\n/**\n * Neon - A dark theme with vibrant cyberpunk colors\n * Inspired by neon-lit cityscapes and retro-futuristic aesthetics\n *\n * Color Palette:\n * - Primary: Electric blues and hot pinks\n * - Accents: Bright purples and cyber greens\n * - Background: Assumes dark terminal (black or very dark grey)\n *\n * Best used with:\n * - Dark terminal themes\n * - High-contrast preferences\n * - Modern, tech-focused applications\n */\nexport const neon: PrettyTerminalTheme = {\n simpleView: {\n colors: {\n trace: chalk.rgb(108, 108, 255), // Electric blue\n debug: chalk.rgb(255, 82, 246), // Hot pink\n info: chalk.rgb(0, 255, 163), // Cyber green\n warn: chalk.rgb(255, 231, 46), // Electric yellow\n error: chalk.rgb(255, 53, 91), // Neon red\n fatal: chalk.bgRgb(255, 53, 91).rgb(0, 255, 163), // Neon red bg with cyber green text\n },\n logIdColor: chalk.rgb(187, 134, 252), // Bright purple\n dataValueColor: chalk.rgb(255, 255, 255), // Pure white\n dataKeyColor: chalk.rgb(0, 255, 240), // Cyan\n selectorColor: chalk.rgb(0, 255, 240), // Electric cyan for cyberpunk feel\n },\n detailedView: {\n colors: {\n trace: chalk.rgb(108, 108, 255),\n debug: chalk.rgb(255, 82, 246),\n info: chalk.rgb(0, 255, 163),\n warn: chalk.rgb(255, 231, 46),\n error: chalk.rgb(255, 53, 91),\n fatal: chalk.bgRgb(255, 53, 91).rgb(0, 255, 163),\n },\n logIdColor: chalk.rgb(187, 134, 252),\n dataValueColor: chalk.rgb(255, 255, 255),\n dataKeyColor: chalk.rgb(0, 255, 240),\n selectorColor: chalk.rgb(0, 255, 240), // Electric cyan for cyberpunk feel\n headerColor: chalk.rgb(255, 82, 246),\n labelColor: chalk.rgb(255, 82, 246).bold,\n separatorColor: chalk.rgb(108, 108, 255),\n jsonColors: {\n keysColor: chalk.rgb(0, 255, 240),\n dashColor: chalk.rgb(255, 255, 255),\n numberColor: chalk.rgb(255, 82, 246),\n stringColor: chalk.rgb(0, 255, 163),\n multilineStringColor: chalk.rgb(0, 255, 163),\n positiveNumberColor: chalk.rgb(0, 255, 163),\n negativeNumberColor: chalk.rgb(255, 53, 91),\n booleanColor: chalk.rgb(255, 231, 46),\n nullUndefinedColor: chalk.rgb(108, 108, 255),\n dateColor: chalk.rgb(187, 134, 252),\n },\n },\n};\n\n/**\n * Nature - A light theme with organic, earthy colors\n * Inspired by forest landscapes and natural elements\n *\n * Color Palette:\n * - Primary: Deep forest greens and rich browns\n * - Accents: Autumn reds and golden yellows\n * - Background: Assumes light terminal (white or very light grey)\n *\n * Best used with:\n * - Light terminal themes\n * - Nature-inspired interfaces\n * - Applications focusing on readability\n */\nexport const nature: PrettyTerminalTheme = {\n simpleView: {\n colors: {\n trace: chalk.rgb(121, 85, 72), // Wooden brown\n debug: chalk.rgb(46, 125, 50), // Forest green\n info: chalk.rgb(0, 105, 92), // Deep teal\n warn: chalk.rgb(175, 115, 0), // Golden amber\n error: chalk.rgb(183, 28, 28), // Autumn red\n fatal: chalk.bgRgb(183, 28, 28).rgb(255, 250, 240), // Red bg with soft white\n },\n logIdColor: chalk.rgb(93, 64, 55), // Deep bark brown\n dataValueColor: chalk.rgb(27, 27, 27), // Near black\n dataKeyColor: chalk.rgb(56, 142, 60), // Leaf green\n selectorColor: chalk.rgb(0, 105, 92), // Deep teal for natural feel\n },\n detailedView: {\n colors: {\n trace: chalk.rgb(121, 85, 72),\n debug: chalk.rgb(46, 125, 50),\n info: chalk.rgb(0, 105, 92),\n warn: chalk.rgb(175, 115, 0),\n error: chalk.rgb(183, 28, 28),\n fatal: chalk.bgRgb(183, 28, 28).rgb(255, 250, 240),\n },\n logIdColor: chalk.rgb(93, 64, 55),\n dataValueColor: chalk.rgb(27, 27, 27),\n dataKeyColor: chalk.rgb(56, 142, 60),\n selectorColor: chalk.rgb(0, 105, 92), // Deep teal for natural feel\n headerColor: chalk.rgb(0, 77, 64),\n labelColor: chalk.rgb(0, 77, 64).bold,\n separatorColor: chalk.rgb(121, 85, 72),\n jsonColors: {\n keysColor: chalk.rgb(56, 142, 60),\n dashColor: chalk.rgb(27, 27, 27),\n numberColor: chalk.rgb(230, 81, 0),\n stringColor: chalk.rgb(0, 105, 92),\n multilineStringColor: chalk.rgb(0, 105, 92),\n positiveNumberColor: chalk.rgb(46, 125, 50),\n negativeNumberColor: chalk.rgb(183, 28, 28),\n booleanColor: chalk.rgb(175, 115, 0),\n nullUndefinedColor: chalk.rgb(121, 85, 72),\n dateColor: chalk.rgb(123, 31, 162),\n },\n },\n};\n\n/**\n * Pastel - A soft, calming theme with gentle colors\n * Inspired by watercolor paintings and cotton candy skies\n *\n * Color Palette:\n * - Primary: Soft pinks and lavenders\n * - Accents: Mint greens and baby blues\n * - Background: Assumes dark terminal (black or very dark grey)\n *\n * Best used with:\n * - Dark terminal themes\n * - Long coding sessions where eye comfort is priority\n * - Environments where a gentler aesthetic is preferred\n * - Applications focusing on reduced visual stress\n */\nexport const pastel: PrettyTerminalTheme = {\n simpleView: {\n colors: {\n trace: chalk.rgb(179, 189, 203), // Soft slate blue\n debug: chalk.rgb(189, 178, 255), // Gentle lavender\n info: chalk.rgb(170, 236, 205), // Mint green\n warn: chalk.rgb(255, 223, 186), // Peach\n error: chalk.rgb(255, 188, 188), // Soft coral\n fatal: chalk.bgRgb(255, 188, 188).rgb(76, 40, 40), // Coral bg with deep brown\n },\n logIdColor: chalk.rgb(203, 195, 227), // Dusty lavender\n dataValueColor: chalk.rgb(236, 236, 236), // Soft white\n dataKeyColor: chalk.rgb(186, 207, 255), // Baby blue\n selectorColor: chalk.rgb(189, 178, 255), // Soft lavender for gentle highlighting\n },\n detailedView: {\n colors: {\n trace: chalk.rgb(179, 189, 203),\n debug: chalk.rgb(189, 178, 255),\n info: chalk.rgb(170, 236, 205),\n warn: chalk.rgb(255, 223, 186),\n error: chalk.rgb(255, 188, 188),\n fatal: chalk.bgRgb(255, 188, 188).rgb(76, 40, 40),\n },\n logIdColor: chalk.rgb(203, 195, 227),\n dataValueColor: chalk.rgb(236, 236, 236),\n dataKeyColor: chalk.rgb(186, 207, 255),\n selectorColor: chalk.rgb(189, 178, 255), // Soft lavender for gentle highlighting\n headerColor: chalk.rgb(255, 198, 255), // Cotton candy pink\n labelColor: chalk.rgb(255, 198, 255).bold,\n separatorColor: chalk.rgb(179, 189, 203),\n jsonColors: {\n keysColor: chalk.rgb(186, 207, 255), // Baby blue\n dashColor: chalk.rgb(236, 236, 236), // Soft white\n numberColor: chalk.rgb(255, 198, 255), // Cotton candy pink\n stringColor: chalk.rgb(170, 236, 205), // Mint green\n multilineStringColor: chalk.rgb(170, 236, 205),\n positiveNumberColor: chalk.rgb(170, 236, 205),\n negativeNumberColor: chalk.rgb(255, 188, 188),\n booleanColor: chalk.rgb(255, 223, 186), // Peach\n nullUndefinedColor: chalk.rgb(179, 189, 203),\n dateColor: chalk.rgb(189, 178, 255), // Gentle lavender\n },\n },\n};\n","/**\n * UIManager handles all user interaction and view state management.\n * This class is responsible for:\n * - Managing keyboard input and navigation\n * - Coordinating between views (simple, selection, detail)\n * - Handling filtering and search\n * - Managing the selection state\n * - Coordinating between storage and rendering\n *\n * The UI has three main modes:\n * 1. Simple View: Real-time log output (default)\n * 2. Selection View: Interactive log browsing with filtering\n * 3. Detail View: In-depth view of a single log entry\n *\n * Navigation Controls:\n * - TAB: Toggle selection mode\n * - Up/Down: Navigate logs in selection mode, scroll in detail mode\n * - Left/Right: Navigate between logs in detail mode\n * - Enter: View log details\n * - Type: Filter logs\n * - Backspace: Clear filter\n * - CTRL+C: Exit\n */\n\nimport chalk from \"chalk\";\n// @ts-expect-error\nimport keypress from \"keypress\";\nimport type { LogRenderer } from \"./LogRenderer.js\";\nimport type { LogStorage } from \"./LogStorage.js\";\nimport type { LogEntry } from \"./types.js\";\n\n/**\n * Manages UI state and user interaction.\n * Acts as the controller between the storage and rendering layers.\n * Handles all keyboard input and view transitions.\n */\nexport class UIManager {\n /** Whether the UI is in log selection mode */\n private isSelectionMode = false;\n\n /** Whether the UI is showing detailed log view */\n private isDetailView = false;\n\n /** Whether log streaming is paused */\n private isPaused = false;\n\n /** Whether interactive mode is disabled */\n private isInteractiveDisabled: boolean;\n\n /** Buffer for logs received while paused */\n private pauseBuffer: LogEntry[] = [];\n\n /** Buffer for new logs in selection mode */\n private selectionBuffer: LogEntry[] = [];\n\n /** Index of currently selected log entry */\n private selectedIndex = 0;\n\n /** Current filter text for log searching */\n private filterText = \"\";\n\n /** Cached array of filtered log entries */\n private logs: LogEntry[] = [];\n\n /** Polling interval for checking new logs in detail view */\n private detailViewPollInterval: NodeJS.Timeout | null = null;\n\n /** Polling interval for checking new logs in selection view */\n private selectionViewPollInterval: NodeJS.Timeout | null = null;\n\n /** Current terminal width in characters */\n private termWidth: number = process.stdout.columns || 80;\n\n /**\n * Creates a new UIManager instance.\n * Sets up keyboard handling and cleanup handlers.\n *\n * @param renderer - Instance for handling log display\n * @param storage - Instance for log persistence\n * @param disableInteractiveMode - Whether to disable interactive mode\n */\n constructor(\n private renderer: LogRenderer,\n private storage: LogStorage,\n disableInteractiveMode = false,\n ) {\n this.isInteractiveDisabled = disableInteractiveMode;\n if (!this.isInteractiveDisabled) {\n this.setupKeyboardHandling();\n }\n // Update terminal width when window is resized\n process.stdout.on(\"resize\", () => {\n this.termWidth = process.stdout.columns || 80;\n // Re-render the current view\n if (this.isDetailView) {\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(entry, prevEntry, nextEntry, this.renderer.getDetailViewScrollPos());\n } else if (this.isSelectionMode) {\n this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);\n }\n });\n }\n\n /**\n * Sets up keyboard input handling and cleanup.\n * Configures raw mode for immediate key processing.\n * Sets up process exit handlers for cleanup.\n * @private\n */\n private setupKeyboardHandling(): void {\n keypress(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.on(\"keypress\", this.handleKeypress.bind(this));\n\n // Setup cleanup handlers for graceful exit\n const cleanup = () => {\n if (this.detailViewPollInterval) {\n clearInterval(this.detailViewPollInterval);\n }\n if (this.selectionViewPollInterval) {\n clearInterval(this.selectionViewPollInterval);\n }\n process.stdin.setRawMode(false);\n process.stdin.removeAllListeners(\"keypress\");\n console.clear();\n this.storage.close();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", cleanup); // Handle Ctrl+C\n process.on(\"SIGTERM\", cleanup); // Handle termination request\n }\n\n /**\n * Starts polling for new logs in selection view\n * @private\n */\n private startSelectionViewPolling(): void {\n // Clear any existing interval\n if (this.selectionViewPollInterval) {\n clearInterval(this.selectionViewPollInterval);\n }\n\n // Set up new polling interval\n this.selectionViewPollInterval = setInterval(() => {\n if (!this.isSelectionMode) {\n clearInterval(this.selectionViewPollInterval!);\n this.selectionViewPollInterval = null;\n return;\n }\n\n // Re-render with notification about buffered logs if any\n if (this.selectionBuffer.length > 0) {\n this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);\n }\n }, 2000); // Poll every 2 seconds\n }\n\n /**\n * Starts polling for new logs in detail view\n * @private\n */\n private startDetailViewPolling(): void {\n // Clear any existing interval\n if (this.detailViewPollInterval) {\n clearInterval(this.detailViewPollInterval);\n }\n\n // Set up new polling interval\n this.detailViewPollInterval = setInterval(() => {\n if (!this.isDetailView) {\n clearInterval(this.detailViewPollInterval!);\n this.detailViewPollInterval = null;\n return;\n }\n\n // Check if total count has changed\n const totalCount = this.filterText\n ? this.storage.getFilteredLogCount(this.filterText)\n : this.storage.getLogCount();\n if (totalCount !== this.logs.length) {\n // Only load the logs we need for display\n const storedLogs = this.filterText ? this.storage.searchLogs(this.filterText) : this.storage.getAllLogs();\n this.logs = storedLogs;\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n totalCount,\n this.filterText,\n );\n }\n }, 2000); // Poll every 2 seconds\n }\n\n /**\n * Updates the filtered list of logs based on search text.\n * Handles both full list and filtered views.\n * Maintains selection state when filter changes.\n * @private\n */\n private updateFilteredLogs(): void {\n // Get the total count first to check if we need to update\n const totalCount = this.filterText ? this.storage.getFilteredLogCount(this.filterText) : this.storage.getLogCount();\n const effectiveCount = totalCount - this.selectionBuffer.length;\n\n // Only reload logs if the count has changed\n if (effectiveCount !== this.logs.length) {\n // Always get fresh logs from storage, but don't include buffered logs\n const storedLogs = this.filterText ? this.storage.searchLogs(this.filterText) : this.storage.getAllLogs();\n this.logs = storedLogs.slice(0, storedLogs.length - this.selectionBuffer.length);\n\n // Ensure selection remains valid after filter\n if (this.logs.length > 0) {\n this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.logs.length - 1));\n } else {\n this.selectedIndex = 0;\n }\n }\n }\n\n private updateNewLogsNotification(): void {\n if (!this.isSelectionMode || !this.selectionBuffer.length) return;\n\n // Move cursor up 2 lines (to the line above the help text), clear it, and write notification\n process.stdout.write(`\\x1b[2A\\r${\" \".repeat(this.termWidth)}\\r`);\n const notification = chalk.dim(\n `${this.selectionBuffer.length} new log${this.selectionBuffer.length === 1 ? \"\" : \"s\"} available (press ↓ to view)`,\n );\n process.stdout.write(`${notification}\\n\\n`);\n }\n\n /**\n * Handles new log entries from the transport.\n * Stores the log and updates the display if needed.\n *\n * @param entry - New log entry to process\n */\n public handleNewLog(entry: LogEntry): void {\n this.storage.store(entry);\n\n // If interactive mode is disabled, always render in simple mode\n if (this.isInteractiveDisabled) {\n this.renderer.renderLogLine(entry);\n return;\n }\n\n // Buffer logs in selection mode\n if (this.isSelectionMode) {\n this.selectionBuffer.push(entry);\n this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);\n return;\n }\n\n // Only handle display in simple view mode (not in selection or detail view)\n if (!this.isDetailView) {\n if (this.isPaused) {\n // Add to pause buffer if paused\n this.pauseBuffer.push(entry);\n // Show pause indicator with buffer size\n process.stdout.write(`\\r${chalk.yellow(`⏸ Paused (${this.pauseBuffer.length} new logs)`)}${\" \".repeat(20)}`);\n } else {\n this.renderer.renderLogLine(entry);\n }\n }\n }\n\n /**\n * Processes keyboard input and manages UI state.\n * Handles navigation, mode switching, and filtering.\n *\n * Key mappings:\n * - CTRL+C: Exit application\n * - TAB: Toggle selection mode\n * - Up/Down: Navigate logs\n * - Enter: View log details\n * - Backspace: Edit filter\n * - P: Toggle pause in simple view\n * - Other keys: Add to filter\n *\n * @param ch - Character input if available\n * @param key - Key event information\n * @private\n */\n private handleKeypress(ch: string, key: any): void {\n // Handle application exit (CTRL+C)\n if (key?.ctrl && key?.name === \"c\") {\n process.stdin.setRawMode(false);\n process.stdin.removeAllListeners(\"keypress\");\n console.clear();\n this.storage.close();\n process.exit(0);\n return;\n }\n\n // Handle pause toggle in simple view\n if (!this.isSelectionMode && !this.isDetailView && ch === \"p\") {\n this.isPaused = !this.isPaused;\n if (!this.isPaused && this.pauseBuffer.length > 0) {\n // Clear the pause indicator\n process.stdout.write(`\\r${\" \".repeat(50)}\\r`);\n // Render buffered logs\n for (const entry of this.pauseBuffer) {\n this.renderer.renderLogLine(entry);\n }\n this.pauseBuffer = [];\n } else if (this.isPaused) {\n // Show initial pause indicator\n process.stdout.write(`\\r${chalk.yellow(\"⏸ Paused (0 new logs)\")}${\" \".repeat(20)}`);\n }\n return;\n }\n\n // Handle entering selection mode from simple view with up/down keys\n if (!this.isSelectionMode && !this.isDetailView && (key?.name === \"up\" || key?.name === \"down\")) {\n this.isSelectionMode = true;\n this.filterText = \"\";\n this.isPaused = true; // Pause the log stream when entering selection mode\n\n // Get all logs up to this point\n const storedLogs = this.storage.getAllLogs();\n this.logs = storedLogs;\n this.selectedIndex = key.name === \"up\" ? Math.max(0, this.logs.length - 1) : Math.max(0, this.logs.length - 1);\n\n this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);\n this.startSelectionViewPolling(); // Start polling when entering selection mode\n return;\n }\n\n // Handle condensed view toggle in simple view\n if (!this.isSelectionMode && !this.isDetailView && ch === \"c\") {\n // Cycle through view modes\n const newMode = this.renderer.cycleViewMode();\n // Clear screen and re-render all logs with new view mode\n console.clear();\n const logs = this.storage.getAllLogs();\n for (const entry of logs) {\n this.renderer.renderLogLine(entry);\n }\n // Show view mode indicator with appropriate description\n const modeDescriptions = {\n full: \"Full view enabled (all data shown without truncation)\",\n truncated: \"Truncated view enabled (timestamp, ID, level, message, truncated data)\",\n condensed: \"Condensed view enabled (timestamp, level and message only)\",\n };\n process.stdout.write(`\\r${chalk.cyan(`ℹ ${modeDescriptions[newMode]}`)}${\" \".repeat(20)}`);\n setTimeout(() => {\n process.stdout.write(`\\r${\" \".repeat(100)}\\r`);\n }, 3000);\n return;\n }\n\n // Handle selection mode navigation and filtering\n if (this.isSelectionMode) {\n if (key) {\n switch (key.name) {\n case \"up\": {\n // Move selection up\n this.selectedIndex = Math.max(0, this.selectedIndex - 1);\n this.renderer.renderSelectionView(\n this.logs,\n this.selectedIndex,\n this.filterText,\n this.selectionBuffer.length,\n );\n return;\n }\n case \"down\": {\n // Move selection down\n if (this.selectedIndex === this.logs.length - 1 && this.selectionBuffer.length > 0) {\n // Append buffered logs when user reaches the bottom\n this.logs.push(...this.selectionBuffer);\n this.selectionBuffer = [];\n }\n this.selectedIndex = Math.min(this.logs.length - 1, this.selectedIndex + 1);\n this.renderer.renderSelectionView(\n this.logs,\n this.selectedIndex,\n this.filterText,\n this.selectionBuffer.length,\n );\n return;\n }\n case \"return\": {\n // Enter detail view for selected log\n if (this.logs.length > 0) {\n this.isSelectionMode = false;\n this.isDetailView = true;\n console.clear(); // Clear console before entering detail view\n const selectedEntry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n selectedEntry,\n prevEntry,\n nextEntry,\n 0,\n this.selectedIndex + 1,\n this.logs.length,\n this.filterText,\n );\n this.startDetailViewPolling(); // Start polling when entering detail view\n }\n return;\n }\n case \"backspace\": {\n // Remove last character from filter\n if (this.filterText.length > 0) {\n this.filterText = this.filterText.slice(0, -1);\n this.updateFilteredLogs();\n this.renderer.renderSelectionView(\n this.logs,\n this.selectedIndex,\n this.filterText,\n this.selectionBuffer.length,\n );\n }\n return;\n }\n case \"tab\": {\n // Exit selection mode back to simple view\n this.isSelectionMode = false;\n this.isPaused = false; // Resume log stream when exiting selection mode\n if (this.selectionViewPollInterval) {\n clearInterval(this.selectionViewPollInterval);\n this.selectionViewPollInterval = null;\n }\n this.filterText = \"\";\n console.clear();\n // Re-render all logs in reverse chronological order\n const logs = this.storage.getAllLogs();\n for (const entry of logs) {\n this.renderer.renderLogLine(entry);\n }\n // Also render any buffered logs\n if (this.selectionBuffer.length > 0) {\n for (const entry of this.selectionBuffer) {\n this.renderer.renderLogLine(entry);\n }\n this.selectionBuffer = [];\n }\n return;\n }\n }\n }\n\n // Handle text input for filtering\n if (ch && (!key || (!key.ctrl && !key.meta)) && ch.length === 1) {\n this.filterText += ch;\n this.updateFilteredLogs();\n this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);\n return;\n }\n }\n\n // Handle detail view navigation\n if (this.isDetailView) {\n // Handle named keys\n if (key?.name) {\n switch (key.name) {\n case \"up\": {\n // Scroll up one line\n this.renderer.scrollDetailView(-1);\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n this.logs.length,\n this.filterText,\n );\n break;\n }\n case \"down\": {\n // Scroll down one line\n this.renderer.scrollDetailView(1);\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n this.logs.length,\n this.filterText,\n );\n break;\n }\n case \"left\": {\n // Show previous log in detail view\n if (this.selectedIndex > 0) {\n this.selectedIndex = Math.max(0, this.selectedIndex - 1);\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n 0,\n this.selectedIndex + 1,\n this.logs.length,\n this.filterText,\n );\n }\n break;\n }\n case \"right\": {\n // Show next log in detail view\n if (this.selectedIndex < this.logs.length - 1) {\n this.selectedIndex = Math.min(this.logs.length - 1, this.selectedIndex + 1);\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n 0,\n this.selectedIndex + 1,\n this.logs.length,\n this.filterText,\n );\n }\n break;\n }\n case \"tab\": {\n // If in JSON view, return to detail view\n if (this.renderer.isInJsonView()) {\n this.renderer.toggleJsonView();\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n this.logs.length,\n this.filterText,\n );\n break;\n }\n\n // Otherwise return to selection view\n this.isDetailView = false;\n if (this.detailViewPollInterval) {\n clearInterval(this.detailViewPollInterval);\n this.detailViewPollInterval = null;\n }\n this.isSelectionMode = true;\n this.updateFilteredLogs(); // Refresh logs when returning to selection view\n this.renderer.renderSelectionView(\n this.logs,\n this.selectedIndex,\n this.filterText,\n this.selectionBuffer.length,\n );\n break;\n }\n }\n }\n\n // Handle character inputs (Q/W for page scrolling, A/S for first/last, C for array toggle)\n if (ch) {\n switch (ch.toLowerCase()) {\n case \"w\": {\n // Scroll down one page\n this.renderer.scrollDetailView(process.stdout.rows - 8); // Account for header/footer space\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n this.logs.length,\n );\n break;\n }\n case \"q\": {\n // Scroll up one page\n this.renderer.scrollDetailView(-process.stdout.rows + 8); // Account for header/footer space\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n this.logs.length,\n );\n break;\n }\n case \"a\": {\n // Jump to first log\n if (this.selectedIndex !== 0) {\n this.selectedIndex = 0;\n const entry = this.logs[this.selectedIndex];\n const prevEntry = null; // No previous entry when at first log\n const nextEntry = this.logs.length > 1 ? this.logs[1] : null;\n this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, 1, this.logs.length);\n }\n break;\n }\n case \"s\": {\n // Jump to last log\n const lastIndex = this.logs.length - 1;\n if (this.selectedIndex !== lastIndex) {\n this.selectedIndex = lastIndex;\n const entry = this.logs[this.selectedIndex];\n const prevEntry = lastIndex > 0 ? this.logs[lastIndex - 1] : null;\n const nextEntry = null; // No next entry when at last log\n this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, this.logs.length, this.logs.length);\n }\n break;\n }\n case \"c\": {\n // Toggle array collapse\n this.renderer.toggleArrayCollapse();\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(\n entry,\n prevEntry,\n nextEntry,\n this.renderer.getDetailViewScrollPos(),\n this.selectedIndex + 1,\n this.logs.length,\n );\n break;\n }\n case \"j\": {\n // Toggle JSON view\n this.renderer.toggleJsonView();\n const entry = this.logs[this.selectedIndex];\n const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;\n const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;\n this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, this.selectedIndex + 1, this.logs.length);\n break;\n }\n }\n }\n }\n }\n}\n","/**\n * A transport for LogLayer that provides a pretty terminal output with interactive features.\n * This transport implements an interactive terminal UI for viewing and filtering logs.\n *\n * Features:\n * - Real-time log display with color-coded levels\n * - Interactive selection mode for browsing logs\n * - Detailed view for inspecting individual log entries\n * - Search/filter functionality\n * - JSON data pretty printing\n * - Configurable themes and colors\n *\n * The transport uses a singleton pattern to ensure only one instance exists,\n * as it manages terminal input and output which cannot be shared.\n */\n\nimport type { LogLayerTransportParams } from \"@loglayer/transport\";\nimport { LoggerlessTransport } from \"@loglayer/transport\";\nimport chalk from \"chalk\";\nimport { LogRenderer } from \"./LogRenderer.js\";\nimport { LogStorage } from \"./LogStorage.js\";\nimport { moonlight } from \"./themes.js\";\nimport type { DetailedViewConfig, PrettyTerminalConfig, ViewConfig } from \"./types.js\";\nimport { UIManager } from \"./UIManager.js\";\n\n/**\n * Main transport class that handles pretty terminal output and interactive features.\n * This class coordinates between different components:\n * - LogStorage: Handles persistence of logs in SQLite\n * - LogRenderer: Manages all rendering and formatting\n * - UIManager: Handles user interaction and view state\n *\n * The transport supports two main view modes:\n * 1. Simple View: Real-time log output with basic formatting\n * 2. Interactive View: Full-screen mode with navigation and filtering\n *\n * Usage:\n * ```typescript\n * const transport = PrettyTerminalTransport.getInstance({\n * maxInlineDepth: 4,\n * maxInlineLength: 120,\n * theme: customTheme\n * });\n * ```\n */\nexport class PrettyTerminalTransport extends LoggerlessTransport {\n /** Singleton instance of the transport */\n private static instance: PrettyTerminalTransport | null = null;\n\n /** Handles all rendering and formatting of logs */\n private renderer: LogRenderer;\n\n /** Manages log persistence in SQLite database */\n private storage: LogStorage;\n\n /** Manages user interaction and view state */\n private uiManager: UIManager;\n\n /** Configuration options */\n private config: PrettyTerminalConfig;\n\n /**\n * Creates a new PrettyTerminalTransport instance.\n * This is a singleton class - only one instance can exist at a time.\n * Use getInstance() instead of constructor directly.\n *\n * @param config - Configuration options for the transport\n * @throws Error if attempting to create multiple instances\n */\n constructor(config: PrettyTerminalConfig = {}) {\n if (PrettyTerminalTransport.instance) {\n throw new Error(\"PrettyTerminalTransport is a singleton. Use getPrettyTerminal() instead.\");\n }\n super(config);\n\n // Store configuration\n this.config = config;\n\n // If transport is disabled, don't initialize anything\n if (config.enabled === false) {\n return;\n }\n\n // Initialize configuration with defaults\n const maxInlineDepth = config.maxInlineDepth || 4;\n const maxInlineLength = config.maxInlineLength || 120;\n const theme = config.theme || moonlight;\n const logFile = config.logFile; // Get optional log file path from config\n\n // Initialize view configurations with defaults\n // Simple view is used for real-time log output\n const simpleViewConfig: Required<ViewConfig> = {\n colors: {\n trace: chalk.gray, // Lowest level, used for verbose output\n debug: chalk.blue, // Debug information\n info: chalk.green, // Normal operation\n warn: chalk.yellow, // Warning conditions\n error: chalk.red, // Error conditions\n fatal: chalk.bgRed.white, // Critical errors\n ...theme.simpleView.colors,\n },\n logIdColor: theme.simpleView.logIdColor || chalk.dim,\n dataValueColor: theme.simpleView.dataValueColor || chalk.white,\n dataKeyColor: theme.simpleView.dataKeyColor || chalk.dim,\n selectorColor: theme.simpleView.selectorColor || chalk.cyan,\n };\n\n // Detailed view is used in interactive mode\n const detailedViewConfig: Required<DetailedViewConfig> = {\n colors: {\n trace: chalk.gray,\n debug: chalk.blue,\n info: chalk.green,\n warn: chalk.yellow,\n error: chalk.red,\n fatal: chalk.bgRed.white,\n ...theme.detailedView?.colors,\n },\n logIdColor: theme.detailedView?.logIdColor || chalk.dim,\n dataValueColor: theme.detailedView?.dataValueColor || chalk.white,\n dataKeyColor: theme.detailedView?.dataKeyColor || chalk.dim,\n selectorColor: theme.detailedView?.selectorColor || chalk.cyan,\n headerColor: theme.detailedView?.headerColor || chalk.cyan,\n labelColor: theme.detailedView?.labelColor || chalk.cyan.bold,\n separatorColor: theme.detailedView?.separatorColor || chalk.dim,\n // JSON formatting colors for detailed data view\n jsonColors: {\n keysColor: chalk.yellow, // Object property names\n dashColor: chalk.white, // Array bullets\n numberColor: chalk.yellow, // Default number color\n stringColor: chalk.white, // Single-line strings\n multilineStringColor: chalk.white, // Multi-line strings\n positiveNumberColor: chalk.green, // Numbers > 0\n negativeNumberColor: chalk.red, // Numbers < 0\n booleanColor: chalk.cyan, // true/false values\n nullUndefinedColor: chalk.grey, // null/undefined\n dateColor: chalk.magenta, // Date objects\n ...theme.detailedView?.jsonColors,\n },\n };\n\n // Initialize components in dependency order\n this.storage = new LogStorage(logFile);\n this.renderer = new LogRenderer(simpleViewConfig, detailedViewConfig, maxInlineDepth, maxInlineLength);\n this.uiManager = new UIManager(this.renderer, this.storage, config.disableInteractiveMode);\n\n PrettyTerminalTransport.instance = this;\n }\n\n /**\n * Gets or creates the singleton instance of PrettyTerminalTransport.\n * This is the recommended way to obtain a transport instance.\n *\n * @param config - Configuration options for the transport\n * @returns The singleton instance of PrettyTerminalTransport\n */\n public static getInstance(config: PrettyTerminalConfig = {}): PrettyTerminalTransport {\n if (!PrettyTerminalTransport.instance) {\n PrettyTerminalTransport.instance = new PrettyTerminalTransport(config);\n }\n return PrettyTerminalTransport.instance;\n }\n\n /**\n * Generates a random ID for each log entry.\n * Uses base36 encoding for compact, readable IDs.\n *\n * @returns A 6-character string ID\n * @example\n * \"a1b2c3\" // Example generated ID\n */\n private generateId(): string {\n return Math.random().toString(36).substring(2, 8);\n }\n\n /**\n * Main transport method that receives logs from LogLayer.\n * This method is called for each log event and handles:\n * - Generating a unique ID for the log\n * - Converting the log data to a storable format\n * - Storing the log in the database\n * - Rendering the log if not in selection mode\n *\n * @param logLevel - The severity level of the log\n * @param messages - Array of message strings to be joined\n * @param data - Additional structured data to be logged\n * @param hasData - Whether the log includes additional data\n * @returns The original messages array\n */\n shipToLogger({ logLevel, messages, data, hasData }: LogLayerTransportParams): any[] {\n // If transport is disabled, return messages without processing\n if (this.config.enabled === false) {\n return messages;\n }\n\n const entry = {\n id: this.generateId(),\n timestamp: Date.now(),\n level: logLevel,\n message: messages.join(\" \"),\n data: hasData ? JSON.stringify(data) : null,\n };\n\n this.uiManager.handleNewLog(entry);\n return messages;\n }\n}\n","import { PrettyTerminalTransport } from \"./PrettyTerminalTransport.js\";\nimport type { PrettyTerminalConfig } from \"./types.js\";\n\nexport * as chalk from \"chalk\";\n\nexport * from \"./PrettyTerminalTransport.js\";\nexport * from \"./themes.js\";\nexport * from \"./types.js\";\n\nexport function getPrettyTerminal(config: PrettyTerminalConfig = {}) {\n return PrettyTerminalTransport.getInstance(config);\n}\n"],"mappings":"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"}
|