@loglayer/transport-pretty-terminal 4.0.4 → 4.1.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 CHANGED
@@ -1,742 +1,727 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4;// src/PrettyTerminalTransport.ts
2
- var _transport = require('@loglayer/transport');
3
- var _chalk = require('chalk'); var chalk8 = _interopRequireWildcard(_chalk);
4
-
5
- // src/views/DetailView.ts
6
-
7
- var _wrapansi = require('wrap-ansi'); var _wrapansi2 = _interopRequireDefault(_wrapansi);
8
-
9
- // src/vendor/prettyjson.js
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
10
22
 
23
+ //#endregion
24
+ let __loglayer_transport = require("@loglayer/transport");
25
+ __loglayer_transport = __toESM(__loglayer_transport);
26
+ let chalk = require("chalk");
27
+ chalk = __toESM(chalk);
28
+ let wrap_ansi = require("wrap-ansi");
29
+ wrap_ansi = __toESM(wrap_ansi);
30
+ let cli_truncate = require("cli-truncate");
31
+ cli_truncate = __toESM(cli_truncate);
32
+ let node_path = require("node:path");
33
+ node_path = __toESM(node_path);
34
+ let better_sqlite3 = require("better-sqlite3");
35
+ better_sqlite3 = __toESM(better_sqlite3);
36
+ let keypress = require("keypress");
37
+ keypress = __toESM(keypress);
11
38
 
12
- // src/vendor/utils.js
39
+ //#region src/vendor/utils.js
40
+ /**
41
+ * Creates a string with the same length as `numSpaces` parameter
42
+ **/
13
43
  function indent(numSpaces) {
14
- return new Array(numSpaces + 1).join(" ");
44
+ return new Array(numSpaces + 1).join(" ");
15
45
  }
46
+ /**
47
+ * Gets the string length of the longer index in a hash
48
+ **/
16
49
  function getMaxIndexLength(input) {
17
- var maxWidth = 0;
18
- Object.getOwnPropertyNames(input).forEach((key) => {
19
- if (input[key] === void 0) {
20
- return;
21
- }
22
- maxWidth = Math.max(maxWidth, key.length);
23
- });
24
- return maxWidth;
50
+ var maxWidth = 0;
51
+ Object.getOwnPropertyNames(input).forEach((key) => {
52
+ if (input[key] === void 0) return;
53
+ maxWidth = Math.max(maxWidth, key.length);
54
+ });
55
+ return maxWidth;
25
56
  }
26
57
  function isIsoStringDate(isoString) {
27
- if (typeof isoString !== "string") {
28
- return false;
29
- }
30
- if (!/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?$/.test(isoString)) {
31
- return false;
32
- }
33
- const testDate = new Date(isoString);
34
- return !Number.isNaN(testDate.getTime());
58
+ if (typeof isoString !== "string") return false;
59
+ if (!/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?$/.test(isoString)) return false;
60
+ const testDate = new Date(isoString);
61
+ return !Number.isNaN(testDate.getTime());
35
62
  }
36
63
 
37
- // src/vendor/prettyjson.js
38
- var conflictChars = /[^\w\s\n\r\v\t.,]/i;
39
- var isPrintable = (input, options) => input !== void 0 || options.renderUndefined;
40
- var isSerializable = (input, onlyPrimitives, options) => {
41
- if (typeof input === "boolean" || typeof input === "number" || typeof input === "function" || input === null || input === void 0 || input instanceof Date) {
42
- return true;
43
- }
44
- if (typeof input === "string" && input.indexOf("\n") === -1) {
45
- return true;
46
- }
47
- if (options.inlineArrays && !onlyPrimitives) {
48
- if (Array.isArray(input) && isSerializable(input[0], true, options)) {
49
- return true;
50
- }
51
- }
52
- return false;
64
+ //#endregion
65
+ //#region src/vendor/prettyjson.js
66
+ const conflictChars = /[^\w\s\n\r\v\t.,]/i;
67
+ const isPrintable = (input, options) => input !== void 0 || options.renderUndefined;
68
+ const isSerializable = (input, onlyPrimitives, options) => {
69
+ if (typeof input === "boolean" || typeof input === "number" || typeof input === "function" || input === null || input === void 0 || input instanceof Date) return true;
70
+ if (typeof input === "string" && input.indexOf("\n") === -1) return true;
71
+ if (options.inlineArrays && !onlyPrimitives) {
72
+ if (Array.isArray(input) && isSerializable(input[0], true, options)) return true;
73
+ }
74
+ return false;
53
75
  };
54
- var getColorRenderer = (colorFn, options) => {
55
- if (options.noColor) {
56
- return (text) => text;
57
- }
58
- if (typeof colorFn !== "function") {
59
- return (text) => text;
60
- }
61
- return colorFn;
76
+ /**
77
+ * @param {Function} colorFn
78
+ * @param {PrettyJSONOptions} options
79
+ */
80
+ const getColorRenderer = (colorFn, options) => {
81
+ if (options.noColor) return (text) => text;
82
+ if (typeof colorFn !== "function") return (text) => text;
83
+ return colorFn;
62
84
  };
63
- var addColorToData = (input, options) => {
64
- if (options.noColor) {
65
- return input;
66
- }
67
- if (input instanceof Date) {
68
- return getColorRenderer(options.dateColor, options)(input.toISOString());
69
- }
70
- if (typeof input === "string") {
71
- if (isIsoStringDate(input)) {
72
- return getColorRenderer(options.dateColor, options)(input);
73
- }
74
- return getColorRenderer(options.stringColor, options)(input);
75
- }
76
- const sInput = `${input}`;
77
- if (typeof input === "boolean") {
78
- return getColorRenderer(options.booleanColor, options)(sInput);
79
- }
80
- if (input === null || input === void 0) {
81
- return getColorRenderer(options.nullUndefinedColor, options)(sInput);
82
- }
83
- if (typeof input === "number") {
84
- if (input >= 0) {
85
- return getColorRenderer(options.positiveNumberColor, options)(sInput);
86
- }
87
- return getColorRenderer(options.negativeNumberColor, options)(sInput);
88
- }
89
- if (typeof input === "function") {
90
- return "function() {}";
91
- }
92
- if (Array.isArray(input)) {
93
- return input.join(", ");
94
- }
95
- return sInput;
85
+ const addColorToData = (input, options) => {
86
+ if (options.noColor) return input;
87
+ if (input instanceof Date) return getColorRenderer(options.dateColor, options)(input.toISOString());
88
+ if (typeof input === "string") {
89
+ if (isIsoStringDate(input)) return getColorRenderer(options.dateColor, options)(input);
90
+ return getColorRenderer(options.stringColor, options)(input);
91
+ }
92
+ const sInput = `${input}`;
93
+ if (typeof input === "boolean") return getColorRenderer(options.booleanColor, options)(sInput);
94
+ if (input === null || input === void 0) return getColorRenderer(options.nullUndefinedColor, options)(sInput);
95
+ if (typeof input === "number") {
96
+ if (input >= 0) return getColorRenderer(options.positiveNumberColor, options)(sInput);
97
+ return getColorRenderer(options.negativeNumberColor, options)(sInput);
98
+ }
99
+ if (typeof input === "function") return "function() {}";
100
+ if (Array.isArray(input)) return input.join(", ");
101
+ return sInput;
96
102
  };
97
- var colorMultilineString = (options, line) => getColorRenderer(options.multilineStringColor, options)(line);
98
- var indentLines = (string, spaces, options) => {
99
- let lines = string.split("\n");
100
- lines = lines.map((line) => indent(spaces) + colorMultilineString(options, line));
101
- return lines.join("\n");
103
+ const colorMultilineString = (options, line) => getColorRenderer(options.multilineStringColor, options)(line);
104
+ const indentLines = (string, spaces, options) => {
105
+ let lines = string.split("\n");
106
+ lines = lines.map((line) => indent(spaces) + colorMultilineString(options, line));
107
+ return lines.join("\n");
102
108
  };
103
- var renderToArray = (data, options, indentation) => {
104
- if (typeof data === "string" && data.match(conflictChars) && options.escape) {
105
- data = JSON.stringify(data);
106
- }
107
- if (!isPrintable(data, options)) {
108
- return [];
109
- }
110
- if (isSerializable(data, false, options)) {
111
- return [indent(indentation) + addColorToData(data, options)];
112
- }
113
- if (typeof data === "string") {
114
- return [
115
- indent(indentation) + colorMultilineString(options, '"""'),
116
- indentLines(data, indentation + options.defaultIndentation, options),
117
- indent(indentation) + colorMultilineString(options, '"""')
118
- ];
119
- }
120
- if (Array.isArray(data)) {
121
- if (data.length === 0) {
122
- return [indent(indentation) + options.emptyArrayMsg];
123
- }
124
- if (options.collapseArrays && data.length > 0) {
125
- return [`${indent(indentation)}[... ${data.length} items]`];
126
- }
127
- const outputArray = [];
128
- data.forEach((element) => {
129
- if (!isPrintable(element, options)) {
130
- return;
131
- }
132
- let line = "- ";
133
- line = getColorRenderer(options.dashColor, options)(line);
134
- line = indent(indentation) + line;
135
- if (isSerializable(element, false, options)) {
136
- line += renderToArray(element, options, 0)[0];
137
- outputArray.push(line);
138
- } else {
139
- outputArray.push(line);
140
- outputArray.push.apply(outputArray, renderToArray(element, options, indentation + options.defaultIndentation));
141
- }
142
- });
143
- return outputArray;
144
- }
145
- if (data instanceof Error) {
146
- return renderToArray(
147
- {
148
- message: data.message,
149
- stack: data.stack.split("\n")
150
- },
151
- options,
152
- indentation
153
- );
154
- }
155
- const maxIndexLength = options.noAlign ? 0 : getMaxIndexLength(data);
156
- let key;
157
- const output = [];
158
- Object.getOwnPropertyNames(data).forEach((i) => {
159
- if (!isPrintable(data[i], options)) {
160
- return;
161
- }
162
- key = `${i}: `;
163
- key = getColorRenderer(options.keysColor, options)(key);
164
- key = indent(indentation) + key;
165
- if (isSerializable(data[i], false, options)) {
166
- const nextIndentation = options.noAlign ? 0 : maxIndexLength - i.length;
167
- key += renderToArray(data[i], options, nextIndentation)[0];
168
- output.push(key);
169
- } else {
170
- output.push(key);
171
- output.push.apply(output, renderToArray(data[i], options, indentation + options.defaultIndentation));
172
- }
173
- });
174
- return output;
109
+ const renderToArray = (data, options, indentation) => {
110
+ if (typeof data === "string" && data.match(conflictChars) && options.escape) data = JSON.stringify(data);
111
+ if (!isPrintable(data, options)) return [];
112
+ if (isSerializable(data, false, options)) return [indent(indentation) + addColorToData(data, options)];
113
+ if (typeof data === "string") return [
114
+ indent(indentation) + colorMultilineString(options, "\"\"\""),
115
+ indentLines(data, indentation + options.defaultIndentation, options),
116
+ indent(indentation) + colorMultilineString(options, "\"\"\"")
117
+ ];
118
+ if (Array.isArray(data)) {
119
+ if (data.length === 0) return [indent(indentation) + options.emptyArrayMsg];
120
+ if (options.collapseArrays && data.length > 0) return [`${indent(indentation)}[... ${data.length} items]`];
121
+ const outputArray = [];
122
+ data.forEach((element) => {
123
+ if (!isPrintable(element, options)) return;
124
+ let line = "- ";
125
+ line = getColorRenderer(options.dashColor, options)(line);
126
+ line = indent(indentation) + line;
127
+ if (isSerializable(element, false, options)) {
128
+ line += renderToArray(element, options, 0)[0];
129
+ outputArray.push(line);
130
+ } else {
131
+ outputArray.push(line);
132
+ outputArray.push.apply(outputArray, renderToArray(element, options, indentation + options.defaultIndentation));
133
+ }
134
+ });
135
+ return outputArray;
136
+ }
137
+ if (data instanceof Error) return renderToArray({
138
+ message: data.message,
139
+ stack: data.stack.split("\n")
140
+ }, options, indentation);
141
+ const maxIndexLength = options.noAlign ? 0 : getMaxIndexLength(data);
142
+ let key;
143
+ const output = [];
144
+ Object.getOwnPropertyNames(data).forEach((i) => {
145
+ if (!isPrintable(data[i], options)) return;
146
+ key = `${i}: `;
147
+ key = getColorRenderer(options.keysColor, options)(key);
148
+ key = indent(indentation) + key;
149
+ if (isSerializable(data[i], false, options)) {
150
+ const nextIndentation = options.noAlign ? 0 : maxIndexLength - i.length;
151
+ key += renderToArray(data[i], options, nextIndentation)[0];
152
+ output.push(key);
153
+ } else {
154
+ output.push(key);
155
+ output.push.apply(output, renderToArray(data[i], options, indentation + options.defaultIndentation));
156
+ }
157
+ });
158
+ return output;
175
159
  };
176
- var validateOptionsAndSetDefaults = (options) => {
177
- options = options || {};
178
- options.emptyArrayMsg = options.emptyArrayMsg || "(empty array)";
179
- options.keysColor = options.keysColor || chalk8.default.green;
180
- options.dashColor = options.dashColor || chalk8.default.green;
181
- options.booleanColor = options.booleanColor || chalk8.default.cyan;
182
- options.nullUndefinedColor = options.nullUndefinedColor || chalk8.default.grey;
183
- options.numberColor = options.numberColor || chalk8.default.blue;
184
- options.positiveNumberColor = options.positiveNumberColor || options.numberColor;
185
- options.negativeNumberColor = options.negativeNumberColor || options.numberColor;
186
- options.dateColor = options.dateColor || chalk8.default.magenta;
187
- options.defaultIndentation = options.defaultIndentation || 2;
188
- options.noColor = !!options.noColor;
189
- options.noAlign = !!options.noAlign;
190
- options.escape = !!options.escape;
191
- options.renderUndefined = !!options.renderUndefined;
192
- options.collapseArrays = !!options.collapseArrays;
193
- options.stringColor = options.stringColor || null;
194
- options.multilineStringColor = options.multilineStringColor || options.stringColor || null;
195
- return options;
160
+ /**
161
+ * @typedef {Object} PrettyJSONOptions
162
+ * @property {Function} [stringColor=null] Chalk color function for strings
163
+ * @property {Function} [multilineStringColor=null] Chalk color function for multiline strings
164
+ * @property {Function} [keysColor=chalk.green] Chalk color function for keys in hashes
165
+ * @property {Function} [dashColor=chalk.green] Chalk color function for dashes in arrays
166
+ * @property {Function} [numberColor=chalk.blue] Default Chalk color function for numbers
167
+ * @property {Function} [positiveNumberColor=numberColor] Chalk color function for positive numbers
168
+ * @property {Function} [negativeNumberColor=numberColor] Chalk color function for negative numbers
169
+ * @property {Function} [booleanColor=chalk.cyan] Chalk color function for boolean values
170
+ * @property {Function} [nullUndefinedColor=chalk.grey] Chalk color function for null || undefined
171
+ * @property {Function} [dateColor=chalk.magenta] Chalk color function for Date objects
172
+ * @property {number} [defaultIndentation=2] Indentation spaces per object level
173
+ * @property {string} [emptyArrayMsg="(empty array)"] Replace empty strings with
174
+ * @property {boolean} [noColor] Flag to disable colors
175
+ * @property {boolean} [noAlign] Flag to disable alignment
176
+ * @property {boolean} [escape] Flag to escape printed content
177
+ * @property {boolean} [collapseArrays] Flag to collapse arrays
178
+ */
179
+ /**
180
+ * Mutating function that ensures we have a valid options object
181
+ * @param {PrettyJSONOptions} options
182
+ * @returns PrettyJSONOptions
183
+ */
184
+ const validateOptionsAndSetDefaults = (options) => {
185
+ options = options || {};
186
+ options.emptyArrayMsg = options.emptyArrayMsg || "(empty array)";
187
+ options.keysColor = options.keysColor || chalk.default.green;
188
+ options.dashColor = options.dashColor || chalk.default.green;
189
+ options.booleanColor = options.booleanColor || chalk.default.cyan;
190
+ options.nullUndefinedColor = options.nullUndefinedColor || chalk.default.grey;
191
+ options.numberColor = options.numberColor || chalk.default.blue;
192
+ options.positiveNumberColor = options.positiveNumberColor || options.numberColor;
193
+ options.negativeNumberColor = options.negativeNumberColor || options.numberColor;
194
+ options.dateColor = options.dateColor || chalk.default.magenta;
195
+ options.defaultIndentation = options.defaultIndentation || 2;
196
+ options.noColor = !!options.noColor;
197
+ options.noAlign = !!options.noAlign;
198
+ options.escape = !!options.escape;
199
+ options.renderUndefined = !!options.renderUndefined;
200
+ options.collapseArrays = !!options.collapseArrays;
201
+ options.stringColor = options.stringColor || null;
202
+ options.multilineStringColor = options.multilineStringColor || options.stringColor || null;
203
+ return options;
196
204
  };
205
+ /**
206
+ * ### Render function
207
+ * *Parameters:*
208
+ *
209
+ * @param {*} data: Data to render
210
+ * @param {PrettyJSONOptions} options: Hash of different options
211
+ * @param {*} indentation **`indentation`**: Base indentation of the output
212
+ *
213
+ * *Example of options hash:*
214
+ *
215
+ * {
216
+ * emptyArrayMsg: '(empty)', // Rendered message on empty strings
217
+ * keysColor: 'blue', // Color for keys in hashes
218
+ * dashColor: 'red', // Color for the dashes in arrays
219
+ * stringColor: 'grey', // Color for strings
220
+ * multilineStringColor: 'cyan' // Color for multiline strings
221
+ * defaultIndentation: 2 // Indentation on nested objects
222
+ * }
223
+ * @returns string with the rendered data
224
+ */
197
225
  function render(data, options, indentation) {
198
- indentation = indentation || 0;
199
- options = validateOptionsAndSetDefaults(options);
200
- return renderToArray(data, options, indentation).join("\n");
226
+ indentation = indentation || 0;
227
+ options = validateOptionsAndSetDefaults(options);
228
+ return renderToArray(data, options, indentation).join("\n");
201
229
  }
202
230
 
203
- // src/views/utils.ts
204
-
205
- var _clitruncate = require('cli-truncate'); var _clitruncate2 = _interopRequireDefault(_clitruncate);
231
+ //#endregion
232
+ //#region src/views/utils.ts
233
+ /**
234
+ * Formats a timestamp into a human-readable string.
235
+ * Format: HH:MM:SS.mmm
236
+ */
206
237
  function formatTimestamp(timestamp, colorFn) {
207
- const date = new Date(timestamp);
208
- return colorFn(
209
- `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}:${date.getSeconds().toString().padStart(2, "0")}.${date.getMilliseconds().toString().padStart(3, "0")}`
210
- );
238
+ const date = new Date(timestamp);
239
+ return colorFn(`${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}:${date.getSeconds().toString().padStart(2, "0")}.${date.getMilliseconds().toString().padStart(3, "0")}`);
211
240
  }
241
+ /**
242
+ * Gets the color function for a log level.
243
+ */
212
244
  function getLevelColor(level, colors) {
213
- return colors[level] || chalk8.default.white;
245
+ return colors[level] || chalk.default.white;
214
246
  }
247
+ /**
248
+ * Formats a value for display.
249
+ */
215
250
  function formatValue(value, expanded = false) {
216
- if (typeof value === "string") return value;
217
- if (typeof value === "number" || typeof value === "boolean") return value.toString();
218
- if (value === null) return "null";
219
- if (value === void 0) return "undefined";
220
- if (Array.isArray(value)) return expanded ? JSON.stringify(value) : "[...]";
221
- if (typeof value === "object") return expanded ? JSON.stringify(value) : "{...}";
222
- return value.toString();
251
+ if (typeof value === "string") return value;
252
+ if (typeof value === "number" || typeof value === "boolean") return value.toString();
253
+ if (value === null) return "null";
254
+ if (value === void 0) return "undefined";
255
+ if (Array.isArray(value)) return expanded ? JSON.stringify(value) : "[...]";
256
+ if (typeof value === "object") return expanded ? JSON.stringify(value) : "{...}";
257
+ return value.toString();
223
258
  }
259
+ /**
260
+ * Formats structured data for inline display with depth limiting.
261
+ */
224
262
  function formatInlineData(data, config, maxDepth, maxLength, expanded = false) {
225
- if (!data) return "";
226
- const pairs = [];
227
- const traverse = (obj, prefix = "", depth = 0) => {
228
- if (!expanded && depth >= maxDepth) return;
229
- for (const [key, value] of Object.entries(obj)) {
230
- const fullKey = prefix ? `${prefix}.${key}` : key;
231
- if (value && typeof value === "object" && !Array.isArray(value)) {
232
- if (expanded) {
233
- pairs.push(`${config.dataKeyColor(fullKey)}=${config.dataValueColor(JSON.stringify(value))}`);
234
- } else {
235
- traverse(value, fullKey, depth + 1);
236
- }
237
- } else {
238
- pairs.push(`${config.dataKeyColor(fullKey)}=${config.dataValueColor(formatValue(value, expanded))}`);
239
- }
240
- }
241
- };
242
- traverse(data);
243
- const result = pairs.join(" ");
244
- return expanded ? result : _clitruncate2.default.call(void 0, result, maxLength);
263
+ if (!data) return "";
264
+ const pairs = [];
265
+ const traverse = (obj, prefix = "", depth = 0) => {
266
+ if (!expanded && depth >= maxDepth) return;
267
+ for (const [key, value] of Object.entries(obj)) {
268
+ const fullKey = prefix ? `${prefix}.${key}` : key;
269
+ if (value && typeof value === "object" && !Array.isArray(value)) if (expanded) pairs.push(`${config.dataKeyColor(fullKey)}=${config.dataValueColor(JSON.stringify(value))}`);
270
+ else traverse(value, fullKey, depth + 1);
271
+ else pairs.push(`${config.dataKeyColor(fullKey)}=${config.dataValueColor(formatValue(value, expanded))}`);
272
+ }
273
+ };
274
+ traverse(data);
275
+ const result = pairs.join(" ");
276
+ return expanded ? result : (0, cli_truncate.default)(result, maxLength);
245
277
  }
246
278
 
247
- // src/views/DetailView.ts
248
- var DetailView = (_class = class {
249
-
250
-
251
- __init() {this.detailViewContent = []}
252
- constructor(config) {;_class.prototype.__init.call(this);
253
- this.config = config;
254
- this.termWidth = process.stdout.columns || 80;
255
- }
256
- updateTerminalWidth(width) {
257
- this.termWidth = width;
258
- }
259
- /**
260
- * Formats a compact single-line version of a log entry
261
- */
262
- formatCompactLogLine(entry, prefix = "") {
263
- if (!entry) return "";
264
- const levelColor = getLevelColor(entry.level, this.config.config.colors);
265
- const logId = this.config.config.logIdColor(`[${entry.id}]`);
266
- const line = `${prefix}${levelColor(entry.level.toUpperCase())} ${logId} ${entry.message}`;
267
- return this.config.config.separatorColor(_wrapansi2.default.call(void 0, line, this.termWidth, { hard: true }));
268
- }
269
- /**
270
- * Formats a timestamp into a human-readable relative time
271
- */
272
- formatRelativeTime(timestamp) {
273
- const now = /* @__PURE__ */ new Date();
274
- const diffMs = now.getTime() - timestamp.getTime();
275
- const diffSecs = Math.floor(diffMs / 1e3);
276
- const diffMins = Math.floor(diffSecs / 60);
277
- const diffHours = Math.floor(diffMins / 60);
278
- const diffDays = Math.floor(diffHours / 24);
279
- if (diffSecs < 60) return `${diffSecs}s ago`;
280
- if (diffMins < 60) return `${diffMins}m ago`;
281
- if (diffHours < 24) return `${diffHours}h ago`;
282
- if (diffDays === 1) return "yesterday";
283
- if (diffDays < 30) return `${diffDays}d ago`;
284
- return timestamp.toLocaleDateString();
285
- }
286
- render() {
287
- console.clear();
288
- console.log("\n".repeat(5));
289
- if (this.config.isJsonView) {
290
- if (this.config.entry.data) {
291
- console.log(JSON.stringify(JSON.parse(this.config.entry.data)));
292
- } else {
293
- console.log("{}");
294
- }
295
- console.log(`
296
- ${this.config.config.separatorColor("TAB to return to detailed view")}`);
297
- return;
298
- }
299
- const headerContent = [];
300
- if (this.config.prevEntry) {
301
- const prevLine = this.formatCompactLogLine(this.config.prevEntry, "\u2190 ");
302
- headerContent.push(prevLine);
303
- headerContent.push(this.config.config.separatorColor("\u2500".repeat(this.termWidth)));
304
- }
305
- const footerContent = [];
306
- if (this.config.nextEntry) {
307
- footerContent.push(this.config.config.separatorColor("\u2500".repeat(this.termWidth)));
308
- const nextLine = this.formatCompactLogLine(this.config.nextEntry, "\u2192 ");
309
- footerContent.push(nextLine);
310
- }
311
- footerContent.push("");
312
- footerContent.push(this.config.config.separatorColor("\u2191/\u2193 scroll \u2022 Q/W page up/down \u2022 J raw JSON"));
313
- footerContent.push(this.config.config.separatorColor("\u2190/\u2192 navigate \u2022 A/S first/last log \u2022 C toggle arrays"));
314
- const mainContent = [];
315
- const levelColor = getLevelColor(this.config.entry.level, this.config.config.colors);
316
- let headerText = `=== Log Detail [${this.config.entry.id}] (${this.config.currentLogIndex} / ${this.config.totalLogs})`;
317
- if (this.config.filterText) {
318
- headerText += ` [Filter: ${this.config.filterText}]`;
319
- }
320
- headerText += " ===";
321
- const header = levelColor(headerText);
322
- mainContent.push(header);
323
- const timestamp = new Date(this.config.entry.timestamp);
324
- const isoTime = formatTimestamp(this.config.entry.timestamp, this.config.config.dataValueColor);
325
- const relativeTime = this.formatRelativeTime(timestamp);
326
- mainContent.push(`${this.config.config.labelColor("Timestamp:")} ${isoTime} (${relativeTime})`);
327
- mainContent.push(
328
- `${this.config.config.labelColor("Level:")} ${levelColor.bold(this.config.entry.level.toUpperCase())}`
329
- );
330
- if (this.config.entry.message) {
331
- mainContent.push(
332
- `${this.config.config.labelColor("Message:")} ${this.config.config.dataValueColor(this.config.entry.message)}`
333
- );
334
- } else {
335
- mainContent.push(
336
- `${this.config.config.labelColor("Message:")} ${this.config.config.dataValueColor.dim("(no message)")}`
337
- );
338
- }
339
- if (this.config.entry.data) {
340
- mainContent.push(this.config.config.labelColor("\nData:"));
341
- const jsonLines = render(JSON.parse(this.config.entry.data), {
342
- ...this.config.config.jsonColors,
343
- defaultIndentation: 2,
344
- collapseArrays: this.config.isArraysCollapsed
345
- }).split("\n");
346
- mainContent.push(...jsonLines);
347
- }
348
- this.detailViewContent = mainContent;
349
- const headerHeight = headerContent.length;
350
- const footerHeight = footerContent.length;
351
- const scrollIndicatorLines = 2;
352
- const bufferSpace = 4;
353
- const topPadding = 2;
354
- const availableHeight = Math.max(
355
- 0,
356
- process.stdout.rows - headerHeight - footerHeight - scrollIndicatorLines - bufferSpace - topPadding
357
- );
358
- for (const line of headerContent) {
359
- console.log(line);
360
- }
361
- if (this.config.scrollPos > 0) {
362
- console.log(chalk8.default.dim("\u2191 More content above"));
363
- }
364
- const startIndex = this.config.scrollPos;
365
- const visibleContent = mainContent.slice(startIndex, startIndex + availableHeight);
366
- for (const line of visibleContent) {
367
- console.log(line);
368
- }
369
- if (this.config.scrollPos + availableHeight < mainContent.length) {
370
- console.log(chalk8.default.dim("\u2193 More content below"));
371
- } else {
372
- console.log(chalk8.default.dim("End of content"));
373
- }
374
- for (const line of footerContent) {
375
- console.log(line);
376
- }
377
- }
378
- /**
379
- * Gets the maximum scroll position based on current content and window size
380
- */
381
- getMaxScrollPosition() {
382
- const headerHeight = this.config.prevEntry ? 2 : 0;
383
- const footerHeight = 5;
384
- const scrollIndicatorLines = 2;
385
- const bufferSpace = 2;
386
- const topPadding = 2;
387
- const availableHeight = Math.max(
388
- 0,
389
- process.stdout.rows - headerHeight - footerHeight - scrollIndicatorLines - bufferSpace - topPadding
390
- );
391
- return Math.max(0, this.detailViewContent.length - availableHeight);
392
- }
393
- }, _class);
394
-
395
- // src/views/SelectionView.ts
396
-
279
+ //#endregion
280
+ //#region src/views/DetailView.ts
281
+ /**
282
+ * Handles rendering of the detail view mode.
283
+ * Shows a full-screen view of a single log entry with:
284
+ * - Previous/next log context
285
+ * - Full timestamp information
286
+ * - Pretty-printed data
287
+ * - Navigation help
288
+ */
289
+ var DetailView = class {
290
+ termWidth;
291
+ config;
292
+ detailViewContent = [];
293
+ constructor(config) {
294
+ this.config = config;
295
+ this.termWidth = process.stdout.columns || 80;
296
+ }
297
+ updateTerminalWidth(width) {
298
+ this.termWidth = width;
299
+ }
300
+ /**
301
+ * Formats a compact single-line version of a log entry
302
+ */
303
+ formatCompactLogLine(entry, prefix = "") {
304
+ if (!entry) return "";
305
+ const levelColor = getLevelColor(entry.level, this.config.config.colors);
306
+ const logId = this.config.config.logIdColor(`[${entry.id}]`);
307
+ const line = `${prefix}${levelColor(entry.level.toUpperCase())} ${logId} ${entry.message}`;
308
+ return this.config.config.separatorColor((0, wrap_ansi.default)(line, this.termWidth, { hard: true }));
309
+ }
310
+ /**
311
+ * Formats a timestamp into a human-readable relative time
312
+ */
313
+ formatRelativeTime(timestamp) {
314
+ const diffMs = (/* @__PURE__ */ new Date()).getTime() - timestamp.getTime();
315
+ const diffSecs = Math.floor(diffMs / 1e3);
316
+ const diffMins = Math.floor(diffSecs / 60);
317
+ const diffHours = Math.floor(diffMins / 60);
318
+ const diffDays = Math.floor(diffHours / 24);
319
+ if (diffSecs < 60) return `${diffSecs}s ago`;
320
+ if (diffMins < 60) return `${diffMins}m ago`;
321
+ if (diffHours < 24) return `${diffHours}h ago`;
322
+ if (diffDays === 1) return "yesterday";
323
+ if (diffDays < 30) return `${diffDays}d ago`;
324
+ return timestamp.toLocaleDateString();
325
+ }
326
+ render() {
327
+ console.clear();
328
+ console.log("\n".repeat(5));
329
+ if (this.config.isJsonView) {
330
+ if (this.config.entry.data) console.log(JSON.stringify(JSON.parse(this.config.entry.data)));
331
+ else console.log("{}");
332
+ console.log(`\n${this.config.config.separatorColor("TAB to return to detailed view")}`);
333
+ return;
334
+ }
335
+ const headerContent = [];
336
+ if (this.config.prevEntry) {
337
+ const prevLine = this.formatCompactLogLine(this.config.prevEntry, "← ");
338
+ headerContent.push(prevLine);
339
+ headerContent.push(this.config.config.separatorColor("".repeat(this.termWidth)));
340
+ }
341
+ const footerContent = [];
342
+ if (this.config.nextEntry) {
343
+ footerContent.push(this.config.config.separatorColor("".repeat(this.termWidth)));
344
+ const nextLine = this.formatCompactLogLine(this.config.nextEntry, " ");
345
+ footerContent.push(nextLine);
346
+ }
347
+ footerContent.push("");
348
+ footerContent.push(this.config.config.separatorColor("↑/↓ scroll • Q/W page up/down • J raw JSON"));
349
+ footerContent.push(this.config.config.separatorColor("←/→ navigate • A/S first/last log • C toggle arrays"));
350
+ const mainContent = [];
351
+ const levelColor = getLevelColor(this.config.entry.level, this.config.config.colors);
352
+ let headerText = `=== Log Detail [${this.config.entry.id}] (${this.config.currentLogIndex} / ${this.config.totalLogs})`;
353
+ if (this.config.filterText) headerText += ` [Filter: ${this.config.filterText}]`;
354
+ headerText += " ===";
355
+ const header = levelColor(headerText);
356
+ mainContent.push(header);
357
+ const timestamp = new Date(this.config.entry.timestamp);
358
+ const isoTime = formatTimestamp(this.config.entry.timestamp, this.config.config.dataValueColor);
359
+ const relativeTime = this.formatRelativeTime(timestamp);
360
+ mainContent.push(`${this.config.config.labelColor("Timestamp:")} ${isoTime} (${relativeTime})`);
361
+ mainContent.push(`${this.config.config.labelColor("Level:")} ${levelColor.bold(this.config.entry.level.toUpperCase())}`);
362
+ if (this.config.entry.message) mainContent.push(`${this.config.config.labelColor("Message:")} ${this.config.config.dataValueColor(this.config.entry.message)}`);
363
+ else mainContent.push(`${this.config.config.labelColor("Message:")} ${this.config.config.dataValueColor.dim("(no message)")}`);
364
+ if (this.config.entry.data) {
365
+ mainContent.push(this.config.config.labelColor("\nData:"));
366
+ const jsonLines = render(JSON.parse(this.config.entry.data), {
367
+ ...this.config.config.jsonColors,
368
+ defaultIndentation: 2,
369
+ collapseArrays: this.config.isArraysCollapsed
370
+ }).split("\n");
371
+ mainContent.push(...jsonLines);
372
+ }
373
+ this.detailViewContent = mainContent;
374
+ const headerHeight = headerContent.length;
375
+ const footerHeight = footerContent.length;
376
+ const availableHeight = Math.max(0, process.stdout.rows - headerHeight - footerHeight - 2 - 4 - 2);
377
+ for (const line of headerContent) console.log(line);
378
+ if (this.config.scrollPos > 0) console.log(chalk.default.dim("↑ More content above"));
379
+ const startIndex = this.config.scrollPos;
380
+ const visibleContent = mainContent.slice(startIndex, startIndex + availableHeight);
381
+ for (const line of visibleContent) console.log(line);
382
+ if (this.config.scrollPos + availableHeight < mainContent.length) console.log(chalk.default.dim("↓ More content below"));
383
+ else console.log(chalk.default.dim("End of content"));
384
+ for (const line of footerContent) console.log(line);
385
+ }
386
+ /**
387
+ * Gets the maximum scroll position based on current content and window size
388
+ */
389
+ getMaxScrollPosition() {
390
+ const headerHeight = this.config.prevEntry ? 2 : 0;
391
+ const availableHeight = Math.max(0, process.stdout.rows - headerHeight - 5 - 2 - 2 - 2);
392
+ return Math.max(0, this.detailViewContent.length - availableHeight);
393
+ }
394
+ };
397
395
 
396
+ //#endregion
397
+ //#region src/views/SelectionView.ts
398
+ /**
399
+ * Handles rendering of the selection view mode.
400
+ * Shows an interactive list of logs with:
401
+ * - Filtering capability
402
+ * - Selected item highlighting
403
+ * - Full data preview inline
404
+ * - Scroll indicators
405
+ */
398
406
  var SelectionView = class {
399
-
400
-
401
- constructor(config) {
402
- this.config = config;
403
- this.termWidth = process.stdout.columns || 80;
404
- }
405
- updateTerminalWidth(width) {
406
- this.termWidth = width;
407
- }
408
- render() {
409
- console.clear();
410
- console.log("\n".repeat(5));
411
- const filterHeight = this.config.filterText ? 2 : 0;
412
- const footerHeight = 2;
413
- const topPadding = 5;
414
- const availableHeight = process.stdout.rows - filterHeight - footerHeight - topPadding;
415
- if (this.config.logs.length === 0) {
416
- console.log(chalk8.default.yellow("No matching logs found"));
417
- } else {
418
- const visibleLines = Math.min(availableHeight, 20);
419
- const bottomPadding = 2;
420
- let startIdx = Math.max(0, this.config.selectedIndex - (visibleLines - bottomPadding - 1));
421
- const endIdx = Math.min(this.config.logs.length, startIdx + visibleLines);
422
- if (endIdx - startIdx < visibleLines && endIdx < this.config.logs.length) {
423
- startIdx = Math.max(0, endIdx - visibleLines);
424
- }
425
- if (startIdx > 0) {
426
- console.log(chalk8.default.dim(" \u2191 More logs above"));
427
- }
428
- this.config.logs.slice(startIdx, endIdx).forEach((entry, index) => {
429
- const actualIndex = startIdx + index;
430
- const isSelected = actualIndex === this.config.selectedIndex;
431
- const prefix = isSelected ? this.config.config.selectorColor("\u25BA ") : " ";
432
- const timestamp = formatTimestamp(entry.timestamp, this.config.config.logIdColor);
433
- const levelColor = getLevelColor(entry.level, this.config.config.colors);
434
- const chevron = levelColor(`${entry.level.toUpperCase()} `);
435
- const logId = chalk8.default.dim(`[${entry.id}]`);
436
- const message = entry.message;
437
- const data = entry.data ? ` ${formatInlineData(JSON.parse(entry.data), this.config.config, 0, 0, true)}` : "";
438
- const mainLine = `${prefix}${timestamp} ${chevron}${logId} ${message}${data}`;
439
- const wrappedText = _wrapansi2.default.call(void 0, mainLine, this.termWidth - 2, { hard: true });
440
- if (isSelected) {
441
- const lines = wrappedText.split("\n");
442
- console.log(lines[0]);
443
- for (const line of lines.slice(1)) {
444
- console.log(` ${this.config.config.selectorColor("\u2502")} ${line}`);
445
- }
446
- } else {
447
- console.log(wrappedText);
448
- }
449
- });
450
- if (endIdx < this.config.logs.length || this.config.newLogCount > 0) {
451
- const moreLogsText = this.config.newLogCount > 0 ? this.config.config.selectorColor(
452
- ` \u2193 ${this.config.newLogCount} new log${this.config.newLogCount === 1 ? "" : "s"} available (press \u2193 to view)`
453
- ) : chalk8.default.dim(" \u2193 More logs below");
454
- console.log(moreLogsText);
455
- }
456
- }
457
- console.log(chalk8.default.dim("\nType to filter \u2022 Enter to view details \u2022 TAB to exit"));
458
- if (this.config.filterText) {
459
- console.log(chalk8.default.dim("\u2500".repeat(this.termWidth)));
460
- console.log(chalk8.default.cyan("Filter:"), chalk8.default.white(this.config.filterText));
461
- }
462
- }
407
+ termWidth;
408
+ config;
409
+ constructor(config) {
410
+ this.config = config;
411
+ this.termWidth = process.stdout.columns || 80;
412
+ }
413
+ updateTerminalWidth(width) {
414
+ this.termWidth = width;
415
+ }
416
+ render() {
417
+ console.clear();
418
+ console.log("\n".repeat(5));
419
+ const filterHeight = this.config.filterText ? 2 : 0;
420
+ const availableHeight = process.stdout.rows - filterHeight - 2 - 5;
421
+ if (this.config.logs.length === 0) console.log(chalk.default.yellow("No matching logs found"));
422
+ else {
423
+ const visibleLines = Math.min(availableHeight, 20);
424
+ let startIdx = Math.max(0, this.config.selectedIndex - (visibleLines - 2 - 1));
425
+ const endIdx = Math.min(this.config.logs.length, startIdx + visibleLines);
426
+ if (endIdx - startIdx < visibleLines && endIdx < this.config.logs.length) startIdx = Math.max(0, endIdx - visibleLines);
427
+ if (startIdx > 0) console.log(chalk.default.dim(" ↑ More logs above"));
428
+ this.config.logs.slice(startIdx, endIdx).forEach((entry, index) => {
429
+ const isSelected = startIdx + index === this.config.selectedIndex;
430
+ const wrappedText = (0, wrap_ansi.default)(`${isSelected ? this.config.config.selectorColor("► ") : " "}${formatTimestamp(entry.timestamp, this.config.config.logIdColor)} ${getLevelColor(entry.level, this.config.config.colors)(`${entry.level.toUpperCase()} `)}${chalk.default.dim(`[${entry.id}]`)} ${entry.message}${entry.data ? ` ${formatInlineData(JSON.parse(entry.data), this.config.config, 0, 0, true)}` : ""}`, this.termWidth - 2, { hard: true });
431
+ if (isSelected) {
432
+ const lines = wrappedText.split("\n");
433
+ console.log(lines[0]);
434
+ for (const line of lines.slice(1)) console.log(` ${this.config.config.selectorColor("")} ${line}`);
435
+ } else console.log(wrappedText);
436
+ });
437
+ if (endIdx < this.config.logs.length || this.config.newLogCount > 0) {
438
+ const moreLogsText = this.config.newLogCount > 0 ? this.config.config.selectorColor(` ↓ ${this.config.newLogCount} new log${this.config.newLogCount === 1 ? "" : "s"} available (press ↓ to view)`) : chalk.default.dim(" ↓ More logs below");
439
+ console.log(moreLogsText);
440
+ }
441
+ }
442
+ console.log(chalk.default.dim("\nType to filter • Enter to view details • TAB to exit"));
443
+ if (this.config.filterText) {
444
+ console.log(chalk.default.dim("─".repeat(this.termWidth)));
445
+ console.log(chalk.default.cyan("Filter:"), chalk.default.white(this.config.filterText));
446
+ }
447
+ }
463
448
  };
464
449
 
465
- // src/views/SimpleView.ts
466
-
450
+ //#endregion
451
+ //#region src/views/SimpleView.ts
452
+ /**
453
+ * Handles rendering of the simple view mode.
454
+ * Supports three display modes:
455
+ * - Truncated: Shows all log details with truncated data
456
+ * - Condensed: Shows timestamp, level and message
457
+ * - Full: Shows all details with complete data
458
+ */
467
459
  var SimpleView = class {
468
-
469
-
470
- constructor(config) {
471
- this.config = config;
472
- this.termWidth = process.stdout.columns || 80;
473
- }
474
- updateTerminalWidth(width) {
475
- this.termWidth = width;
476
- }
477
- /**
478
- * Renders a single log entry based on the current view mode
479
- */
480
- renderLogLine(entry) {
481
- const levelColor = getLevelColor(entry.level, this.config.config.colors);
482
- const chevron = levelColor(`\u25B6 ${entry.level.toUpperCase()} `);
483
- const message = entry.message || "(no message)";
484
- const timestamp = formatTimestamp(entry.timestamp, this.config.config.logIdColor);
485
- switch (this.config.viewMode) {
486
- case "condensed": {
487
- const condensedLine = `${timestamp} ${chevron}${message}`;
488
- console.log(_wrapansi2.default.call(void 0, condensedLine, this.termWidth, { hard: true }));
489
- break;
490
- }
491
- case "full": {
492
- const logId = this.config.config.logIdColor(`[${entry.id}]`);
493
- const fullData = entry.data ? formatInlineData(
494
- JSON.parse(entry.data),
495
- this.config.config,
496
- this.config.maxInlineDepth,
497
- this.config.maxInlineLength,
498
- true
499
- ) : "";
500
- const expandedLine = `${timestamp} ${chevron}${logId} ${message}${fullData ? ` ${fullData}` : ""}`;
501
- console.log(_wrapansi2.default.call(void 0, expandedLine, this.termWidth, { hard: true }));
502
- break;
503
- }
504
- default: {
505
- const logId = this.config.config.logIdColor(`[${entry.id}]`);
506
- const normalData = entry.data ? formatInlineData(
507
- JSON.parse(entry.data),
508
- this.config.config,
509
- this.config.maxInlineDepth,
510
- this.config.maxInlineLength
511
- ) : "";
512
- const normalLine = `${timestamp} ${chevron}${logId} ${message}${normalData ? ` ${normalData}` : ""}`;
513
- console.log(_wrapansi2.default.call(void 0, normalLine, this.termWidth, { hard: true }));
514
- break;
515
- }
516
- }
517
- }
518
- render() {
519
- throw new Error("SimpleView.render() should not be called directly. Use renderLogLine() instead.");
520
- }
460
+ termWidth;
461
+ config;
462
+ constructor(config) {
463
+ this.config = config;
464
+ this.termWidth = process.stdout.columns || 80;
465
+ }
466
+ updateTerminalWidth(width) {
467
+ this.termWidth = width;
468
+ }
469
+ /**
470
+ * Renders a single log entry based on the current view mode
471
+ */
472
+ renderLogLine(entry) {
473
+ const chevron = getLevelColor(entry.level, this.config.config.colors)(`▶ ${entry.level.toUpperCase()} `);
474
+ const message = entry.message || "(no message)";
475
+ const timestamp = formatTimestamp(entry.timestamp, this.config.config.logIdColor);
476
+ switch (this.config.viewMode) {
477
+ case "condensed": {
478
+ const condensedLine = `${timestamp} ${chevron}${message}`;
479
+ console.log((0, wrap_ansi.default)(condensedLine, this.termWidth, { hard: true }));
480
+ break;
481
+ }
482
+ case "full": {
483
+ const logId = this.config.config.logIdColor(`[${entry.id}]`);
484
+ const fullData = entry.data ? formatInlineData(JSON.parse(entry.data), this.config.config, this.config.maxInlineDepth, this.config.maxInlineLength, true) : "";
485
+ const expandedLine = `${timestamp} ${chevron}${logId} ${message}${fullData ? ` ${fullData}` : ""}`;
486
+ console.log((0, wrap_ansi.default)(expandedLine, this.termWidth, { hard: true }));
487
+ break;
488
+ }
489
+ default: {
490
+ const logId = this.config.config.logIdColor(`[${entry.id}]`);
491
+ const normalData = entry.data ? formatInlineData(JSON.parse(entry.data), this.config.config, this.config.maxInlineDepth, this.config.maxInlineLength) : "";
492
+ const normalLine = `${timestamp} ${chevron}${logId} ${message}${normalData ? ` ${normalData}` : ""}`;
493
+ console.log((0, wrap_ansi.default)(normalLine, this.termWidth, { hard: true }));
494
+ break;
495
+ }
496
+ }
497
+ }
498
+ render() {
499
+ throw new Error("SimpleView.render() should not be called directly. Use renderLogLine() instead.");
500
+ }
521
501
  };
522
502
 
523
- // src/LogRenderer.ts
524
- var LogRenderer = (_class2 = class {
525
- /** Current terminal width in characters */
526
-
527
- /** Maximum depth for displaying nested objects inline */
528
-
529
- /** Maximum length for inline data before truncating */
530
-
531
- /** Whether arrays are currently collapsed in detail view */
532
- __init2() {this.isArraysCollapsed = true}
533
- /** Current view mode in simple mode */
534
- __init3() {this.viewMode = "full"}
535
- /** Color and formatting config for simple log view */
536
-
537
- /** Color and formatting config for detailed view */
538
-
539
- /** Whether we're showing raw JSON view */
540
- __init4() {this.isJsonView = false}
541
- /** Current scroll position in detailed view */
542
- __init5() {this.detailViewScrollPos = 0}
543
- /** View instances */
544
-
545
- __init6() {this.detailView = null}
546
- __init7() {this.selectionView = null}
547
- /**
548
- * Creates a new LogRenderer instance.
549
- *
550
- * @param simpleViewConfig - Configuration for simple log view
551
- * @param detailedViewConfig - Configuration for detailed view
552
- * @param maxInlineDepth - Maximum depth for inline object display
553
- * @param maxInlineLength - Maximum length before truncation
554
- */
555
- constructor(simpleViewConfig, detailedViewConfig, maxInlineDepth, maxInlineLength) {;_class2.prototype.__init2.call(this);_class2.prototype.__init3.call(this);_class2.prototype.__init4.call(this);_class2.prototype.__init5.call(this);_class2.prototype.__init6.call(this);_class2.prototype.__init7.call(this);
556
- this.simpleViewConfig = simpleViewConfig;
557
- this.detailedViewConfig = detailedViewConfig;
558
- this.maxInlineDepth = maxInlineDepth;
559
- this.maxInlineLength = maxInlineLength;
560
- this.termWidth = process.stdout.columns || 80;
561
- this.simpleView = new SimpleView({
562
- viewMode: this.viewMode,
563
- maxInlineDepth: this.maxInlineDepth,
564
- maxInlineLength: this.maxInlineLength,
565
- config: this.simpleViewConfig
566
- });
567
- this.detailView = null;
568
- this.selectionView = null;
569
- process.stdout.on("resize", () => {
570
- this.termWidth = process.stdout.columns || 80;
571
- this.simpleView.updateTerminalWidth(this.termWidth);
572
- if (this.detailView) {
573
- this.detailView.updateTerminalWidth(this.termWidth);
574
- }
575
- if (this.selectionView) {
576
- this.selectionView.updateTerminalWidth(this.termWidth);
577
- }
578
- });
579
- }
580
- /**
581
- * Renders a single log line in simple view format.
582
- * Format: [timestamp] LEVEL [id] message data
583
- * Condensed Format: [timestamp] LEVEL message
584
- * Expanded Format: [timestamp] LEVEL [id] message full_data
585
- *
586
- * @param entry - Log entry to render
587
- */
588
- renderLogLine(entry) {
589
- this.simpleView.renderLogLine(entry);
590
- }
591
- /**
592
- * Renders the detailed view of a log entry.
593
- * Shows full entry details with context and formatted data.
594
- *
595
- * @param entry - Log entry to show in detail
596
- * @param prevEntry - Previous entry for context
597
- * @param nextEntry - Next entry for context
598
- * @param scrollPos - Current scroll position
599
- * @param currentLogIndex - Current log index (optional)
600
- * @param totalLogs - Total logs count (optional)
601
- * @param filterText - Current filter text (if any)
602
- */
603
- renderDetailView(entry, prevEntry, nextEntry, scrollPos = 0, currentLogIndex, totalLogs, filterText = "") {
604
- const config = {
605
- entry,
606
- prevEntry,
607
- nextEntry,
608
- scrollPos,
609
- isArraysCollapsed: this.isArraysCollapsed,
610
- isJsonView: this.isJsonView,
611
- currentLogIndex: _nullishCoalesce(currentLogIndex, () => ( (prevEntry ? 2 : nextEntry ? 1 : 1))),
612
- // Use provided index or fallback
613
- totalLogs: _nullishCoalesce(totalLogs, () => ( 1)),
614
- // Use provided total or fallback
615
- filterText,
616
- config: this.detailedViewConfig
617
- };
618
- if (!this.detailView) {
619
- this.detailView = new DetailView(config);
620
- } else {
621
- this.detailView = new DetailView(config);
622
- }
623
- this.detailView.render();
624
- }
625
- /**
626
- * Updates the scroll position in detailed view
627
- * @param delta - Number of lines to scroll
628
- */
629
- scrollDetailView(delta) {
630
- if (!this.detailView) return;
631
- const maxScroll = this.detailView.getMaxScrollPosition();
632
- this.detailViewScrollPos = Math.max(0, Math.min(maxScroll, this.detailViewScrollPos + delta));
633
- }
634
- /**
635
- * Gets the current scroll position
636
- */
637
- getDetailViewScrollPos() {
638
- return this.detailViewScrollPos;
639
- }
640
- /**
641
- * Renders the selection view with a list of logs.
642
- * Shows filtered logs with selection highlight and data preview.
643
- *
644
- * @param logs - Array of logs to display
645
- * @param selectedIndex - Index of currently selected log
646
- * @param filterText - Current filter text (if any)
647
- * @param newLogCount - Number of new logs available
648
- */
649
- renderSelectionView(logs, selectedIndex, filterText, newLogCount) {
650
- const config = {
651
- logs,
652
- selectedIndex,
653
- filterText,
654
- newLogCount,
655
- config: this.detailedViewConfig
656
- };
657
- if (!this.selectionView) {
658
- this.selectionView = new SelectionView(config);
659
- } else {
660
- this.selectionView = new SelectionView(config);
661
- }
662
- this.selectionView.render();
663
- }
664
- /**
665
- * Toggles JSON view state
666
- */
667
- toggleJsonView() {
668
- this.isJsonView = !this.isJsonView;
669
- }
670
- /**
671
- * Gets current JSON view state
672
- */
673
- isInJsonView() {
674
- return this.isJsonView;
675
- }
676
- /**
677
- * Toggles array collapse state in detail view
678
- */
679
- toggleArrayCollapse() {
680
- this.isArraysCollapsed = !this.isArraysCollapsed;
681
- }
682
- /**
683
- * Cycles through view modes: full -> truncated -> condensed
684
- */
685
- cycleViewMode() {
686
- switch (this.viewMode) {
687
- case "full":
688
- this.viewMode = "truncated";
689
- break;
690
- case "truncated":
691
- this.viewMode = "condensed";
692
- break;
693
- case "condensed":
694
- this.viewMode = "full";
695
- break;
696
- }
697
- this.simpleView = new SimpleView({
698
- viewMode: this.viewMode,
699
- maxInlineDepth: this.maxInlineDepth,
700
- maxInlineLength: this.maxInlineLength,
701
- config: this.simpleViewConfig
702
- });
703
- return this.viewMode;
704
- }
705
- /**
706
- * Gets current view mode
707
- */
708
- getViewMode() {
709
- return this.viewMode;
710
- }
711
- }, _class2);
503
+ //#endregion
504
+ //#region src/LogRenderer.ts
505
+ /**
506
+ * LogRenderer coordinates between different view modes and manages the overall rendering state.
507
+ * Delegates actual rendering to specialized view implementations:
508
+ * - SimpleView: For real-time log output
509
+ * - SelectionView: For interactive log browsing
510
+ * - DetailView: For in-depth log inspection
511
+ */
512
+ var LogRenderer = class {
513
+ /** Current terminal width in characters */
514
+ termWidth;
515
+ /** Maximum depth for displaying nested objects inline */
516
+ maxInlineDepth;
517
+ /** Maximum length for inline data before truncating */
518
+ maxInlineLength;
519
+ /** Whether arrays are currently collapsed in detail view */
520
+ isArraysCollapsed = true;
521
+ /** Current view mode in simple mode */
522
+ viewMode = "full";
523
+ /** Color and formatting config for simple log view */
524
+ simpleViewConfig;
525
+ /** Color and formatting config for detailed view */
526
+ detailedViewConfig;
527
+ /** Whether we're showing raw JSON view */
528
+ isJsonView = false;
529
+ /** Current scroll position in detailed view */
530
+ detailViewScrollPos = 0;
531
+ /** View instances */
532
+ simpleView;
533
+ detailView = null;
534
+ selectionView = null;
535
+ /**
536
+ * Creates a new LogRenderer instance.
537
+ *
538
+ * @param simpleViewConfig - Configuration for simple log view
539
+ * @param detailedViewConfig - Configuration for detailed view
540
+ * @param maxInlineDepth - Maximum depth for inline object display
541
+ * @param maxInlineLength - Maximum length before truncation
542
+ */
543
+ constructor(simpleViewConfig, detailedViewConfig, maxInlineDepth, maxInlineLength) {
544
+ this.simpleViewConfig = simpleViewConfig;
545
+ this.detailedViewConfig = detailedViewConfig;
546
+ this.maxInlineDepth = maxInlineDepth;
547
+ this.maxInlineLength = maxInlineLength;
548
+ this.termWidth = process.stdout.columns || 80;
549
+ this.simpleView = new SimpleView({
550
+ viewMode: this.viewMode,
551
+ maxInlineDepth: this.maxInlineDepth,
552
+ maxInlineLength: this.maxInlineLength,
553
+ config: this.simpleViewConfig
554
+ });
555
+ this.detailView = null;
556
+ this.selectionView = null;
557
+ process.stdout.on("resize", () => {
558
+ this.termWidth = process.stdout.columns || 80;
559
+ this.simpleView.updateTerminalWidth(this.termWidth);
560
+ if (this.detailView) this.detailView.updateTerminalWidth(this.termWidth);
561
+ if (this.selectionView) this.selectionView.updateTerminalWidth(this.termWidth);
562
+ });
563
+ }
564
+ /**
565
+ * Renders a single log line in simple view format.
566
+ * Format: [timestamp] LEVEL [id] message data
567
+ * Condensed Format: [timestamp] LEVEL message
568
+ * Expanded Format: [timestamp] LEVEL [id] message full_data
569
+ *
570
+ * @param entry - Log entry to render
571
+ */
572
+ renderLogLine(entry) {
573
+ this.simpleView.renderLogLine(entry);
574
+ }
575
+ /**
576
+ * Renders the detailed view of a log entry.
577
+ * Shows full entry details with context and formatted data.
578
+ *
579
+ * @param entry - Log entry to show in detail
580
+ * @param prevEntry - Previous entry for context
581
+ * @param nextEntry - Next entry for context
582
+ * @param scrollPos - Current scroll position
583
+ * @param currentLogIndex - Current log index (optional)
584
+ * @param totalLogs - Total logs count (optional)
585
+ * @param filterText - Current filter text (if any)
586
+ */
587
+ renderDetailView(entry, prevEntry, nextEntry, scrollPos = 0, currentLogIndex, totalLogs, filterText = "") {
588
+ const config = {
589
+ entry,
590
+ prevEntry,
591
+ nextEntry,
592
+ scrollPos,
593
+ isArraysCollapsed: this.isArraysCollapsed,
594
+ isJsonView: this.isJsonView,
595
+ currentLogIndex: currentLogIndex ?? (prevEntry ? 2 : nextEntry ? 1 : 1),
596
+ totalLogs: totalLogs ?? 1,
597
+ filterText,
598
+ config: this.detailedViewConfig
599
+ };
600
+ if (!this.detailView) this.detailView = new DetailView(config);
601
+ else this.detailView = new DetailView(config);
602
+ this.detailView.render();
603
+ }
604
+ /**
605
+ * Updates the scroll position in detailed view
606
+ * @param delta - Number of lines to scroll
607
+ */
608
+ scrollDetailView(delta) {
609
+ if (!this.detailView) return;
610
+ const maxScroll = this.detailView.getMaxScrollPosition();
611
+ this.detailViewScrollPos = Math.max(0, Math.min(maxScroll, this.detailViewScrollPos + delta));
612
+ }
613
+ /**
614
+ * Gets the current scroll position
615
+ */
616
+ getDetailViewScrollPos() {
617
+ return this.detailViewScrollPos;
618
+ }
619
+ /**
620
+ * Renders the selection view with a list of logs.
621
+ * Shows filtered logs with selection highlight and data preview.
622
+ *
623
+ * @param logs - Array of logs to display
624
+ * @param selectedIndex - Index of currently selected log
625
+ * @param filterText - Current filter text (if any)
626
+ * @param newLogCount - Number of new logs available
627
+ */
628
+ renderSelectionView(logs, selectedIndex, filterText, newLogCount) {
629
+ const config = {
630
+ logs,
631
+ selectedIndex,
632
+ filterText,
633
+ newLogCount,
634
+ config: this.detailedViewConfig
635
+ };
636
+ if (!this.selectionView) this.selectionView = new SelectionView(config);
637
+ else this.selectionView = new SelectionView(config);
638
+ this.selectionView.render();
639
+ }
640
+ /**
641
+ * Toggles JSON view state
642
+ */
643
+ toggleJsonView() {
644
+ this.isJsonView = !this.isJsonView;
645
+ }
646
+ /**
647
+ * Gets current JSON view state
648
+ */
649
+ isInJsonView() {
650
+ return this.isJsonView;
651
+ }
652
+ /**
653
+ * Toggles array collapse state in detail view
654
+ */
655
+ toggleArrayCollapse() {
656
+ this.isArraysCollapsed = !this.isArraysCollapsed;
657
+ }
658
+ /**
659
+ * Cycles through view modes: full -> truncated -> condensed
660
+ */
661
+ cycleViewMode() {
662
+ switch (this.viewMode) {
663
+ case "full":
664
+ this.viewMode = "truncated";
665
+ break;
666
+ case "truncated":
667
+ this.viewMode = "condensed";
668
+ break;
669
+ case "condensed":
670
+ this.viewMode = "full";
671
+ break;
672
+ }
673
+ this.simpleView = new SimpleView({
674
+ viewMode: this.viewMode,
675
+ maxInlineDepth: this.maxInlineDepth,
676
+ maxInlineLength: this.maxInlineLength,
677
+ config: this.simpleViewConfig
678
+ });
679
+ return this.viewMode;
680
+ }
681
+ /**
682
+ * Gets current view mode
683
+ */
684
+ getViewMode() {
685
+ return this.viewMode;
686
+ }
687
+ };
712
688
 
713
- // src/LogStorage.ts
714
- var _path = require('path');
715
- var _bettersqlite3 = require('better-sqlite3'); var _bettersqlite32 = _interopRequireDefault(_bettersqlite3);
689
+ //#endregion
690
+ //#region src/LogStorage.ts
691
+ /**
692
+ * Handles storage and retrieval of log entries using SQLite.
693
+ * Uses an in-memory database for optimal performance and automatic cleanup.
694
+ *
695
+ * The database schema includes:
696
+ * - id: Unique identifier for each log
697
+ * - timestamp: Unix timestamp in milliseconds
698
+ * - level: Log level (trace, debug, info, etc.)
699
+ * - message: Main log message
700
+ * - data: Optional structured data as JSON string
701
+ */
716
702
  var LogStorage = class {
717
- /** SQLite database instance */
718
-
719
- /**
720
- * Creates a new LogStorage instance.
721
- * Initializes a SQLite database and creates the logs table.
722
- *
723
- * @param logFile - Optional path to SQLite file for persistent storage.
724
- * If not provided, uses in-memory database.
725
- * Relative paths are resolved from the current working directory.
726
- */
727
- constructor(logFile) {
728
- const dbPath = logFile ? logFile.startsWith("/") ? logFile : _path.resolve.call(void 0, process.cwd(), logFile) : ":memory:";
729
- this.db = new (0, _bettersqlite32.default)(dbPath);
730
- this.initializeDatabase();
731
- }
732
- /**
733
- * Initializes the database schema.
734
- * Creates the logs table with appropriate columns and indexes.
735
- * If the table already exists, it will be dropped to ensure a clean state.
736
- * @private
737
- */
738
- initializeDatabase() {
739
- this.db.exec(`
703
+ /** SQLite database instance */
704
+ db;
705
+ /**
706
+ * Creates a new LogStorage instance.
707
+ * Initializes a SQLite database and creates the logs table.
708
+ *
709
+ * @param logFile - Optional path to SQLite file for persistent storage.
710
+ * If not provided, uses in-memory database.
711
+ * Relative paths are resolved from the current working directory.
712
+ */
713
+ constructor(logFile) {
714
+ this.db = new better_sqlite3.default(logFile ? logFile.startsWith("/") ? logFile : (0, node_path.resolve)(process.cwd(), logFile) : ":memory:");
715
+ this.initializeDatabase();
716
+ }
717
+ /**
718
+ * Initializes the database schema.
719
+ * Creates the logs table with appropriate columns and indexes.
720
+ * If the table already exists, it will be dropped to ensure a clean state.
721
+ * @private
722
+ */
723
+ initializeDatabase() {
724
+ this.db.exec(`
740
725
  DROP TABLE IF EXISTS logs;
741
726
  CREATE TABLE logs (
742
727
  id TEXT PRIMARY KEY,
@@ -746,1086 +731,950 @@ var LogStorage = class {
746
731
  data TEXT
747
732
  )
748
733
  `);
749
- }
750
- /**
751
- * Stores a new log entry in the database.
752
- * Uses prepared statements for efficient and safe insertion.
753
- *
754
- * @param entry - The log entry to store
755
- * @example
756
- * storage.store({
757
- * id: "abc123",
758
- * timestamp: Date.now(),
759
- * level: "info",
760
- * message: "User logged in",
761
- * data: JSON.stringify({ userId: 123 })
762
- * });
763
- */
764
- store(entry) {
765
- this.db.prepare(`
734
+ }
735
+ /**
736
+ * Stores a new log entry in the database.
737
+ * Uses prepared statements for efficient and safe insertion.
738
+ *
739
+ * @param entry - The log entry to store
740
+ * @example
741
+ * storage.store({
742
+ * id: "abc123",
743
+ * timestamp: Date.now(),
744
+ * level: "info",
745
+ * message: "User logged in",
746
+ * data: JSON.stringify({ userId: 123 })
747
+ * });
748
+ */
749
+ store(entry) {
750
+ this.db.prepare(`
766
751
  INSERT INTO logs (id, timestamp, level, message, data)
767
752
  VALUES (?, ?, ?, ?, ?)
768
753
  `).run(entry.id, entry.timestamp, entry.level, entry.message, entry.data);
769
- }
770
- /**
771
- * Retrieves all logs from the database in chronological order.
772
- * Used when displaying the full log history or clearing filters.
773
- *
774
- * @returns Array of log entries sorted by timestamp
775
- */
776
- getAllLogs() {
777
- return this.db.prepare("SELECT * FROM logs ORDER BY timestamp ASC").all();
778
- }
779
- /**
780
- * Searches logs based on a text query.
781
- * Performs a case-insensitive search across multiple fields:
782
- * - Log ID
783
- * - Message content
784
- * - Structured data
785
- *
786
- * @param searchText - Text to search for
787
- * @returns Array of matching log entries sorted by timestamp
788
- * @example
789
- * const errorLogs = storage.searchLogs("error");
790
- * const userLogs = storage.searchLogs("userId:123");
791
- */
792
- searchLogs(searchText) {
793
- const query = `
754
+ }
755
+ /**
756
+ * Retrieves all logs from the database in chronological order.
757
+ * Used when displaying the full log history or clearing filters.
758
+ *
759
+ * @returns Array of log entries sorted by timestamp
760
+ */
761
+ getAllLogs() {
762
+ return this.db.prepare("SELECT * FROM logs ORDER BY timestamp ASC").all();
763
+ }
764
+ /**
765
+ * Searches logs based on a text query.
766
+ * Performs a case-insensitive search across multiple fields:
767
+ * - Log ID
768
+ * - Message content
769
+ * - Structured data
770
+ *
771
+ * @param searchText - Text to search for
772
+ * @returns Array of matching log entries sorted by timestamp
773
+ * @example
774
+ * const errorLogs = storage.searchLogs("error");
775
+ * const userLogs = storage.searchLogs("userId:123");
776
+ */
777
+ searchLogs(searchText) {
778
+ const query = `
794
779
  SELECT * FROM logs
795
780
  WHERE id LIKE ?
796
781
  OR message LIKE ?
797
782
  OR data LIKE ?
798
783
  ORDER BY timestamp ASC
799
784
  `;
800
- const pattern = `%${searchText}%`;
801
- return this.db.prepare(query).all(pattern, pattern, pattern);
802
- }
803
- /**
804
- * Gets the total number of logs in the database.
805
- * Uses an efficient COUNT query instead of loading all logs.
806
- *
807
- * @returns Total number of log entries
808
- */
809
- getLogCount() {
810
- const result = this.db.prepare("SELECT COUNT(*) as count FROM logs").get();
811
- return result.count;
812
- }
813
- /**
814
- * Gets the total number of logs matching a search query.
815
- * Uses an efficient COUNT query instead of loading all logs.
816
- *
817
- * @param searchText - Text to search for
818
- * @returns Number of matching log entries
819
- */
820
- getFilteredLogCount(searchText) {
821
- const query = `
785
+ const pattern = `%${searchText}%`;
786
+ return this.db.prepare(query).all(pattern, pattern, pattern);
787
+ }
788
+ /**
789
+ * Gets the total number of logs in the database.
790
+ * Uses an efficient COUNT query instead of loading all logs.
791
+ *
792
+ * @returns Total number of log entries
793
+ */
794
+ getLogCount() {
795
+ return this.db.prepare("SELECT COUNT(*) as count FROM logs").get().count;
796
+ }
797
+ /**
798
+ * Gets the total number of logs matching a search query.
799
+ * Uses an efficient COUNT query instead of loading all logs.
800
+ *
801
+ * @param searchText - Text to search for
802
+ * @returns Number of matching log entries
803
+ */
804
+ getFilteredLogCount(searchText) {
805
+ const query = `
822
806
  SELECT COUNT(*) as count FROM logs
823
807
  WHERE id LIKE ?
824
808
  OR message LIKE ?
825
809
  OR data LIKE ?
826
810
  `;
827
- const pattern = `%${searchText}%`;
828
- const result = this.db.prepare(query).get(pattern, pattern, pattern);
829
- return result.count;
830
- }
831
- /**
832
- * Closes the database connection and performs cleanup.
833
- * Should be called when the application exits or the transport is destroyed.
834
- */
835
- close() {
836
- this.db.close();
837
- }
811
+ const pattern = `%${searchText}%`;
812
+ return this.db.prepare(query).get(pattern, pattern, pattern).count;
813
+ }
814
+ /**
815
+ * Closes the database connection and performs cleanup.
816
+ * Should be called when the application exits or the transport is destroyed.
817
+ */
818
+ close() {
819
+ this.db.close();
820
+ }
838
821
  };
839
822
 
840
- // src/themes.ts
841
-
842
- var moonlight = {
843
- simpleView: {
844
- colors: {
845
- trace: chalk8.default.rgb(114, 135, 153),
846
- // Muted blue-grey for less important info
847
- debug: chalk8.default.rgb(130, 170, 255),
848
- // Soft blue that pops but doesn't strain
849
- info: chalk8.default.rgb(195, 232, 141),
850
- // Sage green for good readability
851
- warn: chalk8.default.rgb(255, 203, 107),
852
- // Warm yellow, less harsh than pure yellow
853
- error: chalk8.default.rgb(247, 118, 142),
854
- // Soft red that stands out without being aggressive
855
- fatal: chalk8.default.bgRgb(247, 118, 142).white
856
- // Inverted soft red for maximum visibility
857
- },
858
- logIdColor: chalk8.default.rgb(84, 98, 117),
859
- // Darker blue-grey for secondary information
860
- dataValueColor: chalk8.default.rgb(209, 219, 231),
861
- // Light grey-blue for primary content
862
- dataKeyColor: chalk8.default.rgb(130, 170, 255),
863
- // Matching debug blue for consistency
864
- selectorColor: chalk8.default.rgb(137, 221, 255)
865
- // Ice blue for selection indicators
866
- },
867
- detailedView: {
868
- colors: {
869
- trace: chalk8.default.rgb(114, 135, 153),
870
- debug: chalk8.default.rgb(130, 170, 255),
871
- info: chalk8.default.rgb(195, 232, 141),
872
- warn: chalk8.default.rgb(255, 203, 107),
873
- error: chalk8.default.rgb(247, 118, 142),
874
- fatal: chalk8.default.bgRgb(247, 118, 142).white
875
- },
876
- logIdColor: chalk8.default.rgb(84, 98, 117),
877
- dataValueColor: chalk8.default.rgb(209, 219, 231),
878
- dataKeyColor: chalk8.default.rgb(130, 170, 255),
879
- selectorColor: chalk8.default.rgb(137, 221, 255),
880
- // Ice blue for selection indicators
881
- headerColor: chalk8.default.rgb(137, 221, 255),
882
- labelColor: chalk8.default.rgb(137, 221, 255).bold,
883
- separatorColor: chalk8.default.rgb(84, 98, 117),
884
- jsonColors: {
885
- keysColor: chalk8.default.rgb(130, 170, 255),
886
- dashColor: chalk8.default.rgb(209, 219, 231),
887
- numberColor: chalk8.default.rgb(247, 140, 108),
888
- stringColor: chalk8.default.rgb(195, 232, 141),
889
- multilineStringColor: chalk8.default.rgb(195, 232, 141),
890
- positiveNumberColor: chalk8.default.rgb(195, 232, 141),
891
- negativeNumberColor: chalk8.default.rgb(247, 118, 142),
892
- booleanColor: chalk8.default.rgb(255, 203, 107),
893
- nullUndefinedColor: chalk8.default.rgb(114, 135, 153),
894
- dateColor: chalk8.default.rgb(199, 146, 234)
895
- }
896
- }
823
+ //#endregion
824
+ //#region src/themes.ts
825
+ /**
826
+ * Moonlight - A dark theme with cool blue tones
827
+ * Inspired by moonlit nights and modern IDEs
828
+ *
829
+ * Color Palette:
830
+ * - Primary: Cool blues and soft greens
831
+ * - Accents: Warm yellows and soft reds
832
+ * - Background: Assumes dark terminal (black or very dark grey)
833
+ *
834
+ * Best used with:
835
+ * - Dark terminal themes
836
+ * - Night-time coding sessions
837
+ * - Environments where eye strain is a concern
838
+ */
839
+ const moonlight = {
840
+ simpleView: {
841
+ colors: {
842
+ trace: chalk.default.rgb(114, 135, 153),
843
+ debug: chalk.default.rgb(130, 170, 255),
844
+ info: chalk.default.rgb(195, 232, 141),
845
+ warn: chalk.default.rgb(255, 203, 107),
846
+ error: chalk.default.rgb(247, 118, 142),
847
+ fatal: chalk.default.bgRgb(247, 118, 142).white
848
+ },
849
+ logIdColor: chalk.default.rgb(84, 98, 117),
850
+ dataValueColor: chalk.default.rgb(209, 219, 231),
851
+ dataKeyColor: chalk.default.rgb(130, 170, 255),
852
+ selectorColor: chalk.default.rgb(137, 221, 255)
853
+ },
854
+ detailedView: {
855
+ colors: {
856
+ trace: chalk.default.rgb(114, 135, 153),
857
+ debug: chalk.default.rgb(130, 170, 255),
858
+ info: chalk.default.rgb(195, 232, 141),
859
+ warn: chalk.default.rgb(255, 203, 107),
860
+ error: chalk.default.rgb(247, 118, 142),
861
+ fatal: chalk.default.bgRgb(247, 118, 142).white
862
+ },
863
+ logIdColor: chalk.default.rgb(84, 98, 117),
864
+ dataValueColor: chalk.default.rgb(209, 219, 231),
865
+ dataKeyColor: chalk.default.rgb(130, 170, 255),
866
+ selectorColor: chalk.default.rgb(137, 221, 255),
867
+ headerColor: chalk.default.rgb(137, 221, 255),
868
+ labelColor: chalk.default.rgb(137, 221, 255).bold,
869
+ separatorColor: chalk.default.rgb(84, 98, 117),
870
+ jsonColors: {
871
+ keysColor: chalk.default.rgb(130, 170, 255),
872
+ dashColor: chalk.default.rgb(209, 219, 231),
873
+ numberColor: chalk.default.rgb(247, 140, 108),
874
+ stringColor: chalk.default.rgb(195, 232, 141),
875
+ multilineStringColor: chalk.default.rgb(195, 232, 141),
876
+ positiveNumberColor: chalk.default.rgb(195, 232, 141),
877
+ negativeNumberColor: chalk.default.rgb(247, 118, 142),
878
+ booleanColor: chalk.default.rgb(255, 203, 107),
879
+ nullUndefinedColor: chalk.default.rgb(114, 135, 153),
880
+ dateColor: chalk.default.rgb(199, 146, 234)
881
+ }
882
+ }
897
883
  };
898
- var sunlight = {
899
- simpleView: {
900
- colors: {
901
- trace: chalk8.default.rgb(110, 110, 110),
902
- // Dark grey for subtle information
903
- debug: chalk8.default.rgb(32, 96, 159),
904
- // Deep blue for strong contrast on white
905
- info: chalk8.default.rgb(35, 134, 54),
906
- // Forest green, easier on the eyes than bright green
907
- warn: chalk8.default.rgb(176, 95, 0),
908
- // Brown-orange for natural warning color
909
- error: chalk8.default.rgb(191, 0, 0),
910
- // Deep red for clear visibility on light backgrounds
911
- fatal: chalk8.default.bgRgb(191, 0, 0).white
912
- // White on deep red for critical issues
913
- },
914
- logIdColor: chalk8.default.rgb(110, 110, 110),
915
- dataValueColor: chalk8.default.rgb(0, 0, 0),
916
- dataKeyColor: chalk8.default.rgb(32, 96, 159),
917
- selectorColor: chalk8.default.rgb(0, 91, 129)
918
- // Deep blue for strong contrast
919
- },
920
- detailedView: {
921
- colors: {
922
- trace: chalk8.default.rgb(110, 110, 110),
923
- debug: chalk8.default.rgb(32, 96, 159),
924
- info: chalk8.default.rgb(35, 134, 54),
925
- warn: chalk8.default.rgb(176, 95, 0),
926
- error: chalk8.default.rgb(191, 0, 0),
927
- fatal: chalk8.default.bgRgb(191, 0, 0).white
928
- },
929
- logIdColor: chalk8.default.rgb(110, 110, 110),
930
- dataValueColor: chalk8.default.rgb(0, 0, 0),
931
- dataKeyColor: chalk8.default.rgb(32, 96, 159),
932
- selectorColor: chalk8.default.rgb(0, 91, 129),
933
- // Deep blue for strong contrast
934
- headerColor: chalk8.default.rgb(0, 91, 129),
935
- labelColor: chalk8.default.rgb(0, 91, 129).bold,
936
- separatorColor: chalk8.default.rgb(110, 110, 110),
937
- jsonColors: {
938
- keysColor: chalk8.default.rgb(32, 96, 159),
939
- dashColor: chalk8.default.rgb(0, 0, 0),
940
- numberColor: chalk8.default.rgb(170, 55, 49),
941
- stringColor: chalk8.default.rgb(35, 134, 54),
942
- multilineStringColor: chalk8.default.rgb(35, 134, 54),
943
- positiveNumberColor: chalk8.default.rgb(46, 125, 50),
944
- negativeNumberColor: chalk8.default.rgb(183, 28, 28),
945
- booleanColor: chalk8.default.rgb(176, 95, 0),
946
- nullUndefinedColor: chalk8.default.rgb(110, 110, 110),
947
- dateColor: chalk8.default.rgb(123, 31, 162)
948
- }
949
- }
884
+ /**
885
+ * Sunlight - A light theme with warm tones
886
+ * Inspired by daylight reading and paper documentation
887
+ *
888
+ * Color Palette:
889
+ * - Primary: Deep, rich colors that contrast well with white
890
+ * - Accents: Earth tones and deep jewel tones
891
+ * - Background: Assumes light terminal (white or very light grey)
892
+ *
893
+ * Best used with:
894
+ * - Light terminal themes
895
+ * - Daytime coding sessions
896
+ * - High-glare environments
897
+ * - Printed documentation
898
+ */
899
+ const sunlight = {
900
+ simpleView: {
901
+ colors: {
902
+ trace: chalk.default.rgb(110, 110, 110),
903
+ debug: chalk.default.rgb(32, 96, 159),
904
+ info: chalk.default.rgb(35, 134, 54),
905
+ warn: chalk.default.rgb(176, 95, 0),
906
+ error: chalk.default.rgb(191, 0, 0),
907
+ fatal: chalk.default.bgRgb(191, 0, 0).white
908
+ },
909
+ logIdColor: chalk.default.rgb(110, 110, 110),
910
+ dataValueColor: chalk.default.rgb(0, 0, 0),
911
+ dataKeyColor: chalk.default.rgb(32, 96, 159),
912
+ selectorColor: chalk.default.rgb(0, 91, 129)
913
+ },
914
+ detailedView: {
915
+ colors: {
916
+ trace: chalk.default.rgb(110, 110, 110),
917
+ debug: chalk.default.rgb(32, 96, 159),
918
+ info: chalk.default.rgb(35, 134, 54),
919
+ warn: chalk.default.rgb(176, 95, 0),
920
+ error: chalk.default.rgb(191, 0, 0),
921
+ fatal: chalk.default.bgRgb(191, 0, 0).white
922
+ },
923
+ logIdColor: chalk.default.rgb(110, 110, 110),
924
+ dataValueColor: chalk.default.rgb(0, 0, 0),
925
+ dataKeyColor: chalk.default.rgb(32, 96, 159),
926
+ selectorColor: chalk.default.rgb(0, 91, 129),
927
+ headerColor: chalk.default.rgb(0, 91, 129),
928
+ labelColor: chalk.default.rgb(0, 91, 129).bold,
929
+ separatorColor: chalk.default.rgb(110, 110, 110),
930
+ jsonColors: {
931
+ keysColor: chalk.default.rgb(32, 96, 159),
932
+ dashColor: chalk.default.rgb(0, 0, 0),
933
+ numberColor: chalk.default.rgb(170, 55, 49),
934
+ stringColor: chalk.default.rgb(35, 134, 54),
935
+ multilineStringColor: chalk.default.rgb(35, 134, 54),
936
+ positiveNumberColor: chalk.default.rgb(46, 125, 50),
937
+ negativeNumberColor: chalk.default.rgb(183, 28, 28),
938
+ booleanColor: chalk.default.rgb(176, 95, 0),
939
+ nullUndefinedColor: chalk.default.rgb(110, 110, 110),
940
+ dateColor: chalk.default.rgb(123, 31, 162)
941
+ }
942
+ }
950
943
  };
951
- var neon = {
952
- simpleView: {
953
- colors: {
954
- trace: chalk8.default.rgb(108, 108, 255),
955
- // Electric blue
956
- debug: chalk8.default.rgb(255, 82, 246),
957
- // Hot pink
958
- info: chalk8.default.rgb(0, 255, 163),
959
- // Cyber green
960
- warn: chalk8.default.rgb(255, 231, 46),
961
- // Electric yellow
962
- error: chalk8.default.rgb(255, 53, 91),
963
- // Neon red
964
- fatal: chalk8.default.bgRgb(255, 53, 91).rgb(0, 255, 163)
965
- // Neon red bg with cyber green text
966
- },
967
- logIdColor: chalk8.default.rgb(187, 134, 252),
968
- // Bright purple
969
- dataValueColor: chalk8.default.rgb(255, 255, 255),
970
- // Pure white
971
- dataKeyColor: chalk8.default.rgb(0, 255, 240),
972
- // Cyan
973
- selectorColor: chalk8.default.rgb(0, 255, 240)
974
- // Electric cyan for cyberpunk feel
975
- },
976
- detailedView: {
977
- colors: {
978
- trace: chalk8.default.rgb(108, 108, 255),
979
- debug: chalk8.default.rgb(255, 82, 246),
980
- info: chalk8.default.rgb(0, 255, 163),
981
- warn: chalk8.default.rgb(255, 231, 46),
982
- error: chalk8.default.rgb(255, 53, 91),
983
- fatal: chalk8.default.bgRgb(255, 53, 91).rgb(0, 255, 163)
984
- },
985
- logIdColor: chalk8.default.rgb(187, 134, 252),
986
- dataValueColor: chalk8.default.rgb(255, 255, 255),
987
- dataKeyColor: chalk8.default.rgb(0, 255, 240),
988
- selectorColor: chalk8.default.rgb(0, 255, 240),
989
- // Electric cyan for cyberpunk feel
990
- headerColor: chalk8.default.rgb(255, 82, 246),
991
- labelColor: chalk8.default.rgb(255, 82, 246).bold,
992
- separatorColor: chalk8.default.rgb(108, 108, 255),
993
- jsonColors: {
994
- keysColor: chalk8.default.rgb(0, 255, 240),
995
- dashColor: chalk8.default.rgb(255, 255, 255),
996
- numberColor: chalk8.default.rgb(255, 82, 246),
997
- stringColor: chalk8.default.rgb(0, 255, 163),
998
- multilineStringColor: chalk8.default.rgb(0, 255, 163),
999
- positiveNumberColor: chalk8.default.rgb(0, 255, 163),
1000
- negativeNumberColor: chalk8.default.rgb(255, 53, 91),
1001
- booleanColor: chalk8.default.rgb(255, 231, 46),
1002
- nullUndefinedColor: chalk8.default.rgb(108, 108, 255),
1003
- dateColor: chalk8.default.rgb(187, 134, 252)
1004
- }
1005
- }
944
+ /**
945
+ * Neon - A dark theme with vibrant cyberpunk colors
946
+ * Inspired by neon-lit cityscapes and retro-futuristic aesthetics
947
+ *
948
+ * Color Palette:
949
+ * - Primary: Electric blues and hot pinks
950
+ * - Accents: Bright purples and cyber greens
951
+ * - Background: Assumes dark terminal (black or very dark grey)
952
+ *
953
+ * Best used with:
954
+ * - Dark terminal themes
955
+ * - High-contrast preferences
956
+ * - Modern, tech-focused applications
957
+ */
958
+ const neon = {
959
+ simpleView: {
960
+ colors: {
961
+ trace: chalk.default.rgb(108, 108, 255),
962
+ debug: chalk.default.rgb(255, 82, 246),
963
+ info: chalk.default.rgb(0, 255, 163),
964
+ warn: chalk.default.rgb(255, 231, 46),
965
+ error: chalk.default.rgb(255, 53, 91),
966
+ fatal: chalk.default.bgRgb(255, 53, 91).rgb(0, 255, 163)
967
+ },
968
+ logIdColor: chalk.default.rgb(187, 134, 252),
969
+ dataValueColor: chalk.default.rgb(255, 255, 255),
970
+ dataKeyColor: chalk.default.rgb(0, 255, 240),
971
+ selectorColor: chalk.default.rgb(0, 255, 240)
972
+ },
973
+ detailedView: {
974
+ colors: {
975
+ trace: chalk.default.rgb(108, 108, 255),
976
+ debug: chalk.default.rgb(255, 82, 246),
977
+ info: chalk.default.rgb(0, 255, 163),
978
+ warn: chalk.default.rgb(255, 231, 46),
979
+ error: chalk.default.rgb(255, 53, 91),
980
+ fatal: chalk.default.bgRgb(255, 53, 91).rgb(0, 255, 163)
981
+ },
982
+ logIdColor: chalk.default.rgb(187, 134, 252),
983
+ dataValueColor: chalk.default.rgb(255, 255, 255),
984
+ dataKeyColor: chalk.default.rgb(0, 255, 240),
985
+ selectorColor: chalk.default.rgb(0, 255, 240),
986
+ headerColor: chalk.default.rgb(255, 82, 246),
987
+ labelColor: chalk.default.rgb(255, 82, 246).bold,
988
+ separatorColor: chalk.default.rgb(108, 108, 255),
989
+ jsonColors: {
990
+ keysColor: chalk.default.rgb(0, 255, 240),
991
+ dashColor: chalk.default.rgb(255, 255, 255),
992
+ numberColor: chalk.default.rgb(255, 82, 246),
993
+ stringColor: chalk.default.rgb(0, 255, 163),
994
+ multilineStringColor: chalk.default.rgb(0, 255, 163),
995
+ positiveNumberColor: chalk.default.rgb(0, 255, 163),
996
+ negativeNumberColor: chalk.default.rgb(255, 53, 91),
997
+ booleanColor: chalk.default.rgb(255, 231, 46),
998
+ nullUndefinedColor: chalk.default.rgb(108, 108, 255),
999
+ dateColor: chalk.default.rgb(187, 134, 252)
1000
+ }
1001
+ }
1006
1002
  };
1007
- var nature = {
1008
- simpleView: {
1009
- colors: {
1010
- trace: chalk8.default.rgb(121, 85, 72),
1011
- // Wooden brown
1012
- debug: chalk8.default.rgb(46, 125, 50),
1013
- // Forest green
1014
- info: chalk8.default.rgb(0, 105, 92),
1015
- // Deep teal
1016
- warn: chalk8.default.rgb(175, 115, 0),
1017
- // Golden amber
1018
- error: chalk8.default.rgb(183, 28, 28),
1019
- // Autumn red
1020
- fatal: chalk8.default.bgRgb(183, 28, 28).rgb(255, 250, 240)
1021
- // Red bg with soft white
1022
- },
1023
- logIdColor: chalk8.default.rgb(93, 64, 55),
1024
- // Deep bark brown
1025
- dataValueColor: chalk8.default.rgb(27, 27, 27),
1026
- // Near black
1027
- dataKeyColor: chalk8.default.rgb(56, 142, 60),
1028
- // Leaf green
1029
- selectorColor: chalk8.default.rgb(0, 105, 92)
1030
- // Deep teal for natural feel
1031
- },
1032
- detailedView: {
1033
- colors: {
1034
- trace: chalk8.default.rgb(121, 85, 72),
1035
- debug: chalk8.default.rgb(46, 125, 50),
1036
- info: chalk8.default.rgb(0, 105, 92),
1037
- warn: chalk8.default.rgb(175, 115, 0),
1038
- error: chalk8.default.rgb(183, 28, 28),
1039
- fatal: chalk8.default.bgRgb(183, 28, 28).rgb(255, 250, 240)
1040
- },
1041
- logIdColor: chalk8.default.rgb(93, 64, 55),
1042
- dataValueColor: chalk8.default.rgb(27, 27, 27),
1043
- dataKeyColor: chalk8.default.rgb(56, 142, 60),
1044
- selectorColor: chalk8.default.rgb(0, 105, 92),
1045
- // Deep teal for natural feel
1046
- headerColor: chalk8.default.rgb(0, 77, 64),
1047
- labelColor: chalk8.default.rgb(0, 77, 64).bold,
1048
- separatorColor: chalk8.default.rgb(121, 85, 72),
1049
- jsonColors: {
1050
- keysColor: chalk8.default.rgb(56, 142, 60),
1051
- dashColor: chalk8.default.rgb(27, 27, 27),
1052
- numberColor: chalk8.default.rgb(230, 81, 0),
1053
- stringColor: chalk8.default.rgb(0, 105, 92),
1054
- multilineStringColor: chalk8.default.rgb(0, 105, 92),
1055
- positiveNumberColor: chalk8.default.rgb(46, 125, 50),
1056
- negativeNumberColor: chalk8.default.rgb(183, 28, 28),
1057
- booleanColor: chalk8.default.rgb(175, 115, 0),
1058
- nullUndefinedColor: chalk8.default.rgb(121, 85, 72),
1059
- dateColor: chalk8.default.rgb(123, 31, 162)
1060
- }
1061
- }
1003
+ /**
1004
+ * Nature - A light theme with organic, earthy colors
1005
+ * Inspired by forest landscapes and natural elements
1006
+ *
1007
+ * Color Palette:
1008
+ * - Primary: Deep forest greens and rich browns
1009
+ * - Accents: Autumn reds and golden yellows
1010
+ * - Background: Assumes light terminal (white or very light grey)
1011
+ *
1012
+ * Best used with:
1013
+ * - Light terminal themes
1014
+ * - Nature-inspired interfaces
1015
+ * - Applications focusing on readability
1016
+ */
1017
+ const nature = {
1018
+ simpleView: {
1019
+ colors: {
1020
+ trace: chalk.default.rgb(121, 85, 72),
1021
+ debug: chalk.default.rgb(46, 125, 50),
1022
+ info: chalk.default.rgb(0, 105, 92),
1023
+ warn: chalk.default.rgb(175, 115, 0),
1024
+ error: chalk.default.rgb(183, 28, 28),
1025
+ fatal: chalk.default.bgRgb(183, 28, 28).rgb(255, 250, 240)
1026
+ },
1027
+ logIdColor: chalk.default.rgb(93, 64, 55),
1028
+ dataValueColor: chalk.default.rgb(27, 27, 27),
1029
+ dataKeyColor: chalk.default.rgb(56, 142, 60),
1030
+ selectorColor: chalk.default.rgb(0, 105, 92)
1031
+ },
1032
+ detailedView: {
1033
+ colors: {
1034
+ trace: chalk.default.rgb(121, 85, 72),
1035
+ debug: chalk.default.rgb(46, 125, 50),
1036
+ info: chalk.default.rgb(0, 105, 92),
1037
+ warn: chalk.default.rgb(175, 115, 0),
1038
+ error: chalk.default.rgb(183, 28, 28),
1039
+ fatal: chalk.default.bgRgb(183, 28, 28).rgb(255, 250, 240)
1040
+ },
1041
+ logIdColor: chalk.default.rgb(93, 64, 55),
1042
+ dataValueColor: chalk.default.rgb(27, 27, 27),
1043
+ dataKeyColor: chalk.default.rgb(56, 142, 60),
1044
+ selectorColor: chalk.default.rgb(0, 105, 92),
1045
+ headerColor: chalk.default.rgb(0, 77, 64),
1046
+ labelColor: chalk.default.rgb(0, 77, 64).bold,
1047
+ separatorColor: chalk.default.rgb(121, 85, 72),
1048
+ jsonColors: {
1049
+ keysColor: chalk.default.rgb(56, 142, 60),
1050
+ dashColor: chalk.default.rgb(27, 27, 27),
1051
+ numberColor: chalk.default.rgb(230, 81, 0),
1052
+ stringColor: chalk.default.rgb(0, 105, 92),
1053
+ multilineStringColor: chalk.default.rgb(0, 105, 92),
1054
+ positiveNumberColor: chalk.default.rgb(46, 125, 50),
1055
+ negativeNumberColor: chalk.default.rgb(183, 28, 28),
1056
+ booleanColor: chalk.default.rgb(175, 115, 0),
1057
+ nullUndefinedColor: chalk.default.rgb(121, 85, 72),
1058
+ dateColor: chalk.default.rgb(123, 31, 162)
1059
+ }
1060
+ }
1062
1061
  };
1063
- var pastel = {
1064
- simpleView: {
1065
- colors: {
1066
- trace: chalk8.default.rgb(179, 189, 203),
1067
- // Soft slate blue
1068
- debug: chalk8.default.rgb(189, 178, 255),
1069
- // Gentle lavender
1070
- info: chalk8.default.rgb(170, 236, 205),
1071
- // Mint green
1072
- warn: chalk8.default.rgb(255, 223, 186),
1073
- // Peach
1074
- error: chalk8.default.rgb(255, 188, 188),
1075
- // Soft coral
1076
- fatal: chalk8.default.bgRgb(255, 188, 188).rgb(76, 40, 40)
1077
- // Coral bg with deep brown
1078
- },
1079
- logIdColor: chalk8.default.rgb(203, 195, 227),
1080
- // Dusty lavender
1081
- dataValueColor: chalk8.default.rgb(236, 236, 236),
1082
- // Soft white
1083
- dataKeyColor: chalk8.default.rgb(186, 207, 255),
1084
- // Baby blue
1085
- selectorColor: chalk8.default.rgb(189, 178, 255)
1086
- // Soft lavender for gentle highlighting
1087
- },
1088
- detailedView: {
1089
- colors: {
1090
- trace: chalk8.default.rgb(179, 189, 203),
1091
- debug: chalk8.default.rgb(189, 178, 255),
1092
- info: chalk8.default.rgb(170, 236, 205),
1093
- warn: chalk8.default.rgb(255, 223, 186),
1094
- error: chalk8.default.rgb(255, 188, 188),
1095
- fatal: chalk8.default.bgRgb(255, 188, 188).rgb(76, 40, 40)
1096
- },
1097
- logIdColor: chalk8.default.rgb(203, 195, 227),
1098
- dataValueColor: chalk8.default.rgb(236, 236, 236),
1099
- dataKeyColor: chalk8.default.rgb(186, 207, 255),
1100
- selectorColor: chalk8.default.rgb(189, 178, 255),
1101
- // Soft lavender for gentle highlighting
1102
- headerColor: chalk8.default.rgb(255, 198, 255),
1103
- // Cotton candy pink
1104
- labelColor: chalk8.default.rgb(255, 198, 255).bold,
1105
- separatorColor: chalk8.default.rgb(179, 189, 203),
1106
- jsonColors: {
1107
- keysColor: chalk8.default.rgb(186, 207, 255),
1108
- // Baby blue
1109
- dashColor: chalk8.default.rgb(236, 236, 236),
1110
- // Soft white
1111
- numberColor: chalk8.default.rgb(255, 198, 255),
1112
- // Cotton candy pink
1113
- stringColor: chalk8.default.rgb(170, 236, 205),
1114
- // Mint green
1115
- multilineStringColor: chalk8.default.rgb(170, 236, 205),
1116
- positiveNumberColor: chalk8.default.rgb(170, 236, 205),
1117
- negativeNumberColor: chalk8.default.rgb(255, 188, 188),
1118
- booleanColor: chalk8.default.rgb(255, 223, 186),
1119
- // Peach
1120
- nullUndefinedColor: chalk8.default.rgb(179, 189, 203),
1121
- dateColor: chalk8.default.rgb(189, 178, 255)
1122
- // Gentle lavender
1123
- }
1124
- }
1062
+ /**
1063
+ * Pastel - A soft, calming theme with gentle colors
1064
+ * Inspired by watercolor paintings and cotton candy skies
1065
+ *
1066
+ * Color Palette:
1067
+ * - Primary: Soft pinks and lavenders
1068
+ * - Accents: Mint greens and baby blues
1069
+ * - Background: Assumes dark terminal (black or very dark grey)
1070
+ *
1071
+ * Best used with:
1072
+ * - Dark terminal themes
1073
+ * - Long coding sessions where eye comfort is priority
1074
+ * - Environments where a gentler aesthetic is preferred
1075
+ * - Applications focusing on reduced visual stress
1076
+ */
1077
+ const pastel = {
1078
+ simpleView: {
1079
+ colors: {
1080
+ trace: chalk.default.rgb(179, 189, 203),
1081
+ debug: chalk.default.rgb(189, 178, 255),
1082
+ info: chalk.default.rgb(170, 236, 205),
1083
+ warn: chalk.default.rgb(255, 223, 186),
1084
+ error: chalk.default.rgb(255, 188, 188),
1085
+ fatal: chalk.default.bgRgb(255, 188, 188).rgb(76, 40, 40)
1086
+ },
1087
+ logIdColor: chalk.default.rgb(203, 195, 227),
1088
+ dataValueColor: chalk.default.rgb(236, 236, 236),
1089
+ dataKeyColor: chalk.default.rgb(186, 207, 255),
1090
+ selectorColor: chalk.default.rgb(189, 178, 255)
1091
+ },
1092
+ detailedView: {
1093
+ colors: {
1094
+ trace: chalk.default.rgb(179, 189, 203),
1095
+ debug: chalk.default.rgb(189, 178, 255),
1096
+ info: chalk.default.rgb(170, 236, 205),
1097
+ warn: chalk.default.rgb(255, 223, 186),
1098
+ error: chalk.default.rgb(255, 188, 188),
1099
+ fatal: chalk.default.bgRgb(255, 188, 188).rgb(76, 40, 40)
1100
+ },
1101
+ logIdColor: chalk.default.rgb(203, 195, 227),
1102
+ dataValueColor: chalk.default.rgb(236, 236, 236),
1103
+ dataKeyColor: chalk.default.rgb(186, 207, 255),
1104
+ selectorColor: chalk.default.rgb(189, 178, 255),
1105
+ headerColor: chalk.default.rgb(255, 198, 255),
1106
+ labelColor: chalk.default.rgb(255, 198, 255).bold,
1107
+ separatorColor: chalk.default.rgb(179, 189, 203),
1108
+ jsonColors: {
1109
+ keysColor: chalk.default.rgb(186, 207, 255),
1110
+ dashColor: chalk.default.rgb(236, 236, 236),
1111
+ numberColor: chalk.default.rgb(255, 198, 255),
1112
+ stringColor: chalk.default.rgb(170, 236, 205),
1113
+ multilineStringColor: chalk.default.rgb(170, 236, 205),
1114
+ positiveNumberColor: chalk.default.rgb(170, 236, 205),
1115
+ negativeNumberColor: chalk.default.rgb(255, 188, 188),
1116
+ booleanColor: chalk.default.rgb(255, 223, 186),
1117
+ nullUndefinedColor: chalk.default.rgb(179, 189, 203),
1118
+ dateColor: chalk.default.rgb(189, 178, 255)
1119
+ }
1120
+ }
1125
1121
  };
1126
1122
 
1127
- // src/UIManager.ts
1128
-
1129
- var _keypress = require('keypress'); var _keypress2 = _interopRequireDefault(_keypress);
1130
- var UIManager = (_class3 = class {
1131
- /**
1132
- * Creates a new UIManager instance.
1133
- * Sets up keyboard handling and cleanup handlers.
1134
- *
1135
- * @param renderer - Instance for handling log display
1136
- * @param storage - Instance for log persistence
1137
- * @param disableInteractiveMode - Whether to disable interactive mode
1138
- */
1139
- constructor(renderer, storage, disableInteractiveMode = false) {;_class3.prototype.__init8.call(this);_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);_class3.prototype.__init11.call(this);_class3.prototype.__init12.call(this);_class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this);_class3.prototype.__init18.call(this);
1140
- this.renderer = renderer;
1141
- this.storage = storage;
1142
- this.isInteractiveDisabled = disableInteractiveMode;
1143
- if (!this.isInteractiveDisabled) {
1144
- this.setupKeyboardHandling();
1145
- }
1146
- process.stdout.on("resize", () => {
1147
- this.termWidth = process.stdout.columns || 80;
1148
- if (this.isDetailView) {
1149
- const entry = this.logs[this.selectedIndex];
1150
- const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1151
- const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1152
- this.renderer.renderDetailView(entry, prevEntry, nextEntry, this.renderer.getDetailViewScrollPos());
1153
- } else if (this.isSelectionMode) {
1154
- this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1155
- }
1156
- });
1157
- }
1158
- /** Whether the UI is in log selection mode */
1159
- __init8() {this.isSelectionMode = false}
1160
- /** Whether the UI is showing detailed log view */
1161
- __init9() {this.isDetailView = false}
1162
- /** Whether log streaming is paused */
1163
- __init10() {this.isPaused = false}
1164
- /** Whether interactive mode is disabled */
1165
-
1166
- /** Buffer for logs received while paused */
1167
- __init11() {this.pauseBuffer = []}
1168
- /** Buffer for new logs in selection mode */
1169
- __init12() {this.selectionBuffer = []}
1170
- /** Index of currently selected log entry */
1171
- __init13() {this.selectedIndex = 0}
1172
- /** Current filter text for log searching */
1173
- __init14() {this.filterText = ""}
1174
- /** Cached array of filtered log entries */
1175
- __init15() {this.logs = []}
1176
- /** Polling interval for checking new logs in detail view */
1177
- __init16() {this.detailViewPollInterval = null}
1178
- /** Polling interval for checking new logs in selection view */
1179
- __init17() {this.selectionViewPollInterval = null}
1180
- /** Current terminal width in characters */
1181
- __init18() {this.termWidth = process.stdout.columns || 80}
1182
- /**
1183
- * Sets up keyboard input handling and cleanup.
1184
- * Configures raw mode for immediate key processing.
1185
- * Sets up process exit handlers for cleanup.
1186
- * @private
1187
- */
1188
- setupKeyboardHandling() {
1189
- _keypress2.default.call(void 0, process.stdin);
1190
- process.stdin.setRawMode(true);
1191
- process.stdin.on("keypress", this.handleKeypress.bind(this));
1192
- const cleanup = () => {
1193
- if (this.detailViewPollInterval) {
1194
- clearInterval(this.detailViewPollInterval);
1195
- }
1196
- if (this.selectionViewPollInterval) {
1197
- clearInterval(this.selectionViewPollInterval);
1198
- }
1199
- process.stdin.setRawMode(false);
1200
- process.stdin.removeAllListeners("keypress");
1201
- console.clear();
1202
- this.storage.close();
1203
- process.exit(0);
1204
- };
1205
- process.on("SIGINT", cleanup);
1206
- process.on("SIGTERM", cleanup);
1207
- }
1208
- /**
1209
- * Starts polling for new logs in selection view
1210
- * @private
1211
- */
1212
- startSelectionViewPolling() {
1213
- if (this.selectionViewPollInterval) {
1214
- clearInterval(this.selectionViewPollInterval);
1215
- }
1216
- this.selectionViewPollInterval = setInterval(() => {
1217
- if (!this.isSelectionMode) {
1218
- clearInterval(this.selectionViewPollInterval);
1219
- this.selectionViewPollInterval = null;
1220
- return;
1221
- }
1222
- if (this.selectionBuffer.length > 0) {
1223
- this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1224
- }
1225
- }, 2e3);
1226
- }
1227
- /**
1228
- * Starts polling for new logs in detail view
1229
- * @private
1230
- */
1231
- startDetailViewPolling() {
1232
- if (this.detailViewPollInterval) {
1233
- clearInterval(this.detailViewPollInterval);
1234
- }
1235
- this.detailViewPollInterval = setInterval(() => {
1236
- if (!this.isDetailView) {
1237
- clearInterval(this.detailViewPollInterval);
1238
- this.detailViewPollInterval = null;
1239
- return;
1240
- }
1241
- const totalCount = this.filterText ? this.storage.getFilteredLogCount(this.filterText) : this.storage.getLogCount();
1242
- if (totalCount !== this.logs.length) {
1243
- const storedLogs = this.filterText ? this.storage.searchLogs(this.filterText) : this.storage.getAllLogs();
1244
- this.logs = storedLogs;
1245
- const entry = this.logs[this.selectedIndex];
1246
- const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1247
- const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1248
- this.renderer.renderDetailView(
1249
- entry,
1250
- prevEntry,
1251
- nextEntry,
1252
- this.renderer.getDetailViewScrollPos(),
1253
- this.selectedIndex + 1,
1254
- totalCount,
1255
- this.filterText
1256
- );
1257
- }
1258
- }, 2e3);
1259
- }
1260
- /**
1261
- * Updates the filtered list of logs based on search text.
1262
- * Handles both full list and filtered views.
1263
- * Maintains selection state when filter changes.
1264
- * @private
1265
- */
1266
- updateFilteredLogs() {
1267
- const totalCount = this.filterText ? this.storage.getFilteredLogCount(this.filterText) : this.storage.getLogCount();
1268
- const effectiveCount = totalCount - this.selectionBuffer.length;
1269
- if (effectiveCount !== this.logs.length) {
1270
- const storedLogs = this.filterText ? this.storage.searchLogs(this.filterText) : this.storage.getAllLogs();
1271
- this.logs = storedLogs.slice(0, storedLogs.length - this.selectionBuffer.length);
1272
- if (this.logs.length > 0) {
1273
- this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.logs.length - 1));
1274
- } else {
1275
- this.selectedIndex = 0;
1276
- }
1277
- }
1278
- }
1279
- updateNewLogsNotification() {
1280
- if (!this.isSelectionMode || !this.selectionBuffer.length) return;
1281
- process.stdout.write(`\x1B[2A\r${" ".repeat(this.termWidth)}\r`);
1282
- const notification = chalk8.default.dim(
1283
- `${this.selectionBuffer.length} new log${this.selectionBuffer.length === 1 ? "" : "s"} available (press \u2193 to view)`
1284
- );
1285
- process.stdout.write(`${notification}
1286
-
1287
- `);
1288
- }
1289
- /**
1290
- * Handles new log entries from the transport.
1291
- * Stores the log and updates the display if needed.
1292
- *
1293
- * @param entry - New log entry to process
1294
- */
1295
- handleNewLog(entry) {
1296
- this.storage.store(entry);
1297
- if (this.isInteractiveDisabled) {
1298
- this.renderer.renderLogLine(entry);
1299
- return;
1300
- }
1301
- if (this.isSelectionMode) {
1302
- this.selectionBuffer.push(entry);
1303
- this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1304
- return;
1305
- }
1306
- if (!this.isDetailView) {
1307
- if (this.isPaused) {
1308
- this.pauseBuffer.push(entry);
1309
- process.stdout.write(`\r${chalk8.default.yellow(`\u23F8 Paused (${this.pauseBuffer.length} new logs)`)}${" ".repeat(20)}`);
1310
- } else {
1311
- this.renderer.renderLogLine(entry);
1312
- }
1313
- }
1314
- }
1315
- /**
1316
- * Processes keyboard input and manages UI state.
1317
- * Handles navigation, mode switching, and filtering.
1318
- *
1319
- * Key mappings:
1320
- * - CTRL+C: Exit application
1321
- * - TAB: Toggle selection mode
1322
- * - Up/Down: Navigate logs
1323
- * - Enter: View log details
1324
- * - Backspace: Edit filter
1325
- * - P: Toggle pause in simple view
1326
- * - Other keys: Add to filter
1327
- *
1328
- * @param ch - Character input if available
1329
- * @param key - Key event information
1330
- * @private
1331
- */
1332
- handleKeypress(ch, key) {
1333
- if (_optionalChain([key, 'optionalAccess', _ => _.ctrl]) && _optionalChain([key, 'optionalAccess', _2 => _2.name]) === "c") {
1334
- process.stdin.setRawMode(false);
1335
- process.stdin.removeAllListeners("keypress");
1336
- console.clear();
1337
- this.storage.close();
1338
- process.exit(0);
1339
- return;
1340
- }
1341
- if (!this.isSelectionMode && !this.isDetailView && ch === "p") {
1342
- this.isPaused = !this.isPaused;
1343
- if (!this.isPaused && this.pauseBuffer.length > 0) {
1344
- process.stdout.write(`\r${" ".repeat(50)}\r`);
1345
- for (const entry of this.pauseBuffer) {
1346
- this.renderer.renderLogLine(entry);
1347
- }
1348
- this.pauseBuffer = [];
1349
- } else if (this.isPaused) {
1350
- process.stdout.write(`\r${chalk8.default.yellow("\u23F8 Paused (0 new logs)")}${" ".repeat(20)}`);
1351
- }
1352
- return;
1353
- }
1354
- if (!this.isSelectionMode && !this.isDetailView && (_optionalChain([key, 'optionalAccess', _3 => _3.name]) === "up" || _optionalChain([key, 'optionalAccess', _4 => _4.name]) === "down")) {
1355
- this.isSelectionMode = true;
1356
- this.filterText = "";
1357
- this.isPaused = true;
1358
- const storedLogs = this.storage.getAllLogs();
1359
- this.logs = storedLogs;
1360
- this.selectedIndex = key.name === "up" ? Math.max(0, this.logs.length - 1) : Math.max(0, this.logs.length - 1);
1361
- this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1362
- this.startSelectionViewPolling();
1363
- return;
1364
- }
1365
- if (!this.isSelectionMode && !this.isDetailView && ch === "c") {
1366
- const newMode = this.renderer.cycleViewMode();
1367
- console.clear();
1368
- const logs = this.storage.getAllLogs();
1369
- for (const entry of logs) {
1370
- this.renderer.renderLogLine(entry);
1371
- }
1372
- const modeDescriptions = {
1373
- full: "Full view enabled (all data shown without truncation)",
1374
- truncated: "Truncated view enabled (timestamp, ID, level, message, truncated data)",
1375
- condensed: "Condensed view enabled (timestamp, level and message only)"
1376
- };
1377
- process.stdout.write(`\r${chalk8.default.cyan(`\u2139 ${modeDescriptions[newMode]}`)}${" ".repeat(20)}`);
1378
- setTimeout(() => {
1379
- process.stdout.write(`\r${" ".repeat(100)}\r`);
1380
- }, 3e3);
1381
- return;
1382
- }
1383
- if (this.isSelectionMode) {
1384
- if (key) {
1385
- switch (key.name) {
1386
- case "up": {
1387
- this.selectedIndex = Math.max(0, this.selectedIndex - 1);
1388
- this.renderer.renderSelectionView(
1389
- this.logs,
1390
- this.selectedIndex,
1391
- this.filterText,
1392
- this.selectionBuffer.length
1393
- );
1394
- return;
1395
- }
1396
- case "down": {
1397
- if (this.selectedIndex === this.logs.length - 1 && this.selectionBuffer.length > 0) {
1398
- this.logs.push(...this.selectionBuffer);
1399
- this.selectionBuffer = [];
1400
- }
1401
- this.selectedIndex = Math.min(this.logs.length - 1, this.selectedIndex + 1);
1402
- this.renderer.renderSelectionView(
1403
- this.logs,
1404
- this.selectedIndex,
1405
- this.filterText,
1406
- this.selectionBuffer.length
1407
- );
1408
- return;
1409
- }
1410
- case "return": {
1411
- if (this.logs.length > 0) {
1412
- this.isSelectionMode = false;
1413
- this.isDetailView = true;
1414
- console.clear();
1415
- const selectedEntry = this.logs[this.selectedIndex];
1416
- const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1417
- const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1418
- this.renderer.renderDetailView(
1419
- selectedEntry,
1420
- prevEntry,
1421
- nextEntry,
1422
- 0,
1423
- this.selectedIndex + 1,
1424
- this.logs.length,
1425
- this.filterText
1426
- );
1427
- this.startDetailViewPolling();
1428
- }
1429
- return;
1430
- }
1431
- case "backspace": {
1432
- if (this.filterText.length > 0) {
1433
- this.filterText = this.filterText.slice(0, -1);
1434
- this.updateFilteredLogs();
1435
- this.renderer.renderSelectionView(
1436
- this.logs,
1437
- this.selectedIndex,
1438
- this.filterText,
1439
- this.selectionBuffer.length
1440
- );
1441
- }
1442
- return;
1443
- }
1444
- case "tab": {
1445
- this.isSelectionMode = false;
1446
- this.isPaused = false;
1447
- if (this.selectionViewPollInterval) {
1448
- clearInterval(this.selectionViewPollInterval);
1449
- this.selectionViewPollInterval = null;
1450
- }
1451
- this.filterText = "";
1452
- console.clear();
1453
- const logs = this.storage.getAllLogs();
1454
- for (const entry of logs) {
1455
- this.renderer.renderLogLine(entry);
1456
- }
1457
- if (this.selectionBuffer.length > 0) {
1458
- for (const entry of this.selectionBuffer) {
1459
- this.renderer.renderLogLine(entry);
1460
- }
1461
- this.selectionBuffer = [];
1462
- }
1463
- return;
1464
- }
1465
- }
1466
- }
1467
- if (ch && (!key || !key.ctrl && !key.meta) && ch.length === 1) {
1468
- this.filterText += ch;
1469
- this.updateFilteredLogs();
1470
- this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1471
- return;
1472
- }
1473
- }
1474
- if (this.isDetailView) {
1475
- if (_optionalChain([key, 'optionalAccess', _5 => _5.name])) {
1476
- switch (key.name) {
1477
- case "up": {
1478
- this.renderer.scrollDetailView(-1);
1479
- const entry = this.logs[this.selectedIndex];
1480
- const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1481
- const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1482
- this.renderer.renderDetailView(
1483
- entry,
1484
- prevEntry,
1485
- nextEntry,
1486
- this.renderer.getDetailViewScrollPos(),
1487
- this.selectedIndex + 1,
1488
- this.logs.length,
1489
- this.filterText
1490
- );
1491
- break;
1492
- }
1493
- case "down": {
1494
- this.renderer.scrollDetailView(1);
1495
- const entry = this.logs[this.selectedIndex];
1496
- const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1497
- const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1498
- this.renderer.renderDetailView(
1499
- entry,
1500
- prevEntry,
1501
- nextEntry,
1502
- this.renderer.getDetailViewScrollPos(),
1503
- this.selectedIndex + 1,
1504
- this.logs.length,
1505
- this.filterText
1506
- );
1507
- break;
1508
- }
1509
- case "left": {
1510
- if (this.selectedIndex > 0) {
1511
- this.selectedIndex = Math.max(0, this.selectedIndex - 1);
1512
- const entry = this.logs[this.selectedIndex];
1513
- const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1514
- const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1515
- this.renderer.renderDetailView(
1516
- entry,
1517
- prevEntry,
1518
- nextEntry,
1519
- 0,
1520
- this.selectedIndex + 1,
1521
- this.logs.length,
1522
- this.filterText
1523
- );
1524
- }
1525
- break;
1526
- }
1527
- case "right": {
1528
- if (this.selectedIndex < this.logs.length - 1) {
1529
- this.selectedIndex = Math.min(this.logs.length - 1, this.selectedIndex + 1);
1530
- const entry = this.logs[this.selectedIndex];
1531
- const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1532
- const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1533
- this.renderer.renderDetailView(
1534
- entry,
1535
- prevEntry,
1536
- nextEntry,
1537
- 0,
1538
- this.selectedIndex + 1,
1539
- this.logs.length,
1540
- this.filterText
1541
- );
1542
- }
1543
- break;
1544
- }
1545
- case "tab": {
1546
- if (this.renderer.isInJsonView()) {
1547
- this.renderer.toggleJsonView();
1548
- const entry = this.logs[this.selectedIndex];
1549
- const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1550
- const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1551
- this.renderer.renderDetailView(
1552
- entry,
1553
- prevEntry,
1554
- nextEntry,
1555
- this.renderer.getDetailViewScrollPos(),
1556
- this.selectedIndex + 1,
1557
- this.logs.length,
1558
- this.filterText
1559
- );
1560
- break;
1561
- }
1562
- this.isDetailView = false;
1563
- if (this.detailViewPollInterval) {
1564
- clearInterval(this.detailViewPollInterval);
1565
- this.detailViewPollInterval = null;
1566
- }
1567
- this.isSelectionMode = true;
1568
- this.updateFilteredLogs();
1569
- this.renderer.renderSelectionView(
1570
- this.logs,
1571
- this.selectedIndex,
1572
- this.filterText,
1573
- this.selectionBuffer.length
1574
- );
1575
- break;
1576
- }
1577
- }
1578
- }
1579
- if (ch) {
1580
- switch (ch.toLowerCase()) {
1581
- case "w": {
1582
- this.renderer.scrollDetailView(process.stdout.rows - 8);
1583
- const entry = this.logs[this.selectedIndex];
1584
- const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1585
- const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1586
- this.renderer.renderDetailView(
1587
- entry,
1588
- prevEntry,
1589
- nextEntry,
1590
- this.renderer.getDetailViewScrollPos(),
1591
- this.selectedIndex + 1,
1592
- this.logs.length
1593
- );
1594
- break;
1595
- }
1596
- case "q": {
1597
- this.renderer.scrollDetailView(-process.stdout.rows + 8);
1598
- const entry = this.logs[this.selectedIndex];
1599
- const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1600
- const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1601
- this.renderer.renderDetailView(
1602
- entry,
1603
- prevEntry,
1604
- nextEntry,
1605
- this.renderer.getDetailViewScrollPos(),
1606
- this.selectedIndex + 1,
1607
- this.logs.length
1608
- );
1609
- break;
1610
- }
1611
- case "a": {
1612
- if (this.selectedIndex !== 0) {
1613
- this.selectedIndex = 0;
1614
- const entry = this.logs[this.selectedIndex];
1615
- const prevEntry = null;
1616
- const nextEntry = this.logs.length > 1 ? this.logs[1] : null;
1617
- this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, 1, this.logs.length);
1618
- }
1619
- break;
1620
- }
1621
- case "s": {
1622
- const lastIndex = this.logs.length - 1;
1623
- if (this.selectedIndex !== lastIndex) {
1624
- this.selectedIndex = lastIndex;
1625
- const entry = this.logs[this.selectedIndex];
1626
- const prevEntry = lastIndex > 0 ? this.logs[lastIndex - 1] : null;
1627
- const nextEntry = null;
1628
- this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, this.logs.length, this.logs.length);
1629
- }
1630
- break;
1631
- }
1632
- case "c": {
1633
- this.renderer.toggleArrayCollapse();
1634
- const entry = this.logs[this.selectedIndex];
1635
- const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1636
- const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1637
- this.renderer.renderDetailView(
1638
- entry,
1639
- prevEntry,
1640
- nextEntry,
1641
- this.renderer.getDetailViewScrollPos(),
1642
- this.selectedIndex + 1,
1643
- this.logs.length
1644
- );
1645
- break;
1646
- }
1647
- case "j": {
1648
- this.renderer.toggleJsonView();
1649
- const entry = this.logs[this.selectedIndex];
1650
- const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1651
- const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1652
- this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, this.selectedIndex + 1, this.logs.length);
1653
- break;
1654
- }
1655
- }
1656
- }
1657
- }
1658
- }
1659
- }, _class3);
1660
-
1661
- // src/PrettyTerminalTransport.ts
1662
- var PrettyTerminalTransport = (_class4 = class _PrettyTerminalTransport extends _transport.LoggerlessTransport {
1663
- /** Singleton instance of the transport */
1664
- static __initStatic() {this.instance = null}
1665
- /** Handles all rendering and formatting of logs */
1666
-
1667
- /** Manages log persistence in SQLite database */
1668
-
1669
- /** Manages user interaction and view state */
1670
-
1671
- /** Configuration options */
1672
-
1673
- /**
1674
- * Creates a new PrettyTerminalTransport instance.
1675
- * This is a singleton class - only one instance can exist at a time.
1676
- * Use getInstance() instead of constructor directly.
1677
- *
1678
- * @param config - Configuration options for the transport
1679
- * @throws Error if attempting to create multiple instances
1680
- */
1681
- constructor(config = {}) {
1682
- if (_PrettyTerminalTransport.instance) {
1683
- throw new Error("PrettyTerminalTransport is a singleton. Use getPrettyTerminal() instead.");
1684
- }
1685
- super(config);
1686
- this.config = config;
1687
- if (config.enabled === false) {
1688
- return;
1689
- }
1690
- const maxInlineDepth = config.maxInlineDepth || 4;
1691
- const maxInlineLength = config.maxInlineLength || 120;
1692
- const theme = config.theme || moonlight;
1693
- const logFile = config.logFile;
1694
- const simpleViewConfig = {
1695
- colors: {
1696
- trace: chalk8.default.gray,
1697
- // Lowest level, used for verbose output
1698
- debug: chalk8.default.blue,
1699
- // Debug information
1700
- info: chalk8.default.green,
1701
- // Normal operation
1702
- warn: chalk8.default.yellow,
1703
- // Warning conditions
1704
- error: chalk8.default.red,
1705
- // Error conditions
1706
- fatal: chalk8.default.bgRed.white,
1707
- // Critical errors
1708
- ...theme.simpleView.colors
1709
- },
1710
- logIdColor: theme.simpleView.logIdColor || chalk8.default.dim,
1711
- dataValueColor: theme.simpleView.dataValueColor || chalk8.default.white,
1712
- dataKeyColor: theme.simpleView.dataKeyColor || chalk8.default.dim,
1713
- selectorColor: theme.simpleView.selectorColor || chalk8.default.cyan
1714
- };
1715
- const detailedViewConfig = {
1716
- colors: {
1717
- trace: chalk8.default.gray,
1718
- debug: chalk8.default.blue,
1719
- info: chalk8.default.green,
1720
- warn: chalk8.default.yellow,
1721
- error: chalk8.default.red,
1722
- fatal: chalk8.default.bgRed.white,
1723
- ..._optionalChain([theme, 'access', _6 => _6.detailedView, 'optionalAccess', _7 => _7.colors])
1724
- },
1725
- logIdColor: _optionalChain([theme, 'access', _8 => _8.detailedView, 'optionalAccess', _9 => _9.logIdColor]) || chalk8.default.dim,
1726
- dataValueColor: _optionalChain([theme, 'access', _10 => _10.detailedView, 'optionalAccess', _11 => _11.dataValueColor]) || chalk8.default.white,
1727
- dataKeyColor: _optionalChain([theme, 'access', _12 => _12.detailedView, 'optionalAccess', _13 => _13.dataKeyColor]) || chalk8.default.dim,
1728
- selectorColor: _optionalChain([theme, 'access', _14 => _14.detailedView, 'optionalAccess', _15 => _15.selectorColor]) || chalk8.default.cyan,
1729
- headerColor: _optionalChain([theme, 'access', _16 => _16.detailedView, 'optionalAccess', _17 => _17.headerColor]) || chalk8.default.cyan,
1730
- labelColor: _optionalChain([theme, 'access', _18 => _18.detailedView, 'optionalAccess', _19 => _19.labelColor]) || chalk8.default.cyan.bold,
1731
- separatorColor: _optionalChain([theme, 'access', _20 => _20.detailedView, 'optionalAccess', _21 => _21.separatorColor]) || chalk8.default.dim,
1732
- // JSON formatting colors for detailed data view
1733
- jsonColors: {
1734
- keysColor: chalk8.default.yellow,
1735
- // Object property names
1736
- dashColor: chalk8.default.white,
1737
- // Array bullets
1738
- numberColor: chalk8.default.yellow,
1739
- // Default number color
1740
- stringColor: chalk8.default.white,
1741
- // Single-line strings
1742
- multilineStringColor: chalk8.default.white,
1743
- // Multi-line strings
1744
- positiveNumberColor: chalk8.default.green,
1745
- // Numbers > 0
1746
- negativeNumberColor: chalk8.default.red,
1747
- // Numbers < 0
1748
- booleanColor: chalk8.default.cyan,
1749
- // true/false values
1750
- nullUndefinedColor: chalk8.default.grey,
1751
- // null/undefined
1752
- dateColor: chalk8.default.magenta,
1753
- // Date objects
1754
- ..._optionalChain([theme, 'access', _22 => _22.detailedView, 'optionalAccess', _23 => _23.jsonColors])
1755
- }
1756
- };
1757
- this.storage = new LogStorage(logFile);
1758
- this.renderer = new LogRenderer(simpleViewConfig, detailedViewConfig, maxInlineDepth, maxInlineLength);
1759
- this.uiManager = new UIManager(this.renderer, this.storage, config.disableInteractiveMode);
1760
- _PrettyTerminalTransport.instance = this;
1761
- }
1762
- /**
1763
- * Gets or creates the singleton instance of PrettyTerminalTransport.
1764
- * This is the recommended way to obtain a transport instance.
1765
- *
1766
- * @param config - Configuration options for the transport
1767
- * @returns The singleton instance of PrettyTerminalTransport
1768
- */
1769
- static getInstance(config = {}) {
1770
- if (!_PrettyTerminalTransport.instance) {
1771
- _PrettyTerminalTransport.instance = new _PrettyTerminalTransport(config);
1772
- }
1773
- return _PrettyTerminalTransport.instance;
1774
- }
1775
- /**
1776
- * Generates a random ID for each log entry.
1777
- * Uses base36 encoding for compact, readable IDs.
1778
- *
1779
- * @returns A 6-character string ID
1780
- * @example
1781
- * "a1b2c3" // Example generated ID
1782
- */
1783
- generateId() {
1784
- return Math.random().toString(36).substring(2, 8);
1785
- }
1786
- /**
1787
- * Main transport method that receives logs from LogLayer.
1788
- * This method is called for each log event and handles:
1789
- * - Generating a unique ID for the log
1790
- * - Converting the log data to a storable format
1791
- * - Storing the log in the database
1792
- * - Rendering the log if not in selection mode
1793
- *
1794
- * @param logLevel - The severity level of the log
1795
- * @param messages - Array of message strings to be joined
1796
- * @param data - Additional structured data to be logged
1797
- * @param hasData - Whether the log includes additional data
1798
- * @returns The original messages array
1799
- */
1800
- shipToLogger({ logLevel, messages, data, hasData }) {
1801
- if (this.config.enabled === false) {
1802
- return messages;
1803
- }
1804
- const entry = {
1805
- id: this.generateId(),
1806
- timestamp: Date.now(),
1807
- level: logLevel,
1808
- message: messages.join(" "),
1809
- data: hasData ? JSON.stringify(data) : null
1810
- };
1811
- this.uiManager.handleNewLog(entry);
1812
- return messages;
1813
- }
1814
- }, _class4.__initStatic(), _class4);
1123
+ //#endregion
1124
+ //#region src/UIManager.ts
1125
+ /**
1126
+ * Manages UI state and user interaction.
1127
+ * Acts as the controller between the storage and rendering layers.
1128
+ * Handles all keyboard input and view transitions.
1129
+ */
1130
+ var UIManager = class {
1131
+ /** Whether the UI is in log selection mode */
1132
+ isSelectionMode = false;
1133
+ /** Whether the UI is showing detailed log view */
1134
+ isDetailView = false;
1135
+ /** Whether log streaming is paused */
1136
+ isPaused = false;
1137
+ /** Whether interactive mode is disabled */
1138
+ isInteractiveDisabled;
1139
+ /** Buffer for logs received while paused */
1140
+ pauseBuffer = [];
1141
+ /** Buffer for new logs in selection mode */
1142
+ selectionBuffer = [];
1143
+ /** Index of currently selected log entry */
1144
+ selectedIndex = 0;
1145
+ /** Current filter text for log searching */
1146
+ filterText = "";
1147
+ /** Cached array of filtered log entries */
1148
+ logs = [];
1149
+ /** Polling interval for checking new logs in detail view */
1150
+ detailViewPollInterval = null;
1151
+ /** Polling interval for checking new logs in selection view */
1152
+ selectionViewPollInterval = null;
1153
+ /** Current terminal width in characters */
1154
+ termWidth = process.stdout.columns || 80;
1155
+ /**
1156
+ * Creates a new UIManager instance.
1157
+ * Sets up keyboard handling and cleanup handlers.
1158
+ *
1159
+ * @param renderer - Instance for handling log display
1160
+ * @param storage - Instance for log persistence
1161
+ * @param disableInteractiveMode - Whether to disable interactive mode
1162
+ */
1163
+ constructor(renderer, storage, disableInteractiveMode = false) {
1164
+ this.renderer = renderer;
1165
+ this.storage = storage;
1166
+ this.isInteractiveDisabled = disableInteractiveMode;
1167
+ if (!this.isInteractiveDisabled) this.setupKeyboardHandling();
1168
+ process.stdout.on("resize", () => {
1169
+ this.termWidth = process.stdout.columns || 80;
1170
+ if (this.isDetailView) {
1171
+ const entry = this.logs[this.selectedIndex];
1172
+ const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1173
+ const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1174
+ this.renderer.renderDetailView(entry, prevEntry, nextEntry, this.renderer.getDetailViewScrollPos());
1175
+ } else if (this.isSelectionMode) this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1176
+ });
1177
+ }
1178
+ /**
1179
+ * Sets up keyboard input handling and cleanup.
1180
+ * Configures raw mode for immediate key processing.
1181
+ * Sets up process exit handlers for cleanup.
1182
+ * @private
1183
+ */
1184
+ setupKeyboardHandling() {
1185
+ (0, keypress.default)(process.stdin);
1186
+ process.stdin.setRawMode(true);
1187
+ process.stdin.on("keypress", this.handleKeypress.bind(this));
1188
+ const cleanup = () => {
1189
+ if (this.detailViewPollInterval) clearInterval(this.detailViewPollInterval);
1190
+ if (this.selectionViewPollInterval) clearInterval(this.selectionViewPollInterval);
1191
+ process.stdin.setRawMode(false);
1192
+ process.stdin.removeAllListeners("keypress");
1193
+ console.clear();
1194
+ this.storage.close();
1195
+ process.exit(0);
1196
+ };
1197
+ process.on("SIGINT", cleanup);
1198
+ process.on("SIGTERM", cleanup);
1199
+ }
1200
+ /**
1201
+ * Starts polling for new logs in selection view
1202
+ * @private
1203
+ */
1204
+ startSelectionViewPolling() {
1205
+ if (this.selectionViewPollInterval) clearInterval(this.selectionViewPollInterval);
1206
+ this.selectionViewPollInterval = setInterval(() => {
1207
+ if (!this.isSelectionMode) {
1208
+ clearInterval(this.selectionViewPollInterval);
1209
+ this.selectionViewPollInterval = null;
1210
+ return;
1211
+ }
1212
+ if (this.selectionBuffer.length > 0) this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1213
+ }, 2e3);
1214
+ }
1215
+ /**
1216
+ * Starts polling for new logs in detail view
1217
+ * @private
1218
+ */
1219
+ startDetailViewPolling() {
1220
+ if (this.detailViewPollInterval) clearInterval(this.detailViewPollInterval);
1221
+ this.detailViewPollInterval = setInterval(() => {
1222
+ if (!this.isDetailView) {
1223
+ clearInterval(this.detailViewPollInterval);
1224
+ this.detailViewPollInterval = null;
1225
+ return;
1226
+ }
1227
+ const totalCount = this.filterText ? this.storage.getFilteredLogCount(this.filterText) : this.storage.getLogCount();
1228
+ if (totalCount !== this.logs.length) {
1229
+ this.logs = this.filterText ? this.storage.searchLogs(this.filterText) : this.storage.getAllLogs();
1230
+ const entry = this.logs[this.selectedIndex];
1231
+ const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1232
+ const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1233
+ this.renderer.renderDetailView(entry, prevEntry, nextEntry, this.renderer.getDetailViewScrollPos(), this.selectedIndex + 1, totalCount, this.filterText);
1234
+ }
1235
+ }, 2e3);
1236
+ }
1237
+ /**
1238
+ * Updates the filtered list of logs based on search text.
1239
+ * Handles both full list and filtered views.
1240
+ * Maintains selection state when filter changes.
1241
+ * @private
1242
+ */
1243
+ updateFilteredLogs() {
1244
+ if ((this.filterText ? this.storage.getFilteredLogCount(this.filterText) : this.storage.getLogCount()) - this.selectionBuffer.length !== this.logs.length) {
1245
+ const storedLogs = this.filterText ? this.storage.searchLogs(this.filterText) : this.storage.getAllLogs();
1246
+ this.logs = storedLogs.slice(0, storedLogs.length - this.selectionBuffer.length);
1247
+ if (this.logs.length > 0) this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.logs.length - 1));
1248
+ else this.selectedIndex = 0;
1249
+ }
1250
+ }
1251
+ updateNewLogsNotification() {
1252
+ if (!this.isSelectionMode || !this.selectionBuffer.length) return;
1253
+ process.stdout.write(`\x1b[2A\r${" ".repeat(this.termWidth)}\r`);
1254
+ const notification = chalk.default.dim(`${this.selectionBuffer.length} new log${this.selectionBuffer.length === 1 ? "" : "s"} available (press ↓ to view)`);
1255
+ process.stdout.write(`${notification}\n\n`);
1256
+ }
1257
+ /**
1258
+ * Handles new log entries from the transport.
1259
+ * Stores the log and updates the display if needed.
1260
+ *
1261
+ * @param entry - New log entry to process
1262
+ */
1263
+ handleNewLog(entry) {
1264
+ this.storage.store(entry);
1265
+ if (this.isInteractiveDisabled) {
1266
+ this.renderer.renderLogLine(entry);
1267
+ return;
1268
+ }
1269
+ if (this.isSelectionMode) {
1270
+ this.selectionBuffer.push(entry);
1271
+ this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1272
+ return;
1273
+ }
1274
+ if (!this.isDetailView) if (this.isPaused) {
1275
+ this.pauseBuffer.push(entry);
1276
+ process.stdout.write(`\r${chalk.default.yellow(`⏸ Paused (${this.pauseBuffer.length} new logs)`)}${" ".repeat(20)}`);
1277
+ } else this.renderer.renderLogLine(entry);
1278
+ }
1279
+ /**
1280
+ * Processes keyboard input and manages UI state.
1281
+ * Handles navigation, mode switching, and filtering.
1282
+ *
1283
+ * Key mappings:
1284
+ * - CTRL+C: Exit application
1285
+ * - TAB: Toggle selection mode
1286
+ * - Up/Down: Navigate logs
1287
+ * - Enter: View log details
1288
+ * - Backspace: Edit filter
1289
+ * - P: Toggle pause in simple view
1290
+ * - Other keys: Add to filter
1291
+ *
1292
+ * @param ch - Character input if available
1293
+ * @param key - Key event information
1294
+ * @private
1295
+ */
1296
+ handleKeypress(ch, key) {
1297
+ if (key?.ctrl && key?.name === "c") {
1298
+ process.stdin.setRawMode(false);
1299
+ process.stdin.removeAllListeners("keypress");
1300
+ console.clear();
1301
+ this.storage.close();
1302
+ process.exit(0);
1303
+ return;
1304
+ }
1305
+ if (!this.isSelectionMode && !this.isDetailView && ch === "p") {
1306
+ this.isPaused = !this.isPaused;
1307
+ if (!this.isPaused && this.pauseBuffer.length > 0) {
1308
+ process.stdout.write(`\r${" ".repeat(50)}\r`);
1309
+ for (const entry of this.pauseBuffer) this.renderer.renderLogLine(entry);
1310
+ this.pauseBuffer = [];
1311
+ } else if (this.isPaused) process.stdout.write(`\r${chalk.default.yellow("⏸ Paused (0 new logs)")}${" ".repeat(20)}`);
1312
+ return;
1313
+ }
1314
+ if (!this.isSelectionMode && !this.isDetailView && (key?.name === "up" || key?.name === "down")) {
1315
+ this.isSelectionMode = true;
1316
+ this.filterText = "";
1317
+ this.isPaused = true;
1318
+ this.logs = this.storage.getAllLogs();
1319
+ this.selectedIndex = key.name === "up" ? Math.max(0, this.logs.length - 1) : Math.max(0, this.logs.length - 1);
1320
+ this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1321
+ this.startSelectionViewPolling();
1322
+ return;
1323
+ }
1324
+ if (!this.isSelectionMode && !this.isDetailView && ch === "c") {
1325
+ const newMode = this.renderer.cycleViewMode();
1326
+ console.clear();
1327
+ const logs = this.storage.getAllLogs();
1328
+ for (const entry of logs) this.renderer.renderLogLine(entry);
1329
+ process.stdout.write(`\r${chalk.default.cyan(`ℹ ${{
1330
+ full: "Full view enabled (all data shown without truncation)",
1331
+ truncated: "Truncated view enabled (timestamp, ID, level, message, truncated data)",
1332
+ condensed: "Condensed view enabled (timestamp, level and message only)"
1333
+ }[newMode]}`)}${" ".repeat(20)}`);
1334
+ setTimeout(() => {
1335
+ process.stdout.write(`\r${" ".repeat(100)}\r`);
1336
+ }, 3e3);
1337
+ return;
1338
+ }
1339
+ if (this.isSelectionMode) {
1340
+ if (key) switch (key.name) {
1341
+ case "up":
1342
+ this.selectedIndex = Math.max(0, this.selectedIndex - 1);
1343
+ this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1344
+ return;
1345
+ case "down":
1346
+ if (this.selectedIndex === this.logs.length - 1 && this.selectionBuffer.length > 0) {
1347
+ this.logs.push(...this.selectionBuffer);
1348
+ this.selectionBuffer = [];
1349
+ }
1350
+ this.selectedIndex = Math.min(this.logs.length - 1, this.selectedIndex + 1);
1351
+ this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1352
+ return;
1353
+ case "return":
1354
+ if (this.logs.length > 0) {
1355
+ this.isSelectionMode = false;
1356
+ this.isDetailView = true;
1357
+ console.clear();
1358
+ const selectedEntry = this.logs[this.selectedIndex];
1359
+ const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1360
+ const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1361
+ this.renderer.renderDetailView(selectedEntry, prevEntry, nextEntry, 0, this.selectedIndex + 1, this.logs.length, this.filterText);
1362
+ this.startDetailViewPolling();
1363
+ }
1364
+ return;
1365
+ case "backspace":
1366
+ if (this.filterText.length > 0) {
1367
+ this.filterText = this.filterText.slice(0, -1);
1368
+ this.updateFilteredLogs();
1369
+ this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1370
+ }
1371
+ return;
1372
+ case "tab": {
1373
+ this.isSelectionMode = false;
1374
+ this.isPaused = false;
1375
+ if (this.selectionViewPollInterval) {
1376
+ clearInterval(this.selectionViewPollInterval);
1377
+ this.selectionViewPollInterval = null;
1378
+ }
1379
+ this.filterText = "";
1380
+ console.clear();
1381
+ const logs = this.storage.getAllLogs();
1382
+ for (const entry of logs) this.renderer.renderLogLine(entry);
1383
+ if (this.selectionBuffer.length > 0) {
1384
+ for (const entry of this.selectionBuffer) this.renderer.renderLogLine(entry);
1385
+ this.selectionBuffer = [];
1386
+ }
1387
+ return;
1388
+ }
1389
+ }
1390
+ if (ch && (!key || !key.ctrl && !key.meta) && ch.length === 1) {
1391
+ this.filterText += ch;
1392
+ this.updateFilteredLogs();
1393
+ this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1394
+ return;
1395
+ }
1396
+ }
1397
+ if (this.isDetailView) {
1398
+ if (key?.name) switch (key.name) {
1399
+ case "up": {
1400
+ this.renderer.scrollDetailView(-1);
1401
+ const entry = this.logs[this.selectedIndex];
1402
+ const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1403
+ const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1404
+ this.renderer.renderDetailView(entry, prevEntry, nextEntry, this.renderer.getDetailViewScrollPos(), this.selectedIndex + 1, this.logs.length, this.filterText);
1405
+ break;
1406
+ }
1407
+ case "down": {
1408
+ this.renderer.scrollDetailView(1);
1409
+ const entry = this.logs[this.selectedIndex];
1410
+ const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1411
+ const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1412
+ this.renderer.renderDetailView(entry, prevEntry, nextEntry, this.renderer.getDetailViewScrollPos(), this.selectedIndex + 1, this.logs.length, this.filterText);
1413
+ break;
1414
+ }
1415
+ case "left":
1416
+ if (this.selectedIndex > 0) {
1417
+ this.selectedIndex = Math.max(0, this.selectedIndex - 1);
1418
+ const entry = this.logs[this.selectedIndex];
1419
+ const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1420
+ const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1421
+ this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, this.selectedIndex + 1, this.logs.length, this.filterText);
1422
+ }
1423
+ break;
1424
+ case "right":
1425
+ if (this.selectedIndex < this.logs.length - 1) {
1426
+ this.selectedIndex = Math.min(this.logs.length - 1, this.selectedIndex + 1);
1427
+ const entry = this.logs[this.selectedIndex];
1428
+ const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1429
+ const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1430
+ this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, this.selectedIndex + 1, this.logs.length, this.filterText);
1431
+ }
1432
+ break;
1433
+ case "tab":
1434
+ if (this.renderer.isInJsonView()) {
1435
+ this.renderer.toggleJsonView();
1436
+ const entry = this.logs[this.selectedIndex];
1437
+ const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1438
+ const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1439
+ this.renderer.renderDetailView(entry, prevEntry, nextEntry, this.renderer.getDetailViewScrollPos(), this.selectedIndex + 1, this.logs.length, this.filterText);
1440
+ break;
1441
+ }
1442
+ this.isDetailView = false;
1443
+ if (this.detailViewPollInterval) {
1444
+ clearInterval(this.detailViewPollInterval);
1445
+ this.detailViewPollInterval = null;
1446
+ }
1447
+ this.isSelectionMode = true;
1448
+ this.updateFilteredLogs();
1449
+ this.renderer.renderSelectionView(this.logs, this.selectedIndex, this.filterText, this.selectionBuffer.length);
1450
+ break;
1451
+ }
1452
+ if (ch) switch (ch.toLowerCase()) {
1453
+ case "w": {
1454
+ this.renderer.scrollDetailView(process.stdout.rows - 8);
1455
+ const entry = this.logs[this.selectedIndex];
1456
+ const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1457
+ const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1458
+ this.renderer.renderDetailView(entry, prevEntry, nextEntry, this.renderer.getDetailViewScrollPos(), this.selectedIndex + 1, this.logs.length);
1459
+ break;
1460
+ }
1461
+ case "q": {
1462
+ this.renderer.scrollDetailView(-process.stdout.rows + 8);
1463
+ const entry = this.logs[this.selectedIndex];
1464
+ const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1465
+ const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1466
+ this.renderer.renderDetailView(entry, prevEntry, nextEntry, this.renderer.getDetailViewScrollPos(), this.selectedIndex + 1, this.logs.length);
1467
+ break;
1468
+ }
1469
+ case "a":
1470
+ if (this.selectedIndex !== 0) {
1471
+ this.selectedIndex = 0;
1472
+ const entry = this.logs[this.selectedIndex];
1473
+ const prevEntry = null;
1474
+ const nextEntry = this.logs.length > 1 ? this.logs[1] : null;
1475
+ this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, 1, this.logs.length);
1476
+ }
1477
+ break;
1478
+ case "s": {
1479
+ const lastIndex = this.logs.length - 1;
1480
+ if (this.selectedIndex !== lastIndex) {
1481
+ this.selectedIndex = lastIndex;
1482
+ const entry = this.logs[this.selectedIndex];
1483
+ const prevEntry = lastIndex > 0 ? this.logs[lastIndex - 1] : null;
1484
+ this.renderer.renderDetailView(entry, prevEntry, null, 0, this.logs.length, this.logs.length);
1485
+ }
1486
+ break;
1487
+ }
1488
+ case "c": {
1489
+ this.renderer.toggleArrayCollapse();
1490
+ const entry = this.logs[this.selectedIndex];
1491
+ const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1492
+ const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1493
+ this.renderer.renderDetailView(entry, prevEntry, nextEntry, this.renderer.getDetailViewScrollPos(), this.selectedIndex + 1, this.logs.length);
1494
+ break;
1495
+ }
1496
+ case "j": {
1497
+ this.renderer.toggleJsonView();
1498
+ const entry = this.logs[this.selectedIndex];
1499
+ const prevEntry = this.selectedIndex > 0 ? this.logs[this.selectedIndex - 1] : null;
1500
+ const nextEntry = this.selectedIndex < this.logs.length - 1 ? this.logs[this.selectedIndex + 1] : null;
1501
+ this.renderer.renderDetailView(entry, prevEntry, nextEntry, 0, this.selectedIndex + 1, this.logs.length);
1502
+ break;
1503
+ }
1504
+ }
1505
+ }
1506
+ }
1507
+ };
1815
1508
 
1816
- // src/index.ts
1509
+ //#endregion
1510
+ //#region src/PrettyTerminalTransport.ts
1511
+ /**
1512
+ * Main transport class that handles pretty terminal output and interactive features.
1513
+ * This class coordinates between different components:
1514
+ * - LogStorage: Handles persistence of logs in SQLite
1515
+ * - LogRenderer: Manages all rendering and formatting
1516
+ * - UIManager: Handles user interaction and view state
1517
+ *
1518
+ * The transport supports two main view modes:
1519
+ * 1. Simple View: Real-time log output with basic formatting
1520
+ * 2. Interactive View: Full-screen mode with navigation and filtering
1521
+ *
1522
+ * Usage:
1523
+ * ```typescript
1524
+ * const transport = PrettyTerminalTransport.getInstance({
1525
+ * maxInlineDepth: 4,
1526
+ * maxInlineLength: 120,
1527
+ * theme: customTheme
1528
+ * });
1529
+ * ```
1530
+ */
1531
+ var PrettyTerminalTransport = class PrettyTerminalTransport extends __loglayer_transport.LoggerlessTransport {
1532
+ /** Singleton instance of the transport */
1533
+ static instance = null;
1534
+ /** Handles all rendering and formatting of logs */
1535
+ renderer;
1536
+ /** Manages log persistence in SQLite database */
1537
+ storage;
1538
+ /** Manages user interaction and view state */
1539
+ uiManager;
1540
+ /** Configuration options */
1541
+ config;
1542
+ /**
1543
+ * Creates a new PrettyTerminalTransport instance.
1544
+ * This is a singleton class - only one instance can exist at a time.
1545
+ * Use getInstance() instead of constructor directly.
1546
+ *
1547
+ * @param config - Configuration options for the transport
1548
+ * @throws Error if attempting to create multiple instances
1549
+ */
1550
+ constructor(config = {}) {
1551
+ if (PrettyTerminalTransport.instance) throw new Error("PrettyTerminalTransport is a singleton. Use getPrettyTerminal() instead.");
1552
+ super(config);
1553
+ this.config = config;
1554
+ if (config.enabled === false) return;
1555
+ const maxInlineDepth = config.maxInlineDepth || 4;
1556
+ const maxInlineLength = config.maxInlineLength || 120;
1557
+ const theme = config.theme || moonlight;
1558
+ const logFile = config.logFile;
1559
+ const simpleViewConfig = {
1560
+ colors: {
1561
+ trace: chalk.default.gray,
1562
+ debug: chalk.default.blue,
1563
+ info: chalk.default.green,
1564
+ warn: chalk.default.yellow,
1565
+ error: chalk.default.red,
1566
+ fatal: chalk.default.bgRed.white,
1567
+ ...theme.simpleView.colors
1568
+ },
1569
+ logIdColor: theme.simpleView.logIdColor || chalk.default.dim,
1570
+ dataValueColor: theme.simpleView.dataValueColor || chalk.default.white,
1571
+ dataKeyColor: theme.simpleView.dataKeyColor || chalk.default.dim,
1572
+ selectorColor: theme.simpleView.selectorColor || chalk.default.cyan
1573
+ };
1574
+ const detailedViewConfig = {
1575
+ colors: {
1576
+ trace: chalk.default.gray,
1577
+ debug: chalk.default.blue,
1578
+ info: chalk.default.green,
1579
+ warn: chalk.default.yellow,
1580
+ error: chalk.default.red,
1581
+ fatal: chalk.default.bgRed.white,
1582
+ ...theme.detailedView?.colors
1583
+ },
1584
+ logIdColor: theme.detailedView?.logIdColor || chalk.default.dim,
1585
+ dataValueColor: theme.detailedView?.dataValueColor || chalk.default.white,
1586
+ dataKeyColor: theme.detailedView?.dataKeyColor || chalk.default.dim,
1587
+ selectorColor: theme.detailedView?.selectorColor || chalk.default.cyan,
1588
+ headerColor: theme.detailedView?.headerColor || chalk.default.cyan,
1589
+ labelColor: theme.detailedView?.labelColor || chalk.default.cyan.bold,
1590
+ separatorColor: theme.detailedView?.separatorColor || chalk.default.dim,
1591
+ jsonColors: {
1592
+ keysColor: chalk.default.yellow,
1593
+ dashColor: chalk.default.white,
1594
+ numberColor: chalk.default.yellow,
1595
+ stringColor: chalk.default.white,
1596
+ multilineStringColor: chalk.default.white,
1597
+ positiveNumberColor: chalk.default.green,
1598
+ negativeNumberColor: chalk.default.red,
1599
+ booleanColor: chalk.default.cyan,
1600
+ nullUndefinedColor: chalk.default.grey,
1601
+ dateColor: chalk.default.magenta,
1602
+ ...theme.detailedView?.jsonColors
1603
+ }
1604
+ };
1605
+ this.storage = new LogStorage(logFile);
1606
+ this.renderer = new LogRenderer(simpleViewConfig, detailedViewConfig, maxInlineDepth, maxInlineLength);
1607
+ this.uiManager = new UIManager(this.renderer, this.storage, config.disableInteractiveMode);
1608
+ PrettyTerminalTransport.instance = this;
1609
+ }
1610
+ /**
1611
+ * Gets or creates the singleton instance of PrettyTerminalTransport.
1612
+ * This is the recommended way to obtain a transport instance.
1613
+ *
1614
+ * @param config - Configuration options for the transport
1615
+ * @returns The singleton instance of PrettyTerminalTransport
1616
+ */
1617
+ static getInstance(config = {}) {
1618
+ if (!PrettyTerminalTransport.instance) PrettyTerminalTransport.instance = new PrettyTerminalTransport(config);
1619
+ return PrettyTerminalTransport.instance;
1620
+ }
1621
+ /**
1622
+ * Generates a random ID for each log entry.
1623
+ * Uses base36 encoding for compact, readable IDs.
1624
+ *
1625
+ * @returns A 6-character string ID
1626
+ * @example
1627
+ * "a1b2c3" // Example generated ID
1628
+ */
1629
+ generateId() {
1630
+ return Math.random().toString(36).substring(2, 8);
1631
+ }
1632
+ /**
1633
+ * Main transport method that receives logs from LogLayer.
1634
+ * This method is called for each log event and handles:
1635
+ * - Generating a unique ID for the log
1636
+ * - Converting the log data to a storable format
1637
+ * - Storing the log in the database
1638
+ * - Rendering the log if not in selection mode
1639
+ *
1640
+ * @param logLevel - The severity level of the log
1641
+ * @param messages - Array of message strings to be joined
1642
+ * @param data - Additional structured data to be logged
1643
+ * @param hasData - Whether the log includes additional data
1644
+ * @returns The original messages array
1645
+ */
1646
+ shipToLogger({ logLevel, messages, data, hasData }) {
1647
+ if (this.config.enabled === false) return messages;
1648
+ const entry = {
1649
+ id: this.generateId(),
1650
+ timestamp: Date.now(),
1651
+ level: logLevel,
1652
+ message: messages.join(" "),
1653
+ data: hasData ? JSON.stringify(data) : null
1654
+ };
1655
+ this.uiManager.handleNewLog(entry);
1656
+ return messages;
1657
+ }
1658
+ };
1817
1659
 
1660
+ //#endregion
1661
+ //#region src/index.ts
1818
1662
  function getPrettyTerminal(config = {}) {
1819
- return PrettyTerminalTransport.getInstance(config);
1663
+ return PrettyTerminalTransport.getInstance(config);
1820
1664
  }
1821
1665
 
1822
-
1823
-
1824
-
1825
-
1826
-
1827
-
1828
-
1829
-
1830
- exports.PrettyTerminalTransport = PrettyTerminalTransport; exports.chalk = chalk8; exports.getPrettyTerminal = getPrettyTerminal; exports.moonlight = moonlight; exports.nature = nature; exports.neon = neon; exports.pastel = pastel; exports.sunlight = sunlight;
1666
+ //#endregion
1667
+ exports.PrettyTerminalTransport = PrettyTerminalTransport;
1668
+ Object.defineProperty(exports, 'chalk', {
1669
+ enumerable: true,
1670
+ get: function () {
1671
+ return chalk;
1672
+ }
1673
+ });
1674
+ exports.getPrettyTerminal = getPrettyTerminal;
1675
+ exports.moonlight = moonlight;
1676
+ exports.nature = nature;
1677
+ exports.neon = neon;
1678
+ exports.pastel = pastel;
1679
+ exports.sunlight = sunlight;
1831
1680
  //# sourceMappingURL=index.cjs.map