@logtrace/tracker 0.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.
@@ -0,0 +1,136 @@
1
+ /**
2
+ * packages/cli/src/ui/renderer.js
3
+ *
4
+ * Terminal rendering helpers.
5
+ *
6
+ * All output goes through these functions — never call console.log() directly
7
+ * in command handlers. This keeps the rendering layer swappable and testable.
8
+ *
9
+ * Chalk v5 is ESM-only, which is why we use dynamic import if needed.
10
+ * Since our packages use "type":"module", the static import below works fine.
11
+ */
12
+
13
+ import chalk from 'chalk'
14
+ import Table from 'cli-table3'
15
+
16
+ // ── Status display ────────────────────────────────────────────────────────────
17
+
18
+ /**
19
+ * printStatus(data) — render the `tracker status` output.
20
+ *
21
+ * @param {{ version: string, uptime: number, modules: string[] }} data
22
+ */
23
+ export function printStatus(data) {
24
+ const { version, uptime, modules } = data
25
+
26
+ const uptimeStr = formatUptime(uptime)
27
+ const moduleCount = Array.isArray(modules) ? modules.length : 0
28
+ const moduleStr = moduleCount === 0
29
+ ? chalk.dim('none')
30
+ : modules.join(', ')
31
+
32
+ console.log()
33
+ console.log(
34
+ chalk.bold.green('LogTrace') +
35
+ chalk.dim(` v${version}`) +
36
+ ' ' +
37
+ chalk.dim('|') +
38
+ ' ' +
39
+ chalk.dim('uptime: ') + chalk.cyan(uptimeStr) +
40
+ ' ' +
41
+ chalk.dim('|') +
42
+ ' ' +
43
+ chalk.dim('modules: ') + chalk.yellow(String(moduleCount))
44
+ )
45
+
46
+ if (moduleCount > 0) {
47
+ console.log(chalk.dim(' active: ') + moduleStr)
48
+ }
49
+
50
+ console.log()
51
+ }
52
+
53
+ // ── Error display ─────────────────────────────────────────────────────────────
54
+
55
+ /**
56
+ * printError(message) — render an error message to stderr.
57
+ *
58
+ * @param {string} message
59
+ * @param {Error} [err] - optional error object for stack in dev mode
60
+ */
61
+ export function printError(message, err = null) {
62
+ process.stderr.write(chalk.red(' error ') + message + '\n')
63
+
64
+ if (err && process.env.LOGTRACE_ENV === 'development') {
65
+ process.stderr.write(chalk.dim(err.stack || err.message) + '\n')
66
+ }
67
+ }
68
+
69
+ /**
70
+ * printWarning(message) — render a warning to stdout.
71
+ * @param {string} message
72
+ */
73
+ export function printWarning(message) {
74
+ console.log(chalk.yellow(' warn ') + message)
75
+ }
76
+
77
+ /**
78
+ * printInfo(message) — render an informational line.
79
+ * @param {string} message
80
+ */
81
+ export function printInfo(message) {
82
+ console.log(chalk.dim(' info ') + message)
83
+ }
84
+
85
+ // ── Table display ─────────────────────────────────────────────────────────────
86
+
87
+ /**
88
+ * printTable(headers, rows) — render a formatted table.
89
+ *
90
+ * @param {string[]} headers - column header names
91
+ * @param {Array<string[]>} rows - array of row arrays
92
+ */
93
+ export function printTable(headers, rows) {
94
+ const table = new Table({
95
+ head: headers.map((h) => chalk.bold.white(h)),
96
+ style: {
97
+ head: [], // disable default blue — we apply chalk above
98
+ border: [], // disable default color
99
+ },
100
+ chars: {
101
+ 'top': '─', 'top-mid': '┬', 'top-left': '┌', 'top-right': '┐',
102
+ 'bottom': '─', 'bottom-mid': '┴', 'bottom-left': '└', 'bottom-right': '┘',
103
+ 'left': '│', 'left-mid': '├', 'mid': '─', 'mid-mid': '┼',
104
+ 'right': '│', 'right-mid': '┤', 'middle': '│',
105
+ },
106
+ })
107
+
108
+ for (const row of rows) {
109
+ table.push(row)
110
+ }
111
+
112
+ console.log(table.toString())
113
+ console.log()
114
+ }
115
+
116
+ // ── Utilities ─────────────────────────────────────────────────────────────────
117
+
118
+ /**
119
+ * formatUptime(seconds) — convert seconds to human-readable uptime string.
120
+ *
121
+ * @param {number} seconds
122
+ * @returns {string} e.g. "3d 4h 21m" or "42s"
123
+ */
124
+ export function formatUptime(seconds) {
125
+ if (typeof seconds !== 'number' || isNaN(seconds)) return '?'
126
+
127
+ const d = Math.floor(seconds / 86400)
128
+ const h = Math.floor((seconds % 86400) / 3600)
129
+ const m = Math.floor((seconds % 3600) / 60)
130
+ const s = seconds % 60
131
+
132
+ if (d > 0) return `${d}d ${h}h ${m}m`
133
+ if (h > 0) return `${h}h ${m}m`
134
+ if (m > 0) return `${m}m ${s}s`
135
+ return `${s}s`
136
+ }